All-in-One Event Calendar - Version 1.2.4

Version Description

Download this release

Release Info

Developer theseed
Plugin Icon 128x128 All-in-One Event Calendar
Version 1.2.4
Comparing to
See all releases

Code changes from version 1.2.3 to 1.2.4

all-in-one-event-calendar.php CHANGED
@@ -5,7 +5,7 @@
5
  * Description: An event calendar system with month, week, agenda views, upcoming events widget, color-coded categories, recurrence, and import/export of .ics feeds.
6
  * Author: The Seed Studio
7
  * Author URI: http://theseednetwork.com/
8
- * Version: 1.2.3
9
  */ // NOTE: When updating version number also update first line of app/view/calendar.php
10
  @set_time_limit( 0 );
11
  @ini_set( "memory_limit", "256M" );
@@ -146,8 +146,15 @@ define( 'AI1EC_EXPORT_URL', "$tmp&controller=ai1ec_exporter_controller&action=ex
146
  // ====================================
147
  // = Include iCal parsers and helpers =
148
  // ====================================
149
- require_once( AI1EC_LIB_PATH . '/iCalcreator.class.php' );
150
- require_once( AI1EC_LIB_PATH . '/iCalUtilityFunctions.class.php' );
 
 
 
 
 
 
 
151
  require_once( AI1EC_LIB_PATH . '/SG_iCal.php' );
152
  require_once( AI1EC_LIB_PATH . '/helpers/SG_iCal_Line.php' );
153
  require_once( AI1EC_LIB_PATH . '/helpers/SG_iCal_Duration.php' );
5
  * Description: An event calendar system with month, week, agenda views, upcoming events widget, color-coded categories, recurrence, and import/export of .ics feeds.
6
  * Author: The Seed Studio
7
  * Author URI: http://theseednetwork.com/
8
+ * Version: 1.2.4
9
  */ // NOTE: When updating version number also update first line of app/view/calendar.php
10
  @set_time_limit( 0 );
11
  @ini_set( "memory_limit", "256M" );
146
  // ====================================
147
  // = Include iCal parsers and helpers =
148
  // ====================================
149
+ if( version_compare( PHP_VERSION, '5.3.0' ) >= 0 ) {
150
+ // Parser that requires PHP v5.3.0 or up
151
+ require_once( AI1EC_LIB_PATH . '/iCalcreator-2.10.23/iCalcreator.class.php' );
152
+ require_once( AI1EC_LIB_PATH . '/iCalcreator-2.10.23//iCalUtilityFunctions.class.php' );
153
+ } else {
154
+ // Parser that works on PHP versions below 5.3.0
155
+ require_once( AI1EC_LIB_PATH . '/iCalcreator-2.10/iCalcreator.class.php' );
156
+ require_once( AI1EC_LIB_PATH . '/iCalcreator-2.10/iCalUtilityFunctions.class.php' );
157
+ }
158
  require_once( AI1EC_LIB_PATH . '/SG_iCal.php' );
159
  require_once( AI1EC_LIB_PATH . '/helpers/SG_iCal_Line.php' );
160
  require_once( AI1EC_LIB_PATH . '/helpers/SG_iCal_Duration.php' );
app/helper/class-ai1ec-importer-helper.php CHANGED
@@ -90,7 +90,15 @@ class Ai1ec_Importer_Helper {
90
  $count = 0;
91
 
92
  // include ical parser
93
- require_once( AI1EC_LIB_PATH . '/iCalcreator.class.php' );
 
 
 
 
 
 
 
 
94
 
95
  // set unique id, required if any component UID is missing
96
  $config = array( 'unique_id' => 'ai1ec' );
90
  $count = 0;
91
 
92
  // include ical parser
93
+ if( version_compare( PHP_VERSION, '5.3.0' ) >= 0 ) {
94
+ // Parser that requires PHP v5.3.0 or up
95
+ require_once( AI1EC_LIB_PATH . '/iCalcreator-2.10.23/iCalcreator.class.php' );
96
+ require_once( AI1EC_LIB_PATH . '/iCalcreator-2.10.23//iCalUtilityFunctions.class.php' );
97
+ } else {
98
+ // Parser that works on PHP versions below 5.3.0
99
+ require_once( AI1EC_LIB_PATH . '/iCalcreator-2.10/iCalcreator.class.php' );
100
+ require_once( AI1EC_LIB_PATH . '/iCalcreator-2.10/iCalUtilityFunctions.class.php' );
101
+ }
102
 
103
  // set unique id, required if any component UID is missing
104
  $config = array( 'unique_id' => 'ai1ec' );
app/view/calendar.php CHANGED
@@ -1,4 +1,4 @@
1
- <!-- START All-in-One Event Calendar Plugin - Version 1.2.3 -->
2
  <table class="ai1ec-calendar-toolbar">
3
  <tbody>
4
  <tr>
1
+ <!-- START All-in-One Event Calendar Plugin - Version 1.2.4 -->
2
  <table class="ai1ec-calendar-toolbar">
3
  <tbody>
4
  <tr>
language/all-in-one-event-calendar.pot CHANGED
@@ -2,9 +2,9 @@
2
  # This file is distributed under the same license as the All-in-One Event Calendar package.
3
  msgid ""
4
  msgstr ""
5
- "Project-Id-Version: All-in-One Event Calendar 1.2.3\n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/all-in-one-event-calendar\n"
7
- "POT-Creation-Date: 2012-01-17 01:27:50+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
@@ -12,1216 +12,1215 @@ msgstr ""
12
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13
  "Language-Team: LANGUAGE <LL@li.org>\n"
14
 
15
- #: app/view/row_yearly.php:3 app/view/row_monthly.php:3
16
- #: app/view/row_monthly.php:22 app/view/row_daily.php:3
17
- #: app/view/row_weekly.php:3
18
- msgid "Every"
19
  msgstr ""
20
 
21
- #: app/view/row_yearly.php:7
22
- msgctxt "Recurrence editor - yearly tab"
23
- msgid "In"
 
24
  msgstr ""
25
 
26
- #: app/view/box_eventbrite.php:1
27
- msgid "Eventbrite Ticketing"
28
  msgstr ""
29
 
30
- #: app/view/box_eventbrite.php:7
31
- msgid "Register this event with Eventbrite.com?"
32
  msgstr ""
33
 
34
- #: app/view/box_eventbrite.php:12
35
- msgid "Yes"
 
36
  msgstr ""
37
 
38
- #: app/view/box_eventbrite.php:14
39
- msgid "No"
40
  msgstr ""
41
 
42
- #: app/view/box_eventbrite.php:22
43
- msgid "Set up your first ticket"
44
  msgstr ""
45
 
46
- #: app/view/box_eventbrite.php:24
47
- msgid ""
48
- "To create multiple tickets per event, submit this form, then follow the link "
49
- "to Eventbrite."
50
- msgstr ""
 
51
 
52
- #: app/view/box_eventbrite.php:32
53
- msgid "Name"
 
54
  msgstr ""
55
 
56
- #: app/view/box_eventbrite.php:42
57
- msgid "Description"
 
58
  msgstr ""
59
 
60
- #: app/view/box_eventbrite.php:53
61
- msgid "Type"
 
62
  msgstr ""
63
 
64
- #: app/view/box_eventbrite.php:58
65
- msgid "Set Price"
66
  msgstr ""
67
 
68
- #: app/view/box_eventbrite.php:60
69
- msgid "Donation Based"
70
  msgstr ""
71
 
72
- #: app/view/box_eventbrite.php:68
73
- msgid ""
74
- "The price for this event's first ticket will be taken from the Cost field "
75
- "above."
76
  msgstr ""
77
 
78
- #: app/view/box_eventbrite.php:75
79
- msgid "Quantity"
 
 
 
80
  msgstr ""
81
 
82
- #: app/view/box_eventbrite.php:85
83
- msgid "Include Fee in Price"
84
  msgstr ""
85
 
86
- #: app/view/box_eventbrite.php:90
87
- msgid "Add Service Fee on top of price"
 
88
  msgstr ""
89
 
90
- #: app/view/box_eventbrite.php:92
91
- msgid "Include Service fee in price"
92
  msgstr ""
93
 
94
- #: app/view/box_eventbrite.php:98
95
- msgid "Payment Options"
96
  msgstr ""
97
 
98
- #: app/view/box_eventbrite.php:103
99
- msgid "Paypal"
100
  msgstr ""
101
 
102
- #: app/view/box_eventbrite.php:105
103
- msgid "Google Checkout"
104
  msgstr ""
105
 
106
- #: app/view/box_eventbrite.php:107
107
- msgid "Check"
 
108
  msgstr ""
109
 
110
- #: app/view/box_eventbrite.php:109
111
- msgid "Cash"
112
  msgstr ""
113
 
114
- #: app/view/box_eventbrite.php:111
115
- msgid "Send an Invoice"
116
  msgstr ""
117
 
118
- #: app/view/event-single-footer.php:4
119
- msgid ""
120
- "This post was replicated from another site's <a class=\"ai1ec-ics-icon\" "
121
- "href=\"%s\" title=\"iCalendar feed\">calendar feed</a>."
122
  msgstr ""
123
 
124
- #: app/view/event-single-footer.php:8
125
- msgid "View original post »"
126
  msgstr ""
127
 
128
- #: app/view/row_monthly.php:9
129
- msgid "On day of the month"
130
  msgstr ""
131
 
132
- #: app/view/row_monthly.php:13
133
- msgid "On day of the week"
 
134
  msgstr ""
135
 
136
- #: app/view/box_event_location.php:1
137
- msgid "Event location details"
138
  msgstr ""
139
 
140
- #: app/view/box_event_location.php:7
141
- msgid "Venue name:"
142
  msgstr ""
143
 
144
- #: app/view/box_event_location.php:17
145
- msgid "Address:"
146
  msgstr ""
147
 
148
- #: app/view/box_event_location.php:27
149
- msgid "Show Google Map:"
 
 
150
  msgstr ""
151
 
152
- #. #-#-#-#-# plugin.pot (All-in-One Event Calendar 1.2.3) #-#-#-#-#
153
- #. Author of the plugin/theme
154
- #: app/view/box_the_seed_studio.php:4
155
- msgid "The Seed Studio"
156
  msgstr ""
157
 
158
- #: app/view/box_the_seed_studio.php:7
159
- msgid ""
160
- "The Seed Studio provides web development and support services for clients "
161
- "and web developers."
162
  msgstr ""
163
 
164
- #: app/view/box_the_seed_studio.php:14
165
- msgid "Follow @theseednet"
 
166
  msgstr ""
167
 
168
- #: app/view/box_the_seed_studio.php:20
169
- msgid "Get Support<span> from one of our experienced pros</span>"
 
170
  msgstr ""
171
 
172
- #: app/view/box_the_seed_studio.php:23
173
- msgid "Support"
 
174
  msgstr ""
175
 
176
- #: app/view/box_the_seed_studio.php:25
177
- msgid "View plugin documentation"
 
178
  msgstr ""
179
 
180
- #: app/view/box_the_seed_studio.php:28
181
- msgid ""
182
- "You can also hire The Seed for support on a contract or per-hour basis for "
183
- "this plugin, for your website or for any of your Internet marketing needs "
184
- "(we can really help!)."
185
  msgstr ""
186
 
187
- #: app/view/box_the_seed_studio.php:31
188
- msgid ""
189
- "Plugin users: The Seed gives support priority to clients. For free support "
190
- "from other WordPress users, visit the plugin's forum."
191
  msgstr ""
192
 
193
- #: app/view/box_the_seed_studio.php:34
194
- msgid "Vote and Share"
 
195
  msgstr ""
196
 
197
- #: app/view/box_the_seed_studio.php:36
198
- msgid ""
199
- "This plugin is offered free to the Wordpress Community under the GPL3 "
200
- "license. All we ask is that you:"
201
  msgstr ""
202
 
203
- #: app/view/box_the_seed_studio.php:38
204
- msgid ""
205
- "<a href=\"http://wordpress.org/extend/plugins/all-in-one-event-calendar/\" "
206
- "target=\"_blank\">Give it a five-star rating on wordpress.org</a> (if you "
207
- "think it deserves it!)"
208
  msgstr ""
209
 
210
- #: app/view/box_the_seed_studio.php:39
211
- msgid "Link to the plugin page on our website"
212
  msgstr ""
213
 
214
- #: app/view/box_the_seed_studio.php:40
215
- msgid "Become a Fan on Facebook"
216
  msgstr ""
217
 
218
- #: app/view/box_the_seed_studio.php:41
219
- msgid "Follow us on Twitter"
220
  msgstr ""
221
 
222
- #: app/view/box_the_seed_studio.php:46
223
- msgid "Latest from the Seed Network"
224
  msgstr ""
225
 
226
- #: app/view/event_categories-color_picker.php:5
227
- #: app/view/event_categories-color_picker.php:19
228
- msgid "Category Color"
229
  msgstr ""
230
 
231
- #: app/view/event_categories-color_picker.php:13
232
- #: app/view/event_categories-color_picker.php:25
233
- msgid "Events in this category will be identified by this color"
234
  msgstr ""
235
 
236
- #: app/view/event-multi.php:4 app/view/event-excerpt.php:2
237
- #: app/view/event-single.php:5
238
- msgid "When:"
239
  msgstr ""
240
 
241
- #: app/view/event-multi.php:7
242
- msgid "View in Calendar »"
243
  msgstr ""
244
 
245
- #: app/view/event-multi.php:14 app/view/event-single.php:15
246
- msgid "Repeats:"
247
  msgstr ""
248
 
249
- #: app/view/event-multi.php:20 app/view/event-excerpt.php:4
250
- #: app/view/event-single.php:20
251
- msgid "Where:"
252
  msgstr ""
253
 
254
- #: app/view/event-multi.php:24
255
- msgid "View Map »"
256
  msgstr ""
257
 
258
- #: app/view/event-multi.php:33 app/view/event-single.php:40
259
- msgid "Cost:"
260
  msgstr ""
261
 
262
- #: app/view/event-multi.php:39 app/view/event-single.php:46
263
- msgid "Contact:"
264
  msgstr ""
265
 
266
- #: app/view/event-multi.php:45 app/view/agenda.php:81
267
- #: app/view/event-single.php:52
268
- msgid "Categories:"
 
 
 
269
  msgstr ""
270
 
271
- #: app/view/event-multi.php:51 app/view/agenda.php:87
272
- #: app/view/event-single.php:59
273
- msgid "Tags:"
 
 
274
  msgstr ""
275
 
276
- #: app/view/class-ai1ec-agenda-widget.php:18
277
- #: app/view/class-ai1ec-agenda-widget.php:39
278
- msgid "Upcoming Events"
 
 
279
  msgstr ""
280
 
281
- #: app/view/class-ai1ec-agenda-widget.php:20
282
- msgid "All-in-One Event Calendar: Lists upcoming events in Agenda view"
 
 
 
283
  msgstr ""
284
 
285
- #: app/view/row_weekly.php:6
286
- msgctxt "Recurrence editor - weekly tab"
287
- msgid "On"
288
  msgstr ""
289
 
290
- #: app/view/agenda.php:5
291
- msgid "+ Expand All"
292
  msgstr ""
293
 
294
- #: app/view/agenda.php:8
295
- msgid "− Collapse All"
296
  msgstr ""
297
 
298
- #: app/view/agenda.php:12 app/view/week.php:4 app/view/month.php:4
299
- msgid "Today"
300
  msgstr ""
301
 
302
- #: app/view/agenda.php:29
303
- msgid "There are no upcoming events to display at this time."
304
  msgstr ""
305
 
306
- #: app/view/agenda.php:59 app/view/agenda.php:109 app/view/week.php:69
307
- #: app/view/month.php:68
308
- msgid "(all-day)"
309
  msgstr ""
310
 
311
- #: app/view/agenda.php:77
312
- msgid "Read more »"
 
313
  msgstr ""
314
 
315
- #: app/view/box_event_cost.php:1
316
- msgid "Event cost"
 
 
 
317
  msgstr ""
318
 
319
- #: app/view/box_event_cost.php:7
320
- msgid "Cost"
 
 
321
  msgstr ""
322
 
323
- #: app/view/admin_notices.php:2
324
- msgid "All-in-One Event Calendar Notice:"
 
 
 
 
325
  msgstr ""
326
 
327
- #: app/view/box_time_and_date.php:2
328
- msgid "Event date and time"
 
 
329
  msgstr ""
330
 
331
- #: app/view/box_time_and_date.php:8
332
- msgid "All-day event"
 
 
 
333
  msgstr ""
334
 
335
- #: app/view/box_time_and_date.php:18
336
- msgid "Start date / time"
337
  msgstr ""
338
 
339
- #: app/view/box_time_and_date.php:31
340
- msgid "End date / time"
341
  msgstr ""
342
 
343
- #: app/view/box_time_and_date.php:46
344
- msgid "Repeat"
345
  msgstr ""
346
 
347
- #: app/view/box_time_and_date.php:58
348
- #: app/helper/class-ai1ec-events-helper.php:554
349
- #: app/helper/class-ai1ec-events-helper.php:573
350
- #: app/helper/class-ai1ec-events-helper.php:1502
351
- #: app/helper/class-ai1ec-settings-helper.php:237
352
- msgid "Daily"
353
  msgstr ""
354
 
355
- #: app/view/box_time_and_date.php:59
356
- #: app/helper/class-ai1ec-events-helper.php:555
357
- #: app/helper/class-ai1ec-events-helper.php:574
358
- #: app/helper/class-ai1ec-events-helper.php:1514
359
- msgid "Weekly"
360
  msgstr ""
361
 
362
- #: app/view/box_time_and_date.php:60
363
- #: app/helper/class-ai1ec-events-helper.php:556
364
- #: app/helper/class-ai1ec-events-helper.php:575
365
- #: app/helper/class-ai1ec-events-helper.php:1526
366
- msgid "Monthly"
367
  msgstr ""
368
 
369
- #: app/view/box_time_and_date.php:61
370
- #: app/helper/class-ai1ec-events-helper.php:557
371
- #: app/helper/class-ai1ec-events-helper.php:576
372
- #: app/helper/class-ai1ec-events-helper.php:1538
373
- msgid "Yearly"
374
  msgstr ""
375
 
376
- #: app/view/box_time_and_date.php:70
377
- msgid "End"
378
  msgstr ""
379
 
380
- #: app/view/box_time_and_date.php:77
381
- msgid "Ending after"
382
  msgstr ""
383
 
384
- #: app/view/box_time_and_date.php:84
385
- #: app/helper/class-ai1ec-events-helper.php:1302
386
- msgid "On date"
387
  msgstr ""
388
 
389
- #: app/view/box_time_and_date.php:92
390
- msgid "Apply"
391
  msgstr ""
392
 
393
- #: app/view/box_time_and_date.php:93
394
- msgid "Cancel"
 
395
  msgstr ""
396
 
397
- #: app/view/box_event_contact.php:1
398
- msgid "Organizer contact info"
 
399
  msgstr ""
400
 
401
- #: app/view/box_event_contact.php:7
402
- msgid "Contact name:"
403
  msgstr ""
404
 
405
- #: app/view/box_event_contact.php:17
406
- msgid "Phone:"
407
  msgstr ""
408
 
409
- #: app/view/box_event_contact.php:27
410
- msgid "E-mail:"
411
  msgstr ""
412
 
413
- #: app/view/week.php:33
414
- msgid "All-day"
415
  msgstr ""
416
 
417
- #: app/view/week.php:55 app/view/week.php:127 app/view/month.php:50
418
- msgid "Summary:"
419
  msgstr ""
420
 
421
- #: app/view/week.php:58 app/view/week.php:130 app/view/month.php:53
422
- msgid "click anywhere for details"
423
  msgstr ""
424
 
425
- #: app/view/settings.php:5
426
- msgid "All-in-one Event Calendar"
427
  msgstr ""
428
 
429
- #: app/view/settings.php:16
430
- msgid "Update Settings"
431
  msgstr ""
432
 
433
- #: app/view/import.php:6
434
- msgid "Successfully imported events:"
435
  msgstr ""
436
 
437
- #: app/view/calendar.php:11 app/view/calendar.php:12 app/view/calendar.php:25
438
- #: app/helper/class-ai1ec-settings-helper.php:149
439
- msgid "Month"
440
  msgstr ""
441
 
442
- #: app/view/calendar.php:18 app/view/calendar.php:19
443
- #: app/helper/class-ai1ec-settings-helper.php:152
444
- msgid "Week"
445
  msgstr ""
446
 
447
- #: app/view/calendar.php:26
448
- #: app/controller/class-ai1ec-calendar-controller.php:383
449
- #: app/helper/class-ai1ec-settings-helper.php:155
450
- msgid "Agenda"
451
  msgstr ""
452
 
453
- #: app/view/calendar.php:35
454
- msgid "+ Post Your Event"
 
455
  msgstr ""
456
 
457
- #: app/view/calendar.php:44
458
- msgid "Clear Filters"
 
459
  msgstr ""
460
 
461
- #: app/view/calendar.php:44
462
- msgid ""
463
  msgstr ""
464
 
465
- #: app/view/calendar.php:45
466
- msgid "Filter:"
 
 
467
  msgstr ""
468
 
469
- #: app/view/calendar.php:50
470
- msgid "Categories "
471
  msgstr ""
472
 
473
- #: app/view/calendar.php:72
474
- msgid "Tags "
475
  msgstr ""
476
 
477
- #: app/view/calendar.php:110 app/view/agenda-widget.php:67
478
- msgid ""
479
- "Subscribe to this calendar using your favourite calendar program (iCal, "
480
- "Outlook, etc.)"
481
  msgstr ""
482
 
483
- #: app/view/calendar.php:111 app/view/agenda-widget.php:68
484
- msgid " Subscribe"
485
  msgstr ""
486
 
487
- #: app/view/calendar.php:112
488
- msgid "to this filtered calendar"
 
 
 
489
  msgstr ""
490
 
491
- #: app/view/calendar.php:116 app/view/agenda-widget.php:72
492
- msgid "Subscribe to this calendar in your Google Calendar"
 
 
493
  msgstr ""
494
 
495
- #: app/view/calendar.php:118
496
- msgid "Subscribe in Google Calendar"
 
 
497
  msgstr ""
498
 
499
- #: app/view/event-single.php:8
500
- msgid "Back to Calendar »"
 
 
501
  msgstr ""
502
 
503
- #: app/view/event-single.php:27
504
- msgid "Add this event to your favourite calendar program (iCal, Outlook, etc.)"
 
 
505
  msgstr ""
506
 
507
- #: app/view/event-single.php:28
508
- msgid "✔ Add to Calendar"
 
509
  msgstr ""
510
 
511
- #: app/view/event-single.php:31
512
- msgid "Add this event to your Google Calendar"
513
  msgstr ""
514
 
515
- #: app/view/event-single.php:33
516
- msgid "Add to Google Calendar"
517
  msgstr ""
518
 
519
- #: app/view/box_ics_import_settings.php:2
520
- msgid "Auto-refresh"
521
  msgstr ""
522
 
523
- #: app/view/box_ics_import_settings.php:8 app/view/feed_row.php:3
524
- msgid "iCalendar/.ics Feed URL:"
525
  msgstr ""
526
 
527
- #: app/view/box_ics_import_settings.php:12
528
- msgid "Event category"
 
529
  msgstr ""
530
 
531
- #: app/view/box_ics_import_settings.php:18 app/view/feed_row.php:15
532
- msgid "Tag with"
 
533
  msgstr ""
534
 
535
- #: app/view/box_ics_import_settings.php:22
536
- msgid "+ Add new subscription"
537
  msgstr ""
538
 
539
- #: app/view/event-map.php:2
540
- msgid "Click to view map"
541
  msgstr ""
542
 
543
- #: app/view/event-map.php:9
544
- msgid "View Full-Size Map »"
545
  msgstr ""
546
 
547
- #: app/view/agenda-widget-form.php:2
548
- msgid "Title:"
549
  msgstr ""
550
 
551
- #: app/view/agenda-widget-form.php:6
552
- msgid "Number of events to show:"
553
  msgstr ""
554
 
555
- #: app/view/agenda-widget-form.php:14
556
- msgid "Events with these <strong>Categories</strong>"
557
  msgstr ""
558
 
559
- #: app/view/agenda-widget-form.php:23
560
- msgid "No categories found."
561
  msgstr ""
562
 
563
- #: app/view/agenda-widget-form.php:30
564
- msgid "<strong>Or</strong> events with these <strong>Tags</strong>"
565
  msgstr ""
566
 
567
- #: app/view/agenda-widget-form.php:39
568
- msgid "No tags found."
569
  msgstr ""
570
 
571
- #: app/view/agenda-widget-form.php:46
572
- msgid "<strong>Or</strong> any of these <strong>Events</strong>"
573
  msgstr ""
574
 
575
- #: app/view/agenda-widget-form.php:55
576
- msgid "No events found."
577
  msgstr ""
578
 
579
- #: app/view/agenda-widget-form.php:62
580
- msgid "Show <strong>View Calendar</strong> button"
 
581
  msgstr ""
582
 
583
- #: app/view/agenda-widget-form.php:65
584
- msgid "Show <strong>Subscribe</strong> buttons"
 
585
  msgstr ""
586
 
587
- #: app/view/agenda-widget-form.php:68
588
- msgid "Hide this widget on calendar page"
589
  msgstr ""
590
 
591
  #: app/view/feed_row.php:9
592
  msgid "Event category:"
593
  msgstr ""
594
 
595
- #: app/view/feed_row.php:19
596
- msgid "× Delete"
597
  msgstr ""
598
 
599
- #: app/view/feed_row.php:20
600
- #: app/controller/class-ai1ec-events-controller.php:334
601
- msgid "Update"
602
  msgstr ""
603
 
604
- #: app/view/feed_row.php:22
605
- #: app/controller/class-ai1ec-settings-controller.php:222
606
- msgid "Flush 1 event"
607
- msgid_plural "Flush %s events"
608
- msgstr[0] ""
609
- msgstr[1] ""
610
-
611
- #: app/view/box_general_settings.php:1
612
- msgid "Viewing Events"
613
  msgstr ""
614
 
615
- #: app/view/box_general_settings.php:3
616
- msgid "Calendar page:"
617
  msgstr ""
618
 
619
- #: app/view/box_general_settings.php:7
620
- msgid "Default calendar view:"
621
  msgstr ""
622
 
623
- #: app/view/box_general_settings.php:12
624
- msgid "Timezone:"
625
  msgstr ""
626
 
627
- #: app/view/box_general_settings.php:17
628
- msgid "Contain calendar in this DOM element:"
629
  msgstr ""
630
 
631
- #: app/view/box_general_settings.php:19
632
- msgid ""
633
- "Optional. Provide a <a href=\"http://api.jquery.com/category/selectors/\" "
634
- "target=\"_blank\">jQuery selector</a> that evaluates to a single DOM "
635
- "element. Replaces any existing markup found within target. If left empty, "
636
- "calendar is shown in normal page content container."
637
  msgstr ""
638
 
639
- #: app/view/box_general_settings.php:21
640
- msgid "Week starts on"
 
641
  msgstr ""
642
 
643
- #: app/view/box_general_settings.php:25
644
- msgid "Agenda pages show at most"
645
  msgstr ""
646
 
647
- #: app/view/box_general_settings.php:26
648
- msgid "events"
649
  msgstr ""
650
 
651
- #: app/view/box_general_settings.php:31
652
- msgid "Keep all events <strong>expanded</strong> in the agenda view"
653
  msgstr ""
654
 
655
- #: app/view/box_general_settings.php:37
656
- msgid "<strong>Exclude</strong> events from search results"
657
  msgstr ""
658
 
659
- #: app/view/box_general_settings.php:43
660
- msgid ""
661
- "Show <strong>Post Your Event</strong> button above the calendar to "
662
- "privileged users"
663
  msgstr ""
664
 
665
- #: app/view/box_general_settings.php:49
666
- msgid ""
667
- "Hide <strong>Subscribe</strong>/<strong>Add to Calendar</strong> buttons in "
668
- "calendar and single event views"
669
  msgstr ""
670
 
671
- #: app/view/box_general_settings.php:55
672
- msgid "Hide <strong>Google Maps</strong> until clicked"
673
  msgstr ""
674
 
675
- #: app/view/box_general_settings.php:61
676
- msgid ""
677
- "Use the configured <strong>region</strong> (WordPress locale) to bias the "
678
- "address autocomplete function"
679
  msgstr ""
680
 
681
- #: app/view/box_general_settings.php:67
682
- msgid "Include <strong>event categories</strong> in post category lists"
683
  msgstr ""
684
 
685
- #: app/view/box_general_settings.php:71
686
- msgid "Adding/Editing Events"
687
  msgstr ""
688
 
689
- #: app/view/box_general_settings.php:73
690
- msgid "Input dates in this format:"
691
  msgstr ""
692
 
693
- #: app/view/box_general_settings.php:79
694
- msgid "Use <strong>24h time</strong> in time pickers"
695
  msgstr ""
696
 
697
- #: app/view/box_general_settings.php:85
698
- msgid "Display <strong>Publish</strong> at bottom of Edit Event form"
699
  msgstr ""
700
 
701
- #: app/view/agenda-widget.php:11
702
- msgid "There are no upcoming events."
703
  msgstr ""
704
 
705
- #: app/view/agenda-widget.php:59
706
- msgid "View Calendar »"
 
707
  msgstr ""
708
 
709
- #: app/view/agenda-widget.php:74
710
- msgid "Add to Google"
 
711
  msgstr ""
712
 
713
- #: app/controller/class-ai1ec-events-controller.php:149
714
- msgid "This feed is already being imported."
 
 
715
  msgstr ""
716
 
717
- #: app/controller/class-ai1ec-events-controller.php:150
718
- msgid "Please enter a valid iCalendar URL."
 
719
  msgstr ""
720
 
721
- #: app/controller/class-ai1ec-events-controller.php:285
722
- msgid "times"
723
  msgstr ""
724
 
725
- #: app/controller/class-ai1ec-events-controller.php:334
726
- msgid "Publish"
727
  msgstr ""
728
 
729
- #: app/controller/class-ai1ec-events-controller.php:336
730
- msgid "Submit for Review"
731
  msgstr ""
732
 
733
- #: app/controller/class-ai1ec-events-controller.php:449
734
- msgid "Event updated. <a href=\"%s\">View event</a>"
735
  msgstr ""
736
 
737
- #: app/controller/class-ai1ec-events-controller.php:450
738
- msgid "Custom field updated."
739
  msgstr ""
740
 
741
- #: app/controller/class-ai1ec-events-controller.php:451
742
- msgid "Custom field deleted."
 
 
743
  msgstr ""
744
-
745
- #: app/controller/class-ai1ec-events-controller.php:452
746
- msgid "Event updated."
747
  msgstr ""
748
 
749
- #. translators: %s: date and time of the revision
750
- #: app/controller/class-ai1ec-events-controller.php:454
751
- msgid "Event restored to revision from %s"
752
  msgstr ""
753
 
754
- #: app/controller/class-ai1ec-events-controller.php:455
755
- msgid "Event published. <a href=\"%s\">View event</a>"
756
  msgstr ""
757
 
758
- #: app/controller/class-ai1ec-events-controller.php:456
759
- msgid "Event saved."
760
  msgstr ""
761
 
762
- #: app/controller/class-ai1ec-events-controller.php:457
763
- msgid "Event submitted. <a target=\"_blank\" href=\"%s\">Preview event</a>"
764
  msgstr ""
765
 
766
- #: app/controller/class-ai1ec-events-controller.php:458
767
  msgid ""
768
- "Event scheduled for: <strong>%1$s</strong>. <a target=\"_blank\" href=\"%2$s"
769
- "\">Preview event</a>"
770
  msgstr ""
771
 
772
- #. translators: Publish box date format, see http:php.net/date
773
- #: app/controller/class-ai1ec-events-controller.php:460
774
- msgid "M j, Y @ G:i"
775
  msgstr ""
776
 
777
- #: app/controller/class-ai1ec-events-controller.php:461
778
- msgid "Event draft updated. <a target=\"_blank\" href=\"%s\">Preview event</a>"
779
  msgstr ""
780
 
781
- #: app/controller/class-ai1ec-importer-controller.php:91
782
- msgid "The Events Calendar All-in-One Event Calendar"
783
  msgstr ""
784
 
785
- #: app/controller/class-ai1ec-importer-controller.php:92
786
- msgid ""
787
- "Imports events created using The Events Calendar plugin into the All-in-One "
788
- "Event Calendar"
789
  msgstr ""
790
 
791
- #: app/controller/class-ai1ec-app-controller.php:354
792
- #: app/controller/class-ai1ec-app-controller.php:355
793
- msgid "Settings"
794
  msgstr ""
795
 
796
- #. translators: "%s" represents the week's starting date
797
- #: app/controller/class-ai1ec-calendar-controller.php:326
798
- #: app/helper/class-ai1ec-calendar-helper.php:717
799
- #: app/helper/class-ai1ec-calendar-helper.php:726
800
- msgid "Week of %s"
801
  msgstr ""
802
 
803
- #: app/controller/class-ai1ec-calendar-controller.php:326
804
- msgid "F j"
805
  msgstr ""
806
 
807
- #: app/controller/class-ai1ec-settings-controller.php:82
808
- msgid "Settings Updated."
809
  msgstr ""
810
 
811
- #: app/controller/class-ai1ec-settings-controller.php:173
812
- msgid "Flushed %d events"
813
  msgstr ""
814
 
815
- #: app/controller/class-ai1ec-settings-controller.php:181
816
- #: app/controller/class-ai1ec-settings-controller.php:231
817
- msgid "Invalid ICS feed ID"
818
  msgstr ""
819
 
820
- #: app/controller/class-ai1ec-settings-controller.php:216
821
- msgid "No events were found"
822
  msgstr ""
823
 
824
- #: app/controller/class-ai1ec-settings-controller.php:221
825
- msgid "Imported %d events"
826
  msgstr ""
827
 
828
- #: app/controller/class-ai1ec-settings-controller.php:274
829
- msgctxt "meta box"
830
- msgid "General Settings"
 
831
  msgstr ""
832
 
833
- #: app/controller/class-ai1ec-settings-controller.php:282
834
- msgctxt "meta box"
835
- msgid "The Seed Studio Support"
 
836
  msgstr ""
837
 
838
- #: app/controller/class-ai1ec-settings-controller.php:289
839
- msgctxt "meta box"
840
- msgid "ICS Import Settings"
841
  msgstr ""
842
 
843
- #: app/controller/class-ai1ec-settings-controller.php:338
844
- msgid "<a href=\"%s\">Settings</a>"
845
  msgstr ""
846
 
847
- #: app/controller/class-ai1ec-settings-controller.php:352
848
- msgid "<a href=\"%s\" target=\"_blank\">Donate</a>"
849
  msgstr ""
850
 
851
- #: app/controller/class-ai1ec-settings-controller.php:353
852
- msgid "<a href=\"%s\" target=\"_blank\">Get Support</a>"
853
  msgstr ""
854
 
855
- #: app/model/class-ai1ec-event.php:486
856
- msgid " (all-day)"
 
 
 
857
  msgstr ""
858
 
859
- #: app/helper/class-ai1ec-events-helper.php:319
860
- #: app/helper/class-ai1ec-events-helper.php:341
861
- msgid "No repeat"
 
862
  msgstr ""
863
 
864
- #: app/helper/class-ai1ec-events-helper.php:320
865
- #: app/helper/class-ai1ec-events-helper.php:342
866
- msgid "Every day"
867
  msgstr ""
868
 
869
- #: app/helper/class-ai1ec-events-helper.php:321
870
- #: app/helper/class-ai1ec-events-helper.php:343
871
- msgid "Every week"
 
872
  msgstr ""
873
 
874
- #: app/helper/class-ai1ec-events-helper.php:322
875
- #: app/helper/class-ai1ec-events-helper.php:344
876
- msgid "Every month"
 
 
877
  msgstr ""
878
 
879
- #: app/helper/class-ai1ec-events-helper.php:323
880
- #: app/helper/class-ai1ec-events-helper.php:345
881
- msgid "Every year"
882
  msgstr ""
883
 
884
- #: app/helper/class-ai1ec-events-helper.php:325
885
- #: app/helper/class-ai1ec-events-helper.php:347
886
- msgid "Custom..."
887
  msgstr ""
888
 
889
- #: app/helper/class-ai1ec-events-helper.php:468
890
- msgid "first"
891
  msgstr ""
892
 
893
- #: app/helper/class-ai1ec-events-helper.php:469
894
- msgid "second"
895
  msgstr ""
896
 
897
- #: app/helper/class-ai1ec-events-helper.php:470
898
- msgid "third"
899
  msgstr ""
900
 
901
- #: app/helper/class-ai1ec-events-helper.php:471
902
- msgid "fourth"
903
  msgstr ""
904
 
905
- #: app/helper/class-ai1ec-events-helper.php:473
906
- msgid "last"
907
  msgstr ""
908
 
909
- #: app/helper/class-ai1ec-events-helper.php:478
910
- msgid "Sunday"
911
  msgstr ""
912
 
913
- #: app/helper/class-ai1ec-events-helper.php:479
914
- msgid "Monday"
915
  msgstr ""
916
 
917
- #: app/helper/class-ai1ec-events-helper.php:480
918
- msgid "Tuesday"
919
  msgstr ""
920
 
921
- #: app/helper/class-ai1ec-events-helper.php:481
922
- msgid "Wednesday"
923
  msgstr ""
924
 
925
- #: app/helper/class-ai1ec-events-helper.php:482
926
- msgid "Thursday"
 
 
 
 
927
  msgstr ""
928
 
929
- #: app/helper/class-ai1ec-events-helper.php:483
930
- msgid "Friday"
931
  msgstr ""
932
 
933
- #: app/helper/class-ai1ec-events-helper.php:484
934
- msgid "Saturday"
935
  msgstr ""
936
 
937
- #: app/helper/class-ai1ec-events-helper.php:486
938
- msgid "day"
939
  msgstr ""
940
 
941
- #: app/helper/class-ai1ec-events-helper.php:487
942
- msgid "weekday"
943
  msgstr ""
944
 
945
- #: app/helper/class-ai1ec-events-helper.php:488
946
- msgid "weekend day"
947
  msgstr ""
948
 
949
- #: app/helper/class-ai1ec-events-helper.php:598
950
- msgid "day(s)"
 
 
951
  msgstr ""
952
 
953
- #: app/helper/class-ai1ec-events-helper.php:627
954
- msgid "week(s)"
 
 
955
  msgstr ""
956
 
957
- #: app/helper/class-ai1ec-events-helper.php:697
958
- msgid "month(s)"
959
  msgstr ""
960
 
961
- #: app/helper/class-ai1ec-events-helper.php:720
962
- msgid "year(s)"
 
 
963
  msgstr ""
964
 
965
- #: app/helper/class-ai1ec-events-helper.php:1300
966
- msgid "Never"
967
  msgstr ""
968
 
969
- #: app/helper/class-ai1ec-events-helper.php:1301
970
- msgid "After"
971
  msgstr ""
972
 
973
- #: app/helper/class-ai1ec-events-helper.php:1381
974
- #: app/helper/class-ai1ec-events-helper.php:1390
975
- #: app/helper/class-ai1ec-events-helper.php:1398
976
- msgctxt "Recurrence editor - weekly tab"
977
- msgid "on"
978
  msgstr ""
979
 
980
- #: app/helper/class-ai1ec-events-helper.php:1386
981
- #: app/helper/class-ai1ec-events-helper.php:1415
982
- #: app/helper/class-ai1ec-events-helper.php:1453
983
- msgid "and"
984
  msgstr ""
985
 
986
- #: app/helper/class-ai1ec-events-helper.php:1411
987
- #: app/helper/class-ai1ec-events-helper.php:1418
988
- #: app/helper/class-ai1ec-events-helper.php:1424
989
- #: app/helper/class-ai1ec-events-helper.php:1435
990
- msgctxt "Recurrence editor - monthly tab"
991
- msgid "on"
992
  msgstr ""
993
 
994
- #: app/helper/class-ai1ec-events-helper.php:1411
995
- #: app/helper/class-ai1ec-events-helper.php:1418
996
- #: app/helper/class-ai1ec-events-helper.php:1424
997
- msgid "of the month"
998
  msgstr ""
999
 
1000
- #: app/helper/class-ai1ec-events-helper.php:1448
1001
- #: app/helper/class-ai1ec-events-helper.php:1456
1002
- #: app/helper/class-ai1ec-events-helper.php:1463
1003
- msgctxt "Recurrence editor - yearly tab"
1004
- msgid "on"
1005
  msgstr ""
1006
 
1007
- #: app/helper/class-ai1ec-events-helper.php:1505
1008
- msgid "Every other day"
 
 
1009
  msgstr ""
1010
 
1011
- #: app/helper/class-ai1ec-events-helper.php:1507
1012
- msgid "Every %d days"
1013
  msgstr ""
1014
 
1015
- #: app/helper/class-ai1ec-events-helper.php:1517
1016
- msgid "Every other week"
1017
  msgstr ""
1018
 
1019
- #: app/helper/class-ai1ec-events-helper.php:1519
1020
- msgid "Every %d weeks"
1021
  msgstr ""
1022
 
1023
- #: app/helper/class-ai1ec-events-helper.php:1529
1024
- msgid "Every other month"
1025
  msgstr ""
1026
 
1027
- #: app/helper/class-ai1ec-events-helper.php:1531
1028
- msgid "Every %d months"
1029
  msgstr ""
1030
 
1031
- #: app/helper/class-ai1ec-events-helper.php:1541
1032
- msgid "Every other year"
1033
  msgstr ""
1034
 
1035
- #: app/helper/class-ai1ec-events-helper.php:1543
1036
- msgid "Every %d years"
1037
  msgstr ""
1038
 
1039
- #: app/helper/class-ai1ec-events-helper.php:1563
1040
- msgid "until %s"
1041
  msgstr ""
1042
 
1043
- #: app/helper/class-ai1ec-events-helper.php:1566
1044
- msgid "for %d occurrences"
1045
  msgstr ""
1046
 
1047
- #: app/helper/class-ai1ec-events-helper.php:1568
1048
- msgid "forever"
1049
  msgstr ""
1050
 
1051
- #: app/helper/class-ai1ec-calendar-helper.php:718
1052
- #: app/helper/class-ai1ec-calendar-helper.php:727
1053
- msgid "M j"
1054
  msgstr ""
1055
 
1056
- #: app/helper/class-ai1ec-calendar-helper.php:759
1057
- msgid "« Previous Events"
1058
  msgstr ""
1059
 
1060
- #: app/helper/class-ai1ec-calendar-helper.php:766
1061
- msgid "Next Events »"
1062
  msgstr ""
1063
 
1064
- #: app/helper/class-ai1ec-settings-helper.php:85
1065
- msgid "- Auto-Create New Page -"
1066
  msgstr ""
1067
 
1068
- #: app/helper/class-ai1ec-settings-helper.php:107
1069
- msgid "View \"%s\" »"
1070
  msgstr ""
1071
 
1072
- #: app/helper/class-ai1ec-settings-helper.php:204
1073
- msgid "Default (d/m/y)"
1074
  msgstr ""
1075
 
1076
- #: app/helper/class-ai1ec-settings-helper.php:207
1077
- msgid "US (m/d/y)"
 
1078
  msgstr ""
1079
 
1080
- #: app/helper/class-ai1ec-settings-helper.php:210
1081
- msgid "ISO 8601 (y-m-d)"
1082
  msgstr ""
1083
 
1084
- #: app/helper/class-ai1ec-settings-helper.php:213
1085
- msgid "Dotted (m.d.y)"
1086
  msgstr ""
1087
 
1088
- #: app/helper/class-ai1ec-settings-helper.php:231
1089
- msgid "Hourly"
1090
  msgstr ""
1091
 
1092
- #: app/helper/class-ai1ec-settings-helper.php:234
1093
- msgid "Twice Daily"
1094
  msgstr ""
1095
 
1096
- #: app/helper/class-ai1ec-settings-helper.php:321
1097
- msgid "Calendar"
 
 
1098
  msgstr ""
1099
 
1100
- #: app/helper/class-ai1ec-app-helper.php:147
1101
- msgctxt "Custom post type name"
1102
- msgid "Events"
1103
  msgstr ""
1104
 
1105
- #: app/helper/class-ai1ec-app-helper.php:148
1106
- msgctxt "Custom post type name (singular)"
1107
- msgid "Event"
1108
  msgstr ""
1109
 
1110
- #: app/helper/class-ai1ec-app-helper.php:149
1111
- msgid "Add New"
1112
  msgstr ""
1113
 
1114
- #: app/helper/class-ai1ec-app-helper.php:150
1115
- msgid "Add New Event"
1116
  msgstr ""
1117
 
1118
- #: app/helper/class-ai1ec-app-helper.php:151
1119
- msgid "Edit Event"
1120
  msgstr ""
1121
 
1122
- #: app/helper/class-ai1ec-app-helper.php:152
1123
- msgid "New Event"
1124
  msgstr ""
1125
 
1126
- #: app/helper/class-ai1ec-app-helper.php:153
1127
- msgid "View Event"
1128
  msgstr ""
1129
 
1130
- #: app/helper/class-ai1ec-app-helper.php:154
1131
- msgid "Search Events"
1132
  msgstr ""
1133
 
1134
- #: app/helper/class-ai1ec-app-helper.php:155
1135
- msgid "No Events found"
1136
  msgstr ""
1137
 
1138
- #: app/helper/class-ai1ec-app-helper.php:156
1139
- msgid "No Events found in Trash"
1140
  msgstr ""
1141
 
1142
- #: app/helper/class-ai1ec-app-helper.php:157
1143
- msgid "Parent Event"
1144
  msgstr ""
1145
 
1146
- #: app/helper/class-ai1ec-app-helper.php:158
1147
- msgid "Events"
1148
  msgstr ""
1149
 
1150
- #: app/helper/class-ai1ec-app-helper.php:205
1151
- msgctxt "Event categories taxonomy"
1152
- msgid "Event Categories"
1153
  msgstr ""
1154
 
1155
- #: app/helper/class-ai1ec-app-helper.php:206
1156
- msgctxt "Event categories taxonomy (singular)"
1157
- msgid "Event Category"
1158
  msgstr ""
1159
 
1160
- #: app/helper/class-ai1ec-app-helper.php:213
1161
- msgctxt "Event tags taxonomy"
1162
- msgid "Event Tags"
1163
  msgstr ""
1164
 
1165
- #: app/helper/class-ai1ec-app-helper.php:214
1166
- msgctxt "Event tags taxonomy (singular)"
1167
- msgid "Event Tag"
1168
  msgstr ""
1169
 
1170
- #: app/helper/class-ai1ec-app-helper.php:281
1171
- msgid "Show All "
1172
  msgstr ""
1173
 
1174
- #: app/helper/class-ai1ec-app-helper.php:313
1175
- msgid ""
1176
- "All Events <span class=\"update-plugins count-%d\" title=\"%d Pending Events"
1177
- "\"><span class=\"update-count\">%d</span></span>"
1178
  msgstr ""
1179
 
1180
- #: app/helper/class-ai1ec-app-helper.php:319
1181
- msgid "All Events"
1182
  msgstr ""
1183
 
1184
- #: app/helper/class-ai1ec-app-helper.php:395
1185
- msgid "Event Details"
1186
  msgstr ""
1187
 
1188
- #: app/helper/class-ai1ec-app-helper.php:428
1189
- msgid "Post Date"
1190
  msgstr ""
1191
 
1192
- #: app/helper/class-ai1ec-app-helper.php:429
1193
- msgid "Event date/time"
1194
  msgstr ""
1195
 
1196
- #: app/helper/class-ai1ec-app-helper.php:653
1197
- msgid ""
1198
- "%sTo set up the plugin: %s 1. Select an option in the <strong>Calendar page</"
1199
- "strong> dropdown list. %s 2. Select an option in the <strong>Timezone</"
1200
- "strong> dropdown list. %s 3. Click <strong>Update Settings</strong>. %s"
1201
  msgstr ""
1202
 
1203
- #: app/helper/class-ai1ec-app-helper.php:655
1204
- msgid ""
1205
- "To set up the plugin: Select an option in the <strong>Calendar page</strong> "
1206
- "dropdown list, the click <strong>Update Settings</strong>."
1207
  msgstr ""
1208
 
1209
- #: app/helper/class-ai1ec-app-helper.php:657
1210
- msgid ""
1211
- "To set up the plugin: Select an option in the <strong>Timezone</strong> "
1212
- "dropdown list, the click <strong>Update Settings</strong>."
1213
  msgstr ""
1214
 
1215
- #: app/helper/class-ai1ec-app-helper.php:661
1216
- msgid ""
1217
- "The plugin is installed, but has not been configured. <a href=\"%s\">Click "
1218
- "here to set it up now »</a>"
1219
  msgstr ""
1220
 
1221
- #: app/helper/class-ai1ec-app-helper.php:667
1222
- msgid ""
1223
- "The plugin is installed, but has not been configured. Please log in as a "
1224
- "WordPress Administrator to set it up."
 
 
 
1225
  msgstr ""
1226
 
1227
  #. Plugin Name of the plugin/theme
2
  # This file is distributed under the same license as the All-in-One Event Calendar package.
3
  msgid ""
4
  msgstr ""
5
+ "Project-Id-Version: All-in-One Event Calendar 1.2.4\n"
6
  "Report-Msgid-Bugs-To: http://wordpress.org/tag/all-in-one-event-calendar\n"
7
+ "POT-Creation-Date: 2012-01-19 19:04:49+00:00\n"
8
  "MIME-Version: 1.0\n"
9
  "Content-Type: text/plain; charset=UTF-8\n"
10
  "Content-Transfer-Encoding: 8bit\n"
12
  "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
13
  "Language-Team: LANGUAGE <LL@li.org>\n"
14
 
15
+ #: app/controller/class-ai1ec-importer-controller.php:91
16
+ msgid "The Events Calendar → All-in-One Event Calendar"
 
 
17
  msgstr ""
18
 
19
+ #: app/controller/class-ai1ec-importer-controller.php:92
20
+ msgid ""
21
+ "Imports events created using The Events Calendar plugin into the All-in-One "
22
+ "Event Calendar"
23
  msgstr ""
24
 
25
+ #: app/controller/class-ai1ec-settings-controller.php:82
26
+ msgid "Settings Updated."
27
  msgstr ""
28
 
29
+ #: app/controller/class-ai1ec-settings-controller.php:173
30
+ msgid "Flushed %d events"
31
  msgstr ""
32
 
33
+ #: app/controller/class-ai1ec-settings-controller.php:181
34
+ #: app/controller/class-ai1ec-settings-controller.php:231
35
+ msgid "Invalid ICS feed ID"
36
  msgstr ""
37
 
38
+ #: app/controller/class-ai1ec-settings-controller.php:216
39
+ msgid "No events were found"
40
  msgstr ""
41
 
42
+ #: app/controller/class-ai1ec-settings-controller.php:221
43
+ msgid "Imported %d events"
44
  msgstr ""
45
 
46
+ #: app/controller/class-ai1ec-settings-controller.php:222
47
+ #: app/view/feed_row.php:22
48
+ msgid "Flush 1 event"
49
+ msgid_plural "Flush %s events"
50
+ msgstr[0] ""
51
+ msgstr[1] ""
52
 
53
+ #: app/controller/class-ai1ec-settings-controller.php:274
54
+ msgctxt "meta box"
55
+ msgid "General Settings"
56
  msgstr ""
57
 
58
+ #: app/controller/class-ai1ec-settings-controller.php:282
59
+ msgctxt "meta box"
60
+ msgid "The Seed Studio Support"
61
  msgstr ""
62
 
63
+ #: app/controller/class-ai1ec-settings-controller.php:289
64
+ msgctxt "meta box"
65
+ msgid "ICS Import Settings"
66
  msgstr ""
67
 
68
+ #: app/controller/class-ai1ec-settings-controller.php:338
69
+ msgid "<a href=\"%s\">Settings</a>"
70
  msgstr ""
71
 
72
+ #: app/controller/class-ai1ec-settings-controller.php:352
73
+ msgid "<a href=\"%s\" target=\"_blank\">Donate</a>"
74
  msgstr ""
75
 
76
+ #: app/controller/class-ai1ec-settings-controller.php:353
77
+ msgid "<a href=\"%s\" target=\"_blank\">Get Support</a>"
 
 
78
  msgstr ""
79
 
80
+ #. translators: "%s" represents the week's starting date
81
+ #: app/controller/class-ai1ec-calendar-controller.php:326
82
+ #: app/helper/class-ai1ec-calendar-helper.php:717
83
+ #: app/helper/class-ai1ec-calendar-helper.php:726
84
+ msgid "Week of %s"
85
  msgstr ""
86
 
87
+ #: app/controller/class-ai1ec-calendar-controller.php:326
88
+ msgid "F j"
89
  msgstr ""
90
 
91
+ #: app/controller/class-ai1ec-calendar-controller.php:383
92
+ #: app/helper/class-ai1ec-settings-helper.php:155 app/view/calendar.php:26
93
+ msgid "Agenda"
94
  msgstr ""
95
 
96
+ #: app/controller/class-ai1ec-events-controller.php:149
97
+ msgid "This feed is already being imported."
98
  msgstr ""
99
 
100
+ #: app/controller/class-ai1ec-events-controller.php:150
101
+ msgid "Please enter a valid iCalendar URL."
102
  msgstr ""
103
 
104
+ #: app/controller/class-ai1ec-events-controller.php:285
105
+ msgid "times"
106
  msgstr ""
107
 
108
+ #: app/controller/class-ai1ec-events-controller.php:334
109
+ msgid "Publish"
110
  msgstr ""
111
 
112
+ #: app/controller/class-ai1ec-events-controller.php:334
113
+ #: app/view/feed_row.php:20
114
+ msgid "Update"
115
  msgstr ""
116
 
117
+ #: app/controller/class-ai1ec-events-controller.php:336
118
+ msgid "Submit for Review"
119
  msgstr ""
120
 
121
+ #: app/controller/class-ai1ec-events-controller.php:449
122
+ msgid "Event updated. <a href=\"%s\">View event</a>"
123
  msgstr ""
124
 
125
+ #: app/controller/class-ai1ec-events-controller.php:450
126
+ msgid "Custom field updated."
 
 
127
  msgstr ""
128
 
129
+ #: app/controller/class-ai1ec-events-controller.php:451
130
+ msgid "Custom field deleted."
131
  msgstr ""
132
 
133
+ #: app/controller/class-ai1ec-events-controller.php:452
134
+ msgid "Event updated."
135
  msgstr ""
136
 
137
+ #. translators: %s: date and time of the revision
138
+ #: app/controller/class-ai1ec-events-controller.php:454
139
+ msgid "Event restored to revision from %s"
140
  msgstr ""
141
 
142
+ #: app/controller/class-ai1ec-events-controller.php:455
143
+ msgid "Event published. <a href=\"%s\">View event</a>"
144
  msgstr ""
145
 
146
+ #: app/controller/class-ai1ec-events-controller.php:456
147
+ msgid "Event saved."
148
  msgstr ""
149
 
150
+ #: app/controller/class-ai1ec-events-controller.php:457
151
+ msgid "Event submitted. <a target=\"_blank\" href=\"%s\">Preview event</a>"
152
  msgstr ""
153
 
154
+ #: app/controller/class-ai1ec-events-controller.php:458
155
+ msgid ""
156
+ "Event scheduled for: <strong>%1$s</strong>. <a target=\"_blank\" href=\"%2$s"
157
+ "\">Preview event</a>"
158
  msgstr ""
159
 
160
+ #. translators: Publish box date format, see http:php.net/date
161
+ #: app/controller/class-ai1ec-events-controller.php:460
162
+ msgid "M j, Y @ G:i"
 
163
  msgstr ""
164
 
165
+ #: app/controller/class-ai1ec-events-controller.php:461
166
+ msgid "Event draft updated. <a target=\"_blank\" href=\"%s\">Preview event</a>"
 
 
167
  msgstr ""
168
 
169
+ #: app/controller/class-ai1ec-app-controller.php:354
170
+ #: app/controller/class-ai1ec-app-controller.php:355
171
+ msgid "Settings"
172
  msgstr ""
173
 
174
+ #: app/helper/class-ai1ec-events-helper.php:319
175
+ #: app/helper/class-ai1ec-events-helper.php:341
176
+ msgid "No repeat"
177
  msgstr ""
178
 
179
+ #: app/helper/class-ai1ec-events-helper.php:320
180
+ #: app/helper/class-ai1ec-events-helper.php:342
181
+ msgid "Every day"
182
  msgstr ""
183
 
184
+ #: app/helper/class-ai1ec-events-helper.php:321
185
+ #: app/helper/class-ai1ec-events-helper.php:343
186
+ msgid "Every week"
187
  msgstr ""
188
 
189
+ #: app/helper/class-ai1ec-events-helper.php:322
190
+ #: app/helper/class-ai1ec-events-helper.php:344
191
+ msgid "Every month"
 
 
192
  msgstr ""
193
 
194
+ #: app/helper/class-ai1ec-events-helper.php:323
195
+ #: app/helper/class-ai1ec-events-helper.php:345
196
+ msgid "Every year"
 
197
  msgstr ""
198
 
199
+ #: app/helper/class-ai1ec-events-helper.php:325
200
+ #: app/helper/class-ai1ec-events-helper.php:347
201
+ msgid "Custom..."
202
  msgstr ""
203
 
204
+ #: app/helper/class-ai1ec-events-helper.php:468
205
+ msgid "first"
 
 
206
  msgstr ""
207
 
208
+ #: app/helper/class-ai1ec-events-helper.php:469
209
+ msgid "second"
 
 
 
210
  msgstr ""
211
 
212
+ #: app/helper/class-ai1ec-events-helper.php:470
213
+ msgid "third"
214
  msgstr ""
215
 
216
+ #: app/helper/class-ai1ec-events-helper.php:471
217
+ msgid "fourth"
218
  msgstr ""
219
 
220
+ #: app/helper/class-ai1ec-events-helper.php:473
221
+ msgid "last"
222
  msgstr ""
223
 
224
+ #: app/helper/class-ai1ec-events-helper.php:478
225
+ msgid "Sunday"
226
  msgstr ""
227
 
228
+ #: app/helper/class-ai1ec-events-helper.php:479
229
+ msgid "Monday"
 
230
  msgstr ""
231
 
232
+ #: app/helper/class-ai1ec-events-helper.php:480
233
+ msgid "Tuesday"
 
234
  msgstr ""
235
 
236
+ #: app/helper/class-ai1ec-events-helper.php:481
237
+ msgid "Wednesday"
 
238
  msgstr ""
239
 
240
+ #: app/helper/class-ai1ec-events-helper.php:482
241
+ msgid "Thursday"
242
  msgstr ""
243
 
244
+ #: app/helper/class-ai1ec-events-helper.php:483
245
+ msgid "Friday"
246
  msgstr ""
247
 
248
+ #: app/helper/class-ai1ec-events-helper.php:484
249
+ msgid "Saturday"
 
250
  msgstr ""
251
 
252
+ #: app/helper/class-ai1ec-events-helper.php:486
253
+ msgid "day"
254
  msgstr ""
255
 
256
+ #: app/helper/class-ai1ec-events-helper.php:487
257
+ msgid "weekday"
258
  msgstr ""
259
 
260
+ #: app/helper/class-ai1ec-events-helper.php:488
261
+ msgid "weekend day"
262
  msgstr ""
263
 
264
+ #: app/helper/class-ai1ec-events-helper.php:554
265
+ #: app/helper/class-ai1ec-events-helper.php:573
266
+ #: app/helper/class-ai1ec-events-helper.php:1502
267
+ #: app/helper/class-ai1ec-settings-helper.php:237
268
+ #: app/view/box_time_and_date.php:58
269
+ msgid "Daily"
270
  msgstr ""
271
 
272
+ #: app/helper/class-ai1ec-events-helper.php:555
273
+ #: app/helper/class-ai1ec-events-helper.php:574
274
+ #: app/helper/class-ai1ec-events-helper.php:1514
275
+ #: app/view/box_time_and_date.php:59
276
+ msgid "Weekly"
277
  msgstr ""
278
 
279
+ #: app/helper/class-ai1ec-events-helper.php:556
280
+ #: app/helper/class-ai1ec-events-helper.php:575
281
+ #: app/helper/class-ai1ec-events-helper.php:1526
282
+ #: app/view/box_time_and_date.php:60
283
+ msgid "Monthly"
284
  msgstr ""
285
 
286
+ #: app/helper/class-ai1ec-events-helper.php:557
287
+ #: app/helper/class-ai1ec-events-helper.php:576
288
+ #: app/helper/class-ai1ec-events-helper.php:1538
289
+ #: app/view/box_time_and_date.php:61
290
+ msgid "Yearly"
291
  msgstr ""
292
 
293
+ #: app/helper/class-ai1ec-events-helper.php:598
294
+ msgid "day(s)"
 
295
  msgstr ""
296
 
297
+ #: app/helper/class-ai1ec-events-helper.php:627
298
+ msgid "week(s)"
299
  msgstr ""
300
 
301
+ #: app/helper/class-ai1ec-events-helper.php:697
302
+ msgid "month(s)"
303
  msgstr ""
304
 
305
+ #: app/helper/class-ai1ec-events-helper.php:720
306
+ msgid "year(s)"
307
  msgstr ""
308
 
309
+ #: app/helper/class-ai1ec-events-helper.php:1300
310
+ msgid "Never"
311
  msgstr ""
312
 
313
+ #: app/helper/class-ai1ec-events-helper.php:1301
314
+ msgid "After"
 
315
  msgstr ""
316
 
317
+ #: app/helper/class-ai1ec-events-helper.php:1302
318
+ #: app/view/box_time_and_date.php:84
319
+ msgid "On date"
320
  msgstr ""
321
 
322
+ #: app/helper/class-ai1ec-events-helper.php:1381
323
+ #: app/helper/class-ai1ec-events-helper.php:1390
324
+ #: app/helper/class-ai1ec-events-helper.php:1398
325
+ msgctxt "Recurrence editor - weekly tab"
326
+ msgid "on"
327
  msgstr ""
328
 
329
+ #: app/helper/class-ai1ec-events-helper.php:1386
330
+ #: app/helper/class-ai1ec-events-helper.php:1415
331
+ #: app/helper/class-ai1ec-events-helper.php:1453
332
+ msgid "and"
333
  msgstr ""
334
 
335
+ #: app/helper/class-ai1ec-events-helper.php:1411
336
+ #: app/helper/class-ai1ec-events-helper.php:1418
337
+ #: app/helper/class-ai1ec-events-helper.php:1424
338
+ #: app/helper/class-ai1ec-events-helper.php:1435
339
+ msgctxt "Recurrence editor - monthly tab"
340
+ msgid "on"
341
  msgstr ""
342
 
343
+ #: app/helper/class-ai1ec-events-helper.php:1411
344
+ #: app/helper/class-ai1ec-events-helper.php:1418
345
+ #: app/helper/class-ai1ec-events-helper.php:1424
346
+ msgid "of the month"
347
  msgstr ""
348
 
349
+ #: app/helper/class-ai1ec-events-helper.php:1448
350
+ #: app/helper/class-ai1ec-events-helper.php:1456
351
+ #: app/helper/class-ai1ec-events-helper.php:1463
352
+ msgctxt "Recurrence editor - yearly tab"
353
+ msgid "on"
354
  msgstr ""
355
 
356
+ #: app/helper/class-ai1ec-events-helper.php:1505
357
+ msgid "Every other day"
358
  msgstr ""
359
 
360
+ #: app/helper/class-ai1ec-events-helper.php:1507
361
+ msgid "Every %d days"
362
  msgstr ""
363
 
364
+ #: app/helper/class-ai1ec-events-helper.php:1517
365
+ msgid "Every other week"
366
  msgstr ""
367
 
368
+ #: app/helper/class-ai1ec-events-helper.php:1519
369
+ msgid "Every %d weeks"
 
 
 
 
370
  msgstr ""
371
 
372
+ #: app/helper/class-ai1ec-events-helper.php:1529
373
+ msgid "Every other month"
 
 
 
374
  msgstr ""
375
 
376
+ #: app/helper/class-ai1ec-events-helper.php:1531
377
+ msgid "Every %d months"
 
 
 
378
  msgstr ""
379
 
380
+ #: app/helper/class-ai1ec-events-helper.php:1541
381
+ msgid "Every other year"
 
 
 
382
  msgstr ""
383
 
384
+ #: app/helper/class-ai1ec-events-helper.php:1543
385
+ msgid "Every %d years"
386
  msgstr ""
387
 
388
+ #: app/helper/class-ai1ec-events-helper.php:1563
389
+ msgid "until %s"
390
  msgstr ""
391
 
392
+ #: app/helper/class-ai1ec-events-helper.php:1566
393
+ msgid "for %d occurrences"
 
394
  msgstr ""
395
 
396
+ #: app/helper/class-ai1ec-events-helper.php:1568
397
+ msgid "forever"
398
  msgstr ""
399
 
400
+ #: app/helper/class-ai1ec-app-helper.php:147
401
+ msgctxt "Custom post type name"
402
+ msgid "Events"
403
  msgstr ""
404
 
405
+ #: app/helper/class-ai1ec-app-helper.php:148
406
+ msgctxt "Custom post type name (singular)"
407
+ msgid "Event"
408
  msgstr ""
409
 
410
+ #: app/helper/class-ai1ec-app-helper.php:149
411
+ msgid "Add New"
412
  msgstr ""
413
 
414
+ #: app/helper/class-ai1ec-app-helper.php:150
415
+ msgid "Add New Event"
416
  msgstr ""
417
 
418
+ #: app/helper/class-ai1ec-app-helper.php:151
419
+ msgid "Edit Event"
420
  msgstr ""
421
 
422
+ #: app/helper/class-ai1ec-app-helper.php:152
423
+ msgid "New Event"
424
  msgstr ""
425
 
426
+ #: app/helper/class-ai1ec-app-helper.php:153
427
+ msgid "View Event"
428
  msgstr ""
429
 
430
+ #: app/helper/class-ai1ec-app-helper.php:154
431
+ msgid "Search Events"
432
  msgstr ""
433
 
434
+ #: app/helper/class-ai1ec-app-helper.php:155
435
+ msgid "No Events found"
436
  msgstr ""
437
 
438
+ #: app/helper/class-ai1ec-app-helper.php:156
439
+ msgid "No Events found in Trash"
440
  msgstr ""
441
 
442
+ #: app/helper/class-ai1ec-app-helper.php:157
443
+ msgid "Parent Event"
444
  msgstr ""
445
 
446
+ #: app/helper/class-ai1ec-app-helper.php:158
447
+ msgid "Events"
 
448
  msgstr ""
449
 
450
+ #: app/helper/class-ai1ec-app-helper.php:205
451
+ msgctxt "Event categories taxonomy"
452
+ msgid "Event Categories"
453
  msgstr ""
454
 
455
+ #: app/helper/class-ai1ec-app-helper.php:206
456
+ msgctxt "Event categories taxonomy (singular)"
457
+ msgid "Event Category"
 
458
  msgstr ""
459
 
460
+ #: app/helper/class-ai1ec-app-helper.php:213
461
+ msgctxt "Event tags taxonomy"
462
+ msgid "Event Tags"
463
  msgstr ""
464
 
465
+ #: app/helper/class-ai1ec-app-helper.php:214
466
+ msgctxt "Event tags taxonomy (singular)"
467
+ msgid "Event Tag"
468
  msgstr ""
469
 
470
+ #: app/helper/class-ai1ec-app-helper.php:281
471
+ msgid "Show All "
472
  msgstr ""
473
 
474
+ #: app/helper/class-ai1ec-app-helper.php:313
475
+ msgid ""
476
+ "All Events <span class=\"update-plugins count-%d\" title=\"%d Pending Events"
477
+ "\"><span class=\"update-count\">%d</span></span>"
478
  msgstr ""
479
 
480
+ #: app/helper/class-ai1ec-app-helper.php:319
481
+ msgid "All Events"
482
  msgstr ""
483
 
484
+ #: app/helper/class-ai1ec-app-helper.php:395
485
+ msgid "Event Details"
486
  msgstr ""
487
 
488
+ #: app/helper/class-ai1ec-app-helper.php:428
489
+ msgid "Post Date"
 
 
490
  msgstr ""
491
 
492
+ #: app/helper/class-ai1ec-app-helper.php:429
493
+ msgid "Event date/time"
494
  msgstr ""
495
 
496
+ #: app/helper/class-ai1ec-app-helper.php:653
497
+ msgid ""
498
+ "%sTo set up the plugin: %s 1. Select an option in the <strong>Calendar page</"
499
+ "strong> dropdown list. %s 2. Select an option in the <strong>Timezone</"
500
+ "strong> dropdown list. %s 3. Click <strong>Update Settings</strong>. %s"
501
  msgstr ""
502
 
503
+ #: app/helper/class-ai1ec-app-helper.php:655
504
+ msgid ""
505
+ "To set up the plugin: Select an option in the <strong>Calendar page</strong> "
506
+ "dropdown list, the click <strong>Update Settings</strong>."
507
  msgstr ""
508
 
509
+ #: app/helper/class-ai1ec-app-helper.php:657
510
+ msgid ""
511
+ "To set up the plugin: Select an option in the <strong>Timezone</strong> "
512
+ "dropdown list, the click <strong>Update Settings</strong>."
513
  msgstr ""
514
 
515
+ #: app/helper/class-ai1ec-app-helper.php:661
516
+ msgid ""
517
+ "The plugin is installed, but has not been configured. <a href=\"%s\">Click "
518
+ "here to set it up now »</a>"
519
  msgstr ""
520
 
521
+ #: app/helper/class-ai1ec-app-helper.php:667
522
+ msgid ""
523
+ "The plugin is installed, but has not been configured. Please log in as a "
524
+ "WordPress Administrator to set it up."
525
  msgstr ""
526
 
527
+ #: app/helper/class-ai1ec-calendar-helper.php:718
528
+ #: app/helper/class-ai1ec-calendar-helper.php:727
529
+ msgid "M j"
530
  msgstr ""
531
 
532
+ #: app/helper/class-ai1ec-calendar-helper.php:759
533
+ msgid "« Previous Events"
534
  msgstr ""
535
 
536
+ #: app/helper/class-ai1ec-calendar-helper.php:766
537
+ msgid "Next Events »"
538
  msgstr ""
539
 
540
+ #: app/helper/class-ai1ec-settings-helper.php:85
541
+ msgid "- Auto-Create New Page -"
542
  msgstr ""
543
 
544
+ #: app/helper/class-ai1ec-settings-helper.php:107
545
+ msgid "View \"%s\" »"
546
  msgstr ""
547
 
548
+ #: app/helper/class-ai1ec-settings-helper.php:149 app/view/calendar.php:11
549
+ #: app/view/calendar.php:12 app/view/calendar.php:25
550
+ msgid "Month"
551
  msgstr ""
552
 
553
+ #: app/helper/class-ai1ec-settings-helper.php:152 app/view/calendar.php:18
554
+ #: app/view/calendar.php:19
555
+ msgid "Week"
556
  msgstr ""
557
 
558
+ #: app/helper/class-ai1ec-settings-helper.php:204
559
+ msgid "Default (d/m/y)"
560
  msgstr ""
561
 
562
+ #: app/helper/class-ai1ec-settings-helper.php:207
563
+ msgid "US (m/d/y)"
564
  msgstr ""
565
 
566
+ #: app/helper/class-ai1ec-settings-helper.php:210
567
+ msgid "ISO 8601 (y-m-d)"
568
  msgstr ""
569
 
570
+ #: app/helper/class-ai1ec-settings-helper.php:213
571
+ msgid "Dotted (m.d.y)"
572
  msgstr ""
573
 
574
+ #: app/helper/class-ai1ec-settings-helper.php:231
575
+ msgid "Hourly"
576
  msgstr ""
577
 
578
+ #: app/helper/class-ai1ec-settings-helper.php:234
579
+ msgid "Twice Daily"
580
  msgstr ""
581
 
582
+ #: app/helper/class-ai1ec-settings-helper.php:321
583
+ msgid "Calendar"
584
  msgstr ""
585
 
586
+ #: app/view/settings.php:5
587
+ msgid "All-in-one Event Calendar"
588
  msgstr ""
589
 
590
+ #: app/view/settings.php:16
591
+ msgid "Update Settings"
592
  msgstr ""
593
 
594
+ #: app/view/box_event_cost.php:1
595
+ msgid "Event cost"
596
  msgstr ""
597
 
598
+ #: app/view/box_event_cost.php:7
599
+ msgid "Cost"
600
  msgstr ""
601
 
602
+ #: app/view/event-excerpt.php:2 app/view/event-single.php:5
603
+ #: app/view/event-multi.php:4
604
+ msgid "When:"
605
  msgstr ""
606
 
607
+ #: app/view/event-excerpt.php:4 app/view/event-single.php:20
608
+ #: app/view/event-multi.php:20
609
+ msgid "Where:"
610
  msgstr ""
611
 
612
+ #: app/view/feed_row.php:3 app/view/box_ics_import_settings.php:8
613
+ msgid "iCalendar/.ics Feed URL:"
614
  msgstr ""
615
 
616
  #: app/view/feed_row.php:9
617
  msgid "Event category:"
618
  msgstr ""
619
 
620
+ #: app/view/feed_row.php:15 app/view/box_ics_import_settings.php:18
621
+ msgid "Tag with"
622
  msgstr ""
623
 
624
+ #: app/view/feed_row.php:19
625
+ msgid "× Delete"
 
626
  msgstr ""
627
 
628
+ #: app/view/event-map.php:2
629
+ msgid "Click to view map"
 
 
 
 
 
 
 
630
  msgstr ""
631
 
632
+ #: app/view/event-map.php:9
633
+ msgid "View Full-Size Map »"
634
  msgstr ""
635
 
636
+ #: app/view/box_event_location.php:1
637
+ msgid "Event location details"
638
  msgstr ""
639
 
640
+ #: app/view/box_event_location.php:7
641
+ msgid "Venue name:"
642
  msgstr ""
643
 
644
+ #: app/view/box_event_location.php:17
645
+ msgid "Address:"
646
  msgstr ""
647
 
648
+ #: app/view/box_event_location.php:27
649
+ msgid "Show Google Map:"
 
 
 
 
650
  msgstr ""
651
 
652
+ #: app/view/class-ai1ec-agenda-widget.php:18
653
+ #: app/view/class-ai1ec-agenda-widget.php:39
654
+ msgid "Upcoming Events"
655
  msgstr ""
656
 
657
+ #: app/view/class-ai1ec-agenda-widget.php:20
658
+ msgid "All-in-One Event Calendar: Lists upcoming events in Agenda view"
659
  msgstr ""
660
 
661
+ #: app/view/month.php:4 app/view/agenda.php:12 app/view/week.php:4
662
+ msgid "Today"
663
  msgstr ""
664
 
665
+ #: app/view/month.php:50 app/view/week.php:55 app/view/week.php:127
666
+ msgid "Summary:"
667
  msgstr ""
668
 
669
+ #: app/view/month.php:53 app/view/week.php:58 app/view/week.php:130
670
+ msgid "click anywhere for details"
671
  msgstr ""
672
 
673
+ #: app/view/month.php:68 app/view/agenda.php:59 app/view/agenda.php:109
674
+ #: app/view/week.php:69
675
+ msgid "(all-day)"
 
676
  msgstr ""
677
 
678
+ #: app/view/import.php:6
679
+ msgid "Successfully imported events:"
 
 
680
  msgstr ""
681
 
682
+ #: app/view/event-single.php:8
683
+ msgid "Back to Calendar »"
684
  msgstr ""
685
 
686
+ #: app/view/event-single.php:15 app/view/event-multi.php:14
687
+ msgid "Repeats:"
 
 
688
  msgstr ""
689
 
690
+ #: app/view/event-single.php:27
691
+ msgid "Add this event to your favourite calendar program (iCal, Outlook, etc.)"
692
  msgstr ""
693
 
694
+ #: app/view/event-single.php:28
695
+ msgid " Add to Calendar"
696
  msgstr ""
697
 
698
+ #: app/view/event-single.php:31
699
+ msgid "Add this event to your Google Calendar"
700
  msgstr ""
701
 
702
+ #: app/view/event-single.php:33
703
+ msgid "Add to Google Calendar"
704
  msgstr ""
705
 
706
+ #: app/view/event-single.php:40 app/view/event-multi.php:33
707
+ msgid "Cost:"
708
  msgstr ""
709
 
710
+ #: app/view/event-single.php:46 app/view/event-multi.php:39
711
+ msgid "Contact:"
712
  msgstr ""
713
 
714
+ #: app/view/event-single.php:52 app/view/event-multi.php:45
715
+ #: app/view/agenda.php:81
716
+ msgid "Categories:"
717
  msgstr ""
718
 
719
+ #: app/view/event-single.php:59 app/view/event-multi.php:51
720
+ #: app/view/agenda.php:87
721
+ msgid "Tags:"
722
  msgstr ""
723
 
724
+ #: app/view/row_weekly.php:3 app/view/row_monthly.php:3
725
+ #: app/view/row_monthly.php:22 app/view/row_yearly.php:3
726
+ #: app/view/row_daily.php:3
727
+ msgid "Every"
728
  msgstr ""
729
 
730
+ #: app/view/row_weekly.php:6
731
+ msgctxt "Recurrence editor - weekly tab"
732
+ msgid "On"
733
  msgstr ""
734
 
735
+ #: app/view/box_eventbrite.php:1
736
+ msgid "Eventbrite Ticketing"
737
  msgstr ""
738
 
739
+ #: app/view/box_eventbrite.php:7
740
+ msgid "Register this event with Eventbrite.com?"
741
  msgstr ""
742
 
743
+ #: app/view/box_eventbrite.php:12
744
+ msgid "Yes"
745
  msgstr ""
746
 
747
+ #: app/view/box_eventbrite.php:14
748
+ msgid "No"
749
  msgstr ""
750
 
751
+ #: app/view/box_eventbrite.php:22
752
+ msgid "Set up your first ticket"
753
  msgstr ""
754
 
755
+ #: app/view/box_eventbrite.php:24
756
+ msgid ""
757
+ "To create multiple tickets per event, submit this form, then follow the link "
758
+ "to Eventbrite."
759
  msgstr ""
760
+
761
+ #: app/view/box_eventbrite.php:32
762
+ msgid "Name"
763
  msgstr ""
764
 
765
+ #: app/view/box_eventbrite.php:42
766
+ msgid "Description"
 
767
  msgstr ""
768
 
769
+ #: app/view/box_eventbrite.php:53
770
+ msgid "Type"
771
  msgstr ""
772
 
773
+ #: app/view/box_eventbrite.php:58
774
+ msgid "Set Price"
775
  msgstr ""
776
 
777
+ #: app/view/box_eventbrite.php:60
778
+ msgid "Donation Based"
779
  msgstr ""
780
 
781
+ #: app/view/box_eventbrite.php:68
782
  msgid ""
783
+ "The price for this event's first ticket will be taken from the Cost field "
784
+ "above."
785
  msgstr ""
786
 
787
+ #: app/view/box_eventbrite.php:75
788
+ msgid "Quantity"
 
789
  msgstr ""
790
 
791
+ #: app/view/box_eventbrite.php:85
792
+ msgid "Include Fee in Price"
793
  msgstr ""
794
 
795
+ #: app/view/box_eventbrite.php:90
796
+ msgid "Add Service Fee on top of price"
797
  msgstr ""
798
 
799
+ #: app/view/box_eventbrite.php:92
800
+ msgid "Include Service fee in price"
 
 
801
  msgstr ""
802
 
803
+ #: app/view/box_eventbrite.php:98
804
+ msgid "Payment Options"
 
805
  msgstr ""
806
 
807
+ #: app/view/box_eventbrite.php:103
808
+ msgid "Paypal"
 
 
 
809
  msgstr ""
810
 
811
+ #: app/view/box_eventbrite.php:105
812
+ msgid "Google Checkout"
813
  msgstr ""
814
 
815
+ #: app/view/box_eventbrite.php:107
816
+ msgid "Check"
817
  msgstr ""
818
 
819
+ #: app/view/box_eventbrite.php:109
820
+ msgid "Cash"
821
  msgstr ""
822
 
823
+ #: app/view/box_eventbrite.php:111
824
+ msgid "Send an Invoice"
 
825
  msgstr ""
826
 
827
+ #: app/view/row_monthly.php:9
828
+ msgid "On day of the month"
829
  msgstr ""
830
 
831
+ #: app/view/row_monthly.php:13
832
+ msgid "On day of the week"
833
  msgstr ""
834
 
835
+ #. #-#-#-#-# plugin.pot (All-in-One Event Calendar 1.2.4) #-#-#-#-#
836
+ #. Author of the plugin/theme
837
+ #: app/view/box_the_seed_studio.php:4
838
+ msgid "The Seed Studio"
839
  msgstr ""
840
 
841
+ #: app/view/box_the_seed_studio.php:7
842
+ msgid ""
843
+ "The Seed Studio provides web development and support services for clients "
844
+ "and web developers."
845
  msgstr ""
846
 
847
+ #: app/view/box_the_seed_studio.php:14
848
+ msgid "Follow @theseednet"
 
849
  msgstr ""
850
 
851
+ #: app/view/box_the_seed_studio.php:20
852
+ msgid "Get Support<span> from one of our experienced pros</span>"
853
  msgstr ""
854
 
855
+ #: app/view/box_the_seed_studio.php:23
856
+ msgid "Support"
857
  msgstr ""
858
 
859
+ #: app/view/box_the_seed_studio.php:25
860
+ msgid "View plugin documentation"
861
  msgstr ""
862
 
863
+ #: app/view/box_the_seed_studio.php:28
864
+ msgid ""
865
+ "You can also hire The Seed for support on a contract or per-hour basis for "
866
+ "this plugin, for your website or for any of your Internet marketing needs "
867
+ "(we can really help!)."
868
  msgstr ""
869
 
870
+ #: app/view/box_the_seed_studio.php:31
871
+ msgid ""
872
+ "Plugin users: The Seed gives support priority to clients. For free support "
873
+ "from other WordPress users, visit the plugin's forum."
874
  msgstr ""
875
 
876
+ #: app/view/box_the_seed_studio.php:34
877
+ msgid "Vote and Share"
 
878
  msgstr ""
879
 
880
+ #: app/view/box_the_seed_studio.php:36
881
+ msgid ""
882
+ "This plugin is offered free to the Wordpress Community under the GPL3 "
883
+ "license. All we ask is that you:"
884
  msgstr ""
885
 
886
+ #: app/view/box_the_seed_studio.php:38
887
+ msgid ""
888
+ "<a href=\"http://wordpress.org/extend/plugins/all-in-one-event-calendar/\" "
889
+ "target=\"_blank\">Give it a five-star rating on wordpress.org</a> (if you "
890
+ "think it deserves it!)"
891
  msgstr ""
892
 
893
+ #: app/view/box_the_seed_studio.php:39
894
+ msgid "Link to the plugin page on our website"
 
895
  msgstr ""
896
 
897
+ #: app/view/box_the_seed_studio.php:40
898
+ msgid "Become a Fan on Facebook"
 
899
  msgstr ""
900
 
901
+ #: app/view/box_the_seed_studio.php:41
902
+ msgid "Follow us on Twitter"
903
  msgstr ""
904
 
905
+ #: app/view/box_the_seed_studio.php:46
906
+ msgid "Latest from the Seed Network"
907
  msgstr ""
908
 
909
+ #: app/view/event-multi.php:7
910
+ msgid "View in Calendar »"
911
  msgstr ""
912
 
913
+ #: app/view/event-multi.php:24
914
+ msgid "View Map »"
915
  msgstr ""
916
 
917
+ #: app/view/box_general_settings.php:1
918
+ msgid "Viewing Events"
919
  msgstr ""
920
 
921
+ #: app/view/box_general_settings.php:3
922
+ msgid "Calendar page:"
923
  msgstr ""
924
 
925
+ #: app/view/box_general_settings.php:7
926
+ msgid "Default calendar view:"
927
  msgstr ""
928
 
929
+ #: app/view/box_general_settings.php:12
930
+ msgid "Timezone:"
931
  msgstr ""
932
 
933
+ #: app/view/box_general_settings.php:17
934
+ msgid "Contain calendar in this DOM element:"
935
  msgstr ""
936
 
937
+ #: app/view/box_general_settings.php:19
938
+ msgid ""
939
+ "Optional. Provide a <a href=\"http://api.jquery.com/category/selectors/\" "
940
+ "target=\"_blank\">jQuery selector</a> that evaluates to a single DOM "
941
+ "element. Replaces any existing markup found within target. If left empty, "
942
+ "calendar is shown in normal page content container."
943
  msgstr ""
944
 
945
+ #: app/view/box_general_settings.php:21
946
+ msgid "Week starts on"
947
  msgstr ""
948
 
949
+ #: app/view/box_general_settings.php:25
950
+ msgid "Agenda pages show at most"
951
  msgstr ""
952
 
953
+ #: app/view/box_general_settings.php:26
954
+ msgid "events"
955
  msgstr ""
956
 
957
+ #: app/view/box_general_settings.php:31
958
+ msgid "Keep all events <strong>expanded</strong> in the agenda view"
959
  msgstr ""
960
 
961
+ #: app/view/box_general_settings.php:37
962
+ msgid "<strong>Exclude</strong> events from search results"
963
  msgstr ""
964
 
965
+ #: app/view/box_general_settings.php:43
966
+ msgid ""
967
+ "Show <strong>Post Your Event</strong> button above the calendar to "
968
+ "privileged users"
969
  msgstr ""
970
 
971
+ #: app/view/box_general_settings.php:49
972
+ msgid ""
973
+ "Hide <strong>Subscribe</strong>/<strong>Add to Calendar</strong> buttons in "
974
+ "calendar and single event views"
975
  msgstr ""
976
 
977
+ #: app/view/box_general_settings.php:55
978
+ msgid "Hide <strong>Google Maps</strong> until clicked"
979
  msgstr ""
980
 
981
+ #: app/view/box_general_settings.php:61
982
+ msgid ""
983
+ "Use the configured <strong>region</strong> (WordPress locale) to bias the "
984
+ "address autocomplete function"
985
  msgstr ""
986
 
987
+ #: app/view/box_general_settings.php:67
988
+ msgid "Include <strong>event categories</strong> in post category lists"
989
  msgstr ""
990
 
991
+ #: app/view/box_general_settings.php:71
992
+ msgid "Adding/Editing Events"
993
  msgstr ""
994
 
995
+ #: app/view/box_general_settings.php:73
996
+ msgid "Input dates in this format:"
 
 
 
997
  msgstr ""
998
 
999
+ #: app/view/box_general_settings.php:79
1000
+ msgid "Use <strong>24h time</strong> in time pickers"
 
 
1001
  msgstr ""
1002
 
1003
+ #: app/view/box_general_settings.php:85
1004
+ msgid "Display <strong>Publish</strong> at bottom of Edit Event form"
 
 
 
 
1005
  msgstr ""
1006
 
1007
+ #: app/view/agenda-widget.php:11
1008
+ msgid "There are no upcoming events."
 
 
1009
  msgstr ""
1010
 
1011
+ #: app/view/agenda-widget.php:59
1012
+ msgid "View Calendar »"
 
 
 
1013
  msgstr ""
1014
 
1015
+ #: app/view/agenda-widget.php:67 app/view/calendar.php:110
1016
+ msgid ""
1017
+ "Subscribe to this calendar using your favourite calendar program (iCal, "
1018
+ "Outlook, etc.)"
1019
  msgstr ""
1020
 
1021
+ #: app/view/agenda-widget.php:68 app/view/calendar.php:111
1022
+ msgid " Subscribe"
1023
  msgstr ""
1024
 
1025
+ #: app/view/agenda-widget.php:72 app/view/calendar.php:116
1026
+ msgid "Subscribe to this calendar in your Google Calendar"
1027
  msgstr ""
1028
 
1029
+ #: app/view/agenda-widget.php:74
1030
+ msgid "Add to Google"
1031
  msgstr ""
1032
 
1033
+ #: app/view/box_event_contact.php:1
1034
+ msgid "Organizer contact info"
1035
  msgstr ""
1036
 
1037
+ #: app/view/box_event_contact.php:7
1038
+ msgid "Contact name:"
1039
  msgstr ""
1040
 
1041
+ #: app/view/box_event_contact.php:17
1042
+ msgid "Phone:"
1043
  msgstr ""
1044
 
1045
+ #: app/view/box_event_contact.php:27
1046
+ msgid "E-mail:"
1047
  msgstr ""
1048
 
1049
+ #: app/view/admin_notices.php:2
1050
+ msgid "All-in-One Event Calendar Notice:"
1051
  msgstr ""
1052
 
1053
+ #: app/view/calendar.php:35
1054
+ msgid "+ Post Your Event"
1055
  msgstr ""
1056
 
1057
+ #: app/view/calendar.php:44
1058
+ msgid "Clear Filters"
1059
  msgstr ""
1060
 
1061
+ #: app/view/calendar.php:44
1062
+ msgid "✘"
 
1063
  msgstr ""
1064
 
1065
+ #: app/view/calendar.php:45
1066
+ msgid "Filter:"
1067
  msgstr ""
1068
 
1069
+ #: app/view/calendar.php:50
1070
+ msgid "Categories "
1071
  msgstr ""
1072
 
1073
+ #: app/view/calendar.php:72
1074
+ msgid "Tags "
1075
  msgstr ""
1076
 
1077
+ #: app/view/calendar.php:112
1078
+ msgid "to this filtered calendar"
1079
  msgstr ""
1080
 
1081
+ #: app/view/calendar.php:118
1082
+ msgid "Subscribe in Google Calendar"
1083
  msgstr ""
1084
 
1085
+ #: app/view/row_yearly.php:7
1086
+ msgctxt "Recurrence editor - yearly tab"
1087
+ msgid "In"
1088
  msgstr ""
1089
 
1090
+ #: app/view/agenda.php:5
1091
+ msgid "+ Expand All"
1092
  msgstr ""
1093
 
1094
+ #: app/view/agenda.php:8
1095
+ msgid " Collapse All"
1096
  msgstr ""
1097
 
1098
+ #: app/view/agenda.php:29
1099
+ msgid "There are no upcoming events to display at this time."
1100
  msgstr ""
1101
 
1102
+ #: app/view/agenda.php:77
1103
+ msgid "Read more »"
1104
  msgstr ""
1105
 
1106
+ #: app/view/event-single-footer.php:4
1107
+ msgid ""
1108
+ "This post was replicated from another site's <a class=\"ai1ec-ics-icon\" "
1109
+ "href=\"%s\" title=\"iCalendar feed\">calendar feed</a>."
1110
  msgstr ""
1111
 
1112
+ #: app/view/event-single-footer.php:8
1113
+ msgid "View original post »"
 
1114
  msgstr ""
1115
 
1116
+ #: app/view/agenda-widget-form.php:2
1117
+ msgid "Title:"
 
1118
  msgstr ""
1119
 
1120
+ #: app/view/agenda-widget-form.php:6
1121
+ msgid "Number of events to show:"
1122
  msgstr ""
1123
 
1124
+ #: app/view/agenda-widget-form.php:14
1125
+ msgid "Events with these <strong>Categories</strong>"
1126
  msgstr ""
1127
 
1128
+ #: app/view/agenda-widget-form.php:23
1129
+ msgid "No categories found."
1130
  msgstr ""
1131
 
1132
+ #: app/view/agenda-widget-form.php:30
1133
+ msgid "<strong>Or</strong> events with these <strong>Tags</strong>"
1134
  msgstr ""
1135
 
1136
+ #: app/view/agenda-widget-form.php:39
1137
+ msgid "No tags found."
1138
  msgstr ""
1139
 
1140
+ #: app/view/agenda-widget-form.php:46
1141
+ msgid "<strong>Or</strong> any of these <strong>Events</strong>"
1142
  msgstr ""
1143
 
1144
+ #: app/view/agenda-widget-form.php:55
1145
+ msgid "No events found."
1146
  msgstr ""
1147
 
1148
+ #: app/view/agenda-widget-form.php:62
1149
+ msgid "Show <strong>View Calendar</strong> button"
1150
  msgstr ""
1151
 
1152
+ #: app/view/agenda-widget-form.php:65
1153
+ msgid "Show <strong>Subscribe</strong> buttons"
1154
  msgstr ""
1155
 
1156
+ #: app/view/agenda-widget-form.php:68
1157
+ msgid "Hide this widget on calendar page"
1158
  msgstr ""
1159
 
1160
+ #: app/view/box_time_and_date.php:2
1161
+ msgid "Event date and time"
 
1162
  msgstr ""
1163
 
1164
+ #: app/view/box_time_and_date.php:8
1165
+ msgid "All-day event"
 
1166
  msgstr ""
1167
 
1168
+ #: app/view/box_time_and_date.php:18
1169
+ msgid "Start date / time"
 
1170
  msgstr ""
1171
 
1172
+ #: app/view/box_time_and_date.php:31
1173
+ msgid "End date / time"
 
1174
  msgstr ""
1175
 
1176
+ #: app/view/box_time_and_date.php:46
1177
+ msgid "Repeat"
1178
  msgstr ""
1179
 
1180
+ #: app/view/box_time_and_date.php:70
1181
+ msgid "End"
 
 
1182
  msgstr ""
1183
 
1184
+ #: app/view/box_time_and_date.php:77
1185
+ msgid "Ending after"
1186
  msgstr ""
1187
 
1188
+ #: app/view/box_time_and_date.php:92
1189
+ msgid "Apply"
1190
  msgstr ""
1191
 
1192
+ #: app/view/box_time_and_date.php:93
1193
+ msgid "Cancel"
1194
  msgstr ""
1195
 
1196
+ #: app/view/box_ics_import_settings.php:2
1197
+ msgid "Auto-refresh"
1198
  msgstr ""
1199
 
1200
+ #: app/view/box_ics_import_settings.php:12
1201
+ msgid "Event category"
 
 
 
1202
  msgstr ""
1203
 
1204
+ #: app/view/box_ics_import_settings.php:22
1205
+ msgid "+ Add new subscription"
 
 
1206
  msgstr ""
1207
 
1208
+ #: app/view/week.php:33
1209
+ msgid "All-day"
 
 
1210
  msgstr ""
1211
 
1212
+ #: app/view/event_categories-color_picker.php:5
1213
+ #: app/view/event_categories-color_picker.php:19
1214
+ msgid "Category Color"
 
1215
  msgstr ""
1216
 
1217
+ #: app/view/event_categories-color_picker.php:13
1218
+ #: app/view/event_categories-color_picker.php:25
1219
+ msgid "Events in this category will be identified by this color"
1220
+ msgstr ""
1221
+
1222
+ #: app/model/class-ai1ec-event.php:486
1223
+ msgid " (all-day)"
1224
  msgstr ""
1225
 
1226
  #. Plugin Name of the plugin/theme
lib/{iCalUtilityFunctions.class.php → iCalcreator-2.10.23/iCalUtilityFunctions.class.php} RENAMED
File without changes
lib/{iCalcreator.class.php → iCalcreator-2.10.23/iCalcreator.class.php} RENAMED
File without changes
lib/{lgpl.txt → iCalcreator-2.10.23/lgpl.txt} RENAMED
File without changes
lib/{releaseNotes-2.10.23.txt → iCalcreator-2.10.23/releaseNotes-2.10.23.txt} RENAMED
File without changes
lib/{summary.html → iCalcreator-2.10.23/summary.html} RENAMED
File without changes
lib/{using.html → iCalcreator-2.10.23/using.html} RENAMED
File without changes
lib/iCalcreator-2.10/iCalUtilityFunctions.class.php ADDED
@@ -0,0 +1,1505 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * iCalcreator class v2.10
4
+ * copyright (c) 2007-2011 Kjell-Inge Gustafsson kigkonsult
5
+ * www.kigkonsult.se/iCalcreator/index.php
6
+ * ical@kigkonsult.se
7
+ *
8
+ * This library is free software; you can redistribute it and/or
9
+ * modify it under the terms of the GNU Lesser General Public
10
+ * License as published by the Free Software Foundation; either
11
+ * version 2.1 of the License, or (at your option) any later version.
12
+ *
13
+ * This library is distributed in the hope that it will be useful,
14
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16
+ * Lesser General Public License for more details.
17
+ *
18
+ * You should have received a copy of the GNU Lesser General Public
19
+ * License along with this library; if not, write to the Free Software
20
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21
+ */
22
+ /**
23
+ * moving all utility (static) functions to a utility class
24
+ *
25
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
26
+ * @since 2.6.22 - 2010-09-25
27
+ *
28
+ */
29
+ class iCalUtilityFunctions {
30
+ // Store the single instance of iCalUtilityFunctions
31
+ private static $m_pInstance;
32
+
33
+ // Private constructor to limit object instantiation to within the class
34
+ private function __construct() {
35
+ $m_pInstance = FALSE;
36
+ }
37
+
38
+ // Getter method for creating/returning the single instance of this class
39
+ public static function getInstance() {
40
+ if (!self::$m_pInstance)
41
+ self::$m_pInstance = new iCalUtilityFunctions();
42
+
43
+ return self::$m_pInstance;
44
+ }
45
+ /**
46
+ * check a date(-time) for an opt. timezone and if it is a DATE-TIME or DATE
47
+ *
48
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
49
+ * @since 2.4.16 - 2008-10-25
50
+ * @param array $date, date to check
51
+ * @param int $parno, no of date parts (i.e. year, month.. .)
52
+ * @return array $params, property parameters
53
+ */
54
+ public static function _chkdatecfg( $theDate, & $parno, & $params ) {
55
+ if( isset( $params['TZID'] ))
56
+ $parno = 6;
57
+ elseif( isset( $params['VALUE'] ) && ( 'DATE' == $params['VALUE'] ))
58
+ $parno = 3;
59
+ else {
60
+ if( isset( $params['VALUE'] ) && ( 'PERIOD' == $params['VALUE'] ))
61
+ $parno = 7;
62
+ if( is_array( $theDate )) {
63
+ if( isset( $theDate['timestamp'] ))
64
+ $tzid = ( isset( $theDate['tz'] )) ? $theDate['tz'] : null;
65
+ else
66
+ $tzid = ( isset( $theDate['tz'] )) ? $theDate['tz'] : ( 7 == count( $theDate )) ? end( $theDate ) : null;
67
+ if( !empty( $tzid )) {
68
+ $parno = 7;
69
+ if( !iCalUtilityFunctions::_isOffset( $tzid ))
70
+ $params['TZID'] = $tzid; // save only timezone
71
+ }
72
+ elseif( !$parno && ( 3 == count( $theDate )) &&
73
+ ( isset( $params['VALUE'] ) && ( 'DATE' == $params['VALUE'] )))
74
+ $parno = 3;
75
+ else
76
+ $parno = 6;
77
+ }
78
+ else { // string
79
+ $date = trim( $theDate );
80
+ if( 'Z' == substr( $date, -1 ))
81
+ $parno = 7; // UTC DATE-TIME
82
+ elseif((( 8 == strlen( $date ) && ctype_digit( $date )) || ( 11 >= strlen( $date ))) &&
83
+ ( !isset( $params['VALUE'] ) || !in_array( $params['VALUE'], array( 'DATE-TIME', 'PERIOD' ))))
84
+ $parno = 3; // DATE
85
+ $date = iCalUtilityFunctions::_date_time_string( $date, $parno );
86
+ if( !empty( $date['tz'] )) {
87
+ $parno = 7;
88
+ if( !iCalUtilityFunctions::_isOffset( $date['tz'] ))
89
+ $params['TZID'] = $date['tz']; // save only timezone
90
+ }
91
+ elseif( empty( $parno ))
92
+ $parno = 6;
93
+ }
94
+ if( isset( $params['TZID'] ))
95
+ $parno = 6;
96
+ }
97
+ }
98
+ /**
99
+ * create (very simple) timezone and standard/daylight components
100
+ *
101
+ * Result when 'Europe/Stockholm' is used as timezone:
102
+ *
103
+ * BEGIN:VTIMEZONE
104
+ * TZID:Europe/Stockholm
105
+ * BEGIN:STANDARD
106
+ * DTSTART:20101031T020000
107
+ * TZOFFSETFROM:+0200
108
+ * TZOFFSETTO:+0100
109
+ * RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
110
+ * TZNAME:CET
111
+ * END:STANDARD
112
+ * BEGIN:DAYLIGHT
113
+ * DTSTART:20100328T030000
114
+ * TZOFFSETFROM:+0100
115
+ * TZOFFSETTO:+0200
116
+ * RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3
117
+ * TZNAME:CEST
118
+ * END:DAYLIGHT
119
+ * END:VTIMEZONE
120
+ *
121
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
122
+ * @since 2.9.2 - 2011-05-30
123
+ * @param object $calendar, reference to an iCalcreator calendar instance
124
+ * @param string $timezone, a PHP5 (DateTimeZone) valid timezone
125
+ * @param array $xProp, *[x-propName => x-propValue], optional
126
+ * @return bool
127
+ */
128
+ public static function createTimezone( & $calendar, $timezone, $xProp=array() ) {
129
+ if( !class_exists( 'DateTimeZone' ))
130
+ return FALSE;
131
+ if( empty( $timezone ))
132
+ return FALSE;
133
+ try {
134
+ $dtz = new DateTimeZone( $timezone );
135
+ $transitions = $dtz->getTransitions();
136
+ $stdDTSTART = $stdTZOFFSETTO = $stdTZOFFSETFROM = $stdTZNAME = $dlghtDTSTART = $dlghtTZOFFSETTO = $dlghtTZOFFSETFROM = $dlghtTZNAME = FALSE;
137
+ foreach( $transitions as $trans ) {
138
+ if( substr( $trans['time'], 0, 4 ) > ( date( 'Y' ) - 1 ))
139
+ break;
140
+ if( $trans['isdst'] !== TRUE ) {
141
+ $stdDTSTART = $trans['time'];
142
+ $stdTZOFFSETTO = $dlghtTZOFFSETFROM = iCalUtilityFunctions::offsetSec2His( $trans['offset'] );
143
+ $stdTZNAME = $trans['abbr'];
144
+ }
145
+ else {
146
+ $dlghtDTSTART = $trans['time'];
147
+ $dlghtTZOFFSETTO = $stdTZOFFSETFROM = iCalUtilityFunctions::offsetSec2His( $trans['offset'] );
148
+ $dlghtTZNAME = $trans['abbr'];
149
+ }
150
+ }
151
+ if( $stdDTSTART && $stdTZOFFSETTO && $stdTZOFFSETFROM && $stdTZNAME && $dlghtDTSTART && $dlghtTZOFFSETTO && $dlghtTZOFFSETFROM && $dlghtTZNAME ) {
152
+ $tz = & $calendar->newComponent( 'vtimezone' );
153
+ $tz->setproperty( 'tzid', $timezone );
154
+ if( !empty( $xProp )) {
155
+ foreach( $xProp as $xPropName => $xPropValue )
156
+ if( 'x-' == strtolower( substr( $xPropName, 0, 2 )))
157
+ $tz->setproperty( $xPropName, $xPropValue );
158
+ }
159
+ $std = & $tz->newComponent( 'standard' );
160
+ $std->setProperty( 'dtstart', $stdDTSTART );
161
+ $std->setProperty( 'tzname', $stdTZNAME );
162
+ $std->setProperty( 'tzoffsetto', $stdTZOFFSETTO );
163
+ $std->setProperty( 'tzoffsetfrom', $stdTZOFFSETFROM );
164
+ $std->setProperty( 'RRULE', array( 'FREQ' => 'YEARLY', 'BYDAY' => array( '-1', 'DAY' => 'SU' ), 'BYMONTH' => 10 ));
165
+ $dlght = & $tz->newComponent( 'daylight' );
166
+ $dlght->setProperty( 'dtstart', $dlghtDTSTART );
167
+ $dlght->setProperty( 'tzname', $dlghtTZNAME );
168
+ $dlght->setProperty( 'tzoffsetto', $dlghtTZOFFSETTO );
169
+ $dlght->setProperty( 'tzoffsetfrom', $dlghtTZOFFSETFROM );
170
+ $dlght->setProperty( 'RRULE', array( 'FREQ' => 'YEARLY', 'BYDAY' => array( '-1', 'DAY' => 'SU' ), 'BYMONTH' => 3 ));
171
+ }
172
+ }
173
+ catch( Exception $e ) {
174
+ return FALSE;
175
+ }
176
+ return TRUE;
177
+ }
178
+ /**
179
+ * convert date/datetime to timestamp
180
+ *
181
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
182
+ * @since 2.4.8 - 2008-10-30
183
+ * @param array $datetime datetime/(date)
184
+ * @param string $tz timezone
185
+ * @return timestamp
186
+ */
187
+ public static function _date2timestamp( $datetime, $tz=null ) {
188
+ $output = null;
189
+ if( !isset( $datetime['hour'] )) $datetime['hour'] = '0';
190
+ if( !isset( $datetime['min'] )) $datetime['min'] = '0';
191
+ if( !isset( $datetime['sec'] )) $datetime['sec'] = '0';
192
+ foreach( $datetime as $dkey => $dvalue ) {
193
+ if( 'tz' != $dkey )
194
+ $datetime[$dkey] = (integer) $dvalue;
195
+ }
196
+ if( $tz )
197
+ $datetime['tz'] = $tz;
198
+ $offset = ( isset( $datetime['tz'] ) && ( '' < trim ( $datetime['tz'] ))) ? iCalUtilityFunctions::_tz2offset( $datetime['tz'] ) : 0;
199
+ $output = mktime( $datetime['hour'], $datetime['min'], ($datetime['sec'] + $offset), $datetime['month'], $datetime['day'], $datetime['year'] );
200
+ return $output;
201
+ }
202
+ /**
203
+ * ensures internal date-time/date format for input date-time/date in array format
204
+ *
205
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
206
+ * @since 0.3.0 - 2006-08-15
207
+ * @param array $datetime
208
+ * @param int $parno optional, default FALSE
209
+ * @return array
210
+ */
211
+ public static function _date_time_array( $datetime, $parno=FALSE ) {
212
+ $output = array();
213
+ foreach( $datetime as $dateKey => $datePart ) {
214
+ switch ( $dateKey ) {
215
+ case '0': case 'year': $output['year'] = $datePart; break;
216
+ case '1': case 'month': $output['month'] = $datePart; break;
217
+ case '2': case 'day': $output['day'] = $datePart; break;
218
+ }
219
+ if( 3 != $parno ) {
220
+ switch ( $dateKey ) {
221
+ case '0':
222
+ case '1':
223
+ case '2': break;
224
+ case '3': case 'hour': $output['hour'] = $datePart; break;
225
+ case '4': case 'min' : $output['min'] = $datePart; break;
226
+ case '5': case 'sec' : $output['sec'] = $datePart; break;
227
+ case '6': case 'tz' : $output['tz'] = $datePart; break;
228
+ }
229
+ }
230
+ }
231
+ if( 3 != $parno ) {
232
+ if( !isset( $output['hour'] ))
233
+ $output['hour'] = 0;
234
+ if( !isset( $output['min'] ))
235
+ $output['min'] = 0;
236
+ if( !isset( $output['sec'] ))
237
+ $output['sec'] = 0;
238
+ }
239
+ return $output;
240
+ }
241
+ /**
242
+ * ensures internal date-time/date format for input date-time/date in string fromat
243
+ *
244
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
245
+ * @since 2.6.35 - 2010-12-03
246
+ * @param array $datetime
247
+ * @param int $parno optional, default FALSE
248
+ * @return array
249
+ */
250
+ public static function _date_time_string( $datetime, $parno=FALSE ) {
251
+ $datetime = (string) trim( $datetime );
252
+ $tz = null;
253
+ $len = strlen( $datetime ) - 1;
254
+ if( 'Z' == substr( $datetime, -1 )) {
255
+ $tz = 'Z';
256
+ $datetime = trim( substr( $datetime, 0, $len ));
257
+ }
258
+ elseif( ( ctype_digit( substr( $datetime, -2, 2 ))) && // time or date
259
+ ( '-' == substr( $datetime, -3, 1 )) ||
260
+ ( ':' == substr( $datetime, -3, 1 )) ||
261
+ ( '.' == substr( $datetime, -3, 1 ))) {
262
+ $continue = TRUE;
263
+ }
264
+ elseif( ( ctype_digit( substr( $datetime, -4, 4 ))) && // 4 pos offset
265
+ ( ' +' == substr( $datetime, -6, 2 )) ||
266
+ ( ' -' == substr( $datetime, -6, 2 ))) {
267
+ $tz = substr( $datetime, -5, 5 );
268
+ $datetime = substr( $datetime, 0, ($len - 5));
269
+ }
270
+ elseif( ( ctype_digit( substr( $datetime, -6, 6 ))) && // 6 pos offset
271
+ ( ' +' == substr( $datetime, -8, 2 )) ||
272
+ ( ' -' == substr( $datetime, -8, 2 ))) {
273
+ $tz = substr( $datetime, -7, 7 );
274
+ $datetime = substr( $datetime, 0, ($len - 7));
275
+ }
276
+ elseif( ( 6 < $len ) && ( ctype_digit( substr( $datetime, -6, 6 )))) {
277
+ $continue = TRUE;
278
+ }
279
+ elseif( 'T' == substr( $datetime, -7, 1 )) {
280
+ $continue = TRUE;
281
+ }
282
+ else {
283
+ $cx = $tx = 0; // 19970415T133000 US-Eastern
284
+ for( $cx = -1; $cx > ( 9 - $len ); $cx-- ) {
285
+ $char = substr( $datetime, $cx, 1 );
286
+ if(( ' ' == $char) || ctype_digit( $char))
287
+ break; // if exists, tz ends here.. . ?
288
+ else
289
+ $tx--; // tz length counter
290
+ }
291
+ if( 0 > $tx ) {
292
+ $tz = substr( $datetime, $tx );
293
+ $datetime = trim( substr( $datetime, 0, $len + $tx + 1 ));
294
+ }
295
+ }
296
+ if( 0 < substr_count( $datetime, '-' )) {
297
+ $datetime = str_replace( '-', '/', $datetime );
298
+ }
299
+ elseif( ctype_digit( substr( $datetime, 0, 8 )) &&
300
+ ( 'T' == substr( $datetime, 8, 1 )) &&
301
+ ctype_digit( substr( $datetime, 9, 6 ))) {
302
+ $datetime = substr( $datetime, 4, 2 )
303
+ .'/'.substr( $datetime, 6, 2 )
304
+ .'/'.substr( $datetime, 0, 4 )
305
+ .' '.substr( $datetime, 9, 2 )
306
+ .':'.substr( $datetime, 11, 2 )
307
+ .':'.substr( $datetime, 13);
308
+ }
309
+ $datestring = date( 'Y-m-d H:i:s', strtotime( $datetime ));
310
+ $tz = trim( $tz );
311
+ $output = array();
312
+ $output['year'] = substr( $datestring, 0, 4 );
313
+ $output['month'] = substr( $datestring, 5, 2 );
314
+ $output['day'] = substr( $datestring, 8, 2 );
315
+ if(( 6 == $parno ) || ( 7 == $parno ) || ( !$parno && ( 'Z' == $tz ))) {
316
+ $output['hour'] = substr( $datestring, 11, 2 );
317
+ $output['min'] = substr( $datestring, 14, 2 );
318
+ $output['sec'] = substr( $datestring, 17, 2 );
319
+ if( !empty( $tz ))
320
+ $output['tz'] = $tz;
321
+ }
322
+ elseif( 3 != $parno ) {
323
+ if(( '00' < substr( $datestring, 11, 2 )) ||
324
+ ( '00' < substr( $datestring, 14, 2 )) ||
325
+ ( '00' < substr( $datestring, 17, 2 ))) {
326
+ $output['hour'] = substr( $datestring, 11, 2 );
327
+ $output['min'] = substr( $datestring, 14, 2 );
328
+ $output['sec'] = substr( $datestring, 17, 2 );
329
+ }
330
+ if( !empty( $tz ))
331
+ $output['tz'] = $tz;
332
+ }
333
+ return $output;
334
+ }
335
+ /**
336
+ * convert local startdate/enddate (Ymd[His]) to duration array
337
+ *
338
+ * uses this component dates if missing input dates
339
+ *
340
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
341
+ * @since 2.6.11 - 2010-10-21
342
+ * @param array $startdate
343
+ * @param array $duration
344
+ * @return array duration
345
+ */
346
+ function _date2duration( $startdate, $enddate ) {
347
+ $startWdate = mktime( 0, 0, 0, $startdate['month'], $startdate['day'], $startdate['year'] );
348
+ $endWdate = mktime( 0, 0, 0, $enddate['month'], $enddate['day'], $enddate['year'] );
349
+ $wduration = $endWdate - $startWdate;
350
+ $dur = array();
351
+ $dur['week'] = (int) floor( $wduration / ( 7 * 24 * 60 * 60 ));
352
+ $wduration = $wduration % ( 7 * 24 * 60 * 60 );
353
+ $dur['day'] = (int) floor( $wduration / ( 24 * 60 * 60 ));
354
+ $wduration = $wduration % ( 24 * 60 * 60 );
355
+ $dur['hour'] = (int) floor( $wduration / ( 60 * 60 ));
356
+ $wduration = $wduration % ( 60 * 60 );
357
+ $dur['min'] = (int) floor( $wduration / ( 60 ));
358
+ $dur['sec'] = (int) $wduration % ( 60 );
359
+ return $dur;
360
+ }
361
+ /**
362
+ * ensures internal duration format for input in array format
363
+ *
364
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
365
+ * @since 2.1.1 - 2007-06-24
366
+ * @param array $duration
367
+ * @return array
368
+ */
369
+ public static function _duration_array( $duration ) {
370
+ $output = array();
371
+ if( is_array( $duration ) &&
372
+ ( 1 == count( $duration )) &&
373
+ isset( $duration['sec'] ) &&
374
+ ( 60 < $duration['sec'] )) {
375
+ $durseconds = $duration['sec'];
376
+ $output['week'] = floor( $durseconds / ( 60 * 60 * 24 * 7 ));
377
+ $durseconds = $durseconds % ( 60 * 60 * 24 * 7 );
378
+ $output['day'] = floor( $durseconds / ( 60 * 60 * 24 ));
379
+ $durseconds = $durseconds % ( 60 * 60 * 24 );
380
+ $output['hour'] = floor( $durseconds / ( 60 * 60 ));
381
+ $durseconds = $durseconds % ( 60 * 60 );
382
+ $output['min'] = floor( $durseconds / ( 60 ));
383
+ $output['sec'] = ( $durseconds % ( 60 ));
384
+ }
385
+ else {
386
+ foreach( $duration as $durKey => $durValue ) {
387
+ if( empty( $durValue )) continue;
388
+ switch ( $durKey ) {
389
+ case '0': case 'week': $output['week'] = $durValue; break;
390
+ case '1': case 'day': $output['day'] = $durValue; break;
391
+ case '2': case 'hour': $output['hour'] = $durValue; break;
392
+ case '3': case 'min': $output['min'] = $durValue; break;
393
+ case '4': case 'sec': $output['sec'] = $durValue; break;
394
+ }
395
+ }
396
+ }
397
+ if( isset( $output['week'] ) && ( 0 < $output['week'] )) {
398
+ unset( $output['day'], $output['hour'], $output['min'], $output['sec'] );
399
+ return $output;
400
+ }
401
+ unset( $output['week'] );
402
+ if( empty( $output['day'] ))
403
+ unset( $output['day'] );
404
+ if ( isset( $output['hour'] ) || isset( $output['min'] ) || isset( $output['sec'] )) {
405
+ if( !isset( $output['hour'] )) $output['hour'] = 0;
406
+ if( !isset( $output['min'] )) $output['min'] = 0;
407
+ if( !isset( $output['sec'] )) $output['sec'] = 0;
408
+ if(( 0 == $output['hour'] ) && ( 0 == $output['min'] ) && ( 0 == $output['sec'] ))
409
+ unset( $output['hour'], $output['min'], $output['sec'] );
410
+ }
411
+ return $output;
412
+ }
413
+ /**
414
+ * ensures internal duration format for input in string format
415
+ *
416
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
417
+ * @since 2.0.5 - 2007-03-14
418
+ * @param string $duration
419
+ * @return array
420
+ */
421
+ public static function _duration_string( $duration ) {
422
+ $duration = (string) trim( $duration );
423
+ while( 'P' != strtoupper( substr( $duration, 0, 1 ))) {
424
+ if( 0 < strlen( $duration ))
425
+ $duration = substr( $duration, 1 );
426
+ else
427
+ return false; // no leading P !?!?
428
+ }
429
+ $duration = substr( $duration, 1 ); // skip P
430
+ $duration = str_replace ( 't', 'T', $duration );
431
+ $duration = str_replace ( 'T', '', $duration );
432
+ $output = array();
433
+ $val = null;
434
+ for( $ix=0; $ix < strlen( $duration ); $ix++ ) {
435
+ switch( strtoupper( substr( $duration, $ix, 1 ))) {
436
+ case 'W':
437
+ $output['week'] = $val;
438
+ $val = null;
439
+ break;
440
+ case 'D':
441
+ $output['day'] = $val;
442
+ $val = null;
443
+ break;
444
+ case 'H':
445
+ $output['hour'] = $val;
446
+ $val = null;
447
+ break;
448
+ case 'M':
449
+ $output['min'] = $val;
450
+ $val = null;
451
+ break;
452
+ case 'S':
453
+ $output['sec'] = $val;
454
+ $val = null;
455
+ break;
456
+ default:
457
+ if( !ctype_digit( substr( $duration, $ix, 1 )))
458
+ return false; // unknown duration control character !?!?
459
+ else
460
+ $val .= substr( $duration, $ix, 1 );
461
+ }
462
+ }
463
+ return iCalUtilityFunctions::_duration_array( $output );
464
+ }
465
+ /**
466
+ * convert duration to date in array format
467
+ *
468
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
469
+ * @since 2.8.7 - 2011-03-03
470
+ * @param array $startdate
471
+ * @param array $duration
472
+ * @return array, date format
473
+ */
474
+ function _duration2date( $startdate=null, $duration=null ) {
475
+ if( empty( $startdate )) return FALSE;
476
+ if( empty( $duration )) return FALSE;
477
+ $dateOnly = ( isset( $startdate['hour'] ) || isset( $startdate['min'] ) || isset( $startdate['sec'] )) ? FALSE : TRUE;
478
+ $startdate['hour'] = ( isset( $startdate['hour'] )) ? $startdate['hour'] : 0;
479
+ $startdate['min'] = ( isset( $startdate['min'] )) ? $startdate['min'] : 0;
480
+ $startdate['sec'] = ( isset( $startdate['sec'] )) ? $startdate['sec'] : 0;
481
+ $dtend = 0;
482
+ if( isset( $duration['week'] ))
483
+ $dtend += ( $duration['week'] * 7 * 24 * 60 * 60 );
484
+ if( isset( $duration['day'] ))
485
+ $dtend += ( $duration['day'] * 24 * 60 * 60 );
486
+ if( isset( $duration['hour'] ))
487
+ $dtend += ( $duration['hour'] * 60 *60 );
488
+ if( isset( $duration['min'] ))
489
+ $dtend += ( $duration['min'] * 60 );
490
+ if( isset( $duration['sec'] ))
491
+ $dtend += $duration['sec'];
492
+ $dtend = mktime( $startdate['hour'], $startdate['min'], ( $startdate['sec'] + $dtend ), $startdate['month'], $startdate['day'], $startdate['year'] );
493
+ $dtend2 = array();
494
+ $dtend2['year'] = date('Y', $dtend );
495
+ $dtend2['month'] = date('m', $dtend );
496
+ $dtend2['day'] = date('d', $dtend );
497
+ $dtend2['hour'] = date('H', $dtend );
498
+ $dtend2['min'] = date('i', $dtend );
499
+ $dtend2['sec'] = date('s', $dtend );
500
+ if( isset( $startdate['tz'] ))
501
+ $dtend2['tz'] = $startdate['tz'];
502
+ if( $dateOnly && (( 0 == $dtend2['hour'] ) && ( 0 == $dtend2['min'] ) && ( 0 == $dtend2['sec'] )))
503
+ unset( $dtend2['hour'], $dtend2['min'], $dtend2['sec'] );
504
+ return $dtend2;
505
+ }
506
+ /**
507
+ * if not preSet, if exist, remove key with expected value from array and return hit value else return elseValue
508
+ *
509
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
510
+ * @since 2.4.16 - 2008-11-08
511
+ * @param array $array
512
+ * @param string $expkey, expected key
513
+ * @param string $expval, expected value
514
+ * @param int $hitVal optional, return value if found
515
+ * @param int $elseVal optional, return value if not found
516
+ * @param int $preSet optional, return value if already preset
517
+ * @return int
518
+ */
519
+ public static function _existRem( &$array, $expkey, $expval=FALSE, $hitVal=null, $elseVal=null, $preSet=null ) {
520
+ if( $preSet )
521
+ return $preSet;
522
+ if( !is_array( $array ) || ( 0 == count( $array )))
523
+ return $elseVal;
524
+ foreach( $array as $key => $value ) {
525
+ if( strtoupper( $expkey ) == strtoupper( $key )) {
526
+ if( !$expval || ( strtoupper( $expval ) == strtoupper( $array[$key] ))) {
527
+ unset( $array[$key] );
528
+ return $hitVal;
529
+ }
530
+ }
531
+ }
532
+ return $elseVal;
533
+ }
534
+ /**
535
+ * creates formatted output for calendar component property data value type date/date-time
536
+ *
537
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
538
+ * @since 2.4.8 - 2008-10-30
539
+ * @param array $datetime
540
+ * @param int $parno, optional, default 6
541
+ * @return string
542
+ */
543
+ public static function _format_date_time( $datetime, $parno=6 ) {
544
+ if( !isset( $datetime['year'] ) &&
545
+ !isset( $datetime['month'] ) &&
546
+ !isset( $datetime['day'] ) &&
547
+ !isset( $datetime['hour'] ) &&
548
+ !isset( $datetime['min'] ) &&
549
+ !isset( $datetime['sec'] ))
550
+ return ;
551
+ $output = null;
552
+ // if( !isset( $datetime['day'] )) { $o=''; foreach($datetime as $k=>$v) {if(is_array($v)) $v=implode('-',$v);$o.=" $k=>$v";} echo " day SAKNAS : $o <br />\n"; }
553
+ foreach( $datetime as $dkey => & $dvalue )
554
+ if( 'tz' != $dkey ) $dvalue = (integer) $dvalue;
555
+ $output = date('Ymd', mktime( 0, 0, 0, $datetime['month'], $datetime['day'], $datetime['year']));
556
+ if( isset( $datetime['hour'] ) ||
557
+ isset( $datetime['min'] ) ||
558
+ isset( $datetime['sec'] ) ||
559
+ isset( $datetime['tz'] )) {
560
+ if( isset( $datetime['tz'] ) &&
561
+ !isset( $datetime['hour'] ))
562
+ $datetime['hour'] = 0;
563
+ if( isset( $datetime['hour'] ) &&
564
+ !isset( $datetime['min'] ))
565
+ $datetime['min'] = 0;
566
+ if( isset( $datetime['hour'] ) &&
567
+ isset( $datetime['min'] ) &&
568
+ !isset( $datetime['sec'] ))
569
+ $datetime['sec'] = 0;
570
+ $date = mktime( $datetime['hour'], $datetime['min'], $datetime['sec'], $datetime['month'], $datetime['day'], $datetime['year']);
571
+ $output .= date('\THis', $date );
572
+ if( isset( $datetime['tz'] ) && ( '' < trim ( $datetime['tz'] ))) {
573
+ $datetime['tz'] = trim( $datetime['tz'] );
574
+ if( 'Z' == $datetime['tz'] )
575
+ $output .= 'Z';
576
+ $offset = iCalUtilityFunctions::_tz2offset( $datetime['tz'] );
577
+ if( 0 != $offset ) {
578
+ $date = mktime( $datetime['hour'], $datetime['min'], ($datetime['sec'] + $offset), $datetime['month'], $datetime['day'], $datetime['year']);
579
+ $output = date( 'Ymd\THis\Z', $date );
580
+ }
581
+ }
582
+ elseif( 7 == $parno )
583
+ $output .= 'Z';
584
+ }
585
+ return $output;
586
+ }
587
+ /**
588
+ * creates formatted output for calendar component property data value type duration
589
+ *
590
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
591
+ * @since 2.9.9 - 2011-06-17
592
+ * @param array $duration ( week, day, hour, min, sec )
593
+ * @return string
594
+ */
595
+ public static function _format_duration( $duration ) {
596
+ if( isset( $duration['week'] ) ||
597
+ isset( $duration['day'] ) ||
598
+ isset( $duration['hour'] ) ||
599
+ isset( $duration['min'] ) ||
600
+ isset( $duration['sec'] ))
601
+ $ok = TRUE;
602
+ else
603
+ return;
604
+ if( isset( $duration['week'] ) && ( 0 < $duration['week'] ))
605
+ return 'P'.$duration['week'].'W';
606
+ $output = 'P';
607
+ if( isset($duration['day'] ) && ( 0 < $duration['day'] ))
608
+ $output .= $duration['day'].'D';
609
+ if(( isset( $duration['hour']) && ( 0 < $duration['hour'] )) ||
610
+ ( isset( $duration['min']) && ( 0 < $duration['min'] )) ||
611
+ ( isset( $duration['sec']) && ( 0 < $duration['sec'] )))
612
+ $output .= 'T';
613
+ $output .= ( isset( $duration['hour']) && ( 0 < $duration['hour'] )) ? $duration['hour'].'H' : '';
614
+ $output .= ( isset( $duration['min']) && ( 0 < $duration['min'] )) ? $duration['min']. 'M' : '';
615
+ $output .= ( isset( $duration['sec']) && ( 0 < $duration['sec'] )) ? $duration['sec']. 'S' : '';
616
+ if( 'P' == $output )
617
+ $output = 'PT0S';
618
+ return $output;
619
+ }
620
+ /**
621
+ * checks if input array contains a date
622
+ *
623
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
624
+ * @since 2.4.16 - 2008-10-25
625
+ * @param array $input
626
+ * @return bool
627
+ */
628
+ public static function _isArrayDate( $input ) {
629
+ if( isset( $input['week'] ) || ( !in_array( count( $input ), array( 3, 6, 7 ))))
630
+ return FALSE;
631
+ if( 7 == count( $input ))
632
+ return TRUE;
633
+ if( isset( $input['year'] ) && isset( $input['month'] ) && isset( $input['day'] ))
634
+ return checkdate( (int) $input['month'], (int) $input['day'], (int) $input['year'] );
635
+ if( isset( $input['day'] ) || isset( $input['hour'] ) || isset( $input['min'] ) || isset( $input['sec'] ))
636
+ return FALSE;
637
+ if( in_array( 0, $input ))
638
+ return FALSE;
639
+ if(( 1970 > $input[0] ) || ( 12 < $input[1] ) || ( 31 < $input[2] ))
640
+ return FALSE;
641
+ if(( isset( $input[0] ) && isset( $input[1] ) && isset( $input[2] )) &&
642
+ checkdate( (int) $input[1], (int) $input[2], (int) $input[0] ))
643
+ return TRUE;
644
+ $input = iCalUtilityFunctions::_date_time_string( $input[1].'/'.$input[2].'/'.$input[0], 3 ); // m - d - Y
645
+ if( isset( $input['year'] ) && isset( $input['month'] ) && isset( $input['day'] ))
646
+ return checkdate( (int) $input['month'], (int) $input['day'], (int) $input['year'] );
647
+ return FALSE;
648
+ }
649
+ /**
650
+ * checks if input array contains a timestamp date
651
+ *
652
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
653
+ * @since 2.4.16 - 2008-10-18
654
+ * @param array $input
655
+ * @return bool
656
+ */
657
+ public static function _isArrayTimestampDate( $input ) {
658
+ return ( is_array( $input ) && isset( $input['timestamp'] )) ? TRUE : FALSE ;
659
+ }
660
+ /**
661
+ * controll if input string contains trailing UTC offset
662
+ *
663
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
664
+ * @since 2.4.16 - 2008-10-19
665
+ * @param string $input
666
+ * @return bool
667
+ */
668
+ public static function _isOffset( $input ) {
669
+ $input = trim( (string) $input );
670
+ if( 'Z' == substr( $input, -1 ))
671
+ return TRUE;
672
+ elseif(( 5 <= strlen( $input )) &&
673
+ ( in_array( substr( $input, -5, 1 ), array( '+', '-' ))) &&
674
+ ( '0000' < substr( $input, -4 )) && ( '9999' >= substr( $input, -4 )))
675
+ return TRUE;
676
+ elseif(( 7 <= strlen( $input )) &&
677
+ ( in_array( substr( $input, -7, 1 ), array( '+', '-' ))) &&
678
+ ( '000000' < substr( $input, -6 )) && ( '999999' >= substr( $input, -6 )))
679
+ return TRUE;
680
+ return FALSE;
681
+
682
+ }
683
+ /**
684
+ * transform offset in seconds to [-/+]hhmm[ss]
685
+ *
686
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
687
+ * @since 2011-05-02
688
+ * @param string $seconds
689
+ * @return string
690
+ */
691
+ public static function offsetSec2His( $seconds ) {
692
+ if( '-' == substr( $seconds, 0, 1 )) {
693
+ $prefix = '-';
694
+ $seconds = substr( $seconds, 1 );
695
+ }
696
+ elseif( '+' == substr( $seconds, 0, 1 )) {
697
+ $prefix = '+';
698
+ $seconds = substr( $seconds, 1 );
699
+ }
700
+ else
701
+ $prefix = '+';
702
+ $output = '';
703
+ $hour = (int) floor( $seconds / 3600 );
704
+ if( 10 > $hour )
705
+ $hour = '0'.$hour;
706
+ $seconds = $seconds % 3600;
707
+ $min = (int) floor( $seconds / 60 );
708
+ if( 10 > $min )
709
+ $min = '0'.$min;
710
+ $output = $hour.$min;
711
+ $seconds = $seconds % 60;
712
+ if( 0 < $seconds) {
713
+ if( 9 < $seconds)
714
+ $output .= $seconds;
715
+ else
716
+ $output .= '0'.$seconds;
717
+ }
718
+ return $prefix.$output;
719
+ }
720
+ /**
721
+ * remakes a recur pattern to an array of dates
722
+ *
723
+ * if missing, UNTIL is set 1 year from startdate (emergency break)
724
+ *
725
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
726
+ * @since 2.9.10 - 2011-07-07
727
+ * @param array $result, array to update, array([timestamp] => timestamp)
728
+ * @param array $recur, pattern for recurrency (only value part, params ignored)
729
+ * @param array $wdate, component start date
730
+ * @param array $startdate, start date
731
+ * @param array $enddate, optional
732
+ * @return array of recurrence (start-)dates as index
733
+ * @todo BYHOUR, BYMINUTE, BYSECOND, ev. BYSETPOS due to ambiguity, WEEKLY at year end/start
734
+ */
735
+ public static function _recur2date( & $result, $recur, $wdate, $startdate, $enddate=FALSE ) {
736
+ foreach( $wdate as $k => $v ) if( ctype_digit( $v )) $wdate[$k] = (int) $v;
737
+ $wdateStart = $wdate;
738
+ $wdatets = iCalUtilityFunctions::_date2timestamp( $wdate );
739
+ $startdatets = iCalUtilityFunctions::_date2timestamp( $startdate );
740
+ if( !$enddate ) {
741
+ $enddate = $startdate;
742
+ $enddate['year'] += 1;
743
+ }
744
+ // echo "recur __in_ comp start ".implode('-',$wdate)." period start ".implode('-',$startdate)." period end ".implode('-',$enddate)."<br />\n";print_r($recur);echo "<br />\n";//test###
745
+ $endDatets = iCalUtilityFunctions::_date2timestamp( $enddate ); // fix break
746
+ if( !isset( $recur['COUNT'] ) && !isset( $recur['UNTIL'] ))
747
+ $recur['UNTIL'] = $enddate; // create break
748
+ if( isset( $recur['UNTIL'] )) {
749
+ $tdatets = iCalUtilityFunctions::_date2timestamp( $recur['UNTIL'] );
750
+ if( $endDatets > $tdatets ) {
751
+ $endDatets = $tdatets; // emergency break
752
+ $enddate = iCalUtilityFunctions::_timestamp2date( $endDatets, 6 );
753
+ }
754
+ else
755
+ $recur['UNTIL'] = iCalUtilityFunctions::_timestamp2date( $endDatets, 6 );
756
+ }
757
+ if( $wdatets > $endDatets ) {
758
+ // echo "recur out of date ".implode('-',iCalUtilityFunctions::_date_time_string(date('Y-m-d H:i:s',$wdatets),6))."<br />\n";//test
759
+ return array(); // nothing to do.. .
760
+ }
761
+ if( !isset( $recur['FREQ'] )) // "MUST be specified.. ."
762
+ $recur['FREQ'] = 'DAILY'; // ??
763
+ $wkst = ( isset( $recur['WKST'] ) && ( 'SU' == $recur['WKST'] )) ? 24*60*60 : 0; // ??
764
+ $weekStart = (int) date( 'W', ( $wdatets + $wkst ));
765
+ if( !isset( $recur['INTERVAL'] ))
766
+ $recur['INTERVAL'] = 1;
767
+ $countcnt = ( !isset( $recur['BYSETPOS'] )) ? 1 : 0; // DTSTART counts as the first occurrence
768
+ /* find out how to step up dates and set index for interval count */
769
+ $step = array();
770
+ if( 'YEARLY' == $recur['FREQ'] )
771
+ $step['year'] = 1;
772
+ elseif( 'MONTHLY' == $recur['FREQ'] )
773
+ $step['month'] = 1;
774
+ elseif( 'WEEKLY' == $recur['FREQ'] )
775
+ $step['day'] = 7;
776
+ else
777
+ $step['day'] = 1;
778
+ if( isset( $step['year'] ) && isset( $recur['BYMONTH'] ))
779
+ $step = array( 'month' => 1 );
780
+ if( empty( $step ) && isset( $recur['BYWEEKNO'] )) // ??
781
+ $step = array( 'day' => 7 );
782
+ if( isset( $recur['BYYEARDAY'] ) || isset( $recur['BYMONTHDAY'] ) || isset( $recur['BYDAY'] ))
783
+ $step = array( 'day' => 1 );
784
+ $intervalarr = array();
785
+ if( 1 < $recur['INTERVAL'] ) {
786
+ $intervalix = iCalUtilityFunctions::_recurIntervalIx( $recur['FREQ'], $wdate, $wkst );
787
+ $intervalarr = array( $intervalix => 0 );
788
+ }
789
+ if( isset( $recur['BYSETPOS'] )) { // save start date + weekno
790
+ $bysetposymd1 = $bysetposymd2 = $bysetposw1 = $bysetposw2 = array();
791
+ // echo "bysetposXold_start=$bysetposYold $bysetposMold $bysetposDold<br />\n"; // test ###
792
+ if( is_array( $recur['BYSETPOS'] )) {
793
+ foreach( $recur['BYSETPOS'] as $bix => $bval )
794
+ $recur['BYSETPOS'][$bix] = (int) $bval;
795
+ }
796
+ else
797
+ $recur['BYSETPOS'] = array( (int) $recur['BYSETPOS'] );
798
+ if( 'YEARLY' == $recur['FREQ'] ) {
799
+ $wdate['month'] = $wdate['day'] = 1; // start from beginning of year
800
+ $wdatets = iCalUtilityFunctions::_date2timestamp( $wdate );
801
+ iCalUtilityFunctions::_stepdate( $enddate, $endDatets, array( 'year' => 1 )); // make sure to count whole last year
802
+ }
803
+ elseif( 'MONTHLY' == $recur['FREQ'] ) {
804
+ $wdate['day'] = 1; // start from beginning of month
805
+ $wdatets = iCalUtilityFunctions::_date2timestamp( $wdate );
806
+ iCalUtilityFunctions::_stepdate( $enddate, $endDatets, array( 'month' => 1 )); // make sure to count whole last month
807
+ }
808
+ else
809
+ iCalUtilityFunctions::_stepdate( $enddate, $endDatets, $step); // make sure to count whole last period
810
+ // echo "BYSETPOS endDat++ =".implode('-',$enddate).' step='.var_export($step,TRUE)."<br />\n";//test###
811
+ $bysetposWold = (int) date( 'W', ( $wdatets + $wkst ));
812
+ $bysetposYold = $wdate['year'];
813
+ $bysetposMold = $wdate['month'];
814
+ $bysetposDold = $wdate['day'];
815
+ }
816
+ else
817
+ iCalUtilityFunctions::_stepdate( $wdate, $wdatets, $step);
818
+ $year_old = null;
819
+ $daynames = array( 'SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA' );
820
+ /* MAIN LOOP */
821
+ // echo "recur start ".implode('-',$wdate)." end ".implode('-',$enddate)."<br />\n";//test
822
+ while( TRUE ) {
823
+ if( isset( $endDatets ) && ( $wdatets > $endDatets ))
824
+ break;
825
+ if( isset( $recur['COUNT'] ) && ( $countcnt >= $recur['COUNT'] ))
826
+ break;
827
+ if( $year_old != $wdate['year'] ) {
828
+ $year_old = $wdate['year'];
829
+ $daycnts = array();
830
+ $yeardays = $weekno = 0;
831
+ $yeardaycnt = array();
832
+ for( $m = 1; $m <= 12; $m++ ) { // count up and update up-counters
833
+ $daycnts[$m] = array();
834
+ $weekdaycnt = array();
835
+ foreach( $daynames as $dn )
836
+ $yeardaycnt[$dn] = $weekdaycnt[$dn] = 0;
837
+ $mcnt = date( 't', mktime( 0, 0, 0, $m, 1, $wdate['year'] ));
838
+ for( $d = 1; $d <= $mcnt; $d++ ) {
839
+ $daycnts[$m][$d] = array();
840
+ if( isset( $recur['BYYEARDAY'] )) {
841
+ $yeardays++;
842
+ $daycnts[$m][$d]['yearcnt_up'] = $yeardays;
843
+ }
844
+ if( isset( $recur['BYDAY'] )) {
845
+ $day = date( 'w', mktime( 0, 0, 0, $m, $d, $wdate['year'] ));
846
+ $day = $daynames[$day];
847
+ $daycnts[$m][$d]['DAY'] = $day;
848
+ $weekdaycnt[$day]++;
849
+ $daycnts[$m][$d]['monthdayno_up'] = $weekdaycnt[$day];
850
+ $yeardaycnt[$day]++;
851
+ $daycnts[$m][$d]['yeardayno_up'] = $yeardaycnt[$day];
852
+ }
853
+ if( isset( $recur['BYWEEKNO'] ) || ( $recur['FREQ'] == 'WEEKLY' ))
854
+ $daycnts[$m][$d]['weekno_up'] =(int)date('W',mktime(0,0,$wkst,$m,$d,$wdate['year']));
855
+ }
856
+ }
857
+ $daycnt = 0;
858
+ $yeardaycnt = array();
859
+ if( isset( $recur['BYWEEKNO'] ) || ( $recur['FREQ'] == 'WEEKLY' )) {
860
+ $weekno = null;
861
+ for( $d=31; $d > 25; $d-- ) { // get last weekno for year
862
+ if( !$weekno )
863
+ $weekno = $daycnts[12][$d]['weekno_up'];
864
+ elseif( $weekno < $daycnts[12][$d]['weekno_up'] ) {
865
+ $weekno = $daycnts[12][$d]['weekno_up'];
866
+ break;
867
+ }
868
+ }
869
+ }
870
+ for( $m = 12; $m > 0; $m-- ) { // count down and update down-counters
871
+ $weekdaycnt = array();
872
+ foreach( $daynames as $dn )
873
+ $yeardaycnt[$dn] = $weekdaycnt[$dn] = 0;
874
+ $monthcnt = 0;
875
+ $mcnt = date( 't', mktime( 0, 0, 0, $m, 1, $wdate['year'] ));
876
+ for( $d = $mcnt; $d > 0; $d-- ) {
877
+ if( isset( $recur['BYYEARDAY'] )) {
878
+ $daycnt -= 1;
879
+ $daycnts[$m][$d]['yearcnt_down'] = $daycnt;
880
+ }
881
+ if( isset( $recur['BYMONTHDAY'] )) {
882
+ $monthcnt -= 1;
883
+ $daycnts[$m][$d]['monthcnt_down'] = $monthcnt;
884
+ }
885
+ if( isset( $recur['BYDAY'] )) {
886
+ $day = $daycnts[$m][$d]['DAY'];
887
+ $weekdaycnt[$day] -= 1;
888
+ $daycnts[$m][$d]['monthdayno_down'] = $weekdaycnt[$day];
889
+ $yeardaycnt[$day] -= 1;
890
+ $daycnts[$m][$d]['yeardayno_down'] = $yeardaycnt[$day];
891
+ }
892
+ if( isset( $recur['BYWEEKNO'] ) || ( $recur['FREQ'] == 'WEEKLY' ))
893
+ $daycnts[$m][$d]['weekno_down'] = ($daycnts[$m][$d]['weekno_up'] - $weekno - 1);
894
+ }
895
+ }
896
+ }
897
+ /* check interval */
898
+ if( 1 < $recur['INTERVAL'] ) {
899
+ /* create interval index */
900
+ $intervalix = iCalUtilityFunctions::_recurIntervalIx( $recur['FREQ'], $wdate, $wkst );
901
+ /* check interval */
902
+ $currentKey = array_keys( $intervalarr );
903
+ $currentKey = end( $currentKey ); // get last index
904
+ if( $currentKey != $intervalix )
905
+ $intervalarr = array( $intervalix => ( $intervalarr[$currentKey] + 1 ));
906
+ if(( $recur['INTERVAL'] != $intervalarr[$intervalix] ) &&
907
+ ( 0 != $intervalarr[$intervalix] )) {
908
+ /* step up date */
909
+ // echo "skip: ".implode('-',$wdate)." ix=$intervalix old=$currentKey interval=".$intervalarr[$intervalix]."<br />\n";//test
910
+ iCalUtilityFunctions::_stepdate( $wdate, $wdatets, $step);
911
+ continue;
912
+ }
913
+ else // continue within the selected interval
914
+ $intervalarr[$intervalix] = 0;
915
+ // echo "cont: ".implode('-',$wdate)." ix=$intervalix old=$currentKey interval=".$intervalarr[$intervalix]."<br />\n";//test
916
+ }
917
+ $updateOK = TRUE;
918
+ if( $updateOK && isset( $recur['BYMONTH'] ))
919
+ $updateOK = iCalUtilityFunctions::_recurBYcntcheck( $recur['BYMONTH']
920
+ , $wdate['month']
921
+ ,($wdate['month'] - 13));
922
+ if( $updateOK && isset( $recur['BYWEEKNO'] ))
923
+ $updateOK = iCalUtilityFunctions::_recurBYcntcheck( $recur['BYWEEKNO']
924
+ , $daycnts[$wdate['month']][$wdate['day']]['weekno_up']
925
+ , $daycnts[$wdate['month']][$wdate['day']]['weekno_down'] );
926
+ if( $updateOK && isset( $recur['BYYEARDAY'] ))
927
+ $updateOK = iCalUtilityFunctions::_recurBYcntcheck( $recur['BYYEARDAY']
928
+ , $daycnts[$wdate['month']][$wdate['day']]['yearcnt_up']
929
+ , $daycnts[$wdate['month']][$wdate['day']]['yearcnt_down'] );
930
+ if( $updateOK && isset( $recur['BYMONTHDAY'] ))
931
+ $updateOK = iCalUtilityFunctions::_recurBYcntcheck( $recur['BYMONTHDAY']
932
+ , $wdate['day']
933
+ , $daycnts[$wdate['month']][$wdate['day']]['monthcnt_down'] );
934
+ // echo "efter BYMONTHDAY: ".implode('-',$wdate).' status: '; echo ($updateOK) ? 'TRUE' : 'FALSE'; echo "<br />\n";//test###
935
+ if( $updateOK && isset( $recur['BYDAY'] )) {
936
+ $updateOK = FALSE;
937
+ $m = $wdate['month'];
938
+ $d = $wdate['day'];
939
+ if( isset( $recur['BYDAY']['DAY'] )) { // single day, opt with year/month day order no
940
+ $daynoexists = $daynosw = $daynamesw = FALSE;
941
+ if( $recur['BYDAY']['DAY'] == $daycnts[$m][$d]['DAY'] )
942
+ $daynamesw = TRUE;
943
+ if( isset( $recur['BYDAY'][0] )) {
944
+ $daynoexists = TRUE;
945
+ if(( isset( $recur['FREQ'] ) && ( $recur['FREQ'] == 'MONTHLY' )) || isset( $recur['BYMONTH'] ))
946
+ $daynosw = iCalUtilityFunctions::_recurBYcntcheck( $recur['BYDAY'][0]
947
+ , $daycnts[$m][$d]['monthdayno_up']
948
+ , $daycnts[$m][$d]['monthdayno_down'] );
949
+ elseif( isset( $recur['FREQ'] ) && ( $recur['FREQ'] == 'YEARLY' ))
950
+ $daynosw = iCalUtilityFunctions::_recurBYcntcheck( $recur['BYDAY'][0]
951
+ , $daycnts[$m][$d]['yeardayno_up']
952
+ , $daycnts[$m][$d]['yeardayno_down'] );
953
+ }
954
+ if(( $daynoexists && $daynosw && $daynamesw ) ||
955
+ ( !$daynoexists && !$daynosw && $daynamesw )) {
956
+ $updateOK = TRUE;
957
+ }
958
+ // echo "daynoexists:$daynoexists daynosw:$daynosw daynamesw:$daynamesw<br />\n"; // test ###
959
+ }
960
+ else {
961
+ foreach( $recur['BYDAY'] as $bydayvalue ) {
962
+ $daynoexists = $daynosw = $daynamesw = FALSE;
963
+ if( isset( $bydayvalue['DAY'] ) &&
964
+ ( $bydayvalue['DAY'] == $daycnts[$m][$d]['DAY'] ))
965
+ $daynamesw = TRUE;
966
+ if( isset( $bydayvalue[0] )) {
967
+ $daynoexists = TRUE;
968
+ if(( isset( $recur['FREQ'] ) && ( $recur['FREQ'] == 'MONTHLY' )) ||
969
+ isset( $recur['BYMONTH'] ))
970
+ $daynosw = iCalUtilityFunctions::_recurBYcntcheck( $bydayvalue['0']
971
+ , $daycnts[$m][$d]['monthdayno_up']
972
+ , $daycnts[$m][$d]['monthdayno_down'] );
973
+ elseif( isset( $recur['FREQ'] ) && ( $recur['FREQ'] == 'YEARLY' ))
974
+ $daynosw = iCalUtilityFunctions::_recurBYcntcheck( $bydayvalue['0']
975
+ , $daycnts[$m][$d]['yeardayno_up']
976
+ , $daycnts[$m][$d]['yeardayno_down'] );
977
+ }
978
+ // echo "daynoexists:$daynoexists daynosw:$daynosw daynamesw:$daynamesw<br />\n"; // test ###
979
+ if(( $daynoexists && $daynosw && $daynamesw ) ||
980
+ ( !$daynoexists && !$daynosw && $daynamesw )) {
981
+ $updateOK = TRUE;
982
+ break;
983
+ }
984
+ }
985
+ }
986
+ }
987
+ // echo "efter BYDAY: ".implode('-',$wdate).' status: '; echo ($updateOK) ? 'TRUE' : 'FALSE'; echo "<br />\n"; // test ###
988
+ /* check BYSETPOS */
989
+ if( $updateOK ) {
990
+ if( isset( $recur['BYSETPOS'] ) &&
991
+ ( in_array( $recur['FREQ'], array( 'YEARLY', 'MONTHLY', 'WEEKLY', 'DAILY' )))) {
992
+ if( isset( $recur['WEEKLY'] )) {
993
+ if( $bysetposWold == $daycnts[$wdate['month']][$wdate['day']]['weekno_up'] )
994
+ $bysetposw1[] = $wdatets;
995
+ else
996
+ $bysetposw2[] = $wdatets;
997
+ }
998
+ else {
999
+ if(( isset( $recur['FREQ'] ) && ( 'YEARLY' == $recur['FREQ'] ) &&
1000
+ ( $bysetposYold == $wdate['year'] )) ||
1001
+ ( isset( $recur['FREQ'] ) && ( 'MONTHLY' == $recur['FREQ'] ) &&
1002
+ (( $bysetposYold == $wdate['year'] ) &&
1003
+ ( $bysetposMold == $wdate['month'] ))) ||
1004
+ ( isset( $recur['FREQ'] ) && ( 'DAILY' == $recur['FREQ'] ) &&
1005
+ (( $bysetposYold == $wdate['year'] ) &&
1006
+ ( $bysetposMold == $wdate['month']) &&
1007
+ ( $bysetposDold == $wdate['day'] )))) {
1008
+ // echo "bysetposymd1[]=".implode('-',iCalUtilityFunctions::_date_time_string(date('Y-m-d H:i:s',$wdatets),6))."<br />\n";//test
1009
+ $bysetposymd1[] = $wdatets;
1010
+ }
1011
+ else {
1012
+ // echo "bysetposymd2[]=".implode('-',iCalUtilityFunctions::_date_time_string(date('Y-m-d H:i:s',$wdatets),6))."<br />\n";//test
1013
+ $bysetposymd2[] = $wdatets;
1014
+ }
1015
+ }
1016
+ }
1017
+ else {
1018
+ /* update result array if BYSETPOS is set */
1019
+ $countcnt++;
1020
+ if( $startdatets <= $wdatets ) { // only output within period
1021
+ $result[$wdatets] = TRUE;
1022
+ // echo "recur ".implode('-',iCalUtilityFunctions::_date_time_string(date('Y-m-d H:i:s',$wdatets),6))."<br />\n";//test
1023
+ }
1024
+ // echo "recur undate ".implode('-',iCalUtilityFunctions::_date_time_string(date('Y-m-d H:i:s',$wdatets),6))." okdatstart ".implode('-',iCalUtilityFunctions::_date_time_string(date('Y-m-d H:i:s',$startdatets),6))."<br />\n";//test
1025
+ $updateOK = FALSE;
1026
+ }
1027
+ }
1028
+ /* step up date */
1029
+ iCalUtilityFunctions::_stepdate( $wdate, $wdatets, $step);
1030
+ /* check if BYSETPOS is set for updating result array */
1031
+ if( $updateOK && isset( $recur['BYSETPOS'] )) {
1032
+ $bysetpos = FALSE;
1033
+ if( isset( $recur['FREQ'] ) && ( 'YEARLY' == $recur['FREQ'] ) &&
1034
+ ( $bysetposYold != $wdate['year'] )) {
1035
+ $bysetpos = TRUE;
1036
+ $bysetposYold = $wdate['year'];
1037
+ }
1038
+ elseif( isset( $recur['FREQ'] ) && ( 'MONTHLY' == $recur['FREQ'] &&
1039
+ (( $bysetposYold != $wdate['year'] ) || ( $bysetposMold != $wdate['month'] )))) {
1040
+ $bysetpos = TRUE;
1041
+ $bysetposYold = $wdate['year'];
1042
+ $bysetposMold = $wdate['month'];
1043
+ }
1044
+ elseif( isset( $recur['FREQ'] ) && ( 'WEEKLY' == $recur['FREQ'] )) {
1045
+ $weekno = (int) date( 'W', mktime( 0, 0, $wkst, $wdate['month'], $wdate['day'], $wdate['year']));
1046
+ if( $bysetposWold != $weekno ) {
1047
+ $bysetposWold = $weekno;
1048
+ $bysetpos = TRUE;
1049
+ }
1050
+ }
1051
+ elseif( isset( $recur['FREQ'] ) && ( 'DAILY' == $recur['FREQ'] ) &&
1052
+ (( $bysetposYold != $wdate['year'] ) ||
1053
+ ( $bysetposMold != $wdate['month'] ) ||
1054
+ ( $bysetposDold != $wdate['day'] ))) {
1055
+ $bysetpos = TRUE;
1056
+ $bysetposYold = $wdate['year'];
1057
+ $bysetposMold = $wdate['month'];
1058
+ $bysetposDold = $wdate['day'];
1059
+ }
1060
+ if( $bysetpos ) {
1061
+ if( isset( $recur['BYWEEKNO'] )) {
1062
+ $bysetposarr1 = & $bysetposw1;
1063
+ $bysetposarr2 = & $bysetposw2;
1064
+ }
1065
+ else {
1066
+ $bysetposarr1 = & $bysetposymd1;
1067
+ $bysetposarr2 = & $bysetposymd2;
1068
+ }
1069
+ // echo 'test före out startYMD (weekno)='.$wdateStart['year'].':'.$wdateStart['month'].':'.$wdateStart['day']." ($weekStart) "; // test ###
1070
+ foreach( $recur['BYSETPOS'] as $ix ) {
1071
+ if( 0 > $ix ) // both positive and negative BYSETPOS allowed
1072
+ $ix = ( count( $bysetposarr1 ) + $ix + 1);
1073
+ $ix--;
1074
+ if( isset( $bysetposarr1[$ix] )) {
1075
+ if( $startdatets <= $bysetposarr1[$ix] ) { // only output within period
1076
+ // $testdate = iCalUtilityFunctions::_timestamp2date( $bysetposarr1[$ix], 6 ); // test ###
1077
+ // $testweekno = (int) date( 'W', mktime( 0, 0, $wkst, $testdate['month'], $testdate['day'], $testdate['year'] )); // test ###
1078
+ // echo " testYMD (weekno)=".$testdate['year'].':'.$testdate['month'].':'.$testdate['day']." ($testweekno)"; // test ###
1079
+ $result[$bysetposarr1[$ix]] = TRUE;
1080
+ // echo " recur ".implode('-',iCalUtilityFunctions::_date_time_string(date('Y-m-d H:i:s',$bysetposarr1[$ix]),6)); // test ###
1081
+ }
1082
+ $countcnt++;
1083
+ }
1084
+ if( isset( $recur['COUNT'] ) && ( $countcnt >= $recur['COUNT'] ))
1085
+ break;
1086
+ }
1087
+ // echo "<br />\n"; // test ###
1088
+ $bysetposarr1 = $bysetposarr2;
1089
+ $bysetposarr2 = array();
1090
+ }
1091
+ }
1092
+ }
1093
+ }
1094
+ public static function _recurBYcntcheck( $BYvalue, $upValue, $downValue ) {
1095
+ if( is_array( $BYvalue ) &&
1096
+ ( in_array( $upValue, $BYvalue ) || in_array( $downValue, $BYvalue )))
1097
+ return TRUE;
1098
+ elseif(( $BYvalue == $upValue ) || ( $BYvalue == $downValue ))
1099
+ return TRUE;
1100
+ else
1101
+ return FALSE;
1102
+ }
1103
+ public static function _recurIntervalIx( $freq, $date, $wkst ) {
1104
+ /* create interval index */
1105
+ switch( $freq ) {
1106
+ case 'YEARLY':
1107
+ $intervalix = $date['year'];
1108
+ break;
1109
+ case 'MONTHLY':
1110
+ $intervalix = $date['year'].'-'.$date['month'];
1111
+ break;
1112
+ case 'WEEKLY':
1113
+ $wdatets = iCalUtilityFunctions::_date2timestamp( $date );
1114
+ $intervalix = (int) date( 'W', ( $wdatets + $wkst ));
1115
+ break;
1116
+ case 'DAILY':
1117
+ default:
1118
+ $intervalix = $date['year'].'-'.$date['month'].'-'.$date['day'];
1119
+ break;
1120
+ }
1121
+ return $intervalix;
1122
+ }
1123
+ /**
1124
+ * convert input format for exrule and rrule to internal format
1125
+ *
1126
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
1127
+ * @since 2.9.10 - 2011-07-07
1128
+ * @param array $rexrule
1129
+ * @return array
1130
+ */
1131
+ public static function _setRexrule( $rexrule ) {
1132
+ $input = array();
1133
+ if( empty( $rexrule ))
1134
+ return $input;
1135
+ foreach( $rexrule as $rexrulelabel => $rexrulevalue ) {
1136
+ $rexrulelabel = strtoupper( $rexrulelabel );
1137
+ if( 'UNTIL' != $rexrulelabel )
1138
+ $input[$rexrulelabel] = $rexrulevalue;
1139
+ else {
1140
+ if( iCalUtilityFunctions::_isArrayTimestampDate( $rexrulevalue )) // timestamp date
1141
+ $input[$rexrulelabel] = iCalUtilityFunctions::_timestamp2date( $rexrulevalue, 6 );
1142
+ elseif( iCalUtilityFunctions::_isArrayDate( $rexrulevalue )) // date-time
1143
+ $input[$rexrulelabel] = iCalUtilityFunctions::_date_time_array( $rexrulevalue, 6 );
1144
+ elseif( 8 <= strlen( trim( $rexrulevalue ))) // ex. 2006-08-03 10:12:18
1145
+ $input[$rexrulelabel] = iCalUtilityFunctions::_date_time_string( $rexrulevalue );
1146
+ if(( 3 < count( $input[$rexrulelabel] )) && !isset( $input[$rexrulelabel]['tz'] ))
1147
+ $input[$rexrulelabel]['tz'] = 'Z';
1148
+ }
1149
+ }
1150
+ /* set recurrence rule specification in rfc2445 order */
1151
+ $input2 = array();
1152
+ if( isset( $input['FREQ'] ))
1153
+ $input2['FREQ'] = $input['FREQ'];
1154
+ if( isset( $input['UNTIL'] ))
1155
+ $input2['UNTIL'] = $input['UNTIL'];
1156
+ elseif( isset( $input['COUNT'] ))
1157
+ $input2['COUNT'] = $input['COUNT'];
1158
+ if( isset( $input['INTERVAL'] ))
1159
+ $input2['INTERVAL'] = $input['INTERVAL'];
1160
+ if( isset( $input['BYSECOND'] ))
1161
+ $input2['BYSECOND'] = $input['BYSECOND'];
1162
+ if( isset( $input['BYMINUTE'] ))
1163
+ $input2['BYMINUTE'] = $input['BYMINUTE'];
1164
+ if( isset( $input['BYHOUR'] ))
1165
+ $input2['BYHOUR'] = $input['BYHOUR'];
1166
+ if( isset( $input['BYDAY'] )) {
1167
+ if( !is_array( $input['BYDAY'] )) // ensure upper case.. .
1168
+ $input2['BYDAY'] = strtoupper( $input['BYDAY'] );
1169
+ else {
1170
+ foreach( $input['BYDAY'] as $BYDAYx => $BYDAYv ) {
1171
+ if( 'DAY' == strtoupper( $BYDAYx ))
1172
+ $input2['BYDAY']['DAY'] = strtoupper( $BYDAYv );
1173
+ elseif( !is_array( $BYDAYv )) {
1174
+ $input2['BYDAY'][$BYDAYx] = $BYDAYv;
1175
+ }
1176
+ else {
1177
+ foreach( $BYDAYv as $BYDAYx2 => $BYDAYv2 ) {
1178
+ if( 'DAY' == strtoupper( $BYDAYx2 ))
1179
+ $input2['BYDAY'][$BYDAYx]['DAY'] = strtoupper( $BYDAYv2 );
1180
+ else
1181
+ $input2['BYDAY'][$BYDAYx][$BYDAYx2] = $BYDAYv2;
1182
+ }
1183
+ }
1184
+ }
1185
+ }
1186
+ }
1187
+ if( isset( $input['BYMONTHDAY'] ))
1188
+ $input2['BYMONTHDAY'] = $input['BYMONTHDAY'];
1189
+ if( isset( $input['BYYEARDAY'] ))
1190
+ $input2['BYYEARDAY'] = $input['BYYEARDAY'];
1191
+ if( isset( $input['BYWEEKNO'] ))
1192
+ $input2['BYWEEKNO'] = $input['BYWEEKNO'];
1193
+ if( isset( $input['BYMONTH'] ))
1194
+ $input2['BYMONTH'] = $input['BYMONTH'];
1195
+ if( isset( $input['BYSETPOS'] ))
1196
+ $input2['BYSETPOS'] = $input['BYSETPOS'];
1197
+ if( isset( $input['WKST'] ))
1198
+ $input2['WKST'] = $input['WKST'];
1199
+ return $input2;
1200
+ }
1201
+ /**
1202
+ * convert format for input date to internal date with parameters
1203
+ *
1204
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
1205
+ * @since 2.9.6 - 2011-05-14
1206
+ * @param mixed $year
1207
+ * @param mixed $month optional
1208
+ * @param int $day optional
1209
+ * @param int $hour optional
1210
+ * @param int $min optional
1211
+ * @param int $sec optional
1212
+ * @param string $tz optional
1213
+ * @param array $params optional
1214
+ * @param string $caller optional
1215
+ * @param string $objName optional
1216
+ * @param string $tzid optional
1217
+ * @return array
1218
+ */
1219
+ public static function _setDate( $year, $month=FALSE, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $tz=FALSE, $params=FALSE, $caller=null, $objName=null, $tzid=FALSE ) {
1220
+ $input = $parno = null;
1221
+ $localtime = (( 'dtstart' == $caller ) && in_array( $objName, array( 'vtimezone', 'standard', 'daylight' ))) ? TRUE : FALSE;
1222
+ if( iCalUtilityFunctions::_isArrayDate( $year )) {
1223
+ if( $localtime ) unset ( $month['VALUE'], $month['TZID'] );
1224
+ $input['params'] = iCalUtilityFunctions::_setParams( $month, array( 'VALUE' => 'DATE-TIME' ));
1225
+ if( isset( $input['params']['TZID'] )) {
1226
+ $input['params']['VALUE'] = 'DATE-TIME';
1227
+ unset( $year['tz'] );
1228
+ }
1229
+ $hitval = (( !empty( $year['tz'] ) || !empty( $year[6] ))) ? 7 : 6;
1230
+ $parno = iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE-TIME', $hitval );
1231
+ $parno = iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE', 3, count( $year ), $parno );
1232
+ $input['value'] = iCalUtilityFunctions::_date_time_array( $year, $parno );
1233
+ }
1234
+ elseif( iCalUtilityFunctions::_isArrayTimestampDate( $year )) {
1235
+ if( $localtime ) unset ( $month['VALUE'], $month['TZID'] );
1236
+ $input['params'] = iCalUtilityFunctions::_setParams( $month, array( 'VALUE' => 'DATE-TIME' ));
1237
+ if( isset( $input['params']['TZID'] )) {
1238
+ $input['params']['VALUE'] = 'DATE-TIME';
1239
+ unset( $year['tz'] );
1240
+ }
1241
+ $parno = iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE', 3 );
1242
+ $hitval = ( isset( $year['tz'] )) ? 7 : 6;
1243
+ $parno = iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE-TIME', $hitval, $parno );
1244
+ $input['value'] = iCalUtilityFunctions::_timestamp2date( $year, $parno );
1245
+ }
1246
+ elseif( 8 <= strlen( trim( $year ))) { // ex. 2006-08-03 10:12:18
1247
+ if( $localtime ) unset ( $month['VALUE'], $month['TZID'] );
1248
+ $input['params'] = iCalUtilityFunctions::_setParams( $month, array( 'VALUE' => 'DATE-TIME' ));
1249
+ if( isset( $input['params']['TZID'] )) {
1250
+ $input['params']['VALUE'] = 'DATE-TIME';
1251
+ $parno = 6;
1252
+ }
1253
+ $parno = iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE-TIME', 7, $parno );
1254
+ $parno = iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE', 3, $parno, $parno );
1255
+ $input['value'] = iCalUtilityFunctions::_date_time_string( $year, $parno );
1256
+ }
1257
+ else {
1258
+ if( is_array( $params )) {
1259
+ if( $localtime ) unset ( $params['VALUE'], $params['TZID'] );
1260
+ $input['params'] = iCalUtilityFunctions::_setParams( $params, array( 'VALUE' => 'DATE-TIME' ));
1261
+ }
1262
+ elseif( is_array( $tz )) {
1263
+ $input['params'] = iCalUtilityFunctions::_setParams( $tz, array( 'VALUE' => 'DATE-TIME' ));
1264
+ $tz = FALSE;
1265
+ }
1266
+ elseif( is_array( $hour )) {
1267
+ $input['params'] = iCalUtilityFunctions::_setParams( $hour, array( 'VALUE' => 'DATE-TIME' ));
1268
+ $hour = $min = $sec = $tz = FALSE;
1269
+ }
1270
+ if( isset( $input['params']['TZID'] )) {
1271
+ $tz = null;
1272
+ $input['params']['VALUE'] = 'DATE-TIME';
1273
+ }
1274
+ $parno = iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE', 3 );
1275
+ $hitval = ( !empty( $tz )) ? 7 : 6;
1276
+ $parno = iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE-TIME', $hitval, $parno, $parno );
1277
+ $input['value'] = array( 'year' => $year, 'month' => $month, 'day' => $day );
1278
+ if( 3 != $parno ) {
1279
+ $input['value']['hour'] = ( $hour ) ? $hour : '0';
1280
+ $input['value']['min'] = ( $min ) ? $min : '0';
1281
+ $input['value']['sec'] = ( $sec ) ? $sec : '0';
1282
+ if( !empty( $tz ))
1283
+ $input['value']['tz'] = $tz;
1284
+ }
1285
+ }
1286
+ if( 3 == $parno ) {
1287
+ $input['params']['VALUE'] = 'DATE';
1288
+ unset( $input['value']['tz'] );
1289
+ unset( $input['params']['TZID'] );
1290
+ }
1291
+ elseif( isset( $input['params']['TZID'] ))
1292
+ unset( $input['value']['tz'] );
1293
+ if( $localtime )
1294
+ unset( $input['value']['tz'], $input['params']['TZID'] );
1295
+ elseif(( !isset( $input['params']['VALUE'] ) || ( $input['params']['VALUE'] != 'DATE' )) && !isset( $input['params']['TZID'] ) && $tzid )
1296
+ $input['params']['TZID'] = $tzid;
1297
+ if( isset( $input['value']['tz'] ))
1298
+ $input['value']['tz'] = (string) $input['value']['tz'];
1299
+ if( !empty( $input['value']['tz'] ) && ( 'Z' != $input['value']['tz'] ) &&
1300
+ ( !iCalUtilityFunctions::_isOffset( $input['value']['tz'] )))
1301
+ $input['params']['TZID'] = $input['value']['tz'];
1302
+ return $input;
1303
+ }
1304
+ /**
1305
+ * convert format for input date (UTC) to internal date with parameters
1306
+ *
1307
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
1308
+ * @since 2.4.17 - 2008-10-31
1309
+ * @param mixed $year
1310
+ * @param mixed $month optional
1311
+ * @param int $day optional
1312
+ * @param int $hour optional
1313
+ * @param int $min optional
1314
+ * @param int $sec optional
1315
+ * @param array $params optional
1316
+ * @return array
1317
+ */
1318
+ public static function _setDate2( $year, $month=FALSE, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $params=FALSE ) {
1319
+ $input = null;
1320
+ if( iCalUtilityFunctions::_isArrayDate( $year )) {
1321
+ $input['value'] = iCalUtilityFunctions::_date_time_array( $year, 7 );
1322
+ $input['params'] = iCalUtilityFunctions::_setParams( $month, array( 'VALUE' => 'DATE-TIME' ) );
1323
+ }
1324
+ elseif( iCalUtilityFunctions::_isArrayTimestampDate( $year )) {
1325
+ $input['value'] = iCalUtilityFunctions::_timestamp2date( $year, 7 );
1326
+ $input['params'] = iCalUtilityFunctions::_setParams( $month, array( 'VALUE' => 'DATE-TIME' ) );
1327
+ }
1328
+ elseif( 8 <= strlen( trim( $year ))) { // ex. 2006-08-03 10:12:18
1329
+ $input['value'] = iCalUtilityFunctions::_date_time_string( $year, 7 );
1330
+ $input['params'] = iCalUtilityFunctions::_setParams( $month, array( 'VALUE' => 'DATE-TIME' ) );
1331
+ }
1332
+ else {
1333
+ $input['value'] = array( 'year' => $year
1334
+ , 'month' => $month
1335
+ , 'day' => $day
1336
+ , 'hour' => $hour
1337
+ , 'min' => $min
1338
+ , 'sec' => $sec );
1339
+ $input['params'] = iCalUtilityFunctions::_setParams( $params, array( 'VALUE' => 'DATE-TIME' ));
1340
+ }
1341
+ $parno = iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE-TIME', 7 ); // remove default
1342
+ if( !isset( $input['value']['hour'] ))
1343
+ $input['value']['hour'] = 0;
1344
+ if( !isset( $input['value']['min'] ))
1345
+ $input['value']['min'] = 0;
1346
+ if( !isset( $input['value']['sec'] ))
1347
+ $input['value']['sec'] = 0;
1348
+ if( !isset( $input['value']['tz'] ) || !iCalUtilityFunctions::_isOffset( $input['value']['tz'] ))
1349
+ $input['value']['tz'] = 'Z';
1350
+ return $input;
1351
+ }
1352
+ /**
1353
+ * check index and set (an indexed) content in multiple value array
1354
+ *
1355
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
1356
+ * @since 2.6.12 - 2011-01-03
1357
+ * @param array $valArr
1358
+ * @param mixed $value
1359
+ * @param array $params
1360
+ * @param array $defaults
1361
+ * @param int $index
1362
+ * @return void
1363
+ */
1364
+ public static function _setMval( & $valArr, $value, $params=FALSE, $defaults=FALSE, $index=FALSE ) {
1365
+ if( !is_array( $valArr )) $valArr = array();
1366
+ if( $index )
1367
+ $index = $index - 1;
1368
+ elseif( 0 < count( $valArr )) {
1369
+ $keys = array_keys( $valArr );
1370
+ $index = end( $keys ) + 1;
1371
+ }
1372
+ else
1373
+ $index = 0;
1374
+ $valArr[$index] = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params, $defaults ));
1375
+ ksort( $valArr );
1376
+ }
1377
+ /**
1378
+ * set input (formatted) parameters- component property attributes
1379
+ *
1380
+ * default parameters can be set, if missing
1381
+ *
1382
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
1383
+ * @since 1.x.x - 2007-05-01
1384
+ * @param array $params
1385
+ * @param array $defaults
1386
+ * @return array
1387
+ */
1388
+ public static function _setParams( $params, $defaults=FALSE ) {
1389
+ if( !is_array( $params))
1390
+ $params = array();
1391
+ $input = array();
1392
+ foreach( $params as $paramKey => $paramValue ) {
1393
+ if( is_array( $paramValue )) {
1394
+ foreach( $paramValue as $pkey => $pValue ) {
1395
+ if(( '"' == substr( $pValue, 0, 1 )) && ( '"' == substr( $pValue, -1 )))
1396
+ $paramValue[$pkey] = substr( $pValue, 1, ( strlen( $pValue ) - 2 ));
1397
+ }
1398
+ }
1399
+ elseif(( '"' == substr( $paramValue, 0, 1 )) && ( '"' == substr( $paramValue, -1 )))
1400
+ $paramValue = substr( $paramValue, 1, ( strlen( $paramValue ) - 2 ));
1401
+ if( 'VALUE' == strtoupper( $paramKey ))
1402
+ $input['VALUE'] = strtoupper( $paramValue );
1403
+ else
1404
+ $input[strtoupper( $paramKey )] = $paramValue;
1405
+ }
1406
+ if( is_array( $defaults )) {
1407
+ foreach( $defaults as $paramKey => $paramValue ) {
1408
+ if( !isset( $input[$paramKey] ))
1409
+ $input[$paramKey] = $paramValue;
1410
+ }
1411
+ }
1412
+ return (0 < count( $input )) ? $input : null;
1413
+ }
1414
+ /**
1415
+ * step date, return updated date, array and timpstamp
1416
+ *
1417
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
1418
+ * @since 2.4.16 - 2008-10-18
1419
+ * @param array $date, date to step
1420
+ * @param int $timestamp
1421
+ * @param array $step, default array( 'day' => 1 )
1422
+ * @return void
1423
+ */
1424
+ public static function _stepdate( &$date, &$timestamp, $step=array( 'day' => 1 )) {
1425
+ foreach( $step as $stepix => $stepvalue )
1426
+ $date[$stepix] += $stepvalue;
1427
+ $timestamp = iCalUtilityFunctions::_date2timestamp( $date );
1428
+ $date = iCalUtilityFunctions::_timestamp2date( $timestamp, 6 );
1429
+ foreach( $date as $k => $v ) {
1430
+ if( ctype_digit( $v ))
1431
+ $date[$k] = (int) $v;
1432
+ }
1433
+ }
1434
+ /**
1435
+ * convert timestamp to date array
1436
+ *
1437
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
1438
+ * @since 2.4.16 - 2008-11-01
1439
+ * @param mixed $timestamp
1440
+ * @param int $parno
1441
+ * @return array
1442
+ */
1443
+ public static function _timestamp2date( $timestamp, $parno=6 ) {
1444
+ if( is_array( $timestamp )) {
1445
+ if(( 7 == $parno ) && !empty( $timestamp['tz'] ))
1446
+ $tz = $timestamp['tz'];
1447
+ $timestamp = $timestamp['timestamp'];
1448
+ }
1449
+ $output = array( 'year' => date( 'Y', $timestamp )
1450
+ , 'month' => date( 'm', $timestamp )
1451
+ , 'day' => date( 'd', $timestamp ));
1452
+ if( 3 != $parno ) {
1453
+ $output['hour'] = date( 'H', $timestamp );
1454
+ $output['min'] = date( 'i', $timestamp );
1455
+ $output['sec'] = date( 's', $timestamp );
1456
+ if( isset( $tz ))
1457
+ $output['tz'] = $tz;
1458
+ }
1459
+ return $output;
1460
+ }
1461
+ /**
1462
+ * convert timestamp to duration in array format
1463
+ *
1464
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
1465
+ * @since 2.6.23 - 2010-10-23
1466
+ * @param int $timestamp
1467
+ * @return array, duration format
1468
+ */
1469
+ function _timestamp2duration( $timestamp ) {
1470
+ $dur = array();
1471
+ $dur['week'] = (int) floor( $timestamp / ( 7 * 24 * 60 * 60 ));
1472
+ $timestamp = $timestamp % ( 7 * 24 * 60 * 60 );
1473
+ $dur['day'] = (int) floor( $timestamp / ( 24 * 60 * 60 ));
1474
+ $timestamp = $timestamp % ( 24 * 60 * 60 );
1475
+ $dur['hour'] = (int) floor( $timestamp / ( 60 * 60 ));
1476
+ $timestamp = $timestamp % ( 60 * 60 );
1477
+ $dur['min'] = (int) floor( $timestamp / ( 60 ));
1478
+ $dur['sec'] = (int) $timestamp % ( 60 );
1479
+ return $dur;
1480
+ }
1481
+ /**
1482
+ * convert (numeric) local time offset to seconds correcting localtime to GMT
1483
+ *
1484
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
1485
+ * @since 2.4.16 - 2008-10-19
1486
+ * @param string $offset
1487
+ * @return integer
1488
+ */
1489
+ public static function _tz2offset( $tz ) {
1490
+ $tz = trim( (string) $tz );
1491
+ $offset = 0;
1492
+ if((( 5 != strlen( $tz )) && ( 7 != strlen( $tz ))) ||
1493
+ (( '+' != substr( $tz, 0, 1 )) && ( '-' != substr( $tz, 0, 1 ))) ||
1494
+ (( '0000' >= substr( $tz, 1, 4 )) && ( '9999' < substr( $tz, 1, 4 ))) ||
1495
+ (( 7 == strlen( $tz )) && ( '00' > substr( $tz, 5, 2 )) && ( '99' < substr( $tz, 5, 2 ))))
1496
+ return $offset;
1497
+ $hours2sec = (int) substr( $tz, 1, 2 ) * 3600;
1498
+ $min2sec = (int) substr( $tz, 3, 2 ) * 60;
1499
+ $sec = ( 7 == strlen( $tz )) ? (int) substr( $tz, -2 ) : '00';
1500
+ $offset = $hours2sec + $min2sec + $sec;
1501
+ $offset = ('-' == substr( $tz, 0, 1 )) ? $offset : -1 * $offset;
1502
+ return $offset;
1503
+ }
1504
+ }
1505
+ ?>
lib/iCalcreator-2.10/iCalcreator.class.php ADDED
@@ -0,0 +1,6897 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*********************************************************************************/
3
+ /**
4
+ * iCalcreator class v2.10
5
+ * copyright (c) 2007-2011 Kjell-Inge Gustafsson kigkonsult
6
+ * www.kigkonsult.se/iCalcreator/index.php
7
+ * ical@kigkonsult.se
8
+ *
9
+ * Description:
10
+ * This file is a PHP implementation of RFC 2445.
11
+ *
12
+ * This library is free software; you can redistribute it and/or
13
+ * modify it under the terms of the GNU Lesser General Public
14
+ * License as published by the Free Software Foundation; either
15
+ * version 2.1 of the License, or (at your option) any later version.
16
+ *
17
+ * This library is distributed in the hope that it will be useful,
18
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
19
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20
+ * Lesser General Public License for more details.
21
+ *
22
+ * You should have received a copy of the GNU Lesser General Public
23
+ * License along with this library; if not, write to the Free Software
24
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25
+ */
26
+ /*********************************************************************************/
27
+ /*********************************************************************************/
28
+ /* A little setup */
29
+ /*********************************************************************************/
30
+ /* your local language code */
31
+ // define( 'ICAL_LANG', 'sv' );
32
+ // alt. autosetting
33
+ /*
34
+ $langstr = $_SERVER['HTTP_ACCEPT_LANGUAGE'];
35
+ $pos = strpos( $langstr, ';' );
36
+ if ($pos !== false) {
37
+ $langstr = substr( $langstr, 0, $pos );
38
+ $pos = strpos( $langstr, ',' );
39
+ if ($pos !== false) {
40
+ $pos = strpos( $langstr, ',' );
41
+ $langstr = substr( $langstr, 0, $pos );
42
+ }
43
+ define( 'ICAL_LANG', $langstr );
44
+ }
45
+ */
46
+ /*********************************************************************************/
47
+ /* only for phpversion 5.1 and later, */
48
+ /* date management, default timezone setting */
49
+ /* since 2.6.36 - 2010-12-31 */
50
+ if( substr( phpversion(), 0, 3) >= '5.1' )
51
+ // && ( 'UTC' == date_default_timezone_get()))
52
+ date_default_timezone_set( 'Europe/Stockholm' );
53
+ /*********************************************************************************/
54
+ /* since 2.6.22 - 2010-09-25, do NOT remove!! */
55
+ require_once ( 'iCalUtilityFunctions.class.php' );
56
+ /*********************************************************************************/
57
+ /* version, do NOT remove!! */
58
+ define( 'ICALCREATOR_VERSION', 'iCalcreator 2.10' );
59
+ /*********************************************************************************/
60
+ /*********************************************************************************/
61
+ /**
62
+ * vcalendar class
63
+ *
64
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
65
+ * @since 2.9.6 - 2011-05-14
66
+ */
67
+ class vcalendar {
68
+ // calendar property variables
69
+ var $calscale;
70
+ var $method;
71
+ var $prodid;
72
+ var $version;
73
+ var $xprop;
74
+ // container for calendar components
75
+ var $components;
76
+ // component config variables
77
+ var $allowEmpty;
78
+ var $unique_id;
79
+ var $language;
80
+ var $directory;
81
+ var $filename;
82
+ var $url;
83
+ var $delimiter;
84
+ var $nl;
85
+ var $format;
86
+ var $dtzid;
87
+ // component internal variables
88
+ var $attributeDelimiter;
89
+ var $valueInit;
90
+ // component xCal declaration container
91
+ var $xcaldecl;
92
+ /**
93
+ * constructor for calendar object
94
+ *
95
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
96
+ * @since 2.9.6 - 2011-05-14
97
+ * @param array $config
98
+ * @return void
99
+ */
100
+ function vcalendar ( $config = array()) {
101
+ $this->_makeVersion();
102
+ $this->calscale = null;
103
+ $this->method = null;
104
+ $this->_makeUnique_id();
105
+ $this->prodid = null;
106
+ $this->xprop = array();
107
+ $this->language = null;
108
+ $this->directory = null;
109
+ $this->filename = null;
110
+ $this->url = null;
111
+ $this->dtzid = null;
112
+ /**
113
+ * language = <Text identifying a language, as defined in [RFC 1766]>
114
+ */
115
+ if( defined( 'ICAL_LANG' ) && !isset( $config['language'] ))
116
+ $config['language'] = ICAL_LANG;
117
+ if( !isset( $config['allowEmpty'] )) $config['allowEmpty'] = TRUE;
118
+ if( !isset( $config['nl'] )) $config['nl'] = "\r\n";
119
+ if( !isset( $config['format'] )) $config['format'] = 'iCal';
120
+ if( !isset( $config['delimiter'] )) $config['delimiter'] = DIRECTORY_SEPARATOR;
121
+ $this->setConfig( $config );
122
+
123
+ $this->xcaldecl = array();
124
+ $this->components = array();
125
+ }
126
+ /*********************************************************************************/
127
+ /**
128
+ * Property Name: CALSCALE
129
+ */
130
+ /**
131
+ * creates formatted output for calendar property calscale
132
+ *
133
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
134
+ * @since 2.4.8 - 2008-10-21
135
+ * @return string
136
+ */
137
+ function createCalscale() {
138
+ if( empty( $this->calscale )) return FALSE;
139
+ switch( $this->format ) {
140
+ case 'xcal':
141
+ return ' calscale="'.$this->calscale.'"'.$this->nl;
142
+ break;
143
+ default:
144
+ return 'CALSCALE:'.$this->calscale.$this->nl;
145
+ break;
146
+ }
147
+ }
148
+ /**
149
+ * set calendar property calscale
150
+ *
151
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
152
+ * @since 2.4.8 - 2008-10-21
153
+ * @param string $value
154
+ * @return void
155
+ */
156
+ function setCalscale( $value ) {
157
+ if( empty( $value )) return FALSE;
158
+ $this->calscale = $value;
159
+ }
160
+ /*********************************************************************************/
161
+ /**
162
+ * Property Name: METHOD
163
+ */
164
+ /**
165
+ * creates formatted output for calendar property method
166
+ *
167
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
168
+ * @since 0.9.7 - 2006-11-20
169
+ * @return string
170
+ */
171
+ function createMethod() {
172
+ if( empty( $this->method )) return FALSE;
173
+ switch( $this->format ) {
174
+ case 'xcal':
175
+ return ' method="'.$this->method.'"'.$this->nl;
176
+ break;
177
+ default:
178
+ return 'METHOD:'.$this->method.$this->nl;
179
+ break;
180
+ }
181
+ }
182
+ /**
183
+ * set calendar property method
184
+ *
185
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
186
+ * @since 2.4.8 - 2008-20-23
187
+ * @param string $value
188
+ * @return bool
189
+ */
190
+ function setMethod( $value ) {
191
+ if( empty( $value )) return FALSE;
192
+ $this->method = $value;
193
+ return TRUE;
194
+ }
195
+ /*********************************************************************************/
196
+ /**
197
+ * Property Name: PRODID
198
+ *
199
+ * The identifier is RECOMMENDED to be the identical syntax to the
200
+ * [RFC 822] addr-spec. A good method to assure uniqueness is to put the
201
+ * domain name or a domain literal IP address of the host on which.. .
202
+ */
203
+ /**
204
+ * creates formatted output for calendar property prodid
205
+ *
206
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
207
+ * @since 0.9.7 - 2006-11-20
208
+ * @return string
209
+ */
210
+ function createProdid() {
211
+ if( !isset( $this->prodid ))
212
+ $this->_makeProdid();
213
+ switch( $this->format ) {
214
+ case 'xcal':
215
+ return ' prodid="'.$this->prodid.'"'.$this->nl;
216
+ break;
217
+ default:
218
+ return 'PRODID:'.$this->prodid.$this->nl;
219
+ break;
220
+ }
221
+ }
222
+ /**
223
+ * make default value for calendar prodid
224
+ *
225
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
226
+ * @since 2.6.8 - 2009-12-30
227
+ * @return void
228
+ */
229
+ function _makeProdid() {
230
+ $this->prodid = '-//'.$this->unique_id.'//NONSGML kigkonsult.se '.ICALCREATOR_VERSION.'//'.strtoupper( $this->language );
231
+ }
232
+ /**
233
+ * Conformance: The property MUST be specified once in an iCalendar object.
234
+ * Description: The vendor of the implementation SHOULD assure that this
235
+ * is a globally unique identifier; using some technique such as an FPI
236
+ * value, as defined in [ISO 9070].
237
+ */
238
+ /**
239
+ * make default unique_id for calendar prodid
240
+ *
241
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
242
+ * @since 0.3.0 - 2006-08-10
243
+ * @return void
244
+ */
245
+ function _makeUnique_id() {
246
+ $this->unique_id = ( isset( $_SERVER['SERVER_NAME'] )) ? gethostbyname( $_SERVER['SERVER_NAME'] ) : 'localhost';
247
+ }
248
+ /*********************************************************************************/
249
+ /**
250
+ * Property Name: VERSION
251
+ *
252
+ * Description: A value of "2.0" corresponds to this memo.
253
+ */
254
+ /**
255
+ * creates formatted output for calendar property version
256
+
257
+ *
258
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
259
+ * @since 0.9.7 - 2006-11-20
260
+ * @return string
261
+ */
262
+ function createVersion() {
263
+ if( empty( $this->version ))
264
+ $this->_makeVersion();
265
+ switch( $this->format ) {
266
+ case 'xcal':
267
+ return ' version="'.$this->version.'"'.$this->nl;
268
+ break;
269
+ default:
270
+ return 'VERSION:'.$this->version.$this->nl;
271
+ break;
272
+ }
273
+ }
274
+ /**
275
+ * set default calendar version
276
+ *
277
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
278
+ * @since 0.3.0 - 2006-08-10
279
+ * @return void
280
+ */
281
+ function _makeVersion() {
282
+ $this->version = '2.0';
283
+ }
284
+ /**
285
+ * set calendar version
286
+ *
287
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
288
+ * @since 2.4.8 - 2008-10-23
289
+ * @param string $value
290
+ * @return void
291
+ */
292
+ function setVersion( $value ) {
293
+ if( empty( $value )) return FALSE;
294
+ $this->version = $value;
295
+ return TRUE;
296
+ }
297
+ /*********************************************************************************/
298
+ /**
299
+ * Property Name: x-prop
300
+ */
301
+ /**
302
+ * creates formatted output for calendar property x-prop, iCal format only
303
+ *
304
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
305
+ * @since 2.9.3 - 2011-05-14
306
+ * @return string
307
+ */
308
+ function createXprop() {
309
+ if( 'xcal' == $this->format )
310
+ return false;
311
+ if( empty( $this->xprop ) || !is_array( $this->xprop )) return FALSE;
312
+ $output = null;
313
+ $toolbox = new calendarComponent();
314
+ $toolbox->setConfig( $this->getConfig());
315
+ foreach( $this->xprop as $label => $xpropPart ) {
316
+ if( !isset($xpropPart['value']) || ( empty( $xpropPart['value'] ) && !is_numeric( $xpropPart['value'] ))) {
317
+ $output .= $toolbox->_createElement( $label );
318
+ continue;
319
+ }
320
+ $attributes = $toolbox->_createParams( $xpropPart['params'], array( 'LANGUAGE' ));
321
+ if( is_array( $xpropPart['value'] )) {
322
+ foreach( $xpropPart['value'] as $pix => $theXpart )
323
+ $xpropPart['value'][$pix] = $toolbox->_strrep( $theXpart );
324
+ $xpropPart['value'] = implode( ',', $xpropPart['value'] );
325
+ }
326
+ else
327
+ $xpropPart['value'] = $toolbox->_strrep( $xpropPart['value'] );
328
+ $output .= $toolbox->_createElement( $label, $attributes, $xpropPart['value'] );
329
+ }
330
+ return $output;
331
+ }
332
+ /**
333
+ * set calendar property x-prop
334
+ *
335
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
336
+ * @since 2.9.3 - 2011-05-14
337
+ * @param string $label
338
+ * @param string $value
339
+ * @param array $params optional
340
+ * @return bool
341
+ */
342
+ function setXprop( $label, $value, $params=FALSE ) {
343
+ if( empty( $label )) return FALSE;
344
+ if( empty( $value ) && !is_numeric( $value )) if( $this->getConfig( 'allowEmpty' )) $value = null; else return FALSE;
345
+ $xprop = array( 'value' => $value );
346
+ $xprop['params'] = iCalUtilityFunctions::_setParams( $params );
347
+ if( !is_array( $this->xprop )) $this->xprop = array();
348
+ $this->xprop[strtoupper( $label )] = $xprop;
349
+ return TRUE;
350
+ }
351
+ /*********************************************************************************/
352
+ /**
353
+ * delete calendar property value
354
+ *
355
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
356
+ * @since 2.8.8 - 2011-03-15
357
+ * @param mixed $propName, bool FALSE => X-property
358
+ * @param int $propix, optional, if specific property is wanted in case of multiply occurences
359
+ * @return bool, if successfull delete
360
+ */
361
+ function deleteProperty( $propName=FALSE, $propix=FALSE ) {
362
+ $propName = ( $propName ) ? strtoupper( $propName ) : 'X-PROP';
363
+ if( !$propix )
364
+ $propix = ( isset( $this->propdelix[$propName] ) && ( 'X-PROP' != $propName )) ? $this->propdelix[$propName] + 2 : 1;
365
+ $this->propdelix[$propName] = --$propix;
366
+ $return = FALSE;
367
+ switch( $propName ) {
368
+ case 'CALSCALE':
369
+ if( isset( $this->calscale )) {
370
+ $this->calscale = null;
371
+ $return = TRUE;
372
+ }
373
+ break;
374
+ case 'METHOD':
375
+ if( isset( $this->method )) {
376
+ $this->method = null;
377
+ $return = TRUE;
378
+ }
379
+ break;
380
+ default:
381
+ $reduced = array();
382
+ if( $propName != 'X-PROP' ) {
383
+ if( !isset( $this->xprop[$propName] )) { unset( $this->propdelix[$propName] ); return FALSE; }
384
+ foreach( $this->xprop as $k => $a ) {
385
+ if(( $k != $propName ) && !empty( $a ))
386
+ $reduced[$k] = $a;
387
+ }
388
+ }
389
+ else {
390
+ if( count( $this->xprop ) <= $propix ) return FALSE;
391
+ $xpropno = 0;
392
+ foreach( $this->xprop as $xpropkey => $xpropvalue ) {
393
+ if( $propix != $xpropno )
394
+ $reduced[$xpropkey] = $xpropvalue;
395
+ $xpropno++;
396
+ }
397
+ }
398
+ $this->xprop = $reduced;
399
+ if( empty( $this->xprop )) {
400
+ unset( $this->propdelix[$propName] );
401
+ return FALSE;
402
+ }
403
+ return TRUE;
404
+ }
405
+ return $return;
406
+ }
407
+ /**
408
+ * get calendar property value/params
409
+ *
410
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
411
+ * @since 2.8.8 - 2011-04-16
412
+ * @param string $propName, optional
413
+ * @param int $propix, optional, if specific property is wanted in case of multiply occurences
414
+ * @param bool $inclParam=FALSE
415
+ * @return mixed
416
+ */
417
+ function getProperty( $propName=FALSE, $propix=FALSE, $inclParam=FALSE ) {
418
+ $propName = ( $propName ) ? strtoupper( $propName ) : 'X-PROP';
419
+ if( 'X-PROP' == $propName ) {
420
+ if( !$propix )
421
+ $propix = ( isset( $this->propix[$propName] )) ? $this->propix[$propName] + 2 : 1;
422
+ $this->propix[$propName] = --$propix;
423
+ }
424
+ switch( $propName ) {
425
+ case 'ATTENDEE':
426
+ case 'CATEGORIES':
427
+ case 'DTSTART':
428
+ case 'LOCATION':
429
+ case 'ORGANIZER':
430
+ case 'PRIORITY':
431
+ case 'RESOURCES':
432
+ case 'STATUS':
433
+ case 'SUMMARY':
434
+ case 'RECURRENCE-ID-UID':
435
+ case 'R-UID':
436
+ case 'UID':
437
+ $output = array();
438
+ foreach ( $this->components as $cix => $component) {
439
+ if( !in_array( $component->objName, array('vevent', 'vtodo', 'vjournal', 'vfreebusy' )))
440
+ continue;
441
+ if(( 'ATTENDEE' == $propName ) || ( 'CATEGORIES' == $propName ) || ( 'RESOURCES' == $propName )) {
442
+ $component->_getProperties( $propName, $output );
443
+ continue;
444
+ }
445
+ elseif(( 3 < strlen( $propName )) && ( 'UID' == substr( $propName, -3 ))) {
446
+ if( FALSE !== ( $content = $component->getProperty( 'RECURRENCE-ID' )))
447
+ $content = $component->getProperty( 'UID' );
448
+ }
449
+ elseif( FALSE === ( $content = $component->getProperty( $propName )))
450
+ continue;
451
+ if( FALSE === $content )
452
+ continue;
453
+ elseif( is_array( $content )) {
454
+ if( isset( $content['year'] )) {
455
+ $key = sprintf( '%04d%02d%02d', $content['year'], $content['month'], $content['day'] );
456
+ if( !isset( $output[$key] ))
457
+ $output[$key] = 1;
458
+ else
459
+ $output[$key] += 1;
460
+ }
461
+ else {
462
+ foreach( $content as $partValue => $partCount ) {
463
+ if( !isset( $output[$partValue] ))
464
+ $output[$partValue] = $partCount;
465
+ else
466
+ $output[$partValue] += $partCount;
467
+ }
468
+ }
469
+ } // end elseif( is_array( $content )) {
470
+ elseif( !isset( $output[$content] ))
471
+ $output[$content] = 1;
472
+ else
473
+ $output[$content] += 1;
474
+ } // end foreach ( $this->components as $cix => $component)
475
+ if( !empty( $output ))
476
+ ksort( $output );
477
+ return $output;
478
+ break;
479
+
480
+ case 'CALSCALE':
481
+ return ( !empty( $this->calscale )) ? $this->calscale : FALSE;
482
+ break;
483
+ case 'METHOD':
484
+ return ( !empty( $this->method )) ? $this->method : FALSE;
485
+ break;
486
+ case 'PRODID':
487
+ if( empty( $this->prodid ))
488
+ $this->_makeProdid();
489
+ return $this->prodid;
490
+ break;
491
+ case 'VERSION':
492
+ return ( !empty( $this->version )) ? $this->version : FALSE;
493
+ break;
494
+ default:
495
+ if( $propName != 'X-PROP' ) {
496
+ if( !isset( $this->xprop[$propName] )) return FALSE;
497
+ return ( $inclParam ) ? array( $propName, $this->xprop[$propName] )
498
+ : array( $propName, $this->xprop[$propName]['value'] );
499
+ }
500
+ else {
501
+ if( empty( $this->xprop )) return FALSE;
502
+ $xpropno = 0;
503
+ foreach( $this->xprop as $xpropkey => $xpropvalue ) {
504
+ if( $propix == $xpropno )
505
+ return ( $inclParam ) ? array( $xpropkey, $this->xprop[$xpropkey] )
506
+ : array( $xpropkey, $this->xprop[$xpropkey]['value'] );
507
+ else
508
+ $xpropno++;
509
+ }
510
+ unset( $this->propix[$propName] );
511
+ return FALSE; // not found ??
512
+ }
513
+ }
514
+ return FALSE;
515
+ }
516
+ /**
517
+ * general vcalendar property setting
518
+ *
519
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
520
+ * @since 2.2.13 - 2007-11-04
521
+ * @param mixed $args variable number of function arguments,
522
+ * first argument is ALWAYS component name,
523
+ * second ALWAYS component value!
524
+ * @return bool
525
+ */
526
+ function setProperty () {
527
+ $numargs = func_num_args();
528
+ if( 1 > $numargs )
529
+ return FALSE;
530
+ $arglist = func_get_args();
531
+ $arglist[0] = strtoupper( $arglist[0] );
532
+ switch( $arglist[0] ) {
533
+ case 'CALSCALE':
534
+ return $this->setCalscale( $arglist[1] );
535
+ case 'METHOD':
536
+ return $this->setMethod( $arglist[1] );
537
+ case 'VERSION':
538
+ return $this->setVersion( $arglist[1] );
539
+ default:
540
+ if( !isset( $arglist[1] )) $arglist[1] = null;
541
+ if( !isset( $arglist[2] )) $arglist[2] = null;
542
+ return $this->setXprop( $arglist[0], $arglist[1], $arglist[2] );
543
+ }
544
+ return FALSE;
545
+ }
546
+ /*********************************************************************************/
547
+ /**
548
+ * get vcalendar config values or * calendar components
549
+ *
550
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
551
+ * @since 2.9.6 - 2011-05-14
552
+ * @param mixed $config
553
+ * @return value
554
+ */
555
+ function getConfig( $config = FALSE ) {
556
+ if( !$config ) {
557
+ $return = array();
558
+ $return['ALLOWEMPTY'] = $this->getConfig( 'ALLOWEMPTY' );
559
+ $return['DELIMITER'] = $this->getConfig( 'DELIMITER' );
560
+ $return['DIRECTORY'] = $this->getConfig( 'DIRECTORY' );
561
+ $return['FILENAME'] = $this->getConfig( 'FILENAME' );
562
+ $return['DIRFILE'] = $this->getConfig( 'DIRFILE' );
563
+ $return['FILESIZE'] = $this->getConfig( 'FILESIZE' );
564
+ $return['FORMAT'] = $this->getConfig( 'FORMAT' );
565
+ if( FALSE !== ( $lang = $this->getConfig( 'LANGUAGE' )))
566
+ $return['LANGUAGE'] = $lang;
567
+ $return['NEWLINECHAR'] = $this->getConfig( 'NEWLINECHAR' );
568
+ $return['UNIQUE_ID'] = $this->getConfig( 'UNIQUE_ID' );
569
+ if( FALSE !== ( $url = $this->getConfig( 'URL' )))
570
+ $return['URL'] = $url;
571
+ $return['TZID'] = $this->getConfig( 'TZID' );
572
+ return $return;
573
+ }
574
+ switch( strtoupper( $config )) {
575
+ case 'ALLOWEMPTY':
576
+ return $this->allowEmpty;
577
+ break;
578
+ case 'COMPSINFO':
579
+ unset( $this->compix );
580
+ $info = array();
581
+ foreach( $this->components as $cix => $component ) {
582
+ if( empty( $component )) continue;
583
+ $info[$cix]['ordno'] = $cix + 1;
584
+ $info[$cix]['type'] = $component->objName;
585
+ $info[$cix]['uid'] = $component->getProperty( 'uid' );
586
+ $info[$cix]['props'] = $component->getConfig( 'propinfo' );
587
+ $info[$cix]['sub'] = $component->getConfig( 'compsinfo' );
588
+ }
589
+ return $info;
590
+ break;
591
+ case 'DELIMITER':
592
+ return $this->delimiter;
593
+ break;
594
+ case 'DIRECTORY':
595
+ if( empty( $this->directory ))
596
+ $this->directory = '.';
597
+ return $this->directory;
598
+ break;
599
+ case 'DIRFILE':
600
+ return $this->getConfig( 'directory' ).$this->getConfig( 'delimiter' ).$this->getConfig( 'filename' );
601
+ break;
602
+ case 'FILEINFO':
603
+ return array( $this->getConfig( 'directory' )
604
+ , $this->getConfig( 'filename' )
605
+ , $this->getConfig( 'filesize' ));
606
+ break;
607
+ case 'FILENAME':
608
+ if( empty( $this->filename )) {
609
+ if( 'xcal' == $this->format )
610
+ $this->filename = date( 'YmdHis' ).'.xml'; // recommended xcs.. .
611
+ else
612
+ $this->filename = date( 'YmdHis' ).'.ics';
613
+ }
614
+ return $this->filename;
615
+ break;
616
+ case 'FILESIZE':
617
+ $size = 0;
618
+ if( empty( $this->url )) {
619
+ $dirfile = $this->getConfig( 'dirfile' );
620
+ if( !is_file( $dirfile ) || ( FALSE === ( $size = filesize( $dirfile ))))
621
+ $size = 0;
622
+ clearstatcache();
623
+ }
624
+ return $size;
625
+ break;
626
+ case 'FORMAT':
627
+ return ( $this->format == 'xcal' ) ? 'xCal' : 'iCal';
628
+ break;
629
+ case 'LANGUAGE':
630
+ /* get language for calendar component as defined in [RFC 1766] */
631
+ return $this->language;
632
+ break;
633
+ case 'NL':
634
+ case 'NEWLINECHAR':
635
+ return $this->nl;
636
+ break;
637
+ case 'TZID':
638
+ return $this->dtzid;
639
+ break;
640
+ case 'UNIQUE_ID':
641
+ return $this->unique_id;
642
+ break;
643
+ case 'URL':
644
+ if( !empty( $this->url ))
645
+ return $this->url;
646
+ else
647
+ return FALSE;
648
+ break;
649
+ }
650
+ }
651
+ /**
652
+ * general vcalendar config setting
653
+ *
654
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
655
+ * @since 2.9.6 - 2011-05-14
656
+ * @param mixed $config
657
+ * @param string $value
658
+ * @return void
659
+ */
660
+ function setConfig( $config, $value = FALSE) {
661
+ if( is_array( $config )) {
662
+ foreach( $config as $cKey => $cValue ) {
663
+ if( FALSE === $this->setConfig( $cKey, $cValue ))
664
+ return FALSE;
665
+ }
666
+ return TRUE;
667
+ }
668
+ $res = FALSE;
669
+ switch( strtoupper( $config )) {
670
+ case 'ALLOWEMPTY':
671
+ $this->allowEmpty = $value;
672
+ $subcfg = array( 'ALLOWEMPTY' => $value );
673
+ $res = TRUE;
674
+ break;
675
+ case 'DELIMITER':
676
+ $this->delimiter = $value;
677
+ return TRUE;
678
+ break;
679
+ case 'DIRECTORY':
680
+ $value = trim( $value );
681
+ $del = $this->getConfig('delimiter');
682
+ if( $del == substr( $value, ( 0 - strlen( $del ))))
683
+ $value = substr( $value, 0, ( strlen( $value ) - strlen( $del )));
684
+ if( is_dir( $value )) {
685
+ /* local directory */
686
+ clearstatcache();
687
+ $this->directory = $value;
688
+ $this->url = null;
689
+ return TRUE;
690
+ }
691
+ else
692
+ return FALSE;
693
+ break;
694
+ case 'FILENAME':
695
+ $value = trim( $value );
696
+ if( !empty( $this->url )) {
697
+ /* remote directory+file -> URL */
698
+ $this->filename = $value;
699
+ return TRUE;
700
+ }
701
+ $dirfile = $this->getConfig( 'directory' ).$this->getConfig( 'delimiter' ).$value;
702
+ if( file_exists( $dirfile )) {
703
+ /* local file exists */
704
+ if( is_readable( $dirfile ) || is_writable( $dirfile )) {
705
+ clearstatcache();
706
+ $this->filename = $value;
707
+ return TRUE;
708
+ }
709
+ else
710
+ return FALSE;
711
+ }
712
+ elseif( is_readable($this->getConfig( 'directory' ) ) || is_writable( $this->getConfig( 'directory' ) )) {
713
+ /* read- or writable directory */
714
+ $this->filename = $value;
715
+ return TRUE;
716
+ }
717
+ else
718
+ return FALSE;
719
+ break;
720
+ case 'FORMAT':
721
+ $value = trim( strtolower( $value ));
722
+ if( 'xcal' == $value ) {
723
+ $this->format = 'xcal';
724
+ $this->attributeDelimiter = $this->nl;
725
+ $this->valueInit = null;
726
+ }
727
+ else {
728
+ $this->format = null;
729
+ $this->attributeDelimiter = ';';
730
+ $this->valueInit = ':';
731
+ }
732
+ $subcfg = array( 'FORMAT' => $value );
733
+ $res = TRUE;
734
+ break;
735
+ case 'LANGUAGE':
736
+ // set language for calendar component as defined in [RFC 1766]
737
+ $value = trim( $value );
738
+ $this->language = $value;
739
+ $subcfg = array( 'LANGUAGE' => $value );
740
+ $res = TRUE;
741
+ break;
742
+ case 'NL':
743
+ case 'NEWLINECHAR':
744
+ $this->nl = $value;
745
+ $subcfg = array( 'NL' => $value );
746
+ $res = TRUE;
747
+ break;
748
+ case 'TZID':
749
+ $this->dtzid = $value;
750
+ $subcfg = array( 'TZID' => $value );
751
+ $res = TRUE;
752
+ break;
753
+ case 'UNIQUE_ID':
754
+ $value = trim( $value );
755
+ $this->unique_id = $value;
756
+ $subcfg = array( 'UNIQUE_ID' => $value );
757
+ $res = TRUE;
758
+ break;
759
+ case 'URL':
760
+ /* remote file - URL */
761
+ $value = trim( $value );
762
+ $value = str_replace( 'HTTP://', 'http://', $value );
763
+ $value = str_replace( 'WEBCAL://', 'http://', $value );
764
+ $value = str_replace( 'webcal://', 'http://', $value );
765
+ $this->url = $value;
766
+ $this->directory = null;
767
+ $parts = pathinfo( $value );
768
+ return $this->setConfig( 'filename', $parts['basename'] );
769
+ break;
770
+ default: // any unvalid config key.. .
771
+ return TRUE;
772
+ }
773
+ if( !$res ) return FALSE;
774
+ if( isset( $subcfg ) && !empty( $this->components )) {
775
+ foreach( $subcfg as $cfgkey => $cfgvalue ) {
776
+ foreach( $this->components as $cix => $component ) {
777
+ $res = $component->setConfig( $cfgkey, $cfgvalue, TRUE );
778
+ if( !$res )
779
+ break 2;
780
+ $this->components[$cix] = $component->copy(); // PHP4 compliant
781
+ }
782
+ }
783
+ }
784
+ return $res;
785
+ }
786
+ /*********************************************************************************/
787
+ /**
788
+ * add calendar component to container
789
+ *
790
+ * alias to setComponent
791
+ *
792
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
793
+ * @since 1.x.x - 2007-04-24
794
+ * @param object $component calendar component
795
+ * @return void
796
+ */
797
+ function addComponent( $component ) {
798
+ $this->setComponent( $component );
799
+ }
800
+ /**
801
+ * delete calendar component from container
802
+ *
803
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
804
+ * @since 2.8.8 - 2011-03-15
805
+ * @param mixed $arg1 ordno / component type / component uid
806
+ * @param mixed $arg2 optional, ordno if arg1 = component type
807
+ * @return void
808
+ */
809
+ function deleteComponent( $arg1, $arg2=FALSE ) {
810
+ $argType = $index = null;
811
+ if ( ctype_digit( (string) $arg1 )) {
812
+ $argType = 'INDEX';
813
+ $index = (int) $arg1 - 1;
814
+ }
815
+ elseif(( strlen( $arg1 ) <= strlen( 'vfreebusy' )) && ( FALSE === strpos( $arg1, '@' ))) {
816
+ $argType = strtolower( $arg1 );
817
+ $index = ( !empty( $arg2 ) && ctype_digit( (string) $arg2 )) ? (( int ) $arg2 - 1 ) : 0;
818
+ }
819
+ $cix1dC = 0;
820
+ foreach ( $this->components as $cix => $component) {
821
+ if( empty( $component )) continue;
822
+ if(( 'INDEX' == $argType ) && ( $index == $cix )) {
823
+ unset( $this->components[$cix] );
824
+ return TRUE;
825
+ }
826
+ elseif( $argType == $component->objName ) {
827
+ if( $index == $cix1dC ) {
828
+ unset( $this->components[$cix] );
829
+ return TRUE;
830
+ }
831
+ $cix1dC++;
832
+ }
833
+ elseif( !$argType && ($arg1 == $component->getProperty( 'uid' ))) {
834
+ unset( $this->components[$cix] );
835
+ return TRUE;
836
+ }
837
+ }
838
+ return FALSE;
839
+ }
840
+ /**
841
+ * get calendar component from container
842
+ *
843
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
844
+ * @since 2.9.1 - 2011-04-16
845
+ * @param mixed $arg1 optional, ordno/component type/ component uid
846
+ * @param mixed $arg2 optional, ordno if arg1 = component type
847
+ * @return object
848
+ */
849
+ function getComponent( $arg1=FALSE, $arg2=FALSE ) {
850
+ $index = $argType = null;
851
+ if ( !$arg1 ) { // first or next in component chain
852
+ $argType = 'INDEX';
853
+ $index = $this->compix['INDEX'] = ( isset( $this->compix['INDEX'] )) ? $this->compix['INDEX'] + 1 : 1;
854
+ }
855
+ elseif ( ctype_digit( (string) $arg1 )) { // specific component in chain
856
+ $argType = 'INDEX';
857
+ $index = (int) $arg1;
858
+ unset( $this->compix );
859
+ }
860
+ elseif( is_array( $arg1 )) { // array( *[propertyName => propertyValue] )
861
+ $arg2 = implode( '-', array_keys( $arg1 ));
862
+ $index = $this->compix[$arg2] = ( isset( $this->compix[$arg2] )) ? $this->compix[$arg2] + 1 : 1;
863
+ $dateProps = array( 'DTSTART', 'DTEND', 'DUE', 'CREATED', 'COMPLETED', 'DTSTAMP', 'LAST-MODIFIED', 'RECURRENCE-ID' );
864
+ $otherProps = array( 'ATTENDEE', 'CATEGORIES', 'LOCATION', 'ORGANIZER', 'PRIORITY', 'RESOURCES', 'STATUS', 'SUMMARY', 'UID' );
865
+ }
866
+ elseif(( strlen( $arg1 ) <= strlen( 'vfreebusy' )) && ( FALSE === strpos( $arg1, '@' ))) { // object class name
867
+ unset( $this->compix['INDEX'] );
868
+ $argType = strtolower( $arg1 );
869
+ if( !$arg2 )
870
+ $index = $this->compix[$argType] = ( isset( $this->compix[$argType] )) ? $this->compix[$argType] + 1 : 1;
871
+ elseif( isset( $arg2 ) && ctype_digit( (string) $arg2 ))
872
+ $index = (int) $arg2;
873
+ }
874
+ elseif(( strlen( $arg1 ) > strlen( 'vfreebusy' )) && ( FALSE !== strpos( $arg1, '@' ))) { // UID as 1st argument
875
+ if( !$arg2 )
876
+ $index = $this->compix[$arg1] = ( isset( $this->compix[$arg1] )) ? $this->compix[$arg1] + 1 : 1;
877
+ elseif( isset( $arg2 ) && ctype_digit( (string) $arg2 ))
878
+ $index = (int) $arg2;
879
+ }
880
+ if( isset( $index ))
881
+ $index -= 1;
882
+ $ckeys = array_keys( $this->components );
883
+ if( !empty( $index) && ( $index > end( $ckeys )))
884
+ return FALSE;
885
+ $cix1gC = 0;
886
+ foreach ( $this->components as $cix => $component) {
887
+ if( empty( $component )) continue;
888
+ if(( 'INDEX' == $argType ) && ( $index == $cix ))
889
+ return $component->copy();
890
+ elseif( $argType == $component->objName ) {
891
+ if( $index == $cix1gC )
892
+ return $component->copy();
893
+ $cix1gC++;
894
+ }
895
+ elseif( is_array( $arg1 )) { // array( *[propertyName => propertyValue] )
896
+ $hit = FALSE;
897
+ foreach( $arg1 as $pName => $pValue ) {
898
+ $pName = strtoupper( $pName );
899
+ if( !in_array( $pName, $dateProps ) && !in_array( $pName, $otherProps ))
900
+ continue;
901
+ if(( 'ATTENDEE' == $pName ) || ( 'CATEGORIES' == $pName ) || ( 'RESOURCES' == $pName )) { // multiple ocurrence may occur
902
+ $propValues = array();
903
+ $component->_getProperties( $pName, $propValues );
904
+ $propValues = array_keys( $propValues );
905
+ $hit = ( in_array( $pValue, $propValues )) ? TRUE : FALSE;
906
+ continue;
907
+ } // end if(( 'CATEGORIES' == $propName ) || ( 'RESOURCES' == $propName )) { // multiple ocurrence may occur
908
+ if( FALSE === ( $value = $component->getProperty( $pName ))) { // single ocurrency
909
+ $hit = FALSE; // missing property
910
+ continue;
911
+ }
912
+ if( 'SUMMARY' == $pName ) { // exists within (any case)
913
+ $hit = ( FALSE !== stripos( $d, $pValue )) ? TRUE : FALSE;
914
+ continue;
915
+ }
916
+ if( in_array( strtoupper( $pName ), $dateProps )) {
917
+ $valuedate = sprintf( '%04d%02d%02d', $value['year'], $value['month'], $value['day'] );
918
+ if( 8 < strlen( $pValue )) {
919
+ if( isset( $value['hour'] )) {
920
+ if( 'T' == substr( $pValue, 8, 1 ))
921
+ $pValue = str_replace( 'T', '', $pValue );
922
+ $valuedate .= sprintf( '%02d%02d%02d', $value['hour'], $value['min'], $value['sec'] );
923
+ }
924
+ else
925
+ $pValue = substr( $pValue, 0, 8 );
926
+ }
927
+ $hit = ( $pValue == $valuedate ) ? TRUE : FALSE;
928
+ continue;
929
+ }
930
+ elseif( !is_array( $value ))
931
+ $value = array( $value );
932
+ foreach( $value as $part ) {
933
+ $part = ( FALSE !== strpos( $part, ',' )) ? explode( ',', $part ) : array( $part );
934
+ foreach( $part as $subPart ) {
935
+ if( $pValue == $subPart ) {
936
+ $hit = TRUE;
937
+ continue 2;
938
+ }
939
+ }
940
+ }
941
+ $hit = FALSE; // no hit in property
942
+ } // end foreach( $arg1 as $pName => $pValue )
943
+ if( $hit ) {
944
+ if( $index == $cix1gC )
945
+ return $component->copy();
946
+ $cix1gC++;
947
+ }
948
+ } // end elseif( is_array( $arg1 )) { // array( *[propertyName => propertyValue] )
949
+ elseif( !$argType && ($arg1 == $component->getProperty( 'uid' ))) { // UID
950
+ if( $index == $cix1gC )
951
+ return $component->copy();
952
+ $cix1gC++;
953
+ }
954
+ } // end foreach ( $this->components.. .
955
+ /* not found.. . */
956
+ unset( $this->compix );
957
+ return FALSE;
958
+ }
959
+ /**
960
+ * create new calendar component, already included within calendar
961
+ *
962
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
963
+ * @since 2.6.33 - 2011-01-03
964
+ * @param string $compType component type
965
+ * @return object (reference)
966
+ */
967
+ function & newComponent( $compType ) {
968
+ $config = $this->getConfig();
969
+ $keys = array_keys( $this->components );
970
+ $ix = end( $keys) + 1;
971
+ switch( strtoupper( $compType )) {
972
+ case 'EVENT':
973
+ case 'VEVENT':
974
+ $this->components[$ix] = new vevent( $config );
975
+ break;
976
+ case 'TODO':
977
+ case 'VTODO':
978
+ $this->components[$ix] = new vtodo( $config );
979
+ break;
980
+ case 'JOURNAL':
981
+ case 'VJOURNAL':
982
+ $this->components[$ix] = new vjournal( $config );
983
+ break;
984
+ case 'FREEBUSY':
985
+ case 'VFREEBUSY':
986
+ $this->components[$ix] = new vfreebusy( $config );
987
+ break;
988
+ case 'TIMEZONE':
989
+ case 'VTIMEZONE':
990
+ array_unshift( $this->components, new vtimezone( $config ));
991
+ $ix = 0;
992
+ break;
993
+ default:
994
+ return FALSE;
995
+ }
996
+ return $this->components[$ix];
997
+ }
998
+ /**
999
+ * select components from calendar on date or selectOption basis
1000
+ *
1001
+ * Ensure DTSTART is set for every component.
1002
+ * No date controls occurs.
1003
+ *
1004
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
1005
+ * @since 2.9.7 - 2011-06-04
1006
+ * @param mixed $startY optional, start Year, default current Year ALT. array selecOptions
1007
+ * @param int $startM optional, start Month, default current Month
1008
+ * @param int $startD optional, start Day, default current Day
1009
+ * @param int $endY optional, end Year, default $startY
1010
+ * @param int $endY optional, end Month, default $startM
1011
+ * @param int $endY optional, end Day, default $startD
1012
+ * @param mixed $cType optional, calendar component type(-s), default FALSE=all else string/array type(-s)
1013
+ * @param bool $flat optional, FALSE (default) => output : array[Year][Month][Day][]
1014
+ * TRUE => output : array[] (ignores split)
1015
+ * @param bool $any optional, TRUE (default) - select component that take place within period
1016
+ * FALSE - only components that starts within period
1017
+ * @param bool $split optional, TRUE (default) - one component copy every day it take place during the
1018
+ * period (implies flat=FALSE)
1019
+ * FALSE - one occurance of component only in output array
1020
+ * @return array or FALSE
1021
+ */
1022
+ function selectComponents( $startY=FALSE, $startM=FALSE, $startD=FALSE, $endY=FALSE, $endM=FALSE, $endD=FALSE, $cType=FALSE, $flat=FALSE, $any=TRUE, $split=TRUE ) {
1023
+ /* check if empty calendar */
1024
+ if( 0 >= count( $this->components )) return FALSE;
1025
+ if( is_array( $startY ))
1026
+ return $this->selectComponents2( $startY );
1027
+ /* check default dates */
1028
+ if( !$startY ) $startY = date( 'Y' );
1029
+ if( !$startM ) $startM = date( 'm' );
1030
+ if( !$startD ) $startD = date( 'd' );
1031
+ $startDate = mktime( 0, 0, 0, $startM, $startD, $startY );
1032
+ if( !$endY ) $endY = $startY;
1033
+ if( !$endM ) $endM = $startM;
1034
+ if( !$endD ) $endD = $startD;
1035
+ $endDate = mktime( 23, 59, 59, $endM, $endD, $endY );
1036
+ //echo 'selectComp arg='.date( 'Y-m-d H:i:s', $startDate).' -- '.date( 'Y-m-d H:i:s', $endDate)."<br />\n"; $tcnt = 0;// test ###
1037
+ /* check component types */
1038
+ $validTypes = array('vevent', 'vtodo', 'vjournal', 'vfreebusy' );
1039
+ if( is_array( $cType )) {
1040
+ foreach( $cType as $cix => $theType ) {
1041
+ $cType[$cix] = $theType = strtolower( $theType );
1042
+ if( !in_array( $theType, $validTypes ))
1043
+ $cType[$cix] = 'vevent';
1044
+ }
1045
+ $cType = array_unique( $cType );
1046
+ }
1047
+ elseif( !empty( $cType )) {
1048
+ $cType = strtolower( $cType );
1049
+ if( !in_array( $cType, $validTypes ))
1050
+ $cType = array( 'vevent' );
1051
+ else
1052
+ $cType = array( $cType );
1053
+ }
1054
+ else
1055
+ $cType = $validTypes;
1056
+ if( 0 >= count( $cType ))
1057
+ $cType = $validTypes;
1058
+ if(( TRUE === $flat ) && ( TRUE === $split )) // invalid combination
1059
+ $split = FALSE;
1060
+ /* iterate components */
1061
+ $result = array();
1062
+ foreach ( $this->components as $cix => $component ) {
1063
+ if( empty( $component )) continue;
1064
+ unset( $start );
1065
+ /* deselect unvalid type components */
1066
+ if( !in_array( $component->objName, $cType )) continue;
1067
+ $start = $component->getProperty( 'dtstart' );
1068
+ /* select due when dtstart is missing */
1069
+ if( empty( $start ) && ( $component->objName == 'vtodo' ) && ( FALSE === ( $start = $component->getProperty( 'due' ))))
1070
+ continue;
1071
+ $dtendExist = $dueExist = $durationExist = $endAllDayEvent = FALSE;
1072
+ unset( $end, $startWdate, $endWdate, $rdurWsecs, $rdur, $exdatelist, $workstart, $workend, $endDateFormat ); // clean up
1073
+ $startWdate = iCalUtilityFunctions::_date2timestamp( $start );
1074
+ $startDateFormat = ( isset( $start['hour'] )) ? 'Y-m-d H:i:s' : 'Y-m-d';
1075
+ /* get end date from dtend/due/duration properties */
1076
+ $end = $component->getProperty( 'dtend' );
1077
+ if( !empty( $end )) {
1078
+ $dtendExist = TRUE;
1079
+ $endDateFormat = ( isset( $end['hour'] )) ? 'Y-m-d H:i:s' : 'Y-m-d';
1080
+ }
1081
+ if( empty( $end ) && ( $component->objName == 'vtodo' )) {
1082
+ $end = $component->getProperty( 'due' );
1083
+ if( !empty( $end )) {
1084
+ $dueExist = TRUE;
1085
+ $endDateFormat = ( isset( $end['hour'] )) ? 'Y-m-d H:i:s' : 'Y-m-d';
1086
+ }
1087
+ }
1088
+ if( !empty( $end ) && !isset( $end['hour'] )) {
1089
+ /* a DTEND without time part regards an event that ends the day before,
1090
+ for an all-day event DTSTART=20071201 DTEND=20071202 (taking place 20071201!!! */
1091
+ $endAllDayEvent = TRUE;
1092
+ $endWdate = mktime( 23, 59, 59, $end['month'], ($end['day'] - 1), $end['year'] );
1093
+ $end['year'] = date( 'Y', $endWdate );
1094
+ $end['month'] = date( 'm', $endWdate );
1095
+ $end['day'] = date( 'd', $endWdate );
1096
+ $end['hour'] = 23;
1097
+ $end['min'] = $end['sec'] = 59;
1098
+ }
1099
+ if( empty( $end )) {
1100
+ $end = $component->getProperty( 'duration', FALSE, FALSE, TRUE );// in dtend (array) format
1101
+ if( !empty( $end ))
1102
+ $durationExist = TRUE;
1103
+ $endDateFormat = ( isset( $start['hour'] )) ? 'Y-m-d H:i:s' : 'Y-m-d';
1104
+ // if( !empty($end)) echo 'selectComp 4 start='.implode('-',$start).' end='.implode('-',$end)."<br />\n"; // test ###
1105
+ }
1106
+ if( empty( $end )) { // assume one day duration if missing end date
1107
+ $end = array( 'year' => $start['year'], 'month' => $start['month'], 'day' => $start['day'], 'hour' => 23, 'min' => 59, 'sec' => 59 );
1108
+ }
1109
+ // if( isset($end)) echo 'selectComp 5 start='.implode('-',$start).' end='.implode('-',$end)."<br />\n"; // test ###
1110
+ $endWdate = iCalUtilityFunctions::_date2timestamp( $end );
1111
+ if( $endWdate < $startWdate ) { // MUST be after start date!!
1112
+ $end = array( 'year' => $start['year'], 'month' => $start['month'], 'day' => $start['day'], 'hour' => 23, 'min' => 59, 'sec' => 59 );
1113
+ $endWdate = iCalUtilityFunctions::_date2timestamp( $end );
1114
+ }
1115
+ $rdurWsecs = $endWdate - $startWdate; // compute component duration in seconds
1116
+ /* make a list of optional exclude dates for component occurence from exrule and exdate */
1117
+ $exdatelist = array();
1118
+ $workstart = iCalUtilityFunctions::_timestamp2date(( $startDate - $rdurWsecs ), 6);
1119
+ $workend = iCalUtilityFunctions::_timestamp2date(( $endDate + $rdurWsecs ), 6);
1120
+ while( FALSE !== ( $exrule = $component->getProperty( 'exrule' ))) // check exrule
1121
+ iCalUtilityFunctions::_recur2date( $exdatelist, $exrule, $start, $workstart, $workend );
1122
+ while( FALSE !== ( $exdate = $component->getProperty( 'exdate' ))) { // check exdate
1123
+ foreach( $exdate as $theExdate ) {
1124
+ $exWdate = iCalUtilityFunctions::_date2timestamp( $theExdate );
1125
+ $exWdate = mktime( 0, 0, 0, date( 'm', $exWdate ), date( 'd', $exWdate ), date( 'Y', $exWdate ) ); // on a day-basis !!!
1126
+ if((( $startDate - $rdurWsecs ) <= $exWdate ) && ( $endDate >= $exWdate ))
1127
+ $exdatelist[$exWdate] = TRUE;
1128
+ }
1129
+ }
1130
+ /* if 'any' components, check repeating components, removing all excluding dates */
1131
+ if( TRUE === $any ) {
1132
+ /* make a list of optional repeating dates for component occurence, rrule, rdate */
1133
+ $recurlist = array();
1134
+ while( FALSE !== ( $rrule = $component->getProperty( 'rrule' ))) // check rrule
1135
+ iCalUtilityFunctions::_recur2date( $recurlist, $rrule, $start, $workstart, $workend );
1136
+ foreach( $recurlist as $recurkey => $recurvalue ) // key=match date as timestamp
1137
+ $recurlist[$recurkey] = $rdurWsecs; // add duration in seconds
1138
+ while( FALSE !== ( $rdate = $component->getProperty( 'rdate' ))) { // check rdate
1139
+ foreach( $rdate as $theRdate ) {
1140
+ if( is_array( $theRdate ) && ( 2 == count( $theRdate )) && // all days within PERIOD
1141
+ array_key_exists( '0', $theRdate ) && array_key_exists( '1', $theRdate )) {
1142
+ $rstart = iCalUtilityFunctions::_date2timestamp( $theRdate[0] );
1143
+ if(( $rstart < ( $startDate - $rdurWsecs )) || ( $rstart > $endDate ))
1144
+ continue;
1145
+ if( isset( $theRdate[1]['year'] )) // date-date period
1146
+ $rend = iCalUtilityFunctions::_date2timestamp( $theRdate[1] );
1147
+ else { // date-duration period
1148
+ $rend = iCalUtilityFunctions::_duration2date( $theRdate[0], $theRdate[1] );
1149
+ $rend = iCalUtilityFunctions::_date2timestamp( $rend );
1150
+ }
1151
+ while( $rstart < $rend ) {
1152
+ $recurlist[$rstart] = $rdurWsecs; // set start date for recurrence instance + rdate duration in seconds
1153
+ $rstart = mktime( date( 'H', $rstart ), date( 'i', $rstart ), date( 's', $rstart ), date( 'm', $rstart ), date( 'd', $rstart ) + 1, date( 'Y', $rstart ) ); // step one day
1154
+ }
1155
+ } // PERIOD end
1156
+ else { // single date
1157
+ $theRdate = iCalUtilityFunctions::_date2timestamp( $theRdate );
1158
+ if((( $startDate - $rdurWsecs ) <= $theRdate ) && ( $endDate >= $theRdate ))
1159
+ $recurlist[$theRdate] = $rdurWsecs; // set start date for recurrence instance + event duration in seconds
1160
+ }
1161
+ }
1162
+ }
1163
+ if( 0 < count( $recurlist )) {
1164
+ ksort( $recurlist );
1165
+ $xRecurrence = 1;
1166
+ foreach( $recurlist as $recurkey => $durvalue ) {
1167
+ // echo "recurKey=".date( 'Y-m-d H:i:s', $recurkey ).' dur='.iCalUtilityFunctions::offsetSec2His( $durvalue )."<br />\n"; // test ###;
1168
+ if((( $startDate - $rdurWsecs ) > $recurkey ) || ( $endDate < $recurkey )) // not within period
1169
+ continue;
1170
+ $checkDate = mktime( 0, 0, 0, date( 'm', $recurkey ), date( 'd', $recurkey ), date( 'Y', $recurkey ) ); // on a day-basis !!!
1171
+ if( isset( $exdatelist[$checkDate] )) // check excluded dates
1172
+ continue;
1173
+ if( $startWdate >= $recurkey ) // exclude component start date
1174
+ continue;
1175
+ $component2 = $component->copy();
1176
+ $rstart = $recurkey;
1177
+ $rend = $recurkey + $durvalue;
1178
+ /* add repeating components within valid dates to output array, only start date set */
1179
+ if( $flat ) {
1180
+ $datestring = date( $startDateFormat, $recurkey );
1181
+ if( isset( $start['tz'] ))
1182
+ $datestring .= ' '.$start['tz'];
1183
+ // echo "X-CURRENT-DTSTART 0 =$datestring tcnt =".++$tcnt."<br />";$component2->setProperty( 'X-CNT', $tcnt ); // test ###
1184
+ $component2->setProperty( 'X-CURRENT-DTSTART', $datestring );
1185
+ if( $dtendExist || $dueExist || $durationExist ) {
1186
+ $datestring = date( $endDateFormat, $recurkey + $durvalue ); // fixa korrekt sluttid
1187
+ if( isset( $end['tz'] ))
1188
+ $datestring .= ' '.$end['tz'];
1189
+ $propName = ( !$dueExist ) ? 'X-CURRENT-DTEND' : 'X-CURRENT-DUE';
1190
+ $component2->setProperty( $propName, $datestring );
1191
+ } // end if( $dtendExist || $dueExist || $durationExist )
1192
+ $component2->setProperty( 'X-RECURRENCE', ++$xRecurrence );
1193
+ $result[$component2->getProperty( 'UID' )] = $component2->copy(); // copy to output
1194
+ }
1195
+ /* add repeating components within valid dates to output array, one each day */
1196
+ elseif( $split ) {
1197
+ if( $rend > $endDate )
1198
+ $rend = $endDate;
1199
+ $startYMD = date( 'Ymd', $rstart );
1200
+ $endYMD = date( 'Ymd', $rend );
1201
+ // echo "splitStart=".date( 'Y-m-d H:i:s', $rstart ).' end='.date( 'Y-m-d H:i:s', $rend )."<br />\n"; // test ###;
1202
+ while( $rstart <= $rend ) { // iterate.. .
1203
+ $checkDate = mktime( 0, 0, 0, date( 'm', $rstart ), date( 'd', $rstart ), date( 'Y', $rstart ) ); // on a day-basis !!!
1204
+ if( isset( $exdatelist[$checkDate] )) // exclude any recurrence START date, found in exdatelist
1205
+ break;
1206
+ // echo "checking date after startdate=".date( 'Y-m-d H:i:s', $rstart ).' mot '.date( 'Y-m-d H:i:s', $startDate )."<br />"; // test ###;
1207
+ if( $rstart >= $startDate ) { // date after dtstart
1208
+ if( date( 'Ymd', $rstart ) > $startYMD ) // date after dtstart
1209
+ $datestring = date( $startDateFormat, $checkDate );
1210
+ else
1211
+ $datestring = date( $startDateFormat, $rstart );
1212
+ if( isset( $start['tz'] ))
1213
+ $datestring .= ' '.$start['tz'];
1214
+ //echo "X-CURRENT-DTSTART 1 = $datestring xRecurrence=$xRecurrence tcnt =".++$tcnt."<br />";$component2->setProperty( 'X-CNT', $tcnt ); // test ###
1215
+ $component2->setProperty( 'X-CURRENT-DTSTART', $datestring );
1216
+ if( $dtendExist || $dueExist || $durationExist ) {
1217
+ if( date( 'Ymd', $rstart ) < $endYMD ) // not the last day
1218
+ $tend = mktime( 23, 59, 59, date( 'm', $rstart ), date( 'd', $rstart ), date( 'Y', $rstart ));
1219
+ else
1220
+ $tend = mktime( date( 'H', $endWdate ), date( 'i', $endWdate ), date( 's', $endWdate ), date( 'm', $rstart ), date( 'd', $rstart ), date( 'Y', $rstart ) ); // on a day-basis !!!
1221
+ $datestring = date( $endDateFormat, $tend );
1222
+ if( isset( $end['tz'] ))
1223
+ $datestring .= ' '.$end['tz'];
1224
+ $propName = ( !$dueExist ) ? 'X-CURRENT-DTEND' : 'X-CURRENT-DUE';
1225
+ $component2->setProperty( $propName, $datestring );
1226
+ } // end if( $dtendExist || $dueExist || $durationExist )
1227
+ $component2->setProperty( 'X-RECURRENCE', $xRecurrence );
1228
+ $wd = getdate( $rstart );
1229
+ $result[$wd['year']][$wd['mon']][$wd['mday']][$component2->getProperty( 'UID' )] = $component2->copy(); // copy to output
1230
+ } // end if( $checkDate > $startYMD ) { // date after dtstart
1231
+ $rstart = mktime( date( 'H', $rstart ), date( 'i', $rstart ), date( 's', $rstart ), date( 'm', $rstart ), date( 'd', $rstart ) + 1, date( 'Y', $rstart ) ); // step one day
1232
+ } // end while( $rstart <= $rend )
1233
+ $xRecurrence += 1;
1234
+ } // end elseif( $split )
1235
+ elseif( $rstart >= $startDate ) { // date within period //* flat=FALSE && split=FALSE *//
1236
+ $checkDate = mktime( 0, 0, 0, date( 'm', $rstart ), date( 'd', $rstart ), date( 'Y', $rstart ) ); // on a day-basis !!!
1237
+ if( !isset( $exdatelist[$checkDate] )) { // exclude any recurrence START date, found in exdatelist
1238
+ $xRecurrence += 1;
1239
+ $datestring = date( $startDateFormat, $rstart );
1240
+ if( isset( $start['tz'] ))
1241
+ $datestring .= ' '.$start['tz'];
1242
+ //echo "X-CURRENT-DTSTART 2 = $datestring xRecurrence=$xRecurrence tcnt =".++$tcnt."<br />";$component2->setProperty( 'X-CNT', $tcnt ); // test ###
1243
+ $component2->setProperty( 'X-CURRENT-DTSTART', $datestring );
1244
+ if( $dtendExist || $dueExist || $durationExist ) {
1245
+ $rstart += $rdurWsecs;
1246
+ if( date( 'Ymd', $rstart ) < date( 'Ymd', $endWdate ))
1247
+ $tend = mktime( 23, 59, 59, date( 'm', $rstart ), date( 'd', $rstart ), date( 'Y', $rstart ));
1248
+ else
1249
+ $tend = mktime( date( 'H', $endWdate ), date( 'i', $endWdate ), date( 's', $endWdate ), date( 'm', $rstart ), date( 'd', $rstart ), date( 'Y', $rstart ) ); // on a day-basis !!!
1250
+ $datestring = date( $endDateFormat, $tend );
1251
+ if( isset( $end['tz'] ))
1252
+ $datestring .= ' '.$end['tz'];
1253
+ $propName = ( !$dueExist ) ? 'X-CURRENT-DTEND' : 'X-CURRENT-DUE';
1254
+ $component2->setProperty( $propName, $datestring );
1255
+ } // end if( $dtendExist || $dueExist || $durationExist )
1256
+ $component2->setProperty( 'X-RECURRENCE', $xRecurrence );
1257
+ $wd = getdate( $rstart );
1258
+ $result[$wd['year']][$wd['mon']][$wd['mday']][$component2->getProperty( 'UID' )] = $component2->copy(); // copy to output
1259
+ } // end if( !isset( $exdatelist[$checkDate] ))
1260
+ } // end elseif( $rstart >= $startDate )
1261
+ } // end foreach( $recurlist as $recurkey => $durvalue )
1262
+ } // end if( 0 < count( $recurlist ))
1263
+ /* deselect components with startdate/enddate not within period */
1264
+ if(( $endWdate < $startDate ) || ( $startWdate > $endDate ))
1265
+ continue;
1266
+ } // end if( TRUE === $any )
1267
+ /* deselect components with startdate not within period */
1268
+ elseif(( $startWdate < $startDate ) || ( $startWdate > $endDate ))
1269
+ continue;
1270
+ /* add the selected component (WITHIN valid dates) to output array */
1271
+ if( $flat )
1272
+ $result[$component->getProperty( 'UID' )] = $component->copy(); // copy to output;
1273
+ elseif( $split ) { // split the original component
1274
+ if( $endWdate > $endDate )
1275
+ $endWdate = $endDate; // use period end date
1276
+ $rstart = $startWdate;
1277
+ if( $rstart < $startDate )
1278
+ $rstart = $startDate; // use period start date
1279
+ $checkDate = mktime( 0, 0, 0, date( 'm', $rstart ), date( 'd', $rstart ), date( 'Y', $rstart ) ); // on a day-basis !!!
1280
+ if( !isset( $exdatelist[$checkDate] )) { // exclude any recurrence START date, found in exdatelist
1281
+ foreach( array( 'X-CURRENT-DTSTART','X-CURRENT-DTEND','X-CURRENT-DUE','X-RECURRENCE' ) as $propName )
1282
+ $component->deleteProperty( $propName ); // remove any x-props, if set
1283
+ while( $rstart <= $endWdate ) { // iterate
1284
+ if( $rstart > $startWdate ) { // if NOT startdate, set X-properties
1285
+ $datestring = date( $startDateFormat, mktime( 0, 0, 0, date( 'm', $rstart ), date( 'd', $rstart ), date( 'Y', $rstart )));
1286
+ if( isset( $start['tz'] ))
1287
+ $datestring .= ' '.$start['tz'];
1288
+ // echo "X-CURRENT-DTSTART 3 = $datestring xRecurrence=$xRecurrence tcnt =".++$tcnt."<br />";$component->setProperty( 'X-CNT', $tcnt ); // test ###
1289
+ $component->setProperty( 'X-CURRENT-DTSTART', $datestring );
1290
+ if( $dtendExist || $dueExist || $durationExist ) {
1291
+ if( date( 'Ymd', $rstart ) < date( 'Ymd', $endWdate ))
1292
+ $tend = mktime( 0, 0, 0, date( 'm', $rstart ), date( 'd', $rstart ), date( 'Y', $rstart ));
1293
+ else
1294
+ $tend = mktime( date( 'H', $endWdate ), date( 'i', $endWdate ), date( 's', $endWdate ), date( 'm', $rstart ), date( 'd', $rstart ), date( 'Y', $rstart ) ); // on a day-basis !!!
1295
+ $datestring = date( $endDateFormat, $tend );
1296
+ if( isset( $end['tz'] ))
1297
+ $datestring .= ' '.$end['tz'];
1298
+ $propName = ( !$dueExist ) ? 'X-CURRENT-DTEND' : 'X-CURRENT-DUE';
1299
+ $component->setProperty( $propName, $datestring );
1300
+ } // end if( $dtendExist || $dueExist || $durationExist )
1301
+ } // end if( $rstart > $startWdate )
1302
+ $wd = getdate( $rstart );
1303
+ $result[$wd['year']][$wd['mon']][$wd['mday']][$component->getProperty( 'UID' )] = $component->copy(); // copy to output
1304
+ $rstart = mktime( date( 'H', $rstart ), date( 'i', $rstart ), date( 's', $rstart ), date( 'm', $rstart ), date( 'd', $rstart ) + 1, date( 'Y', $rstart ) ); // step one day
1305
+ } // end while( $rstart <= $endWdate )
1306
+ } // end if( !isset( $exdatelist[$checkDate] ))
1307
+ } // end if( $split ) - else use component date
1308
+ elseif( $startWdate >= $startDate ) { // within period
1309
+ $checkDate = mktime( 0, 0, 0, date( 'm', $startWdate ), date( 'd', $startWdate ), date( 'Y', $startWdate ) ); // on a day-basis !!!
1310
+ if( !isset( $exdatelist[$checkDate] )) { // exclude any recurrence START date, found in exdatelist
1311
+ foreach( array( 'X-CURRENT-DTSTART','X-CURRENT-DTEND','X-CURRENT-DUE','X-RECURRENCE' ) as $propName )
1312
+ $component->deleteProperty( $propName ); // remove any x-props, if set
1313
+ $wd = getdate( $startWdate );
1314
+ $result[$wd['year']][$wd['mon']][$wd['mday']][$component->getProperty( 'UID' )] = $component->copy(); // copy to output
1315
+ }
1316
+ }
1317
+ } // end foreach ( $this->components as $cix => $component )
1318
+ if( 0 >= count( $result )) return FALSE;
1319
+ elseif( !$flat ) {
1320
+ foreach( $result as $y => $yeararr ) {
1321
+ foreach( $yeararr as $m => $montharr ) {
1322
+ foreach( $montharr as $d => $dayarr )
1323
+ $result[$y][$m][$d] = array_values( $dayarr ); // skip tricky UID-index
1324
+ ksort( $result[$y][$m] );
1325
+ }
1326
+ ksort( $result[$y] );
1327
+ }
1328
+ ksort( $result );
1329
+ } // end elseif( !$flat )
1330
+ return $result;
1331
+ }
1332
+ /**
1333
+ * select components from calendar on based on Categories, Location, Resources and/or Summary
1334
+ *
1335
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
1336
+ * @since 2.8.8 - 2011-05-03
1337
+ * @param array $selectOptions, (string) key => (mixed) value, (key=propertyName)
1338
+ * @return array
1339
+ */
1340
+ function selectComponents2( $selectOptions ) {
1341
+ $output = array();
1342
+ $allowedProperties = array( 'ATTENDEE', 'CATEGORIES', 'LOCATION', 'ORGANIZER', 'RESOURCES', 'PRIORITY', 'STATUS', 'SUMMARY', 'UID' );
1343
+ foreach( $this->components as $cix => $component3 ) {
1344
+ if( !in_array( $component3->objName, array('vevent', 'vtodo', 'vjournal', 'vfreebusy' )))
1345
+ continue;
1346
+ $uid = $component3->getProperty( 'UID' );
1347
+ foreach( $selectOptions as $propName => $pvalue ) {
1348
+ $propName = strtoupper( $propName );
1349
+ if( !in_array( $propName, $allowedProperties ))
1350
+ continue;
1351
+ if( !is_array( $pvalue ))
1352
+ $pvalue = array( $pvalue );
1353
+ if(( 'UID' == $propName ) && in_array( $uid, $pvalue )) {
1354
+ $output[] = $component3->copy();
1355
+ continue;
1356
+ }
1357
+ elseif(( 'ATTENDEE' == $propName ) || ( 'CATEGORIES' == $propName ) || ( 'RESOURCES' == $propName )) {
1358
+ $propValues = array();
1359
+ $component3->_getProperties( $propName, $propValues );
1360
+ $propValues = array_keys( $propValues );
1361
+ foreach( $pvalue as $theValue ) {
1362
+ if( in_array( $theValue, $propValues ) && !isset( $output[$uid] )) {
1363
+ $output[$uid] = $component3->copy();
1364
+ break;
1365
+ }
1366
+ }
1367
+ continue;
1368
+ } // end elseif(( 'ATTENDEE' == $propName ) || ( 'CATEGORIES' == $propName ) || ( 'RESOURCES' == $propName ))
1369
+ elseif( FALSE === ( $d = $component3->getProperty( $propName ))) // single ocurrence
1370
+ continue;
1371
+ if( is_array( $d )) {
1372
+ foreach( $d as $part ) {
1373
+ if( in_array( $part, $pvalue ) && !isset( $output[$uid] ))
1374
+ $output[$uid] = $component3->copy();
1375
+ }
1376
+ }
1377
+ elseif(( 'SUMMARY' == $propName ) && !isset( $output[$uid] )) {
1378
+ foreach( $pvalue as $pval ) {
1379
+ if( FALSE !== stripos( $d, $pval )) {
1380
+ $output[$uid] = $component3->copy();
1381
+ break;
1382
+ }
1383
+ }
1384
+ }
1385
+ elseif( in_array( $d, $pvalue ) && !isset( $output[$uid] ))
1386
+ $output[$uid] = $component3->copy();
1387
+ } // end foreach( $selectOptions as $propName => $pvalue ) {
1388
+ } // end foreach( $this->components as $cix => $component3 ) {
1389
+ if( !empty( $output )) {
1390
+ ksort( $output );
1391
+ $output = array_values( $output );
1392
+ }
1393
+ return $output;
1394
+ }
1395
+ /**
1396
+ * add calendar component to container
1397
+ *
1398
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
1399
+ * @since 2.8.8 - 2011-03-15
1400
+ * @param object $component calendar component
1401
+ * @param mixed $arg1 optional, ordno/component type/ component uid
1402
+ * @param mixed $arg2 optional, ordno if arg1 = component type
1403
+ * @return void
1404
+ */
1405
+ function setComponent( $component, $arg1=FALSE, $arg2=FALSE ) {
1406
+ $component->setConfig( $this->getConfig(), FALSE, TRUE );
1407
+ if( !in_array( $component->objName, array( 'valarm', 'vtimezone' ))) {
1408
+ /* make sure dtstamp and uid is set */
1409
+ $dummy1 = $component->getProperty( 'dtstamp' );
1410
+ $dummy2 = $component->getProperty( 'uid' );
1411
+ }
1412
+ if( !$arg1 ) { // plain insert, last in chain
1413
+ $this->components[] = $component->copy();
1414
+ return TRUE;
1415
+ }
1416
+ $argType = $index = null;
1417
+ if ( ctype_digit( (string) $arg1 )) { // index insert/replace
1418
+ $argType = 'INDEX';
1419
+ $index = (int) $arg1 - 1;
1420
+ }
1421
+ elseif( in_array( strtolower( $arg1 ), array( 'vevent', 'vtodo', 'vjournal', 'vfreebusy', 'valarm', 'vtimezone' ))) {
1422
+ $argType = strtolower( $arg1 );
1423
+ $index = ( ctype_digit( (string) $arg2 )) ? ((int) $arg2) - 1 : 0;
1424
+ }
1425
+ // else if arg1 is set, arg1 must be an UID
1426
+ $cix1sC = 0;
1427
+ foreach ( $this->components as $cix => $component2) {
1428
+ if( empty( $component2 )) continue;
1429
+ if(( 'INDEX' == $argType ) && ( $index == $cix )) { // index insert/replace
1430
+ $this->components[$cix] = $component->copy();
1431
+ return TRUE;
1432
+ }
1433
+ elseif( $argType == $component2->objName ) { // component Type index insert/replace
1434
+ if( $index == $cix1sC ) {
1435
+ $this->components[$cix] = $component->copy();
1436
+ return TRUE;
1437
+ }
1438
+ $cix1sC++;
1439
+ }
1440
+ elseif( !$argType && ( $arg1 == $component2->getProperty( 'uid' ))) { // UID insert/replace
1441
+ $this->components[$cix] = $component->copy();
1442
+ return TRUE;
1443
+ }
1444
+ }
1445
+ /* arg1=index and not found.. . insert at index .. .*/
1446
+ if( 'INDEX' == $argType ) {
1447
+ $this->components[$index] = $component->copy();
1448
+ ksort( $this->components, SORT_NUMERIC );
1449
+ }
1450
+ else /* not found.. . insert last in chain anyway .. .*/
1451
+ $this->components[] = $component->copy();
1452
+ return TRUE;
1453
+ }
1454
+ /**
1455
+ * sort iCal compoments
1456
+ *
1457
+ * ascending sort on properties (if exist) x-current-dtstart, dtstart,
1458
+ * x-current-dtend, dtend, x-current-due, due, duration, created, dtstamp, uid
1459
+ * if no arguments, otherwise sorting on argument CATEGORIES, LOCATION, SUMMARY or RESOURCES
1460
+ *
1461
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
1462
+ * @since 2.8.4 - 2011-06-02
1463
+ * @param string $sortArg, optional
1464
+ * @return void
1465
+ *
1466
+ */
1467
+ function sort( $sortArg=FALSE ) {
1468
+ if( is_array( $this->components )) {
1469
+ if( $sortArg ) {
1470
+ $sortArg = strtoupper( $sortArg );
1471
+ if( !in_array( $sortArg, array( 'ATTENDEE', 'CATEGORIES', 'DTSTAMP', 'LOCATION', 'ORGANIZER', 'RESOURCES', 'PRIORITY', 'STATUS', 'SUMMARY' )))
1472
+ $sortArg = FALSE;
1473
+ }
1474
+ /* set sort parameters for each component */
1475
+ foreach( $this->components as $cix => & $c ) {
1476
+ $c->srtk = array( '0', '0', '0', '0' );
1477
+ if( 'vtimezone' == $c->objName ) {
1478
+ if( FALSE === ( $c->srtk[0] = $c->getProperty( 'tzid' )))
1479
+ $c->srtk[0] = 0;
1480
+ continue;
1481
+ }
1482
+ elseif( $sortArg ) {
1483
+ if(( 'ATTENDEE' == $sortArg ) || ( 'CATEGORIES' == $sortArg ) || ( 'RESOURCES' == $sortArg )) {
1484
+ $propValues = array();
1485
+ $c->_getProperties( $sortArg, $propValues );
1486
+ $c->srtk[0] = reset( array_keys( $propValues ));
1487
+ }
1488
+ elseif( FALSE !== ( $d = $c->getProperty( $sortArg )))
1489
+ $c->srtk[0] = $d;
1490
+ continue;
1491
+ }
1492
+ if( FALSE !== ( $d = $c->getProperty( 'X-CURRENT-DTSTART' )))
1493
+ $c->srtk[0] = iCalUtilityFunctions::_date_time_string( $d[1] );
1494
+ elseif( FALSE === ( $c->srtk[0] = $c->getProperty( 'dtstart' )))
1495
+ $c->srtk[1] = 0; // sortkey 0 : dtstart
1496
+ if( FALSE !== ( $d = $c->getProperty( 'X-CURRENT-DTEND' )))
1497
+ $c->srtk[1] = iCalUtilityFunctions::_date_time_string( $d[1] ); // sortkey 1 : dtend/due(/dtstart+duration)
1498
+ elseif( FALSE === ( $c->srtk[1] = $c->getProperty( 'dtend' ))) {
1499
+ if( FALSE !== ( $d = $c->getProperty( 'X-CURRENT-DUE' )))
1500
+ $c->srtk[1] = iCalUtilityFunctions::_date_time_string( $d[1] );
1501
+ elseif( FALSE === ( $c->srtk[1] = $c->getProperty( 'due' )))
1502
+ if( FALSE === ( $c->srtk[1] = $c->getProperty( 'duration', FALSE, FALSE, TRUE )))
1503
+ $c->srtk[1] = 0;
1504
+ }
1505
+ if( FALSE === ( $c->srtk[2] = $c->getProperty( 'created' ))) // sortkey 2 : created/dtstamp
1506
+ if( FALSE === ( $c->srtk[2] = $c->getProperty( 'dtstamp' )))
1507
+ $c->srtk[2] = 0;
1508
+ if( FALSE === ( $c->srtk[3] = $c->getProperty( 'uid' ))) // sortkey 3 : uid
1509
+ $c->srtk[3] = 0;
1510
+ } // end foreach( $this->components as & $c
1511
+ /* sort */
1512
+ usort( $this->components, array( $this, '_cmpfcn' ));
1513
+ }
1514
+ }
1515
+ function _cmpfcn( $a, $b ) {
1516
+ if( empty( $a )) return -1;
1517
+ if( empty( $b )) return 1;
1518
+ if( 'vtimezone' == $a->objName ) {
1519
+ if( 'vtimezone' != $b->objName ) return -1;
1520
+ elseif( $a->srtk[0] <= $b->srtk[0] ) return -1;
1521
+ else return 1;
1522
+ }
1523
+ elseif( 'vtimezone' == $b->objName ) return 1;
1524
+ $sortkeys = array( 'year', 'month', 'day', 'hour', 'min', 'sec' );
1525
+ for( $k = 0; $k < 4 ; $k++ ) {
1526
+ if( empty( $a->srtk[$k] )) return -1;
1527
+ elseif( empty( $b->srtk[$k] )) return 1;
1528
+ if( is_array( $a->srtk[$k] )) {
1529
+ if( is_array( $b->srtk[$k] )) {
1530
+ foreach( $sortkeys as $key ) {
1531
+ if ( empty( $a->srtk[$k][$key] )) return -1;
1532
+ elseif( empty( $b->srtk[$k][$key] )) return 1;
1533
+ if ( $a->srtk[$k][$key] == $b->srtk[$k][$key])
1534
+ continue;
1535
+ if (( (int) $a->srtk[$k][$key] ) < ((int) $b->srtk[$k][$key] ))
1536
+ return -1;
1537
+ elseif(( (int) $a->srtk[$k][$key] ) > ((int) $b->srtk[$k][$key] ))
1538
+ return 1;
1539
+ }
1540
+ }
1541
+ else return -1;
1542
+ }
1543
+ elseif( is_array( $b->srtk[$k] )) return 1;
1544
+ elseif( $a->srtk[$k] < $b->srtk[$k] ) return -1;
1545
+ elseif( $a->srtk[$k] > $b->srtk[$k] ) return 1;
1546
+ }
1547
+ return 0;
1548
+ }
1549
+ /**
1550
+ * parse iCal text/file into vcalendar, components, properties and parameters
1551
+ *
1552
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
1553
+ * @since 2.8.2 - 2011-05-21
1554
+ * @param mixed $unparsedtext, optional, strict rfc2445 formatted, single property string or array of property strings
1555
+ * @return bool FALSE if error occurs during parsing
1556
+ *
1557
+ */
1558
+ function parse( $unparsedtext=FALSE ) {
1559
+ $nl = $this->getConfig( 'nl' );
1560
+ if(( FALSE === $unparsedtext ) || empty( $unparsedtext )) {
1561
+ /* directory+filename is set previously via setConfig directory+filename or url */
1562
+ if( FALSE === ( $filename = $this->getConfig( 'url' )))
1563
+ $filename = $this->getConfig( 'dirfile' );
1564
+ /* READ FILE */
1565
+ if( FALSE === ( $rows = file_get_contents( $filename )))
1566
+ return FALSE; /* err 1 */
1567
+ }
1568
+ elseif( is_array( $unparsedtext ))
1569
+ $rows = implode( '\n'.$nl, $unparsedtext );
1570
+ else
1571
+ $rows = & $unparsedtext;
1572
+ /* identify BEGIN:VCALENDAR, MUST be first row */
1573
+ if( 'BEGIN:VCALENDAR' != strtoupper( substr( $rows, 0, 15 )))
1574
+ return FALSE; /* err 8 */
1575
+ /* fix line folding */
1576
+ $eolchars = array( "\r\n", "\n\r", "\n", "\r" ); // check all line endings
1577
+ $EOLmark = FALSE;
1578
+ foreach( $eolchars as $eolchar ) {
1579
+ if( !$EOLmark && ( FALSE !== strpos( $rows, $eolchar ))) {
1580
+ $rows = str_replace( $eolchar." ", '', $rows );
1581
+ $rows = str_replace( $eolchar."\t", '', $rows );
1582
+ if( $eolchar != $nl )
1583
+ $rows = str_replace( $eolchar, $nl, $rows );
1584
+ $EOLmark = TRUE;
1585
+ }
1586
+ }
1587
+ $tmp = explode( $nl, $rows );
1588
+ $rows = array();
1589
+ foreach( $tmp as $tmpr )
1590
+ if( !empty( $tmpr ))
1591
+ $rows[] = $tmpr;
1592
+ /* skip trailing empty lines */
1593
+ $lix = count( $rows ) - 1;
1594
+ while( empty( $rows[$lix] ) && ( 0 < $lix ))
1595
+ $lix -= 1;
1596
+ /* identify ending END:VCALENDAR row, MUST be last row */
1597
+ if( 'END:VCALENDAR' != strtoupper( substr( $rows[$lix], 0, 13 )))
1598
+ return FALSE; /* err 9 */
1599
+ if( 3 > count( $rows ))
1600
+ return FALSE; /* err 10 */
1601
+ $comp = & $this;
1602
+ $calsync = 0;
1603
+ /* identify components and update unparsed data within component */
1604
+ $config = $this->getConfig();
1605
+ foreach( $rows as $line ) {
1606
+ if( '' == trim( $line ))
1607
+ continue;
1608
+ if( 'BEGIN:VCALENDAR' == strtoupper( substr( $line, 0, 15 ))) {
1609
+ $calsync++;
1610
+ continue;
1611
+ }
1612
+ elseif( 'END:VCALENDAR' == strtoupper( substr( $line, 0, 13 ))) {
1613
+ $calsync--;
1614
+ break;
1615
+ }
1616
+ elseif( 1 != $calsync )
1617
+ return FALSE; /* err 20 */
1618
+ elseif( in_array( strtoupper( substr( $line, 0, 6 )), array( 'END:VE', 'END:VF', 'END:VJ', 'END:VT' ))) {
1619
+ $this->components[] = $comp->copy();
1620
+ continue;
1621
+ }
1622
+
1623
+ if( 'BEGIN:VEVENT' == strtoupper( substr( $line, 0, 12 )))
1624
+ $comp = new vevent( $config );
1625
+ elseif( 'BEGIN:VFREEBUSY' == strtoupper( substr( $line, 0, 15 )))
1626
+ $comp = new vfreebusy( $config );
1627
+ elseif( 'BEGIN:VJOURNAL' == strtoupper( substr( $line, 0, 14 )))
1628
+ $comp = new vjournal( $config );
1629
+ elseif( 'BEGIN:VTODO' == strtoupper( substr( $line, 0, 11 )))
1630
+ $comp = new vtodo( $config );
1631
+ elseif( 'BEGIN:VTIMEZONE' == strtoupper( substr( $line, 0, 15 )))
1632
+ $comp = new vtimezone( $config );
1633
+ else /* update component with unparsed data */
1634
+ $comp->unparsed[] = $line;
1635
+ } // end - foreach( rows.. .
1636
+ unset( $config );
1637
+ /* parse data for calendar (this) object */
1638
+ if( isset( $this->unparsed ) && is_array( $this->unparsed ) && ( 0 < count( $this->unparsed ))) {
1639
+ /* concatenate property values spread over several lines */
1640
+ $lastix = -1;
1641
+ $propnames = array( 'calscale','method','prodid','version','x-' );
1642
+ $proprows = array();
1643
+ foreach( $this->unparsed as $line ) {
1644
+ if( '' == trim( $line ))
1645
+ continue;
1646
+ $newProp = FALSE;
1647
+ foreach ( $propnames as $propname ) {
1648
+ if( $propname == strtolower( substr( $line, 0, strlen( $propname )))) {
1649
+ $newProp = TRUE;
1650
+ break;
1651
+ }
1652
+ }
1653
+ if( $newProp ) {
1654
+ $newProp = FALSE;
1655
+ $lastix++;
1656
+ $proprows[$lastix] = $line;
1657
+ }
1658
+ else
1659
+ $proprows[$lastix] .= '!"#¤%&/()=?'.$line;
1660
+ }
1661
+ foreach( $proprows as $line ) {
1662
+ $line = str_replace( '!"#¤%&/()=? ', '', $line );
1663
+ $line = str_replace( '!"#¤%&/()=?', '', $line );
1664
+ if( '\n' == substr( $line, -2 ))
1665
+ $line = substr( $line, 0, strlen( $line ) - 2 );
1666
+ /* get property name */
1667
+ $cix = $propname = null;
1668
+ for( $cix=0, $clen = strlen( $line ); $cix < $clen; $cix++ ) {
1669
+ if( in_array( $line[$cix], array( ':', ';' )))
1670
+ break;
1671
+ else
1672
+ $propname .= $line[$cix];
1673
+ }
1674
+ /* ignore version/prodid properties */
1675
+ if( in_array( strtoupper( $propname ), array( 'VERSION', 'PRODID' )))
1676
+ continue;
1677
+ $line = substr( $line, $cix);
1678
+ /* separate attributes from value */
1679
+ $attr = array();
1680
+ $attrix = -1;
1681
+ $strlen = strlen( $line );
1682
+ for( $cix=0; $cix < $strlen; $cix++ ) {
1683
+ if(( ':' == $line[$cix] ) &&
1684
+ ( '://' != substr( $line, $cix, 3 )) &&
1685
+ ( !in_array( strtolower( substr( $line, $cix - 3, 4 )), array( 'fax:', 'cid:', 'sms:', 'tel:', 'urn:' ))) &&
1686
+ ( !in_array( strtolower( substr( $line, $cix - 4, 5 )), array( 'crid:', 'news:', 'pres:' ))) &&
1687
+ ( 'mailto:' != strtolower( substr( $line, $cix - 6, 7 )))) {
1688
+ $attrEnd = TRUE;
1689
+ if(( $cix < ( $strlen - 4 )) &&
1690
+ ctype_digit( substr( $line, $cix+1, 4 ))) { // an URI with a (4pos) portnr??
1691
+ for( $c2ix = $cix; 3 < $c2ix; $c2ix-- ) {
1692
+ if( '://' == substr( $line, $c2ix - 2, 3 )) {
1693
+ $attrEnd = FALSE;
1694
+ break; // an URI with a portnr!!
1695
+ }
1696
+ }
1697
+ }
1698
+ if( $attrEnd) {
1699
+ $line = substr( $line, $cix + 1 );
1700
+ break;
1701
+ }
1702
+ }
1703
+ if( ';' == $line[$cix] )
1704
+ $attr[++$attrix] = null;
1705
+ else
1706
+ $attr[$attrix] .= $line[$cix];
1707
+ }
1708
+
1709
+ /* make attributes in array format */
1710
+ $propattr = array();
1711
+ foreach( $attr as $attribute ) {
1712
+ $attrsplit = explode( '=', $attribute, 2 );
1713
+ if( 1 < count( $attrsplit ))
1714
+ $propattr[$attrsplit[0]] = $attrsplit[1];
1715
+ else
1716
+ $propattr[] = $attribute;
1717
+ }
1718
+ /* update Property */
1719
+ if( FALSE !== strpos( $line, ',' )) {
1720
+ $content = explode( ',', $line );
1721
+ $clen = count( $content );
1722
+ for( $cix = 0; $cix < $clen; $cix++ ) {
1723
+ if( "\\" == substr( $content[$cix], -1 )) {
1724
+ $content[$cix] .= ','.$content[$cix + 1];
1725
+ unset( $content[$cix + 1] );
1726
+ $cix++;
1727
+ }
1728
+ }
1729
+ if( 1 < count( $content )) {
1730
+ foreach( $content as $cix => $contentPart )
1731
+ $content[$cix] = calendarComponent::_strunrep( $contentPart );
1732
+ $this->setProperty( $propname, $content, $propattr );
1733
+ continue;
1734
+ }
1735
+ else
1736
+ $line = reset( $content );
1737
+ $line = calendarComponent::_strunrep( $line );
1738
+ }
1739
+ $this->setProperty( $propname, trim( $line ), $propattr );
1740
+ } // end - foreach( $this->unparsed.. .
1741
+ } // end - if( is_array( $this->unparsed.. .
1742
+ unset( $unparsedtext, $rows, $this->unparsed, $proprows );
1743
+ /* parse Components */
1744
+ if( is_array( $this->components ) && ( 0 < count( $this->components ))) {
1745
+ $ckeys = array_keys( $this->components );
1746
+ foreach( $ckeys as $ckey ) {
1747
+ if( !empty( $this->components[$ckey] ) && !empty( $this->components[$ckey]->unparsed )) {
1748
+ $this->components[$ckey]->parse();
1749
+ }
1750
+ }
1751
+ }
1752
+ else
1753
+ return FALSE; /* err 91 or something.. . */
1754
+ return TRUE;
1755
+ }
1756
+ /*********************************************************************************/
1757
+ /**
1758
+ * creates formatted output for calendar object instance
1759
+ *
1760
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
1761
+ * @since 2.8.1 - 2011-03-12
1762
+ * @return string
1763
+ */
1764
+ function createCalendar() {
1765
+ $calendarInit1 = $calendarInit2 = $calendarxCaldecl = $calendarStart = $calendar = null;
1766
+ switch( $this->format ) {
1767
+ case 'xcal':
1768
+ $calendarInit1 = '<?xml version="1.0" encoding="UTF-8"?>'.$this->nl.
1769
+ '<!DOCTYPE iCalendar PUBLIC "-//IETF//DTD XCAL/iCalendar XML//EN"'.$this->nl.
1770
+ '"http://www.ietf.org/internet-drafts/draft-ietf-calsch-many-xcal-01.txt"';
1771
+ $calendarInit2 = '>'.$this->nl;
1772
+ $calendarStart = '<vcalendar';
1773
+ break;
1774
+ default:
1775
+ $calendarStart = 'BEGIN:VCALENDAR'.$this->nl;
1776
+ break;
1777
+ }
1778
+ $calendarStart .= $this->createVersion();
1779
+ $calendarStart .= $this->createProdid();
1780
+ $calendarStart .= $this->createCalscale();
1781
+ $calendarStart .= $this->createMethod();
1782
+ switch( $this->format ) {
1783
+ case 'xcal':
1784
+ $nlstrlen = strlen( $this->nl );
1785
+ if( $this->nl == substr( $calendarStart, ( 0 - $nlstrlen )))
1786
+ $calendarStart = substr( $calendarStart, 0, ( strlen( $calendarStart ) - $nlstrlen ));
1787
+ $calendarStart .= '>'.$this->nl;
1788
+ break;
1789
+ default:
1790
+ break;
1791
+ }
1792
+ $calendar .= $this->createXprop();
1793
+ foreach( $this->components as $component ) {
1794
+ if( empty( $component )) continue;
1795
+ $component->setConfig( $this->getConfig(), FALSE, TRUE );
1796
+ $calendar .= $component->createComponent( $this->xcaldecl );
1797
+ }
1798
+ if(( 0 < count( $this->xcaldecl )) && ( 'xcal' == $this->format )) { // xCal only
1799
+ $calendarInit1 .= $this->nl.'['.$this->nl;
1800
+ $old_xcaldecl = array();
1801
+ foreach( $this->xcaldecl as $declix => $declPart ) {
1802
+ if(( 0 < count( $old_xcaldecl)) &&
1803
+ ( in_array( $declPart['uri'], $old_xcaldecl['uri'] )) &&
1804
+ ( in_array( $declPart['external'], $old_xcaldecl['external'] )))
1805
+ continue; // no duplicate uri and ext. references
1806
+ $calendarxCaldecl .= '<!';
1807
+ foreach( $declPart as $declKey => $declValue ) {
1808
+ switch( $declKey ) { // index
1809
+ case 'xmldecl': // no 1
1810
+ $calendarxCaldecl .= $declValue.' ';
1811
+ break;
1812
+ case 'uri': // no 2
1813
+ $calendarxCaldecl .= $declValue.' ';
1814
+ $old_xcaldecl['uri'][] = $declValue;
1815
+ break;
1816
+ case 'ref': // no 3
1817
+ $calendarxCaldecl .= $declValue.' ';
1818
+ break;
1819
+ case 'external': // no 4
1820
+ $calendarxCaldecl .= '"'.$declValue.'" ';
1821
+ $old_xcaldecl['external'][] = $declValue;
1822
+ break;
1823
+ case 'type': // no 5
1824
+ $calendarxCaldecl .= $declValue.' ';
1825
+ break;
1826
+ case 'type2': // no 6
1827
+ $calendarxCaldecl .= $declValue;
1828
+ break;
1829
+ }
1830
+ }
1831
+ $calendarxCaldecl .= '>'.$this->nl;
1832
+ }
1833
+ $calendarInit2 = ']'.$calendarInit2;
1834
+ }
1835
+ switch( $this->format ) {
1836
+ case 'xcal':
1837
+ $calendar .= '</vcalendar>'.$this->nl;
1838
+ break;
1839
+ default:
1840
+ $calendar .= 'END:VCALENDAR'.$this->nl;
1841
+ break;
1842
+ }
1843
+ return $calendarInit1.$calendarxCaldecl.$calendarInit2.$calendarStart.$calendar;
1844
+ }
1845
+ /**
1846
+ * a HTTP redirect header is sent with created, updated and/or parsed calendar
1847
+ *
1848
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
1849
+ * @since 2.9.12 - 2011-07-13
1850
+ * @param bool $utf8Encode
1851
+ * @param bool $gzip
1852
+ * @return redirect
1853
+ */
1854
+ function returnCalendar( $utf8Encode=FALSE, $gzip=FALSE ) {
1855
+ $filename = $this->getConfig( 'filename' );
1856
+ $output = $this->createCalendar();
1857
+ if( $utf8Encode )
1858
+ $output = utf8_encode( $output );
1859
+ if( $gzip ) {
1860
+ $output = gzencode( $output, 9 );
1861
+ header( 'Content-Encoding: gzip');
1862
+ header( 'Vary: *');
1863
+ }
1864
+ $filesize = strlen( $output );
1865
+ if( 'xcal' == $this->format )
1866
+ header( 'Content-Type: application/calendar+xml; charset=utf-8' );
1867
+ else
1868
+ header( 'Content-Type: text/calendar; charset=utf-8' );
1869
+ header( 'Content-Length: '.$filesize );
1870
+ header( 'Content-Disposition: attachment; filename="'.$filename.'"' );
1871
+ header( 'Cache-Control: max-age=10' );
1872
+ echo $output;
1873
+ die();
1874
+ }
1875
+ /**
1876
+ * save content in a file
1877
+ *
1878
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
1879
+ * @since 2.2.12 - 2007-12-30
1880
+ * @param string $directory optional
1881
+ * @param string $filename optional
1882
+ * @param string $delimiter optional
1883
+ * @return bool
1884
+ */
1885
+ function saveCalendar( $directory=FALSE, $filename=FALSE, $delimiter=FALSE ) {
1886
+ if( $directory )
1887
+ $this->setConfig( 'directory', $directory );
1888
+ if( $filename )
1889
+ $this->setConfig( 'filename', $filename );
1890
+ if( $delimiter && ($delimiter != DIRECTORY_SEPARATOR ))
1891
+ $this->setConfig( 'delimiter', $delimiter );
1892
+ if( FALSE === ( $dirfile = $this->getConfig( 'url' )))
1893
+ $dirfile = $this->getConfig( 'dirfile' );
1894
+ $iCalFile = @fopen( $dirfile, 'w' );
1895
+ if( $iCalFile ) {
1896
+ if( FALSE === fwrite( $iCalFile, $this->createCalendar() ))
1897
+ return FALSE;
1898
+ fclose( $iCalFile );
1899
+ return TRUE;
1900
+ }
1901
+ else
1902
+ return FALSE;
1903
+ }
1904
+ /**
1905
+ * if recent version of calendar file exists (default one hour), an HTTP redirect header is sent
1906
+ * else FALSE is returned
1907
+ *
1908
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
1909
+ * @since 2.2.12 - 2007-10-28
1910
+ * @param string $directory optional alt. int timeout
1911
+ * @param string $filename optional
1912
+ * @param string $delimiter optional
1913
+ * @param int timeout optional, default 3600 sec
1914
+ * @return redirect/FALSE
1915
+ */
1916
+ function useCachedCalendar( $directory=FALSE, $filename=FALSE, $delimiter=FALSE, $timeout=3600) {
1917
+ if ( $directory && ctype_digit( (string) $directory ) && !$filename ) {
1918
+ $timeout = (int) $directory;
1919
+ $directory = FALSE;
1920
+ }
1921
+ if( $directory )
1922
+ $this->setConfig( 'directory', $directory );
1923
+ if( $filename )
1924
+ $this->setConfig( 'filename', $filename );
1925
+ if( $delimiter && ( $delimiter != DIRECTORY_SEPARATOR ))
1926
+ $this->setConfig( 'delimiter', $delimiter );
1927
+ $filesize = $this->getConfig( 'filesize' );
1928
+ if( 0 >= $filesize )
1929
+ return FALSE;
1930
+ $dirfile = $this->getConfig( 'dirfile' );
1931
+ if( time() - filemtime( $dirfile ) < $timeout) {
1932
+ clearstatcache();
1933
+ $dirfile = $this->getConfig( 'dirfile' );
1934
+ $filename = $this->getConfig( 'filename' );
1935
+ // if( headers_sent( $filename, $linenum ))
1936
+ // die( "Headers already sent in $filename on line $linenum\n" );
1937
+ if( 'xcal' == $this->format )
1938
+ header( 'Content-Type: application/calendar+xml; charset=utf-8' );
1939
+ else
1940
+ header( 'Content-Type: text/calendar; charset=utf-8' );
1941
+ header( 'Content-Length: '.$filesize );
1942
+ header( 'Content-Disposition: attachment; filename="'.$filename.'"' );
1943
+ header( 'Cache-Control: max-age=10' );
1944
+ $fp = @fopen( $dirfile, 'r' );
1945
+ if( $fp ) {
1946
+ fpassthru( $fp );
1947
+ fclose( $fp );
1948
+ }
1949
+ die();
1950
+ }
1951
+ else
1952
+ return FALSE;
1953
+ }
1954
+ }
1955
+ /*********************************************************************************/
1956
+ /*********************************************************************************/
1957
+ /**
1958
+ * abstract class for calendar components
1959
+ *
1960
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
1961
+ * @since 2.9.6 - 2011-05-14
1962
+ */
1963
+ class calendarComponent {
1964
+ // component property variables
1965
+ var $uid;
1966
+ var $dtstamp;
1967
+
1968
+ // component config variables
1969
+ var $allowEmpty;
1970
+ var $language;
1971
+ var $nl;
1972
+ var $unique_id;
1973
+ var $format;
1974
+ var $objName; // created automatically at instance creation
1975
+ var $dtzid; // default (local) timezone
1976
+ // component internal variables
1977
+ var $componentStart1;
1978
+ var $componentStart2;
1979
+ var $componentEnd1;
1980
+ var $componentEnd2;
1981
+ var $elementStart1;
1982
+ var $elementStart2;
1983
+ var $elementEnd1;
1984
+ var $elementEnd2;
1985
+ var $intAttrDelimiter;
1986
+ var $attributeDelimiter;
1987
+ var $valueInit;
1988
+ // component xCal declaration container
1989
+ var $xcaldecl;
1990
+ /**
1991
+ * constructor for calendar component object
1992
+ *
1993
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
1994
+ * @since 2.9.6 - 2011-05-17
1995
+ */
1996
+ function calendarComponent() {
1997
+ $this->objName = ( isset( $this->timezonetype )) ?
1998
+ strtolower( $this->timezonetype ) : get_class ( $this );
1999
+ $this->uid = array();
2000
+ $this->dtstamp = array();
2001
+
2002
+ $this->language = null;
2003
+ $this->nl = null;
2004
+ $this->unique_id = null;
2005
+ $this->format = null;
2006
+ $this->dtzid = null;
2007
+ $this->allowEmpty = TRUE;
2008
+ $this->xcaldecl = array();
2009
+
2010
+ $this->_createFormat();
2011
+ $this->_makeDtstamp();
2012
+ }
2013
+ /*********************************************************************************/
2014
+ /**
2015
+ * Property Name: ACTION
2016
+ */
2017
+ /**
2018
+ * creates formatted output for calendar component property action
2019
+ *
2020
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2021
+ * @since 2.4.8 - 2008-10-22
2022
+ * @return string
2023
+ */
2024
+ function createAction() {
2025
+ if( empty( $this->action )) return FALSE;
2026
+ if( empty( $this->action['value'] ))
2027
+ return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'ACTION' ) : FALSE;
2028
+ $attributes = $this->_createParams( $this->action['params'] );
2029
+ return $this->_createElement( 'ACTION', $attributes, $this->action['value'] );
2030
+ }
2031
+ /**
2032
+ * set calendar component property action
2033
+ *
2034
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2035
+ * @since 2.4.8 - 2008-11-04
2036
+ * @param string $value "AUDIO" / "DISPLAY" / "EMAIL" / "PROCEDURE"
2037
+ * @param mixed $params
2038
+ * @return bool
2039
+ */
2040
+ function setAction( $value, $params=FALSE ) {
2041
+ if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = null; else return FALSE;
2042
+ $this->action = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
2043
+ return TRUE;
2044
+ }
2045
+ /*********************************************************************************/
2046
+ /**
2047
+ * Property Name: ATTACH
2048
+ */
2049
+ /**
2050
+ * creates formatted output for calendar component property attach
2051
+ *
2052
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2053
+ * @since 0.9.7 - 2006-11-23
2054
+ * @return string
2055
+ */
2056
+ function createAttach() {
2057
+ if( empty( $this->attach )) return FALSE;
2058
+ $output = null;
2059
+ foreach( $this->attach as $attachPart ) {
2060
+ if(! empty( $attachPart['value'] )) {
2061
+ $attributes = $this->_createParams( $attachPart['params'] );
2062
+ $output .= $this->_createElement( 'ATTACH', $attributes, $attachPart['value'] );
2063
+ }
2064
+ elseif( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( 'ATTACH' );
2065
+ }
2066
+ return $output;
2067
+ }
2068
+ /**
2069
+ * set calendar component property attach
2070
+ *
2071
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2072
+ * @since 2.5.1 - 2008-11-06
2073
+ * @param string $value
2074
+ * @param array $params, optional
2075
+ * @param integer $index, optional
2076
+ * @return bool
2077
+ */
2078
+ function setAttach( $value, $params=FALSE, $index=FALSE ) {
2079
+ if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = null; else return FALSE;
2080
+ iCalUtilityFunctions::_setMval( $this->attach, $value, $params, FALSE, $index );
2081
+ return TRUE;
2082
+ }
2083
+ /*********************************************************************************/
2084
+ /**
2085
+ * Property Name: ATTENDEE
2086
+ */
2087
+ /**
2088
+ * creates formatted output for calendar component property attendee
2089
+ *
2090
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2091
+ * @since 2.9.8 - 2011-05-30
2092
+ * @return string
2093
+ */
2094
+ function createAttendee() {
2095
+ if( empty( $this->attendee )) return FALSE;
2096
+ $output = null;
2097
+ foreach( $this->attendee as $attendeePart ) { // start foreach 1
2098
+ if( empty( $attendeePart['value'] )) {
2099
+ if( $this->getConfig( 'allowEmpty' ))
2100
+ $output .= $this->_createElement( 'ATTENDEE' );
2101
+ continue;
2102
+ }
2103
+ $attendee1 = $attendee2 = null;
2104
+ foreach( $attendeePart as $paramlabel => $paramvalue ) { // start foreach 2
2105
+ if( 'value' == $paramlabel )
2106
+ $attendee2 .= $paramvalue;
2107
+ elseif(( 'params' == $paramlabel ) && ( is_array( $paramvalue ))) { // start elseif
2108
+ // set attenddee parameters in rfc2445 order
2109
+ if( isset( $paramvalue['CUTYPE'] ))
2110
+ $attendee1 .= $this->intAttrDelimiter.'CUTYPE='.$paramvalue['CUTYPE'];
2111
+ if( isset( $paramvalue['MEMBER'] )) {
2112
+ $attendee1 .= $this->intAttrDelimiter.'MEMBER=';
2113
+ foreach( $paramvalue['MEMBER'] as $cix => $opv )
2114
+ $attendee1 .= ( $cix ) ? ', "'.$opv.'"' : '"'.$opv.'"' ;
2115
+ }
2116
+ if( isset( $paramvalue['ROLE'] ))
2117
+ $attendee1 .= $this->intAttrDelimiter.'ROLE='.$paramvalue['ROLE'];
2118
+ if( isset( $paramvalue['PARTSTAT'] ))
2119
+ $attendee1 .= $this->intAttrDelimiter.'PARTSTAT='.$paramvalue['PARTSTAT'];
2120
+ if( isset( $paramvalue['RSVP'] ))
2121
+ $attendee1 .= $this->intAttrDelimiter.'RSVP='.$paramvalue['RSVP'];
2122
+ if( isset( $paramvalue['DELEGATED-TO'] )) {
2123
+ $attendee1 .= $this->intAttrDelimiter.'DELEGATED-TO=';
2124
+ foreach( $paramvalue['DELEGATED-TO'] as $cix => $opv )
2125
+ $attendee1 .= ( $cix ) ? ', "'.$opv.'"' : '"'.$opv.'"' ;
2126
+ }
2127
+ if( isset( $paramvalue['DELEGATED-FROM'] )) {
2128
+ $attendee1 .= $this->intAttrDelimiter.'DELEGATED-FROM=';
2129
+ foreach( $paramvalue['DELEGATED-FROM'] as $cix => $opv )
2130
+ $attendee1 .= ( $cix ) ? ', "'.$opv.'"' : '"'.$opv.'"' ;
2131
+ }
2132
+ if( isset( $paramvalue['SENT-BY'] ))
2133
+ $attendee1 .= $this->intAttrDelimiter.'SENT-BY="'.$paramvalue['SENT-BY'].'"';
2134
+ if( isset( $paramvalue['CN'] ))
2135
+ $attendee1 .= $this->intAttrDelimiter.'CN="'.$paramvalue['CN'].'"';
2136
+ if( isset( $paramvalue['DIR'] ))
2137
+ $attendee1 .= $this->intAttrDelimiter.'DIR="'.$paramvalue['DIR'].'"';
2138
+ if( isset( $paramvalue['LANGUAGE'] ))
2139
+ $attendee1 .= $this->intAttrDelimiter.'LANGUAGE='.$paramvalue['LANGUAGE'];
2140
+ $xparams = array();
2141
+ foreach( $paramvalue as $optparamlabel => $optparamvalue ) { // start foreach 3
2142
+ if( ctype_digit( (string) $optparamlabel )) {
2143
+ $xparams[] = $optparamvalue;
2144
+ continue;
2145
+ }
2146
+ if( !in_array( $optparamlabel, array( 'CUTYPE', 'MEMBER', 'ROLE', 'PARTSTAT', 'RSVP', 'DELEGATED-TO', 'DELEGATED-FROM', 'SENT-BY', 'CN', 'DIR', 'LANGUAGE' )))
2147
+ $xparams[$optparamlabel] = $optparamvalue;
2148
+ } // end foreach 3
2149
+ ksort( $xparams, SORT_STRING );
2150
+ foreach( $xparams as $paramKey => $paramValue ) {
2151
+ if( ctype_digit( (string) $paramKey ))
2152
+ $attendee1 .= $this->intAttrDelimiter.$paramValue;
2153
+ else
2154
+ $attendee1 .= $this->intAttrDelimiter."$paramKey=$paramValue";
2155
+ } // end foreach 3
2156
+ } // end elseif(( 'params' == $paramlabel ) && ( is_array( $paramvalue )))
2157
+ } // end foreach 2
2158
+ $output .= $this->_createElement( 'ATTENDEE', $attendee1, $attendee2 );
2159
+ } // end foreach 1
2160
+ return $output;
2161
+ }
2162
+ /**
2163
+ * set calendar component property attach
2164
+ *
2165
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2166
+ * @since 2.6.34 - 2010-12-18
2167
+ * @param string $value
2168
+ * @param array $params, optional
2169
+ * @param integer $index, optional
2170
+ * @return bool
2171
+ */
2172
+ function setAttendee( $value, $params=FALSE, $index=FALSE ) {
2173
+ if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = null; else return FALSE;
2174
+ // ftp://, http://, mailto:, file://, gopher://, news:, nntp://, telnet://, wais://, prospero:// may exist.. . also in params
2175
+ if( FALSE !== ( $pos = strpos( substr( $value, 0, 9 ), ':' )))
2176
+ $value = strtoupper( substr( $value, 0, $pos )).substr( $value, $pos );
2177
+ elseif( !empty( $value ))
2178
+ $value = 'MAILTO:'.$value;
2179
+ $params2 = array();
2180
+ if( is_array($params )) {
2181
+ $optarrays = array();
2182
+ foreach( $params as $optparamlabel => $optparamvalue ) {
2183
+ $optparamlabel = strtoupper( $optparamlabel );
2184
+ switch( $optparamlabel ) {
2185
+ case 'MEMBER':
2186
+ case 'DELEGATED-TO':
2187
+ case 'DELEGATED-FROM':
2188
+ if( !is_array( $optparamvalue ))
2189
+ $optparamvalue = array( $optparamvalue );
2190
+ foreach( $optparamvalue as $part ) {
2191
+ $part = trim( $part );
2192
+ if(( '"' == substr( $part, 0, 1 )) &&
2193
+ ( '"' == substr( $part, -1 )))
2194
+ $part = substr( $part, 1, ( strlen( $part ) - 2 ));
2195
+ if( 'mailto:' != strtolower( substr( $part, 0, 7 )))
2196
+ $part = "MAILTO:$part";
2197
+ else
2198
+ $part = 'MAILTO:'.substr( $part, 7 );
2199
+ $optarrays[$optparamlabel][] = $part;
2200
+ }
2201
+ break;
2202
+ default:
2203
+ if(( '"' == substr( $optparamvalue, 0, 1 )) &&
2204
+ ( '"' == substr( $optparamvalue, -1 )))
2205
+ $optparamvalue = substr( $optparamvalue, 1, ( strlen( $optparamvalue ) - 2 ));
2206
+ if( 'SENT-BY' == $optparamlabel ) {
2207
+ if( 'mailto:' != strtolower( substr( $optparamvalue, 0, 7 )))
2208
+ $optparamvalue = "MAILTO:$optparamvalue";
2209
+ else
2210
+ $optparamvalue = 'MAILTO:'.substr( $optparamvalue, 7 );
2211
+ }
2212
+ $params2[$optparamlabel] = $optparamvalue;
2213
+ break;
2214
+ } // end switch( $optparamlabel.. .
2215
+ } // end foreach( $optparam.. .
2216
+ foreach( $optarrays as $optparamlabel => $optparams )
2217
+ $params2[$optparamlabel] = $optparams;
2218
+ }
2219
+ // remove defaults
2220
+ iCalUtilityFunctions::_existRem( $params2, 'CUTYPE', 'INDIVIDUAL' );
2221
+ iCalUtilityFunctions::_existRem( $params2, 'PARTSTAT', 'NEEDS-ACTION' );
2222
+ iCalUtilityFunctions::_existRem( $params2, 'ROLE', 'REQ-PARTICIPANT' );
2223
+ iCalUtilityFunctions::_existRem( $params2, 'RSVP', 'FALSE' );
2224
+ // check language setting
2225
+ if( isset( $params2['CN' ] )) {
2226
+ $lang = $this->getConfig( 'language' );
2227
+ if( !isset( $params2['LANGUAGE' ] ) && !empty( $lang ))
2228
+ $params2['LANGUAGE' ] = $lang;
2229
+ }
2230
+ iCalUtilityFunctions::_setMval( $this->attendee, $value, $params2, FALSE, $index );
2231
+ return TRUE;
2232
+ }
2233
+ /*********************************************************************************/
2234
+ /**
2235
+ * Property Name: CATEGORIES
2236
+ */
2237
+ /**
2238
+ * creates formatted output for calendar component property categories
2239
+ *
2240
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2241
+ * @since 2.4.8 - 2008-10-22
2242
+ * @return string
2243
+ */
2244
+ function createCategories() {
2245
+ if( empty( $this->categories )) return FALSE;
2246
+ $output = null;
2247
+ foreach( $this->categories as $category ) {
2248
+ if( empty( $category['value'] )) {
2249
+ if ( $this->getConfig( 'allowEmpty' ))
2250
+ $output .= $this->_createElement( 'CATEGORIES' );
2251
+ continue;
2252
+ }
2253
+ $attributes = $this->_createParams( $category['params'], array( 'LANGUAGE' ));
2254
+ if( is_array( $category['value'] )) {
2255
+ foreach( $category['value'] as $cix => $categoryPart )
2256
+ $category['value'][$cix] = $this->_strrep( $categoryPart );
2257
+ $content = implode( ',', $category['value'] );
2258
+ }
2259
+ else
2260
+ $content = $this->_strrep( $category['value'] );
2261
+ $output .= $this->_createElement( 'CATEGORIES', $attributes, $content );
2262
+ }
2263
+ return $output;
2264
+ }
2265
+ /**
2266
+ * set calendar component property categories
2267
+ *
2268
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2269
+ * @since 2.5.1 - 2008-11-06
2270
+ * @param mixed $value
2271
+ * @param array $params, optional
2272
+ * @param integer $index, optional
2273
+ * @return bool
2274
+ */
2275
+ function setCategories( $value, $params=FALSE, $index=FALSE ) {
2276
+ if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = null; else return FALSE;
2277
+ iCalUtilityFunctions::_setMval( $this->categories, $value, $params, FALSE, $index );
2278
+ return TRUE;
2279
+ }
2280
+ /*********************************************************************************/
2281
+ /**
2282
+ * Property Name: CLASS
2283
+ */
2284
+ /**
2285
+ * creates formatted output for calendar component property class
2286
+ *
2287
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2288
+ * @since 0.9.7 - 2006-11-20
2289
+ * @return string
2290
+ */
2291
+ function createClass() {
2292
+ if( empty( $this->class )) return FALSE;
2293
+ if( empty( $this->class['value'] ))
2294
+ return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'CLASS' ) : FALSE;
2295
+ $attributes = $this->_createParams( $this->class['params'] );
2296
+ return $this->_createElement( 'CLASS', $attributes, $this->class['value'] );
2297
+ }
2298
+ /**
2299
+ * set calendar component property class
2300
+ *
2301
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2302
+ * @since 2.4.8 - 2008-11-04
2303
+ * @param string $value "PUBLIC" / "PRIVATE" / "CONFIDENTIAL" / iana-token / x-name
2304
+ * @param array $params optional
2305
+ * @return bool
2306
+ */
2307
+ function setClass( $value, $params=FALSE ) {
2308
+ if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = null; else return FALSE;
2309
+ $this->class = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
2310
+ return TRUE;
2311
+ }
2312
+ /*********************************************************************************/
2313
+ /**
2314
+ * Property Name: COMMENT
2315
+ */
2316
+ /**
2317
+ * creates formatted output for calendar component property comment
2318
+ *
2319
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2320
+ * @since 2.4.8 - 2008-10-22
2321
+ * @return string
2322
+ */
2323
+ function createComment() {
2324
+ if( empty( $this->comment )) return FALSE;
2325
+ $output = null;
2326
+ foreach( $this->comment as $commentPart ) {
2327
+ if( empty( $commentPart['value'] )) {
2328
+ if( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( 'COMMENT' );
2329
+ continue;
2330
+ }
2331
+ $attributes = $this->_createParams( $commentPart['params'], array( 'ALTREP', 'LANGUAGE' ));
2332
+ $content = $this->_strrep( $commentPart['value'] );
2333
+ $output .= $this->_createElement( 'COMMENT', $attributes, $content );
2334
+ }
2335
+ return $output;
2336
+ }
2337
+ /**
2338
+ * set calendar component property comment
2339
+ *
2340
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2341
+ * @since 2.5.1 - 2008-11-06
2342
+ * @param string $value
2343
+ * @param array $params, optional
2344
+ * @param integer $index, optional
2345
+ * @return bool
2346
+ */
2347
+ function setComment( $value, $params=FALSE, $index=FALSE ) {
2348
+ if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = null; else return FALSE;
2349
+ iCalUtilityFunctions::_setMval( $this->comment, $value, $params, FALSE, $index );
2350
+ return TRUE;
2351
+ }
2352
+ /*********************************************************************************/
2353
+ /**
2354
+ * Property Name: COMPLETED
2355
+ */
2356
+ /**
2357
+ * creates formatted output for calendar component property completed
2358
+ *
2359
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2360
+ * @since 2.4.8 - 2008-10-22
2361
+ * @return string
2362
+ */
2363
+ function createCompleted( ) {
2364
+ if( empty( $this->completed )) return FALSE;
2365
+ if( !isset( $this->completed['value']['year'] ) &&
2366
+ !isset( $this->completed['value']['month'] ) &&
2367
+ !isset( $this->completed['value']['day'] ) &&
2368
+ !isset( $this->completed['value']['hour'] ) &&
2369
+ !isset( $this->completed['value']['min'] ) &&
2370
+ !isset( $this->completed['value']['sec'] ))
2371
+ if( $this->getConfig( 'allowEmpty' ))
2372
+ return $this->_createElement( 'COMPLETED' );
2373
+ else return FALSE;
2374
+ $formatted = iCalUtilityFunctions::_format_date_time( $this->completed['value'], 7 );
2375
+ $attributes = $this->_createParams( $this->completed['params'] );
2376
+ return $this->_createElement( 'COMPLETED', $attributes, $formatted );
2377
+ }
2378
+ /**
2379
+ * set calendar component property completed
2380
+ *
2381
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2382
+ * @since 2.4.8 - 2008-10-23
2383
+ * @param mixed $year
2384
+ * @param mixed $month optional
2385
+ * @param int $day optional
2386
+ * @param int $hour optional
2387
+ * @param int $min optional
2388
+ * @param int $sec optional
2389
+ * @param array $params optional
2390
+ * @return bool
2391
+ */
2392
+ function setCompleted( $year, $month=FALSE, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $params=FALSE ) {
2393
+ if( empty( $year )) {
2394
+ if( $this->getConfig( 'allowEmpty' )) {
2395
+ $this->completed = array( 'value' => null, 'params' => iCalUtilityFunctions::_setParams( $params ));
2396
+ return TRUE;
2397
+ }
2398
+ else
2399
+ return FALSE;
2400
+ }
2401
+ $this->completed = iCalUtilityFunctions::_setDate2( $year, $month, $day, $hour, $min, $sec, $params );
2402
+ return TRUE;
2403
+ }
2404
+ /*********************************************************************************/
2405
+ /**
2406
+ * Property Name: CONTACT
2407
+ */
2408
+ /**
2409
+ * creates formatted output for calendar component property contact
2410
+ *
2411
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2412
+ * @since 2.4.8 - 2008-10-23
2413
+ * @return string
2414
+ */
2415
+ function createContact() {
2416
+ if( empty( $this->contact )) return FALSE;
2417
+ $output = null;
2418
+ foreach( $this->contact as $contact ) {
2419
+ if( !empty( $contact['value'] )) {
2420
+ $attributes = $this->_createParams( $contact['params'], array( 'ALTREP', 'LANGUAGE' ));
2421
+ $content = $this->_strrep( $contact['value'] );
2422
+ $output .= $this->_createElement( 'CONTACT', $attributes, $content );
2423
+ }
2424
+ elseif( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( 'CONTACT' );
2425
+ }
2426
+ return $output;
2427
+ }
2428
+ /**
2429
+ * set calendar component property contact
2430
+ *
2431
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2432
+ * @since 2.5.1 - 2008-11-05
2433
+ * @param string $value
2434
+ * @param array $params, optional
2435
+ * @param integer $index, optional
2436
+ * @return bool
2437
+ */
2438
+ function setContact( $value, $params=FALSE, $index=FALSE ) {
2439
+ if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = null; else return FALSE;
2440
+ iCalUtilityFunctions::_setMval( $this->contact, $value, $params, FALSE, $index );
2441
+ return TRUE;
2442
+ }
2443
+ /*********************************************************************************/
2444
+ /**
2445
+ * Property Name: CREATED
2446
+ */
2447
+ /**
2448
+ * creates formatted output for calendar component property created
2449
+ *
2450
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2451
+ * @since 2.4.8 - 2008-10-21
2452
+ * @return string
2453
+ */
2454
+ function createCreated() {
2455
+ if( empty( $this->created )) return FALSE;
2456
+ $formatted = iCalUtilityFunctions::_format_date_time( $this->created['value'], 7 );
2457
+ $attributes = $this->_createParams( $this->created['params'] );
2458
+ return $this->_createElement( 'CREATED', $attributes, $formatted );
2459
+ }
2460
+ /**
2461
+ * set calendar component property created
2462
+ *
2463
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2464
+ * @since 2.4.8 - 2008-10-23
2465
+ * @param mixed $year optional
2466
+ * @param mixed $month optional
2467
+ * @param int $day optional
2468
+ * @param int $hour optional
2469
+ * @param int $min optional
2470
+ * @param int $sec optional
2471
+ * @param mixed $params optional
2472
+ * @return bool
2473
+ */
2474
+ function setCreated( $year=FALSE, $month=FALSE, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $params=FALSE ) {
2475
+ if( !isset( $year )) {
2476
+ $year = date('Ymd\THis', mktime( date( 'H' ), date( 'i' ), date( 's' ) - date( 'Z'), date( 'm' ), date( 'd' ), date( 'Y' )));
2477
+ }
2478
+ $this->created = iCalUtilityFunctions::_setDate2( $year, $month, $day, $hour, $min, $sec, $params );
2479
+ return TRUE;
2480
+ }
2481
+ /*********************************************************************************/
2482
+ /**
2483
+ * Property Name: DESCRIPTION
2484
+ */
2485
+ /**
2486
+ * creates formatted output for calendar component property description
2487
+ *
2488
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2489
+ * @since 2.4.8 - 2008-10-22
2490
+ * @return string
2491
+ */
2492
+ function createDescription() {
2493
+ if( empty( $this->description )) return FALSE;
2494
+ $output = null;
2495
+ foreach( $this->description as $description ) {
2496
+ if( !empty( $description['value'] )) {
2497
+ $attributes = $this->_createParams( $description['params'], array( 'ALTREP', 'LANGUAGE' ));
2498
+ $content = $this->_strrep( $description['value'] );
2499
+ $output .= $this->_createElement( 'DESCRIPTION', $attributes, $content );
2500
+ }
2501
+ elseif( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( 'DESCRIPTION' );
2502
+ }
2503
+ return $output;
2504
+ }
2505
+ /**
2506
+ * set calendar component property description
2507
+ *
2508
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2509
+ * @since 2.6.24 - 2010-11-06
2510
+ * @param string $value
2511
+ * @param array $params, optional
2512
+ * @param integer $index, optional
2513
+ * @return bool
2514
+ */
2515
+ function setDescription( $value, $params=FALSE, $index=FALSE ) {
2516
+ if( empty( $value )) { if( $this->getConfig( 'allowEmpty' )) $value = null; else return FALSE; }
2517
+ if( 'vjournal' != $this->objName )
2518
+ $index = 1;
2519
+ iCalUtilityFunctions::_setMval( $this->description, $value, $params, FALSE, $index );
2520
+ return TRUE;
2521
+ }
2522
+ /*********************************************************************************/
2523
+ /**
2524
+ * Property Name: DTEND
2525
+ */
2526
+ /**
2527
+ * creates formatted output for calendar component property dtend
2528
+ *
2529
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2530
+ * @since 2.9.6 - 2011-05-14
2531
+ * @return string
2532
+ */
2533
+ function createDtend() {
2534
+ if( empty( $this->dtend )) return FALSE;
2535
+ if( !isset( $this->dtend['value']['year'] ) &&
2536
+ !isset( $this->dtend['value']['month'] ) &&
2537
+ !isset( $this->dtend['value']['day'] ) &&
2538
+ !isset( $this->dtend['value']['hour'] ) &&
2539
+ !isset( $this->dtend['value']['min'] ) &&
2540
+ !isset( $this->dtend['value']['sec'] ))
2541
+ if( $this->getConfig( 'allowEmpty' ))
2542
+ return $this->_createElement( 'DTEND' );
2543
+ else return FALSE;
2544
+ $formatted = iCalUtilityFunctions::_format_date_time( $this->dtend['value'] );
2545
+ if(( FALSE !== ( $tzid = $this->getConfig( 'TZID' ))) &&
2546
+ ( !isset( $this->dtend['params']['VALUE'] ) || ( $this->dtend['params']['VALUE'] != 'DATE' )) &&
2547
+ !isset( $this->dtend['params']['TZID'] ))
2548
+ $this->dtend['params']['TZID'] = $tzid;
2549
+ $attributes = $this->_createParams( $this->dtend['params'] );
2550
+ return $this->_createElement( 'DTEND', $attributes, $formatted );
2551
+ }
2552
+ /**
2553
+ * set calendar component property dtend
2554
+ *
2555
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2556
+ * @since 2.9.6 - 2011-05-14
2557
+ * @param mixed $year
2558
+ * @param mixed $month optional
2559
+ * @param int $day optional
2560
+ * @param int $hour optional
2561
+ * @param int $min optional
2562
+ * @param int $sec optional
2563
+ * @param string $tz optional
2564
+ * @param array params optional
2565
+ * @return bool
2566
+ */
2567
+ function setDtend( $year, $month=FALSE, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $tz=FALSE, $params=FALSE ) {
2568
+ if( empty( $year )) {
2569
+ if( $this->getConfig( 'allowEmpty' )) {
2570
+ $this->dtend = array( 'value' => null, 'params' => iCalUtilityFunctions::_setParams( $params ));
2571
+ return TRUE;
2572
+ }
2573
+ else
2574
+ return FALSE;
2575
+ }
2576
+ $this->dtend = iCalUtilityFunctions::_setDate( $year, $month, $day, $hour, $min, $sec, $tz, $params, null, null, $this->getConfig( 'TZID' ));
2577
+ return TRUE;
2578
+ }
2579
+ /*********************************************************************************/
2580
+ /**
2581
+ * Property Name: DTSTAMP
2582
+ */
2583
+ /**
2584
+ * creates formatted output for calendar component property dtstamp
2585
+ *
2586
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2587
+ * @since 2.4.4 - 2008-03-07
2588
+ * @return string
2589
+ */
2590
+ function createDtstamp() {
2591
+ if( !isset( $this->dtstamp['value']['year'] ) &&
2592
+ !isset( $this->dtstamp['value']['month'] ) &&
2593
+ !isset( $this->dtstamp['value']['day'] ) &&
2594
+ !isset( $this->dtstamp['value']['hour'] ) &&
2595
+ !isset( $this->dtstamp['value']['min'] ) &&
2596
+ !isset( $this->dtstamp['value']['sec'] ))
2597
+ $this->_makeDtstamp();
2598
+ $formatted = iCalUtilityFunctions::_format_date_time( $this->dtstamp['value'], 7 );
2599
+ $attributes = $this->_createParams( $this->dtstamp['params'] );
2600
+ return $this->_createElement( 'DTSTAMP', $attributes, $formatted );
2601
+ }
2602
+ /**
2603
+ * computes datestamp for calendar component object instance dtstamp
2604
+ *
2605
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2606
+ * @since 2.6.25 - 2010-11-09
2607
+ * @return void
2608
+ */
2609
+ function _makeDtstamp() {
2610
+ $d = mktime( date('H'), date('m'), (date('s') - date( 'Z' )), date('m'), date('d'), date('Y'));
2611
+ $this->dtstamp['value'] = array( 'year' => date( 'Y', $d )
2612
+ , 'month' => date( 'm', $d )
2613
+ , 'day' => date( 'd', $d )
2614
+ , 'hour' => date( 'H', $d )
2615
+ , 'min' => date( 'i', $d )
2616
+ , 'sec' => date( 's', $d ));
2617
+ $this->dtstamp['params'] = null;
2618
+ }
2619
+ /**
2620
+ * set calendar component property dtstamp
2621
+ *
2622
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2623
+ * @since 2.4.8 - 2008-10-23
2624
+ * @param mixed $year
2625
+ * @param mixed $month optional
2626
+ * @param int $day optional
2627
+ * @param int $hour optional
2628
+ * @param int $min optional
2629
+ * @param int $sec optional
2630
+ * @param array $params optional
2631
+ * @return TRUE
2632
+ */
2633
+ function setDtstamp( $year, $month=FALSE, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $params=FALSE ) {
2634
+ if( empty( $year ))
2635
+ $this->_makeDtstamp();
2636
+ else
2637
+ $this->dtstamp = iCalUtilityFunctions::_setDate2( $year, $month, $day, $hour, $min, $sec, $params );
2638
+ return TRUE;
2639
+ }
2640
+ /*********************************************************************************/
2641
+ /**
2642
+ * Property Name: DTSTART
2643
+ */
2644
+ /**
2645
+ * creates formatted output for calendar component property dtstart
2646
+ *
2647
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2648
+ * @since 2.9.6 - 2011-05-15
2649
+ * @return string
2650
+ */
2651
+ function createDtstart() {
2652
+ if( empty( $this->dtstart )) return FALSE;
2653
+ if( !isset( $this->dtstart['value']['year'] ) &&
2654
+ !isset( $this->dtstart['value']['month'] ) &&
2655
+ !isset( $this->dtstart['value']['day'] ) &&
2656
+ !isset( $this->dtstart['value']['hour'] ) &&
2657
+ !isset( $this->dtstart['value']['min'] ) &&
2658
+ !isset( $this->dtstart['value']['sec'] )) {
2659
+ if( $this->getConfig( 'allowEmpty' ))
2660
+ return $this->_createElement( 'DTSTART' );
2661
+ else return FALSE;
2662
+ }
2663
+ if( in_array( $this->objName, array( 'vtimezone', 'standard', 'daylight' )))
2664
+ unset( $this->dtstart['value']['tz'], $this->dtstart['params']['TZID'] );
2665
+ elseif(( FALSE !== ( $tzid = $this->getConfig( 'TZID' ))) &&
2666
+ ( !isset( $this->dtstart['params']['VALUE'] ) || ( $this->dtstart['params']['VALUE'] != 'DATE' )) &&
2667
+ !isset( $this->dtstart['params']['TZID'] ))
2668
+ $this->dtstart['params']['TZID'] = $tzid;
2669
+ $formatted = iCalUtilityFunctions::_format_date_time( $this->dtstart['value'] );
2670
+ $attributes = $this->_createParams( $this->dtstart['params'] );
2671
+ return $this->_createElement( 'DTSTART', $attributes, $formatted );
2672
+ }
2673
+ /**
2674
+ * set calendar component property dtstart
2675
+ *
2676
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2677
+ * @since 2.6.22 - 2010-09-22
2678
+ * @param mixed $year
2679
+ * @param mixed $month optional
2680
+ * @param int $day optional
2681
+ * @param int $hour optional
2682
+ * @param int $min optional
2683
+ * @param int $sec optional
2684
+ * @param string $tz optional
2685
+ * @param array $params optional
2686
+ * @return bool
2687
+ */
2688
+ function setDtstart( $year, $month=FALSE, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $tz=FALSE, $params=FALSE ) {
2689
+ if( empty( $year )) {
2690
+ if( $this->getConfig( 'allowEmpty' )) {
2691
+ $this->dtstart = array( 'value' => null, 'params' => iCalUtilityFunctions::_setParams( $params ));
2692
+ return TRUE;
2693
+ }
2694
+ else
2695
+ return FALSE;
2696
+ }
2697
+ $this->dtstart = iCalUtilityFunctions::_setDate( $year, $month, $day, $hour, $min, $sec, $tz, $params, 'dtstart', $this->objName, $this->getConfig( 'TZID' ));
2698
+ return TRUE;
2699
+ }
2700
+ /*********************************************************************************/
2701
+ /**
2702
+ * Property Name: DUE
2703
+ */
2704
+ /**
2705
+ * creates formatted output for calendar component property due
2706
+ *
2707
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2708
+ * @since 2.4.8 - 2008-10-22
2709
+ * @return string
2710
+ */
2711
+ function createDue() {
2712
+ if( empty( $this->due )) return FALSE;
2713
+ if( !isset( $this->due['value']['year'] ) &&
2714
+ !isset( $this->due['value']['month'] ) &&
2715
+ !isset( $this->due['value']['day'] ) &&
2716
+ !isset( $this->due['value']['hour'] ) &&
2717
+ !isset( $this->due['value']['min'] ) &&
2718
+ !isset( $this->due['value']['sec'] )) {
2719
+ if( $this->getConfig( 'allowEmpty' ))
2720
+ return $this->_createElement( 'DUE' );
2721
+ else
2722
+ return FALSE;
2723
+ }
2724
+ $formatted = iCalUtilityFunctions::_format_date_time( $this->due['value'] );
2725
+ if(( FALSE !== ( $tzid = $this->getConfig( 'TZID' ))) &&
2726
+ ( !isset( $this->due['params']['VALUE'] ) || ( $this->due['params']['VALUE'] != 'DATE' )) &&
2727
+ !isset( $this->due['params']['TZID'] ))
2728
+ $this->due['params']['TZID'] = $tzid;
2729
+ $attributes = $this->_createParams( $this->due['params'] );
2730
+ return $this->_createElement( 'DUE', $attributes, $formatted );
2731
+ }
2732
+ /**
2733
+ * set calendar component property due
2734
+ *
2735
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2736
+ * @since 2.4.8 - 2008-11-04
2737
+ * @param mixed $year
2738
+ * @param mixed $month optional
2739
+ * @param int $day optional
2740
+ * @param int $hour optional
2741
+ * @param int $min optional
2742
+ * @param int $sec optional
2743
+ * @param array $params optional
2744
+ * @return bool
2745
+ */
2746
+ function setDue( $year, $month=FALSE, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $tz=FALSE, $params=FALSE ) {
2747
+ if( empty( $year )) {
2748
+ if( $this->getConfig( 'allowEmpty' )) {
2749
+ $this->due = array( 'value' => null, 'params' => iCalUtilityFunctions::_setParams( $params ));
2750
+ return TRUE;
2751
+ }
2752
+ else
2753
+ return FALSE;
2754
+ }
2755
+ $this->due = iCalUtilityFunctions::_setDate( $year, $month, $day, $hour, $min, $sec, $tz, $params, null, null, $this->getConfig( 'TZID' ));
2756
+ return TRUE;
2757
+ }
2758
+ /*********************************************************************************/
2759
+ /**
2760
+ * Property Name: DURATION
2761
+ */
2762
+ /**
2763
+ * creates formatted output for calendar component property duration
2764
+ *
2765
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2766
+ * @since 2.4.8 - 2008-10-21
2767
+ * @return string
2768
+ */
2769
+ function createDuration() {
2770
+ if( empty( $this->duration )) return FALSE;
2771
+ if( !isset( $this->duration['value']['week'] ) &&
2772
+ !isset( $this->duration['value']['day'] ) &&
2773
+ !isset( $this->duration['value']['hour'] ) &&
2774
+ !isset( $this->duration['value']['min'] ) &&
2775
+ !isset( $this->duration['value']['sec'] ))
2776
+ if( $this->getConfig( 'allowEmpty' ))
2777
+ return $this->_createElement( 'DURATION', array(), null );
2778
+ else return FALSE;
2779
+ $attributes = $this->_createParams( $this->duration['params'] );
2780
+ return $this->_createElement( 'DURATION', $attributes, iCalUtilityFunctions::_format_duration( $this->duration['value'] ));
2781
+ }
2782
+ /**
2783
+ * set calendar component property duration
2784
+ *
2785
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2786
+ * @since 2.4.8 - 2008-11-04
2787
+ * @param mixed $week
2788
+ * @param mixed $day optional
2789
+ * @param int $hour optional
2790
+ * @param int $min optional
2791
+ * @param int $sec optional
2792
+ * @param array $params optional
2793
+ * @return bool
2794
+ */
2795
+ function setDuration( $week, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $params=FALSE ) {
2796
+ if( empty( $week )) if( $this->getConfig( 'allowEmpty' )) $week = null; else return FALSE;
2797
+ if( is_array( $week ) && ( 1 <= count( $week )))
2798
+ $this->duration = array( 'value' => iCalUtilityFunctions::_duration_array( $week ), 'params' => iCalUtilityFunctions::_setParams( $day ));
2799
+ elseif( is_string( $week ) && ( 3 <= strlen( trim( $week )))) {
2800
+ $week = trim( $week );
2801
+ if( in_array( substr( $week, 0, 1 ), array( '+', '-' )))
2802
+ $week = substr( $week, 1 );
2803
+ $this->duration = array( 'value' => iCalUtilityFunctions::_duration_string( $week ), 'params' => iCalUtilityFunctions::_setParams( $day ));
2804
+ }
2805
+ elseif( empty( $week ) && empty( $day ) && empty( $hour ) && empty( $min ) && empty( $sec ))
2806
+ return FALSE;
2807
+ else
2808
+ $this->duration = array( 'value' => iCalUtilityFunctions::_duration_array( array( $week, $day, $hour, $min, $sec )), 'params' => iCalUtilityFunctions::_setParams( $params ));
2809
+ return TRUE;
2810
+ }
2811
+ /*********************************************************************************/
2812
+ /**
2813
+ * Property Name: EXDATE
2814
+ */
2815
+ /**
2816
+ * creates formatted output for calendar component property exdate
2817
+ *
2818
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2819
+ * @since 2.4.8 - 2008-10-22
2820
+ * @return string
2821
+ */
2822
+ function createExdate() {
2823
+ if( empty( $this->exdate )) return FALSE;
2824
+ $output = null;
2825
+ foreach( $this->exdate as $ex => $theExdate ) {
2826
+ if( empty( $theExdate['value'] )) {
2827
+ if( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( 'EXDATE' );
2828
+ continue;
2829
+ }
2830
+ $content = $attributes = null;
2831
+ foreach( $theExdate['value'] as $eix => $exdatePart ) {
2832
+ $parno = count( $exdatePart );
2833
+ $formatted = iCalUtilityFunctions::_format_date_time( $exdatePart, $parno );
2834
+ if( isset( $theExdate['params']['TZID'] ))
2835
+ $formatted = str_replace( 'Z', '', $formatted);
2836
+ if( 0 < $eix ) {
2837
+ if( isset( $theExdate['value'][0]['tz'] )) {
2838
+ if( ctype_digit( substr( $theExdate['value'][0]['tz'], -4 )) ||
2839
+ ( 'Z' == $theExdate['value'][0]['tz'] )) {
2840
+ if( 'Z' != substr( $formatted, -1 ))
2841
+ $formatted .= 'Z';
2842
+ }
2843
+ else
2844
+ $formatted = str_replace( 'Z', '', $formatted );
2845
+ }
2846
+ else
2847
+ $formatted = str_replace( 'Z', '', $formatted );
2848
+ }
2849
+ $content .= ( 0 < $eix ) ? ','.$formatted : $formatted;
2850
+ }
2851
+ $attributes .= $this->_createParams( $theExdate['params'] );
2852
+ $output .= $this->_createElement( 'EXDATE', $attributes, $content );
2853
+ }
2854
+ return $output;
2855
+ }
2856
+ /**
2857
+ * set calendar component property exdate
2858
+ *
2859
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2860
+ * @since 2.5.1 - 2008-11-05
2861
+ * @param array exdates
2862
+ * @param array $params, optional
2863
+ * @param integer $index, optional
2864
+ * @return bool
2865
+ */
2866
+ function setExdate( $exdates, $params=FALSE, $index=FALSE ) {
2867
+ if( empty( $exdates )) {
2868
+ if( $this->getConfig( 'allowEmpty' )) {
2869
+ iCalUtilityFunctions::_setMval( $this->exdate, null, $params, FALSE, $index );
2870
+ return TRUE;
2871
+ }
2872
+ else
2873
+ return FALSE;
2874
+ }
2875
+ $input = array( 'params' => iCalUtilityFunctions::_setParams( $params, array( 'VALUE' => 'DATE-TIME' )));
2876
+ /* ev. check 1:st date and save ev. timezone **/
2877
+ iCalUtilityFunctions::_chkdatecfg( reset( $exdates ), $parno, $input['params'] );
2878
+ iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE-TIME' ); // remove default parameter
2879
+ foreach( $exdates as $eix => $theExdate ) {
2880
+ if( iCalUtilityFunctions::_isArrayTimestampDate( $theExdate ))
2881
+ $exdatea = iCalUtilityFunctions::_timestamp2date( $theExdate, $parno );
2882
+ elseif( is_array( $theExdate ))
2883
+ $exdatea = iCalUtilityFunctions::_date_time_array( $theExdate, $parno );
2884
+ elseif( 8 <= strlen( trim( $theExdate ))) // ex. 2006-08-03 10:12:18
2885
+ $exdatea = iCalUtilityFunctions::_date_time_string( $theExdate, $parno );
2886
+ if( 3 == $parno )
2887
+ unset( $exdatea['hour'], $exdatea['min'], $exdatea['sec'], $exdatea['tz'] );
2888
+ elseif( isset( $exdatea['tz'] ))
2889
+ $exdatea['tz'] = (string) $exdatea['tz'];
2890
+ if( isset( $input['params']['TZID'] ) ||
2891
+ ( isset( $exdatea['tz'] ) && !iCalUtilityFunctions::_isOffset( $exdatea['tz'] )) ||
2892
+ ( isset( $input['value'][0] ) && ( !isset( $input['value'][0]['tz'] ))) ||
2893
+ ( isset( $input['value'][0]['tz'] ) && !iCalUtilityFunctions::_isOffset( $input['value'][0]['tz'] )))
2894
+ unset( $exdatea['tz'] );
2895
+ $input['value'][] = $exdatea;
2896
+ }
2897
+ if( 0 >= count( $input['value'] ))
2898
+ return FALSE;
2899
+ if( 3 == $parno ) {
2900
+ $input['params']['VALUE'] = 'DATE';
2901
+ unset( $input['params']['TZID'] );
2902
+ }
2903
+ iCalUtilityFunctions::_setMval( $this->exdate, $input['value'], $input['params'], FALSE, $index );
2904
+ return TRUE;
2905
+ }
2906
+ /*********************************************************************************/
2907
+ /**
2908
+ * Property Name: EXRULE
2909
+ */
2910
+ /**
2911
+ * creates formatted output for calendar component property exrule
2912
+ *
2913
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2914
+ * @since 2.4.8 - 2008-10-22
2915
+ * @return string
2916
+ */
2917
+ function createExrule() {
2918
+ if( empty( $this->exrule )) return FALSE;
2919
+ return $this->_format_recur( 'EXRULE', $this->exrule );
2920
+ }
2921
+ /**
2922
+ * set calendar component property exdate
2923
+ *
2924
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2925
+ * @since 2.5.1 - 2008-11-05
2926
+ * @param array $exruleset
2927
+ * @param array $params, optional
2928
+ * @param integer $index, optional
2929
+ * @return bool
2930
+ */
2931
+ function setExrule( $exruleset, $params=FALSE, $index=FALSE ) {
2932
+ if( empty( $exruleset )) if( $this->getConfig( 'allowEmpty' )) $exruleset = null; else return FALSE;
2933
+ iCalUtilityFunctions::_setMval( $this->exrule, iCalUtilityFunctions::_setRexrule( $exruleset ), $params, FALSE, $index );
2934
+ return TRUE;
2935
+ }
2936
+ /*********************************************************************************/
2937
+ /**
2938
+ * Property Name: FREEBUSY
2939
+ */
2940
+ /**
2941
+ * creates formatted output for calendar component property freebusy
2942
+ *
2943
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2944
+ * @since 2.4.8 - 2008-10-22
2945
+ * @return string
2946
+ */
2947
+ function createFreebusy() {
2948
+ if( empty( $this->freebusy )) return FALSE;
2949
+ $output = null;
2950
+ foreach( $this->freebusy as $freebusyPart ) {
2951
+ if( empty( $freebusyPart['value'] )) {
2952
+ if( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( 'FREEBUSY' );
2953
+ continue;
2954
+ }
2955
+ $attributes = $content = null;
2956
+ if( isset( $freebusyPart['value']['fbtype'] )) {
2957
+ $attributes .= $this->intAttrDelimiter.'FBTYPE='.$freebusyPart['value']['fbtype'];
2958
+ unset( $freebusyPart['value']['fbtype'] );
2959
+ $freebusyPart['value'] = array_values( $freebusyPart['value'] );
2960
+ }
2961
+ else
2962
+ $attributes .= $this->intAttrDelimiter.'FBTYPE=BUSY';
2963
+ $attributes .= $this->_createParams( $freebusyPart['params'] );
2964
+ $fno = 1;
2965
+ $cnt = count( $freebusyPart['value']);
2966
+ foreach( $freebusyPart['value'] as $periodix => $freebusyPeriod ) {
2967
+ $formatted = iCalUtilityFunctions::_format_date_time( $freebusyPeriod[0] );
2968
+ $content .= $formatted;
2969
+ $content .= '/';
2970
+ $cnt2 = count( $freebusyPeriod[1]);
2971
+ if( array_key_exists( 'year', $freebusyPeriod[1] )) // date-time
2972
+ $cnt2 = 7;
2973
+ elseif( array_key_exists( 'week', $freebusyPeriod[1] )) // duration
2974
+ $cnt2 = 5;
2975
+ if(( 7 == $cnt2 ) && // period= -> date-time
2976
+ isset( $freebusyPeriod[1]['year'] ) &&
2977
+ isset( $freebusyPeriod[1]['month'] ) &&
2978
+ isset( $freebusyPeriod[1]['day'] )) {
2979
+ $content .= iCalUtilityFunctions::_format_date_time( $freebusyPeriod[1] );
2980
+ }
2981
+ else { // period= -> dur-time
2982
+ $content .= iCalUtilityFunctions::_format_duration( $freebusyPeriod[1] );
2983
+ }
2984
+ if( $fno < $cnt )
2985
+ $content .= ',';
2986
+ $fno++;
2987
+ }
2988
+ $output .= $this->_createElement( 'FREEBUSY', $attributes, $content );
2989
+ }
2990
+ return $output;
2991
+ }
2992
+ /**
2993
+ * set calendar component property freebusy
2994
+ *
2995
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
2996
+ * @since 2.8.10 - 2011-03-24
2997
+ * @param string $fbType
2998
+ * @param array $fbValues
2999
+ * @param array $params, optional
3000
+ * @param integer $index, optional
3001
+ * @return bool
3002
+ */
3003
+ function setFreebusy( $fbType, $fbValues, $params=FALSE, $index=FALSE ) {
3004
+ if( empty( $fbValues )) {
3005
+ if( $this->getConfig( 'allowEmpty' )) {
3006
+ iCalUtilityFunctions::_setMval( $this->freebusy, null, $params, FALSE, $index );
3007
+ return TRUE;
3008
+ }
3009
+ else
3010
+ return FALSE;
3011
+ }
3012
+ $fbType = strtoupper( $fbType );
3013
+ if(( !in_array( $fbType, array( 'FREE', 'BUSY', 'BUSY-UNAVAILABLE', 'BUSY-TENTATIVE' ))) &&
3014
+ ( 'X-' != substr( $fbType, 0, 2 )))
3015
+ $fbType = 'BUSY';
3016
+ $input = array( 'fbtype' => $fbType );
3017
+ foreach( $fbValues as $fbPeriod ) { // periods => period
3018
+ if( empty( $fbPeriod ))
3019
+ continue;
3020
+ $freebusyPeriod = array();
3021
+ foreach( $fbPeriod as $fbMember ) { // pairs => singlepart
3022
+ $freebusyPairMember = array();
3023
+ if( is_array( $fbMember )) {
3024
+ if( iCalUtilityFunctions::_isArrayDate( $fbMember )) { // date-time value
3025
+ $freebusyPairMember = iCalUtilityFunctions::_date_time_array( $fbMember, 7 );
3026
+ $freebusyPairMember['tz'] = 'Z';
3027
+ }
3028
+ elseif( iCalUtilityFunctions::_isArrayTimestampDate( $fbMember )) { // timestamp value
3029
+ $freebusyPairMember = iCalUtilityFunctions::_timestamp2date( $fbMember['timestamp'], 7 );
3030
+ $freebusyPairMember['tz'] = 'Z';
3031
+ }
3032
+ else { // array format duration
3033
+ $freebusyPairMember = iCalUtilityFunctions::_duration_array( $fbMember );
3034
+ }
3035
+ }
3036
+ elseif(( 3 <= strlen( trim( $fbMember ))) && // string format duration
3037
+ ( in_array( $fbMember{0}, array( 'P', '+', '-' )))) {
3038
+ if( 'P' != $fbMember{0} )
3039
+ $fbmember = substr( $fbMember, 1 );
3040
+ $freebusyPairMember = iCalUtilityFunctions::_duration_string( $fbMember );
3041
+ }
3042
+ elseif( 8 <= strlen( trim( $fbMember ))) { // text date ex. 2006-08-03 10:12:18
3043
+ $freebusyPairMember = iCalUtilityFunctions::_date_time_string( $fbMember, 7 );
3044
+ $freebusyPairMember['tz'] = 'Z';
3045
+ }
3046
+ $freebusyPeriod[] = $freebusyPairMember;
3047
+ }
3048
+ $input[] = $freebusyPeriod;
3049
+ }
3050
+ iCalUtilityFunctions::_setMval( $this->freebusy, $input, $params, FALSE, $index );
3051
+ return TRUE;
3052
+ }
3053
+ /*********************************************************************************/
3054
+ /**
3055
+ * Property Name: GEO
3056
+ */
3057
+ /**
3058
+ * creates formatted output for calendar component property geo
3059
+ *
3060
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3061
+ * @since 2.4.8 - 2008-10-21
3062
+ * @return string
3063
+ */
3064
+ function createGeo() {
3065
+ if( empty( $this->geo )) return FALSE;
3066
+ if( empty( $this->geo['value'] ))
3067
+ return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'GEO' ) : FALSE;
3068
+ $attributes = $this->_createParams( $this->geo['params'] );
3069
+ $content = null;
3070
+ $content .= number_format( (float) $this->geo['value']['latitude'], 6, '.', '');
3071
+ $content .= ';';
3072
+ $content .= number_format( (float) $this->geo['value']['longitude'], 6, '.', '');
3073
+ return $this->_createElement( 'GEO', $attributes, $content );
3074
+ }
3075
+ /**
3076
+ * set calendar component property geo
3077
+ *
3078
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3079
+ * @since 2.4.8 - 2008-11-04
3080
+ * @param float $latitude
3081
+ * @param float $longitude
3082
+ * @param array $params optional
3083
+ * @return bool
3084
+ */
3085
+ function setGeo( $latitude, $longitude, $params=FALSE ) {
3086
+ if( !empty( $latitude ) && !empty( $longitude )) {
3087
+ if( !is_array( $this->geo )) $this->geo = array();
3088
+ $this->geo['value']['latitude'] = $latitude;
3089
+ $this->geo['value']['longitude'] = $longitude;
3090
+ $this->geo['params'] = iCalUtilityFunctions::_setParams( $params );
3091
+ }
3092
+ elseif( $this->getConfig( 'allowEmpty' ))
3093
+ $this->geo = array( 'value' => null, 'params' => iCalUtilityFunctions::_setParams( $params ) );
3094
+ else
3095
+ return FALSE;
3096
+ return TRUE;
3097
+ }
3098
+ /*********************************************************************************/
3099
+ /**
3100
+ * Property Name: LAST-MODIFIED
3101
+ */
3102
+ /**
3103
+ * creates formatted output for calendar component property last-modified
3104
+ *
3105
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3106
+ * @since 2.4.8 - 2008-10-21
3107
+ * @return string
3108
+ */
3109
+ function createLastModified() {
3110
+ if( empty( $this->lastmodified )) return FALSE;
3111
+ $attributes = $this->_createParams( $this->lastmodified['params'] );
3112
+ $formatted = iCalUtilityFunctions::_format_date_time( $this->lastmodified['value'], 7 );
3113
+ return $this->_createElement( 'LAST-MODIFIED', $attributes, $formatted );
3114
+ }
3115
+ /**
3116
+ * set calendar component property completed
3117
+ *
3118
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3119
+ * @since 2.4.8 - 2008-10-23
3120
+ * @param mixed $year optional
3121
+ * @param mixed $month optional
3122
+ * @param int $day optional
3123
+ * @param int $hour optional
3124
+ * @param int $min optional
3125
+ * @param int $sec optional
3126
+ * @param array $params optional
3127
+ * @return boll
3128
+ */
3129
+ function setLastModified( $year=FALSE, $month=FALSE, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $params=FALSE ) {
3130
+ if( empty( $year ))
3131
+ $year = date('Ymd\THis', mktime( date( 'H' ), date( 'i' ), date( 's' ) - date( 'Z'), date( 'm' ), date( 'd' ), date( 'Y' )));
3132
+ $this->lastmodified = iCalUtilityFunctions::_setDate2( $year, $month, $day, $hour, $min, $sec, $params );
3133
+ return TRUE;
3134
+ }
3135
+ /*********************************************************************************/
3136
+ /**
3137
+ * Property Name: LOCATION
3138
+ */
3139
+ /**
3140
+ * creates formatted output for calendar component property location
3141
+ *
3142
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3143
+ * @since 2.4.8 - 2008-10-22
3144
+ * @return string
3145
+ */
3146
+ function createLocation() {
3147
+ if( empty( $this->location )) return FALSE;
3148
+ if( empty( $this->location['value'] ))
3149
+ return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'LOCATION' ) : FALSE;
3150
+ $attributes = $this->_createParams( $this->location['params'], array( 'ALTREP', 'LANGUAGE' ));
3151
+ $content = $this->_strrep( $this->location['value'] );
3152
+ return $this->_createElement( 'LOCATION', $attributes, $content );
3153
+ }
3154
+ /**
3155
+ * set calendar component property location
3156
+ '
3157
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3158
+ * @since 2.4.8 - 2008-11-04
3159
+ * @param string $value
3160
+ * @param array params optional
3161
+ * @return bool
3162
+ */
3163
+ function setLocation( $value, $params=FALSE ) {
3164
+ if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = null; else return FALSE;
3165
+ $this->location = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
3166
+ return TRUE;
3167
+ }
3168
+ /*********************************************************************************/
3169
+ /**
3170
+ * Property Name: ORGANIZER
3171
+ */
3172
+ /**
3173
+ * creates formatted output for calendar component property organizer
3174
+ *
3175
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3176
+ * @since 2.6.33 - 2010-12-17
3177
+ * @return string
3178
+ */
3179
+ function createOrganizer() {
3180
+ if( empty( $this->organizer )) return FALSE;
3181
+ if( empty( $this->organizer['value'] ))
3182
+ return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'ORGANIZER' ) : FALSE;
3183
+ $attributes = $this->_createParams( $this->organizer['params']
3184
+ , array( 'CN', 'DIR', 'SENT-BY', 'LANGUAGE' ));
3185
+ return $this->_createElement( 'ORGANIZER', $attributes, $this->organizer['value'] );
3186
+ }
3187
+ /**
3188
+ * set calendar component property organizer
3189
+ *
3190
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3191
+ * @since 2.6.27 - 2010-11-29
3192
+ * @param string $value
3193
+ * @param array params optional
3194
+ * @return bool
3195
+ */
3196
+ function setOrganizer( $value, $params=FALSE ) {
3197
+ if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = null; else return FALSE;
3198
+ if( FALSE === ( $pos = strpos( substr( $value, 0, 9 ), ':' )))
3199
+ $value = 'MAILTO:'.$value;
3200
+ else
3201
+ $value = strtolower( substr( $value, 0, $pos )).substr( $value, $pos );
3202
+ $value = str_replace( 'mailto:', 'MAILTO:', $value );
3203
+ $this->organizer = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
3204
+ if( isset( $this->organizer['params']['SENT-BY'] )){
3205
+ if( 'mailto:' !== strtolower( substr( $this->organizer['params']['SENT-BY'], 0, 7 )))
3206
+ $this->organizer['params']['SENT-BY'] = 'MAILTO:'.$this->organizer['params']['SENT-BY'];
3207
+ else
3208
+ $this->organizer['params']['SENT-BY'] = 'MAILTO:'.substr( $this->organizer['params']['SENT-BY'], 7 );
3209
+ }
3210
+ return TRUE;
3211
+ }
3212
+ /*********************************************************************************/
3213
+ /**
3214
+ * Property Name: PERCENT-COMPLETE
3215
+ */
3216
+ /**
3217
+ * creates formatted output for calendar component property percent-complete
3218
+ *
3219
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3220
+ * @since 2.9.3 - 2011-05-14
3221
+ * @return string
3222
+ */
3223
+ function createPercentComplete() {
3224
+ if( !isset($this->percentcomplete) || ( empty( $this->percentcomplete ) && !is_numeric( $this->percentcomplete ))) return FALSE;
3225
+ if( !isset( $this->percentcomplete['value'] ) || ( empty( $this->percentcomplete['value'] ) && !is_numeric( $this->percentcomplete['value'] )))
3226
+ return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'PERCENT-COMPLETE' ) : FALSE;
3227
+ $attributes = $this->_createParams( $this->percentcomplete['params'] );
3228
+ return $this->_createElement( 'PERCENT-COMPLETE', $attributes, $this->percentcomplete['value'] );
3229
+ }
3230
+ /**
3231
+ * set calendar component property percent-complete
3232
+ *
3233
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3234
+ * @since 2.9.3 - 2011-05-14
3235
+ * @param int $value
3236
+ * @param array $params optional
3237
+ * @return bool
3238
+ */
3239
+ function setPercentComplete( $value, $params=FALSE ) {
3240
+ if( empty( $value ) && !is_numeric( $value )) if( $this->getConfig( 'allowEmpty' )) $value = null; else return FALSE;
3241
+ $this->percentcomplete = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
3242
+ return TRUE;
3243
+ }
3244
+ /*********************************************************************************/
3245
+ /**
3246
+ * Property Name: PRIORITY
3247
+ */
3248
+ /**
3249
+ * creates formatted output for calendar component property priority
3250
+ *
3251
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3252
+ * @since 2.9.3 - 2011-05-14
3253
+ * @return string
3254
+ */
3255
+ function createPriority() {
3256
+ if( !isset($this->priority) || ( empty( $this->priority ) && !is_numeric( $this->priority ))) return FALSE;
3257
+ if( !isset( $this->priority['value'] ) || ( empty( $this->priority['value'] ) && !is_numeric( $this->priority['value'] )))
3258
+ return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'PRIORITY' ) : FALSE;
3259
+ $attributes = $this->_createParams( $this->priority['params'] );
3260
+ return $this->_createElement( 'PRIORITY', $attributes, $this->priority['value'] );
3261
+ }
3262
+ /**
3263
+ * set calendar component property priority
3264
+ *
3265
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3266
+ * @since 2.9.3 - 2011-05-14
3267
+ * @param int $value
3268
+ * @param array $params optional
3269
+ * @return bool
3270
+ */
3271
+ function setPriority( $value, $params=FALSE ) {
3272
+ if( empty( $value ) && !is_numeric( $value )) if( $this->getConfig( 'allowEmpty' )) $value = null; else return FALSE;
3273
+ $this->priority = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
3274
+ return TRUE;
3275
+ }
3276
+ /*********************************************************************************/
3277
+ /**
3278
+ * Property Name: RDATE
3279
+ */
3280
+ /**
3281
+ * creates formatted output for calendar component property rdate
3282
+ *
3283
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3284
+ * @since 2.4.16 - 2008-10-26
3285
+ * @return string
3286
+ */
3287
+ function createRdate() {
3288
+ if( empty( $this->rdate )) return FALSE;
3289
+ $utctime = ( in_array( $this->objName, array( 'vtimezone', 'standard', 'daylight' ))) ? TRUE : FALSE;
3290
+ $output = null;
3291
+ if( $utctime )
3292
+ unset( $this->rdate['params']['TZID'] );
3293
+ foreach( $this->rdate as $theRdate ) {
3294
+ if( empty( $theRdate['value'] )) {
3295
+ if( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( 'RDATE' );
3296
+ continue;
3297
+ }
3298
+ if( $utctime )
3299
+ unset( $theRdate['params']['TZID'] );
3300
+ $attributes = $this->_createParams( $theRdate['params'] );
3301
+ $cnt = count( $theRdate['value'] );
3302
+ $content = null;
3303
+ $rno = 1;
3304
+ foreach( $theRdate['value'] as $rpix => $rdatePart ) {
3305
+ $contentPart = null;
3306
+ if( is_array( $rdatePart ) &&
3307
+ isset( $theRdate['params']['VALUE'] ) && ( 'PERIOD' == $theRdate['params']['VALUE'] )) { // PERIOD
3308
+ if( $utctime )
3309
+ unset( $rdatePart[0]['tz'] );
3310
+ $formatted = iCalUtilityFunctions::_format_date_time( $rdatePart[0]); // PERIOD part 1
3311
+ if( $utctime || !empty( $theRdate['params']['TZID'] ))
3312
+ $formatted = str_replace( 'Z', '', $formatted);
3313
+ if( 0 < $rpix ) {
3314
+ if( !empty( $rdatePart[0]['tz'] ) && iCalUtilityFunctions::_isOffset( $rdatePart[0]['tz'] )) {
3315
+ if( 'Z' != substr( $formatted, -1 )) $formatted .= 'Z';
3316
+ }
3317
+ else
3318
+ $formatted = str_replace( 'Z', '', $formatted );
3319
+ }
3320
+ $contentPart .= $formatted;
3321
+ $contentPart .= '/';
3322
+ $cnt2 = count( $rdatePart[1]);
3323
+ if( array_key_exists( 'year', $rdatePart[1] )) {
3324
+ if( array_key_exists( 'hour', $rdatePart[1] ))
3325
+ $cnt2 = 7; // date-time
3326
+ else
3327
+ $cnt2 = 3; // date
3328
+ }
3329
+ elseif( array_key_exists( 'week', $rdatePart[1] )) // duration
3330
+ $cnt2 = 5;
3331
+ if(( 7 == $cnt2 ) && // period= -> date-time
3332
+ isset( $rdatePart[1]['year'] ) &&
3333
+ isset( $rdatePart[1]['month'] ) &&
3334
+ isset( $rdatePart[1]['day'] )) {
3335
+ if( $utctime )
3336
+ unset( $rdatePart[1]['tz'] );
3337
+ $formatted = iCalUtilityFunctions::_format_date_time( $rdatePart[1] ); // PERIOD part 2
3338
+ if( $utctime || !empty( $theRdate['params']['TZID'] ))
3339
+ $formatted = str_replace( 'Z', '', $formatted);
3340
+ if( !empty( $rdatePart[0]['tz'] ) && iCalUtilityFunctions::_isOffset( $rdatePart[0]['tz'] )) {
3341
+ if( 'Z' != substr( $formatted, -1 )) $formatted .= 'Z';
3342
+ }
3343
+ else
3344
+ $formatted = str_replace( 'Z', '', $formatted );
3345
+ $contentPart .= $formatted;
3346
+ }
3347
+ else { // period= -> dur-time
3348
+ $contentPart .= iCalUtilityFunctions::_format_duration( $rdatePart[1] );
3349
+ }
3350
+ } // PERIOD end
3351
+ else { // SINGLE date start
3352
+ if( $utctime )
3353
+ unset( $rdatePart['tz'] );
3354
+ $formatted = iCalUtilityFunctions::_format_date_time( $rdatePart);
3355
+ if( $utctime || !empty( $theRdate['params']['TZID'] ))
3356
+ $formatted = str_replace( 'Z', '', $formatted);
3357
+ if( !$utctime && ( 0 < $rpix )) {
3358
+ if( !empty( $theRdate['value'][0]['tz'] ) && iCalUtilityFunctions::_isOffset( $theRdate['value'][0]['tz'] )) {
3359
+ if( 'Z' != substr( $formatted, -1 ))
3360
+ $formatted .= 'Z';
3361
+ }
3362
+ else
3363
+ $formatted = str_replace( 'Z', '', $formatted );
3364
+ }
3365
+ $contentPart .= $formatted;
3366
+ }
3367
+ $content .= $contentPart;
3368
+ if( $rno < $cnt )
3369
+ $content .= ',';
3370
+ $rno++;
3371
+ }
3372
+ $output .= $this->_createElement( 'RDATE', $attributes, $content );
3373
+ }
3374
+ return $output;
3375
+ }
3376
+ /**
3377
+ * set calendar component property rdate
3378
+ *
3379
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3380
+ * @since 2.5.1 - 2008-11-07
3381
+ * @param array $rdates
3382
+ * @param array $params, optional
3383
+ * @param integer $index, optional
3384
+ * @return bool
3385
+ */
3386
+ function setRdate( $rdates, $params=FALSE, $index=FALSE ) {
3387
+ if( empty( $rdates )) {
3388
+ if( $this->getConfig( 'allowEmpty' )) {
3389
+ iCalUtilityFunctions::_setMval( $this->rdate, null, $params, FALSE, $index );
3390
+ return TRUE;
3391
+ }
3392
+ else
3393
+ return FALSE;
3394
+ }
3395
+ $input = array( 'params' => iCalUtilityFunctions::_setParams( $params, array( 'VALUE' => 'DATE-TIME' )));
3396
+ if( in_array( $this->objName, array( 'vtimezone', 'standard', 'daylight' ))) {
3397
+ unset( $input['params']['TZID'] );
3398
+ $input['params']['VALUE'] = 'DATE-TIME';
3399
+ }
3400
+ /* check if PERIOD, if not set */
3401
+ if((!isset( $input['params']['VALUE'] ) || !in_array( $input['params']['VALUE'], array( 'DATE', 'PERIOD' ))) &&
3402
+ isset( $rdates[0] ) && is_array( $rdates[0] ) && ( 2 == count( $rdates[0] )) &&
3403
+ isset( $rdates[0][0] ) && isset( $rdates[0][1] ) && !isset( $rdates[0]['timestamp'] ) &&
3404
+ (( is_array( $rdates[0][0] ) && ( isset( $rdates[0][0]['timestamp'] ) ||
3405
+ iCalUtilityFunctions::_isArrayDate( $rdates[0][0] ))) ||
3406
+ ( is_string( $rdates[0][0] ) && ( 8 <= strlen( trim( $rdates[0][0] ))))) &&
3407
+ ( is_array( $rdates[0][1] ) || ( is_string( $rdates[0][1] ) && ( 3 <= strlen( trim( $rdates[0][1] ))))))
3408
+ $input['params']['VALUE'] = 'PERIOD';
3409
+ /* check 1:st date, upd. $parno (opt) and save ev. timezone **/
3410
+ $date = reset( $rdates );
3411
+ if( isset( $input['params']['VALUE'] ) && ( 'PERIOD' == $input['params']['VALUE'] )) // PERIOD
3412
+ $date = reset( $date );
3413
+ iCalUtilityFunctions::_chkdatecfg( $date, $parno, $input['params'] );
3414
+ if( in_array( $this->objName, array( 'vtimezone', 'standard', 'daylight' )))
3415
+ unset( $input['params']['TZID'] );
3416
+ iCalUtilityFunctions::_existRem( $input['params'], 'VALUE', 'DATE-TIME' ); // remove default
3417
+ foreach( $rdates as $rpix => $theRdate ) {
3418
+ $inputa = null;
3419
+ if( is_array( $theRdate )) {
3420
+ if( isset( $input['params']['VALUE'] ) && ( 'PERIOD' == $input['params']['VALUE'] )) { // PERIOD
3421
+ foreach( $theRdate as $rix => $rPeriod ) {
3422
+ if( is_array( $rPeriod )) {
3423
+ if( iCalUtilityFunctions::_isArrayTimestampDate( $rPeriod )) // timestamp
3424
+ $inputab = ( isset( $rPeriod['tz'] )) ? iCalUtilityFunctions::_timestamp2date( $rPeriod, $parno ) : iCalUtilityFunctions::_timestamp2date( $rPeriod, 6 );
3425
+ elseif( iCalUtilityFunctions::_isArrayDate( $rPeriod ))
3426
+ $inputab = ( 3 < count ( $rPeriod )) ? iCalUtilityFunctions::_date_time_array( $rPeriod, $parno ) : iCalUtilityFunctions::_date_time_array( $rPeriod, 6 );
3427
+ elseif (( 1 == count( $rPeriod )) && ( 8 <= strlen( reset( $rPeriod )))) // text-date
3428
+ $inputab = iCalUtilityFunctions::_date_time_string( reset( $rPeriod ), $parno );
3429
+ else // array format duration
3430
+ $inputab = iCalUtilityFunctions::_duration_array( $rPeriod );
3431
+ }
3432
+ elseif(( 3 <= strlen( trim( $rPeriod ))) && // string format duration
3433
+ ( in_array( $rPeriod[0], array( 'P', '+', '-' )))) {
3434
+ if( 'P' != $rPeriod[0] )
3435
+ $rPeriod = substr( $rPeriod, 1 );
3436
+ $inputab = iCalUtilityFunctions::_duration_string( $rPeriod );
3437
+ }
3438
+ elseif( 8 <= strlen( trim( $rPeriod ))) // text date ex. 2006-08-03 10:12:18
3439
+ $inputab = iCalUtilityFunctions::_date_time_string( $rPeriod, $parno );
3440
+ if( isset( $input['params']['TZID'] ) ||
3441
+ ( isset( $inputab['tz'] ) && !iCalUtilityFunctions::_isOffset( $inputab['tz'] )) ||
3442
+ ( isset( $inputa[0] ) && ( !isset( $inputa[0]['tz'] ))) ||
3443
+ ( isset( $inputa[0]['tz'] ) && !iCalUtilityFunctions::_isOffset( $inputa[0]['tz'] )))
3444
+ unset( $inputab['tz'] );
3445
+ $inputa[] = $inputab;
3446
+ }
3447
+ } // PERIOD end
3448
+ elseif ( iCalUtilityFunctions::_isArrayTimestampDate( $theRdate )) // timestamp
3449
+ $inputa = iCalUtilityFunctions::_timestamp2date( $theRdate, $parno );
3450
+ else // date[-time]
3451
+ $inputa = iCalUtilityFunctions::_date_time_array( $theRdate, $parno );
3452
+ }
3453
+ elseif( 8 <= strlen( trim( $theRdate ))) // text date ex. 2006-08-03 10:12:18
3454
+ $inputa = iCalUtilityFunctions::_date_time_string( $theRdate, $parno );
3455
+ if( !isset( $input['params']['VALUE'] ) || ( 'PERIOD' != $input['params']['VALUE'] )) { // no PERIOD
3456
+ if( 3 == $parno )
3457
+ unset( $inputa['hour'], $inputa['min'], $inputa['sec'], $inputa['tz'] );
3458
+ elseif( isset( $inputa['tz'] ))
3459
+ $inputa['tz'] = (string) $inputa['tz'];
3460
+ if( isset( $input['params']['TZID'] ) ||
3461
+ ( isset( $inputa['tz'] ) && !iCalUtilityFunctions::_isOffset( $inputa['tz'] )) ||
3462
+ ( isset( $input['value'][0] ) && ( !isset( $input['value'][0]['tz'] ))) ||
3463
+ ( isset( $input['value'][0]['tz'] ) && !iCalUtilityFunctions::_isOffset( $input['value'][0]['tz'] )))
3464
+ unset( $inputa['tz'] );
3465
+ }
3466
+ $input['value'][] = $inputa;
3467
+ }
3468
+ if( 3 == $parno ) {
3469
+ $input['params']['VALUE'] = 'DATE';
3470
+ unset( $input['params']['TZID'] );
3471
+ }
3472
+ iCalUtilityFunctions::_setMval( $this->rdate, $input['value'], $input['params'], FALSE, $index );
3473
+ return TRUE;
3474
+ }
3475
+ /*********************************************************************************/
3476
+ /**
3477
+ * Property Name: RECURRENCE-ID
3478
+ */
3479
+ /**
3480
+ * creates formatted output for calendar component property recurrence-id
3481
+ *
3482
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3483
+ * @since 2.9.6 - 2011-05-15
3484
+ * @return string
3485
+ */
3486
+ function createRecurrenceid() {
3487
+ if( empty( $this->recurrenceid )) return FALSE;
3488
+ if( empty( $this->recurrenceid['value'] ))
3489
+ return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'RECURRENCE-ID' ) : FALSE;
3490
+ $formatted = iCalUtilityFunctions::_format_date_time( $this->recurrenceid['value'] );
3491
+ if(( FALSE !== ( $tzid = $this->getConfig( 'TZID' ))) &&
3492
+ ( !isset( $this->recurrenceid['params']['VALUE'] ) || ( $this->recurrenceid['params']['VALUE'] != 'DATE' )) &&
3493
+ !isset( $this->recurrenceid['params']['TZID'] ))
3494
+ $this->recurrenceid['params']['TZID'] = $tzid;
3495
+ $attributes = $this->_createParams( $this->recurrenceid['params'] );
3496
+ return $this->_createElement( 'RECURRENCE-ID', $attributes, $formatted );
3497
+ }
3498
+ /**
3499
+ * set calendar component property recurrence-id
3500
+ *
3501
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3502
+ * @since 2.9.6 - 2011-05-15
3503
+ * @param mixed $year
3504
+ * @param mixed $month optional
3505
+ * @param int $day optional
3506
+ * @param int $hour optional
3507
+ * @param int $min optional
3508
+ * @param int $sec optional
3509
+ * @param array $params optional
3510
+ * @return bool
3511
+ */
3512
+ function setRecurrenceid( $year, $month=FALSE, $day=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $tz=FALSE, $params=FALSE ) {
3513
+ if( empty( $year )) {
3514
+ if( $this->getConfig( 'allowEmpty' )) {
3515
+ $this->recurrenceid = array( 'value' => null, 'params' => null );
3516
+ return TRUE;
3517
+ }
3518
+ else
3519
+ return FALSE;
3520
+ }
3521
+ $this->recurrenceid = iCalUtilityFunctions::_setDate( $year, $month, $day, $hour, $min, $sec, $tz, $params, null, null, $this->getConfig( 'TZID' ));
3522
+ return TRUE;
3523
+ }
3524
+ /*********************************************************************************/
3525
+ /**
3526
+ * Property Name: RELATED-TO
3527
+ */
3528
+ /**
3529
+ * creates formatted output for calendar component property related-to
3530
+ *
3531
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3532
+ * @since 2.4.8 - 2008-10-23
3533
+ * @return string
3534
+ */
3535
+ function createRelatedTo() {
3536
+ if( empty( $this->relatedto )) return FALSE;
3537
+ $output = null;
3538
+ foreach( $this->relatedto as $relation ) {
3539
+ if( empty( $relation['value'] )) {
3540
+ if( $this->getConfig( 'allowEmpty' )) $output.= $this->_createElement( 'RELATED-TO', $this->_createParams( $relation['params'] ));
3541
+ continue;
3542
+ }
3543
+ $attributes = $this->_createParams( $relation['params'] );
3544
+ $content = ( 'xcal' != $this->format ) ? '<' : '';
3545
+ $content .= $this->_strrep( $relation['value'] );
3546
+ $content .= ( 'xcal' != $this->format ) ? '>' : '';
3547
+ $output .= $this->_createElement( 'RELATED-TO', $attributes, $content );
3548
+ }
3549
+ return $output;
3550
+ }
3551
+ /**
3552
+ * set calendar component property related-to
3553
+ *
3554
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3555
+ * @since 2.5.1 - 2008-11-07
3556
+ * @param float $relid
3557
+ * @param array $params, optional
3558
+ * @param index $index, optional
3559
+ * @return bool
3560
+ */
3561
+ function setRelatedTo( $value, $params=FALSE, $index=FALSE ) {
3562
+ if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = null; else return FALSE;
3563
+ if(( '<' == substr( $value, 0, 1 )) && ( '>' == substr( $value, -1 )))
3564
+ $value = substr( $value, 1, ( strlen( $value ) - 2 ));
3565
+ iCalUtilityFunctions::_existRem( $params, 'RELTYPE', 'PARENT', TRUE ); // remove default
3566
+ iCalUtilityFunctions::_setMval( $this->relatedto, $value, $params, FALSE, $index );
3567
+ return TRUE;
3568
+ }
3569
+ /*********************************************************************************/
3570
+ /**
3571
+ * Property Name: REPEAT
3572
+ */
3573
+ /**
3574
+ * creates formatted output for calendar component property repeat
3575
+ *
3576
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3577
+ * @since 2.9.3 - 2011-05-14
3578
+ * @return string
3579
+ */
3580
+ function createRepeat() {
3581
+ if( !isset( $this->repeat ) || ( empty( $this->repeat ) && !is_numeric( $this->repeat ))) return FALSE;
3582
+ if( !isset( $this->repeat['value']) || ( empty( $this->repeat['value'] ) && !is_numeric( $this->repeat['value'] )))
3583
+ return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'REPEAT' ) : FALSE;
3584
+ $attributes = $this->_createParams( $this->repeat['params'] );
3585
+ return $this->_createElement( 'REPEAT', $attributes, $this->repeat['value'] );
3586
+ }
3587
+ /**
3588
+ * set calendar component property transp
3589
+ *
3590
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3591
+ * @since 2.9.3 - 2011-05-14
3592
+ * @param string $value
3593
+ * @param array $params optional
3594
+ * @return void
3595
+ */
3596
+ function setRepeat( $value, $params=FALSE ) {
3597
+ if( empty( $value ) && !is_numeric( $value )) if( $this->getConfig( 'allowEmpty' )) $value = null; else return FALSE;
3598
+ $this->repeat = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
3599
+ return TRUE;
3600
+ }
3601
+ /*********************************************************************************/
3602
+ /**
3603
+ * Property Name: REQUEST-STATUS
3604
+ */
3605
+ /**
3606
+ * creates formatted output for calendar component property request-status
3607
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3608
+ * @since 2.4.8 - 2008-10-23
3609
+ * @return string
3610
+ */
3611
+ function createRequestStatus() {
3612
+ if( empty( $this->requeststatus )) return FALSE;
3613
+ $output = null;
3614
+ foreach( $this->requeststatus as $rstat ) {
3615
+ if( empty( $rstat['value']['statcode'] )) {
3616
+ if( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( 'REQUEST-STATUS' );
3617
+ continue;
3618
+ }
3619
+ $attributes = $this->_createParams( $rstat['params'], array( 'LANGUAGE' ));
3620
+ $content = number_format( (float) $rstat['value']['statcode'], 2, '.', '');
3621
+ $content .= ';'.$this->_strrep( $rstat['value']['text'] );
3622
+ if( isset( $rstat['value']['extdata'] ))
3623
+ $content .= ';'.$this->_strrep( $rstat['value']['extdata'] );
3624
+ $output .= $this->_createElement( 'REQUEST-STATUS', $attributes, $content );
3625
+ }
3626
+ return $output;
3627
+ }
3628
+ /**
3629
+ * set calendar component property request-status
3630
+ *
3631
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3632
+ * @since 2.5.1 - 2008-11-05
3633
+ * @param float $statcode
3634
+ * @param string $text
3635
+ * @param string $extdata, optional
3636
+ * @param array $params, optional
3637
+ * @param integer $index, optional
3638
+ * @return bool
3639
+ */
3640
+ function setRequestStatus( $statcode, $text, $extdata=FALSE, $params=FALSE, $index=FALSE ) {
3641
+ if( empty( $statcode ) || empty( $text )) if( $this->getConfig( 'allowEmpty' )) $statcode = $text = null; else return FALSE;
3642
+ $input = array( 'statcode' => $statcode, 'text' => $text );
3643
+ if( $extdata )
3644
+ $input['extdata'] = $extdata;
3645
+ iCalUtilityFunctions::_setMval( $this->requeststatus, $input, $params, FALSE, $index );
3646
+ return TRUE;
3647
+ }
3648
+ /*********************************************************************************/
3649
+ /**
3650
+ * Property Name: RESOURCES
3651
+ */
3652
+ /**
3653
+ * creates formatted output for calendar component property resources
3654
+ *
3655
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3656
+ * @since 2.4.8 - 2008-10-23
3657
+ * @return string
3658
+ */
3659
+ function createResources() {
3660
+ if( empty( $this->resources )) return FALSE;
3661
+ $output = null;
3662
+ foreach( $this->resources as $resource ) {
3663
+ if( empty( $resource['value'] )) {
3664
+ if( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( 'RESOURCES' );
3665
+ continue;
3666
+ }
3667
+ $attributes = $this->_createParams( $resource['params'], array( 'ALTREP', 'LANGUAGE' ));
3668
+ if( is_array( $resource['value'] )) {
3669
+ foreach( $resource['value'] as $rix => $resourcePart )
3670
+ $resource['value'][$rix] = $this->_strrep( $resourcePart );
3671
+ $content = implode( ',', $resource['value'] );
3672
+ }
3673
+ else
3674
+ $content = $this->_strrep( $resource['value'] );
3675
+ $output .= $this->_createElement( 'RESOURCES', $attributes, $content );
3676
+ }
3677
+ return $output;
3678
+ }
3679
+ /**
3680
+ * set calendar component property recources
3681
+ *
3682
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3683
+ * @since 2.5.1 - 2008-11-05
3684
+ * @param mixed $value
3685
+ * @param array $params, optional
3686
+ * @param integer $index, optional
3687
+ * @return bool
3688
+ */
3689
+ function setResources( $value, $params=FALSE, $index=FALSE ) {
3690
+ if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = null; else return FALSE;
3691
+ iCalUtilityFunctions::_setMval( $this->resources, $value, $params, FALSE, $index );
3692
+ return TRUE;
3693
+ }
3694
+ /*********************************************************************************/
3695
+ /**
3696
+ * Property Name: RRULE
3697
+ */
3698
+ /**
3699
+ * creates formatted output for calendar component property rrule
3700
+ *
3701
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3702
+ * @since 2.4.8 - 2008-10-21
3703
+ * @return string
3704
+ */
3705
+ function createRrule() {
3706
+ if( empty( $this->rrule )) return FALSE;
3707
+ return $this->_format_recur( 'RRULE', $this->rrule );
3708
+ }
3709
+ /**
3710
+ * set calendar component property rrule
3711
+ *
3712
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3713
+ * @since 2.5.1 - 2008-11-05
3714
+ * @param array $rruleset
3715
+ * @param array $params, optional
3716
+ * @param integer $index, optional
3717
+ * @return void
3718
+ */
3719
+ function setRrule( $rruleset, $params=FALSE, $index=FALSE ) {
3720
+ if( empty( $rruleset )) if( $this->getConfig( 'allowEmpty' )) $rruleset = null; else return FALSE;
3721
+ iCalUtilityFunctions::_setMval( $this->rrule, iCalUtilityFunctions::_setRexrule( $rruleset ), $params, FALSE, $index );
3722
+ return TRUE;
3723
+ }
3724
+ /*********************************************************************************/
3725
+ /**
3726
+ * Property Name: SEQUENCE
3727
+ */
3728
+ /**
3729
+ * creates formatted output for calendar component property sequence
3730
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3731
+ * @since 2.9.3 - 2011-05-14
3732
+ * @return string
3733
+ */
3734
+ function createSequence() {
3735
+ if( !isset( $this->sequence ) || ( empty( $this->sequence ) && !is_numeric( $this->sequence ))) return FALSE;
3736
+ if(( !isset($this->sequence['value'] ) || ( empty( $this->sequence['value'] ) && !is_numeric( $this->sequence['value'] ))) &&
3737
+ ( '0' != $this->sequence['value'] ))
3738
+ return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'SEQUENCE' ) : FALSE;
3739
+ $attributes = $this->_createParams( $this->sequence['params'] );
3740
+ return $this->_createElement( 'SEQUENCE', $attributes, $this->sequence['value'] );
3741
+ }
3742
+ /**
3743
+ * set calendar component property sequence
3744
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3745
+ * @since 2.9.3 - 2011-05-14
3746
+ * @param int $value optional
3747
+ * @param array $params optional
3748
+ * @return bool
3749
+ */
3750
+ function setSequence( $value=FALSE, $params=FALSE ) {
3751
+ if(( empty( $value ) && !is_numeric( $value )) && ( '0' != $value ))
3752
+ $value = ( isset( $this->sequence['value'] ) && ( 0 < $this->sequence['value'] )) ? $this->sequence['value'] + 1 : 1;
3753
+ $this->sequence = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
3754
+ return TRUE;
3755
+ }
3756
+ /*********************************************************************************/
3757
+ /**
3758
+ * Property Name: STATUS
3759
+ */
3760
+ /**
3761
+ * creates formatted output for calendar component property status
3762
+ *
3763
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3764
+ * @since 2.4.8 - 2008-10-21
3765
+ * @return string
3766
+ */
3767
+ function createStatus() {
3768
+ if( empty( $this->status )) return FALSE;
3769
+ if( empty( $this->status['value'] ))
3770
+ return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'STATUS' ) : FALSE;
3771
+ $attributes = $this->_createParams( $this->status['params'] );
3772
+ return $this->_createElement( 'STATUS', $attributes, $this->status['value'] );
3773
+ }
3774
+ /**
3775
+ * set calendar component property status
3776
+ *
3777
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3778
+ * @since 2.4.8 - 2008-11-04
3779
+ * @param string $value
3780
+ * @param array $params optional
3781
+ * @return bool
3782
+ */
3783
+ function setStatus( $value, $params=FALSE ) {
3784
+ if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = null; else return FALSE;
3785
+ $this->status = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
3786
+ return TRUE;
3787
+ }
3788
+ /*********************************************************************************/
3789
+ /**
3790
+ * Property Name: SUMMARY
3791
+ */
3792
+ /**
3793
+ * creates formatted output for calendar component property summary
3794
+ *
3795
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3796
+ * @since 2.4.8 - 2008-10-21
3797
+ * @return string
3798
+ */
3799
+ function createSummary() {
3800
+ if( empty( $this->summary )) return FALSE;
3801
+ if( empty( $this->summary['value'] ))
3802
+ return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'SUMMARY' ) : FALSE;
3803
+ $attributes = $this->_createParams( $this->summary['params'], array( 'ALTREP', 'LANGUAGE' ));
3804
+ $content = $this->_strrep( $this->summary['value'] );
3805
+ return $this->_createElement( 'SUMMARY', $attributes, $content );
3806
+ }
3807
+ /**
3808
+ * set calendar component property summary
3809
+ *
3810
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3811
+ * @since 2.4.8 - 2008-11-04
3812
+ * @param string $value
3813
+ * @param string $params optional
3814
+ * @return bool
3815
+ */
3816
+ function setSummary( $value, $params=FALSE ) {
3817
+ if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = null; else return FALSE;
3818
+ $this->summary = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
3819
+ return TRUE;
3820
+ }
3821
+ /*********************************************************************************/
3822
+ /**
3823
+ * Property Name: TRANSP
3824
+ */
3825
+ /**
3826
+ * creates formatted output for calendar component property transp
3827
+ *
3828
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3829
+ * @since 2.4.8 - 2008-10-21
3830
+ * @return string
3831
+ */
3832
+ function createTransp() {
3833
+ if( empty( $this->transp )) return FALSE;
3834
+ if( empty( $this->transp['value'] ))
3835
+ return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'TRANSP' ) : FALSE;
3836
+ $attributes = $this->_createParams( $this->transp['params'] );
3837
+ return $this->_createElement( 'TRANSP', $attributes, $this->transp['value'] );
3838
+ }
3839
+ /**
3840
+ * set calendar component property transp
3841
+ *
3842
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3843
+ * @since 2.4.8 - 2008-11-04
3844
+ * @param string $value
3845
+ * @param string $params optional
3846
+ * @return bool
3847
+ */
3848
+ function setTransp( $value, $params=FALSE ) {
3849
+ if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = null; else return FALSE;
3850
+ $this->transp = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
3851
+ return TRUE;
3852
+ }
3853
+ /*********************************************************************************/
3854
+ /**
3855
+ * Property Name: TRIGGER
3856
+ */
3857
+ /**
3858
+ * creates formatted output for calendar component property trigger
3859
+ *
3860
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3861
+ * @since 2.4.16 - 2008-10-21
3862
+ * @return string
3863
+ */
3864
+ function createTrigger() {
3865
+ if( empty( $this->trigger )) return FALSE;
3866
+ if( empty( $this->trigger['value'] ))
3867
+ return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'TRIGGER' ) : FALSE;
3868
+ $content = $attributes = null;
3869
+ if( isset( $this->trigger['value']['year'] ) &&
3870
+ isset( $this->trigger['value']['month'] ) &&
3871
+ isset( $this->trigger['value']['day'] ))
3872
+ $content .= iCalUtilityFunctions::_format_date_time( $this->trigger['value'] );
3873
+ else {
3874
+ if( TRUE !== $this->trigger['value']['relatedStart'] )
3875
+ $attributes .= $this->intAttrDelimiter.'RELATED=END';
3876
+ if( $this->trigger['value']['before'] )
3877
+ $content .= '-';
3878
+ $content .= iCalUtilityFunctions::_format_duration( $this->trigger['value'] );
3879
+ }
3880
+ $attributes .= $this->_createParams( $this->trigger['params'] );
3881
+ return $this->_createElement( 'TRIGGER', $attributes, $content );
3882
+ }
3883
+ /**
3884
+ * set calendar component property trigger
3885
+ *
3886
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
3887
+ * @since 2.9.9 - 2011-06-17
3888
+ * @param mixed $year
3889
+ * @param mixed $month optional
3890
+ * @param int $day optional
3891
+ * @param int $week optional
3892
+ * @param int $hour optional
3893
+ * @param int $min optional
3894
+ * @param int $sec optional
3895
+ * @param bool $relatedStart optional
3896
+ * @param bool $before optional
3897
+ * @param array $params optional
3898
+ * @return bool
3899
+ */
3900
+ function setTrigger( $year, $month=null, $day=null, $week=FALSE, $hour=FALSE, $min=FALSE, $sec=FALSE, $relatedStart=TRUE, $before=TRUE, $params=FALSE ) {
3901
+ if( empty( $year ) && empty( $month ) && empty( $day ) && empty( $week ) && empty( $hour ) && empty( $min ) && empty( $sec ))
3902
+ if( $this->getConfig( 'allowEmpty' )) {
3903
+ $this->trigger = array( 'value' => null, 'params' => iCalUtilityFunctions::_setParams( $params ) );
3904
+ return TRUE;
3905
+ }
3906
+ else
3907
+ return FALSE;
3908
+ if( iCalUtilityFunctions::_isArrayTimestampDate( $year )) { // timestamp
3909
+ $params = iCalUtilityFunctions::_setParams( $month );
3910
+ $date = iCalUtilityFunctions::_timestamp2date( $year, 7 );
3911
+ foreach( $date as $k => $v )
3912
+ $$k = $v;
3913
+ }
3914
+ elseif( is_array( $year ) && ( is_array( $month ) || empty( $month ))) {
3915
+ $params = iCalUtilityFunctions::_setParams( $month );
3916
+ if(!(array_key_exists( 'year', $year ) && // exclude date-time
3917
+ array_key_exists( 'month', $year ) &&
3918
+ array_key_exists( 'day', $year ))) { // when this must be a duration
3919
+ if( isset( $params['RELATED'] ) && ( 'END' == strtoupper( $params['RELATED'] )))
3920
+ $relatedStart = FALSE;
3921
+ else
3922
+ $relatedStart = ( array_key_exists( 'relatedStart', $year ) && ( TRUE !== $year['relatedStart'] )) ? FALSE : TRUE;
3923
+ $before = ( array_key_exists( 'before', $year ) && ( TRUE !== $year['before'] )) ? FALSE : TRUE;
3924
+ }
3925
+ $SSYY = ( array_key_exists( 'year', $year )) ? $year['year'] : null;
3926
+ $month = ( array_key_exists( 'month', $year )) ? $year['month'] : null;
3927
+ $day = ( array_key_exists( 'day', $year )) ? $year['day'] : null;
3928
+ $week = ( array_key_exists( 'week', $year )) ? $year['week'] : null;
3929
+ $hour = ( array_key_exists( 'hour', $year )) ? $year['hour'] : 0; //null;
3930
+ $min = ( array_key_exists( 'min', $year )) ? $year['min'] : 0; //null;
3931
+ $sec = ( array_key_exists( 'sec', $year )) ? $year['sec'] : 0; //null;
3932
+ $year = $SSYY;
3933
+ }
3934
+ elseif(is_string( $year ) && ( is_array( $month ) || empty( $month ))) { // duration or date in a string
3935
+ $params = iCalUtilityFunctions::_setParams( $month );
3936
+ if( in_array( $year[0], array( 'P', '+', '-' ))) { // duration
3937
+ $relatedStart = ( isset( $params['RELATED'] ) && ( 'END' == strtoupper( $params['RELATED'] ))) ? FALSE : TRUE;
3938
+ $before = ( '-' == $year[0] ) ? TRUE : FALSE;
3939
+ if( 'P' != $year[0] )
3940
+ $year = substr( $year, 1 );
3941
+ $date = iCalUtilityFunctions::_duration_string( $year);
3942
+ }
3943
+ else // date
3944
+ $date = iCalUtilityFunctions::_date_time_string( $year, 7 );
3945
+ unset( $year, $month, $day );
3946
+ if( empty( $date ))
3947
+ $sec = 0;
3948
+ else
3949
+ foreach( $date as $k => $v )
3950
+ $$k = $v;
3951
+ }
3952
+ else // single values in function input parameters
3953
+ $params = iCalUtilityFunctions::_setParams( $params );
3954
+ if( !empty( $year ) && !empty( $month ) && !empty( $day )) { // date
3955
+ $params['VALUE'] = 'DATE-TIME';
3956
+ $hour = ( $hour ) ? $hour : 0;
3957
+ $min = ( $min ) ? $min : 0;
3958
+ $sec = ( $sec ) ? $sec : 0;
3959
+ $this->trigger = array( 'params' => $params );
3960
+ $this->trigger['value'] = array( 'year' => $year
3961
+ , 'month' => $month
3962
+ , 'day' => $day
3963
+ , 'hour' => $hour
3964
+ , 'min' => $min
3965
+ , 'sec' => $sec
3966
+ , 'tz' => 'Z' );
3967
+ return TRUE;
3968
+ }
3969
+ elseif(( empty( $year ) && empty( $month )) && // duration
3970
+ (( !empty( $week ) || ( 0 == $week )) ||
3971
+ ( !empty( $day ) || ( 0 == $day )) ||
3972
+ ( !empty( $hour ) || ( 0 == $hour )) ||
3973
+ ( !empty( $min ) || ( 0 == $min )) ||
3974
+ ( !empty( $sec ) || ( 0 == $sec )))) {
3975
+ unset( $params['RELATED'] ); // set at output creation (END only)
3976
+ unset( $params['VALUE'] ); // 'DURATION' default
3977
+ $this->trigger = array( 'params' => $params );
3978
+ $this->trigger['value'] = array();
3979
+ if( !empty( $week )) $this->trigger['value']['week'] = $week;
3980
+ if( !empty( $day )) $this->trigger['value']['day'] = $day;
3981
+ if( !empty( $hour )) $this->trigger['value']['hour'] = $hour;
3982
+ if( !empty( $min )) $this->trigger['value']['min'] = $min;
3983
+ if( !empty( $sec )) $this->trigger['value']['sec'] = $sec;
3984
+ if( empty( $this->trigger['value'] )) {
3985
+ $this->trigger['value']['sec'] = 0;
3986
+ $before = FALSE;
3987
+ }
3988
+ $relatedStart = ( FALSE !== $relatedStart ) ? TRUE : FALSE;
3989
+ $before = ( FALSE !== $before ) ? TRUE : FALSE;
3990
+ $this->trigger['value']['relatedStart'] = $relatedStart;
3991
+ $this->trigger['value']['before'] = $before;
3992
+ return TRUE;
3993
+ }
3994
+ return FALSE;
3995
+ }
3996
+ /*********************************************************************************/
3997
+ /**
3998
+ * Property Name: TZID
3999
+ */
4000
+ /**
4001
+ * creates formatted output for calendar component property tzid
4002
+ *
4003
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
4004
+ * @since 2.4.8 - 2008-10-21
4005
+ * @return string
4006
+ */
4007
+ function createTzid() {
4008
+ if( empty( $this->tzid )) return FALSE;
4009
+ if( empty( $this->tzid['value'] ))
4010
+ return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'TZID' ) : FALSE;
4011
+ $attributes = $this->_createParams( $this->tzid['params'] );
4012
+ return $this->_createElement( 'TZID', $attributes, $this->_strrep( $this->tzid['value'] ));
4013
+ }
4014
+ /**
4015
+ * set calendar component property tzid
4016
+ *
4017
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
4018
+ * @since 2.4.8 - 2008-11-04
4019
+ * @param string $value
4020
+ * @param array $params optional
4021
+ * @return bool
4022
+ */
4023
+ function setTzid( $value, $params=FALSE ) {
4024
+ if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = null; else return FALSE;
4025
+ $this->tzid = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
4026
+ return TRUE;
4027
+ }
4028
+ /*********************************************************************************/
4029
+ /**
4030
+ * .. .
4031
+ * Property Name: TZNAME
4032
+ */
4033
+ /**
4034
+ * creates formatted output for calendar component property tzname
4035
+ *
4036
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
4037
+ * @since 2.4.8 - 2008-10-21
4038
+ * @return string
4039
+ */
4040
+ function createTzname() {
4041
+ if( empty( $this->tzname )) return FALSE;
4042
+ $output = null;
4043
+ foreach( $this->tzname as $theName ) {
4044
+ if( !empty( $theName['value'] )) {
4045
+ $attributes = $this->_createParams( $theName['params'], array( 'LANGUAGE' ));
4046
+ $output .= $this->_createElement( 'TZNAME', $attributes, $this->_strrep( $theName['value'] ));
4047
+ }
4048
+ elseif( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( 'TZNAME' );
4049
+ }
4050
+ return $output;
4051
+ }
4052
+ /**
4053
+ * set calendar component property tzname
4054
+ *
4055
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
4056
+ * @since 2.5.1 - 2008-11-05
4057
+ * @param string $value
4058
+ * @param string $params, optional
4059
+ * @param integer $index, optional
4060
+ * @return bool
4061
+ */
4062
+ function setTzname( $value, $params=FALSE, $index=FALSE ) {
4063
+ if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = null; else return FALSE;
4064
+ iCalUtilityFunctions::_setMval( $this->tzname, $value, $params, FALSE, $index );
4065
+ return TRUE;
4066
+ }
4067
+ /*********************************************************************************/
4068
+ /**
4069
+ * Property Name: TZOFFSETFROM
4070
+ */
4071
+ /**
4072
+ * creates formatted output for calendar component property tzoffsetfrom
4073
+ *
4074
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
4075
+ * @since 2.4.8 - 2008-10-21
4076
+ * @return string
4077
+ */
4078
+ function createTzoffsetfrom() {
4079
+ if( empty( $this->tzoffsetfrom )) return FALSE;
4080
+ if( empty( $this->tzoffsetfrom['value'] ))
4081
+ return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'TZOFFSETFROM' ) : FALSE;
4082
+ $attributes = $this->_createParams( $this->tzoffsetfrom['params'] );
4083
+ return $this->_createElement( 'TZOFFSETFROM', $attributes, $this->tzoffsetfrom['value'] );
4084
+ }
4085
+ /**
4086
+ * set calendar component property tzoffsetfrom
4087
+ *
4088
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
4089
+ * @since 2.4.8 - 2008-11-04
4090
+ * @param string $value
4091
+ * @param string $params optional
4092
+ * @return bool
4093
+ */
4094
+ function setTzoffsetfrom( $value, $params=FALSE ) {
4095
+ if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = null; else return FALSE;
4096
+ $this->tzoffsetfrom = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
4097
+ return TRUE;
4098
+ }
4099
+ /*********************************************************************************/
4100
+ /**
4101
+ * Property Name: TZOFFSETTO
4102
+ */
4103
+ /**
4104
+ * creates formatted output for calendar component property tzoffsetto
4105
+ *
4106
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
4107
+ * @since 2.4.8 - 2008-10-21
4108
+ * @return string
4109
+ */
4110
+ function createTzoffsetto() {
4111
+ if( empty( $this->tzoffsetto )) return FALSE;
4112
+ if( empty( $this->tzoffsetto['value'] ))
4113
+ return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'TZOFFSETTO' ) : FALSE;
4114
+ $attributes = $this->_createParams( $this->tzoffsetto['params'] );
4115
+ return $this->_createElement( 'TZOFFSETTO', $attributes, $this->tzoffsetto['value'] );
4116
+ }
4117
+ /**
4118
+ * set calendar component property tzoffsetto
4119
+ *
4120
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
4121
+ * @since 2.4.8 - 2008-11-04
4122
+ * @param string $value
4123
+ * @param string $params optional
4124
+ * @return bool
4125
+ */
4126
+ function setTzoffsetto( $value, $params=FALSE ) {
4127
+ if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = null; else return FALSE;
4128
+ $this->tzoffsetto = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
4129
+ return TRUE;
4130
+ }
4131
+ /*********************************************************************************/
4132
+ /**
4133
+ * Property Name: TZURL
4134
+ */
4135
+ /**
4136
+ * creates formatted output for calendar component property tzurl
4137
+ *
4138
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
4139
+ * @since 2.4.8 - 2008-10-21
4140
+ * @return string
4141
+ */
4142
+ function createTzurl() {
4143
+ if( empty( $this->tzurl )) return FALSE;
4144
+ if( empty( $this->tzurl['value'] ))
4145
+ return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'TZURL' ) : FALSE;
4146
+ $attributes = $this->_createParams( $this->tzurl['params'] );
4147
+ return $this->_createElement( 'TZURL', $attributes, $this->tzurl['value'] );
4148
+ }
4149
+ /**
4150
+ * set calendar component property tzurl
4151
+ *
4152
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
4153
+ * @since 2.4.8 - 2008-11-04
4154
+ * @param string $value
4155
+ * @param string $params optional
4156
+ * @return boll
4157
+ */
4158
+ function setTzurl( $value, $params=FALSE ) {
4159
+ if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = null; else return FALSE;
4160
+ $this->tzurl = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
4161
+ return TRUE;
4162
+ }
4163
+ /*********************************************************************************/
4164
+ /**
4165
+ * Property Name: UID
4166
+ */
4167
+ /**
4168
+ * creates formatted output for calendar component property uid
4169
+ *
4170
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
4171
+ * @since 0.9.7 - 2006-11-20
4172
+ * @return string
4173
+ */
4174
+ function createUid() {
4175
+ if( 0 >= count( $this->uid ))
4176
+ $this->_makeuid();
4177
+ $attributes = $this->_createParams( $this->uid['params'] );
4178
+ return $this->_createElement( 'UID', $attributes, $this->uid['value'] );
4179
+ }
4180
+ /**
4181
+ * create an unique id for this calendar component object instance
4182
+ *
4183
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
4184
+ * @since 2.2.7 - 2007-09-04
4185
+ * @return void
4186
+ */
4187
+ function _makeUid() {
4188
+ $date = date('Ymd\THisT');
4189
+ $unique = substr(microtime(), 2, 4);
4190
+ $base = 'aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPrRsStTuUvVxXuUvVwWzZ1234567890';
4191
+ $start = 0;
4192
+ $end = strlen( $base ) - 1;
4193
+ $length = 6;
4194
+ $str = null;
4195
+ for( $p = 0; $p < $length; $p++ )
4196
+ $unique .= $base{mt_rand( $start, $end )};
4197
+ $this->uid = array( 'params' => null );
4198
+ $this->uid['value'] = $date.'-'.$unique.'@'.$this->getConfig( 'unique_id' );
4199
+ }
4200
+ /**
4201
+ * set calendar component property uid
4202
+ *
4203
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
4204
+ * @since 2.4.8 - 2008-11-04
4205
+ * @param string $value
4206
+ * @param string $params optional
4207
+ * @return bool
4208
+ */
4209
+ function setUid( $value, $params=FALSE ) {
4210
+ if( empty( $value )) return FALSE; // no allowEmpty check here !!!!
4211
+ $this->uid = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
4212
+ return TRUE;
4213
+ }
4214
+ /*********************************************************************************/
4215
+ /**
4216
+ * Property Name: URL
4217
+ */
4218
+ /**
4219
+ * creates formatted output for calendar component property url
4220
+ *
4221
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
4222
+ * @since 2.4.8 - 2008-10-21
4223
+ * @return string
4224
+ */
4225
+ function createUrl() {
4226
+ if( empty( $this->url )) return FALSE;
4227
+ if( empty( $this->url['value'] ))
4228
+ return ( $this->getConfig( 'allowEmpty' )) ? $this->_createElement( 'URL' ) : FALSE;
4229
+ $attributes = $this->_createParams( $this->url['params'] );
4230
+ return $this->_createElement( 'URL', $attributes, $this->url['value'] );
4231
+ }
4232
+ /**
4233
+ * set calendar component property url
4234
+ *
4235
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
4236
+ * @since 2.4.8 - 2008-11-04
4237
+ * @param string $value
4238
+ * @param string $params optional
4239
+ * @return bool
4240
+ */
4241
+ function setUrl( $value, $params=FALSE ) {
4242
+ if( empty( $value )) if( $this->getConfig( 'allowEmpty' )) $value = null; else return FALSE;
4243
+ $this->url = array( 'value' => $value, 'params' => iCalUtilityFunctions::_setParams( $params ));
4244
+ return TRUE;
4245
+ }
4246
+ /*********************************************************************************/
4247
+ /**
4248
+ * Property Name: x-prop
4249
+ */
4250
+ /**
4251
+ * creates formatted output for calendar component property x-prop
4252
+ *
4253
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
4254
+ * @since 2.9.3 - 2011-05-14
4255
+ * @return string
4256
+ */
4257
+ function createXprop() {
4258
+ if( empty( $this->xprop )) return FALSE;
4259
+ $output = null;
4260
+ foreach( $this->xprop as $label => $xpropPart ) {
4261
+ if( !isset($xpropPart['value']) || ( empty( $xpropPart['value'] ) && !is_numeric( $xpropPart['value'] ))) {
4262
+ if( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( $label );
4263
+ continue;
4264
+ }
4265
+ $attributes = $this->_createParams( $xpropPart['params'], array( 'LANGUAGE' ));
4266
+ if( is_array( $xpropPart['value'] )) {
4267
+ foreach( $xpropPart['value'] as $pix => $theXpart )
4268
+ $xpropPart['value'][$pix] = $this->_strrep( $theXpart );
4269
+ $xpropPart['value'] = implode( ',', $xpropPart['value'] );
4270
+ }
4271
+ else
4272
+ $xpropPart['value'] = $this->_strrep( $xpropPart['value'] );
4273
+ $output .= $this->_createElement( $label, $attributes, $xpropPart['value'] );
4274
+ }
4275
+ return $output;
4276
+ }
4277
+ /**
4278
+ * set calendar component property x-prop
4279
+ *
4280
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
4281
+ * @since 2.9.3 - 2011-05-14
4282
+ * @param string $label
4283
+ * @param mixed $value
4284
+ * @param array $params optional
4285
+ * @return bool
4286
+ */
4287
+ function setXprop( $label, $value, $params=FALSE ) {
4288
+ if( empty( $label )) return;
4289
+ if( empty( $value ) && !is_numeric( $value )) if( $this->getConfig( 'allowEmpty' )) $value = null; else return FALSE;
4290
+ $xprop = array( 'value' => $value );
4291
+ $xprop['params'] = iCalUtilityFunctions::_setParams( $params );
4292
+ if( !is_array( $this->xprop )) $this->xprop = array();
4293
+ $this->xprop[strtoupper( $label )] = $xprop;
4294
+ return TRUE;
4295
+ }
4296
+ /*********************************************************************************/
4297
+ /*********************************************************************************/
4298
+ /**
4299
+ * create element format parts
4300
+ *
4301
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
4302
+ * @since 2.0.6 - 2006-06-20
4303
+ * @return string
4304
+ */
4305
+ function _createFormat() {
4306
+ $objectname = null;
4307
+ switch( $this->format ) {
4308
+ case 'xcal':
4309
+ $objectname = ( isset( $this->timezonetype )) ?
4310
+ strtolower( $this->timezonetype ) : strtolower( $this->objName );
4311
+ $this->componentStart1 = $this->elementStart1 = '<';
4312
+ $this->componentStart2 = $this->elementStart2 = '>';
4313
+ $this->componentEnd1 = $this->elementEnd1 = '</';
4314
+ $this->componentEnd2 = $this->elementEnd2 = '>'.$this->nl;
4315
+ $this->intAttrDelimiter = '<!-- -->';
4316
+ $this->attributeDelimiter = $this->nl;
4317
+ $this->valueInit = null;
4318
+ break;
4319
+ default:
4320
+ $objectname = ( isset( $this->timezonetype )) ?
4321
+ strtoupper( $this->timezonetype ) : strtoupper( $this->objName );
4322
+ $this->componentStart1 = 'BEGIN:';
4323
+ $this->componentStart2 = null;
4324
+ $this->componentEnd1 = 'END:';
4325
+ $this->componentEnd2 = $this->nl;
4326
+ $this->elementStart1 = null;
4327
+ $this->elementStart2 = null;
4328
+ $this->elementEnd1 = null;
4329
+ $this->elementEnd2 = $this->nl;
4330
+ $this->intAttrDelimiter = '<!-- -->';
4331
+ $this->attributeDelimiter = ';';
4332
+ $this->valueInit = ':';
4333
+ break;
4334
+ }
4335
+ return $objectname;
4336
+ }
4337
+ /**
4338
+ * creates formatted output for calendar component property
4339
+ *
4340
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
4341
+ * @since 2.6.22 - 2010-12-06
4342
+ * @param string $label property name
4343
+ * @param string $attributes property attributes
4344
+ * @param string $content property content (optional)
4345
+ * @return string
4346
+ */
4347
+ function _createElement( $label, $attributes=null, $content=FALSE ) {
4348
+ switch( $this->format ) {
4349
+ case 'xcal':
4350
+ $label = strtolower( $label );
4351
+ break;
4352
+ default:
4353
+ $label = strtoupper( $label );
4354
+ break;
4355
+ }
4356
+ $output = $this->elementStart1.$label;
4357
+ $categoriesAttrLang = null;
4358
+ $attachInlineBinary = FALSE;
4359
+ $attachfmttype = null;
4360
+ if( !empty( $attributes )) {
4361
+ $attributes = trim( $attributes );
4362
+ if ( 'xcal' == $this->format) {
4363
+ $attributes2 = explode( $this->intAttrDelimiter, $attributes );
4364
+ $attributes = null;
4365
+ foreach( $attributes2 as $attribute ) {
4366
+ $attrKVarr = explode( '=', $attribute );
4367
+ if( empty( $attrKVarr[0] ))
4368
+ continue;
4369
+ if( !isset( $attrKVarr[1] )) {
4370
+ $attrValue = $attrKVarr[0];
4371
+ $attrKey = null;
4372
+ }
4373
+ elseif( 2 == count( $attrKVarr)) {
4374
+ $attrKey = strtolower( $attrKVarr[0] );
4375
+ $attrValue = $attrKVarr[1];
4376
+ }
4377
+ else {
4378
+ $attrKey = strtolower( $attrKVarr[0] );
4379
+ unset( $attrKVarr[0] );
4380
+ $attrValue = implode( '=', $attrKVarr );
4381
+ }
4382
+ if(( 'attach' == $label ) && ( in_array( $attrKey, array( 'fmttype', 'encoding', 'value' )))) {
4383
+ $attachInlineBinary = TRUE;
4384
+ if( 'fmttype' == $attrKey )
4385
+ $attachfmttype = $attrKey.'='.$attrValue;
4386
+ continue;
4387
+ }
4388
+ elseif(( 'categories' == $label ) && ( 'language' == $attrKey ))
4389
+ $categoriesAttrLang = $attrKey.'='.$attrValue;
4390
+ else {
4391
+ $attributes .= ( empty( $attributes )) ? ' ' : $this->attributeDelimiter.' ';
4392
+ $attributes .= ( !empty( $attrKey )) ? $attrKey.'=' : null;
4393
+ if(( '"' == substr( $attrValue, 0, 1 )) && ( '"' == substr( $attrValue, -1 ))) {
4394
+ $attrValue = substr( $attrValue, 1, ( strlen( $attrValue ) - 2 ));
4395
+ $attrValue = str_replace( '"', '', $attrValue );
4396
+ }
4397
+ $attributes .= '"'.htmlspecialchars( $attrValue ).'"';
4398
+ }
4399
+ }
4400
+ }
4401
+ else {
4402
+ $attributes = str_replace( $this->intAttrDelimiter, $this->attributeDelimiter, $attributes );
4403
+ }
4404
+ }
4405
+ if(((( 'attach' == $label ) && !$attachInlineBinary ) ||
4406
+ ( in_array( $label, array( 'tzurl', 'url' )))) && ( 'xcal' == $this->format)) {
4407
+ $pos = strrpos($content, "/");
4408
+ $docname = ( $pos !== false) ? substr( $content, (1 - strlen( $content ) + $pos )) : $content;
4409
+ $this->xcaldecl[] = array( 'xmldecl' => 'ENTITY'
4410
+ , 'uri' => $docname
4411
+ , 'ref' => 'SYSTEM'
4412
+ , 'external' => $content
4413
+ , 'type' => 'NDATA'
4414
+ , 'type2' => 'BINERY' );
4415
+ $attributes .= ( empty( $attributes )) ? ' ' : $this->attributeDelimiter.' ';
4416
+ $attributes .= 'uri="'.$docname.'"';
4417
+ $content = null;
4418
+ if( 'attach' == $label ) {
4419
+ $attributes = str_replace( $this->attributeDelimiter, $this->intAttrDelimiter, $attributes );
4420
+ $content = $this->_createElement( 'extref', $attributes, null );
4421
+ $attributes = null;
4422
+ }
4423
+ }
4424
+ elseif(( 'attach' == $label ) && $attachInlineBinary && ( 'xcal' == $this->format)) {
4425
+ $content = $this->nl.$this->_createElement( 'b64bin', $attachfmttype, $content ); // max one attribute
4426
+ }
4427
+ $output .= $attributes;
4428
+ if( !$content && ( '0' != $content )) {
4429
+ switch( $this->format ) {
4430
+ case 'xcal':
4431
+ $output .= ' /';
4432
+ $output .= $this->elementStart2;
4433
+ return $output;
4434
+ break;
4435
+ default:
4436
+ $output .= $this->elementStart2.$this->valueInit;
4437
+ return $this->_size75( $output );
4438
+ break;
4439
+ }
4440
+ }
4441
+ $output .= $this->elementStart2;
4442
+ $output .= $this->valueInit.$content;
4443
+ switch( $this->format ) {
4444
+ case 'xcal':
4445
+ return $output.$this->elementEnd1.$label.$this->elementEnd2;
4446
+ break;
4447
+ default:
4448
+ return $this->_size75( $output );
4449
+ break;
4450
+ }
4451
+ }
4452
+ /**
4453
+ * creates formatted output for calendar component property parameters
4454
+ *
4455
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
4456
+ * @since 2.6.33 - 2010-12-18
4457
+ * @param array $params optional
4458
+ * @param array $ctrKeys optional
4459
+ * @return string
4460
+ */
4461
+ function _createParams( $params=array(), $ctrKeys=array() ) {
4462
+ if( !is_array( $params ) || empty( $params ))
4463
+ $params = array();
4464
+ $attrLANG = $attr1 = $attr2 = $lang = null;
4465
+ $CNattrKey = ( in_array( 'CN', $ctrKeys )) ? TRUE : FALSE ;
4466
+ $LANGattrKey = ( in_array( 'LANGUAGE', $ctrKeys )) ? TRUE : FALSE ;
4467
+ $CNattrExist = $LANGattrExist = FALSE;
4468
+ $xparams = array();
4469
+ foreach( $params as $paramKey => $paramValue ) {
4470
+ if( ctype_digit( (string) $paramKey )) {
4471
+ $xparams[] = $paramValue;
4472
+ continue;
4473
+ }
4474
+ $paramKey = strtoupper( $paramKey );
4475
+ if( !in_array( $paramKey, array( 'ALTREP', 'CN', 'DIR', 'ENCODING', 'FMTTYPE', 'LANGUAGE', 'RANGE', 'RELTYPE', 'SENT-BY', 'TZID', 'VALUE' )))
4476
+ $xparams[$paramKey] = $paramValue;
4477
+ else
4478
+ $params[$paramKey] = $paramValue;
4479
+ }
4480
+ ksort( $xparams, SORT_STRING );
4481
+ foreach( $xparams as $paramKey => $paramValue ) {
4482
+ if( ctype_digit( (string) $paramKey ))
4483
+ $attr2 .= $this->intAttrDelimiter.$paramValue;
4484
+ else
4485
+ $attr2 .= $this->intAttrDelimiter."$paramKey=$paramValue";
4486
+ }
4487
+ if( isset( $params['FMTTYPE'] ) && !in_array( 'FMTTYPE', $ctrKeys )) {
4488
+ $attr1 .= $this->intAttrDelimiter.'FMTTYPE='.$params['FMTTYPE'].$attr2;
4489
+ $attr2 = null;
4490
+ }
4491
+ if( isset( $params['ENCODING'] ) && !in_array( 'ENCODING', $ctrKeys )) {
4492
+ if( !empty( $attr2 )) {
4493
+ $attr1 .= $attr2;
4494
+ $attr2 = null;
4495
+ }
4496
+ $attr1 .= $this->intAttrDelimiter.'ENCODING='.$params['ENCODING'];
4497
+ }
4498
+ if( isset( $params['VALUE'] ) && !in_array( 'VALUE', $ctrKeys ))
4499
+ $attr1 .= $this->intAttrDelimiter.'VALUE='.$params['VALUE'];
4500
+ if( isset( $params['TZID'] ) && !in_array( 'TZID', $ctrKeys ))
4501
+ $attr1 .= $this->intAttrDelimiter.'TZID='.$params['TZID'];
4502
+ if( isset( $params['RANGE'] ) && !in_array( 'RANGE', $ctrKeys ))
4503
+ $attr1 .= $this->intAttrDelimiter.'RANGE='.$params['RANGE'];
4504
+ if( isset( $params['RELTYPE'] ) && !in_array( 'RELTYPE', $ctrKeys ))
4505
+ $attr1 .= $this->intAttrDelimiter.'RELTYPE='.$params['RELTYPE'];
4506
+ if( isset( $params['CN'] ) && $CNattrKey ) {
4507
+ $attr1 = $this->intAttrDelimiter.'CN="'.$params['CN'].'"';
4508
+ $CNattrExist = TRUE;
4509
+ }
4510
+ if( isset( $params['DIR'] ) && in_array( 'DIR', $ctrKeys ))
4511
+ $attr1 .= $this->intAttrDelimiter.'DIR="'.$params['DIR'].'"';
4512
+ if( isset( $params['SENT-BY'] ) && in_array( 'SENT-BY', $ctrKeys ))
4513
+ $attr1 .= $this->intAttrDelimiter.'SENT-BY="'.$params['SENT-BY'].'"';
4514
+ if( isset( $params['ALTREP'] ) && in_array( 'ALTREP', $ctrKeys ))
4515
+ $attr1 .= $this->intAttrDelimiter.'ALTREP="'.$params['ALTREP'].'"';
4516
+ if( isset( $params['LANGUAGE'] ) && $LANGattrKey ) {
4517
+ $attrLANG .= $this->intAttrDelimiter.'LANGUAGE='.$params['LANGUAGE'];
4518
+ $LANGattrExist = TRUE;
4519
+ }
4520
+ if( !$LANGattrExist ) {
4521
+ $lang = $this->getConfig( 'language' );
4522
+ if(( $CNattrExist || $LANGattrKey ) && $lang )
4523
+ $attrLANG .= $this->intAttrDelimiter.'LANGUAGE='.$lang;
4524
+ }
4525
+ return $attr1.$attrLANG.$attr2;
4526
+ }
4527
+ /**
4528
+ * creates formatted output for calendar component property data value type recur
4529
+ *
4530
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
4531
+ * @since 2.4.8 - 2008-10-22
4532
+ * @param array $recurlabel
4533
+ * @param array $recurdata
4534
+ * @return string
4535
+ */
4536
+ function _format_recur( $recurlabel, $recurdata ) {
4537
+ $output = null;
4538
+ foreach( $recurdata as $therule ) {
4539
+ if( empty( $therule['value'] )) {
4540
+ if( $this->getConfig( 'allowEmpty' )) $output .= $this->_createElement( $recurlabel );
4541
+ continue;
4542
+ }
4543
+ $attributes = ( isset( $therule['params'] )) ? $this->_createParams( $therule['params'] ) : null;
4544
+ $content1 = $content2 = null;
4545
+ foreach( $therule['value'] as $rulelabel => $rulevalue ) {
4546
+ switch( $rulelabel ) {
4547
+ case 'FREQ': {
4548
+ $content1 .= "FREQ=$rulevalue";
4549
+ break;
4550
+ }
4551
+ case 'UNTIL': {
4552
+ $content2 .= ";UNTIL=";
4553
+ $content2 .= iCalUtilityFunctions::_format_date_time( $rulevalue );
4554
+ break;
4555
+ }
4556
+ case 'COUNT':
4557
+ case 'INTERVAL':
4558
+ case 'WKST': {
4559
+ $content2 .= ";$rulelabel=$rulevalue";
4560
+ break;
4561
+ }
4562
+ case 'BYSECOND':
4563
+ case 'BYMINUTE':
4564
+ case 'BYHOUR':
4565
+ case 'BYMONTHDAY':
4566
+ case 'BYYEARDAY':
4567
+ case 'BYWEEKNO':
4568
+ case 'BYMONTH':
4569
+ case 'BYSETPOS': {
4570
+ $content2 .= ";$rulelabel=";
4571
+ if( is_array( $rulevalue )) {
4572
+ foreach( $rulevalue as $vix => $valuePart ) {
4573
+ $content2 .= ( $vix ) ? ',' : null;
4574
+ $content2 .= $valuePart;
4575
+ }
4576
+ }
4577
+ else
4578
+ $content2 .= $rulevalue;
4579
+ break;
4580
+ }
4581
+ case 'BYDAY': {
4582
+ $content2 .= ";$rulelabel=";
4583
+ $bydaycnt = 0;
4584
+ foreach( $rulevalue as $vix => $valuePart ) {
4585
+ $content21 = $content22 = null;
4586
+ if( is_array( $valuePart )) {
4587
+ $content2 .= ( $bydaycnt ) ? ',' : null;
4588
+ foreach( $valuePart as $vix2 => $valuePart2 ) {
4589
+ if( 'DAY' != strtoupper( $vix2 ))
4590
+ $content21 .= $valuePart2;
4591
+ else
4592
+ $content22 .= $valuePart2;
4593
+ }
4594
+ $content2 .= $content21.$content22;
4595
+ $bydaycnt++;
4596
+ }
4597
+ else {
4598
+ $content2 .= ( $bydaycnt ) ? ',' : null;
4599
+ if( 'DAY' != strtoupper( $vix ))
4600
+ $content21 .= $valuePart;
4601
+ else {
4602
+ $content22 .= $valuePart;
4603
+ $bydaycnt++;
4604
+ }
4605
+ $content2 .= $content21.$content22;
4606
+ }
4607
+ }
4608
+ break;
4609
+ }
4610
+ default: {
4611
+ $content2 .= ";$rulelabel=$rulevalue";
4612
+ break;
4613
+ }
4614
+ }
4615
+ }
4616
+ $output .= $this->_createElement( $recurlabel, $attributes, $content1.$content2 );
4617
+ }
4618
+ return $output;
4619
+ }
4620
+ /**
4621
+ * check if property not exists within component
4622
+ *
4623
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
4624
+ * @since 2.5.1 - 2008-10-15
4625
+ * @param string $propName
4626
+ * @return bool
4627
+ */
4628
+ function _notExistProp( $propName ) {
4629
+ if( empty( $propName )) return FALSE; // when deleting x-prop, an empty propName may be used=allowed
4630
+ $propName = strtolower( $propName );
4631
+ if( 'last-modified' == $propName ) { if( !isset( $this->lastmodified )) return TRUE; }
4632
+ elseif( 'percent-complete' == $propName ) { if( !isset( $this->percentcomplete )) return TRUE; }
4633
+ elseif( 'recurrence-id' == $propName ) { if( !isset( $this->recurrenceid )) return TRUE; }
4634
+ elseif( 'related-to' == $propName ) { if( !isset( $this->relatedto )) return TRUE; }
4635
+ elseif( 'request-status' == $propName ) { if( !isset( $this->requeststatus )) return TRUE; }
4636
+ elseif(( 'x-' != substr($propName,0,2)) && !isset( $this->$propName )) return TRUE;
4637
+ return FALSE;
4638
+ }
4639
+ /*********************************************************************************/
4640
+ /*********************************************************************************/
4641
+ /**
4642
+ * get general component config variables or info about subcomponents
4643
+ *
4644
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
4645
+ * @since 2.9.6 - 2011-05-14
4646
+ * @param mixed $config
4647
+ * @return value
4648
+ */
4649
+ function getConfig( $config = FALSE) {
4650
+ if( !$config ) {
4651
+ $return = array();
4652
+ $return['ALLOWEMPTY'] = $this->getConfig( 'ALLOWEMPTY' );
4653
+ $return['FORMAT'] = $this->getConfig( 'FORMAT' );
4654
+ if( FALSE !== ( $lang = $this->getConfig( 'LANGUAGE' )))
4655
+ $return['LANGUAGE'] = $lang;
4656
+ $return['NEWLINECHAR'] = $this->getConfig( 'NEWLINECHAR' );
4657
+ $return['TZTD'] = $this->getConfig( 'TZID' );
4658
+ $return['UNIQUE_ID'] = $this->getConfig( 'UNIQUE_ID' );
4659
+ return $return;
4660
+ }
4661
+ switch( strtoupper( $config )) {
4662
+ case 'ALLOWEMPTY':
4663
+ return $this->allowEmpty;
4664
+ break;
4665
+ case 'COMPSINFO':
4666
+ unset( $this->compix );
4667
+ $info = array();
4668
+ if( isset( $this->components )) {
4669
+ foreach( $this->components as $cix => $component ) {
4670
+ if( empty( $component )) continue;
4671
+ $info[$cix]['ordno'] = $cix + 1;
4672
+ $info[$cix]['type'] = $component->objName;
4673
+ $info[$cix]['uid'] = $component->getProperty( 'uid' );
4674
+ $info[$cix]['props'] = $component->getConfig( 'propinfo' );
4675
+ $info[$cix]['sub'] = $component->getConfig( 'compsinfo' );
4676
+ }
4677
+ }
4678
+ return $info;
4679
+ break;
4680
+ case 'FORMAT':
4681
+ return $this->format;
4682
+ break;
4683
+ case 'LANGUAGE':
4684
+ // get language for calendar component as defined in [RFC 1766]
4685
+ return $this->language;
4686
+ break;
4687
+ case 'NL':
4688
+ case 'NEWLINECHAR':
4689
+ return $this->nl;
4690
+ break;
4691
+ case 'PROPINFO':
4692
+ $output = array();
4693
+ if( !in_array( $this->objName, array( 'valarm', 'vtimezone', 'standard', 'daylight' ))) {
4694
+ if( empty( $this->uid['value'] )) $this->_makeuid();
4695
+ $output['UID'] = 1;
4696
+ }
4697
+ if( !empty( $this->dtstamp )) $output['DTSTAMP'] = 1;
4698
+ if( !empty( $this->summary )) $output['SUMMARY'] = 1;
4699
+ if( !empty( $this->description )) $output['DESCRIPTION'] = count( $this->description );
4700
+ if( !empty( $this->dtstart )) $output['DTSTART'] = 1;
4701
+ if( !empty( $this->dtend )) $output['DTEND'] = 1;
4702
+ if( !empty( $this->due )) $output['DUE'] = 1;
4703
+ if( !empty( $this->duration )) $output['DURATION'] = 1;
4704
+ if( !empty( $this->rrule )) $output['RRULE'] = count( $this->rrule );
4705
+ if( !empty( $this->rdate )) $output['RDATE'] = count( $this->rdate );
4706
+ if( !empty( $this->exdate )) $output['EXDATE'] = count( $this->exdate );
4707
+ if( !empty( $this->exrule )) $output['EXRULE'] = count( $this->exrule );
4708
+ if( !empty( $this->action )) $output['ACTION'] = 1;
4709
+ if( !empty( $this->attach )) $output['ATTACH'] = count( $this->attach );
4710
+ if( !empty( $this->attendee )) $output['ATTENDEE'] = count( $this->attendee );
4711
+ if( !empty( $this->categories )) $output['CATEGORIES'] = count( $this->categories );
4712
+ if( !empty( $this->class )) $output['CLASS'] = 1;
4713
+ if( !empty( $this->comment )) $output['COMMENT'] = count( $this->comment );
4714
+ if( !empty( $this->completed )) $output['COMPLETED'] = 1;
4715
+ if( !empty( $this->contact )) $output['CONTACT'] = count( $this->contact );
4716
+ if( !empty( $this->created )) $output['CREATED'] = 1;
4717
+ if( !empty( $this->freebusy )) $output['FREEBUSY'] = count( $this->freebusy );
4718
+ if( !empty( $this->geo )) $output['GEO'] = 1;
4719
+ if( !empty( $this->lastmodified )) $output['LAST-MODIFIED'] = 1;
4720
+ if( !empty( $this->location )) $output['LOCATION'] = 1;
4721
+ if( !empty( $this->organizer )) $output['ORGANIZER'] = 1;
4722
+ if( !empty( $this->percentcomplete )) $output['PERCENT-COMPLETE'] = 1;
4723
+ if( !empty( $this->priority )) $output['PRIORITY'] = 1;
4724
+ if( !empty( $this->recurrenceid )) $output['RECURRENCE-ID'] = 1;
4725
+ if( !empty( $this->relatedto )) $output['RELATED-TO'] = count( $this->relatedto );
4726
+ if( !empty( $this->repeat )) $output['REPEAT'] = 1;
4727
+ if( !empty( $this->requeststatus )) $output['REQUEST-STATUS'] = count( $this->requeststatus );
4728
+ if( !empty( $this->resources )) $output['RESOURCES'] = count( $this->resources );
4729
+ if( !empty( $this->sequence )) $output['SEQUENCE'] = 1;
4730
+ if( !empty( $this->sequence )) $output['SEQUENCE'] = 1;
4731
+ if( !empty( $this->status )) $output['STATUS'] = 1;
4732
+ if( !empty( $this->transp )) $output['TRANSP'] = 1;
4733
+ if( !empty( $this->trigger )) $output['TRIGGER'] = 1;
4734
+ if( !empty( $this->tzid )) $output['TZID'] = 1;
4735
+ if( !empty( $this->tzname )) $output['TZNAME'] = count( $this->tzname );
4736
+ if( !empty( $this->tzoffsetfrom )) $output['TZOFFSETFROM'] = 1;
4737
+ if( !empty( $this->tzoffsetto )) $output['TZOFFSETTO'] = 1;
4738
+ if( !empty( $this->tzurl )) $output['TZURL'] = 1;
4739
+ if( !empty( $this->url )) $output['URL'] = 1;
4740
+ if( !empty( $this->xprop )) $output['X-PROP'] = count( $this->xprop );
4741
+ return $output;
4742
+ break;
4743
+ case 'TZID':
4744
+ return $this->dtzid;
4745
+ break;
4746
+ case 'UNIQUE_ID':
4747
+ if( empty( $this->unique_id ))
4748
+ $this->unique_id = ( isset( $_SERVER['SERVER_NAME'] )) ? gethostbyname( $_SERVER['SERVER_NAME'] ) : 'localhost';
4749
+ return $this->unique_id;
4750
+ break;
4751
+ }
4752
+ }
4753
+ /**
4754
+ * general component config setting
4755
+ *
4756
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
4757
+ * @since 2.9.6 - 2011-05-14
4758
+ * @param mixed $config
4759
+ * @param string $value
4760
+ * @param bool $softUpdate
4761
+ * @return void
4762
+ */
4763
+ function setConfig( $config, $value = FALSE, $softUpdate = FALSE ) {
4764
+ if( is_array( $config )) {
4765
+ foreach( $config as $cKey => $cValue ) {
4766
+ if( FALSE === $this->setConfig( $cKey, $cValue, $softUpdate ))
4767
+ return FALSE;
4768
+ }
4769
+ return TRUE;
4770
+ }
4771
+ $res = FALSE;
4772
+ switch( strtoupper( $config )) {
4773
+ case 'ALLOWEMPTY':
4774
+ $this->allowEmpty = $value;
4775
+ $subcfg = array( 'ALLOWEMPTY' => $value );
4776
+ $res = TRUE;
4777
+ break;
4778
+ case 'FORMAT':
4779
+ $value = trim( strtolower( $value ));
4780
+ $this->format = $value;
4781
+ $this->_createFormat();
4782
+ $subcfg = array( 'FORMAT' => $value );
4783
+ $res = TRUE;
4784
+ break;
4785
+ case 'LANGUAGE':
4786
+ // set language for calendar component as defined in [RFC 1766]
4787
+ $value = trim( $value );
4788
+ if( empty( $this->language ) || !$softUpdate )
4789
+ $this->language = $value;
4790
+ $subcfg = array( 'LANGUAGE' => $value );
4791
+ $res = TRUE;
4792
+ break;
4793
+ case 'NL':
4794
+ case 'NEWLINECHAR':
4795
+ $this->nl = $value;
4796
+ $subcfg = array( 'NL' => $value );
4797
+ $res = TRUE;
4798
+ break;
4799
+ case 'TZID':
4800
+ $this->dtzid = $value;
4801
+ $subcfg = array( 'TZID' => $value );
4802
+ $res = TRUE;
4803
+ break;
4804
+ case 'UNIQUE_ID':
4805
+ $value = trim( $value );
4806
+ $this->unique_id = $value;
4807
+ $subcfg = array( 'UNIQUE_ID' => $value );
4808
+ $res = TRUE;
4809
+ break;
4810
+ default: // any unvalid config key.. .
4811
+ return TRUE;
4812
+ }
4813
+ if( !$res ) return FALSE;
4814
+ if( isset( $subcfg ) && !empty( $this->components )) {
4815
+ foreach( $subcfg as $cfgkey => $cfgvalue ) {
4816
+ foreach( $this->components as $cix => $component ) {
4817
+ $res = $component->setConfig( $cfgkey, $cfgvalue, $softUpdate );
4818
+ if( !$res )
4819
+ break 2;
4820
+ $this->components[$cix] = $component->copy(); // PHP4 compliant
4821
+ }
4822
+ }
4823
+ }
4824
+ return $res;
4825
+ }
4826
+ /*********************************************************************************/
4827
+ /**
4828
+ * delete component property value
4829
+ *
4830
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
4831
+ * @since 2.8.8 - 2011-03-15
4832
+ * @param mixed $propName, bool FALSE => X-property
4833
+ * @param int $propix, optional, if specific property is wanted in case of multiply occurences
4834
+ * @return bool, if successfull delete TRUE
4835
+ */
4836
+ function deleteProperty( $propName=FALSE, $propix=FALSE ) {
4837
+ if( $this->_notExistProp( $propName )) return FALSE;
4838
+ $propName = strtoupper( $propName );
4839
+ if( in_array( $propName, array( 'ATTACH', 'ATTENDEE', 'CATEGORIES', 'COMMENT', 'CONTACT', 'DESCRIPTION', 'EXDATE', 'EXRULE',
4840
+ 'FREEBUSY', 'RDATE', 'RELATED-TO', 'RESOURCES', 'RRULE', 'REQUEST-STATUS', 'TZNAME', 'X-PROP' ))) {
4841
+ if( !$propix )
4842
+ $propix = ( isset( $this->propdelix[$propName] ) && ( 'X-PROP' != $propName )) ? $this->propdelix[$propName] + 2 : 1;
4843
+ $this->propdelix[$propName] = --$propix;
4844
+ }
4845
+ $return = FALSE;
4846
+ switch( $propName ) {
4847
+ case 'ACTION':
4848
+ if( !empty( $this->action )) {
4849
+ $this->action = '';
4850
+ $return = TRUE;
4851
+ }
4852
+ break;
4853
+ case 'ATTACH':
4854
+ return $this->deletePropertyM( $this->attach, $this->propdelix[$propName] );
4855
+ break;
4856
+ case 'ATTENDEE':
4857
+ return $this->deletePropertyM( $this->attendee, $this->propdelix[$propName] );
4858
+ break;
4859
+ case 'CATEGORIES':
4860
+ return $this->deletePropertyM( $this->categories, $this->propdelix[$propName] );
4861
+ break;
4862
+ case 'CLASS':
4863
+ if( !empty( $this->class )) {
4864
+ $this->class = '';
4865
+ $return = TRUE;
4866
+ }
4867
+ break;
4868
+ case 'COMMENT':
4869
+ return $this->deletePropertyM( $this->comment, $this->propdelix[$propName] );
4870
+ break;
4871
+ case 'COMPLETED':
4872
+ if( !empty( $this->completed )) {
4873
+ $this->completed = '';
4874
+ $return = TRUE;
4875
+ }
4876
+ break;
4877
+ case 'CONTACT':
4878
+ return $this->deletePropertyM( $this->contact, $this->propdelix[$propName] );
4879
+ break;
4880
+ case 'CREATED':
4881
+ if( !empty( $this->created )) {
4882
+ $this->created = '';
4883
+ $return = TRUE;
4884
+ }
4885
+ break;
4886
+ case 'DESCRIPTION':
4887
+ return $this->deletePropertyM( $this->description, $this->propdelix[$propName] );
4888
+ break;
4889
+ case 'DTEND':
4890
+ if( !empty( $this->dtend )) {
4891
+ $this->dtend = '';
4892
+ $return = TRUE;
4893
+ }
4894
+ break;
4895
+ case 'DTSTAMP':
4896
+ if( in_array( $this->objName, array( 'valarm', 'vtimezone', 'standard', 'daylight' )))
4897
+ return FALSE;
4898
+ if( !empty( $this->dtstamp )) {
4899
+ $this->dtstamp = '';
4900
+ $return = TRUE;
4901
+ }
4902
+ break;
4903
+ case 'DTSTART':
4904
+ if( !empty( $this->dtstart )) {
4905
+ $this->dtstart = '';
4906
+ $return = TRUE;
4907
+ }
4908
+ break;
4909
+ case 'DUE':
4910
+ if( !empty( $this->due )) {
4911
+ $this->due = '';
4912
+ $return = TRUE;
4913
+ }
4914
+ break;
4915
+ case 'DURATION':
4916
+ if( !empty( $this->duration )) {
4917
+ $this->duration = '';
4918
+ $return = TRUE;
4919
+ }
4920
+ break;
4921
+ case 'EXDATE':
4922
+ return $this->deletePropertyM( $this->exdate, $this->propdelix[$propName] );
4923
+ break;
4924
+ case 'EXRULE':
4925
+ return $this->deletePropertyM( $this->exrule, $this->propdelix[$propName] );
4926
+ break;
4927
+ case 'FREEBUSY':
4928
+ return $this->deletePropertyM( $this->freebusy, $this->propdelix[$propName] );
4929
+ break;
4930
+ case 'GEO':
4931
+ if( !empty( $this->geo )) {
4932
+ $this->geo = '';
4933
+ $return = TRUE;
4934
+ }
4935
+ break;
4936
+ case 'LAST-MODIFIED':
4937
+ if( !empty( $this->lastmodified )) {
4938
+ $this->lastmodified = '';
4939
+ $return = TRUE;
4940
+ }
4941
+ break;
4942
+ case 'LOCATION':
4943
+ if( !empty( $this->location )) {
4944
+ $this->location = '';
4945
+ $return = TRUE;
4946
+ }
4947
+ break;
4948
+ case 'ORGANIZER':
4949
+ if( !empty( $this->organizer )) {
4950
+ $this->organizer = '';
4951
+ $return = TRUE;
4952
+ }
4953
+ break;
4954
+ case 'PERCENT-COMPLETE':
4955
+ if( !empty( $this->percentcomplete )) {
4956
+ $this->percentcomplete = '';
4957
+ $return = TRUE;
4958
+ }
4959
+ break;
4960
+ case 'PRIORITY':
4961
+ if( !empty( $this->priority )) {
4962
+ $this->priority = '';
4963
+ $return = TRUE;
4964
+ }
4965
+ break;
4966
+ case 'RDATE':
4967
+ return $this->deletePropertyM( $this->rdate, $this->propdelix[$propName] );
4968
+ break;
4969
+ case 'RECURRENCE-ID':
4970
+ if( !empty( $this->recurrenceid )) {
4971
+ $this->recurrenceid = '';
4972
+ $return = TRUE;
4973
+ }
4974
+ break;
4975
+ case 'RELATED-TO':
4976
+ return $this->deletePropertyM( $this->relatedto, $this->propdelix[$propName] );
4977
+ break;
4978
+ case 'REPEAT':
4979
+ if( !empty( $this->repeat )) {
4980
+ $this->repeat = '';
4981
+ $return = TRUE;
4982
+ }
4983
+ break;
4984
+ case 'REQUEST-STATUS':
4985
+ return $this->deletePropertyM( $this->requeststatus, $this->propdelix[$propName] );
4986
+ break;
4987
+ case 'RESOURCES':
4988
+ return $this->deletePropertyM( $this->resources, $this->propdelix[$propName] );
4989
+ break;
4990
+ case 'RRULE':
4991
+ return $this->deletePropertyM( $this->rrule, $this->propdelix[$propName] );
4992
+ break;
4993
+ case 'SEQUENCE':
4994
+ if( !empty( $this->sequence )) {
4995
+ $this->sequence = '';
4996
+ $return = TRUE;
4997
+ }
4998
+ break;
4999
+ case 'STATUS':
5000
+ if( !empty( $this->status )) {
5001
+ $this->status = '';
5002
+ $return = TRUE;
5003
+ }
5004
+ break;
5005
+ case 'SUMMARY':
5006
+ if( !empty( $this->summary )) {
5007
+ $this->summary = '';
5008
+ $return = TRUE;
5009
+ }
5010
+ break;
5011
+ case 'TRANSP':
5012
+ if( !empty( $this->transp )) {
5013
+ $this->transp = '';
5014
+ $return = TRUE;
5015
+ }
5016
+ break;
5017
+ case 'TRIGGER':
5018
+ if( !empty( $this->trigger )) {
5019
+ $this->trigger = '';
5020
+ $return = TRUE;
5021
+ }
5022
+ break;
5023
+ case 'TZID':
5024
+ if( !empty( $this->tzid )) {
5025
+ $this->tzid = '';
5026
+ $return = TRUE;
5027
+ }
5028
+ break;
5029
+ case 'TZNAME':
5030
+ return $this->deletePropertyM( $this->tzname, $this->propdelix[$propName] );
5031
+ break;
5032
+ case 'TZOFFSETFROM':
5033
+ if( !empty( $this->tzoffsetfrom )) {
5034
+ $this->tzoffsetfrom = '';
5035
+ $return = TRUE;
5036
+ }
5037
+ break;
5038
+ case 'TZOFFSETTO':
5039
+ if( !empty( $this->tzoffsetto )) {
5040
+ $this->tzoffsetto = '';
5041
+ $return = TRUE;
5042
+ }
5043
+ break;
5044
+ case 'TZURL':
5045
+ if( !empty( $this->tzurl )) {
5046
+ $this->tzurl = '';
5047
+ $return = TRUE;
5048
+ }
5049
+ break;
5050
+ case 'UID':
5051
+ if( in_array( $this->objName, array( 'valarm', 'vtimezone', 'standard', 'daylight' )))
5052
+ return FALSE;
5053
+ if( !empty( $this->uid )) {
5054
+ $this->uid = '';
5055
+ $return = TRUE;
5056
+ }
5057
+ break;
5058
+ case 'URL':
5059
+ if( !empty( $this->url )) {
5060
+ $this->url = '';
5061
+ $return = TRUE;
5062
+ }
5063
+ break;
5064
+ default:
5065
+ $reduced = '';
5066
+ if( $propName != 'X-PROP' ) {
5067
+ if( !isset( $this->xprop[$propName] )) return FALSE;
5068
+ foreach( $this->xprop as $k => $a ) {
5069
+ if(( $k != $propName ) && !empty( $a ))
5070
+ $reduced[$k] = $a;
5071
+ }
5072
+ }
5073
+ else {
5074
+ if( count( $this->xprop ) <= $propix ) { unset( $this->propdelix[$propName] ); return FALSE; }
5075
+ $xpropno = 0;
5076
+ foreach( $this->xprop as $xpropkey => $xpropvalue ) {
5077
+ if( $propix != $xpropno )
5078
+ $reduced[$xpropkey] = $xpropvalue;
5079
+ $xpropno++;
5080
+ }
5081
+ }
5082
+ $this->xprop = $reduced;
5083
+ if( empty( $this->xprop )) {
5084
+ unset( $this->propdelix[$propName] );
5085
+ return FALSE;
5086
+ }
5087
+ return TRUE;
5088
+ }
5089
+ return $return;
5090
+ }
5091
+ /*********************************************************************************/
5092
+ /**
5093
+ * delete component property value, fixing components with multiple occurencies
5094
+ *
5095
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
5096
+ * @since 2.8.8 - 2011-03-15
5097
+ * @param array $multiprop, reference to a component property
5098
+ * @param int $propix, reference to removal counter
5099
+ * @return bool TRUE
5100
+ */
5101
+ function deletePropertyM( & $multiprop, & $propix ) {
5102
+ if( isset( $multiprop[$propix] ))
5103
+ unset( $multiprop[$propix] );
5104
+ if( empty( $multiprop )) {
5105
+ $multiprop = '';
5106
+ unset( $propix );
5107
+ return FALSE;
5108
+ }
5109
+ else
5110
+ return TRUE;
5111
+ }
5112
+ /**
5113
+ * get component property value/params
5114
+ *
5115
+ * if property has multiply values, consequtive function calls are needed
5116
+ *
5117
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
5118
+ * @since 2.9.3 - 2011-05-18
5119
+ * @param string $propName, optional
5120
+ * @param int @propix, optional, if specific property is wanted in case of multiply occurences
5121
+ * @param bool $inclParam=FALSE
5122
+ * @param bool $specform=FALSE
5123
+ * @return mixed
5124
+ */
5125
+ function getProperty( $propName=FALSE, $propix=FALSE, $inclParam=FALSE, $specform=FALSE ) {
5126
+ if( $this->_notExistProp( $propName )) return FALSE;
5127
+ $propName = ( $propName ) ? strtoupper( $propName ) : 'X-PROP';
5128
+ if( in_array( $propName, array( 'ATTACH', 'ATTENDEE', 'CATEGORIES', 'COMMENT', 'CONTACT', 'DESCRIPTION', 'EXDATE', 'EXRULE',
5129
+ 'FREEBUSY', 'RDATE', 'RELATED-TO', 'RESOURCES', 'RRULE', 'REQUEST-STATUS', 'TZNAME', 'X-PROP' ))) {
5130
+ if( !$propix )
5131
+ $propix = ( isset( $this->propix[$propName] )) ? $this->propix[$propName] + 2 : 1;
5132
+ $this->propix[$propName] = --$propix;
5133
+ }
5134
+ switch( $propName ) {
5135
+ case 'ACTION':
5136
+ if( !empty( $this->action['value'] )) return ( $inclParam ) ? $this->action : $this->action['value'];
5137
+ break;
5138
+ case 'ATTACH':
5139
+ while( is_array( $this->attach ) && !isset( $this->attach[$propix] ) && ( 0 < count( $this->attach )) && ( $propix < end( array_keys( $this->attach ))))
5140
+ $propix++;
5141
+ if( !isset( $this->attach[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
5142
+ return ( $inclParam ) ? $this->attach[$propix] : $this->attach[$propix]['value'];
5143
+ break;
5144
+ case 'ATTENDEE':
5145
+ while( is_array( $this->attendee ) && !isset( $this->attendee[$propix] ) && ( 0 < count( $this->attendee )) && ( $propix < end( array_keys( $this->attendee ))))
5146
+ $propix++;
5147
+ if( !isset( $this->attendee[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
5148
+ return ( $inclParam ) ? $this->attendee[$propix] : $this->attendee[$propix]['value'];
5149
+ break;
5150
+ case 'CATEGORIES':
5151
+ while( is_array( $this->categories ) && !isset( $this->categories[$propix] ) && ( 0 < count( $this->categories )) && ( $propix < end( array_keys( $this->categories ))))
5152
+ $propix++;
5153
+ if( !isset( $this->categories[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
5154
+ return ( $inclParam ) ? $this->categories[$propix] : $this->categories[$propix]['value'];
5155
+ break;
5156
+ case 'CLASS':
5157
+ if( !empty( $this->class['value'] )) return ( $inclParam ) ? $this->class : $this->class['value'];
5158
+ break;
5159
+ case 'COMMENT':
5160
+ while( is_array( $this->comment ) && !isset( $this->comment[$propix] ) && ( 0 < count( $this->comment )) && ( $propix < end( array_keys( $this->comment ))))
5161
+ $propix++;
5162
+ if( !isset( $this->comment[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
5163
+ return ( $inclParam ) ? $this->comment[$propix] : $this->comment[$propix]['value'];
5164
+ break;
5165
+ case 'COMPLETED':
5166
+ if( !empty( $this->completed['value'] )) return ( $inclParam ) ? $this->completed : $this->completed['value'];
5167
+ break;
5168
+ case 'CONTACT':
5169
+ while( is_array( $this->contact ) && !isset( $this->contact[$propix] ) && ( 0 < count( $this->contact )) && ( $propix < end( array_keys( $this->contact ))))
5170
+ $propix++;
5171
+ if( !isset( $this->contact[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
5172
+ return ( $inclParam ) ? $this->contact[$propix] : $this->contact[$propix]['value'];
5173
+ break;
5174
+ case 'CREATED':
5175
+ if( !empty( $this->created['value'] )) return ( $inclParam ) ? $this->created : $this->created['value'];
5176
+ break;
5177
+ case 'DESCRIPTION':
5178
+ while( is_array( $this->description ) && !isset( $this->description[$propix] ) && ( 0 < count( $this->description )) && ( $propix < end( array_keys( $this->description ))))
5179
+ $propix++;
5180
+ if( !isset( $this->description[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
5181
+ return ( $inclParam ) ? $this->description[$propix] : $this->description[$propix]['value'];
5182
+ break;
5183
+ case 'DTEND':
5184
+ if( !empty( $this->dtend['value'] )) return ( $inclParam ) ? $this->dtend : $this->dtend['value'];
5185
+ break;
5186
+ case 'DTSTAMP':
5187
+ if( in_array( $this->objName, array( 'valarm', 'vtimezone', 'standard', 'daylight' )))
5188
+ return;
5189
+ if( !isset( $this->dtstamp['value'] ))
5190
+ $this->_makeDtstamp();
5191
+ return ( $inclParam ) ? $this->dtstamp : $this->dtstamp['value'];
5192
+ break;
5193
+ case 'DTSTART':
5194
+ if( !empty( $this->dtstart['value'] )) return ( $inclParam ) ? $this->dtstart : $this->dtstart['value'];
5195
+ break;
5196
+ case 'DUE':
5197
+ if( !empty( $this->due['value'] )) return ( $inclParam ) ? $this->due : $this->due['value'];
5198
+ break;
5199
+ case 'DURATION':
5200
+ if( !isset( $this->duration['value'] )) return FALSE;
5201
+ $value = ( $specform && isset( $this->dtstart['value'] ) && isset( $this->duration['value'] )) ? iCalUtilityFunctions::_duration2date( $this->dtstart['value'], $this->duration['value'] ) : $this->duration['value'];
5202
+ return ( $inclParam ) ? array( 'value' => $value, 'params' => $this->duration['params'] ) : $value;
5203
+ break;
5204
+ case 'EXDATE':
5205
+ while( is_array( $this->exdate ) && !isset( $this->exdate[$propix] ) && ( 0 < count( $this->exdate )) && ( $propix < end( array_keys( $this->exdate ))))
5206
+ $propix++;
5207
+ if( !isset( $this->exdate[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
5208
+ return ( $inclParam ) ? $this->exdate[$propix] : $this->exdate[$propix]['value'];
5209
+ break;
5210
+ case 'EXRULE':
5211
+ while( is_array( $this->exrule ) && !isset( $this->exrule[$propix] ) && ( 0 < count( $this->exrule )) && ( $propix < end( array_keys( $this->exrule ))))
5212
+ $propix++;
5213
+ if( !isset( $this->exrule[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
5214
+ return ( $inclParam ) ? $this->exrule[$propix] : $this->exrule[$propix]['value'];
5215
+ break;
5216
+ case 'FREEBUSY':
5217
+ while( is_array( $this->freebusy ) && !isset( $this->freebusy[$propix] ) && ( 0 < count( $this->freebusy )) && ( $propix < end( array_keys( $this->freebusy ))))
5218
+ $propix++;
5219
+ if( !isset( $this->freebusy[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
5220
+ return ( $inclParam ) ? $this->freebusy[$propix] : $this->freebusy[$propix]['value'];
5221
+ break;
5222
+ case 'GEO':
5223
+ if( !empty( $this->geo['value'] )) return ( $inclParam ) ? $this->geo : $this->geo['value'];
5224
+ break;
5225
+ case 'LAST-MODIFIED':
5226
+ if( !empty( $this->lastmodified['value'] )) return ( $inclParam ) ? $this->lastmodified : $this->lastmodified['value'];
5227
+ break;
5228
+ case 'LOCATION':
5229
+ if( !empty( $this->location['value'] )) return ( $inclParam ) ? $this->location : $this->location['value'];
5230
+ break;
5231
+ case 'ORGANIZER':
5232
+ if( !empty( $this->organizer['value'] )) return ( $inclParam ) ? $this->organizer : $this->organizer['value'];
5233
+ break;
5234
+ case 'PERCENT-COMPLETE':
5235
+ if( !empty( $this->percentcomplete['value'] ) || ( isset( $this->percentcomplete['value'] ) && ( '0' == $this->percentcomplete['value'] ))) return ( $inclParam ) ? $this->percentcomplete : $this->percentcomplete['value'];
5236
+ break;
5237
+ case 'PRIORITY':
5238
+ if( !empty( $this->priority['value'] ) || ( isset( $this->priority['value'] ) && ('0' == $this->priority['value'] ))) return ( $inclParam ) ? $this->priority : $this->priority['value'];
5239
+ break;
5240
+ case 'RDATE':
5241
+ while( is_array( $this->rdate ) && !isset( $this->rdate[$propix] ) && ( 0 < count( $this->rdate )) && ( $propix < end( array_keys( $this->rdate ))))
5242
+ $propix++;
5243
+ if( !isset( $this->rdate[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
5244
+ return ( $inclParam ) ? $this->rdate[$propix] : $this->rdate[$propix]['value'];
5245
+ break;
5246
+ case 'RECURRENCE-ID':
5247
+ if( !empty( $this->recurrenceid['value'] )) return ( $inclParam ) ? $this->recurrenceid : $this->recurrenceid['value'];
5248
+ break;
5249
+ case 'RELATED-TO':
5250
+ while( is_array( $this->relatedto ) && !isset( $this->relatedto[$propix] ) && ( 0 < count( $this->relatedto )) && ( $propix < end( array_keys( $this->relatedto ))))
5251
+ $propix++;
5252
+ if( !isset( $this->relatedto[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
5253
+ return ( $inclParam ) ? $this->relatedto[$propix] : $this->relatedto[$propix]['value'];
5254
+ break;
5255
+ case 'REPEAT':
5256
+ if( !empty( $this->repeat['value'] ) || ( isset( $this->repeat['value'] ) && ( '0' == $this->repeat['value'] ))) return ( $inclParam ) ? $this->repeat : $this->repeat['value'];
5257
+ break;
5258
+ case 'REQUEST-STATUS':
5259
+ while( is_array( $this->requeststatus ) && !isset( $this->requeststatus[$propix] ) && ( 0 < count( $this->requeststatus )) && ( $propix < end( array_keys( $this->requeststatus ))))
5260
+ $propix++;
5261
+ if( !isset( $this->requeststatus[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
5262
+ return ( $inclParam ) ? $this->requeststatus[$propix] : $this->requeststatus[$propix]['value'];
5263
+ break;
5264
+ case 'RESOURCES':
5265
+ while( is_array( $this->resources ) && !isset( $this->resources[$propix] ) && ( 0 < count( $this->resources )) && ( $propix < end( array_keys( $this->resources ))))
5266
+ $propix++;
5267
+ if( !isset( $this->resources[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
5268
+ return ( $inclParam ) ? $this->resources[$propix] : $this->resources[$propix]['value'];
5269
+ break;
5270
+ case 'RRULE':
5271
+ while( is_array( $this->rrule ) && !isset( $this->rrule[$propix] ) && ( 0 < count( $this->rrule )) && ( $propix < end( array_keys( $this->rrule ))))
5272
+ $propix++;
5273
+ if( !isset( $this->rrule[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
5274
+ return ( $inclParam ) ? $this->rrule[$propix] : $this->rrule[$propix]['value'];
5275
+ break;
5276
+ case 'SEQUENCE':
5277
+ if( isset( $this->sequence['value'] ) && ( isset( $this->sequence['value'] ) && ( '0' <= $this->sequence['value'] ))) return ( $inclParam ) ? $this->sequence : $this->sequence['value'];
5278
+ break;
5279
+ case 'STATUS':
5280
+ if( !empty( $this->status['value'] )) return ( $inclParam ) ? $this->status : $this->status['value'];
5281
+ break;
5282
+ case 'SUMMARY':
5283
+ if( !empty( $this->summary['value'] )) return ( $inclParam ) ? $this->summary : $this->summary['value'];
5284
+ break;
5285
+ case 'TRANSP':
5286
+ if( !empty( $this->transp['value'] )) return ( $inclParam ) ? $this->transp : $this->transp['value'];
5287
+ break;
5288
+ case 'TRIGGER':
5289
+ if( !empty( $this->trigger['value'] )) return ( $inclParam ) ? $this->trigger : $this->trigger['value'];
5290
+ break;
5291
+ case 'TZID':
5292
+ if( !empty( $this->tzid['value'] )) return ( $inclParam ) ? $this->tzid : $this->tzid['value'];
5293
+ break;
5294
+ case 'TZNAME':
5295
+ while( is_array( $this->tzname ) && !isset( $this->tzname[$propix] ) && ( 0 < count( $this->tzname )) && ( $propix < end( array_keys( $this->tzname ))))
5296
+ $propix++;
5297
+ if( !isset( $this->tzname[$propix] )) { unset( $this->propix[$propName] ); return FALSE; }
5298
+ return ( $inclParam ) ? $this->tzname[$propix] : $this->tzname[$propix]['value'];
5299
+ break;
5300
+ case 'TZOFFSETFROM':
5301
+ if( !empty( $this->tzoffsetfrom['value'] )) return ( $inclParam ) ? $this->tzoffsetfrom : $this->tzoffsetfrom['value'];
5302
+ break;
5303
+ case 'TZOFFSETTO':
5304
+ if( !empty( $this->tzoffsetto['value'] )) return ( $inclParam ) ? $this->tzoffsetto : $this->tzoffsetto['value'];
5305
+ break;
5306
+ case 'TZURL':
5307
+ if( !empty( $this->tzurl['value'] )) return ( $inclParam ) ? $this->tzurl : $this->tzurl['value'];
5308
+ break;
5309
+ case 'UID':
5310
+ if( in_array( $this->objName, array( 'valarm', 'vtimezone', 'standard', 'daylight' )))
5311
+ return FALSE;
5312
+ if( empty( $this->uid['value'] ))
5313
+ $this->_makeuid();
5314
+ return ( $inclParam ) ? $this->uid : $this->uid['value'];
5315
+ break;
5316
+ case 'URL':
5317
+ if( !empty( $this->url['value'] )) return ( $inclParam ) ? $this->url : $this->url['value'];
5318
+ break;
5319
+ default:
5320
+ if( $propName != 'X-PROP' ) {
5321
+ if( !isset( $this->xprop[$propName] )) return FALSE;
5322
+ return ( $inclParam ) ? array( $propName, $this->xprop[$propName] )
5323
+ : array( $propName, $this->xprop[$propName]['value'] );
5324
+ }
5325
+ else {
5326
+ if( empty( $this->xprop )) return FALSE;
5327
+ $xpropno = 0;
5328
+ foreach( $this->xprop as $xpropkey => $xpropvalue ) {
5329
+ if( $propix == $xpropno )
5330
+ return ( $inclParam ) ? array( $xpropkey, $this->xprop[$xpropkey] )
5331
+ : array( $xpropkey, $this->xprop[$xpropkey]['value'] );
5332
+ else
5333
+ $xpropno++;
5334
+ }
5335
+ return FALSE; // not found ??
5336
+ }
5337
+ }
5338
+ return FALSE;
5339
+ }
5340
+ /**
5341
+ * returns calendar property unique values for 'CATEGORIES', 'RESOURCES' or 'ATTENDEE' and each number of ocurrence
5342
+ *
5343
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
5344
+ * @since 2.8.8 - 2011-04-13
5345
+ * @param string $propName
5346
+ * @param array $output, incremented result array
5347
+ */
5348
+ function _getProperties( $propName, & $output ) {
5349
+ if( !in_array( strtoupper( $propName ), array( 'ATTENDEE', 'CATEGORIES', 'RESOURCES' )))
5350
+ return output;
5351
+ while( FALSE !== ( $content = $this->getProperty( $propName ))) {
5352
+ if( is_array( $content )) {
5353
+ foreach( $content as $part ) {
5354
+ if( FALSE !== strpos( $part, ',' )) {
5355
+ $part = explode( ',', $part );
5356
+ foreach( $part as $thePart ) {
5357
+ $thePart = trim( $thePart );
5358
+ if( !empty( $thePart )) {
5359
+ if( !isset( $output[$thePart] ))
5360
+ $output[$thePart] = 1;
5361
+ else
5362
+ $output[$thePart] += 1;
5363
+ }
5364
+ }
5365
+ }
5366
+ else {
5367
+ $part = trim( $part );
5368
+ if( !isset( $output[$part] ))
5369
+ $output[$part] = 1;
5370
+ else
5371
+ $output[$part] += 1;
5372
+ }
5373
+ }
5374
+ }
5375
+ elseif( FALSE !== strpos( $content, ',' )) {
5376
+ $content = explode( ',', $content );
5377
+ foreach( $content as $thePart ) {
5378
+ $thePart = trim( $thePart );
5379
+ if( !empty( $thePart )) {
5380
+ if( !isset( $output[$thePart] ))
5381
+ $output[$thePart] = 1;
5382
+ else
5383
+ $output[$thePart] += 1;
5384
+ }
5385
+ }
5386
+ }
5387
+ else {
5388
+ $content = trim( $content );
5389
+ if( !empty( $content )) {
5390
+ if( !isset( $output[$content] ))
5391
+ $output[$content] = 1;
5392
+ else
5393
+ $output[$content] += 1;
5394
+ }
5395
+ }
5396
+ }
5397
+ ksort( $output );
5398
+ return $output;
5399
+ }
5400
+ /**
5401
+ * general component property setting
5402
+ *
5403
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
5404
+ * @since 2.5.1 - 2008-11-05
5405
+ * @param mixed $args variable number of function arguments,
5406
+ * first argument is ALWAYS component name,
5407
+ * second ALWAYS component value!
5408
+ * @return void
5409
+ */
5410
+ function setProperty() {
5411
+ $numargs = func_num_args();
5412
+ if( 1 > $numargs ) return FALSE;
5413
+ $arglist = func_get_args();
5414
+ if( $this->_notExistProp( $arglist[0] )) return FALSE;
5415
+ if( !$this->getConfig( 'allowEmpty' ) && ( !isset( $arglist[1] ) || empty( $arglist[1] )))
5416
+ return FALSE;
5417
+ $arglist[0] = strtoupper( $arglist[0] );
5418
+ for( $argix=$numargs; $argix < 12; $argix++ ) {
5419
+ if( !isset( $arglist[$argix] ))
5420
+ $arglist[$argix] = null;
5421
+ }
5422
+ switch( $arglist[0] ) {
5423
+ case 'ACTION':
5424
+ return $this->setAction( $arglist[1], $arglist[2] );
5425
+ case 'ATTACH':
5426
+ return $this->setAttach( $arglist[1], $arglist[2], $arglist[3] );
5427
+ case 'ATTENDEE':
5428
+ return $this->setAttendee( $arglist[1], $arglist[2], $arglist[3] );
5429
+ case 'CATEGORIES':
5430
+ return $this->setCategories( $arglist[1], $arglist[2], $arglist[3] );
5431
+ case 'CLASS':
5432
+ return $this->setClass( $arglist[1], $arglist[2] );
5433
+ case 'COMMENT':
5434
+ return $this->setComment( $arglist[1], $arglist[2], $arglist[3] );
5435
+ case 'COMPLETED':
5436
+ return $this->setCompleted( $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5], $arglist[6], $arglist[7] );
5437
+ case 'CONTACT':
5438
+ return $this->setContact( $arglist[1], $arglist[2], $arglist[3] );
5439
+ case 'CREATED':
5440
+ return $this->setCreated( $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5], $arglist[6], $arglist[7] );
5441
+ case 'DESCRIPTION':
5442
+ return $this->setDescription( $arglist[1], $arglist[2], $arglist[3] );
5443
+ case 'DTEND':
5444
+ return $this->setDtend( $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5], $arglist[6], $arglist[7], $arglist[8] );
5445
+ case 'DTSTAMP':
5446
+ return $this->setDtstamp( $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5], $arglist[6], $arglist[7] );
5447
+ case 'DTSTART':
5448
+ return $this->setDtstart( $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5], $arglist[6], $arglist[7], $arglist[8] );
5449
+ case 'DUE':
5450
+ return $this->setDue( $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5], $arglist[6], $arglist[7], $arglist[8] );
5451
+ case 'DURATION':
5452
+ return $this->setDuration( $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5], $arglist[6] );
5453
+ case 'EXDATE':
5454
+ return $this->setExdate( $arglist[1], $arglist[2], $arglist[3] );
5455
+ case 'EXRULE':
5456
+ return $this->setExrule( $arglist[1], $arglist[2], $arglist[3] );
5457
+ case 'FREEBUSY':
5458
+ return $this->setFreebusy( $arglist[1], $arglist[2], $arglist[3], $arglist[4] );
5459
+ case 'GEO':
5460
+ return $this->setGeo( $arglist[1], $arglist[2], $arglist[3] );
5461
+ case 'LAST-MODIFIED':
5462
+ return $this->setLastModified( $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5], $arglist[6], $arglist[7] );
5463
+ case 'LOCATION':
5464
+ return $this->setLocation( $arglist[1], $arglist[2] );
5465
+ case 'ORGANIZER':
5466
+ return $this->setOrganizer( $arglist[1], $arglist[2] );
5467
+ case 'PERCENT-COMPLETE':
5468
+ return $this->setPercentComplete( $arglist[1], $arglist[2] );
5469
+ case 'PRIORITY':
5470
+ return $this->setPriority( $arglist[1], $arglist[2] );
5471
+ case 'RDATE':
5472
+ return $this->setRdate( $arglist[1], $arglist[2], $arglist[3] );
5473
+ case 'RECURRENCE-ID':
5474
+ return $this->setRecurrenceid( $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5], $arglist[6], $arglist[7], $arglist[8] );
5475
+ case 'RELATED-TO':
5476
+ return $this->setRelatedTo( $arglist[1], $arglist[2], $arglist[3] );
5477
+ case 'REPEAT':
5478
+ return $this->setRepeat( $arglist[1], $arglist[2] );
5479
+ case 'REQUEST-STATUS':
5480
+ return $this->setRequestStatus( $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5] );
5481
+ case 'RESOURCES':
5482
+ return $this->setResources( $arglist[1], $arglist[2], $arglist[3] );
5483
+ case 'RRULE':
5484
+ return $this->setRrule( $arglist[1], $arglist[2], $arglist[3] );
5485
+ case 'SEQUENCE':
5486
+ return $this->setSequence( $arglist[1], $arglist[2] );
5487
+ case 'STATUS':
5488
+ return $this->setStatus( $arglist[1], $arglist[2] );
5489
+ case 'SUMMARY':
5490
+ return $this->setSummary( $arglist[1], $arglist[2] );
5491
+ case 'TRANSP':
5492
+ return $this->setTransp( $arglist[1], $arglist[2] );
5493
+ case 'TRIGGER':
5494
+ return $this->setTrigger( $arglist[1], $arglist[2], $arglist[3], $arglist[4], $arglist[5], $arglist[6], $arglist[7], $arglist[8], $arglist[9], $arglist[10], $arglist[11] );
5495
+ case 'TZID':
5496
+ return $this->setTzid( $arglist[1], $arglist[2] );
5497
+ case 'TZNAME':
5498
+ return $this->setTzname( $arglist[1], $arglist[2], $arglist[3] );
5499
+ case 'TZOFFSETFROM':
5500
+ return $this->setTzoffsetfrom( $arglist[1], $arglist[2] );
5501
+ case 'TZOFFSETTO':
5502
+ return $this->setTzoffsetto( $arglist[1], $arglist[2] );
5503
+ case 'TZURL':
5504
+ return $this->setTzurl( $arglist[1], $arglist[2] );
5505
+ case 'UID':
5506
+ return $this->setUid( $arglist[1], $arglist[2] );
5507
+ case 'URL':
5508
+ return $this->setUrl( $arglist[1], $arglist[2] );
5509
+ default:
5510
+ return $this->setXprop( $arglist[0], $arglist[1], $arglist[2] );
5511
+ }
5512
+ return FALSE;
5513
+ }
5514
+ /*********************************************************************************/
5515
+ /**
5516
+ * parse component unparsed data into properties
5517
+ *
5518
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
5519
+ * @since 2.8.2 - 2011-05-21
5520
+ * @param mixed $unparsedtext, optional, strict rfc2445 formatted, single property string or array of strings
5521
+ * @return bool FALSE if error occurs during parsing
5522
+ *
5523
+ */
5524
+ function parse( $unparsedtext=null ) {
5525
+ if( !empty( $unparsedtext )) {
5526
+ $nl = $this->getConfig( 'nl' );
5527
+ if( is_array( $unparsedtext ))
5528
+ $unparsedtext = implode( '\n'.$nl, $unparsedtext );
5529
+ /* fix line folding */
5530
+ $eolchars = array( "\r\n", "\n\r", "\n", "\r" ); // check all line endings
5531
+ $EOLmark = FALSE;
5532
+ foreach( $eolchars as $eolchar ) {
5533
+ if( !$EOLmark && ( FALSE !== strpos( $unparsedtext, $eolchar ))) {
5534
+ $unparsedtext = str_replace( $eolchar." ", '', $unparsedtext );
5535
+ $unparsedtext = str_replace( $eolchar."\t", '', $unparsedtext );
5536
+ if( $eolchar != $nl )
5537
+ $unparsedtext = str_replace( $eolchar, $nl, $unparsedtext );
5538
+ $EOLmark = TRUE;
5539
+ }
5540
+ }
5541
+ $tmp = explode( $nl, $unparsedtext );
5542
+ $unparsedtext = array();
5543
+ foreach( $tmp as $tmpr )
5544
+ if( !empty( $tmpr ))
5545
+ $unparsedtext[] = $tmpr;
5546
+ }
5547
+ elseif( !isset( $this->unparsed ))
5548
+ $unparsedtext = array();
5549
+ else
5550
+ $unparsedtext = $this->unparsed;
5551
+ $this->unparsed = array();
5552
+ $comp = & $this;
5553
+ $config = $this->getConfig();
5554
+ foreach ( $unparsedtext as $line ) {
5555
+ // echo $comp->objName.": $line<br />"; // test ###
5556
+ if( in_array( strtoupper( substr( $line, 0, 6 )), array( 'END:VA', 'END:ST', 'END:DA' )))
5557
+ $this->components[] = $comp->copy();
5558
+ elseif( 'END:' == strtoupper( substr( $line, 0, 4 )))
5559
+ break;
5560
+ elseif( 'BEGIN:VALARM' == strtoupper( substr( $line, 0, 12 )))
5561
+ $comp = new valarm( $config);
5562
+ elseif( 'BEGIN:STANDARD' == strtoupper( substr( $line, 0, 14 )))
5563
+ $comp = new vtimezone( 'standard', $config );
5564
+ elseif( 'BEGIN:DAYLIGHT' == strtoupper( substr( $line, 0, 14 )))
5565
+ $comp = new vtimezone( 'daylight', $config );
5566
+ elseif( 'BEGIN:' == strtoupper( substr( $line, 0, 6 )))
5567
+ continue;
5568
+ else {
5569
+ $comp->unparsed[] = $line;
5570
+ // echo $comp->objName.": $line<br />\n"; // test ###
5571
+ }
5572
+ }
5573
+ unset( $config );
5574
+ // echo $this->objName.'<br />'.var_export( $this->unparsed, TRUE )."<br />\n"; // test ###
5575
+ /* concatenate property values spread over several lines */
5576
+ $lastix = -1;
5577
+ $propnames = array( 'action', 'attach', 'attendee', 'categories', 'comment', 'completed'
5578
+ , 'contact', 'class', 'created', 'description', 'dtend', 'dtstart'
5579
+ , 'dtstamp', 'due', 'duration', 'exdate', 'exrule', 'freebusy', 'geo'
5580
+ , 'last-modified', 'location', 'organizer', 'percent-complete'
5581
+ , 'priority', 'rdate', 'recurrence-id', 'related-to', 'repeat'
5582
+ , 'request-status', 'resources', 'rrule', 'sequence', 'status'
5583
+ , 'summary', 'transp', 'trigger', 'tzid', 'tzname', 'tzoffsetfrom'
5584
+ , 'tzoffsetto', 'tzurl', 'uid', 'url', 'x-' );
5585
+ $proprows = array();
5586
+ foreach( $this->unparsed as $line ) {
5587
+ $newProp = FALSE;
5588
+ foreach ( $propnames as $propname ) {
5589
+ if( $propname == strtolower( substr( $line, 0, strlen( $propname )))) {
5590
+ $newProp = TRUE;
5591
+ break;
5592
+ }
5593
+ }
5594
+ if( $newProp ) {
5595
+ if( -1 < $lastix )
5596
+ $proprows[$lastix] = $proprows[$lastix];
5597
+ $newProp = FALSE;
5598
+ $lastix++;
5599
+ $proprows[$lastix] = $line;
5600
+ }
5601
+ else
5602
+ $proprows[$lastix] .= '!"#¤%&/()=?'.$line;
5603
+ }
5604
+ /* parse each property 'line' */
5605
+ foreach( $proprows as $line ) {
5606
+ $line = str_replace( '!"#¤%&/()=? ', '', $line );
5607
+ $line = str_replace( '!"#¤%&/()=?', '', $line );
5608
+ if( '\n' == substr( $line, -2 ))
5609
+ $line = substr( $line, 0, strlen( $line ) - 2 );
5610
+ /* get propname, (problem with x-properties, otherwise in previous loop) */
5611
+ $cix = $propname = null;
5612
+ for( $cix=0, $clen = strlen( $line ); $cix < $clen; $cix++ ) {
5613
+ if( in_array( $line[$cix], array( ':', ';' )))
5614
+ break;
5615
+ else {
5616
+ $propname .= $line[$cix];
5617
+ }
5618
+ }
5619
+ if(( 'x-' == substr( $propname, 0, 2 )) || ( 'X-' == substr( $propname, 0, 2 ))) {
5620
+ $propname2 = $propname;
5621
+ $propname = 'X-';
5622
+ }
5623
+ /* rest of the line is opt.params and value */
5624
+ $line = substr( $line, $cix );
5625
+ /* separate attributes from value */
5626
+ $attr = array();
5627
+ $attrix = -1;
5628
+ $clen = strlen( $line );
5629
+ for( $cix=0; $cix < $clen; $cix++ ) {
5630
+ if(( ':' == $line[$cix] ) &&
5631
+ ( '://' != substr( $line, $cix, 3 )) &&
5632
+ ( !in_array( strtolower( substr( $line, $cix - 3, 4 )), array( 'fax:', 'cid:', 'sms:', 'tel:', 'urn:' ))) &&
5633
+ ( !in_array( strtolower( substr( $line, $cix - 4, 5 )), array( 'crid:', 'news:', 'pres:' ))) &&
5634
+ ( 'mailto:' != strtolower( substr( $line, $cix - 6, 7 )))) {
5635
+ $attrEnd = TRUE;
5636
+ if(( $cix < ( $clen - 4 )) &&
5637
+ ctype_digit( substr( $line, $cix+1, 4 ))) { // an URI with a (4pos) portnr??
5638
+ for( $c2ix = $cix; 3 < $c2ix; $c2ix-- ) {
5639
+ if( '://' == substr( $line, $c2ix - 2, 3 )) {
5640
+ $attrEnd = FALSE;
5641
+ break; // an URI with a portnr!!
5642
+ }
5643
+ }
5644
+ }
5645
+ if( $attrEnd) {
5646
+ $line = substr( $line, $cix + 1 );
5647
+ break;
5648
+ }
5649
+ }
5650
+ if( ';' == $line[$cix] )
5651
+ $attr[++$attrix] = null;
5652
+ else
5653
+ $attr[$attrix] .= $line[$cix];
5654
+ }
5655
+ /* make attributes in array format */
5656
+ $propattr = array();
5657
+ foreach( $attr as $attribute ) {
5658
+ $attrsplit = explode( '=', $attribute, 2 );
5659
+ if( 1 < count( $attrsplit ))
5660
+ $propattr[$attrsplit[0]] = $attrsplit[1];
5661
+ else
5662
+ $propattr[] = $attribute;
5663
+ }
5664
+ /* call setProperty( $propname.. . */
5665
+ switch( strtoupper( $propname )) {
5666
+ case 'ATTENDEE':
5667
+ foreach( $propattr as $pix => $attr ) {
5668
+ $attr2 = explode( ',', $attr );
5669
+ if( 1 < count( $attr2 ))
5670
+ $propattr[$pix] = $attr2;
5671
+ }
5672
+ $this->setProperty( $propname, $line, $propattr );
5673
+ break;
5674
+ case 'CATEGORIES':
5675
+ case 'RESOURCES':
5676
+ if( FALSE !== strpos( $line, ',' )) {
5677
+ $content = explode( ',', $line );
5678
+ $clen = count( $content );
5679
+ for( $cix = 0; $cix < $clen; $cix++ ) {
5680
+ if( "\\" == substr($content[$cix], -1)) {
5681
+ $content[$cix] .= ','.$content[$cix + 1];
5682
+ unset($content[$cix + 1]);
5683
+ $cix++;
5684
+ }
5685
+ }
5686
+ if( 1 < count( $content )) {
5687
+ $content = array_values( $content );
5688
+ foreach( $content as $cix => $contentPart )
5689
+ $content[$cix] = calendarComponent::_strunrep( $contentPart );
5690
+ $this->setProperty( $propname, $content, $propattr );
5691
+ break;
5692
+ }
5693
+ else
5694
+ $line = reset( $content );
5695
+ }
5696
+ case 'X-':
5697
+ $propname = ( isset( $propname2 )) ? $propname2 : $propname;
5698
+ case 'COMMENT':
5699
+ case 'CONTACT':
5700
+ case 'DESCRIPTION':
5701
+ case 'LOCATION':
5702
+ case 'SUMMARY':
5703
+ if( empty( $line ))
5704
+ $propattr = null;
5705
+ $this->setProperty( $propname, calendarComponent::_strunrep( $line ), $propattr );
5706
+ unset( $propname2 );
5707
+ break;
5708
+ case 'REQUEST-STATUS':
5709
+ $values = explode( ';', $line, 3 );
5710
+ $values[1] = ( !isset( $values[1] )) ? null : calendarComponent::_strunrep( $values[1] );
5711
+ $values[2] = ( !isset( $values[2] )) ? null : calendarComponent::_strunrep( $values[2] );
5712
+ $this->setProperty( $propname
5713
+ , $values[0] // statcode
5714
+ , $values[1] // statdesc
5715
+ , $values[2] // extdata
5716
+ , $propattr );
5717
+ break;
5718
+ case 'FREEBUSY':
5719
+ $fbtype = ( isset( $propattr['FBTYPE'] )) ? $propattr['FBTYPE'] : ''; // force setting default, if missing
5720
+ unset( $propattr['FBTYPE'] );
5721
+ $values = explode( ',', $line );
5722
+ foreach( $values as $vix => $value ) {
5723
+ $value2 = explode( '/', $value );
5724
+ if( 1 < count( $value2 ))
5725
+ $values[$vix] = $value2;
5726
+ }
5727
+ $this->setProperty( $propname, $fbtype, $values, $propattr );
5728
+ break;
5729
+ case 'GEO':
5730
+ $value = explode( ';', $line, 2 );
5731
+ if( 2 > count( $value ))
5732
+ $value[1] = null;
5733
+ $this->setProperty( $propname, $value[0], $value[1], $propattr );
5734
+ break;
5735
+ case 'EXDATE':
5736
+ $values = ( !empty( $line )) ? explode( ',', $line ) : null;
5737
+ $this->setProperty( $propname, $values, $propattr );
5738
+ break;
5739
+ case 'RDATE':
5740
+ if( empty( $line )) {
5741
+ $this->setProperty( $propname, $line, $propattr );
5742
+ break;
5743
+ }
5744
+ $values = explode( ',', $line );
5745
+ foreach( $values as $vix => $value ) {
5746
+ $value2 = explode( '/', $value );
5747
+ if( 1 < count( $value2 ))
5748
+ $values[$vix] = $value2;
5749
+ }
5750
+ $this->setProperty( $propname, $values, $propattr );
5751
+ break;
5752
+ case 'EXRULE':
5753
+ case 'RRULE':
5754
+ $values = explode( ';', $line );
5755
+ $recur = array();
5756
+ foreach( $values as $value2 ) {
5757
+ if( empty( $value2 ))
5758
+ continue; // ;-char in ending position ???
5759
+ $value3 = explode( '=', $value2, 2 );
5760
+ $rulelabel = strtoupper( $value3[0] );
5761
+ switch( $rulelabel ) {
5762
+ case 'BYDAY': {
5763
+ $value4 = explode( ',', $value3[1] );
5764
+ if( 1 < count( $value4 )) {
5765
+ foreach( $value4 as $v5ix => $value5 ) {
5766
+ $value6 = array();
5767
+ $dayno = $dayname = null;
5768
+ $value5 = trim( (string) $value5 );
5769
+ if(( ctype_alpha( substr( $value5, -1 ))) &&
5770
+ ( ctype_alpha( substr( $value5, -2, 1 )))) {
5771
+ $dayname = substr( $value5, -2, 2 );
5772
+ if( 2 < strlen( $value5 ))
5773
+ $dayno = substr( $value5, 0, ( strlen( $value5 ) - 2 ));
5774
+ }
5775
+ if( $dayno )
5776
+ $value6[] = $dayno;
5777
+ if( $dayname )
5778
+ $value6['DAY'] = $dayname;
5779
+ $value4[$v5ix] = $value6;
5780
+ }
5781
+ }
5782
+ else {
5783
+ $value4 = array();
5784
+ $dayno = $dayname = null;
5785
+ $value5 = trim( (string) $value3[1] );
5786
+ if(( ctype_alpha( substr( $value5, -1 ))) &&
5787
+ ( ctype_alpha( substr( $value5, -2, 1 )))) {
5788
+ $dayname = substr( $value5, -2, 2 );
5789
+ if( 2 < strlen( $value5 ))
5790
+ $dayno = substr( $value5, 0, ( strlen( $value5 ) - 2 ));
5791
+ }
5792
+ if( $dayno )
5793
+ $value4[] = $dayno;
5794
+ if( $dayname )
5795
+ $value4['DAY'] = $dayname;
5796
+ }
5797
+ $recur[$rulelabel] = $value4;
5798
+ break;
5799
+ }
5800
+ default: {
5801
+ $value4 = explode( ',', $value3[1] );
5802
+ if( 1 < count( $value4 ))
5803
+ $value3[1] = $value4;
5804
+ $recur[$rulelabel] = $value3[1];
5805
+ break;
5806
+ }
5807
+ } // end - switch $rulelabel
5808
+ } // end - foreach( $values.. .
5809
+ $this->setProperty( $propname, $recur, $propattr );
5810
+ break;
5811
+ case 'ACTION':
5812
+ case 'CLASSIFICATION':
5813
+ case 'STATUS':
5814
+ case 'TRANSP':
5815
+ case 'UID':
5816
+ case 'TZID':
5817
+ case 'RELATED-TO':
5818
+ case 'TZNAME':
5819
+ $line = calendarComponent::_strunrep( $line );
5820
+ default:
5821
+ $this->setProperty( $propname, $line, $propattr );
5822
+ break;
5823
+ } // end switch( $propname.. .
5824
+ } // end - foreach( $proprows.. .
5825
+ unset( $unparsedtext, $this->unparsed, $proprows );
5826
+ if( isset( $this->components ) && is_array( $this->components ) && ( 0 < count( $this->components ))) {
5827
+ $ckeys = array_keys( $this->components );
5828
+ foreach( $ckeys as $ckey ) {
5829
+ if( !empty( $this->components[$ckey] ) && !empty( $this->components[$ckey]->unparsed )) {
5830
+ $this->components[$ckey]->parse();
5831
+ }
5832
+ }
5833
+ }
5834
+ return TRUE;
5835
+ }
5836
+ /*********************************************************************************/
5837
+ /*********************************************************************************/
5838
+ /**
5839
+ * return a copy of this component
5840
+ *
5841
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
5842
+ * @since 2.8.8 - 2011-03-15
5843
+ * @return object
5844
+ */
5845
+ function copy() {
5846
+ $serialized_contents = serialize( $this );
5847
+ $copy = unserialize( $serialized_contents );
5848
+ return $copy;
5849
+ }
5850
+ /*********************************************************************************/
5851
+ /*********************************************************************************/
5852
+ /**
5853
+ * delete calendar subcomponent from component container
5854
+ *
5855
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
5856
+ * @since 2.8.8 - 2011-03-15
5857
+ * @param mixed $arg1 ordno / component type / component uid
5858
+ * @param mixed $arg2 optional, ordno if arg1 = component type
5859
+ * @return void
5860
+ */
5861
+ function deleteComponent( $arg1, $arg2=FALSE ) {
5862
+ if( !isset( $this->components )) return FALSE;
5863
+ $argType = $index = null;
5864
+ if ( ctype_digit( (string) $arg1 )) {
5865
+ $argType = 'INDEX';
5866
+ $index = (int) $arg1 - 1;
5867
+ }
5868
+ elseif(( strlen( $arg1 ) <= strlen( 'vfreebusy' )) && ( FALSE === strpos( $arg1, '@' ))) {
5869
+ $argType = strtolower( $arg1 );
5870
+ $index = ( !empty( $arg2 ) && ctype_digit( (string) $arg2 )) ? (( int ) $arg2 - 1 ) : 0;
5871
+ }
5872
+ $cix2dC = 0;
5873
+ foreach ( $this->components as $cix => $component) {
5874
+ if( empty( $component )) continue;
5875
+ if(( 'INDEX' == $argType ) && ( $index == $cix )) {
5876
+ unset( $this->components[$cix] );
5877
+ return TRUE;
5878
+ }
5879
+ elseif( $argType == $component->objName ) {
5880
+ if( $index == $cix2dC ) {
5881
+ unset( $this->components[$cix] );
5882
+ return TRUE;
5883
+ }
5884
+ $cix2dC++;
5885
+ }
5886
+ elseif( !$argType && ($arg1 == $component->getProperty( 'uid' ))) {
5887
+ unset( $this->components[$cix] );
5888
+ return TRUE;
5889
+ }
5890
+ }
5891
+ return FALSE;
5892
+ }
5893
+ /**
5894
+ * get calendar component subcomponent from component container
5895
+ *
5896
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
5897
+ * @since 2.8.8 - 2011-03-15
5898
+ * @param mixed $arg1 optional, ordno/component type/ component uid
5899
+ * @param mixed $arg2 optional, ordno if arg1 = component type
5900
+ * @return object
5901
+ */
5902
+ function getComponent ( $arg1=FALSE, $arg2=FALSE ) {
5903
+ if( !isset( $this->components )) return FALSE;
5904
+ $index = $argType = null;
5905
+ if ( !$arg1 ) {
5906
+ $argType = 'INDEX';
5907
+ $index = $this->compix['INDEX'] =
5908
+ ( isset( $this->compix['INDEX'] )) ? $this->compix['INDEX'] + 1 : 1;
5909
+ }
5910
+ elseif ( ctype_digit( (string) $arg1 )) {
5911
+ $argType = 'INDEX';
5912
+ $index = (int) $arg1;
5913
+ unset( $this->compix );
5914
+ }
5915
+ elseif(( strlen( $arg1 ) <= strlen( 'vfreebusy' )) && ( FALSE === strpos( $arg1, '@' ))) {
5916
+ unset( $this->compix['INDEX'] );
5917
+ $argType = strtolower( $arg1 );
5918
+ if( !$arg2 )
5919
+ $index = $this->compix[$argType] = ( isset( $this->compix[$argType] )) ? $this->compix[$argType] + 1 : 1;
5920
+ else
5921
+ $index = (int) $arg2;
5922
+ }
5923
+ $index -= 1;
5924
+ $ckeys = array_keys( $this->components );
5925
+ if( !empty( $index) && ( $index > end( $ckeys )))
5926
+ return FALSE;
5927
+ $cix2gC = 0;
5928
+ foreach( $this->components as $cix => $component ) {
5929
+ if( empty( $component )) continue;
5930
+ if(( 'INDEX' == $argType ) && ( $index == $cix ))
5931
+ return $component->copy();
5932
+ elseif( $argType == $component->objName ) {
5933
+ if( $index == $cix2gC )
5934
+ return $component->copy();
5935
+ $cix2gC++;
5936
+ }
5937
+ elseif( !$argType && ( $arg1 == $component->getProperty( 'uid' )))
5938
+ return $component->copy();
5939
+ }
5940
+ /* not found.. . */
5941
+ unset( $this->compix );
5942
+ return false;
5943
+ }
5944
+ /**
5945
+ * add calendar component as subcomponent to container for subcomponents
5946
+ *
5947
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
5948
+ * @since 1.x.x - 2007-04-24
5949
+ * @param object $component calendar component
5950
+ * @return void
5951
+ */
5952
+ function addSubComponent ( $component ) {
5953
+ $this->setComponent( $component );
5954
+ }
5955
+ /**
5956
+ * create new calendar component subcomponent, already included within component
5957
+ *
5958
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
5959
+ * @since 2.6.33 - 2011-01-03
5960
+ * @param string $compType subcomponent type
5961
+ * @return object (reference)
5962
+ */
5963
+ function & newComponent( $compType ) {
5964
+ $config = $this->getConfig();
5965
+ $keys = array_keys( $this->components );
5966
+ $ix = end( $keys) + 1;
5967
+ switch( strtoupper( $compType )) {
5968
+ case 'ALARM':
5969
+ case 'VALARM':
5970
+ $this->components[$ix] = new valarm( $config );
5971
+ break;
5972
+ case 'STANDARD':
5973
+ array_unshift( $this->components, new vtimezone( 'STANDARD', $config ));
5974
+ $ix = 0;
5975
+ break;
5976
+ case 'DAYLIGHT':
5977
+ $this->components[$ix] = new vtimezone( 'DAYLIGHT', $config );
5978
+ break;
5979
+ default:
5980
+ return FALSE;
5981
+ }
5982
+ return $this->components[$ix];
5983
+ }
5984
+ /**
5985
+ * add calendar component as subcomponent to container for subcomponents
5986
+ *
5987
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
5988
+ * @since 2.8.8 - 2011-03-15
5989
+ * @param object $component calendar component
5990
+ * @param mixed $arg1 optional, ordno/component type/ component uid
5991
+ * @param mixed $arg2 optional, ordno if arg1 = component type
5992
+ * @return bool
5993
+ */
5994
+ function setComponent( $component, $arg1=FALSE, $arg2=FALSE ) {
5995
+ if( !isset( $this->components )) return FALSE;
5996
+ $component->setConfig( $this->getConfig(), FALSE, TRUE );
5997
+ if( !in_array( $component->objName, array( 'valarm', 'vtimezone', 'standard', 'daylight' ))) {
5998
+ /* make sure dtstamp and uid is set */
5999
+ $dummy = $component->getProperty( 'dtstamp' );
6000
+ $dummy = $component->getProperty( 'uid' );
6001
+ }
6002
+ if( !$arg1 ) { // plain insert, last in chain
6003
+ $this->components[] = $component->copy();
6004
+ return TRUE;
6005
+ }
6006
+ $argType = $index = null;
6007
+ if ( ctype_digit( (string) $arg1 )) { // index insert/replace
6008
+ $argType = 'INDEX';
6009
+ $index = (int) $arg1 - 1;
6010
+ }
6011
+ elseif( in_array( strtolower( $arg1 ), array( 'vevent', 'vtodo', 'vjournal', 'vfreebusy', 'valarm', 'vtimezone' ))) {
6012
+ $argType = strtolower( $arg1 );
6013
+ $index = ( ctype_digit( (string) $arg2 )) ? ((int) $arg2) - 1 : 0;
6014
+ }
6015
+ // else if arg1 is set, arg1 must be an UID
6016
+ $cix2sC = 0;
6017
+ foreach ( $this->components as $cix => $component2 ) {
6018
+ if( empty( $component2 )) continue;
6019
+ if(( 'INDEX' == $argType ) && ( $index == $cix )) { // index insert/replace
6020
+ $this->components[$cix] = $component->copy();
6021
+ return TRUE;
6022
+ }
6023
+ elseif( $argType == $component2->objName ) { // component Type index insert/replace
6024
+ if( $index == $cix2sC ) {
6025
+ $this->components[$cix] = $component->copy();
6026
+ return TRUE;
6027
+ }
6028
+ $cix2sC++;
6029
+ }
6030
+ elseif( !$argType && ( $arg1 == $component2->getProperty( 'uid' ))) { // UID insert/replace
6031
+ $this->components[$cix] = $component->copy();
6032
+ return TRUE;
6033
+ }
6034
+ }
6035
+ /* arg1=index and not found.. . insert at index .. .*/
6036
+ if( 'INDEX' == $argType ) {
6037
+ $this->components[$index] = $component->copy();
6038
+ ksort( $this->components, SORT_NUMERIC );
6039
+ }
6040
+ else /* not found.. . insert last in chain anyway .. .*/
6041
+ $this->components[] = $component->copy();
6042
+ return TRUE;
6043
+ }
6044
+ /**
6045
+ * creates formatted output for subcomponents
6046
+ *
6047
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
6048
+ * @since 2.6.27 - 2010-12-12
6049
+ * @return string
6050
+ */
6051
+ function createSubComponent() {
6052
+ $output = null;
6053
+ foreach( $this->components as $component ) {
6054
+ if( empty( $component )) continue;
6055
+ $component->setConfig( $this->getConfig(), FALSE, TRUE );
6056
+ $output .= $component->createComponent( $this->xcaldecl );
6057
+ }
6058
+ return $output;
6059
+ }
6060
+ /********************************************************************************/
6061
+ /**
6062
+ * break lines at pos 75
6063
+ *
6064
+ * Lines of text SHOULD NOT be longer than 75 octets, excluding the line
6065
+ * break. Long content lines SHOULD be split into a multiple line
6066
+ * representations using a line "folding" technique. That is, a long
6067
+ * line can be split between any two characters by inserting a CRLF
6068
+ * immediately followed by a single linear white space character (i.e.,
6069
+ * SPACE, US-ASCII decimal 32 or HTAB, US-ASCII decimal 9). Any sequence
6070
+ * of CRLF followed immediately by a single linear white space character
6071
+ * is ignored (i.e., removed) when processing the content type.
6072
+ *
6073
+ * Edited 2007-08-26 by Anders Litzell, anders@litzell.se to fix bug where
6074
+ * the reserved expression "\n" in the arg $string could be broken up by the
6075
+ * folding of lines, causing ambiguity in the return string.
6076
+ * Fix uses var $breakAtChar=75 and breaks the line at $breakAtChar-1 if need be.
6077
+ *
6078
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
6079
+ * @since 2.6.13 - 2010-12-06
6080
+ * @param string $value
6081
+ * @return string
6082
+ */
6083
+ function _size75( $string ) {
6084
+ $tmp = $string;
6085
+ $string = null;
6086
+ /* if PHP is config with mb_string.. . */
6087
+ if( defined( MB_OVERLOAD_STRING )) {
6088
+ $strlen = mb_strlen( $tmp );
6089
+ while( $strlen > 75 ) {
6090
+ $breakAtChar = 75;
6091
+ if( substr( $tmp, ( $breakAtChar - 1 ), strlen( '\n' )) == '\n' )
6092
+ $breakAtChar = $breakAtChar - 1;
6093
+ $string .= mb_substr( $tmp, 0, $breakAtChar );
6094
+ if( '\n' == substr( $string, ( 0 - strlen( '\n' ))))
6095
+ $string = substr( $string, 0, ( strlen( $string ) - strlen( '\n' )));
6096
+ if( $this->nl != mb_substr( $string, ( 0 - strlen( $this->nl ))))
6097
+ $string .= $this->nl;
6098
+ $tmp = ' '.mb_substr( $tmp, $breakAtChar );
6099
+ $strlen = mb_strlen( $tmp );
6100
+ } // end while
6101
+ if( 0 < $strlen ) {
6102
+ $string .= $tmp; // the rest
6103
+ if( '\n' == substr( $string, ( 0 - strlen( '\n' ))))
6104
+ $string = substr( $string, 0, ( strlen( $string ) - strlen( '\n' )));
6105
+ if( $this->nl != mb_substr( $string, ( 0 - strlen( $this->nl ))))
6106
+ $string .= $this->nl;
6107
+ }
6108
+ return $string;
6109
+ }
6110
+ /* if PHP is not config with mb_string.. . */
6111
+ $eolcharlen = strlen( '\n' );
6112
+ while( TRUE ) {
6113
+ $bytecnt = strlen( $tmp );
6114
+ $charCnt = $ix = 0;
6115
+ for( $ix = 0; $ix < $bytecnt; $ix++ ) {
6116
+ if(( 73 < $charCnt ) && ( '\n' == substr( $tmp, $ix, $eolcharlen ))) {
6117
+ $ix += $eolcharlen;
6118
+ break; // break when '\n' and eol
6119
+ }
6120
+ elseif( 74 < $charCnt )
6121
+ break; // always break for-loop here
6122
+ else {
6123
+ $byte = ord( $tmp[$ix] );
6124
+ if ($byte <= 127) { // add a one byte character
6125
+ $string .= substr( $tmp, $ix, 1 );
6126
+ $charCnt += 1;
6127
+ }
6128
+ else if ($byte >= 194 && $byte <= 223) { // start byte in two byte character
6129
+ $string .= substr( $tmp, $ix, 2 ); // add a two bytes character
6130
+ $charCnt += 1;
6131
+ }
6132
+ else if ($byte >= 224 && $byte <= 239) { // start byte in three bytes character
6133
+ $string .= substr( $tmp, $ix, 3 ); // add a three bytes character
6134
+ $charCnt += 1;
6135
+ }
6136
+ else if ($byte >= 240 && $byte <= 244) { // start byte in four bytes character
6137
+ $string .= substr( $tmp, $ix, 4 ); // add a four bytes character
6138
+ $charCnt += 1;
6139
+ }
6140
+ }
6141
+ } // end for
6142
+ if( '\n' == substr( $string, ( 0 - strlen( '\n' ))))
6143
+ $string = substr( $string, 0, ( strlen( $string ) - strlen( '\n' )));
6144
+ if( $this->nl != substr( $string, ( 0 - strlen( $this->nl ))))
6145
+ $string .= $this->nl;
6146
+ $tmp = substr( $tmp, $ix );
6147
+ if( empty( $tmp ))
6148
+ break; // while-loop breakes here
6149
+ else
6150
+ $tmp = ' '.$tmp;
6151
+ } // end while
6152
+ if( !empty( $tmp )) {
6153
+ if( '\n' == substr( $string, ( 0 - strlen( '\n' ))))
6154
+ $string = substr( $string, 0, ( strlen( $string ) - strlen( '\n' ))).$this->nl;
6155
+ if( $this->nl != substr( $string, ( 0 - strlen( $this->nl ))))
6156
+ $string .= $this->nl;
6157
+ }
6158
+ return $string;
6159
+ }
6160
+ /**
6161
+ * special characters management output
6162
+ *
6163
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
6164
+ * @since 2.6.15 - 2010-09-24
6165
+ * @param string $string
6166
+ * @return string
6167
+ */
6168
+ function _strrep( $string ) {
6169
+ switch( $this->format ) {
6170
+ case 'xcal':
6171
+ $string = str_replace( '\n', $this->nl, $string);
6172
+ $string = htmlspecialchars( strip_tags( stripslashes( urldecode ( $string ))));
6173
+ break;
6174
+ default:
6175
+ $pos = 0;
6176
+ $specChars = array( 'n', 'N', 'r', ',', ';' );
6177
+ while( $pos <= strlen( $string )) {
6178
+ $pos = strpos( $string, "\\", $pos );
6179
+ if( FALSE === $pos )
6180
+ break;
6181
+ if( !in_array( substr( $string, $pos, 1 ), $specChars )) {
6182
+ $string = substr( $string, 0, $pos )."\\".substr( $string, ( $pos + 1 ));
6183
+ $pos += 1;
6184
+ }
6185
+ $pos += 1;
6186
+ }
6187
+ if( FALSE !== strpos( $string, '"' ))
6188
+ $string = str_replace('"', "'", $string);
6189
+ if( FALSE !== strpos( $string, ',' ))
6190
+ $string = str_replace(',', '\,', $string);
6191
+ if( FALSE !== strpos( $string, ';' ))
6192
+ $string = str_replace(';', '\;', $string);
6193
+
6194
+ if( FALSE !== strpos( $string, "\r\n" ))
6195
+ $string = str_replace( "\r\n", '\n', $string);
6196
+ elseif( FALSE !== strpos( $string, "\r" ))
6197
+ $string = str_replace( "\r", '\n', $string);
6198
+
6199
+ elseif( FALSE !== strpos( $string, "\n" ))
6200
+ $string = str_replace( "\n", '\n', $string);
6201
+
6202
+ if( FALSE !== strpos( $string, '\N' ))
6203
+ $string = str_replace( '\N', '\n', $string);
6204
+ // if( FALSE !== strpos( $string, $this->nl ))
6205
+ $string = str_replace( $this->nl, '\n', $string);
6206
+ break;
6207
+ }
6208
+ return $string;
6209
+ }
6210
+ /**
6211
+ * special characters management input (from iCal file)
6212
+ *
6213
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
6214
+ * @since 2.6.22 - 2010-10-17
6215
+ * @param string $string
6216
+ * @return string
6217
+ */
6218
+ static function _strunrep( $string ) {
6219
+ $string = str_replace( '\\\\', '\\', $string);
6220
+ $string = str_replace( '\,', ',', $string);
6221
+ $string = str_replace( '\;', ';', $string);
6222
+ // $string = str_replace( '\n', $this->nl, $string); // ??
6223
+ return $string;
6224
+ }
6225
+ }
6226
+ /*********************************************************************************/
6227
+ /*********************************************************************************/
6228
+ /**
6229
+ * class for calendar component VEVENT
6230
+ *
6231
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
6232
+ * @since 2.5.1 - 2008-10-12
6233
+ */
6234
+ class vevent extends calendarComponent {
6235
+ var $attach;
6236
+ var $attendee;
6237
+ var $categories;
6238
+ var $comment;
6239
+ var $contact;
6240
+ var $class;
6241
+ var $created;
6242
+ var $description;
6243
+ var $dtend;
6244
+ var $dtstart;
6245
+ var $duration;
6246
+ var $exdate;
6247
+ var $exrule;
6248
+ var $geo;
6249
+ var $lastmodified;
6250
+ var $location;
6251
+ var $organizer;
6252
+ var $priority;
6253
+ var $rdate;
6254
+ var $recurrenceid;
6255
+ var $relatedto;
6256
+ var $requeststatus;
6257
+ var $resources;
6258
+ var $rrule;
6259
+ var $sequence;
6260
+ var $status;
6261
+ var $summary;
6262
+ var $transp;
6263
+ var $url;
6264
+ var $xprop;
6265
+ // component subcomponents container
6266
+ var $components;
6267
+ /**
6268
+ * constructor for calendar component VEVENT object
6269
+ *
6270
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
6271
+ * @since 2.8.2 - 2011-05-01
6272
+ * @param array $config
6273
+ * @return void
6274
+ */
6275
+ function vevent( $config = array()) {
6276
+ $this->calendarComponent();
6277
+
6278
+ $this->attach = '';
6279
+ $this->attendee = '';
6280
+ $this->categories = '';
6281
+ $this->class = '';
6282
+ $this->comment = '';
6283
+ $this->contact = '';
6284
+ $this->created = '';
6285
+ $this->description = '';
6286
+ $this->dtstart = '';
6287
+ $this->dtend = '';
6288
+ $this->duration = '';
6289
+ $this->exdate = '';
6290
+ $this->exrule = '';
6291
+ $this->geo = '';
6292
+ $this->lastmodified = '';
6293
+ $this->location = '';
6294
+ $this->organizer = '';
6295
+ $this->priority = '';
6296
+ $this->rdate = '';
6297
+ $this->recurrenceid = '';
6298
+ $this->relatedto = '';
6299
+ $this->requeststatus = '';
6300
+ $this->resources = '';
6301
+ $this->rrule = '';
6302
+ $this->sequence = '';
6303
+ $this->status = '';
6304
+ $this->summary = '';
6305
+ $this->transp = '';
6306
+ $this->url = '';
6307
+ $this->xprop = '';
6308
+
6309
+ $this->components = array();
6310
+
6311
+ if( defined( 'ICAL_LANG' ) && !isset( $config['language'] ))
6312
+ $config['language'] = ICAL_LANG;
6313
+ if( !isset( $config['allowEmpty'] )) $config['allowEmpty'] = TRUE;
6314
+ if( !isset( $config['nl'] )) $config['nl'] = "\r\n";
6315
+ if( !isset( $config['format'] )) $config['format'] = 'iCal';
6316
+ if( !isset( $config['delimiter'] )) $config['delimiter'] = DIRECTORY_SEPARATOR;
6317
+ $this->setConfig( $config );
6318
+
6319
+ }
6320
+ /**
6321
+ * create formatted output for calendar component VEVENT object instance
6322
+ *
6323
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
6324
+ * @since 2.5.1 - 2008-11-07
6325
+ * @param array $xcaldecl
6326
+ * @return string
6327
+ */
6328
+ function createComponent( &$xcaldecl ) {
6329
+ $objectname = $this->_createFormat();
6330
+ $component = $this->componentStart1.$objectname.$this->componentStart2.$this->nl;
6331
+ $component .= $this->createUid();
6332
+ $component .= $this->createDtstamp();
6333
+ $component .= $this->createAttach();
6334
+ $component .= $this->createAttendee();
6335
+ $component .= $this->createCategories();
6336
+ $component .= $this->createComment();
6337
+ $component .= $this->createContact();
6338
+ $component .= $this->createClass();
6339
+ $component .= $this->createCreated();
6340
+ $component .= $this->createDescription();
6341
+ $component .= $this->createDtstart();
6342
+ $component .= $this->createDtend();
6343
+ $component .= $this->createDuration();
6344
+ $component .= $this->createExdate();
6345
+ $component .= $this->createExrule();
6346
+ $component .= $this->createGeo();
6347
+ $component .= $this->createLastModified();
6348
+ $component .= $this->createLocation();
6349
+ $component .= $this->createOrganizer();
6350
+ $component .= $this->createPriority();
6351
+ $component .= $this->createRdate();
6352
+ $component .= $this->createRrule();
6353
+ $component .= $this->createRelatedTo();
6354
+ $component .= $this->createRequestStatus();
6355
+ $component .= $this->createRecurrenceid();
6356
+ $component .= $this->createResources();
6357
+ $component .= $this->createSequence();
6358
+ $component .= $this->createStatus();
6359
+ $component .= $this->createSummary();
6360
+ $component .= $this->createTransp();
6361
+ $component .= $this->createUrl();
6362
+ $component .= $this->createXprop();
6363
+ $component .= $this->createSubComponent();
6364
+ $component .= $this->componentEnd1.$objectname.$this->componentEnd2;
6365
+ if( is_array( $this->xcaldecl ) && ( 0 < count( $this->xcaldecl ))) {
6366
+ foreach( $this->xcaldecl as $localxcaldecl )
6367
+ $xcaldecl[] = $localxcaldecl;
6368
+ }
6369
+ return $component;
6370
+ }
6371
+ }
6372
+ /*********************************************************************************/
6373
+ /*********************************************************************************/
6374
+ /**
6375
+ * class for calendar component VTODO
6376
+ *
6377
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
6378
+ * @since 2.5.1 - 2008-10-12
6379
+ */
6380
+ class vtodo extends calendarComponent {
6381
+ var $attach;
6382
+ var $attendee;
6383
+ var $categories;
6384
+ var $comment;
6385
+ var $completed;
6386
+ var $contact;
6387
+ var $class;
6388
+ var $created;
6389
+ var $description;
6390
+ var $dtstart;
6391
+ var $due;
6392
+ var $duration;
6393
+ var $exdate;
6394
+ var $exrule;
6395
+ var $geo;
6396
+ var $lastmodified;
6397
+ var $location;
6398
+ var $organizer;
6399
+ var $percentcomplete;
6400
+ var $priority;
6401
+ var $rdate;
6402
+ var $recurrenceid;
6403
+ var $relatedto;
6404
+ var $requeststatus;
6405
+ var $resources;
6406
+ var $rrule;
6407
+ var $sequence;
6408
+ var $status;
6409
+ var $summary;
6410
+ var $url;
6411
+ var $xprop;
6412
+ // component subcomponents container
6413
+ var $components;
6414
+ /**
6415
+ * constructor for calendar component VTODO object
6416
+ *
6417
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
6418
+ * @since 2.8.2 - 2011-05-01
6419
+ * @param array $config
6420
+ * @return void
6421
+ */
6422
+ function vtodo( $config = array()) {
6423
+ $this->calendarComponent();
6424
+
6425
+ $this->attach = '';
6426
+ $this->attendee = '';
6427
+ $this->categories = '';
6428
+ $this->class = '';
6429
+ $this->comment = '';
6430
+ $this->completed = '';
6431
+ $this->contact = '';
6432
+ $this->created = '';
6433
+ $this->description = '';
6434
+ $this->dtstart = '';
6435
+ $this->due = '';
6436
+ $this->duration = '';
6437
+ $this->exdate = '';
6438
+ $this->exrule = '';
6439
+ $this->geo = '';
6440
+ $this->lastmodified = '';
6441
+ $this->location = '';
6442
+ $this->organizer = '';
6443
+ $this->percentcomplete = '';
6444
+ $this->priority = '';
6445
+ $this->rdate = '';
6446
+ $this->recurrenceid = '';
6447
+ $this->relatedto = '';
6448
+ $this->requeststatus = '';
6449
+ $this->resources = '';
6450
+ $this->rrule = '';
6451
+ $this->sequence = '';
6452
+ $this->status = '';
6453
+ $this->summary = '';
6454
+ $this->url = '';
6455
+ $this->xprop = '';
6456
+
6457
+ $this->components = array();
6458
+
6459
+ if( defined( 'ICAL_LANG' ) && !isset( $config['language'] ))
6460
+ $config['language'] = ICAL_LANG;
6461
+ if( !isset( $config['allowEmpty'] )) $config['allowEmpty'] = TRUE;
6462
+ if( !isset( $config['nl'] )) $config['nl'] = "\r\n";
6463
+ if( !isset( $config['format'] )) $config['format'] = 'iCal';
6464
+ if( !isset( $config['delimiter'] )) $config['delimiter'] = DIRECTORY_SEPARATOR;
6465
+ $this->setConfig( $config );
6466
+
6467
+ }
6468
+ /**
6469
+ * create formatted output for calendar component VTODO object instance
6470
+ *
6471
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
6472
+ * @since 2.5.1 - 2008-11-07
6473
+ * @param array $xcaldecl
6474
+ * @return string
6475
+ */
6476
+ function createComponent( &$xcaldecl ) {
6477
+ $objectname = $this->_createFormat();
6478
+ $component = $this->componentStart1.$objectname.$this->componentStart2.$this->nl;
6479
+ $component .= $this->createUid();
6480
+ $component .= $this->createDtstamp();
6481
+ $component .= $this->createAttach();
6482
+ $component .= $this->createAttendee();
6483
+ $component .= $this->createCategories();
6484
+ $component .= $this->createClass();
6485
+ $component .= $this->createComment();
6486
+ $component .= $this->createCompleted();
6487
+ $component .= $this->createContact();
6488
+ $component .= $this->createCreated();
6489
+ $component .= $this->createDescription();
6490
+ $component .= $this->createDtstart();
6491
+ $component .= $this->createDue();
6492
+ $component .= $this->createDuration();
6493
+ $component .= $this->createExdate();
6494
+ $component .= $this->createExrule();
6495
+ $component .= $this->createGeo();
6496
+ $component .= $this->createLastModified();
6497
+ $component .= $this->createLocation();
6498
+ $component .= $this->createOrganizer();
6499
+ $component .= $this->createPercentComplete();
6500
+ $component .= $this->createPriority();
6501
+ $component .= $this->createRdate();
6502
+ $component .= $this->createRelatedTo();
6503
+ $component .= $this->createRequestStatus();
6504
+ $component .= $this->createRecurrenceid();
6505
+ $component .= $this->createResources();
6506
+ $component .= $this->createRrule();
6507
+ $component .= $this->createSequence();
6508
+ $component .= $this->createStatus();
6509
+ $component .= $this->createSummary();
6510
+ $component .= $this->createUrl();
6511
+ $component .= $this->createXprop();
6512
+ $component .= $this->createSubComponent();
6513
+ $component .= $this->componentEnd1.$objectname.$this->componentEnd2;
6514
+ if( is_array( $this->xcaldecl ) && ( 0 < count( $this->xcaldecl ))) {
6515
+ foreach( $this->xcaldecl as $localxcaldecl )
6516
+ $xcaldecl[] = $localxcaldecl;
6517
+ }
6518
+ return $component;
6519
+ }
6520
+ }
6521
+ /*********************************************************************************/
6522
+ /*********************************************************************************/
6523
+ /**
6524
+ * class for calendar component VJOURNAL
6525
+ *
6526
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
6527
+ * @since 2.5.1 - 2008-10-12
6528
+ */
6529
+ class vjournal extends calendarComponent {
6530
+ var $attach;
6531
+ var $attendee;
6532
+ var $categories;
6533
+ var $comment;
6534
+ var $contact;
6535
+ var $class;
6536
+ var $created;
6537
+ var $description;
6538
+ var $dtstart;
6539
+ var $exdate;
6540
+ var $exrule;
6541
+ var $lastmodified;
6542
+ var $organizer;
6543
+ var $rdate;
6544
+ var $recurrenceid;
6545
+ var $relatedto;
6546
+ var $requeststatus;
6547
+ var $rrule;
6548
+ var $sequence;
6549
+ var $status;
6550
+ var $summary;
6551
+ var $url;
6552
+ var $xprop;
6553
+ /**
6554
+ * constructor for calendar component VJOURNAL object
6555
+ *
6556
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
6557
+ * @since 2.8.2 - 2011-05-01
6558
+ * @param array $config
6559
+ * @return void
6560
+ */
6561
+ function vjournal( $config = array()) {
6562
+ $this->calendarComponent();
6563
+
6564
+ $this->attach = '';
6565
+ $this->attendee = '';
6566
+ $this->categories = '';
6567
+ $this->class = '';
6568
+ $this->comment = '';
6569
+ $this->contact = '';
6570
+ $this->created = '';
6571
+ $this->description = '';
6572
+ $this->dtstart = '';
6573
+ $this->exdate = '';
6574
+ $this->exrule = '';
6575
+ $this->lastmodified = '';
6576
+ $this->organizer = '';
6577
+ $this->rdate = '';
6578
+ $this->recurrenceid = '';
6579
+ $this->relatedto = '';
6580
+ $this->requeststatus = '';
6581
+ $this->rrule = '';
6582
+ $this->sequence = '';
6583
+ $this->status = '';
6584
+ $this->summary = '';
6585
+ $this->url = '';
6586
+ $this->xprop = '';
6587
+
6588
+ if( defined( 'ICAL_LANG' ) && !isset( $config['language'] ))
6589
+ $config['language'] = ICAL_LANG;
6590
+ if( !isset( $config['allowEmpty'] )) $config['allowEmpty'] = TRUE;
6591
+ if( !isset( $config['nl'] )) $config['nl'] = "\r\n";
6592
+ if( !isset( $config['format'] )) $config['format'] = 'iCal';
6593
+ if( !isset( $config['delimiter'] )) $config['delimiter'] = DIRECTORY_SEPARATOR;
6594
+ $this->setConfig( $config );
6595
+
6596
+ }
6597
+ /**
6598
+ * create formatted output for calendar component VJOURNAL object instance
6599
+ *
6600
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
6601
+ * @since 2.5.1 - 2008-10-12
6602
+ * @param array $xcaldecl
6603
+ * @return string
6604
+ */
6605
+ function createComponent( &$xcaldecl ) {
6606
+ $objectname = $this->_createFormat();
6607
+ $component = $this->componentStart1.$objectname.$this->componentStart2.$this->nl;
6608
+ $component .= $this->createUid();
6609
+ $component .= $this->createDtstamp();
6610
+ $component .= $this->createAttach();
6611
+ $component .= $this->createAttendee();
6612
+ $component .= $this->createCategories();
6613
+ $component .= $this->createClass();
6614
+ $component .= $this->createComment();
6615
+ $component .= $this->createContact();
6616
+ $component .= $this->createCreated();
6617
+ $component .= $this->createDescription();
6618
+ $component .= $this->createDtstart();
6619
+ $component .= $this->createExdate();
6620
+ $component .= $this->createExrule();
6621
+ $component .= $this->createLastModified();
6622
+ $component .= $this->createOrganizer();
6623
+ $component .= $this->createRdate();
6624
+ $component .= $this->createRequestStatus();
6625
+ $component .= $this->createRecurrenceid();
6626
+ $component .= $this->createRelatedTo();
6627
+ $component .= $this->createRrule();
6628
+ $component .= $this->createSequence();
6629
+ $component .= $this->createStatus();
6630
+ $component .= $this->createSummary();
6631
+ $component .= $this->createUrl();
6632
+ $component .= $this->createXprop();
6633
+ $component .= $this->componentEnd1.$objectname.$this->componentEnd2;
6634
+ if( is_array( $this->xcaldecl ) && ( 0 < count( $this->xcaldecl ))) {
6635
+ foreach( $this->xcaldecl as $localxcaldecl )
6636
+ $xcaldecl[] = $localxcaldecl;
6637
+ }
6638
+ return $component;
6639
+ }
6640
+ }
6641
+ /*********************************************************************************/
6642
+ /*********************************************************************************/
6643
+ /**
6644
+ * class for calendar component VFREEBUSY
6645
+ *
6646
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
6647
+ * @since 2.5.1 - 2008-10-12
6648
+ */
6649
+ class vfreebusy extends calendarComponent {
6650
+ var $attendee;
6651
+ var $comment;
6652
+ var $contact;
6653
+ var $dtend;
6654
+ var $dtstart;
6655
+ var $duration;
6656
+ var $freebusy;
6657
+ var $organizer;
6658
+ var $requeststatus;
6659
+ var $url;
6660
+ var $xprop;
6661
+ // component subcomponents container
6662
+ var $components;
6663
+ /**
6664
+ * constructor for calendar component VFREEBUSY object
6665
+ *
6666
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
6667
+ * @since 2.8.2 - 2011-05-01
6668
+ * @param array $config
6669
+ * @return void
6670
+ */
6671
+ function vfreebusy( $config = array()) {
6672
+ $this->calendarComponent();
6673
+
6674
+ $this->attendee = '';
6675
+ $this->comment = '';
6676
+ $this->contact = '';
6677
+ $this->dtend = '';
6678
+ $this->dtstart = '';
6679
+ $this->duration = '';
6680
+ $this->freebusy = '';
6681
+ $this->organizer = '';
6682
+ $this->requeststatus = '';
6683
+ $this->url = '';
6684
+ $this->xprop = '';
6685
+
6686
+ if( defined( 'ICAL_LANG' ) && !isset( $config['language'] ))
6687
+ $config['language'] = ICAL_LANG;
6688
+ if( !isset( $config['allowEmpty'] )) $config['allowEmpty'] = TRUE;
6689
+ if( !isset( $config['nl'] )) $config['nl'] = "\r\n";
6690
+ if( !isset( $config['format'] )) $config['format'] = 'iCal';
6691
+ if( !isset( $config['delimiter'] )) $config['delimiter'] = DIRECTORY_SEPARATOR;
6692
+ $this->setConfig( $config );
6693
+
6694
+ }
6695
+ /**
6696
+ * create formatted output for calendar component VFREEBUSY object instance
6697
+ *
6698
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
6699
+ * @since 2.3.1 - 2007-11-19
6700
+ * @param array $xcaldecl
6701
+ * @return string
6702
+ */
6703
+ function createComponent( &$xcaldecl ) {
6704
+ $objectname = $this->_createFormat();
6705
+ $component = $this->componentStart1.$objectname.$this->componentStart2.$this->nl;
6706
+ $component .= $this->createUid();
6707
+ $component .= $this->createDtstamp();
6708
+ $component .= $this->createAttendee();
6709
+ $component .= $this->createComment();
6710
+ $component .= $this->createContact();
6711
+ $component .= $this->createDtstart();
6712
+ $component .= $this->createDtend();
6713
+ $component .= $this->createDuration();
6714
+ $component .= $this->createFreebusy();
6715
+ $component .= $this->createOrganizer();
6716
+ $component .= $this->createRequestStatus();
6717
+ $component .= $this->createUrl();
6718
+ $component .= $this->createXprop();
6719
+ $component .= $this->componentEnd1.$objectname.$this->componentEnd2;
6720
+ if( is_array( $this->xcaldecl ) && ( 0 < count( $this->xcaldecl ))) {
6721
+ foreach( $this->xcaldecl as $localxcaldecl )
6722
+ $xcaldecl[] = $localxcaldecl;
6723
+ }
6724
+ return $component;
6725
+ }
6726
+ }
6727
+ /*********************************************************************************/
6728
+ /*********************************************************************************/
6729
+ /**
6730
+ * class for calendar component VALARM
6731
+ *
6732
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
6733
+ * @since 2.5.1 - 2008-10-12
6734
+ */
6735
+ class valarm extends calendarComponent {
6736
+ var $action;
6737
+ var $attach;
6738
+ var $attendee;
6739
+ var $description;
6740
+ var $duration;
6741
+ var $repeat;
6742
+ var $summary;
6743
+ var $trigger;
6744
+ var $xprop;
6745
+ /**
6746
+ * constructor for calendar component VALARM object
6747
+ *
6748
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
6749
+ * @since 2.8.2 - 2011-05-01
6750
+ * @param array $config
6751
+ * @return void
6752
+ */
6753
+ function valarm( $config = array()) {
6754
+ $this->calendarComponent();
6755
+
6756
+ $this->action = '';
6757
+ $this->attach = '';
6758
+ $this->attendee = '';
6759
+ $this->description = '';
6760
+ $this->duration = '';
6761
+ $this->repeat = '';
6762
+ $this->summary = '';
6763
+ $this->trigger = '';
6764
+ $this->xprop = '';
6765
+
6766
+ if( defined( 'ICAL_LANG' ) && !isset( $config['language'] ))
6767
+ $config['language'] = ICAL_LANG;
6768
+ if( !isset( $config['allowEmpty'] )) $config['allowEmpty'] = TRUE;
6769
+ if( !isset( $config['nl'] )) $config['nl'] = "\r\n";
6770
+ if( !isset( $config['format'] )) $config['format'] = 'iCal';
6771
+ if( !isset( $config['delimiter'] )) $config['delimiter'] = DIRECTORY_SEPARATOR;
6772
+ $this->setConfig( $config );
6773
+
6774
+ }
6775
+ /**
6776
+ * create formatted output for calendar component VALARM object instance
6777
+ *
6778
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
6779
+ * @since 2.5.1 - 2008-10-22
6780
+ * @param array $xcaldecl
6781
+ * @return string
6782
+ */
6783
+ function createComponent( &$xcaldecl ) {
6784
+ $objectname = $this->_createFormat();
6785
+ $component = $this->componentStart1.$objectname.$this->componentStart2.$this->nl;
6786
+ $component .= $this->createAction();
6787
+ $component .= $this->createAttach();
6788
+ $component .= $this->createAttendee();
6789
+ $component .= $this->createDescription();
6790
+ $component .= $this->createDuration();
6791
+ $component .= $this->createRepeat();
6792
+ $component .= $this->createSummary();
6793
+ $component .= $this->createTrigger();
6794
+ $component .= $this->createXprop();
6795
+ $component .= $this->componentEnd1.$objectname.$this->componentEnd2;
6796
+ return $component;
6797
+ }
6798
+ }
6799
+ /**********************************************************************************
6800
+ /*********************************************************************************/
6801
+ /**
6802
+ * class for calendar component VTIMEZONE
6803
+ *
6804
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
6805
+ * @since 2.5.1 - 2008-10-12
6806
+ */
6807
+ class vtimezone extends calendarComponent {
6808
+ var $timezonetype;
6809
+
6810
+ var $comment;
6811
+ var $dtstart;
6812
+ var $lastmodified;
6813
+ var $rdate;
6814
+ var $rrule;
6815
+ var $tzid;
6816
+ var $tzname;
6817
+ var $tzoffsetfrom;
6818
+ var $tzoffsetto;
6819
+ var $tzurl;
6820
+ var $xprop;
6821
+ // component subcomponents container
6822
+ var $components;
6823
+ /**
6824
+ * constructor for calendar component VTIMEZONE object
6825
+ *
6826
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
6827
+ * @since 2.8.2 - 2011-05-01
6828
+ * @param mixed $timezonetype optional, default FALSE ( STANDARD / DAYLIGHT )
6829
+ * @param array $config
6830
+ * @return void
6831
+ */
6832
+ function vtimezone( $timezonetype=FALSE, $config = array()) {
6833
+ if( is_array( $timezonetype )) {
6834
+ $config = $timezonetype;
6835
+ $timezonetype = FALSE;
6836
+ }
6837
+ if( !$timezonetype )
6838
+ $this->timezonetype = 'VTIMEZONE';
6839
+ else
6840
+ $this->timezonetype = strtoupper( $timezonetype );
6841
+ $this->calendarComponent();
6842
+
6843
+ $this->comment = '';
6844
+ $this->dtstart = '';
6845
+ $this->lastmodified = '';
6846
+ $this->rdate = '';
6847
+ $this->rrule = '';
6848
+ $this->tzid = '';
6849
+ $this->tzname = '';
6850
+ $this->tzoffsetfrom = '';
6851
+ $this->tzoffsetto = '';
6852
+ $this->tzurl = '';
6853
+ $this->xprop = '';
6854
+
6855
+ $this->components = array();
6856
+
6857
+ if( defined( 'ICAL_LANG' ) && !isset( $config['language'] ))
6858
+ $config['language'] = ICAL_LANG;
6859
+ if( !isset( $config['allowEmpty'] )) $config['allowEmpty'] = TRUE;
6860
+ if( !isset( $config['nl'] )) $config['nl'] = "\r\n";
6861
+ if( !isset( $config['format'] )) $config['format'] = 'iCal';
6862
+ if( !isset( $config['delimiter'] )) $config['delimiter'] = DIRECTORY_SEPARATOR;
6863
+ $this->setConfig( $config );
6864
+
6865
+ }
6866
+ /**
6867
+ * create formatted output for calendar component VTIMEZONE object instance
6868
+ *
6869
+ * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
6870
+ * @since 2.5.1 - 2008-10-25
6871
+ * @param array $xcaldecl
6872
+ * @return string
6873
+ */
6874
+ function createComponent( &$xcaldecl ) {
6875
+ $objectname = $this->_createFormat();
6876
+ $component = $this->componentStart1.$objectname.$this->componentStart2.$this->nl;
6877
+ $component .= $this->createTzid();
6878
+ $component .= $this->createLastModified();
6879
+ $component .= $this->createTzurl();
6880
+ $component .= $this->createDtstart();
6881
+ $component .= $this->createTzoffsetfrom();
6882
+ $component .= $this->createTzoffsetto();
6883
+ $component .= $this->createComment();
6884
+ $component .= $this->createRdate();
6885
+ $component .= $this->createRrule();
6886
+ $component .= $this->createTzname();
6887
+ $component .= $this->createXprop();
6888
+ $component .= $this->createSubComponent();
6889
+ $component .= $this->componentEnd1.$objectname.$this->componentEnd2;
6890
+ if( is_array( $this->xcaldecl ) && ( 0 < count( $this->xcaldecl ))) {
6891
+ foreach( $this->xcaldecl as $localxcaldecl )
6892
+ $xcaldecl[] = $localxcaldecl;
6893
+ }
6894
+ return $component;
6895
+ }
6896
+ }
6897
+ ?>
lib/iCalcreator-2.10/lgpl.txt ADDED
@@ -0,0 +1,504 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ GNU LESSER GENERAL PUBLIC LICENSE
2
+ Version 2.1, February 1999
3
+
4
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
5
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6
+ Everyone is permitted to copy and distribute verbatim copies
7
+ of this license document, but changing it is not allowed.
8
+
9
+ [This is the first released version of the Lesser GPL. It also counts
10
+ as the successor of the GNU Library Public License, version 2, hence
11
+ the version number 2.1.]
12
+
13
+ Preamble
14
+
15
+ The licenses for most software are designed to take away your
16
+ freedom to share and change it. By contrast, the GNU General Public
17
+ Licenses are intended to guarantee your freedom to share and change
18
+ free software--to make sure the software is free for all its users.
19
+
20
+ This license, the Lesser General Public License, applies to some
21
+ specially designated software packages--typically libraries--of the
22
+ Free Software Foundation and other authors who decide to use it. You
23
+ can use it too, but we suggest you first think carefully about whether
24
+ this license or the ordinary General Public License is the better
25
+ strategy to use in any particular case, based on the explanations below.
26
+
27
+ When we speak of free software, we are referring to freedom of use,
28
+ not price. Our General Public Licenses are designed to make sure that
29
+ you have the freedom to distribute copies of free software (and charge
30
+ for this service if you wish); that you receive source code or can get
31
+ it if you want it; that you can change the software and use pieces of
32
+ it in new free programs; and that you are informed that you can do
33
+ these things.
34
+
35
+ To protect your rights, we need to make restrictions that forbid
36
+ distributors to deny you these rights or to ask you to surrender these
37
+ rights. These restrictions translate to certain responsibilities for
38
+ you if you distribute copies of the library or if you modify it.
39
+
40
+ For example, if you distribute copies of the library, whether gratis
41
+ or for a fee, you must give the recipients all the rights that we gave
42
+ you. You must make sure that they, too, receive or can get the source
43
+ code. If you link other code with the library, you must provide
44
+ complete object files to the recipients, so that they can relink them
45
+ with the library after making changes to the library and recompiling
46
+ it. And you must show them these terms so they know their rights.
47
+
48
+ We protect your rights with a two-step method: (1) we copyright the
49
+ library, and (2) we offer you this license, which gives you legal
50
+ permission to copy, distribute and/or modify the library.
51
+
52
+ To protect each distributor, we want to make it very clear that
53
+ there is no warranty for the free library. Also, if the library is
54
+ modified by someone else and passed on, the recipients should know
55
+ that what they have is not the original version, so that the original
56
+ author's reputation will not be affected by problems that might be
57
+ introduced by others.
58
+
59
+ Finally, software patents pose a constant threat to the existence of
60
+ any free program. We wish to make sure that a company cannot
61
+ effectively restrict the users of a free program by obtaining a
62
+ restrictive license from a patent holder. Therefore, we insist that
63
+ any patent license obtained for a version of the library must be
64
+ consistent with the full freedom of use specified in this license.
65
+
66
+ Most GNU software, including some libraries, is covered by the
67
+ ordinary GNU General Public License. This license, the GNU Lesser
68
+ General Public License, applies to certain designated libraries, and
69
+ is quite different from the ordinary General Public License. We use
70
+ this license for certain libraries in order to permit linking those
71
+ libraries into non-free programs.
72
+
73
+ When a program is linked with a library, whether statically or using
74
+ a shared library, the combination of the two is legally speaking a
75
+ combined work, a derivative of the original library. The ordinary
76
+ General Public License therefore permits such linking only if the
77
+ entire combination fits its criteria of freedom. The Lesser General
78
+ Public License permits more lax criteria for linking other code with
79
+ the library.
80
+
81
+ We call this license the "Lesser" General Public License because it
82
+ does Less to protect the user's freedom than the ordinary General
83
+ Public License. It also provides other free software developers Less
84
+ of an advantage over competing non-free programs. These disadvantages
85
+ are the reason we use the ordinary General Public License for many
86
+ libraries. However, the Lesser license provides advantages in certain
87
+ special circumstances.
88
+
89
+ For example, on rare occasions, there may be a special need to
90
+ encourage the widest possible use of a certain library, so that it becomes
91
+ a de-facto standard. To achieve this, non-free programs must be
92
+ allowed to use the library. A more frequent case is that a free
93
+ library does the same job as widely used non-free libraries. In this
94
+ case, there is little to gain by limiting the free library to free
95
+ software only, so we use the Lesser General Public License.
96
+
97
+ In other cases, permission to use a particular library in non-free
98
+ programs enables a greater number of people to use a large body of
99
+ free software. For example, permission to use the GNU C Library in
100
+ non-free programs enables many more people to use the whole GNU
101
+ operating system, as well as its variant, the GNU/Linux operating
102
+ system.
103
+
104
+ Although the Lesser General Public License is Less protective of the
105
+ users' freedom, it does ensure that the user of a program that is
106
+ linked with the Library has the freedom and the wherewithal to run
107
+ that program using a modified version of the Library.
108
+
109
+ The precise terms and conditions for copying, distribution and
110
+ modification follow. Pay close attention to the difference between a
111
+ "work based on the library" and a "work that uses the library". The
112
+ former contains code derived from the library, whereas the latter must
113
+ be combined with the library in order to run.
114
+
115
+ GNU LESSER GENERAL PUBLIC LICENSE
116
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
117
+
118
+ 0. This License Agreement applies to any software library or other
119
+ program which contains a notice placed by the copyright holder or
120
+ other authorized party saying it may be distributed under the terms of
121
+ this Lesser General Public License (also called "this License").
122
+ Each licensee is addressed as "you".
123
+
124
+ A "library" means a collection of software functions and/or data
125
+ prepared so as to be conveniently linked with application programs
126
+ (which use some of those functions and data) to form executables.
127
+
128
+ The "Library", below, refers to any such software library or work
129
+ which has been distributed under these terms. A "work based on the
130
+ Library" means either the Library or any derivative work under
131
+ copyright law: that is to say, a work containing the Library or a
132
+ portion of it, either verbatim or with modifications and/or translated
133
+ straightforwardly into another language. (Hereinafter, translation is
134
+ included without limitation in the term "modification".)
135
+
136
+ "Source code" for a work means the preferred form of the work for
137
+ making modifications to it. For a library, complete source code means
138
+ all the source code for all modules it contains, plus any associated
139
+ interface definition files, plus the scripts used to control compilation
140
+ and installation of the library.
141
+
142
+ Activities other than copying, distribution and modification are not
143
+ covered by this License; they are outside its scope. The act of
144
+ running a program using the Library is not restricted, and output from
145
+ such a program is covered only if its contents constitute a work based
146
+ on the Library (independent of the use of the Library in a tool for
147
+ writing it). Whether that is true depends on what the Library does
148
+ and what the program that uses the Library does.
149
+
150
+ 1. You may copy and distribute verbatim copies of the Library's
151
+ complete source code as you receive it, in any medium, provided that
152
+ you conspicuously and appropriately publish on each copy an
153
+ appropriate copyright notice and disclaimer of warranty; keep intact
154
+ all the notices that refer to this License and to the absence of any
155
+ warranty; and distribute a copy of this License along with the
156
+ Library.
157
+
158
+ You may charge a fee for the physical act of transferring a copy,
159
+ and you may at your option offer warranty protection in exchange for a
160
+ fee.
161
+
162
+ 2. You may modify your copy or copies of the Library or any portion
163
+ of it, thus forming a work based on the Library, and copy and
164
+ distribute such modifications or work under the terms of Section 1
165
+ above, provided that you also meet all of these conditions:
166
+
167
+ a) The modified work must itself be a software library.
168
+
169
+ b) You must cause the files modified to carry prominent notices
170
+ stating that you changed the files and the date of any change.
171
+
172
+ c) You must cause the whole of the work to be licensed at no
173
+ charge to all third parties under the terms of this License.
174
+
175
+ d) If a facility in the modified Library refers to a function or a
176
+ table of data to be supplied by an application program that uses
177
+ the facility, other than as an argument passed when the facility
178
+ is invoked, then you must make a good faith effort to ensure that,
179
+ in the event an application does not supply such function or
180
+ table, the facility still operates, and performs whatever part of
181
+ its purpose remains meaningful.
182
+
183
+ (For example, a function in a library to compute square roots has
184
+ a purpose that is entirely well-defined independent of the
185
+ application. Therefore, Subsection 2d requires that any
186
+ application-supplied function or table used by this function must
187
+ be optional: if the application does not supply it, the square
188
+ root function must still compute square roots.)
189
+
190
+ These requirements apply to the modified work as a whole. If
191
+ identifiable sections of that work are not derived from the Library,
192
+ and can be reasonably considered independent and separate works in
193
+ themselves, then this License, and its terms, do not apply to those
194
+ sections when you distribute them as separate works. But when you
195
+ distribute the same sections as part of a whole which is a work based
196
+ on the Library, the distribution of the whole must be on the terms of
197
+ this License, whose permissions for other licensees extend to the
198
+ entire whole, and thus to each and every part regardless of who wrote
199
+ it.
200
+
201
+ Thus, it is not the intent of this section to claim rights or contest
202
+ your rights to work written entirely by you; rather, the intent is to
203
+ exercise the right to control the distribution of derivative or
204
+ collective works based on the Library.
205
+
206
+ In addition, mere aggregation of another work not based on the Library
207
+ with the Library (or with a work based on the Library) on a volume of
208
+ a storage or distribution medium does not bring the other work under
209
+ the scope of this License.
210
+
211
+ 3. You may opt to apply the terms of the ordinary GNU General Public
212
+ License instead of this License to a given copy of the Library. To do
213
+ this, you must alter all the notices that refer to this License, so
214
+ that they refer to the ordinary GNU General Public License, version 2,
215
+ instead of to this License. (If a newer version than version 2 of the
216
+ ordinary GNU General Public License has appeared, then you can specify
217
+ that version instead if you wish.) Do not make any other change in
218
+ these notices.
219
+
220
+ Once this change is made in a given copy, it is irreversible for
221
+ that copy, so the ordinary GNU General Public License applies to all
222
+ subsequent copies and derivative works made from that copy.
223
+
224
+ This option is useful when you wish to copy part of the code of
225
+ the Library into a program that is not a library.
226
+
227
+ 4. You may copy and distribute the Library (or a portion or
228
+ derivative of it, under Section 2) in object code or executable form
229
+ under the terms of Sections 1 and 2 above provided that you accompany
230
+ it with the complete corresponding machine-readable source code, which
231
+ must be distributed under the terms of Sections 1 and 2 above on a
232
+ medium customarily used for software interchange.
233
+
234
+ If distribution of object code is made by offering access to copy
235
+ from a designated place, then offering equivalent access to copy the
236
+ source code from the same place satisfies the requirement to
237
+ distribute the source code, even though third parties are not
238
+ compelled to copy the source along with the object code.
239
+
240
+ 5. A program that contains no derivative of any portion of the
241
+ Library, but is designed to work with the Library by being compiled or
242
+ linked with it, is called a "work that uses the Library". Such a
243
+ work, in isolation, is not a derivative work of the Library, and
244
+ therefore falls outside the scope of this License.
245
+
246
+ However, linking a "work that uses the Library" with the Library
247
+ creates an executable that is a derivative of the Library (because it
248
+ contains portions of the Library), rather than a "work that uses the
249
+ library". The executable is therefore covered by this License.
250
+ Section 6 states terms for distribution of such executables.
251
+
252
+ When a "work that uses the Library" uses material from a header file
253
+ that is part of the Library, the object code for the work may be a
254
+ derivative work of the Library even though the source code is not.
255
+ Whether this is true is especially significant if the work can be
256
+ linked without the Library, or if the work is itself a library. The
257
+ threshold for this to be true is not precisely defined by law.
258
+
259
+ If such an object file uses only numerical parameters, data
260
+ structure layouts and accessors, and small macros and small inline
261
+ functions (ten lines or less in length), then the use of the object
262
+ file is unrestricted, regardless of whether it is legally a derivative
263
+ work. (Executables containing this object code plus portions of the
264
+ Library will still fall under Section 6.)
265
+
266
+ Otherwise, if the work is a derivative of the Library, you may
267
+ distribute the object code for the work under the terms of Section 6.
268
+ Any executables containing that work also fall under Section 6,
269
+ whether or not they are linked directly with the Library itself.
270
+
271
+ 6. As an exception to the Sections above, you may also combine or
272
+ link a "work that uses the Library" with the Library to produce a
273
+ work containing portions of the Library, and distribute that work
274
+ under terms of your choice, provided that the terms permit
275
+ modification of the work for the customer's own use and reverse
276
+ engineering for debugging such modifications.
277
+
278
+ You must give prominent notice with each copy of the work that the
279
+ Library is used in it and that the Library and its use are covered by
280
+ this License. You must supply a copy of this License. If the work
281
+ during execution displays copyright notices, you must include the
282
+ copyright notice for the Library among them, as well as a reference
283
+ directing the user to the copy of this License. Also, you must do one
284
+ of these things:
285
+
286
+ a) Accompany the work with the complete corresponding
287
+ machine-readable source code for the Library including whatever
288
+ changes were used in the work (which must be distributed under
289
+ Sections 1 and 2 above); and, if the work is an executable linked
290
+ with the Library, with the complete machine-readable "work that
291
+ uses the Library", as object code and/or source code, so that the
292
+ user can modify the Library and then relink to produce a modified
293
+ executable containing the modified Library. (It is understood
294
+ that the user who changes the contents of definitions files in the
295
+ Library will not necessarily be able to recompile the application
296
+ to use the modified definitions.)
297
+
298
+ b) Use a suitable shared library mechanism for linking with the
299
+ Library. A suitable mechanism is one that (1) uses at run time a
300
+ copy of the library already present on the user's computer system,
301
+ rather than copying library functions into the executable, and (2)
302
+ will operate properly with a modified version of the library, if
303
+ the user installs one, as long as the modified version is
304
+ interface-compatible with the version that the work was made with.
305
+
306
+ c) Accompany the work with a written offer, valid for at
307
+ least three years, to give the same user the materials
308
+ specified in Subsection 6a, above, for a charge no more
309
+ than the cost of performing this distribution.
310
+
311
+ d) If distribution of the work is made by offering access to copy
312
+ from a designated place, offer equivalent access to copy the above
313
+ specified materials from the same place.
314
+
315
+ e) Verify that the user has already received a copy of these
316
+ materials or that you have already sent this user a copy.
317
+
318
+ For an executable, the required form of the "work that uses the
319
+ Library" must include any data and utility programs needed for
320
+ reproducing the executable from it. However, as a special exception,
321
+ the materials to be distributed need not include anything that is
322
+ normally distributed (in either source or binary form) with the major
323
+ components (compiler, kernel, and so on) of the operating system on
324
+ which the executable runs, unless that component itself accompanies
325
+ the executable.
326
+
327
+ It may happen that this requirement contradicts the license
328
+ restrictions of other proprietary libraries that do not normally
329
+ accompany the operating system. Such a contradiction means you cannot
330
+ use both them and the Library together in an executable that you
331
+ distribute.
332
+
333
+ 7. You may place library facilities that are a work based on the
334
+ Library side-by-side in a single library together with other library
335
+ facilities not covered by this License, and distribute such a combined
336
+ library, provided that the separate distribution of the work based on
337
+ the Library and of the other library facilities is otherwise
338
+ permitted, and provided that you do these two things:
339
+
340
+ a) Accompany the combined library with a copy of the same work
341
+ based on the Library, uncombined with any other library
342
+ facilities. This must be distributed under the terms of the
343
+ Sections above.
344
+
345
+ b) Give prominent notice with the combined library of the fact
346
+ that part of it is a work based on the Library, and explaining
347
+ where to find the accompanying uncombined form of the same work.
348
+
349
+ 8. You may not copy, modify, sublicense, link with, or distribute
350
+ the Library except as expressly provided under this License. Any
351
+ attempt otherwise to copy, modify, sublicense, link with, or
352
+ distribute the Library is void, and will automatically terminate your
353
+ rights under this License. However, parties who have received copies,
354
+ or rights, from you under this License will not have their licenses
355
+ terminated so long as such parties remain in full compliance.
356
+
357
+ 9. You are not required to accept this License, since you have not
358
+ signed it. However, nothing else grants you permission to modify or
359
+ distribute the Library or its derivative works. These actions are
360
+ prohibited by law if you do not accept this License. Therefore, by
361
+ modifying or distributing the Library (or any work based on the
362
+ Library), you indicate your acceptance of this License to do so, and
363
+ all its terms and conditions for copying, distributing or modifying
364
+ the Library or works based on it.
365
+
366
+ 10. Each time you redistribute the Library (or any work based on the
367
+ Library), the recipient automatically receives a license from the
368
+ original licensor to copy, distribute, link with or modify the Library
369
+ subject to these terms and conditions. You may not impose any further
370
+ restrictions on the recipients' exercise of the rights granted herein.
371
+ You are not responsible for enforcing compliance by third parties with
372
+ this License.
373
+
374
+ 11. If, as a consequence of a court judgment or allegation of patent
375
+ infringement or for any other reason (not limited to patent issues),
376
+ conditions are imposed on you (whether by court order, agreement or
377
+ otherwise) that contradict the conditions of this License, they do not
378
+ excuse you from the conditions of this License. If you cannot
379
+ distribute so as to satisfy simultaneously your obligations under this
380
+ License and any other pertinent obligations, then as a consequence you
381
+ may not distribute the Library at all. For example, if a patent
382
+ license would not permit royalty-free redistribution of the Library by
383
+ all those who receive copies directly or indirectly through you, then
384
+ the only way you could satisfy both it and this License would be to
385
+ refrain entirely from distribution of the Library.
386
+
387
+ If any portion of this section is held invalid or unenforceable under any
388
+ particular circumstance, the balance of the section is intended to apply,
389
+ and the section as a whole is intended to apply in other circumstances.
390
+
391
+ It is not the purpose of this section to induce you to infringe any
392
+ patents or other property right claims or to contest validity of any
393
+ such claims; this section has the sole purpose of protecting the
394
+ integrity of the free software distribution system which is
395
+ implemented by public license practices. Many people have made
396
+ generous contributions to the wide range of software distributed
397
+ through that system in reliance on consistent application of that
398
+ system; it is up to the author/donor to decide if he or she is willing
399
+ to distribute software through any other system and a licensee cannot
400
+ impose that choice.
401
+
402
+ This section is intended to make thoroughly clear what is believed to
403
+ be a consequence of the rest of this License.
404
+
405
+ 12. If the distribution and/or use of the Library is restricted in
406
+ certain countries either by patents or by copyrighted interfaces, the
407
+ original copyright holder who places the Library under this License may add
408
+ an explicit geographical distribution limitation excluding those countries,
409
+ so that distribution is permitted only in or among countries not thus
410
+ excluded. In such case, this License incorporates the limitation as if
411
+ written in the body of this License.
412
+
413
+ 13. The Free Software Foundation may publish revised and/or new
414
+ versions of the Lesser General Public License from time to time.
415
+ Such new versions will be similar in spirit to the present version,
416
+ but may differ in detail to address new problems or concerns.
417
+
418
+ Each version is given a distinguishing version number. If the Library
419
+ specifies a version number of this License which applies to it and
420
+ "any later version", you have the option of following the terms and
421
+ conditions either of that version or of any later version published by
422
+ the Free Software Foundation. If the Library does not specify a
423
+ license version number, you may choose any version ever published by
424
+ the Free Software Foundation.
425
+
426
+ 14. If you wish to incorporate parts of the Library into other free
427
+ programs whose distribution conditions are incompatible with these,
428
+ write to the author to ask for permission. For software which is
429
+ copyrighted by the Free Software Foundation, write to the Free
430
+ Software Foundation; we sometimes make exceptions for this. Our
431
+ decision will be guided by the two goals of preserving the free status
432
+ of all derivatives of our free software and of promoting the sharing
433
+ and reuse of software generally.
434
+
435
+ NO WARRANTY
436
+
437
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
438
+ WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
439
+ EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
440
+ OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
441
+ KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
442
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
443
+ PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
444
+ LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
445
+ THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
446
+
447
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
448
+ WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
449
+ AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
450
+ FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
451
+ CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
452
+ LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
453
+ RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
454
+ FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
455
+ SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
456
+ DAMAGES.
457
+
458
+ END OF TERMS AND CONDITIONS
459
+
460
+ How to Apply These Terms to Your New Libraries
461
+
462
+ If you develop a new library, and you want it to be of the greatest
463
+ possible use to the public, we recommend making it free software that
464
+ everyone can redistribute and change. You can do so by permitting
465
+ redistribution under these terms (or, alternatively, under the terms of the
466
+ ordinary General Public License).
467
+
468
+ To apply these terms, attach the following notices to the library. It is
469
+ safest to attach them to the start of each source file to most effectively
470
+ convey the exclusion of warranty; and each file should have at least the
471
+ "copyright" line and a pointer to where the full notice is found.
472
+
473
+ <one line to give the library's name and a brief idea of what it does.>
474
+ Copyright (C) <year> <name of author>
475
+
476
+ This library is free software; you can redistribute it and/or
477
+ modify it under the terms of the GNU Lesser General Public
478
+ License as published by the Free Software Foundation; either
479
+ version 2.1 of the License, or (at your option) any later version.
480
+
481
+ This library is distributed in the hope that it will be useful,
482
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
483
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
484
+ Lesser General Public License for more details.
485
+
486
+ You should have received a copy of the GNU Lesser General Public
487
+ License along with this library; if not, write to the Free Software
488
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
489
+
490
+ Also add information on how to contact you by electronic and paper mail.
491
+
492
+ You should also get your employer (if you work as a programmer) or your
493
+ school, if any, to sign a "copyright disclaimer" for the library, if
494
+ necessary. Here is a sample; alter the names:
495
+
496
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
497
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
498
+
499
+ <signature of Ty Coon>, 1 April 1990
500
+ Ty Coon, President of Vice
501
+
502
+ That's all there is to it!
503
+
504
+
lib/iCalcreator-2.10/releaseNotes-2.10.txt ADDED
@@ -0,0 +1,82 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 2.8.1 ######################
2
+ calendar property VERSION always first
3
+
4
+ 2.8.2 ###################### / thanks Alvin and Jorge L P
5
+ function parse on calendar and component level
6
+ updated management of line folding
7
+
8
+ 2.8.3 ######################
9
+ updated using.html, datetime parameter tz
10
+
11
+ 2.8.4 ######################
12
+ updated function sort
13
+ allow sorting on Attendee, Categories, DTSTAMP, Location, Organizer, Priority, Resources, Status, Summary
14
+
15
+ 2.8.5 ######################
16
+ function SelectComponents
17
+ allow select of calendar component properties,
18
+ function argument array( <propertyName> => <propertyValue>)
19
+ propertyName = 'Attendee'/'Categories'/'Location'/'Organizer'/'Priority'/'Resources'/'Status'/'Summary'/'UID'
20
+ propertyValue = (string) propertyValue / (array) ( propertyValue *[, propertyValue] )
21
+
22
+ 2.8.6 ######################
23
+ function getProperty on calendar level
24
+ new arguments: 'DTSTART', 'Attendee', 'Categories', 'Location', 'Organizer', 'Priority', 'Resources', 'Status', 'Summary', 'UID' or 'Recurrence-id-uid'
25
+ Returns unique property values+counts from all calendar components,
26
+ output format: array(*[<uniquePropertyValue> => occurr_cnt])
27
+
28
+ 2.8.7 ######################
29
+ bug in function iCalUtilityFunctions::_duration2date fixed
30
+
31
+ 2.8.8 ######################
32
+ updated functions getProperty and deleteProperty
33
+ management of properties with multiple ocurrence
34
+
35
+ 2.8.9 ###################### / thanks Jorge L P
36
+ bug in function SelectComponents
37
+ regarding X-CURRENT-*-values
38
+
39
+ 2.8.10 ######################
40
+ bug in function setFreebusy
41
+ if property is empty.. .
42
+
43
+ 2.9.1 ######################
44
+ consecutive calls with UID as argument,
45
+ function (calendar) getComponent
46
+ new argument, array( *[propertyName => propertyValue] )
47
+
48
+ 2.9.2 ######################
49
+ Simple create of timezone (including standard/daylight) component
50
+ New function in iCalUtilityFunctions:createTimezone (, offsetSec2His)
51
+
52
+ 2.9.3 ###################### / thanks Jorge L P
53
+ Management of properties with numeric (integer) content,
54
+ PERCENT-COMPLETE, PRIORITY, REPEAT, SEQUENCE, X-PROP
55
+ uppdate of get- and setfunctions
56
+
57
+ 2.9.4 ###################### / thanks Jorge L P
58
+ update of function parse on calendar level
59
+
60
+ 2.9.5 ######################
61
+ update of function parse on calendar and component level level
62
+ set config when creating new component
63
+
64
+ 2.9.6 ######################
65
+ auto completion of (default) timezone when setting DTEND, DTSTART, DUE, RECURRENCE-ID
66
+ update of setfunctions for DTEND, DTSTART, DUE, RECURRENCE-ID
67
+ update of getConfig and all config setting on calendar and component level
68
+
69
+ 2.9.7 ###################### / thanks Dan
70
+ bug in function selectComponents - sourceforge ID: 3307044
71
+
72
+ 2.9.8 ###################### / thanks Jorge L P
73
+ bug in function createAttendee
74
+
75
+ 2.9.9 ###################### / thanks Jorge L P
76
+ bug in iCalUtilityFunctions:_format_duration, TRIGGER with no duration
77
+
78
+ 2.9.10 ###################### / thanks Andrew
79
+ Bug in iCalUtilityFunctions::_recur2date (, _setRexrule), BYSETPOS
80
+
81
+ 2.9.12 ###################### / thanks Joc
82
+ function returnCalendar, new arguments for utf8 encoding and gzencode
lib/iCalcreator-2.10/summary.html ADDED
@@ -0,0 +1,283 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"
2
+ "http://www.w3.org/TR/html4/frameset.dtd">
3
+ <html>
4
+ <head>
5
+ <title>iCalcreator 2.10 summary</title>
6
+ <meta name="author" content="Kjell-Inge Gustafsson - kigkonsult" />
7
+ <meta name="copyright" content="2007-2011 Kjell-Inge Gustafsson - kigkonsult" />
8
+ <meta name="keywords" content="ical, calendar, calender, xcal, xml, icalender, rfc2445, vcalender, php, create" />
9
+ <meta name="description" content="iCalcreator" />
10
+ <style type="text/css">
11
+ body {
12
+ FONT-FAMILY : "Lucida Grande","Lucida Sans Unicode", "Bitstream Vera Sans", Lucida, Arial, Geneva, Helvetica, sans-serif;
13
+ FONT-SIZE : small;
14
+ MARGIN : 10px;
15
+ WIDTH : 800px;
16
+ }
17
+ h1 {
18
+ FONT-FAMILY : "Lucida Grande","Lucida Sans Unicode", "Bitstream Vera Sans", Lucida, Arial, Geneva, Helvetica, sans-serif;
19
+ FONT-SIZE : large;
20
+ }
21
+ h2 {
22
+ FONT-FAMILY : "Lucida Grande","Lucida Sans Unicode", "Bitstream Vera Sans", Lucida, Arial, Geneva, Helvetica, sans-serif;
23
+ FONT-SIZE : large;
24
+ }
25
+ h4 {
26
+ FONT-FAMILY : "Lucida Grande","Lucida Sans Unicode", "Bitstream Vera Sans", Lucida, Arial, Geneva, Helvetica, sans-serif;
27
+ FONT-SIZE : small;
28
+ FONT-WEIGHT : bold;
29
+ }
30
+ .code {
31
+ FONT-FAMILY : monospace;
32
+ FONT-SIZE : medium;
33
+ WHITE-SPACE : pre;
34
+ }
35
+ .comment {
36
+ FONT-FAMILY : arial;
37
+ FONT-SIZE : small;
38
+ FONT-STYLE : italic;
39
+ }
40
+ </style>
41
+ </head>
42
+ <body>
43
+ <h1>iCalcreator 2.10</h1>
44
+ iCalcreator class v2.10<br />
45
+ copyright (c) 2007-2011 Kjell-Inge Gustafsson, kigkonsult<br />
46
+ <a href="http://www.kigkonsult.se/iCalcreator/index.php" title="www.kigkonsult.se/iCalcreator" target="_blank">www.kigkonsult.se/iCalcreator</a><br />
47
+ ical@kigkonsult.se<br />
48
+ <br />
49
+ iCalcreator is a PHP class managing iCal formatted files for non-calendar
50
+ systems like CMS, project management systems and other applications able
51
+ to process calendar information like agendas, tasks, reports, totos,
52
+ journaling data and for communication with calendar systems and applications.
53
+ <br /><br />
54
+ This is a <b>short summary</b> how to use iCalcreator; create, parse, edit, select and output functionality.
55
+ <br /><br />
56
+ iCalcreator is built of a class file with support of a function class file and are calendar component property oriented.
57
+ Development environment is PHP version 5.x but coding is done to meet 4.x backward compatibility and may work.
58
+ <h4>iCal</h4>
59
+ A short iCal description is found at <a href="http://en.wikipedia.org/wiki/ICalendar#Core_object" title="iCalendar From Wikipedia, the free encyclopedia" target="_blank">Wikipedia</a>. If You are not familiar with iCal, read this first!<br />
60
+ Knowledge of calendar protocol rfc2445/rfc2446 is to recommend;<br />
61
+ <a href="http://www.kigkonsult.se/downloads/dl.php?f=rfc2445" title="RFC2445" target="_blank">rfc2445</a>
62
+ - Internet Calendaring and Scheduling Core Object Specification (iCalendar)<br />
63
+ <a href="http://www.kigkonsult.se/downloads/dl.php?f=rfc2446" title="RFC2446" target="_blank">rfc2446</a>
64
+ - iCalendar Transport-Independent Interoperability Protocol (iTIP) Scheduling Events, BusyTime, To-dos and Journal Entries <br />
65
+ All functions calls are made as simple as possible BUT (, !!!,) read these rfc's properly!<br />
66
+ <h4>Downloads</h4>
67
+ Download
68
+ <a href="http://www.kigkonsult.se/downloads/index.php#iCalcreator" title="iCalcreator complete manual" target="_blank"><b>complete manual</b></a>
69
+ and
70
+ <a href="http://www.kigkonsult.se/downloads/index.php#iCalcreator" title="iCalcreator coding samples" target="_blank"><b>coding samples</b></a>.
71
+ from <a href="http://www.kigkonsult.se/iCalcreator/index.php" title="iCalcreator" target="_blank">www.kigkonsult.se/iCalcreator</a>.
72
+ <h4>INSTALL</h4>
73
+ Unpack to any folder<br />
74
+ - add this folder to your include-path<br />
75
+ - or unpack to your application-(include)-folder<br />
76
+ Add &quot;require_once [folder/]iCalcreator.class.php;&quot; to your php-script.
77
+ <br />
78
+ <br />
79
+ If using php version 5.1 or higher, the default timezone need to be set/altered, now &quot;Europe/Stockholm&quot;,
80
+ line 52 in the iCalcreator.class.php file.
81
+ <br />
82
+ When creating a new calendar/component instance, review config settings.
83
+
84
+ <h2>CREATE</h2>
85
+
86
+ <p class="code">require_once( &quot;iCalcreator.class.php&quot; );
87
+ $config = array( &quot;unique_id&quot; =&gt; &quot;icaldomain.com&quot; ); // <span class="comment">set Your unique id</span>
88
+ $v = new vcalendar( $config ); // <span class="comment">create a new calendar instance</span>
89
+
90
+ $v->setProperty( &quot;method&quot;, &quot;PUBLISH&quot; ); // <span class="comment">required of some calendar software</span>
91
+ $v->setProperty( &quot;x-wr-calname&quot;, &quot;Calendar Sample&quot; ); // <span class="comment">required of some calendar software</span>
92
+ $v->setProperty( &quot;X-WR-CALDESC&quot;, &quot;Calendar Description&quot; ); // <span class="comment">required of some calendar software</span>
93
+ $tz = &quot;Europe/Stockholm&quot;;
94
+ $v->setProperty( &quot;X-WR-TIMEZONE&quot;, $tz ); // <span class="comment">required of some calendar software</span>
95
+ .. .
96
+ iCalUtilityFunctions::createTimezone( $v, $tz ) // <span class="comment">creates (very simple) timezone component(-s)</span>
97
+ .. .
98
+ $vevent = & $v->newComponent( &quot;vevent&quot; ); // <span class="comment">create an event calendar component</span>
99
+ $vevent->setProperty( &quot;dtstart&quot;, array( &quot;year&quot;=&gt;2007, &quot;month&quot;=&gt;4, &quot;day&quot;=&gt;1, &quot;hour&quot;=&gt;19, &quot;min&quot;=&gt;0, &quot;sec&quot;=&gt;0 ));
100
+ $vevent->setProperty( &quot;dtend&quot;, array( &quot;year&quot;=&gt;2007, &quot;month&quot;=&gt;4, &quot;day&quot;=&gt;1, &quot;hour&quot;=&gt;22, &quot;min&quot;=&gt;30, &quot;sec&quot;=&gt;0 ));
101
+ $vevent->setProperty( &quot;LOCATION&quot;, &quot;Central Placa&quot; ); // <span class="comment">property name - case independent</span>
102
+ $vevent->setProperty( &quot;summary&quot;, &quot;PHP summit&quot; );
103
+ $vevent->setProperty( &quot;description&quot;, &quot;This is a description&quot; );
104
+ $vevent->setProperty( &quot;comment&quot;, &quot;This is a comment&quot; );
105
+ $vevent->setProperty( &quot;attendee&quot;, &quot;attendee1@icaldomain.net&quot; );
106
+ .. .
107
+ $vevent = & $v->newComponent( &quot;vevent&quot; ); // <span class="comment">create next event calendar component</span>
108
+ $vevent->setProperty( &quot;dtstart&quot;, &quot;20070401&quot;, array(&quot;VALUE&quot; =&gt; &quot;DATE&quot;));// <span class="comment">alt. date format, now for an all-day event</span>
109
+ $vevent->setProperty( &quot;organizer&quot; , &quot;boss@icaldomain.com&quot; );
110
+ $vevent->setProperty( &quot;summary&quot;, &quot;ALL-DAY event&quot; );
111
+ $vevent->setProperty( &quot;description&quot;, &quot;This is a description for an all-day event&quot; );
112
+ $vevent->setProperty( &quot;resources&quot;, &quot;COMPUTER PROJECTOR&quot; );
113
+ $vevent->setProperty( &quot;rrule&quot;, array( &quot;FREQ&quot; =&gt; &quot;WEEKLY&quot;, &quot;count&quot; =&gt; 4));// <span class="comment">weekly, four occasions</span>
114
+ $vevent->parse( &quot;LOCATION:1CP Conference Room 4350&quot; ); // <span class="comment">supporting parse of strict rfc2445 formatted text</span>
115
+ .. .
116
+ .. .// <span class="comment">all calendar components are described in <a href="http://www.kigkonsult.se/downloads/dl.php?f=rfc2445" title="RFC2445" target="_blank">rfc2445</a></span>
117
+ .. .// <span class="comment">a complete iCalcreator function list (ex. setProperty) in <a href="http://www.kigkonsult.se/downloads/index.php#iCalcreator" title="iCalcreator complete manual" target="_blank">iCalcreator manual</a></span>
118
+ .. .
119
+ $v->returnCalendar(); // <span class="comment">redirect calendar file to browser</span>
120
+ </p>
121
+ <h2>PARSE</h2>
122
+ <p class="code">require_once( &quot;iCalcreator.class.php&quot; );
123
+ $config = array( &quot;unique_id&quot; =&gt; &quot;icaldomain.com&quot; ); // <span class="comment">set Your unique id, required if any component UID is missing</span>
124
+ $v = new vcalendar( $config ); // <span class="comment">create a new calendar instance</span>
125
+
126
+ /* start parse of local file */
127
+ $config = array( &quot;directory&quot; =&gt; &quot;calendar&quot;, &quot;filename&quot; =&gt; &quot;file.ics&quot; );
128
+ $v->setConfig( $config ); // <span class="comment">set directory and file name</span>
129
+ $v->parse();
130
+
131
+ /* start parse of remote file */
132
+ $v->setConfig( &quot;url&quot;, &quot;http://www.aDomain.net/file.ics&quot; ); // <span class="comment">iCalcreator also support parse from or write to remote files</span>
133
+ $v->parse();
134
+
135
+ $v->setProperty( &quot;method&quot;, &quot;PUBLISH&quot; ); // <span class="comment">required of some calendar software</span>
136
+ $v->setProperty( &quot;x-wr-calname&quot;, &quot;Calendar Sample&quot; ); // <span class="comment">required of some calendar software</span>
137
+ $v->setProperty( &quot;X-WR-CALDESC&quot;, &quot;Calendar Description&quot; ); // <span class="comment">required of some calendar software</span>
138
+ $v->setProperty( &quot;X-WR-TIMEZONE&quot;, &quot;Europe/Stockholm&quot; ); // <span class="comment">required of some calendar software</span>
139
+
140
+ .. .
141
+ $v->sort(); // <span class="comment">ensure start date order</span>
142
+ .. .
143
+ </p>
144
+ <h2>EDIT</h2>
145
+ <p class="code">require_once( &quot;iCalcreator.class.php&quot; );
146
+ $config = array( &quot;unique_id&quot; =&gt; &quot;icaldomain.com&quot;, &quot;directory&quot; =&gt; &quot;calendar&quot;, &quot;filename&quot; =&gt; &quot;file.ics&quot; );
147
+ // <span class="comment">set Your unique id, import directory and file name</span>
148
+ $v = new vcalendar( $config ); // <span class="comment">create a new calendar instance</span>
149
+
150
+ $v->parse();
151
+
152
+ $v->setProperty( &quot;method&quot;, &quot;PUBLISH&quot; ); // <span class="comment">required of some calendar software</span>
153
+ $v->setProperty( &quot;x-wr-calname&quot;, &quot;Calendar Sample&quot; ); // <span class="comment">required of some calendar software</span>
154
+ $v->setProperty( &quot;X-WR-CALDESC&quot;, &quot;Calendar Description&quot; ); // <span class="comment">required of some calendar software</span>
155
+ $v->setProperty( &quot;X-WR-TIMEZONE&quot;, &quot;Europe/Stockholm&quot; ); // <span class="comment">required of some calendar software</span>
156
+
157
+ while( $vevent = $v->getComponent( &quot;vevent&quot; )) { // <span class="comment">read events, one by one</span>
158
+ $uid = $vevent->getProperty( &quot;uid&quot; ); // <span class="comment">uid required, one occurence (unique id/key for component)</span>
159
+ .. .
160
+ $dtstart = $vevent->getProperty( &quot;dtstart&quot; ); // <span class="comment">dtstart required, one occurence</span>
161
+ .. .
162
+ if( $description = $vevent->getProperty( &quot;description&quot;, 1 )) { // <span class="comment">description optional, first occurence</span>
163
+ .. . // <span class="comment">edit the description</span>
164
+ $vevent->setProperty( &quot;description&quot;, $description, FALSE, 1 ); // <span class="comment">update/replace the description</span>
165
+ }
166
+ while( $comment = $vevent->getProperty( &quot;comment&quot; )) { // <span class="comment">comment optional, may occur more than once </span>
167
+ .. . // <span class="comment">manage comments</span>
168
+ }
169
+ .. .
170
+ while( $vevent->deleteProperty( &quot;attendee&quot; ))
171
+ continue; // <span class="comment">remove all ATTENDEE properties .. .</span>
172
+ .. .
173
+ $v->setComponent ( $vevent, $uid ); // <span class="comment">update/replace event in calendar with <b>uid</b> as key </span>
174
+ }
175
+ .. .
176
+ .. .// <span class="comment">a complete iCalcreator function list (ex. getProperty, deleteProperty) in <a href="http://www.kigkonsult.se/downloads/index.php" title="iCalcreator complete manual" target="_blank">iCalcreator manual</a></span>
177
+ .. .
178
+ </p>
179
+ <h2>SELECT</h2>
180
+ <p class="code">require_once( &quot;iCalcreator.class.php&quot; );
181
+ $config = array( &quot;unique_id&quot; =&gt; &quot;icaldomain.com&quot; ); // <span class="comment">set Your unique id</span>
182
+ $v = new vcalendar( $config ); // <span class="comment">create a new calendar instance</span>
183
+
184
+ $v->setConfig( &quot;url&quot;, &quot;http://www.aDomain.net/file.ics&quot; ); // <span class="comment">iCalcreator also support remote files</span>
185
+ $v->parse();
186
+ $v->sort(); // <span class="comment">ensure start date order</span>
187
+
188
+ $v->setProperty( &quot;method&quot;, &quot;PUBLISH&quot; ); // <span class="comment">required of some calendar software</span>
189
+ $v->setProperty( &quot;x-wr-calname&quot;, &quot;Calendar Sample&quot; ); // <span class="comment">required of some calendar software</span>
190
+ $v->setProperty( &quot;X-WR-CALDESC&quot;, &quot;Calendar Description&quot; ); // <span class="comment">required of some calendar software</span>
191
+ $v->setProperty( &quot;X-WR-TIMEZONE&quot;, &quot;Europe/Stockholm&quot; ); // <span class="comment">required of some calendar software</span>
192
+
193
+ $eventArray = $v->selectComponents(); // <span class="comment">select components occuring <b>today</b></span>
194
+ // <span class="comment">(including components with recurrence pattern)</span>
195
+ foreach( $eventArray as $year =&gt; $yearArray) {
196
+ foreach( $yearArray as $month =&gt; $monthArray ) {
197
+ foreach( $monthArray as $day =&gt; $dailyEventsArray ) {
198
+ foreach( $dailyEventsArray as $vevent ) {
199
+ $currddate = $event->getProperty( &quot;x-current-dtstart&quot; );
200
+ // <span class="comment">if member of a recurrence set (2nd occurence etc)</span>
201
+ // <span class="comment">returns array( &quot;x-current-dtstart&quot;</span>
202
+ // <span class="comment"> , &lt;(string) date(&quot;Y-m-d [H:i:s][timezone/UTC offset]&quot;)&gt;)</span>
203
+ $dtstart = $vevent->getProperty( &quot;dtstart&quot; ); // <span class="comment">dtstart required, one occurence, (orig. start date)</span>
204
+ $summary = $vevent->getProperty( &quot;summary&quot; );
205
+ $description = $vevent->getProperty( &quot;description&quot; );
206
+ .. .
207
+ .. .
208
+ }
209
+ }
210
+ }
211
+ }
212
+
213
+ $valueOcurr = $v->getProperty( &quot;CATEGORIES&quot; ); // <span class="comment">fetch specific property (unique) values and number of ocurrencies</span>
214
+ // <span class="comment">ATTENDEE, CATEGORIES, DTSTART, LOCATION, ORGANIZER, PRIORITY, RESOURCES, STATUS, SUMMARY, UID</span>
215
+ foreach( $valueOcurr as $uniqueValue =&gt; $ocurr ) {
216
+ .. .
217
+ }
218
+
219
+ $selectSpec = array( &quot;CATEGORIES&quot; =&gt; &quot;course1&quot; );
220
+ $specComps = $v->selectComponents( $selectSpec ); // <span class="comment">selects components based on specific property value(-s)</span>
221
+ // <span class="comment">ATTENDEE, CATEGORIES, LOCATION, ORGANIZER, PRIORITY, RESOURCES, STATUS, SUMMARY, UID</span>
222
+ foreach( $specComps as $comp ) {
223
+ .. .
224
+ }
225
+ </p>
226
+ <h2>OUTPUT</h2>
227
+ <p class="code">require_once( &quot;iCalcreator.class.php&quot; );
228
+ $config = array( &quot;unique_id&quot; =&gt; &quot;icaldomain.com&quot; ); // <span class="comment">set Your unique id</span>
229
+ $v = new vcalendar( $config ); // <span class="comment">create a new calendar instance</span>
230
+
231
+ $v->setProperty( &quot;method&quot;, &quot;PUBLISH&quot; ); // <span class="comment">required of some calendar software</span>
232
+ $v->setProperty( &quot;x-wr-calname&quot;, &quot;Calendar Sample&quot; ); // <span class="comment">required of some calendar software</span>
233
+ $v->setProperty( &quot;X-WR-CALDESC&quot;, &quot;Calendar Description&quot; ); // <span class="comment">required of some calendar software</span>
234
+ $v->setProperty( &quot;X-WR-TIMEZONE&quot;, &quot;Europe/Stockholm&quot; ); // <span class="comment">required of some calendar software</span>
235
+ .. .
236
+ .. .// <span class="comment">parse calendar file(s) and/or edit/create calendar components.. .</span>
237
+ .. .
238
+ </p>
239
+ <h4> // opt 1</h4>
240
+ <p class="code">.. .
241
+ $v->returnCalendar(); // <span class="comment">redirect calendar file to browser</span>
242
+ </p>
243
+ <h4> // opt 2</h4>
244
+ <p class="code">.. .
245
+ $config = array( &quot;directory&quot; =&gt; &quot;depot&quot;, &quot;filename&quot; =&gt; &quot;calendar.ics&quot; );
246
+ $v->setConfig( $config ); // <span class="comment">set output directory and file name</span>
247
+ $v->saveCalendar(); // <span class="comment">save calendar to (local) file</span>
248
+ </p>
249
+ <h4> // opt 3</h4>
250
+ <p class="code">.. .
251
+ $config = array( &quot;url&quot; =&gt; &quot;http://www.aDomain.net/file.ics&quot; );
252
+ $v->setConfig( $config ); // <span class="comment">set output url</span>
253
+ $v->saveCalendar(); // <span class="comment">save calendar to remote url</span>
254
+ </p>
255
+
256
+ <h2>COPYRIGHT AND LICENSE</h2>
257
+
258
+ <h4>Copyright</h4>
259
+ iCalcreator class<br />
260
+ copyright (c) 2007-2011 Kjell-Inge Gustafsson, kigkonsult<br />
261
+ <a href="http://www.kigkonsult.se/iCalcreator/index.php" title="www.kigkonsult.se/iCalcreator" target="_blank">www.kigkonsult.se/iCalcreator</a><br />
262
+ ical@kigkonsult.se<br />
263
+
264
+ <h4>License</h4>
265
+
266
+ This library is free software; you can redistribute it and/or
267
+ modify it under the terms of the GNU Lesser General Public
268
+ License as published by the Free Software Foundation; either
269
+ version 2.1 of the License, or (at your option) any later version.
270
+ <br /><br />
271
+ This library is distributed in the hope that it will be useful,
272
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
273
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
274
+ Lesser General Public License for more details.
275
+ <br /><br />
276
+ You should have received a copy of the GNU Lesser General Public
277
+ License along with this library; if not, write to the Free Software
278
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
279
+ or download it <a href="http://www.kigkonsult.se/downloads/dl.php?f=LGPL" target="_blank">here</a>.
280
+ <br />
281
+ <br />
282
+ </body>
283
+ </html>
lib/iCalcreator-2.10/using.html ADDED
@@ -0,0 +1,5683 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN"
2
+ "http://www.w3.org/TR/html4/frameset.dtd">
3
+ <html>
4
+ <head>
5
+ <title>iCalcreator 2.10 manual</title>
6
+ <meta name="author" content="Kjell-Inge Gustafsson - kigkonsult" />
7
+ <meta name="copyright" content="2007-2011 Kjell-Inge Gustafsson - kigkonsult" />
8
+ <meta name="keywords" content="ical, calendar, calender, xcal, xml, icalender, rfc2445, vcalender, php, create" />
9
+ <meta name="description" content="iCalcreator" />
10
+ <style type="text/css">
11
+ * {
12
+ BACKGROUND-COLOR: white;
13
+ COLOR : black;
14
+ }
15
+ a {
16
+ FONT-FAMILY : "Lucida Grande","Lucida Sans Unicode", "Bitstream Vera Sans", Lucida, Arial, Geneva, Helvetica, sans-serif;
17
+ FONT-SIZE : small;
18
+ }
19
+ a.ref {
20
+ background-color: transparent;
21
+ FONT-FAMILY : monospace, arial;
22
+ FONT-SIZE : small;
23
+ FONT-STYLE : normal;
24
+ TEXT-DECORATION : none;
25
+ }
26
+ body {
27
+ FONT-FAMILY : "Lucida Grande","Lucida Sans Unicode", "Bitstream Vera Sans", Lucida, Arial, Geneva, Helvetica, sans-serif;
28
+ FONT-SIZE : small;
29
+ MARGIN-LEFT : 10px;
30
+ WIDTH : 600px;
31
+ }
32
+ h1 {
33
+ BACKGROUND-COLOR: silver;
34
+ BORDER : thin solid black;
35
+ FONT-FAMILY : "Lucida Grande","Lucida Sans Unicode", "Bitstream Vera Sans", Lucida, Arial, Geneva, Helvetica, sans-serif;
36
+ FONT-SIZE : x-large;
37
+ FONT-WEIGHT : bold;
38
+ DISPLAY : block;
39
+ }
40
+ h2 {
41
+ FONT-FAMILY : "Lucida Grande","Lucida Sans Unicode", "Bitstream Vera Sans", Lucida, Arial, Geneva, Helvetica, sans-serif;
42
+ FONT-SIZE : large;
43
+ }
44
+ h3 {
45
+ FONT-FAMILY : "Lucida Grande","Lucida Sans Unicode", "Bitstream Vera Sans", Lucida, Arial, Geneva, Helvetica, sans-serif;
46
+ FONT-SIZE : medium;
47
+ }
48
+ h4 {
49
+ FONT-FAMILY : "Lucida Grande","Lucida Sans Unicode", "Bitstream Vera Sans", Lucida, Arial, Geneva, Helvetica, sans-serif;
50
+ FONT-SIZE : small;
51
+ FONT-WEIGHT : bold;
52
+ }
53
+ h5 {
54
+ FONT-FAMILY : "Lucida Grande","Lucida Sans Unicode", "Bitstream Vera Sans", Lucida, Arial, Geneva, Helvetica, sans-serif;
55
+ FONT-SIZE : small;
56
+ FONT-WEIGHT : normal;
57
+ TEXT-DECORATION : underline;
58
+ }
59
+ p {
60
+ FONT-FAMILY : "Lucida Grande","Lucida Sans Unicode", "Bitstream Vera Sans", Lucida, Arial, Geneva, Helvetica, sans-serif;
61
+ FONT-SIZE : small;
62
+ }
63
+ .bb {
64
+ BORDER-BOTTOM : gray dotted thin;
65
+ }
66
+ .blb {
67
+ BORDER-LEFT : gray dotted thin;
68
+ BORDER-BOTTOM : gray dotted thin;
69
+ TEXT-ALIGN : center;
70
+ }
71
+ .bl {
72
+ BORDER-LEFT : gray dotted thin;
73
+ }
74
+ .center {
75
+ TEXT-ALIGN : center;
76
+ }
77
+ .comment {
78
+ background-color: transparent;
79
+ FONT-FAMILY : monospace;
80
+ FONT-SIZE : medium;
81
+ FONT-STYLE : italic;
82
+ FONT-WEIGHT : 300;
83
+ xLETTER-SPACING : 0.1em;
84
+ WHITE-SPACE : pre;
85
+ }
86
+ .example {
87
+ background-color: #DCDCDC;
88
+ FONT-FAMILY : Courier, "Courier New";
89
+ FONT-SIZE : small;
90
+ FONT-WEIGHT : 500;
91
+ LINE-HEIGHT : 1.2em;
92
+ WHITE-SPACE : pre;
93
+ }
94
+ .format {
95
+ BORDER : gray dotted thin;
96
+ FONT-FAMILY : Courier, "Courier New";
97
+ FONT-SIZE : small;
98
+ FONT-WEIGHT : 500;
99
+ LINE-HEIGHT : 1.5em;
100
+ WHITE-SPACE : pre;
101
+ }
102
+ .header {
103
+ BACKGROUND-COLOR: silver;
104
+ BORDER : thin solid black;
105
+ FONT-FAMILY : "Lucida Grande","Lucida Sans Unicode", "Bitstream Vera Sans", Lucida, Arial, Geneva, Helvetica, sans-serif;
106
+ FONT-SIZE : xx-large;
107
+ WIDTH : 600px;
108
+ }
109
+ .label {
110
+ FONT-FAMILY : arial;
111
+ FONT-SIZE : small;
112
+ FONT-WEIGHT : bold;
113
+ LETTER-SPACING : 0.1em;
114
+ }
115
+ .quotes {
116
+ background-color: transparent;
117
+ FONT-FAMILY : arial;
118
+ FONT-SIZE : small;
119
+ FONT-STYLE : italic;
120
+ FONT-WEIGHT : 300;
121
+ LETTER-SPACING : 0.1em;
122
+ WHITE-SPACE : pre;
123
+ }
124
+ .ref {
125
+ BACKGROUND-COLOR: transparent;
126
+ FONT-FAMILY : monospace, arial;
127
+ FONT-SIZE : x-small;
128
+ xFONT-STYLE : italic;
129
+ xFONT-WEIGHT : 600;
130
+ VERTICAL-ALIGN : top;
131
+ LETTER-SPACING : 0.2em;
132
+ }
133
+ .top {
134
+ VERTICAL-ALIGN : top;
135
+ }
136
+ </style>
137
+ </head>
138
+ <body>
139
+ <a name="top"></a>
140
+ <p class="header">iCalcreator 2.10</p>
141
+ iCalcreator class v2.10<br />
142
+ copyright (c) 2007-2011 Kjell-Inge Gustafsson, kigkonsult<br />
143
+ <a href="http://www.kigkonsult.se/iCalcreator/index.php" title="www.kigkonsult.Se/iCalcreator" target="_blank">www.kigkonsult.Se/iCalcreator</a><br />
144
+ ical@kigkonsult.se<br />
145
+
146
+ <h2>Description:</h2>
147
+ iCalcreator is a PHP implementation of RFC2445/RFC2446 to manage iCal/xCal formatted files.
148
+ <br />
149
+
150
+ <a name="INTRO"></a><h1>1. INTRO</h1>
151
+ <p>
152
+ iCalcreator is a PHP class managing iCal formatted files for non-calendar
153
+ systems like CMS, project management systems and other applications able
154
+ to process calendar information like agendas, tasks, reports, todos,
155
+ journalling data and for communication with calendar systems and applications.
156
+ </p>
157
+ <p>
158
+ iCalcreator features create, parse, edit and select calendar and calendar components.
159
+ </p>
160
+ <p>
161
+ iCalcreator is built of a class file with support of a function class file and are calendar
162
+ component property oriented. Development environment is PHP version 5.x but coding is done
163
+ to meet 4.x backward compatibility and may work.
164
+ </p>
165
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a>
166
+
167
+ <a name="iCal"></a><h2>1.1 Ical</h2>
168
+
169
+ The iCalendar format, as described in <a href="http://www.kigkonsult.se/downloads/dl.php?f=rfc2445" title="Download RFC2445 in text format">rfc2445</a>
170
+ (and <a href="http://www.kigkonsult.se/downloads/dl.php?f=rfc2446" title="Download RFC2446 in text format">rfc2446</a>)
171
+ <p class="quotes">allows for the capture and exchange of information normally stored within a<br />calendaring and scheduling application</p>
172
+ and <p class="quotes">is an exchange format between applications or systems.</p>
173
+
174
+ <p>
175
+ A short iCal description is found at <a href="http://en.wikipedia.org/wiki/ICalendar#Core_object" title="iCalendar From Wikipedia, the free encyclopedia">Wikipedia</a>. If You are not familiar with iCal, read this first!<br />
176
+ Knowledge of calendar protocol rfc2445/rfc2446 is to recommend.
177
+ </p>
178
+ <p>
179
+ <a href="http://www.kigkonsult.se/downloads/dl.php?f=rfc2445" title="Download RFC2445 in text format">rfc2445</a>
180
+ - Internet Calendaring and Scheduling Core Object Specification (iCalendar),
181
+ <br />
182
+ download <a href="http://www.kigkonsult.se/downloads/dl.php?f=rfc2445" title="Download RFC2445 in text format">here</a>
183
+ or examine <a href="http://www.kigkonsult.se/iCalcreator/iCalDictionary/index.html" title="view online" target="_blank">online</a>.
184
+ </p>
185
+ <p>
186
+ <a href="http://www.kigkonsult.se/downloads/dl.php?f=rfc2446" title="Download RFC2446 in text format">rfc2446</a>
187
+ - iCalendar Transport-Independent Interoperability Protocol (iTIP) Scheduling Events, BusyTime, To-dos and Journal Entries,
188
+ download <a href="http://www.kigkonsult.se/downloads/dl.php?f=rfc2446" title="Download RFC2446 in text format">here</a>.
189
+ </p>
190
+ <p>
191
+ All iCalcreator functions calls are made as simple as possible BUT (, !!!,) read these rfc's properly!
192
+ xCal (iCal xml) output format is supported but still experimental.
193
+ </p>
194
+ <br />
195
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a>
196
+
197
+ <a name="This_manual"></a><h2>1.2 This manual</h2>
198
+ This style is used for text.
199
+ <p class="format">This style is used for formats.</p>
200
+ <p class="example">This style is used for PHP coding examples.
201
+ <span class="comment"> // this style is used for coding comments.</span></p>
202
+ <p class="comment">This style is used for content details.</p>
203
+ <p class="quotes">This style is used for RFC2445 quotes.</p>
204
+ <p>
205
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a>
206
+
207
+ <a name="Versioning"></a><h2>1.3 Versioning</h2>
208
+
209
+ The release numbering convention used is major.minor.micro.
210
+ <dl>
211
+ <dt>Major
212
+ <dd>Indicates a very large change in the core package. Rewrites or major milestones.
213
+ <dt>Minor
214
+ <dd>Significant amount of feature addition/modification.<br />odd number - development/experimental release<br /> even number - production release
215
+ <dt>Micro
216
+ <dd>Mostly bug fix and maintenance number.
217
+ <dt>(Suffix)
218
+ <dd>rc1 for first release candidate, a1 for alpha 1, etc.
219
+ </dl>
220
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a>
221
+
222
+ <a name="Support"></a><h2>1.4 Support</h2>
223
+ <p>
224
+ The main support channel is using iCalcreator
225
+ <a title="Sourceforge" href="http://sourceforge.net/projects/icalcreator/forums/" target="_blank">Sourceforge</a> forum.
226
+ </p>
227
+ <p>
228
+ Use the contact <a href="http://www.kigkonsult.se/contact/index.php" title="www.kigkonsult.Se/contact" target="_blank">page</a>
229
+ for queries, improvement/development issues or professional support and development.
230
+ Please note that paid support or consulting service has the highest priority.
231
+ </p>
232
+ <p>
233
+ Our services are available for support and designing and developing iCalcreator etc. customizations,
234
+ adaptations and other PHP/MySQL solutions with a special focus on software utility and reliability,
235
+ supported through our iterative acquire/design/transition process modell.
236
+ </p>
237
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a>
238
+
239
+ <a name="INSTALL"></a><h2>1.5 Install</h2>
240
+ Unpack to any folder<br />
241
+ - add this folder to your include-path<br />
242
+ - or unpack to your application-(include)-folder<br />
243
+ Add
244
+ <p class="format">require_once [folder/]iCalcreator.class.php;</p>
245
+ to your php-script.
246
+ <br />
247
+ <br />
248
+ If using php version 5.1 or higher, the default timezone need to be set/altered, now &quot;Europe/Stockholm&quot;,
249
+ line 50 in the iCalcreator.class.php file.
250
+ <br />
251
+ <br />
252
+ When creating a new calendar/component instance, review <a href="#Calendar_configuration_functions">config</a> settings.
253
+ <br />
254
+ <br />
255
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a>
256
+
257
+ <a name="Additional_Descriptors"></a><h2>1.6 Additional Descriptors</h2>
258
+ The following properties (as described in <a href="http://en.wikipedia.org/wiki/ICalendar#Calendar_extensions" title="http://en.wikipedia.org/wiki/ICalendar#Calendar_extensions">wikipedia:iCal</a>) may be required when importing iCal files into some calendaring software (MS etc.):
259
+ <dl>
260
+ <dt>on calendar level
261
+ <dd><a href="#METHOD">METHOD</a> property (value PUBLISH etc.)
262
+ <dd><a href="#X-PROPERTY">X-WR-CALNAME</a> x-property
263
+ <dd><a href="#X-PROPERTY">X-WR-CALDESC</a> x-property
264
+ <dd><a href="#X-PROPERTY">X-WR-RELCALID</a> x-property <span class="comment">(a <a href="/wiki/Universally_Unique_Identifier" title="Universally Unique Identifier" class="mw-redirect">UUID</a>.)</span>
265
+ <dd><a href="#X-PROPERTY">X-WR-TIMEZONE</a> x-property
266
+ <dt>on component level
267
+ <dd><a href="#DTSTAMP">DTSTAMP</a> property (iCalcreator auto created)
268
+ <dd><a href="#UID">UID</a> property (iCalcreator auto created)
269
+ </dl>
270
+ Recommendation is also to set <a href="#Unique_id">unique_id</a> when creating a new vcalendar/component instance, to ensure accurate setting of all components <a href="#UID">UID</a> property, even before <a href="#parse_merge">parse</a>.
271
+ <p class="label">Example</p>
272
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot; );
273
+ $vcalendar = new vcalendar( $config );
274
+ $vcalendar->setProperty( &quot;method&quot;, &quot;PUBLISH&quot; )
275
+ $vcalendar->setProperty( &quot;x-wr-calname&quot;, &quot;Calendar Sample&quot; );
276
+ $vcalendar->setProperty( &quot;X-WR-CALDESC&quot;, &quot;Calendar Description&quot; );
277
+ $uuid = &quot;3E26604A-50F4-4449-8B3E-E4F4932D05B5&quot;;
278
+ $vcalendar->setProperty( &quot;X-WR-RELCALID&quot;, $uuid );
279
+ $vcalendar->setProperty( &quot;X-WR-TIMEZONE&quot;, &quot;Europe/Stockholm&quot; );
280
+ .. .
281
+ </p>
282
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a>
283
+
284
+ <a name="Addendum"></a><h2>1.7 Addendum</h2>
285
+ <p>
286
+ Download iCalcreator <a title="download iCalcreator coding samples" href="http://www.kigkonsult.se/downloads/index.php" target="_blank">coding samples</a>.
287
+ <br />
288
+ Examples how to employ iCalcreator in software development:<br />
289
+ <a title="Create iCal event file on-demand from form" href="http://www.kigkonsult.se/eventCreator/index.php" target="_blank">The iCal file event editor</a> and
290
+ <a title="tinycal" href="http://www.kigkonsult.se/tinycal/index.php" target="_blank">tinycal</a>, calendar-in-a-box.
291
+ </p>
292
+ <p>
293
+ There are free iCal/xCal icons in the images directory, to use as buttons on a web page.
294
+ </p>
295
+ The PHP coding examples are only examples, recommendation is to use a
296
+ coding standard, the following, incomplete, list is a good start;
297
+ <br/>
298
+ <a href="http://www.dagbladet.no/development/phpcodingstandard/" target="_blank">http://www.dagbladet.no/development/phpcodingstandard/</a>
299
+ <!--
300
+ <br/>
301
+ <a href="http://ez.no/ezpublish/documentation/development/standards/php" target="_blank">http://ez.no/ezpublish/documentation/development/standards/php</a>
302
+ -->
303
+ <br/>
304
+ <a href="http://framework.zend.com/manual/en/coding-standard.overview.html" target="_blank">http://framework.zend.com/manual/en/coding-standard.overview.html</a>
305
+ <!--
306
+ <br/>
307
+ <a href="http://gforge.org/docman/view.php/1/2/coding-standards.html" target="_blank">http://gforge.org/docman/view.php/1/2/coding-standards.html</a>
308
+ -->
309
+ <br/>
310
+ <a href="http://pear.php.net/manual/en/standards.php" target="_blank">http://pear.php.net/manual/en/standards.php</a>
311
+ <br />
312
+ <br />
313
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a>
314
+
315
+ <a name="INDEX"><h2>1.8 INDEX</h2>
316
+
317
+ <a href="#INTRO">1. INTRO</a><br />
318
+ <br />
319
+ <a href="#iCal">1.1 Ical</a><br />
320
+ <a href="#This_manual">1.2 This manual</a><br />
321
+ <a href="#Versioning">1.3 Versioning</a><br />
322
+ <a href="#Support">1.4 Support</a><br />
323
+ <a href="#INSTALL">1.5 Install</a><br />
324
+ <a href="#Additional_Descriptors">1.6 Additional_Descriptors</a><br />
325
+ <a href="#Addendum">1.7 Addendum</a><br />
326
+ <a href="#INDEX">1.8 INDEX</a><br />
327
+ <br />
328
+ <a href="#Calendar_Component_list">2. Calendar Component list</a><br />
329
+ <br />
330
+ <a href="#VCALENDAR">2.1 VCALENDAR</a><br />
331
+ <a href="#VEVENT">2.2 VEVENT</a><br />
332
+ <a href="#VTODO">2.3 VTODO</a><br />
333
+ <a href="#VJOURNAL">2.4 VJOURNAL</a><br />
334
+ <a href="#VFREEBUSY">2.5 VFREEBUSY</a><br />
335
+ <a href="#VALARM">2.6 VALARM</a><br />
336
+ <a href="#VTIMEZONE">2.7 VTIMEZONE</a><br />
337
+ <a href="#CalProps">2.10 Component Properties</a><br />
338
+ <br />
339
+ <a href="#Function_list">3. Function list</a><br />
340
+ <br />
341
+ <a href="#Calendar_object_functions">3.1 Calendar object functions</a><br />
342
+ <br />
343
+ <a href="#Calendar_object_constructors">3.1.1 Constructors</a><br />
344
+ <a href="#vcalendar">3.1.1.1 vcalendar</a><br />
345
+ <a href="#vevent">3.1.1.2 vevent</a><br />
346
+ <a href="#vtodo">3.1.1.3 vtodo</a><br />
347
+ <a href="#vjournal">3.1.1.4 vjournal</a><br />
348
+ <a href="#vfreebusy">3.1.1.5 vfreebusy</a><br />
349
+ <a href="#valarm">3.1.1.6 valarm</a><br />
350
+ <a href="#vtimezone">3.1.1.7 vtimezone</a><br />
351
+ <a href="#standard">3.1.1.8 standard</a><br />
352
+ <a href="#daylight">3.1.1.9 daylight</a><br />
353
+ <br />
354
+ <a href="#Calendar_property_functions">3.1.2 Calendar property functions</a><br />
355
+ <a href="#deleteProperty">3.1.2.1 deleteProperty</a><br />
356
+ <a href="#getProperty">3.1.2.2 getProperty</a><br />
357
+ <a href="#setProperty">3.1.2.3 setProperty</a><br />
358
+ <a href="#CALSCALE">3.1.2.4 CALSCALE</a><br />
359
+ <a href="#METHOD">3.1.2.5 METHOD</a><br />
360
+ <a href="#VERSION">3.1.2.6 VERSION</a><br />
361
+ <a href="#X-PROPERTY">3.1.2.7 X-PROPERTY</a><br />
362
+ <br />
363
+ <a href="#Calendar_component_functions">3.1.3 Calendar component functions</a><br />
364
+ <a href="#deleteComponent">3.1.3.1 deleteComponent</a><br />
365
+ <a href="#getComponent">3.1.3.2 getComponent</a><br />
366
+ <a href="#newComponent">3.1.3.3 newComponent</a><br />
367
+ <a href="#selectComponents">3.1.3.4 selectComponents</a><br />
368
+ <a href="#setComponent">3.1.3.5 setComponent</a><br />
369
+ <br />
370
+ <a href="#Calendar_inputoutput_functions">3.1.4 Calendar input/output functions</a><br />
371
+ <a href="#parse_merge">3.1.4.1 parse and merge</a><br />
372
+ <a href="#createCalendar">3.1.4.2 createCalendar</a><br />
373
+ <a href="#returnCalendar">3.1.4.3 returnCalendar</a><br />
374
+ <a href="#saveCalendar">3.1.4.4 saveCalendar</a><br />
375
+ <a href="#sort">3.1.4.5 sort</a><br />
376
+ <a href="#useCachedCalendar">3.1.4.6 useCachedCalendar</a><br />
377
+ <br />
378
+ <a href="#Calendar_configuration_functions">3.1.5 Calendar configuration functions</a><br />
379
+ <a href="#configKeys">3.1.5.1 configuration keys</a><br />
380
+ <a href="#getConfig">3.1.5.2 getConfig</a><br />
381
+ <a href="#initConfig">3.1.5.3 calendar/component initialization</a><br />
382
+ <a href="#setConfig">3.1.5.4 setConfig</a><br />
383
+ <a href="#allowEmpty">3.1.5.5 Allow empty components</h4><br />
384
+ <a href="#Compsinfo">3.1.5.6 Component information</h4><br />
385
+ <a href="#Delimiter">3.1.5.7 Delimiter</a><br />
386
+ <a href="#Directory">3.1.5.8 Directory</a><br />
387
+ <a href="#Fileinfo">3.1.5.9 Fileinfo</a><br />
388
+ <a href="#Filename">3.1.5.10 Filename</a><br />
389
+ <a href="#Filesize">3.1.5.11 Filesize</a><br />
390
+ <a href="#Format">3.1.5.12 Format</a><br />
391
+ <a href="#Language">3.1.5.13 Language</a><br />
392
+ <a href="#NewlineChar">3.1.5.14 NewlineChar</a><br />
393
+ <a href="#dTZID">3.1.5.15 TZID</a><br />
394
+ <a href="#Unique_id">3.1.5.16 Unique_id</a><br />
395
+ <a href="#configURL">3.1.5.17 URL</a><br />
396
+ <br />
397
+ <a href="#Calendar_component_object_property_function_list">3.2 Calendar component/object property function list</a><br />
398
+ <br />
399
+ <a href="#deleteProperty_PROP">3.2.1 deleteProperty</a><br />
400
+ <a href="#getProperty_PROP">3.2.2 getProperty</a><br />
401
+ <a href="#parse">3.2.3 parse</a><br />
402
+ <a href="#setProperty_PROP">3.2.4 setProperty</a><br />
403
+ <br />
404
+ <a href="#ACTION">3.2.5 ACTION</a><br />
405
+ <a href="#ATTACH">3.2.6 ATTACH</a><br />
406
+ <a href="#ATTENDEE">3.2.7 ATTENDEE</a><br />
407
+ <a href="#CATEGORIES">3.2.8 CATEGORIES</a><br />
408
+ <a href="#CLASS">3.2.9 CLASS</a><br />
409
+ <a href="#COMMENT">3.2.10 COMMENT</a><br />
410
+ <a href="#COMPLETED">3.2.11 COMPLETED</a><br />
411
+ <a href="#CONTACT">3.2.12 CONTACT</a><br />
412
+ <a href="#CREATED">3.2.13 CREATED</a><br />
413
+ <a href="#DESCRIPTION">3.2.14 DESCRIPTION</a><br />
414
+ <a href="#DTEND">3.2.15 DTEND</a><br />
415
+ <a href="#DTSTAMP">3.2.16 DTSTAMP</a><br />
416
+ <a href="#DTSTART">3.2.17 DTSTART</a><br />
417
+ <a href="#DUE">3.2.18 DUE</a><br />
418
+ <a href="#DURATION">3.2.19 DURATION</a><br />
419
+ <a href="#EXDATE">3.2.20 EXDATE</a><br />
420
+ <a href="#EXRULE">3.2.21 EXRULE</a><br />
421
+ <a href="#FREEBUSY_PROP">3.2.22 FREEBUSY</a><br />
422
+ <a href="#GEO">3.2.23 GEO</a><br />
423
+ <a href="#LAST-MODIFIED">3.2.24 LAST-MODIFIED</a><br />
424
+ <a href="#LOCATION">3.2.25 LOCATION</a><br />
425
+ <a href="#ORGANIZER">3.2.26 ORGANIZER</a><br />
426
+ <a href="#PERCENT-COMPLETE">3.2.27 PERCENT-COMPLETE</a><br />
427
+ <a href="#PRIORITY">3.2.28 PRIORITY</a><br />
428
+ <a href="#RDATE">3.2.29 RDATE</a><br />
429
+ <a href="#RECURRENCE-ID">3.2.30 RECURRENCE-ID</a><br />
430
+ <a href="#RELATED-TO">3.2.31 RELATED-TO</a><br />
431
+ <a href="#REPEAT">3.2.32 REPEAT</a><br />
432
+ <a href="#REQUEST-STATUS">3.2.33 REQUEST-STATUS</a><br />
433
+ <a href="#RESOURCES">3.2.34 RESOURCES</a><br />
434
+ <a href="#RRULE">3.2.35 RRULE</a><br />
435
+ <a href="#SEQUENCE">3.2.36 SEQUENCE</a><br />
436
+ <a href="#STATUS">3.2.37 STATUS</a><br />
437
+ <a href="#SUMMARY">3.2.38 SUMMARY</a><br />
438
+ <a href="#TRANSP">3.2.39 TRANSP</a><br />
439
+ <a href="#TRIGGER">3.2.40 TRIGGER</a><br />
440
+ <a href="#TZID">3.2.41 TZID</a><br />
441
+ <a href="#TZNAME">3.2.42 TZNAME</a><br />
442
+ <a href="#TZOFFSETFROM">3.2.43 TZOFFSETFROM</a><br />
443
+ <a href="#TZOFFSETTO">3.2.44 TZOFFSETTO</a><br />
444
+ <a href="#TZURL">3.2.45 TZURL</a><br />
445
+ <a href="#UID">3.2.46 UID</a><br />
446
+ <a href="#URL">3.2.47 URL</a><br />
447
+ <a href="#X-PROPERTY_PROP">3.2.48 X-PROPERTY</a><br />
448
+ <br />
449
+ <a href="#Calendar_component_configuration_functions">3.3 Calendar Component configuration functions</a><br />
450
+ <br />
451
+ <a href="#Language_PROP">3.3.1 Language</a><br />
452
+ <br />
453
+ <a href="#Calendar_component_object_misc_functions">3.4 Calendar component object misc. functions</a><br />
454
+ <br />
455
+ <a href="#deleteComponent_PROP">3.4.1 deleteComponent</a><br />
456
+ <a href="#getComponent_PROP">3.4.2 getComponent</a><br />
457
+ <a href="#newComponent_PROP">3.4.3 newComponent</a><br />
458
+ <a href="#setComponent_PROP">3.4.4 setComponent</a><br />
459
+ <br />
460
+ <a href="#iCalUtilityFunctions">4. iCalUtilityFunctions</a><br />
461
+ <br />
462
+ <a href="#createTimezone">4.1 createTimezone</a><br />
463
+ <br />
464
+ <a href="#Copyright_and_Licence">5. COPYRIGHT AND LICENSE</a><br />
465
+ <br />
466
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a>
467
+
468
+ <a name="Calendar_Component_list"></a><h1>2. Calendar Component list</h1>
469
+ Quote from <a href="http://www.kigkonsult.se/iCalcreator/iCalDictionary/index.html" title="RFC2445 in HTML format">rfc2445</a>!
470
+ (Described in iCal output format, content corresponds to xCal format.)<br />
471
+
472
+ <a name="VCALENDAR"></a><h2>2.1 VCALENDAR</h2>
473
+ <p class="center">icalobject = 1*(&quot;BEGIN&quot; &quot;:&quot; &quot;VCALENDAR&quot; CRLF</p>
474
+ <p class="center">icalbody</p>
475
+ <p class="center">&quot;END&quot; &quot;:&quot; &quot;VCALENDAR&quot; CRLF)</p>
476
+ <br />
477
+ icalbody = calprops component
478
+ <br />
479
+ calprops = 2*(
480
+ <br />
481
+ <p class="center">&quot;prodid&quot; and &quot;version&quot; are both REQUIRED, but MUST NOT occur more than once
482
+ <p class="center">prodid / <a href="#VERSION">version</a> /</p>
483
+ <p class="center">&quot;calscale&quot;and &quot;method&quot;are optional, but MUST NOT occur more than once</p>
484
+ <p class="center"><a href="#CALSCALE">calscale</a> / <a href="#METHOD">method</a> /</p>
485
+ <p class="center"><a href="#X-PROPERTY">x-prop</a></p>
486
+ )
487
+ <br />
488
+ <p class="center">component = 1*(<a href="#VEVENT">eventc</a> / <a href="#VTODO">todoc</a> / <a href="#VJOURNAL">journalc</a> / <a href="#VFREEBUSY">freebusyc</a> / <a href="#VTIMEZONE">timezonec</a> / iana-comp* / x-comp*)</p>
489
+ <p class="center">iana-comp = &quot;BEGIN&quot; &quot;:&quot; iana-token CRLF</p>
490
+ <p class="center">1*contentline</p>
491
+ <p class="center">&quot;END&quot; &quot;:&quot; iana-token CRLF</p>
492
+ <p class="center">x-comp = &quot;BEGIN&quot; &quot;:&quot; x-name CRLF</p>
493
+ <p class="center">1*contentline</p>
494
+ <p class="center">&quot;END&quot; &quot;:&quot; x-name CRLF</p>
495
+ *) <span class="comment">not supported by iCalcreator</span></p>
496
+ <br />
497
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_Component_list">[up]</a>
498
+
499
+ <a name="VEVENT"></a><h2>2.2 VEVENT</h2>
500
+ <p class="center">&quot;BEGIN&quot; &quot;:&quot; &quot;VEVENT&quot; CRLF</p>
501
+ <p class="center">eventprop *alarmc</p>
502
+ <p class="center">&quot;END&quot; &quot;:&quot; &quot;VEVENT&quot; CRLF</p>
503
+ eventprop = *(
504
+ <p class="center">the following are optional,but MUST NOT occur more than once</p>
505
+ <p class="center"><a href="#CLASS">class</a> / <a href="#CREATED">created</a> / <a href="#DESCRIPTION">description</a> / <a href="#DTSTART">dtstart</a> /</p>
506
+ <p class="center"><a href="#GEO">geo</a> / <a href="#LAST-MODIFIED">last-mod</a> / <a href="#LOCATION">location</a> / <a href="#ORGANIZER">organizer</a> / <a href="#PRIORITY">priority</a> / </p>
507
+ <p class="center"><a href="#DTSTAMP">dtstamp</a> / <a href="#SEQUENCE">seq</a> / <a href="#STATUS">status</a> / <a href="#SUMMARY">summary</a> / </p>
508
+ <p class="center"><a href="#TRANSP">transp</a> / <a href="#UID">uid</a> / <a href="#URL">url</a> / <a href="#RECURRENCE-ID">recurid</a> /</p>
509
+ <p class="center">either &quot;<a href="#DTEND">dtend</a>&quot; or &quot;<a href="#DURATION">duration</a>&quot; may appear in a &quot;eventprop&quot;, </p>
510
+ <p class="center">but &quot;<a href="#DTEND">dtend</a>&quot; and &quot;<a href="#DURATION">duration</a>&quot; MUST NOT occur in the same &quot;eventprop&quot;</p>
511
+ <p class="center"><a href="#DTEND">dtend</a> / <a href="#DURATION">duration</a> /</p>
512
+ <p class="center">the following are optional, and MAY occur more than once</p>
513
+ <p class="center"><a href="#ATTACH">attach</a> / <a href="#ATTENDEE">attendee</a> / <a href="#CATEGORIES">categories</a> / <a href="#COMMENT">comment</a> / </p>
514
+ <p class="center"><a href="#CONTACT">contact</a> / <a href="#EXDATE">exdate</a> / <a href="#EXRULE">exrule</a> / <a href="#REQUEST-STATUS">rstatus</a> / </p>
515
+ <p class="center"><a href="#RELATED-TO">related</a> / <a href="#RESOURCES">resources</a> / <a href="#RDATE">rdate</a> / <a href="#RRULE">rrule</a> / <a href="#X-PROPERTY_PROP">x-prop</a></p>
516
+ )
517
+ <br />
518
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_Component_list">[up]</a>
519
+
520
+ <a name="VTODO"></a><h2>2.3 VTODO</h2>
521
+ <p class="center">&quot;BEGIN&quot; &quot;:&quot; &quot;VTODO&quot; CRLF</p>
522
+ <p class="center">todoprop *alarmc</p>
523
+ <p class="center">&quot;END&quot; &quot;:&quot; &quot;VTODO&quot; CRLF</p>
524
+ todoprop = *(
525
+ <p class="center">the following are optional, but MUST NOT occur more than once</p>
526
+ <p class="center"><a href="#CLASS">class</a> / <a href="#COMPLETED">completed</a> / <a href="#CREATED">created</a> / <a href="#DESCRIPTION">description</a> / <a href="#DTSTAMP">dtstamp</a> / <a href="#DTSTART">dtstart</a> / </p>
527
+ <p class="center"><a href="#GEO">geo</a> / <a href="#LAST-MODIFIED">last-mod</a> / <a href="#LOCATION">location</a> / <a href="#ORGANIZER">organizer</a> / <a href="#PERCENT-COMPLETE">percent</a> / <a href="#PRIORITY">priority</a> / </p>
528
+ <p class="center"><a href="#RECURRENCE-ID">recurid</a> / <a href="#SEQUENCE">seq</a> / <a href="#STATUS">status</a> / <a href="#SUMMARY">summary</a> /<a href="#UID">uid</a> / <a href="#URL">url</a> /</p>
529
+ <p class="center">either &quot;<a href="#DUE">due</a>&quot; or &quot;<a href="#DURATION">duration</a>&quot; may appear in a &quot;todoprop&quot;,</p>
530
+ <p class="center"> but &quot;<a href="#DUE">due</a>&quot; and &quot;<a href="#DURATION">duration</a>&quot; MUST NOT occur in the same &quot;todoprop&quot;</p>
531
+ <p class="center"><a href="#DUE">due</a> / <a href="#DURATION">duration</a> /</p>
532
+ <p class="center">the following are optional,and MAY occur more than once</p>
533
+ <p class="center"><a href="#ATTACH">attach</a> / <a href="#ATTENDEE">attendee</a> / <a href="#CATEGORIES">categories</a> / <a href="#COMMENT">comment</a> / </p>
534
+ <p class="center"><a href="#CONTACT">contact</a> / <a href="#EXDATE">exdate</a> / <a href="#EXRULE">exrule</a> / <a href="#REQUEST-STATUS">rstatus</a> / </p>
535
+ <p class="center"><a href="#RELATED-TO">related</a> / <a href="#RESOURCES">resources</a> / <a href="#RDATE">rdate</a> / <a href="#RRULE">rrule</a> / <a href="#X-PROPERTY_PROP">x-prop</a></p>
536
+ )
537
+ <br />
538
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_Component_list">[up]</a>
539
+
540
+ <a name="VJOURNAL"></a><h2>2.4 VJOURNAL</h2>
541
+ <p class="center">journalc = &quot;BEGIN&quot; &quot;:&quot; &quot;VJOURNAL&quot; CRLF</p>
542
+ <p class="center">jourprop</p>
543
+ <p class="center">&quot;END&quot; &quot;:&quot; &quot;VJOURNAL&quot; CRLF</p>
544
+ jourprop = *(
545
+ <p class="center">the following are optional, but MUST NOT occur more than once</p>
546
+ <p class="center"><a href="#CLASS">class</a> / <a href="#CREATED">created</a> / <a href="#DESCRIPTION">description</a> / <a href="#DTSTART">dtstart</a> / </p>
547
+ <p class="center"><a href="#DTSTAMP">dtstamp</a> / <a href="#LAST-MODIFIED">last-mod</a> / <a href="#ORGANIZER">organizer</a> / <a href="#RECURRENCE-ID">recurid</a> / </p>
548
+ <p class="center"><a href="#SEQUENCE">seq</a> / <a href="#STATUS">status</a> / <a href="#SUMMARY">summary</a> /<a href="#UID">uid</a> / <a href="#URL">url</a> /</p>
549
+ <p class="center">the following are optional,and MAY occur more than once</p>
550
+ <p class="center"><a href="#ATTACH">attach</a> / <a href="#ATTENDEE">attendee</a> / <a href="#CATEGORIES">categories</a> / <a href="#COMMENT">comment</a> /</p>
551
+ <p class="center"><a href="#CONTACT">contact</a> / <a href="#EXDATE">exdate</a> / <a href="#EXRULE">exrule</a> / <a href="#RELATED-TO">related</a> / </p>
552
+ <p class="center"><a href="#RDATE">rdate</a> / <a href="#RRULE">rrule</a> / <a href="#REQUEST-STATUS">rstatus</a> / <a href="#X-PROPERTY_PROP">x-prop</a></p>
553
+ )
554
+ <br />
555
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_Component_list">[up]</a>
556
+
557
+ <a name="VFREEBUSY"></a><h2>2.5 VFREEBUSY</h2>
558
+ <p class="center">&quot;BEGIN&quot; &quot;:&quot; &quot;VFREEBUSY&quot; CRLF</p>
559
+ <p class="center">fbprop</p>
560
+ <p class="center">&quot;END&quot; &quot;:&quot; &quot;VFREEBUSY&quot; CRLF</p>
561
+ fbprop = *(
562
+ <p class="center">the following are optional, but MUST NOT occur more than once</p>
563
+ <p class="center"><a href="#CONTACT">contact</a> / <a href="#DTSTART">dtstart</a> / <a href="#DTEND">dtend</a> / <a href="#DURATION">duration</a> / </p>
564
+ <p class="center"><a href="#DTSTAMP">dtstamp</a> / <a href="#ORGANIZER">organizer</a> / <a href="#UID">uid</a> / <a href="#URL">url</a> / </p>
565
+ <p class="center">the following are optional,and MAY occur more than once</p>
566
+ <p class="center"><a href="#ATTENDEE">attendee</a> / <a href="#COMMENT">comment</a> / <a href="#FREEBUSY_PROP">freebusy</a> / <a href="#REQUEST-STATUS">rstatus</a> / <a href="#X-PROPERTY_PROP">x-prop</a></p>
567
+ )
568
+ <br />
569
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_Component_list">[up]</a>
570
+
571
+ <a name="VALARM"></a><h2>2.6 VALARM</h2>
572
+ <p class="center">&quot;BEGIN&quot; &quot;:&quot; &quot;VALARM&quot; CRLF</p>
573
+ <p class="center">(audioprop / dispprop / emailprop / procprop)</p>
574
+ <p class="center">&quot;END&quot; &quot;:&quot; &quot;VALARM&quot; CRLF</p> audioprop = 2*(
575
+ <p class="center">&quot;<a href="#ACTION">action</a>&quot; and &quot;<a href="#TRIGGER">trigger</a>&quot; are both REQUIRED, but MUST NOT occur more than once</p>
576
+ <p class="center"><a href="#ACTION">action</a> / <a href="#TRIGGER">trigger</a> /</p>
577
+ <p class="center">&quot;<a href="#DURATION">duration</a>&quot; and &quot;<a href="#REPEAT">repeat</a>&quot; are both optional,and MUST NOT occur more than once each,</p>
578
+ <p class="center">but if one occurs, so MUST the other</p>
579
+ <p class="center"><a href="#DURATION">duration</a> / <a href="#REPEAT">repeat</a> /</p>
580
+ <p class="center">the following is optional, but MUST NOT occur more than once</p>
581
+ <p class="center"><a href="#ATTACH">attach</a> / </p>
582
+ <p class="center">the following is optional, and MAY occur more than once</p>
583
+ <p class="center"><a href="#X-PROPERTY_PROP">x-prop</a></p>
584
+ )
585
+ <br />
586
+ dispprop = 3*(
587
+ <p class="center">the following are all REQUIRED, but MUST NOT occur more than once</p>
588
+ <p class="center"><a href="#ACTION">action</a> / <a href="#DESCRIPTION">description</a> / <a href="#TRIGGER">trigger</a> /</p>
589
+ <p class="center">&quot;<a href="#DURATION">duration</a>&quot; and &quot;<a href="#REPEAT">repeat</a>&quot; are both optional,and MUST NOT occur more than once each,</p>
590
+ <p class="center">but if one occurs, so MUST the other</p>
591
+ <p class="center"><a href="#DURATION">duration</a> / <a href="#REPEAT">repeat</a> /</p>
592
+ <p class="center">the following is optional, and MAY occur more than once</p>
593
+ <p class="center"><a href="#X-PROPERTY_PROP">x-prop</a></p>
594
+ )
595
+ <br />
596
+ emailprop = 5*(
597
+ <p class="center">the following are all REQUIRED, but MUST NOT occur more than once</p>
598
+ <p class="center"><a href="#ACTION">action</a> / <a href="#DESCRIPTION">description</a> / <a href="#TRIGGER">trigger</a> / <a href="#SUMMARY">summary</a></p>
599
+ <p class="center">the following is REQUIRED, and MAY occur more than once</p>
600
+ <p class="center"><a href="#ATTENDEE">attendee</a> / </p>
601
+ <p class="center">&quot;<a href="#DURATION">duration</a>&quot; and &quot;<a href="#REPEAT">repeat</a>&quot; are both optional, and MUST NOT occur more than once each,</p>
602
+ <p class="center">but if one occurs, so MUST the other</p>
603
+ <p class="center"><a href="#DURATION">duration</a> / <a href="#REPEAT">repeat</a> /</p>
604
+ <p class="center">the following are optional, and MAY occur more than once</p>
605
+ <p class="center"><a href="#ATTACH">attach</a> / <a href="#X-PROPERTY_PROP">x-prop</a></p>
606
+ )
607
+ <br />
608
+ procprop = 3*(
609
+ <p class="center">the following are all REQUIRED, but MUST NOT occur more than once</p>
610
+ <p class="center"><a href="#ACTION">action</a> / <a href="#ATTACH">attach</a> / <a href="#TRIGGER">trigger</a> /</p>
611
+ <p class="center">&quot;<a href="#DURATION">duration</a>&quot; and &quot;<a href="#REPEAT">repeat</a>&quot; are both optional, and MUST NOT occur more than once each,</p>
612
+ <p class="center">but if one occurs, so MUST the other</p>
613
+ <p class="center"><a href="#DURATION">duration</a> /
614
+ <a href="#REPEAT">repeat</a> /</p>
615
+ <p class="center">&quot;<a href="#DESCRIPTION">description</a>&quot; is optional, and MUST NOT occur more than once</p>
616
+ <p class="center"><a href="#DESCRIPTION">description</a> / </p>
617
+ <p class="center">the following is optional, and MAY occur more than once</p>
618
+ <p class="center"><a href="#X-PROPERTY_PROP">x-prop</a></p>
619
+ )
620
+ <br />
621
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_Component_list">[up]</a>
622
+
623
+ <a name="VTIMEZONE"></a><h2>2.7 VTIMEZONE</h2>
624
+ <p class="center">&quot;BEGIN&quot; &quot;:&quot; &quot;VTIMEZONE&quot; CRLF</p>
625
+ 2*(
626
+ <p class="center">&quot;<a href="#TZID">tzid</a>&quot; is required, but MUST NOT occur more than once</p>
627
+ <p class="center"><a href="#TZID">tzid</a> / </p>
628
+ <p class="center">&quot;<a href="#LAST-MODIFIED">last-mod</a>&quot; and &quot;<a href="#TZURL">tzurl</a>&quot; are optional, but MUST NOT occur more than once</p>
629
+ <p class="center"><a href="#LAST-MODIFIED">last-mod</a> / <a href="#TZURL">tzurl</a> /</p>
630
+ <p class="center">one of &quot;standardc&quot; or &quot;daylightc&quot; MUST occur and each MAY occur more than once.</p>
631
+ <p class="center">standardc / daylightc /</p>
632
+ <p class="center">the following is optional, and MAY occur more than once</p>
633
+ <p class="center"><a href="#X-PROPERTY_PROP">x-prop</a></p>
634
+ )
635
+ <p class="center">&quot;END&quot; &quot;:&quot; &quot;VTIMEZONE&quot; CRLF</p>
636
+ <p class="center">standardc = &quot;BEGIN&quot; &quot;:&quot; &quot;STANDARD&quot; CRLF</p>
637
+ <p class="center">tzprop</p>
638
+ <p class="center">&quot;END&quot; &quot;:&quot; &quot;STANDARD&quot; CRLF</p>
639
+ <p class="center">daylightc = &quot;BEGIN&quot; &quot;:&quot; &quot;DAYLIGHT&quot; CRLF</p>
640
+ <p class="center">tzprop</p>
641
+ <p class="center">&quot;END&quot; &quot;:&quot; &quot;DAYLIGHT&quot; CRLF</p>
642
+ <br />
643
+ tzprop = 3*(
644
+ <p class="center">the following are each REQUIRED, but MUST NOT occur more than once</p>
645
+ <p class="center"><a href="#DTSTART">dtstart</a> / <a href="#TZOFFSETTO">tzoffsetto</a> / <a href="#TZOFFSETFROM">tzoffsetfrom</a> /</p>
646
+ <p class="center">the following are optional, and MAY occur more than once</p>
647
+ <p class="center"><a href="#COMMENT">comment</a> /<a href="#RDATE">rdate</a> / <a href="#RRULE">rrule</a> / <a href="#TZNAME">tzname</a> / <a href="#X-PROPERTY_PROP">x-prop</a></p>
648
+ )
649
+ <br />
650
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_Component_list">[up]</a>
651
+
652
+ <a name="CalProps"></a><h2>2.8 Component Properties</h2>
653
+ A comprehensive table showing relation between calendar components and properties.
654
+ <a href="#VTIMEZONE">vtimezone</a> properties are not included.
655
+ <br /><br />
656
+ <table>
657
+ <tr>
658
+ <td>0-1</td>
659
+ <td colspan="8">OPTIONAL property, MUST NOT occur more than once.</td>
660
+ </tr>
661
+ <tr>
662
+ <td>0-m</td>
663
+ <td colspan="8">OPTIONAL property, MAY occur more than once.</td>
664
+ </tr>
665
+ <tr>
666
+ <td>0&nbsp;or&nbsp;1=1</td>
667
+ <td colspan="8">A pair of OPTIONAL properties, MUST NOT occur more than once each.<br />If one occurs, so MUST the other</td>
668
+ </tr>
669
+ <tr>
670
+ <td>0*1</td>
671
+ <td colspan="8">A pair of OPTIONAL properties, MUST NOT occur more than once each.<br />If one occurs, so MUST NOT the other</td>
672
+ </tr>
673
+ <tr>
674
+ <td>1-m</td>
675
+ <td colspan="8">REQUIRED property, MAY occur more than once.</td>
676
+ </tr>
677
+ <tr>
678
+ <td>1</td>
679
+ <td colspan="8">REQUIRED property, MUST NOT occur more than once.</td>
680
+ </tr>
681
+ <tr>
682
+ <td colspan="9">&nbsp;</td>
683
+ </tr>
684
+ <tr>
685
+ <td>&nbsp;</td>
686
+ <td class="bl bb center top" rowspan="2"><a class="ref" href="#VEVENT">v<br/>e<br/>v<br/>e<br/>n<br/>t</a></td>
687
+ <td class="bl bb center top" rowspan="2"><a class="ref" href="#VTODO">v<br/>t<br/>o<br/>d<br/>o</a></td>
688
+ <td class="bl bb center top" rowspan="2"><a class="ref" href="#VJOURNAL">v<br/>j<br/>o<br/>u<br/>r<br/>n<br/>a<br/>l</a></td>
689
+ <td class="bl bb center top" rowspan="2"><a class="ref" href="#VFREEBUSY">v<br/>f<br/>r<br/>e<br/>e<br/>b<br/>u<br/>s<br/>y</a></td>
690
+ <td class="bl top center" colspan="4"><a class="ref" href="#VALARM">v&nbsp;a&nbsp;l&nbsp;a&nbsp;r&nbsp;m</a></td>
691
+ </tr>
692
+ <tr>
693
+ <td class="bb">&nbsp;</td>
694
+ <td class="bl bb center ref"><br/><br/><br/><br/>a<br/>u<br/>d<br/>i<br/>o</td>
695
+ <td class="bl bb center ref"><br/><br/>d<br/>i<br/>s<br/>p<br/>l<br/>a<br/>y</td>
696
+ <td class="bl bb center ref"><br/><br/><br/><br/>e<br/>m<br/>a<br/>i<br/>l</td>
697
+ <td class="bl bb center ref">p<br/>r<br/>o<br/>c<br/>e<br/>d<br/>u<br/>r<br/>e</td>
698
+ </tr>
699
+ <tr>
700
+ <td class="bb"><a class="ref" href="#ACTION">action</a></td>
701
+ <td class="blb">&nbsp;</td>
702
+ <td class="blb">&nbsp;</td>
703
+ <td class="blb">&nbsp;</td>
704
+ <td class="blb">&nbsp;</td>
705
+ <td class="blb">1</td>
706
+ <td class="blb">1</td>
707
+ <td class="blb">1</td>
708
+ <td class="blb">1</td>
709
+ </tr>
710
+ <tr>
711
+ <td class="bb"><a class="ref" href="#ATTACH">attach</a></td>
712
+ <td class="blb">0-m</td>
713
+ <td class="blb">0-m</td>
714
+ <td class="blb">0-m</td>
715
+ <td class="blb"></td>
716
+ <td class="blb">0-1</td>
717
+ <td class="blb">&nbsp;</td>
718
+ <td class="blb">0-m</td>
719
+ <td class="blb">1</td>
720
+ </tr>
721
+ <tr>
722
+ <td class="bb"><a class="ref" href="#ATTENDEE">attendee</a></td>
723
+ <td class="blb">0-m</td>
724
+ <td class="blb">0-m</td>
725
+ <td class="blb">0-m</td>
726
+ <td class="blb">0-m</td>
727
+ <td class="blb">&nbsp;</td>
728
+ <td class="blb">&nbsp;</td>
729
+ <td class="blb">1-m</td>
730
+ <td class="blb">&nbsp;</td>
731
+ </tr>
732
+ <tr>
733
+ <td class="bb"><a class="ref" href="#CATEGORIES">categories</a></td>
734
+ <td class="blb">0-m</td>
735
+ <td class="blb">0-m</td>
736
+ <td class="blb">0-m</td>
737
+ <td class="blb">&nbsp;</td>
738
+ <td class="blb">&nbsp;</td>
739
+ <td class="blb">&nbsp;</td>
740
+ <td class="blb">&nbsp;</td>
741
+ <td class="blb">&nbsp;</td>
742
+ </tr>
743
+ <tr>
744
+ <td class="bb"><a class="ref" href="#CLASS">class</a></td>
745
+ <td class="blb">0-1</td>
746
+ <td class="blb">0-1</td>
747
+ <td class="blb">0-1</td>
748
+ <td class="blb">&nbsp;</td>
749
+ <td class="blb">&nbsp;</td>
750
+ <td class="blb">&nbsp;</td>
751
+ <td class="blb">&nbsp;</td>
752
+ <td class="blb">&nbsp;</td>
753
+ </tr>
754
+ <tr>
755
+ <td class="bb"><a class="ref" href="#COMMENT">comment</a></td>
756
+ <td class="blb">0-m</td>
757
+ <td class="blb">0-m</td>
758
+ <td class="blb">0-m</td>
759
+ <td class="blb">0-m</td>
760
+ <td class="blb">&nbsp;</td>
761
+ <td class="blb">&nbsp;</td>
762
+ <td class="blb">&nbsp;</td>
763
+ <td class="blb">&nbsp;</td>
764
+ </tr>
765
+ <tr>
766
+ <td class="bb"><a class="ref" href="#COMPLETED">completed</a></td>
767
+ <td class="blb">&nbsp;</td>
768
+ <td class="blb">0-1</td>
769
+ <td class="blb">&nbsp;</td>
770
+ <td class="blb">&nbsp;</td>
771
+ <td class="blb">&nbsp;</td>
772
+ <td class="blb">&nbsp;</td>
773
+ <td class="blb">&nbsp;</td>
774
+ <td class="blb">&nbsp;</td>
775
+ </tr>
776
+ <tr>
777
+ <td class="bb"><a class="ref" href="#CONTACT">contact</a></td>
778
+ <td class="blb">0-m</td>
779
+ <td class="blb">0-m</td>
780
+ <td class="blb">0-m</td>
781
+ <td class="blb">0-1</td>
782
+ <td class="blb">&nbsp;</td>
783
+ <td class="blb">&nbsp;</td>
784
+ <td class="blb">&nbsp;</td>
785
+ <td class="blb">&nbsp;</td>
786
+ </tr>
787
+ <tr>
788
+ <td class="bb"><a class="ref" href="#CREATED">created</a></td>
789
+ <td class="blb">0-1</td>
790
+ <td class="blb">0-1</td>
791
+ <td class="blb">0-1</td>
792
+ <td class="blb">&nbsp;</td>
793
+ <td class="blb">&nbsp;</td>
794
+ <td class="blb">&nbsp;</td>
795
+ <td class="blb">&nbsp;</td>
796
+ <td class="blb">&nbsp;</td>
797
+ </tr>
798
+ <tr>
799
+ <td class="bb"><a class="ref" href="#DESCRIPTION">description</a></td>
800
+ <td class="blb">0-1</td>
801
+ <td class="blb">0-1</td>
802
+ <td class="blb">0-m</td>
803
+ <td class="blb">&nbsp;</td>
804
+ <td class="blb">&nbsp;</td>
805
+ <td class="blb">1</td>
806
+ <td class="blb">1</td>
807
+ <td class="blb">0-1</td>
808
+ </tr>
809
+ <tr>
810
+ <td class="bb"><a class="ref" href="#DTEND">dtend</a></td>
811
+ <td class="blb">0*1</td>
812
+ <td class="blb">&nbsp;</td>
813
+ <td class="blb">&nbsp;</td>
814
+ <td class="blb">0-1</td>
815
+ <td class="blb">&nbsp;</td>
816
+ <td class="blb">&nbsp;</td>
817
+ <td class="blb">&nbsp;</td>
818
+ <td class="blb">&nbsp;</td>
819
+ </tr>
820
+ <tr>
821
+ <td class="bb"><a class="ref" href="#DTSTAMP">dtstamp</a></td>
822
+ <td class="blb">0-1</td>
823
+ <td class="blb">0-1</td>
824
+ <td class="blb">0-1</td>
825
+ <td class="blb">0-1</td>
826
+ <td class="blb">&nbsp;</td>
827
+ <td class="blb">&nbsp;</td>
828
+ <td class="blb">&nbsp;</td>
829
+ <td class="blb">&nbsp;</td>
830
+ </tr>
831
+ <tr>
832
+ <td class="bb"><a class="ref" href="#DTSTART">dtstart</a></td>
833
+ <td class="blb">0-1</td>
834
+ <td class="blb">0-1</td>
835
+ <td class="blb">0-1</td>
836
+ <td class="blb">0-1</td>
837
+ <td class="blb">&nbsp;</td>
838
+ <td class="blb">&nbsp;</td>
839
+ <td class="blb">&nbsp;</td>
840
+ <td class="blb">&nbsp;</td>
841
+ </tr>
842
+ <tr>
843
+ <td class="bb"><a class="ref" href="#DUE">due</a></td>
844
+ <td class="blb">&nbsp;</td>
845
+ <td class="blb">0*1</td>
846
+ <td class="blb">&nbsp;</td>
847
+ <td class="blb">&nbsp;</td>
848
+ <td class="blb">&nbsp;</td>
849
+ <td class="blb">&nbsp;</td>
850
+ <td class="blb">&nbsp;</td>
851
+ <td class="blb">&nbsp;</td>
852
+ </tr>
853
+ <tr>
854
+ <td class="bb"><a class="ref" href="#DURATION">duration</a></td>
855
+ <td class="blb">0*1</td>
856
+ <td class="blb">0*1</td>
857
+ <td class="blb">&nbsp;</td>
858
+ <td class="blb">0-1</td>
859
+ <td class="blb">0&nbsp;or&nbsp;1=1</td>
860
+ <td class="blb">0&nbsp;or&nbsp;1=1</td>
861
+ <td class="blb">0&nbsp;or&nbsp;1=1</td>
862
+ <td class="blb">0&nbsp;or&nbsp;1=1</td>
863
+ </tr>
864
+ <tr>
865
+ <td class="bb"><a class="ref" href="#EXDATE">exdate</a></td>
866
+ <td class="blb">0-m</td>
867
+ <td class="blb">0-m</td>
868
+ <td class="blb">0-m</td>
869
+ <td class="blb">&nbsp;</td>
870
+ <td class="blb">&nbsp;</td>
871
+ <td class="blb">&nbsp;</td>
872
+ <td class="blb">&nbsp;</td>
873
+ <td class="blb">&nbsp;</td>
874
+ </tr>
875
+ <tr>
876
+ <td class="bb"><a class="ref" href="#EXRULE">exrule</a></td>
877
+ <td class="blb">0-m</td>
878
+ <td class="blb">0-m</td>
879
+ <td class="blb">0-m</td>
880
+ <td class="blb">&nbsp;</td>
881
+ <td class="blb">&nbsp;</td>
882
+ <td class="blb">&nbsp;</td>
883
+ <td class="blb">&nbsp;</td>
884
+ <td class="blb">&nbsp;</td>
885
+ </tr>
886
+ <tr>
887
+ <td class="bb"><a class="ref" href="#FREEBUSY_PROP">freebusy</a></td>
888
+ <td class="blb">&nbsp;</td>
889
+ <td class="blb">&nbsp;</td>
890
+ <td class="blb">&nbsp;</td>
891
+ <td class="blb">0-m</td>
892
+ <td class="blb">&nbsp;</td>
893
+ <td class="blb">&nbsp;</td>
894
+ <td class="blb">&nbsp;</td>
895
+ <td class="blb">&nbsp;</td>
896
+ </tr>
897
+ <tr>
898
+ <td class="bb"><a class="ref" href="#GEO">geo</a></td>
899
+ <td class="blb">0-1</td>
900
+ <td class="blb">0-1</td>
901
+ <td class="blb">&nbsp;</td>
902
+ <td class="blb">&nbsp;</td>
903
+ <td class="blb">&nbsp;</td>
904
+ <td class="blb">&nbsp;</td>
905
+ <td class="blb">&nbsp;</td>
906
+ <td class="blb">&nbsp;</td>
907
+ </tr>
908
+ <tr>
909
+ <td class="bb"><a class="ref" href="#LAST-MODIFIED">last-mod</a></td>
910
+ <td class="blb">0-1</td>
911
+ <td class="blb">0-1</td>
912
+ <td class="blb">0-1</td>
913
+ <td class="blb"></td>
914
+ <td class="blb">&nbsp;</td>
915
+ <td class="blb">&nbsp;</td>
916
+ <td class="blb">&nbsp;</td>
917
+ <td class="blb">&nbsp;</td>
918
+ </tr>
919
+ <tr>
920
+ <td class="bb"><a class="ref" href="#LOCATION">location</a></td>
921
+ <td class="blb">0-1</td>
922
+ <td class="blb">0-1</td>
923
+ <td class="blb">&nbsp;</td>
924
+ <td class="blb">&nbsp;</td>
925
+ <td class="blb">&nbsp;</td>
926
+ <td class="blb">&nbsp;</td>
927
+ <td class="blb">&nbsp;</td>
928
+ <td class="blb">&nbsp;</td>
929
+ </tr>
930
+ <tr>
931
+ <td class="bb"><a class="ref" href="#ORGANIZER">organizer</a></td>
932
+ <td class="blb">0-1</td>
933
+ <td class="blb">0-1</td>
934
+ <td class="blb">0-1</td>
935
+ <td class="blb">0-1</td>
936
+ <td class="blb">&nbsp;</td>
937
+ <td class="blb">&nbsp;</td>
938
+ <td class="blb">&nbsp;</td>
939
+ <td class="blb">&nbsp;</td>
940
+ </tr>
941
+ <tr>
942
+ <td class="bb"><a class="ref" href="#PERCENT-COMPLETE">percent</a></td>
943
+ <td class="blb">&nbsp;</td>
944
+ <td class="blb">0-1</td>
945
+ <td class="blb">&nbsp;</td>
946
+ <td class="blb">&nbsp;</td>
947
+ <td class="blb">&nbsp;</td>
948
+ <td class="blb">&nbsp;</td>
949
+ <td class="blb">&nbsp;</td>
950
+ <td class="blb">&nbsp;</td>
951
+ </tr>
952
+ <tr>
953
+ <td class="bb"><a class="ref" href="#PRIORITY">priority</a></td>
954
+ <td class="blb">0-1</td>
955
+ <td class="blb">0-1</td>
956
+ <td class="blb">&nbsp;</td>
957
+ <td class="blb">&nbsp;</td>
958
+ <td class="blb">&nbsp;</td>
959
+ <td class="blb">&nbsp;</td>
960
+ <td class="blb">&nbsp;</td>
961
+ <td class="blb">&nbsp;</td>
962
+ </tr>
963
+ <tr>
964
+ <td class="bb"><a class="ref" href="#RDATE">rdate</a></td>
965
+ <td class="blb">0-m</td>
966
+ <td class="blb">0-m</td>
967
+ <td class="blb">0-m</td>
968
+ <td class="blb">&nbsp;</td>
969
+ <td class="blb">&nbsp;</td>
970
+ <td class="blb">&nbsp;</td>
971
+ <td class="blb">&nbsp;</td>
972
+ <td class="blb">&nbsp;</td>
973
+ </tr>
974
+ <tr>
975
+ <td class="bb"><a class="ref" href="#RECURRENCE-ID">recurid</a></td>
976
+ <td class="blb">0-1</td>
977
+ <td class="blb">0-1</td>
978
+ <td class="blb">0-1</td>
979
+ <td class="blb">&nbsp;</td>
980
+ <td class="blb">&nbsp;</td>
981
+ <td class="blb">&nbsp;</td>
982
+ <td class="blb">&nbsp;</td>
983
+ <td class="blb">&nbsp;</td>
984
+ </tr>
985
+ <tr>
986
+ <td class="bb"><a class="ref" href="#RELATED-TO">related</a></td>
987
+ <td class="blb">0-m</td>
988
+ <td class="blb">0-m</td>
989
+ <td class="blb">0-m</td>
990
+ <td class="blb">&nbsp;</td>
991
+ <td class="blb">&nbsp;</td>
992
+ <td class="blb">&nbsp;</td>
993
+ <td class="blb">&nbsp;</td>
994
+ <td class="blb">&nbsp;</td>
995
+ </tr>
996
+ <tr>
997
+ <td class="bb"><a class="ref" href="#REPEAT">repeat</a></td>
998
+ <td class="blb">&nbsp;</td>
999
+ <td class="blb">&nbsp;</td>
1000
+ <td class="blb">&nbsp;</td>
1001
+ <td class="blb">&nbsp;</td>
1002
+ <td class="blb">0&nbsp;or&nbsp;1=1</td>
1003
+ <td class="blb">0&nbsp;or&nbsp;1=1</td>
1004
+ <td class="blb">0&nbsp;or&nbsp;1=1</td>
1005
+ <td class="blb">0&nbsp;or&nbsp;1=1</td>
1006
+ </tr>
1007
+ <tr>
1008
+ <td class="bb"><a class="ref" href="#RESOURCES">resources</a></td>
1009
+ <td class="blb">0-m</td>
1010
+ <td class="blb">0-m</td>
1011
+ <td class="blb">&nbsp;</td>
1012
+ <td class="blb">&nbsp;</td>
1013
+ <td class="blb">&nbsp;</td>
1014
+ <td class="blb">&nbsp;</td>
1015
+ <td class="blb">&nbsp;</td>
1016
+ <td class="blb">&nbsp;</td>
1017
+ </tr>
1018
+ <tr>
1019
+ <td class="bb"><a class="ref" href="#RRULE">rrule</a></td>
1020
+ <td class="blb">0-m</td>
1021
+ <td class="blb">0-m</td>
1022
+ <td class="blb">0-m</td>
1023
+ <td class="blb">&nbsp;</td>
1024
+ <td class="blb">&nbsp;</td>
1025
+ <td class="blb">&nbsp;</td>
1026
+ <td class="blb">&nbsp;</td>
1027
+ <td class="blb">&nbsp;</td>
1028
+ </tr>
1029
+ <tr>
1030
+ <td class="bb"><a class="ref" href="#REQUEST-STATUS">rstatus</a></td>
1031
+ <td class="blb">0-m</td>
1032
+ <td class="blb">0-m</td>
1033
+ <td class="blb">0-m</td>
1034
+ <td class="blb">0-m</td>
1035
+ <td class="blb">&nbsp;</td>
1036
+ <td class="blb">&nbsp;</td>
1037
+ <td class="blb">&nbsp;</td>
1038
+ <td class="blb">&nbsp;</td>
1039
+ </tr>
1040
+ <tr>
1041
+ <td class="bb"><a class="ref" href="#SEQUENCE">sequence</a></td>
1042
+ <td class="blb">0-1</td>
1043
+ <td class="blb">0-1</td>
1044
+ <td class="blb">0-1</td>
1045
+ <td class="blb">&nbsp;</td>
1046
+ <td class="blb">&nbsp;</td>
1047
+ <td class="blb">&nbsp;</td>
1048
+ <td class="blb">&nbsp;</td>
1049
+ <td class="blb">&nbsp;</td>
1050
+ </tr>
1051
+ <tr>
1052
+ <td class="bb"><a class="ref" href="#STATUS">status</a></td>
1053
+ <td class="blb">0-1</td>
1054
+ <td class="blb">0-1</td>
1055
+ <td class="blb">0-1</td>
1056
+ <td class="blb">&nbsp;</td>
1057
+ <td class="blb">&nbsp;</td>
1058
+ <td class="blb">&nbsp;</td>
1059
+ <td class="blb">&nbsp;</td>
1060
+ <td class="blb">&nbsp;</td>
1061
+ </tr>
1062
+ <tr>
1063
+ <td class="bb"><a class="ref" href="#SUMMARY">summary</a></td>
1064
+ <td class="blb">0-1</td>
1065
+ <td class="blb">0-1</td>
1066
+ <td class="blb">0-1</td>
1067
+ <td class="blb">&nbsp;</td>
1068
+ <td class="blb">&nbsp;</td>
1069
+ <td class="blb">&nbsp;</td>
1070
+ <td class="blb">1</td>
1071
+ <td class="blb">&nbsp;</td>
1072
+ </tr>
1073
+ <tr>
1074
+ <td class="bb"><a class="ref" href="#TRANSP">transp</a></td>
1075
+ <td class="blb">0-1</td>
1076
+ <td class="blb">&nbsp;</td>
1077
+ <td class="blb">&nbsp;</td>
1078
+ <td class="blb">&nbsp;</td>
1079
+ <td class="blb">&nbsp;</td>
1080
+ <td class="blb">&nbsp;</td>
1081
+ <td class="blb">&nbsp;</td>
1082
+ <td class="blb">&nbsp;</td>
1083
+ </tr>
1084
+ <tr>
1085
+ <td class="bb"><a class="ref" href="#TRIGGER">trigger</a></td>
1086
+ <td class="blb">&nbsp;</td>
1087
+ <td class="blb">&nbsp;</td>
1088
+ <td class="blb">&nbsp;</td>
1089
+ <td class="blb">&nbsp;</td>
1090
+ <td class="blb">1</td>
1091
+ <td class="blb">1</td>
1092
+ <td class="blb">1</td>
1093
+ <td class="blb">1</td>
1094
+ </tr>
1095
+ <tr>
1096
+ <td class="bb"><a class="ref" href="#UID">uid</a></td>
1097
+ <td class="blb">0-1</td>
1098
+ <td class="blb">0-1</td>
1099
+ <td class="blb">0-1</td>
1100
+ <td class="blb">0-1</td>
1101
+ <td class="blb">&nbsp;</td>
1102
+ <td class="blb">&nbsp;</td>
1103
+ <td class="blb">&nbsp;</td>
1104
+ <td class="blb">&nbsp;</td>
1105
+ </tr>
1106
+ <tr>
1107
+ <td class="bb"><a class="ref" href="#URL">url</a></td>
1108
+ <td class="blb">0-1</td>
1109
+ <td class="blb">0-1</td>
1110
+ <td class="blb">0-1</td>
1111
+ <td class="blb">0-1</td>
1112
+ <td class="blb">&nbsp;</td>
1113
+ <td class="blb">&nbsp;</td>
1114
+ <td class="blb">&nbsp;</td>
1115
+ <td class="blb">&nbsp;</td>
1116
+ </tr>
1117
+ <tr>
1118
+ <td class="bb"><a class="ref" href="#X-PROPERTY_PROP">x-prop</a></td>
1119
+ <td class="blb">0-m</td>
1120
+ <td class="blb">0-m</td>
1121
+ <td class="blb">0-m</td>
1122
+ <td class="blb">0-m</td>
1123
+ <td class="blb">0-m</td>
1124
+ <td class="blb">0-m</td>
1125
+ <td class="blb">0-m</td>
1126
+ <td class="blb">0-m</td>
1127
+ </tr>
1128
+ </table>
1129
+ <p>
1130
+ If not set, <a href="#DTSTART">DTSTART</a> and <a href="#UID">UID</a> are created automatic by iCalcreator for <a href="#VEVENT">vevent</a>, <a href="#VTODO">vtodo</a>, <a href="#VJOURNAL">vjournal</a> and <a href="#VFREEBUSY">vfreebusy</a> components
1131
+ when using calendar functions <a href="#saveCalendar">saveCalendar</a> or <a href="#returnCalendar">returnCalendar</a> or when fetching DTSTART/UID property value with
1132
+ component function <a href="#getProperty">getProperty</a>.
1133
+ </p>
1134
+ <br />
1135
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_Component_list">[up]</a>
1136
+
1137
+ <a name="Function_list"></a><h1>3. Function list</h1>
1138
+
1139
+ <a name="Calendar_object_functions"></a><h2>3.1 Calendar object functions</h2>
1140
+
1141
+ <a name="Calendar_object_constructors"></a><h3>3.1.1 Constructors</h3>
1142
+ <a name="vcalendar"></a><h2>3.1.1.1 vcalendar</h2>
1143
+ Create a new <a href="#VCALENDAR">VCALENDAR</a> object.
1144
+ <p class="label">Format</p>
1145
+ <p class="format">vcalendar()</p>
1146
+ <p class="label">Example</p>
1147
+ <p class="example">$config = array( 'unique_id' => 'domain.org' );
1148
+ $vcalendar = new vcalendar( $config );
1149
+ ...
1150
+ </p>
1151
+ <br />
1152
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Function_list">[up]</a>
1153
+
1154
+ <a name="vevent"></a><h4>3.1.1.2 vevent</h4>
1155
+ <p class="label">Format 1</p>
1156
+ Create a new <a href="#VEVENT">VEVENT</a> object using a calendar factory-method, returning a reference to the new component.
1157
+ <p class="format">newComponent( 'vevent' )</p>
1158
+ <p class="label">Example</p>
1159
+ <p class="example">$config = array( 'unique_id' => 'domain.org' );
1160
+ $vcalendar = new vcalendar( $config );
1161
+ ...
1162
+ $vevent = & $vcalendar->newComponent( 'vevent' );
1163
+ ...
1164
+ </p>
1165
+ <p class="label">Format 2</p>
1166
+ Create a new <a href="#VEVENT">VEVENT</a> object.
1167
+ <p class="format">vevent()</p>
1168
+ <p class="label">Example</p>
1169
+ <p class="example">$config = array( 'unique_id' => 'domain.org' );
1170
+ $vcalendar = new vcalendar( $config );
1171
+ ...
1172
+ $vevent = new vevent();
1173
+ ...
1174
+ $vcalendar->setComponent( $vevent );
1175
+ // <span class="ref">required, inserts component object within calendar object</span>
1176
+ ...
1177
+ </p>
1178
+ <br />
1179
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Function_list">[up]</a>
1180
+
1181
+ <a name="vtodo"></a><h4>3.1.1.3 vtodo</h4>
1182
+ <p class="label">Format 1</p>
1183
+ Create a new <a href="#VTODO">VTODO</a> object using a calendar factory-method, returning a reference to the new component.
1184
+ <p class="format">newComponent( 'vtodo' )</p>
1185
+ <p class="label">Example</p>
1186
+ <p class="example">$config = array( 'unique_id' => 'domain.org' );
1187
+ $vcalendar = new vcalendar( $config );
1188
+ ...
1189
+ $vtodo = & $vcalendar->newComponent( 'vtodo' );
1190
+ ...
1191
+ </p>
1192
+ <p class="label">Format 2</p>
1193
+ Create a new <a href="#VTODO">VTODO</a> object.
1194
+ <p class="format">vtodo()</p>
1195
+ <p class="label">Example</p>
1196
+ <p class="example">$config = array( 'unique_id' => 'domain.org' );
1197
+ $vcalendar = new vcalendar( $config );
1198
+ ...
1199
+ $vtodo = new vtodo();
1200
+ ...
1201
+ $vcalendar->setComponent( $vtodo );
1202
+ // <span class="ref">required, inserts component object within calendar object</span>
1203
+ ...
1204
+ </p>
1205
+ <br />
1206
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Function_list">[up]</a>
1207
+
1208
+ <a name="vjournal"></a><h4>3.1.1.4 vjournal</h4>
1209
+ <p class="label">Format 1</p>
1210
+ Create a new <a href="#VJOUNAL">VJOURNAL</a> object using a calendar factory-method, returning a reference to the new component.
1211
+ <p class="format">newComponent( 'vjournal' )</p>
1212
+ <p class="label">Example</p>
1213
+ <p class="example">$config = array( 'unique_id' => 'domain.org' );
1214
+ $vcalendar = new vcalendar( $config );
1215
+ ...
1216
+ $vjournal = & $vcalendar->newComponent( 'vjournal' );
1217
+ ...
1218
+ </p>
1219
+ <p class="label">Format 2</p>
1220
+ Create a new <a href="#VJOURNAL">VJOURNAL</a> object.
1221
+ <p class="format">vjournal()</p>
1222
+ <p class="label">Example</p>
1223
+ <p class="example">$config = array( 'unique_id' => 'domain.org' );
1224
+ $vcalendar = new vcalendar( $config );
1225
+ ...
1226
+ $vjournal = new vjournal();
1227
+ ...
1228
+ $vcalendar->setComponent( $vjournal );
1229
+ ...
1230
+ </p>
1231
+ <br />
1232
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Function_list">[up]</a>
1233
+
1234
+ <a name="vfreebusy"></a><h4>3.1.1.5 vfreebusy</h4>
1235
+ <p class="label">Format 1</p>
1236
+ Create a new <a href="#VFREEBUSY">VFREEBUSY</a> object using a calendar factory-method, returning a reference to the new component.
1237
+ <p class="format">newComponent( 'vfreebusy' )</p>
1238
+ <p class="label">Example</p>
1239
+ <p class="example">$config = array( 'unique_id' => 'domain.org' );
1240
+ $vcalendar = new vcalendar( $config );
1241
+ ...
1242
+ $vfreebusy = & $vcalendar->newComponent( 'vfreebusy' );
1243
+ ...
1244
+ </p>
1245
+ <p class="label">Format 2</p>
1246
+ Create a new <a href="#VFREEBUSY">VFREEBUSY</a> object.
1247
+ <p class="format">vfreebusy()</p>
1248
+ <p class="label">Example</p>
1249
+ <p class="example">$config = array( 'unique_id' => 'domain.org' );
1250
+ $vcalendar = new vcalendar( $config );
1251
+ ...
1252
+ $vfreebusy = new vfreebusy();
1253
+ ...
1254
+ $vcalendar->setComponent( $vfreebusy );
1255
+ // <span class="ref">required, inserts component object within calendar object</span>
1256
+ ...
1257
+ </p>
1258
+ <br />
1259
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Function_list">[up]</a>
1260
+
1261
+ <a name="valarm"></a><h4>3.1.1.6 valarm</h4>
1262
+ <p class="label">Format 1</p>
1263
+ Create a new <a href="#VALARM">VALARM</a> object using a component factory-method, returning a reference to the new (sub-)component.
1264
+ <p class="format">newComponent( 'valarm' )</p>
1265
+ <p class="label">Example</p>
1266
+ <p class="example">$config = array( 'unique_id' => 'domain.org' );
1267
+ $vcalendar = new vcalendar( $config );
1268
+ ...
1269
+ $vevent = & $vcalendar->newComponent( 'vevent' );
1270
+ ...
1271
+ $valarm = & $vevent->newComponent( 'valarm' );
1272
+ ...
1273
+ </p>
1274
+ <p class="label">Format 2</p>
1275
+ Create a new <a href="#VALARM">VALARM</a> object.
1276
+ <p class="format">valarm()</p>
1277
+ <p class="label">Example</p>
1278
+ <p class="example">$config = array( 'unique_id' => 'domain.org' );
1279
+ $vcalendar = new vcalendar( $config );
1280
+ ...
1281
+ $vevent = new vevent();
1282
+ ...
1283
+ $valarm = new valarm();
1284
+ ...
1285
+ $vevent->setComponent( $valarm );
1286
+ // <span class="ref">required, inserts subcomponent object within component object</span>
1287
+ $vcalendar->setComponent( $vevent );
1288
+ // <span class="ref">required, inserts component object within calendar object</span>
1289
+ ...
1290
+ </p>
1291
+ <br />
1292
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Function_list">[up]</a>
1293
+
1294
+ <a name="vtimezone"></a><h4>3.1.1.7 vtimezone</h4>
1295
+ <p class="label">Format 1</p>
1296
+ Create a new <a href="#VTIMEZONE">VTIMEZONE</a> object using a calendar factory-method, returning a reference to the new component.
1297
+ <p class="format">newComponent( 'vtimezone' )</p>
1298
+ <p class="label">Example</p>
1299
+ <p class="example">$config = array( 'unique_id' => 'domain.org' );
1300
+ $vcalendar = new vcalendar( $config );
1301
+ ...
1302
+ $vtimezone = & $vcalendar->newComponent( 'vtimezone' );
1303
+ ...
1304
+ </p>
1305
+ <p class="label">Format 2</p>
1306
+ Create a new <a href="#VTIMEZONE">VTIMEZONE</a> object.
1307
+ <p class="format">vtimezone()</p>
1308
+ <p class="label">Example</p>
1309
+ <p class="example">$config = array( 'unique_id' => 'domain.org' );
1310
+ $vcalendar = new vcalendar( $config );
1311
+ ...
1312
+ $vtimezone = new vtimezone();
1313
+ ...
1314
+ $vcalendar->setComponent( $vtimezone );
1315
+ // <span class="ref">required, inserts component object within calendar object</span>
1316
+ ...
1317
+ </p>
1318
+ <br />
1319
+ <h5>Auto create timezone components</h5>
1320
+ It is possible to auto create timezone components, using a function in iCalUtilityFunctions class, createTimezone,
1321
+ and utilizing The PHP DateTimeZone class (PHP 5 >= 5.2.0).
1322
+ <p class="label">Format</p>
1323
+ <p class="format">iCalUtilityFunctions::createTimezone( vcalendar calendar, string timezone)</p>
1324
+ <p class="comment">calendar = vcalendar instance
1325
+ timezone = a PHP5 (DateTimeZone) valid timezone
1326
+ </p>
1327
+ <p class="label">Example</p>
1328
+ <p class="example">$config = array( 'unique_id' => 'domain.org' );
1329
+ $vcalendar = new vcalendar( $config );
1330
+ iCalUtilityFunctions::createTimezone( $vcalendar, 'Europe/Stockholm' )</p>
1331
+ will results in (when using function createCalendar/returnCalendar)
1332
+ <p class="comment">BEGIN:VTIMEZONE
1333
+ TZID:Europe/Stockholm
1334
+ BEGIN:STANDARD
1335
+ DTSTART:20101031T020000
1336
+ TZOFFSETFROM:+0200
1337
+ TZOFFSETTO:+0100
1338
+ RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
1339
+ TZNAME:CET
1340
+ END:STANDARD
1341
+ BEGIN:DAYLIGHT
1342
+ DTSTART:20100328T030000
1343
+ TZOFFSETFROM:+0100
1344
+ TZOFFSETTO:+0200
1345
+ RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3
1346
+ TZNAME:CEST
1347
+ END:DAYLIGHT
1348
+ END:VTIMEZONE</p>
1349
+ <br />
1350
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Function_list">[up]</a>
1351
+
1352
+ <a name="standard"></a><h4>3.1.1.8 standard</h4>
1353
+ <p class="label">Format 1</p>
1354
+ Create a new <a href="#VTIMEZONE">VTIMEZONE</a> <b>standard</b> object using a component factory-method, returning a reference to the new (sub-)component.
1355
+ <p class="format">newComponent( 'standard' )</p>
1356
+ <p class="label">Example</p>
1357
+ <p class="example">$config = array( 'unique_id' => 'domain.org' );
1358
+ $vcalendar = new vcalendar( $config );
1359
+ ...
1360
+ $vtimezone = & $vcalendar->newComponent( 'vtimezone' );
1361
+ ...
1362
+ $standard = & $vtimezone->newComponent( 'standard' );
1363
+ ...
1364
+ $daylight = & $vtimezone->newComponent( 'daylight' );
1365
+ ...
1366
+ </p>
1367
+ <p class="label">Format 2</p>
1368
+ Create a new <a href="#VTIMEZONE">VTIMEZONE</a> STANDARD object.
1369
+ <p class="format">vtimezone( 'standard' )</p>
1370
+ <p class="label">Example</p>
1371
+ <p class="example">$config = array( 'unique_id' => 'domain.org' );
1372
+ $vcalendar = new vcalendar( $config );
1373
+ ...
1374
+ $vtimezone = new vtimezone();
1375
+ ...
1376
+ $standard = new vtimezone( 'standard' );
1377
+ ...
1378
+ $vtimezone->setComponent( $standard );
1379
+ // <span class="ref">required, inserts subcomponent object within component object</span>
1380
+ $daylight = new vtimezone( 'daylight' );
1381
+ ...
1382
+ $vtimezone->setComponent( $daylight );
1383
+ // <span class="ref">required, inserts subcomponent object within component object</span>
1384
+ $vcalendar->setComponent( $vtimezone );
1385
+ // <span class="ref">required, inserts component object within calendar object</span>
1386
+ ...
1387
+ </p>
1388
+ <br />
1389
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Function_list">[up]</a>
1390
+
1391
+ <a name="daylight"></a><h4>3.1.1.9 daylight</h4>
1392
+ <p class="label">Format 1</p>
1393
+ Create a new <a name="VTIMEZONE">VTIMEZONE</a> <b>daylight</b> object using a component factory-method, returning a reference to the new (sub-)component.
1394
+ <p class="format">newComponent( 'standard' )</p>
1395
+ <p class="label">Example</p>
1396
+ <p class="example">$config = array( 'unique_id' => 'domain.org' );
1397
+ $vcalendar = new vcalendar( $config );
1398
+ ...
1399
+ $vtimezone = & $vcalendar->newComponent( 'vtimezone' );
1400
+ ...
1401
+ $standard = & $vtimezone->newComponent( 'standard' );
1402
+ ...
1403
+ $daylight = & $vtimezone->newComponent( 'daylight' );
1404
+ ...
1405
+ </p>
1406
+ <p class="label">Format 2</p>
1407
+ Create a new <a href="#VTIMEZONE">VTIMEZONE</a> DAYLIGHT object.
1408
+ <p class="format">vtimezone( 'daylight' )</p>
1409
+ <p class="label">Example</p>
1410
+ <p class="example"></p>
1411
+ <p class="example">$config = array( 'unique_id' => 'domain.org' );
1412
+ $vcalendar = new vcalendar( $config );
1413
+ ...
1414
+ $vtimezone = new vtimezone();
1415
+ ...
1416
+ $standard = new vtimezone( 'standard' );
1417
+ ...
1418
+ $vtimezone->setComponent( $standard );
1419
+ $daylight = new vtimezone( 'daylight' );
1420
+ ...
1421
+ $vtimezone->setComponent( $daylight );
1422
+ $vcalendar->setComponent( $vtimezone );
1423
+ ...
1424
+ </p>
1425
+ <br />
1426
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Function_list">[up]</a>
1427
+
1428
+
1429
+ <a name="Calendar_property_functions"></a><h3>3.1.2 Calendar property functions</h3>
1430
+
1431
+ <a name="deleteProperty"></a><h4>3.1.2.1 deleteProperty</h4>
1432
+ General calendar deleteProperty function, simplifying removal of calendar properties.<br />
1433
+ FALSE is returned if no property exists or when end-of-properties at consecutive function calls.
1434
+ <p class="label">Format</p>
1435
+ <p class="format">deleteProperty( [ string PropName [, int order=1 ] )</p>
1436
+ <p class="comment">propName - case independent, rfc2445 component property names,
1437
+ unknown/missing propName will be regarded as <a href="#X-PROPERTY">X-property</a>.
1438
+ order - if missing 1st/next occurrence,
1439
+ used with multiple (property) occurrences
1440
+ </p>
1441
+ <p class="label">Example 1</p>
1442
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;, &quot;filename&quot; =&gt; &quot;file.ics&quot; );
1443
+ $vcalendar = new vcalendar( $config );
1444
+ $vcalendar->parse();
1445
+ if( !$vcalendar->deleteProperty( &quot;method&quot; ))
1446
+ &nbsp;&nbsp;echo "METHOD property not found";
1447
+ .. .
1448
+ </p>
1449
+ <br />
1450
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_property_functions">[up]</a>
1451
+
1452
+ <a name="getProperty"></a><h4>3.1.2.2 getProperty</h4>
1453
+ <p class="label">Format 1</p>
1454
+ General calendar getProperty function, simplifying fetch of calendar properties.<br />
1455
+ FALSE is returned if no property exists or when end-of-properties at consecutive function calls.
1456
+ <p class="format">getProperty( [ string PropName [, int order=1 [, bool complete=FALSE ]]] )</p>
1457
+ <p class="comment">propName - case independent, rfc2445 component property names,
1458
+ unknown/missing propName will be regarded as <a href="#X-PROPERTY">X-property</a>.
1459
+ order - if missing 1st/next occurrence,
1460
+ used with multiply (property) occurrences
1461
+ complete - FALSE (default) : output only property value
1462
+ - TRUE : output =
1463
+ array( &quot;value&quot;=&gt; &lt;value&gt; ,&quot;params&quot; =&gt; &lt;parameter array&gt;)
1464
+ </p>
1465
+ <p class="label">Example 1</p>
1466
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;, &quot;filename&quot; =&gt; &quot;file.ics&quot; );
1467
+ $vcalendar = new vcalendar( $config );
1468
+ $vcalendar->parse();
1469
+ $calscale = $vcalendar->getProperty( &quot;calscale&quot; );
1470
+ .. .
1471
+ </p>
1472
+ <p class="label">Example 2</p>
1473
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;, &quot;filename&quot; =&gt; &quot;file.ics&quot; );
1474
+ $vcalendar = new vcalendar( $config );
1475
+ $vcalendar->parse();
1476
+ while( $xprop = $vcalendar->getProperty( )) { // <span class="ref">get x-properties in order.. .</span>
1477
+ .. .
1478
+ </p>
1479
+ <p class="label">Format 2</p>
1480
+ Ability to fetch specific property (unique) values and number of ocurrencies,
1481
+ <a href="#ATTENDEE">ATTENDEE</a>, <a href="#CATEGORIES">CATEGORIES</a>, <a href="#DTSTART">DTSTART</a>, <a href="#LOCATION">LOCATION</a>, <a href="#ORGANIZER">ORGANIZER</a>, <a href="#PRIORITY">PRIORITY</a>, <a href="#RESOURCES">RESOURCES</a>,
1482
+ <a href="#STATUS">STATUS</a>, <a href="#SUMMARY">SUMMARY</a>, <a href="#UID">UID</a> or &quot;RECURRENCE-ID-UID&quot; (alt. &quot;R-UID&quot; ) from <b>ALL</b> components within calendar.<br />
1483
+ Outputs an array( *[&lt;unique-property-value&gt; =&gt; &lt;number of ocurrency&gt;] )<br />or an empty array if no hits.<br />
1484
+ If a property contains multiple values (ex. &quot;RESOURCES:pc,developer&quot; or &quot;CATAGORIES:course1,courseB&quot;), they are split into unique values.
1485
+ <p class="format">getProperty( string PropName )</p>
1486
+ <p class="comment">propName - case independent, above
1487
+ <a href="#DTSTART">DTSTART</a> as argument returns dates, in format &quot;YYYYMMDD&quot;,
1488
+ &quot;RECURRENCE-ID-UID&quot;returns <a href="#UID">UID</a> values for component(-s) where <a href="#RECURRENCE-ID">RECURRENCE-ID</a> is set.
1489
+ <a href="#ATTENDEE">ATTENDEE</a> and <a href="#ORGANIZER">ORGANIZER</a> values are prefixed by protocol ex.&quot;MAILTO:chair@ical.net&quot;.
1490
+ </p>
1491
+ <br />
1492
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_property_functions">[up]</a>
1493
+
1494
+ <a name="setProperty"></a><h4>3.1.2.3 setProperty</h4>
1495
+ General calendar setProperty function,simplifying insert of calendar properties.<br />
1496
+ A successful update returns TRUE.
1497
+ <p class="label">Format</p>
1498
+ <p class="format">setProperty( string PropName, mixed Proparg_1 *[, mixed Proparg_n] )</p>
1499
+ propName case independent, strict rfc2445 calendar property names, unknown propName will be regarded as <a href="#X-PROPERTY">X-property</a>.
1500
+ <p class="label">Example</p>
1501
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;, &quot;filename&quot; =&gt; &quot;file.ics&quot; );
1502
+ $vcalendar = new vcalendar( $config ); // <span class="ref">initiate new CALENDAR</span>
1503
+ $vcalendar->setProperty( &quot;calscale&quot;, &quot;GREGORIAN&quot; );
1504
+ </p>
1505
+ <br />
1506
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_property_functions">[up]</a>
1507
+
1508
+ <a name="CALSCALE"></a><h4>3.1.2.4 CALSCALE</h4>
1509
+ This property defines the calendar scale used for the calendar information specified in the iCalendar object.
1510
+ <br /><br />
1511
+ The default value is &quot;GREGORIAN&quot;, implied when missing.
1512
+ <h5>Delete CALSCALE</h5>
1513
+ Remove CALSCALE from component.
1514
+ <p class="label">Format</p>
1515
+ <p class="format">deleteProperty( &quot;calscale&quot; )</p>
1516
+ <p class="label">Example</p>
1517
+ <p class="example">$vcalendar->deleteProperty( &quot;CALSCALE&quot; );</p>
1518
+ <h5>Get Calscale</h5>
1519
+ Fetch property value.
1520
+ <p class="label">Format</p>
1521
+ <p class="format">getProperty( &quot;calscale&quot; )</p>
1522
+ <p class="label">Example</p>
1523
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;, &quot;filename&quot; =&gt; &quot;file.ics&quot; );
1524
+ $vcalendar = new vcalendar( $config );
1525
+ $vcalendar->parse();
1526
+ $calscale = $vcalendar->getProperty( &quot;calscale&quot; );
1527
+ .. .
1528
+ </p>
1529
+ <h5>Set CALSCALE</h5>
1530
+ Insert property value.
1531
+ <p class="label">Format</p>
1532
+ <p class="format">setProperty( &quot;calscale&quot;, string value )</p>
1533
+ <p class="label">Example</p>
1534
+ <p class="example">
1535
+ $config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot; );
1536
+ $vcalendar = new vcalendar( $config ); // <span class="ref">initiate new CALENDAR</span>
1537
+ $vcalendar->setProperty( &quot;calscale&quot;, &quot;GREGORIAN&quot; );
1538
+ .. .
1539
+ </p>
1540
+ <br />
1541
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_property_functions">[up]</a>
1542
+
1543
+
1544
+ <a name="METHOD"></a><h4>3.1.2.5 METHOD</h4>
1545
+ This property defines the iCalendar object method associated with the calendar object.
1546
+ <br /><br />
1547
+ METHOD property (value PUBLISH etc.) may be required when importing iCal files
1548
+ into some calendaring software (MS etc.), as well as <a href="#X-PROPERTY">x-properties</a>
1549
+ "X-WR-CALNAME", "X-WR-CALDESC" and "X-WR-TIMEZONE"
1550
+ and (auto created) <a href="#DTSTAMP">DTSTAMP</a> and <a href="#UID">UID</a> properties.
1551
+ <h5>Delete METHOD</h5>
1552
+ Remove METHOD from component.
1553
+ <p class="label">Format</p>
1554
+ <p class="format">deleteProperty( &quot;METHOD&quot; )</p>
1555
+ <p class="label">Example</p>
1556
+ <p class="example">$vcalendar->deleteProperty( &quot;METHOD&quot; );</p>
1557
+ <h5>Get METHOD</h5>
1558
+ Fetch property value.
1559
+ <p class="label">Format</p>
1560
+ <p class="format">getProperty( &quot;method&quot; );</p>
1561
+ <p class="label">Example</p>
1562
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot; );
1563
+ $vcalendar = new vcalendar( $config );
1564
+ $vcalendar->parse();
1565
+ $method = $vcalendar->getProperty( &quot;method&quot; )
1566
+ .. .
1567
+ </p>
1568
+ <h5>Set METHOD</h5>
1569
+ Insert property value.
1570
+ <p class="label">Format</p>
1571
+ <p class="format">setProperty( &quot;method&quot;, string value )</p>
1572
+ <p class="label">Example</p>
1573
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot; );
1574
+ $vcalendar = new vcalendar( $config ); // <span class="ref">initiate new CALENDAR</span>
1575
+ $vcalendar->setProperty( &quot;method&quot;, &quot;PUBLISH&quot; )
1576
+ </p>
1577
+ <br />
1578
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_property_functions">[up]</a>
1579
+
1580
+
1581
+ <a name="VERSION"></a><h4>3.1.2.6 VERSION</h4>
1582
+ This property specifies the identifier corresponding to the highest version number or the minimum
1583
+ and maximum range of the iCalendar specification that is required in order to interpret the iCalendar object.<br />
1584
+ This property is always placed first in the calendar file.<br />
1585
+ <h5>Get Version</h5>
1586
+ Fetch property value.
1587
+ <p class="label">Format</p>
1588
+ <p class="format">getProperty( &quot;version&quot; )</p>
1589
+ <p class="label">Example</p>
1590
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;, &quot;filename&quot; =&gt; &quot;file.ics&quot; );
1591
+ $vcalendar = new vcalendar( $config );
1592
+ $vcalendar->parse();
1593
+ $version = $vcalendar->getProperty( &quot;version&quot; )
1594
+ .. .
1595
+ </p>
1596
+ <h5>Set Version</h5>
1597
+ Insert property value.
1598
+ Only version 2.0 valid, version is <b>AUTO</b> generated at calendar creation.
1599
+ <p class="label">Format</p>
1600
+ <p class="format">setProperty( &quot;version&quot;, string version )</p>
1601
+ <p class="label">Example</p>
1602
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot; );
1603
+ $vcalendar = new vcalendar( $config ); // <span class="ref">initiate new CALENDAR</span>
1604
+ $vcalendar->setProperty( &quot;version&quot;, &quot;2.0&quot; )
1605
+ </p>
1606
+ <br />
1607
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_property_functions">[up]</a>
1608
+
1609
+ <a name="X-PROPERTY"></a><h4>3.1.2.7 X-PROPERTY</h4>
1610
+ A calendar, non-standard property with a TEXT value and a name with an &quot;X-&quot; prefix. In a calendar,
1611
+ an x-prop, with an unique name, can occur only once but the number of x-props are unlimited.
1612
+ <br /><br />
1613
+ X-properties "X-WR-CALNAME", "X-WR-CALDESC" and "X-WR-TIMEZONE" may be required when importing iCal files
1614
+ into some calendaring software (MS etc.), as well as <a href="#METHOD">METHOD</a> property (value PUBLISH etc.)
1615
+ and (auto created) <a href="#DTSTAMP">DTSTAMP</a> and <a href="#UID">UID</a> properties.
1616
+ <h5>Delete X-PROPERTY</h5>
1617
+ Remove X-PROPERTY from calendar.
1618
+ <p class="label">Format</p>
1619
+ <p class="format">deleteProperty( &quot;&lt;X-PROPERTY&gt;&quot; )</p>
1620
+ <p class="label">Example 1</p>
1621
+ <p class="example">$vcalendar->deleteProperty( &quot;&lt;X-PROPERTY&gt;&quot; );</p>
1622
+ <p class="label">Example 2</p>
1623
+ Deleting all x-properties.
1624
+ <p class="example">while( $vcalendar->deleteProperty())
1625
+ continue;</p>
1626
+ <h5>Get X-PROPERTY</h5>
1627
+ Fetch property value.
1628
+ <p class="label">Format</p>
1629
+ <p class="format">getProperty()<br />
1630
+ getProperty( &quot;&lt;X-PROPERTY&gt;&quot; )</p>
1631
+ <p class="comment">output = array( propertyName<span class="ref">1</span>, propertyData<span class="ref">2</span> )</p>
1632
+ <p class="format">getProperty( FALSE, propOrderNo/FALSE, TRUE )</p>
1633
+ <p class="comment">output = array( propertyName<span class="ref">1</span>
1634
+ , array( &quot;value&quot; =&gt; propertyData<span class="ref">2</span> )
1635
+ , &quot;params&quot; =&gt; params<span class="ref">&nbsp;3</span>))
1636
+ </p>
1637
+ <p class="label">Example 1</p>
1638
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;, &quot;filename&quot; =&gt; &quot;file.ics&quot; );
1639
+ $vcalendar = new vcalendar( $config );
1640
+ $vcalendar->parse();
1641
+ while( $xprop = $vcalendar->getProperty( )) { //<span class="ref">read all x-props in a loop</span>
1642
+ .. .
1643
+ </p>
1644
+ <p class="comment">$xprop = array( propertyName<span class="ref">1</span>, propertyData<span class="ref">2</span> )</p>
1645
+ <p class="label">Example 2</p>
1646
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;, &quot;filename&quot; =&gt; &quot;file.ics&quot; );
1647
+ $vcalendar = new vcalendar( $config );
1648
+ $vcalendar->parse();
1649
+ if( $xprop = $vcalendar->getProperty( &quot;X-WR-TIMEZONE&quot; )) {
1650
+ //<span class="ref">if exists, read X-WR-TIMEZONE x-prop</span>
1651
+ .. .
1652
+ </p>
1653
+ <p class="comment">$xprop = array( &quot;X-WR-TIMEZONE&quot;, propertyData<span class="ref">2</span> )</p>
1654
+ <p class="label">Example 3</p>
1655
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;, &quot;filename&quot; =&gt; &quot;file.ics&quot; );
1656
+ $vcalendar = new vcalendar( $config );
1657
+ $vcalendar->parse();
1658
+ while( $xprop = $vcalendar->getProperty( FALSE, FALSE, TRUE )) {
1659
+ .. .
1660
+ </p>
1661
+ <p class="comment">$xprop = array( propertyName<span class="ref">1</span>
1662
+ , array( &quot;value &quot; =&gt; propertyData<span class="ref">2</span> )
1663
+ , &quot;params &quot;=&gt; params<span class="ref">&nbsp;3</span> )
1664
+ </p>
1665
+ <h5>Set X-PROPERTY</h5>
1666
+ Insert property name and value. If an x-prop with the same name already exists, it will be replaced.
1667
+ PropertyNames are always stored upperCase, ex. x-wr-calname =&gt; X-WR-CALNAME.
1668
+ <p class="label">Format</p>
1669
+ <p class="format">setProperty( propertyName, propertyData [, params ] )</p>
1670
+ <p class="comment">propertyName<span class="ref">1</span> = Any property name with a &quot;X-&quot; prefix
1671
+ propertyData<span class="ref">2</span> = Value type TEXT
1672
+ params<span class="ref">3</span> = array( [&quot;LANGUAGE&quot; =&gt; &quot;&lt;lang&gt;&quot;] [, xparam] )
1673
+ xparam = *[ xparamkey =&gt; xparamvalue ]
1674
+ propOrderNo = int ordernumber, 1=1st, 2=2nd etc</p>
1675
+ </p>
1676
+ <p class="label">Example</p>
1677
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot; );
1678
+ $vcalendar = new vcalendar( $config ); // initiate new CALENDAR
1679
+ // <span class="ref">set some X-properties.. .</span>
1680
+ $vcalendar->setProperty( &quot;x-wr-calname&quot;, &quot;Calendar Sample&quot; )
1681
+ $vcalendar->setProperty( &quot;X-WR-CALDESC&quot;, &quot;Calendar Description&quot; );
1682
+ $vcalendar->setProperty( &quot;X-WR-TIMEZONE&quot;, &quot;Europe/Stockholm&quot; );
1683
+ </p>
1684
+ <br />
1685
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_property_functions">[up]</a>
1686
+
1687
+ <a name="Calendar_component_functions"></a><h3>3.1.3 Calendar component functions</h3>
1688
+
1689
+ <a name="deleteComponent"></a><h4>3.1.3.1 deleteComponent</h4>
1690
+ Remove component from calendar.<br />
1691
+ FALSE is returned if no property exists or when end-of-properties at consecutive function calls.
1692
+ <p class="label">format 1</p>
1693
+ Remove component with order number (1st=1, 2nd=2.. .).
1694
+ <p class="format">deleteComponent( int orderNumber )</p>
1695
+ <p class="label">format 2</p>
1696
+ Remove component with component type (e.g. &quot;vevent&quot;) and order 1 alt. suborder number.
1697
+ <p class="format">deleteComponent( string componentType [, int componentSuborderNumber])</p>
1698
+ <p class="label">format 3</p>
1699
+ Remove component with <a href="#UID">UID</a>. N.B <a href="#UID">UID</a> is NOT set for
1700
+ <a href="#VALARM">ALARM</a> / <a href="#VTIMEZONE">TIMEZONE</a> components.
1701
+ <p class="format">deleteComponent( string <a href="#UID">UID</a> )</p>
1702
+ <p class="label">Example 1</p>
1703
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;, &quot;filename&quot; =&gt; &quot;file.ics&quot; );
1704
+ $vcalendar = new vcalendar( $config );
1705
+ $vcalendar->parse();
1706
+ $vcalendar->deleteComponent( 1 );
1707
+ $vcalendar->deleteComponent( &quot;vtodo&quot;, 2 );
1708
+ $vcalendar->deleteComponent( &quot;20070803T194810CEST-0123U3PXiX@domain.com&quot;);
1709
+ .. .
1710
+ </p>
1711
+ <p class="label">Example 2</p>
1712
+ Deleting all components, using format 2 without order number.
1713
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;, &quot;filename&quot; =&gt; &quot;file.ics&quot; );
1714
+ $vcalendar = new vcalendar( $config );
1715
+ $vcalendar->parse();
1716
+ .. .
1717
+ while( $vcalendar->deleteComponent( &quot;vevent&quot;))
1718
+ continue;
1719
+ .. .
1720
+ $vtodo = $vcalendar->getComponent( 'vtodo' );
1721
+ while( $vtodo->deleteComponent( &quot;valarm&quot;))
1722
+ continue;
1723
+ .. .
1724
+ </p>
1725
+ <br />
1726
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_functions">[up]</a>
1727
+
1728
+ <a name="getComponent"></a><h4>3.1.3.2 getComponent</h4>
1729
+ Get component from calendar.<br />
1730
+ FALSE is returned if no property exists or when end-of-properties at consecutive function calls.
1731
+
1732
+ <p class="label">format 1</p>
1733
+ Get next component, until end-of-components.
1734
+ <p class="format">getComponent()</p>
1735
+
1736
+ <p class="label">format 2</p>
1737
+ Get specific component with order number (1st=1, 2nd=2.. .).
1738
+ <p class="format">getComponent( int orderNumber )</p>
1739
+
1740
+ <p class="label">format 3</p>
1741
+ Get (first/next) component with component type (until end-of-components) alt.
1742
+ get specific component with component type and suborder number (1st=1, 2nd=2.. .).
1743
+ <p class="format">getComponent( string componentType [, int componentSuborderNumber])</p>
1744
+
1745
+ <p class="label">format 4</p>
1746
+ Get (first/next) component with <a href="#UID">UID</a> as key. (<a href="#UID">UID</a> is NOT set for
1747
+ <a href="#VALARM">ALARM</a> / <a href="#VTIMEZONE">TIMEZONE</a> components.)
1748
+ <p class="format">getComponent( string <a href="#UID">UID</a> )</p>
1749
+
1750
+ <p class="label">format 5</p>
1751
+ Get (first/next) component based on specific property contents;
1752
+ <a href="#DTSTART">DTSTART</a>, <a href="#DTEND">DTEND</a>, <a href="#DUE">DUE</a>, <a href="#CREATED">CREATED</a>, <a href="#COMPLETED">COMPLETED</a>, <a href="#DTSTAMP">DTSTAMP</a>, <a href="#LAST-MODIFIED">LAST-MODIFIED</a>, <a href="#RECURRENCE-ID">RECURRENCE-ID</a>,
1753
+ <a href="#ATTENDEE">ATTENDEE</a>, <a href="#CATEGORIES">CATEGORIES</a>, <a href="#LOCATION">LOCATION</a>, <a href="#ORGANIZER">ORGANIZER</a>, <a href="#PRIORITY">PRIORITY</a>, <a href="RESOURCES">RESOURCES</a>, <a href="STATUS">STATUS</a>, <a href="#SUMMARY">SUMMARY</a>, <a href="#UID">UID</a>.
1754
+ For the property &quot;SUMMARY&quot; ,if a search value (any case) exists within property value, a hit exists.
1755
+ For the other, non-date, properties an exact (strict case) match is required.<br />
1756
+ Note, <a href="#ATTENDEE">ATTENDEE</a> and <a href="#ORGANIZER">ORGANIZER</a> values must be prefixed by protocol ex.&quot;MAILTO:chair@ical.net&quot;.
1757
+
1758
+ <p class="format">getComponent( array(*[string propertyName =&gt; string uniqueValue] ))</p>
1759
+ <p class="comment">propertyName = property name, above
1760
+ propertyData = unique property value (strict case),
1761
+ date format &quot;YYYYMMDD&quot; (if any side is DATE, only dates are used),
1762
+ datetime format &quot;YYYYMMDDTHHMMSS&quot;
1763
+ </p>
1764
+ <p class="label">Example 1</p>
1765
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;, &quot;filename&quot; =&gt; &quot;file.ics&quot; );
1766
+ $vcalendar = new vcalendar( $config );
1767
+ $vcalendar->parse();
1768
+ while( $comp = $vcalendar->getComponent()) {
1769
+ .. .
1770
+ }
1771
+ .. .
1772
+ </p>
1773
+ <p class="label">Example 2</p>
1774
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;, &quot;filename&quot; =&gt; &quot;file.ics&quot; );
1775
+ $vcalendar = new vcalendar( $config );
1776
+ $vcalendar->parse();
1777
+ if( $comp = $vcalendar->getComponent( 1 )) {
1778
+ .. .
1779
+ }
1780
+ .. .
1781
+ </p>
1782
+ <p class="label">Example 3</p>
1783
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;, &quot;filename&quot; =&gt; &quot;file.ics&quot; );
1784
+ $vcalendar = new vcalendar( $config );
1785
+ $vcalendar->parse();
1786
+ if( $comp = $vcalendar->getComponent( &quot;vtodo&quot;, 2 ) {
1787
+ .. .
1788
+ }
1789
+ .. .
1790
+ </p>
1791
+ <p class="label">Example 4</p>
1792
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;, &quot;filename&quot; =&gt; &quot;file.ics&quot; );
1793
+ $vcalendar = new vcalendar( $config );
1794
+ $vcalendar->parse();
1795
+ $uid = &quot;20070803T194810CEST-0123U3PXiX@domain.com&quot;;
1796
+ if($comp = $vcalendar->getComponent( $uid ){
1797
+ .. .
1798
+ }
1799
+ .. .
1800
+ </p>
1801
+ <br />
1802
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_functions">[up]</a>
1803
+
1804
+ <a name="newComponent"></a><h4>3.1.3.3 newComponent</h4>
1805
+ Create component (<a href="#VEVENT">EVENT</a> / <a href="#VTODO">VTODO</a> / <a href="#VJOURNAL">VJOURNAL</a> / <a href="#VFREEBUSY">VFREEBUSY</a> / <a href="#VTIMEZONE">VTIMEZONE</a>)
1806
+ using a calendar factory-method, returning a reference to the new component.
1807
+ <p class="label">Format</p>
1808
+ <p class="format">newComponent( string componentType )</p>
1809
+ <p class="label">Example</p>
1810
+ <p class="example">$config = array( 'unique_id' => 'domain.org' );
1811
+ $vcalendar = new vcalendar( $config );
1812
+ ...
1813
+ $vevent = & $vcalendar->newComponent( 'vevent' );
1814
+ ...
1815
+ </p>
1816
+
1817
+ <br />
1818
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_functions">[up]</a>
1819
+
1820
+ <a name="selectComponents"></a><h4>3.1.3.4 selectComponents</h4>
1821
+ <p class="label">Format 1</p>
1822
+ Selects <a href="#VEVENT">EVENT</a> / <a href="#VTODO">VTODO</a> / <a href="#VJOURNAL">VJOURNAL</a> / <a href="#VFREEBUSY">VFREEBUSY</a> components from calendar on based on <i>dates</i> (notice <a href="#date_restriction">date restriction</a>), based on the initial <a href="#DTSTART">DTSTART</a> property
1823
+ along with the <a href="#RRULE">RRULE</a>, <a href="#RDATE">RDATE</a>, <a href="#EXDATE">EXDATE</a> and <a href="#EXRULE">EXRULE</a> properties in the component.
1824
+ If property <a href="#DTSTART">DTSTART</a> is missing in a <a href="#VTODO">VTODO</a> component then <a href="#DTSTART">DUE</a> is used.<br />
1825
+ <br />
1826
+ Limitation; if using component properties <a href="#UID">UID</a> in combination with <a href="#SEQUENCE">SEQUENCE</a> and <a href="#RECURRENCE-ID">RECURRENCE-ID</a> (i.e an individual instance within the recurrence set),
1827
+ the use of recurrence-id parameter &quot;RANGE&quot; (&quot;THISANDPRIOR&quot; and/or &quot;THISANDFUTURE&quot;) has no effect.<br />
1828
+ <br />
1829
+ This function requires calendar components in order, i.e. execute <a href="#sort">sort</a> before &quot;selectComponents&quot;, notice example below.<br />
1830
+ <br />
1831
+ FALSE is returned if no selected component exists.
1832
+ <p class="format">selectComponents([ int startYear, int startMonth, int startDay
1833
+ [, int endYear, int endMonth, int endDay
1834
+ [, mixed cType [, bool flat [,bool any [,bool split]]]]]])
1835
+ </p>
1836
+ Returns an array with components (events.. .).
1837
+ For all recurrent instances of a calendar component, an x-property,
1838
+ &quot;X-CURRENT-DTSTART&quot; and opt. also &quot;X-CURRENT-DTEND&quot; alt. &quot;X-CURRENT-DUE&quot;,
1839
+ has been created with a TEXT content, &quot;Y-m-d&nbsp;[H:i:s][timezone/UTC&nbsp;offset]&quot;
1840
+ showing the current start and opt. also end alt. due date.<br />
1841
+ Also a &quot;X-RECURRENCE&quot; x-property is set with order number (valid if selectComponents is called from DTSTART date).
1842
+ <p class="comment">startYear : start year (4*digit), default current year
1843
+ startMonth : start month (1-2*digit), default current month
1844
+ startDay : start day (1-2*digit), default current day
1845
+ endYear : end year (4*digit), default startYear
1846
+ endMonth : end month (-2*digit), default startMonth
1847
+ endDay : end day (1-2*digit), default startDay
1848
+ cType : calendar component type(-s), string/array
1849
+ ('vevent', 'vtodo', 'vjournal', 'vfreebusy')
1850
+ FALSE (default) all
1851
+ flat : TRUE =&gt; output : array[] (ignores split)
1852
+ FALSE (default) =&gt;
1853
+ output : array[Year][Month][Day][]
1854
+ any : TRUE (default) -
1855
+ select component that occurs within period
1856
+ FALSE -
1857
+ only components that starts (DTSTART) within period
1858
+ split : TRUE (default) -
1859
+ one component copy for every day it occurs
1860
+ within the period (implies flat=FALSE)
1861
+ FALSE - one occurrence of component in output array
1862
+ ,start date/recurrence date
1863
+ </p>
1864
+ <p class="label">Example</p>
1865
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;,
1866
+ &quot;directory&quot; =&gt; &quot;import&quot;,
1867
+ &quot;filename&quot; =&gt; &quot;file.ics&quot; );
1868
+ $vcalendar = new vcalendar( $config );
1869
+ $vcalendar->parse();
1870
+ $vcalendar->sort();
1871
+ $events_arr = $vcalendar->selectComponents( 2007,11,1,2007,11,30,'vevent');
1872
+ // <span class="comment">select all events occurring 1-30 nov. 2007</span>
1873
+ foreach( $events_arr as $year =&gt; $year_arr ) {
1874
+ foreach( $year_arr as $month =&gt; $month_arr ) {
1875
+ foreach( $month_arr as $day =&gt; $day_arr ) {
1876
+ foreach( $day_arr as $event ) {
1877
+ $currddate = $event->getProperty( 'x-current-dtstart' );
1878
+ <span class="comment">// if member of a recurrence set, returns
1879
+ // array(' x-current-dtstart',
1880
+ // &lt;(string) date(&quot;Y-m-d&nbsp;[H:i:s][timezone/UTC&nbsp;offset]&quot;)&gt;)</span>
1881
+ $startDate = $event->getProperty( 'dtstart' );
1882
+ $summary = $event->getProperty( 'summary' );
1883
+ $description = $event->getProperty( 'description' );
1884
+ .. .
1885
+ </p>
1886
+ <p class="label">format 2</p>
1887
+ Using this format, the function selects components based on specific property value(-s),
1888
+ <a href="#ATTENDEE">ATTENDEE</a>, <a href="#CATEGORIES">CATEGORIES</a>, <a href="#LOCATION">LOCATION, <a href="#ORGANIZER">ORGANIZER</a>, <a href="#PRIORITY">PRIORITY</a>, <a href="#RESOURCES">RESOURCES</a>, <a href="#STATUS">STATUS</a>, <a href="#SUMMARY">SUMMARY</a> or <a href="#UID">UID</a>.
1889
+ For the property &quot;SUMMARY&quot; ,if a search value (any case) exists within property value, a hit exists.
1890
+ For the other properties an exact (strict case) match is required.<br />
1891
+ <a href="#ATTENDEE">ATTENDEE</a> and <a href="#ORGANIZER">ORGANIZER</a> search values must be prefixed by protocol ex. &quot;MAILTO:chair@ical.net&quot;.
1892
+ Multiple search properties may coexist.
1893
+ <p class="format">selectComponents( searchArray )</p>
1894
+ Outputs an array of matched (unique) components in <a href="#UID">UID</a> order.
1895
+ <p class="comment">searchArray : array( propertyName =&gt; propertyValue )
1896
+ propertyName : above (any case)
1897
+ propertyValue : string value / array( *[string value] )
1898
+ </p>
1899
+ <p class="label">Example</p>
1900
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;,
1901
+ &quot;directory&quot; =&gt; &quot;import&quot;,
1902
+ &quot;filename&quot; =&gt; &quot;file.ics&quot; );
1903
+ $vcalendar = new vcalendar( $config );
1904
+ $vcalendar->parse();
1905
+ $vcalendar->sort();
1906
+ $searchArray = array( &quot;PRIORITY&quot; =&gt; array( 1, 2, 3, 4, 5 ));
1907
+ $mediumHighPrioArr = $vcalendar->selectComponents( $searchArray );
1908
+ // <span class="comment">select all components with high (1) and medium priority</span>
1909
+ if( !empty( $mediumHighPrioArr )) {
1910
+ $mediumHighPrioCal = new vcalendar();
1911
+ $mediumHighPrioCal-&gt;setProperty("X-WR-CALDESC", "High-Medium events");
1912
+ foreach( $mediumHighPrioArr as $mediumHighPrioComponent )
1913
+ $mediumHighPrioCal-&gt;setComponent( $mediumHighPrioComponent );
1914
+ $mediumHighPrioCal-&gt;returnCalendar();
1915
+ }
1916
+ .. .
1917
+ </p>
1918
+ <br />
1919
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_functions">[up]</a>
1920
+
1921
+ <a name="setComponent"></a><h4>3.1.3.5 setComponent</h4>
1922
+ Replace or update component in calendar.
1923
+ Also add calendar component to calendar when calendar component is created with the procedural (<b>non</b>-factory) method,
1924
+ see example <a href="#vevent">VEVENT</a>, format 2.
1925
+ A successful update return TRUE.
1926
+ <p class="label">format 1</p>
1927
+ Insert last in component chain.
1928
+ <p class="format">setComponent( component )
1929
+ addComponent( component ) // <span class="ref">alias</span>
1930
+ </p>
1931
+ <p class="comment">addComponent, may be removed i future versions.</p>
1932
+ <p class="label">format 2</p>
1933
+ Insert/replace component with order number (1st=1, 2nd=2.. .).
1934
+ If replace and orderNumber is not found, component is inserted last in chain.
1935
+ <p class="format">setComponent( component, int orderNumber )</p>
1936
+ <p class="label">format 3</p>
1937
+ Replace component with component type and 1st alt. component order number.
1938
+ If orderNumber is not found, component is inserted last in chain.
1939
+ <p class="format">setComponent( component, string componentType [,int component suborder no])</p>
1940
+ <p class="label">format 4</p>
1941
+ Replace component with <a href="#UID">UID</a>.
1942
+ N.B <a href="#UID">UID</a> is NOT set for <a href="#VALARM">ALARM</a> / <a href="#VTIMEZONE">TIMEZONE</a> components.
1943
+ If <a href="#UID">UID</a> is not found, component is inserted last in chain.
1944
+ <p class="format">setComponent( component, string <a href="#UID">UID</a> )</p>
1945
+ <p class="label">Example</p>
1946
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;, &quot;filename&quot; =&gt; &quot;file.ics&quot; );
1947
+ $vcalendar = new vcalendar( $config );
1948
+ $vcalendar->parse();
1949
+ $vevent = vcalendar->getComponent( 1 );&nbsp;//<span class="comment">fetch first EVENT</span>
1950
+ $vevent->setProperty( &quot;dtstart&quot;&nbsp;//<span class="comment">update <a href="#DTSTART">DTSTART</a> property</span>
1951
+ , 2006, 12, 24, 19, 30, 00 );
1952
+ .. .
1953
+ $vcalendar->setComponent( $vevent, 1 ); // replace first component
1954
+ .. .
1955
+ </p>
1956
+ <br />
1957
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_functions">[up]</a>
1958
+
1959
+ <a name="Calendar_inputoutput_functions"></a><h3>3.1.4 Calendar input/output functions</h3>
1960
+
1961
+ <a name="parse_merge"></a><h4>3.1.4.1 parse and merge</h4>
1962
+ Parse iCal file(-s) or string/array calendarContent into a single vcalendar object (components, properties and parameters),
1963
+ including multiple vcalendars (within a single ICS file) parse, e.g. Oracle Calendar exports.
1964
+
1965
+ <br /><br />
1966
+ As long as php.ini directive &quot;allow_url_fopen&quot; is enabled, remote files, URLs; protocol &quot;http&quot; (&quot;webcal&quot;), are supported. A remote file, URL, <b>must</b> be prefixed by &quot;http://&quot; (&quot;webcal://&quot;) and suffixed by a valid filename.! Recommendation is to download (cache) remote file before parsing, due to execution time and control.
1967
+ <br /><br />
1968
+ If missing, component property <a href="#UID">UID</a> is created when parsing. For that reason <a href="#Unique_id">UNIQUE_ID</a> might need to be set before parsing, Se examples below.
1969
+ <br /><br />
1970
+ Notice <a href="#date_restriction">date restriction</a>!
1971
+ <br /><br />
1972
+ If parse error occurs (like file access error, invalid calendar file or calendar file without components), FALSE is returned.
1973
+ <p class="label">Format</p>
1974
+ <p class="format">parse( [ mixed textToParse ] )</p>
1975
+ <p class="comment">textToParse = string calendarContent
1976
+ ex. result from &quot;file_get_contents( 'filename')&quot;
1977
+ array calendarContent
1978
+ ex. result from &quot;file( 'filename', FILE_IGNORE_NEW_LINES )&quot;</p>
1979
+ <p class="label">parse example 1</p>
1980
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;, &quot;filename&quot; =&gt; &quot;file.ics&quot; );
1981
+ $vcalendar = new vcalendar( $config );
1982
+ $vcalendar->parse();
1983
+ .. .
1984
+ </p>
1985
+ <p class="label">parse example 2</p>
1986
+ <p class="example">
1987
+ $config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;,
1988
+ &quot;url&quot; =&gt; &quot;http://www.ical.net/calendars/calendar.ics&quot; );
1989
+ $vcalendar = new vcalendar( $config );
1990
+ $vcalendar->parse();
1991
+ .. .
1992
+ </p>
1993
+ <p class="label">parse example 3</p>
1994
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;,
1995
+ &quot;url&quot; =&gt; &quot;http://www.ical.net/calendars/calendar.ics&quot; );
1996
+ $vcalendar = new vcalendar( $config );
1997
+ ...
1998
+ $str = array(
1999
+ 'BEGIN:VCALENDAR',
2000
+ 'PRODID:-//test.org//NONSGML kigkonsult.se iCalcreator 2.10//',
2001
+ 'VERSION:2.0',
2002
+ 'BEGIN:VEVENT',
2003
+ 'DTSTART:20101224T190000Z',
2004
+ 'DTEND:20101224T200000Z',
2005
+ 'DTSTAMP:20101020T103827Z',
2006
+ 'UID:20101020T113827-1234GkdhFR@test.org',
2007
+ 'DESCRIPTION:example',
2008
+ 'END:VEVENT',
2009
+ 'END:VCALENDAR');
2010
+ $vcalendar->parse( $str );
2011
+ ...
2012
+ </p>
2013
+ <p class="label">merge example</p>
2014
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;,
2015
+ &quot;directory&quot; =&gt; &quot;import&quot; );
2016
+ $vcalendar = new vcalendar( $config );
2017
+
2018
+ $vcalendar->setConfig( &quot;filename&quot;,&nbsp;&nbsp;&quot;file1.ics&quot; );
2019
+ $vcalendar->parse();
2020
+
2021
+ $vcalendar->setConfig( &quot;filename&quot;,&nbsp;&nbsp;&quot;file2.ics&quot; );
2022
+ $vcalendar->parse();
2023
+
2024
+ $vcalendar->sort();
2025
+ $vcalendar->setConfig( &quot;directory&quot;,&nbsp;&quot;export&quot; );
2026
+ $vcalendar->setConfig( &quot;filename&quot;,&nbsp;&nbsp;&quot;icalmerge.ics&quot; );
2027
+ $vcalendar->saveCalendar();
2028
+ .. .
2029
+ </p>
2030
+ <br />
2031
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_inputoutput_functions">[up]</a>
2032
+
2033
+ <a name="createCalendar"></a><h4>3.1.4.2 createCalendar</h4>
2034
+ Generate and return calendar in a string, testing.. .?
2035
+ <p class="label">Format</p>
2036
+ <p class="format">createCalendar()</p>
2037
+ <p class="label">Example</p>
2038
+ <p class="example">.. .
2039
+ $str = $vcalendar->createCalendar();
2040
+ echo $str;
2041
+ </p>
2042
+ <br />
2043
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_inputoutput_functions">[up]</a>
2044
+
2045
+ <a name="returnCalendar"></a><h4>3.1.4.3 returnCalendar</h4>
2046
+ Redirect calendar content to user browser. Filename, addressed to browser, is auto generated if missing or not set;<br />
2047
+ <span class="format">$filename = date( &quot;YmdHis&quot; ).&quot;.ics&quot; </span><br />
2048
+ <p class="label">Format</p>
2049
+ <p class="format">returnCalendar( [bool utf8Encode [, bool gzip ]] )</p>
2050
+ <p class="comment">utf8Encode = TRUE: utf8 encoded output, FALSE: (default) no encoding
2051
+ gzip = TRUE: gzip compressed output and header 'Content-Encoding: gzip' set,
2052
+ FALSE: (default) no compressing</p>
2053
+ <p class="label">Example 1</p>
2054
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot; );
2055
+ $vcalendar = new vcalendar( $config );
2056
+ .. .
2057
+ $vevent = & $vcalendar->newComponent( 'vevent' );
2058
+ $vevent->setProperty( &quot;dtstart&quot;, array( &quot;year&quot; =&gt; 2007
2059
+ , &quot;month&quot; =&gt; 4
2060
+ , &quot;day&quot; =&gt; 1
2061
+ , &quot;hour&quot; =&gt; 19 ));
2062
+ $vevent->setProperty( &quot;duration&quot;, 0, 0, 3 ));
2063
+ $vevent->setProperty( &quot;LOCATION&quot;, &quot;Central Plaza&quot; );
2064
+ $vevent->setProperty( &quot;summary&quot;, &quot;PHP summit&quot; );
2065
+ .. .
2066
+ $vcalendar->returnCalendar();
2067
+ </p>
2068
+ <p class="label">Example 2</p>
2069
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;,
2070
+ &quot;directory&quot; =&gt; &quot;import&quot;,
2071
+ &quot;filename&quot; =&gt; &quot;file.ics&quot; );
2072
+ $vcalendar = new vcalendar( $config );
2073
+ $vcalendar->parse();
2074
+ $utf8Encode = TRUE;
2075
+ $hacPar = 'HTTP_ACCEPT_ENCODING';
2076
+ if( isset( $_SERVER[$hacPar] ) &amp;&amp;
2077
+ ( FALSE !== strpos( strtolower( $_SERVER[$hacPar] ), 'gzip' )))
2078
+ $gzip = TRUE;
2079
+ else
2080
+ $gzip = FALSE;
2081
+ $vcalendar->returnCalendar( $utf8Encode, $gzip );
2082
+ </p>
2083
+ <br />
2084
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_inputoutput_functions">[up]</a>
2085
+
2086
+ <a name="saveCalendar"></a><h4>3.1.4.4 saveCalendar</h4>
2087
+ Save ical calendar in a file, uses present directory if directory not set, filename is auto generated if missing or not set;<br />
2088
+ <span class="format">$filename = date( &quot;YmdHis&quot; ).&quot;.ics&quot; </span><br />
2089
+ Directory/filename <b>must</b> be writeable, delimiter default PHP constant DIRECTORY_SEPARATOR.
2090
+ <br /><br />
2091
+ As long as php.ini directive &quot;allow_url_fopen&quot; is enabled, remote files, URLs; protocol &quot;http&quot; (&quot;webcal&quot;), are supported. Recommendation is to save to a local file and upload later, due to execution time and control.
2092
+ <br /><br />
2093
+ If file error occurs, FALSE is returned.
2094
+ <p class="label">Format</p>
2095
+ <p class="format">saveCalendar ( string directory/FALSE
2096
+ [, string filename/FALSE
2097
+ [, string delimiter/FALSE ]] )
2098
+ </p>
2099
+ Parameters for <span class="format">directory/filename/delimiter</span>, kept for backward compatibility,
2100
+ may be removed i future versions. Recommendation is to use <span class="format">setConfig</span>, Se
2101
+ example below.
2102
+ <p class="label">Example</p>
2103
+ <p class="example">.. .
2104
+ $vcalendar->setConfig( array( &quot;directory&quot; =&gt; &quot;depot&quot;,
2105
+ &quot;filename&quot; =&gt; &quot;calendar.ics&quot; ));
2106
+ $result = $vcalendar->saveCalendar();
2107
+ if( !$result )
2108
+ &nbsp;&nbsp;echo &quot;error when saving.. .&quot;
2109
+ </p>
2110
+ <br />
2111
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_inputoutput_functions">[up]</a>
2112
+
2113
+ <a name="sort"></a><h4>3.1.4.5 sort</h4>
2114
+ <p class="label">Format 1</p>
2115
+ Sort created/parsed calendar components on the following (prioritized) keys:<br />
2116
+ 1 - X-CURRENT-DTSTART - X-CURRENT-DTEND/X-CURRENT-DUE<br />
2117
+ &nbsp;&nbsp;&nbsp;&nbsp;(if created in function <a href="#selectComponents">selectComponents</a>)<br />
2118
+ 1 - <a href="#DTSTART">DTSTART</a> - <a href="#DTEND">DTEND</a> alt. <a href="#DURATION">DURATION</a> (<a href="#VEVENT">VEVENT</a> and <a href="#VFREEBUSY">VFREEBUSY</a> components)<br />
2119
+ 1 - <a href="#DTSTART">DTSTART</a> - <a href="#DUE">DUE</a> alt. <a href="#DURATION">DURATION</a> (<a href="#VTODO">VTODO</a> components)<br />
2120
+ 1 - <a href="#DTSTART">DTSTART</a> (<a href="#VJOURNAL">VJOURNAL</a> components)<br />
2121
+ 2 - <a href="#CREATED">CREATED</a> / <a href="#DTSTAMP">DTSTAMP</a><br />
2122
+ 3 - <a href="#UID">UID</a><br />
2123
+ <a href="#VTIMEZONE">VTIMEZONE</a> component(-s) are always sorted first in chain.<br />
2124
+ Sub-components (<a href="#VTIMEZONE">STANDARD</a>&nbsp;/&nbsp;<a href="#VTIMEZONE">DAYLIGHT</a>&nbsp;/&nbsp;<a href="#VALARM">ALARM</a>), if exists, are not sorted.
2125
+ <p class="format">sort()</p>
2126
+ <p class="label">Example</p>
2127
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;,
2128
+ &quot;directory&quot; =&gt; &quot;import&quot;,
2129
+ &quot;filename&quot; =&gt; &quot;file.ics&quot; );
2130
+ $vcalendar = new vcalendar( $config );
2131
+ $vcalendar->parse();
2132
+ $vcalendar->sort();
2133
+ $vcalendar->returnCalendar();
2134
+ </p>
2135
+
2136
+ <p class="label">Format 2</p>
2137
+ Sort created/parsed calendar components on specific property values and ascending order.
2138
+ <p class="format">sort( sortArgument )</p>
2139
+ <p class="comment">sortArgument: &quot;<a href="#ATTENDEE">ATTENDEE</a>&quot; / &quot;<a href="#CATEGORIES">CATEGORIES</a>&quot; / &quot;<a href="#DTSTAMP">DTSTAMP</a>&quot; / &quot;<a href="#LOCATION">LOCATION"</a>&quot; /
2140
+ &quot;<a href="#ORGANIZER">ORGANIZER</a>&quot; /&quot;<a href="#RESOURCES">RESOURCES</a>&quot; / &quot;<a href="#PRIORITY">PRIORITY</a>&quot; / &quot;<a href="#STATUS">STATUS</a>&quot; / &quot;<a href="#SUMMARY">SUMMARY</a>&quot;
2141
+ for a property where multiple ocurrence may exist
2142
+ (<a href="#ATTENDEE">ATTENDEE</a>, <a href="#CATEGORIES">CATEGORIES</a>, <a href="#RESOURCES">RESOURCES</a> ),
2143
+ lowest (alphabetic) value is used as sort parameter.
2144
+ </p>
2145
+ <br />
2146
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_inputoutput_functions">[up]</a>
2147
+
2148
+ <a name="useCachedCalendar"></a><h4>3.1.4.6 useCachedCalendar</h4>
2149
+ If recent version of local (non-empty and saved) calendar file exists, an HTTP redirect header is sent otherwise FALSE is returned.
2150
+ <p class="label">Format</p>
2151
+ <p class="format">useCachedCalendar( [ int timeout ] )
2152
+ useCachedCalendar( string directory/FALSE
2153
+ , string filename/FALSE
2154
+ , string delimiter/FALSE
2155
+ [, int timeout ] )
2156
+ </p>
2157
+ <p class="comment">timeout : default 3600 sec
2158
+ Second format with parameters for <span class="format">directory/filename/delimiter</span>,<br />kept for backward compatibility, may be removed i future<br />versions. Recommendation is to use <span class="format">setConfig</span>, Se example below.</span></p>
2159
+ <p class="label">Example</p>
2160
+ <p class="example">.. .
2161
+ $vcalendar->setConfig( &quot;directory&quot;, &quot;depot&quot; );
2162
+ $vcalendar->setConfig( &quot;filename&quot;, &quot;calendar.ics&quot; );
2163
+ $vcalendar->useCachedCalendar();
2164
+ </p>
2165
+ <br />
2166
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_inputoutput_functions">[up]</a>
2167
+
2168
+ <a name="Calendar_configuration_functions"></a><h3>3.1.5 Calendar configuration functions</h3>
2169
+
2170
+ <a name="configKeys"></a><h4>3.1.5.1 configuration keys</h4>
2171
+ All configuration keys (allowEmpty, compsInfo etc.) case independent.
2172
+ <br />
2173
+ <br />
2174
+ <table>
2175
+ <tr>
2176
+ <td class="bl bb">key</td>
2177
+ <td class="bl bb">calendar</td>
2178
+ <td class="bl bb">component</td>
2179
+ <td class="bl bb">remark</td>
2180
+ </tr>
2181
+ <tr>
2182
+ <td class="bl bb"><a class="ref" href="#allowEmpty">allowEmpty</a></td>
2183
+ <td class="bl bb center">*</td>
2184
+ <td class="bl bb center">*</td>
2185
+ <td class="bl bb ref">&nbsp;</td>
2186
+ </tr>
2187
+ <tr>
2188
+ <td class="bl bb"><a class="ref" href="#Compsinfo">Compsinfo</a></td>
2189
+ <td class="bl bb center">*</td>
2190
+ <td class="bl bb center">*</td>
2191
+ <td class="bl bb ref">getConfig only</td>
2192
+ </tr>
2193
+ <tr>
2194
+ <td class="bl bb"><a class="ref" href="#Delimiter">Delimiter</a></td>
2195
+ <td class="bl bb center">*</td>
2196
+ <td class="bl bb">&nbsp;</td>
2197
+ <td class="bl bb ref">&nbsp;</td>
2198
+ </tr>
2199
+ <tr>
2200
+ <td class="bl bb"><a class="ref" href="#Directory">Directory</a></td>
2201
+ <td class="bl bb center">*</td>
2202
+ <td class="bl bb">&nbsp;</td>
2203
+ <td class="bl bb ref">&nbsp;</td>
2204
+ </tr>
2205
+ <tr>
2206
+ <td class="bl bb"><a class="ref" href="#Filename">Filename</a></td>
2207
+ <td class="bl bb center">*</td>
2208
+ <td class="bl bb">&nbsp;</td>
2209
+ <td class="bl bb ref">&nbsp;</td>
2210
+ </tr>
2211
+ <tr>
2212
+ <td class="bl bb"><a class="ref" href="#Dirfile">Dirfile</a></td>
2213
+ <td class="bl bb center">*</td>
2214
+ <td class="bl bb">&nbsp;</td>
2215
+ <td class="bl bb ref">getConfig only</td>
2216
+ </tr>
2217
+ <tr>
2218
+ <td class="bl bb"><a class="ref" href="#Filesize">Filesize</a></td>
2219
+ <td class="bl bb center">*</td>
2220
+ <td class="bl bb">&nbsp;</td>
2221
+ <td class="bl bb ref">getConfig only</td>
2222
+ </tr>
2223
+ <tr>
2224
+ <td class="bl bb"><a class="ref" href="#Format">Format</a></td>
2225
+ <td class="bl bb center">*</td>
2226
+ <td class="bl bb">&nbsp;</td>
2227
+ <td class="bl bb ref">&nbsp;</td>
2228
+ </tr>
2229
+ <tr>
2230
+ <td class="bl bb"><a class="ref" href="#Language">Language</a></td>
2231
+ <td class="bl bb center">*</td>
2232
+ <td class="bl bb center">*</td>
2233
+ <td class="bl bb ref">&nbsp;</td>
2234
+ </tr>
2235
+ <tr>
2236
+ <td class="bl bb"><a class="ref" href="#NewlineChar">NewlineChar</a></td>
2237
+ <td class="bl bb center">*</td>
2238
+ <td class="bl bb center">*</td>
2239
+ <td class="bl bb ref">&nbsp;</td>
2240
+ </tr>
2241
+ <tr>
2242
+ <td class="bl bb"><a class="ref" href="#dTZID">TZID</a></td>
2243
+ <td class="bl bb center">*</td>
2244
+ <td class="bl bb center">*</td>
2245
+ <td class="bl bb ref">&nbsp;</td>
2246
+ </tr>
2247
+ <tr>
2248
+ <td class="bl bb"><a class="ref" href="#Unique_id">Unique_id</a></td>
2249
+ <td class="bl bb center">*</td>
2250
+ <td class="bl bb center">*</td>
2251
+ <td class="bl bb ref">&nbsp;</td>
2252
+ </tr>
2253
+ <tr>
2254
+ <td class="bl bb"><a class="ref" href="#configURL">URL</a></td>
2255
+ <td class="bl bb center">*</td>
2256
+ <td class="bl bb">&nbsp;</td>
2257
+ <td class="bl bb ref">&nbsp;</td>
2258
+ </tr>
2259
+ </table>
2260
+ <br />
2261
+ <br />
2262
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_configuration_functions">[up]</a>
2263
+
2264
+ <a name="getConfig"></a><h4>3.1.5.2 getConfig</h4>
2265
+ <p class="format">getConfig( [string key )</p>
2266
+ <p class="label">Example 1</p>
2267
+ <p class="example">.. .
2268
+ $filename = $vcalendar->getConfig( 'filename' );<span class="comment">
2269
+ .. .</p>
2270
+ In this example, notice <a href="#Filename">Filename</a></span>
2271
+ <br />
2272
+ <p class="label">Example 2</p>
2273
+ <p class="example">.. .
2274
+ $config = $vcalendar->getConfig();
2275
+ .. .</p>
2276
+ <p class="comment">Output= array( string key =&gt; mixed value
2277
+ *[, string key =&gt; mixed value] )</p>
2278
+ <br />
2279
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_configuration_functions">[up]</a>
2280
+
2281
+ <a name="initConfig"></a><h4>3.1.5.3 calendar/component initialization</h4>
2282
+ <p class="label">Format</p>
2283
+ When creating a new calendar.
2284
+ <p class="format">vcalendar( array( string key =&gt; mixed value *[,string key =&gt; mixed value]))</p>
2285
+ <p class="label">Example 1</p>
2286
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;,
2287
+ &quot;directory&quot; =&gt; &quot;import&quot;,
2288
+ &quot;filename&quot; =&gt; &quot;file.ics&quot; );
2289
+ $vcalendar = new vcalendar( $config );
2290
+ .. .
2291
+ </p>
2292
+ When creating a new calendar component.
2293
+ <p class="format">component( array( string key =&gt; mixed value *[,string key =&gt; mixed value]))</p>
2294
+ <p class="label">Example 2</p>
2295
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot; );
2296
+ $vevent = new vevent( $config );
2297
+ .. .
2298
+ </p>
2299
+ <p class="label">Example 3</p>
2300
+ <p class="example">. ..
2301
+ $config = $vcalendar->getConfig();
2302
+ $vevent = new vevent( $config );
2303
+ .. .
2304
+ </p>
2305
+ Only component relevant configuration are set. If using the <a href="#newComponent">newComponent</a> function, configuration is set automatically.
2306
+ <br />
2307
+ <br />
2308
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_configuration_functions">[up]</a>
2309
+
2310
+ <a name="setConfig"></a><h4>3.1.5.4 setConfig</h4>
2311
+ A successful &quot;setConfig&quot; returns TRUE.
2312
+ <p class="label">Format 1</p>
2313
+ <p class="format">setConfig( array( string key=>mixed value *[, string key=>mixed value]))</p>
2314
+ <p class="label">Example 1</p>
2315
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;,
2316
+ &quot;directory&quot; =&gt; &quot;import&quot;,
2317
+ &quot;filename&quot; =&gt; &quot;file.ics&quot; );
2318
+ $vcalendar = new vcalendar();
2319
+ $vcalendar->setConfig( $config );
2320
+ .. .
2321
+ </p>
2322
+ <p class="label">Example 2</p>
2323
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot; );
2324
+ $vevent = new vevent();
2325
+ $vevent->setConfig( $config );
2326
+ .. .
2327
+ </p>
2328
+ <p class="label">Format 2</p>
2329
+ <p class="format">setConfig( string key, string value )</p>
2330
+ <p class="label">Example 1</p>
2331
+ <p class="example">$vcalendar = new vcalendar();
2332
+ $vcalendar->setConfig( &quot;directory&quot;, &quot;depot&quot; );
2333
+ .. .
2334
+ </p>
2335
+ <p class="label">Example 2</p>
2336
+ <p class="example">$vevent = new vevent();
2337
+ $vevent->setConfig( &quot;unique_id&quot;, &quot;domain.com&quot; );
2338
+ .. .
2339
+ </p>
2340
+ <br />
2341
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_configuration_functions">[up]</a>
2342
+
2343
+ <a name="allowEmpty"></a><h4>3.1.5.5 Allow empty components</h4>
2344
+ Allow or reject empty calendar properties, default allow (TRUE).
2345
+
2346
+ <br />
2347
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_configuration_functions">[up]</a>
2348
+
2349
+ <a name="Compsinfo"></a><h4>3.1.5.6 Component information</h4>
2350
+ Only to use with function getConfig.<br/>
2351
+ <br />
2352
+ Get information about calendar components. Returns array with basic information
2353
+ about all components (in array format) within calendar.
2354
+ <p class="comment">Output = array ( *compinfo )
2355
+ compinfo = array ( &quot;ordno&quot; =&gt; int ordno,
2356
+ // <span class="ref">order number (1st=1, 2nd=2..)</span>
2357
+ , &quot;type&quot; =&gt; string type
2358
+ // <span class="ref">component type (vevent, vtodo.. .</span>
2359
+ , &quot;uid&quot; =&gt; string uid
2360
+ // <span class="ref">component <a href="#UID">UID</a> (not for <a href="#VALARM">ALARM</a> / <a href="#VTIMEZONE">TIMEZONE</a>)</span>
2361
+ , &quot;props&quot; =&gt;
2362
+ array( *[ propertyName =&gt; Property count ])
2363
+ // <span class="ref">for every set property</span>
2364
+ , &quot;sub&quot; =&gt; array( *compinfo ))
2365
+ // <span class="ref">if subcomponents exists, an array for each subcomponent</span></p>
2366
+ <p class="label">Example</p>
2367
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;,
2368
+ &quot;directory&quot; =&gt; &quot;import&quot;,
2369
+ &quot;filename&quot; =&gt; &quot;file.ics&quot; );
2370
+ $vcalendar = new vcalendar( $config );
2371
+ $vcalendar->parse();
2372
+ $compsinfo = $vcalendar->getConfig( &quot;compsinfo&quot; );
2373
+ foreach( $compsinfo as compinfo) {
2374
+ &nbsp;echo &quot; order number : &quot;.$compinfo[&quot;ordno&quot;].&quot;&lt;br&nbsp;/&gt;&quot;;
2375
+ &nbsp;echo &quot; type : &quot;.$compinfo[&quot;type&quot;].&quot;&lt;br&nbsp;/&gt;&quot;;
2376
+ &nbsp;echo &quot; UID : &quot;.$compinfo[&quot;uid&quot;].&quot;&lt;br&nbsp;/&gt;&quot;;
2377
+ &nbsp;foreach( $compinfo[&quot;props&quot;] as $propertyName =&gt; $propertyCount )
2378
+ &nbsp;&nbsp;echo &quot; $propertyName = $propertyCount&quot;;
2379
+ &nbsp;if( is_array( $compinfo[&quot;sub&quot;] )) {
2380
+ &nbsp;&nbsp;foreach( $compinfo[&quot;sub&quot;] as $subcompinfo ) {
2381
+ &nbsp;&nbsp;&nbsp;echo &quot; order number : &quot;.$subcompinfo[&quot;ordno&quot;].&quot;&lt;br&nbsp;/&gt;&quot;;
2382
+ &nbsp;&nbsp;&nbsp;/* .. dito if subcomponents exists .. . */
2383
+ &nbsp;&nbsp;}
2384
+ &nbsp;}
2385
+ }
2386
+ </p>
2387
+ <br />
2388
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_configuration_functions">[up]</a>
2389
+
2390
+ <a name="Delimiter"></a><h4>3.1.5.7 Delimiter</h4>
2391
+ Directory/filename delimiter.
2392
+ <br />
2393
+ <br />
2394
+ Default PHP constant DIRECTORY_SEPARATOR. If used, <b>must</b> be set BEFORE filename!
2395
+ <br />
2396
+ <br />
2397
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_configuration_functions">[up]</a>
2398
+
2399
+ <a name="Directory"></a><h4>3.1.5.8 Directory</h4>
2400
+ Local directory to store/read iCal files, default &nbsp;&quot;<b>.</b>&quot;.
2401
+ <br />
2402
+ <br />
2403
+ Directory <b>must</b> be set BEFORE <a href="#Filename">filename</a> and <b>must</b> exist and be writeable otherwise FALSE is returned.
2404
+ When setting Directory any previously set <a href="#configURL">URL</a> is removed.
2405
+ <br />
2406
+ <br />
2407
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_configuration_functions">[up]</a>
2408
+
2409
+ <a name="Fileinfo"></a><h4>3.1.5.9 Fileinfo</h4>
2410
+ Only available in function getConfig, giving information in array format about <a href="#Directory">directory</a>, <a href="#Filename">filename</a> and <a href="#Filesize">filesize</a>.
2411
+ <p class="label">Example</p>
2412
+ <p class="example">$fileinfo = $vcalendar->getConfig( &quot;fileinfo&quot; );</p>
2413
+ <p class="comment">output = array( &lt;directory&gt;, &lt;filename&gt;, &lt;filesize&gt; )</p>
2414
+ <br />
2415
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_configuration_functions">[up]</a>
2416
+
2417
+ <a name="Filename"></a><h4>3.1.5.10 Filename</h4>
2418
+ iCal local file name, default created like (if not set):<br />
2419
+ <p class="format">$filename = date( &quot;YmdHis&quot; ).&quot;.ics&quot;;</p>
2420
+ <p class="format">$filename = date( &quot;YmdHis&quot; ).&quot;.xml&quot;; <span class="comment"> // if <a href="#Format">format</a> set to &quot;xcal&quot;</span></p>
2421
+ <br />
2422
+ If not set, filename is created when requested, ex. in functions <a href="#saveCalendar">saveCalendar</a> or getConfig('filename').
2423
+ <br />
2424
+ <br />
2425
+ Local filename <b>must</b> be set AFTER setting directory (and opt. delimiter)!
2426
+ Filename (and opt. directory) <b>must</b> be readable/writeable otherwise FALSE is returned.
2427
+ <br />
2428
+ <br />
2429
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_configuration_functions">[up]</a>
2430
+
2431
+ <a name="Filesize"></a><h4>3.1.5.11 Filesize</h4>
2432
+ Only when getting configuration (using function getConfig).<br/>
2433
+ Returns the size of the file in bytes, to be called<br />
2434
+ - after &quot;saveCalendar()&quot;<br />
2435
+ or<br />
2436
+ - after a &quot;setConfig( &quot;directory&quot; / &quot;filename&quot; )&quot; and before/after &quot;parse()&quot;.<br />
2437
+ Getting the filesize for a remote file (URL) will always return zero.
2438
+ <br />
2439
+ <br />
2440
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_configuration_functions">[up]</a>
2441
+
2442
+ <a name="Format"></a><h4>3.1.5.12 Format</h4>
2443
+ Format for calendar output, &quot;iCal&quot;/&quot;xCal&quot;, any case.
2444
+ <br />
2445
+ &quot;iCal&quot; is default (rfc2445), &quot;xCal&quot; force xml formatted output.
2446
+ <br />
2447
+ <br />
2448
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_configuration_functions">[up]</a>
2449
+
2450
+ <a name="Language"></a><h4>3.1.5.13 Language</h4>
2451
+ Language for calendar and component TEXT value properties as defined in [RFC 1766].
2452
+ <br />
2453
+ <br />
2454
+ If NOT set in TEXT property parameters, language from &quot;setConfig( &quot;language&quot;, ..&quot; at component level will be used, if set,
2455
+ otherwise language from &quot;setConfig( &quot;language&quot;, ..&quot; at calendar level will be used, if set.
2456
+ <br />
2457
+ <br />
2458
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_configuration_functions">[up]</a>
2459
+
2460
+ <a name="NewlineChar"></a><h4>3.1.5.14 NewlineChar</h4>
2461
+ Character(s) used for carriage return + line feed (CR+LF), default &quot;\r\n&quot;.
2462
+ <br />
2463
+ <br />
2464
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_configuration_functions">[up]</a>
2465
+
2466
+ <a name="dTZID"></a><h4>3.1.5.15 TZID</h4>
2467
+ Default (local) timezone, will be used if no TZID parameter is used when setting <a href="#DTSTART">DTSTART</a>, <a href="#DTEND">DTEND</a>, <a href="#DUE">DUE</a> or <a href="#RECURRENCE-ID">RECURRENCE-ID</a> (auto completion).
2468
+ Note, some calendar software require <a href="#Additional_Descriptors">X-WR-TIMEZONE</a> (to be set manually).
2469
+ <br />
2470
+ <br />
2471
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_configuration_functions">[up]</a>
2472
+
2473
+ <a name="Unique_id"></a><h4>3.1.5.16 Unique_id</h4>
2474
+ Unique_id is used when creating property PRODID (default auto created) at calendar level
2475
+ and <a href="#UID">UID</a> at component level.
2476
+ <p class="quotes">PRODID
2477
+ RFC2445:
2478
+ * The identifier is RECOMMENDED to be the identical syntax to the
2479
+ * [RFC 822] addr-spec. A good method to assure uniqueness is to put the
2480
+ * domain name or a domain literal IP address of the host on which.. .<p>
2481
+ Default <b>AUTO</b> generated, PHP: gethostbyname( $_SERVER[&quot;SERVER_NAME&quot;] )
2482
+ when running in a web server environment or &quot;localhost&quot; when doing command line execution.
2483
+ Used when setting other (domain) name than server name.
2484
+ <br />
2485
+ <br />
2486
+ A strong recommendation is <b>always</b> to set unique_id when creating a new vcalendar or component object,
2487
+ to ensure accurate creation of all components <a href="#UID">UID</a> property, also before <a href="#parse">parse</a>, in case of missing <a href="#UID">UID</a>.
2488
+ <br />
2489
+ <br />
2490
+
2491
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_configuration_functions">[up]</a>
2492
+
2493
+ <a name="configURL"></a><h4>3.1.5.17 URL</h4>
2494
+ When managing remote files with URL (writing using <a href="#saveCalendar">saveCalendar()</a>, or reading using <a href="#parse">parse()</a>),
2495
+ only protocol &quot;http&quot; (&quot;webcal&quot;) is supported,
2496
+ i.e. <b>must</b> be prefixed by &quot;http://&quot; (&quot;webcal://&quot;) and suffixed by a valid filename.
2497
+
2498
+ <h5>Set URL</h5>
2499
+ When setting URL, any previously set Directory is removed.<br />
2500
+ The URL filename part can be retrieved by &quot;getConfig( 'filename' )&quot;.
2501
+ <br />
2502
+ <br />
2503
+ When storing a remote iCal file locally, only directory need to be set,
2504
+ filename remains unchanged (i.e. 1. set URL, 2. parse, 3. set directory).
2505
+ <p class="label">Example</p>
2506
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;,
2507
+ &quot;url&quot;, &quot;http://www.iCal.net/depot/calendar.ics&quot; );
2508
+ $vcalendar = new vcalendar( $config );
2509
+ $vcalendar->parse();
2510
+ $vcalendar->sort();
2511
+ .. .
2512
+ .. .
2513
+ $vcalendar->setConfig( &quot;directory&quot;, &quot;depot&quot; );
2514
+ $vcalendar->saveCalendar(); // <span class="ref">local save in &quot;depot&quot; folder, </span>
2515
+ // <span class="ref">using original filename</span>
2516
+ </p>
2517
+ <br />
2518
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_configuration_functions">[up]</a>
2519
+
2520
+ <a name="Calendar_component_object_property_function_list"></a><h2>3.2 Calendar component object property function list</h2>
2521
+ <p>
2522
+ All calendar component property functions for get/set data.<br />
2523
+ For property format in detail, see
2524
+ RFC2445 - Internet Calendaring and Scheduling Core Object Specification (iCalendar) in <a href="http://www.kigkonsult.se/downloads/dl.php?f=rfc2445" title="RFC2445 in text format"><b>text</b></a>
2525
+ and <a href="http://www.kigkonsult.se/iCalcreator/iCalDictionary/index.html" title="RFC2445 in HTML format" target="_blank"><b>HTML</b></a> format.
2526
+ </p>
2527
+ <a name="DATE_WITH_UTC_TIME"></a>
2528
+ <span class="label">Notice:</span> for properties and DATE-TIME with <b>UTC</b> time.
2529
+ <p class="quotes">RFC2445:
2530
+ The date with UTC time, or absolute time, is identified by a LATIN CAPITAL
2531
+ LETTER Z suffix character (US-ASCII decimal 90), the UTC designator,
2532
+ appended to the time value. For example, the following represents January
2533
+ 19, 1998, at 0700 UTC:</p>
2534
+ <p class="quotes">DTSTART:19980119T070000Z</p>
2535
+ <p class="quotes">The <a href="#TZID">TZID</a> property parameter MUST <b>NOT</b> be applied to DATE-TIME properties
2536
+ whose time values are specified in UTC.</p>
2537
+ </p>
2538
+ <p>
2539
+ <a name="date_restriction"></a>
2540
+ <span class="label">Notice:</span> date limitation.<br />
2541
+ Due to limitation in PHP date commands, e.g. <span class="format">mktime</span>, <span class="format">strtotime</span>, a date (e.g. while setting <a href="#DTSTART">DTSTART</a> property) before &quot;January 1 1970 00:00:00 GMT&quot; can force a PHP date command to generate an error or set date to &quot;January 1 1970&quot;.
2542
+ </p>
2543
+ <a name="deleteProperty_PROP"></a><h3>3.2.1 deleteProperty</h3>
2544
+ General calendar delete property function,simplifying removal of calendar properties.<br />
2545
+ FALSE is returned if no property exists or when end-of-properties at consecutive function calls.
2546
+ <p class="label">Format</p>
2547
+ <p class="format">deleteProperty( [ string PropName [, int order=1 ] )</p>
2548
+ <p class="comment">propName - case independent, rfc2445 component property names,
2549
+ unknown/missing propName will be used as <a href="#X-PROPERTY_PROP">X-property</a>.
2550
+ order - if missing 1st/next occurrence,
2551
+ used with multiply (property) occurrences</p>
2552
+ <p class="label">Example</p>
2553
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;,
2554
+ &quot;directory&quot; =&gt; &quot;import&quot;,
2555
+ &quot;filename&quot; =&gt; &quot;file.ics&quot; );
2556
+ $vcalendar = new vcalendar( $config );
2557
+ $vcalendar->parse();
2558
+ $e = $vcalendar->getComponent( &quot;vevent&quot; );
2559
+ while( $e->deleteProperty( &quot;comment&quot; ))
2560
+ &nbsp;&nbsp;continue; // <span class="ref">remove all COMMENT properties</span>
2561
+ .. .
2562
+ </p>
2563
+ <br />
2564
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
2565
+
2566
+ <a name="getProperty_PROP"></a><h3>3.2.2 getProperty</h3>
2567
+ General get property function, simplifying fetch of calendar properties.<br />
2568
+ FALSE is returned if no property exists or when end-of-properties at consecutive function calls.
2569
+ <p class="label">Format</p>
2570
+ <p class="format">getProperty( string PropName [, int order=1 [, bool complete=FALSE ]] )</p>
2571
+ <p class="comment">propName - case independent, rfc2445 component property names,
2572
+ unknown/missing propName will be used as <a href="#X-PROPERTY_PROP">X-property</a>.
2573
+ order - if missing/FALSE 1st/next occurrence,
2574
+ otherwise with multiply occurrences (1st=1, 2nd=2.. .)
2575
+ complete - FALSE (default): output only property value
2576
+ TRUE : output =
2577
+ array(&quot;value&quot; =&gt; &lt;value&gt;
2578
+ ,&quot;params&quot;=&gt; &lt;parameter array&gt;)
2579
+ </p>
2580
+ <p class="label">Example</p>
2581
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;,
2582
+ &quot;directory&quot; =&gt; &quot;import&quot;,
2583
+ &quot;filename&quot; =&gt; &quot;file.ics&quot; );
2584
+ $vcalendar = new vcalendar( $config );
2585
+ $vcalendar->parse();
2586
+ while( $vevent = $vcalendar->getComponent( &quot;vevent&quot; )) {
2587
+ &nbsp;$dtstart = $vevent->getProperty( &quot;dtstart&quot; ); // <span class="ref">one occurrence</span>
2588
+ &nbsp;$description = $vevent->getProperty( &quot;description&quot; ); // <span class="ref">one occurrence</span>
2589
+ &nbsp;while( $comment = $vevent->getProperty( &quot;comment&quot; )) {
2590
+ // <span class="ref">MAY occur more than once</span>
2591
+ &nbsp;.. .
2592
+ &nbsp;}
2593
+ .. .
2594
+ </p>
2595
+ <br />
2596
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
2597
+
2598
+ <a name="parse"></a><h3>3.2.3 parse</h3>
2599
+ Parse strict rfc2445 component property text and/or ALARMs.
2600
+ <br /><br />
2601
+ A rfc2445 strict formatted property text, in string or array format and starting with property name.
2602
+ <br />
2603
+ <br />
2604
+ Complete <a href="#VALARM">ALARM</a>s, all properties included, in array format and
2605
+ first array row as &quot;BEGIN:VALARM&quot;, last as &quot;END:VALARM&quot;
2606
+ as well as <a href="#VTIMEZONE">TIMEZONE</a> and standard/daylight subcomponents.
2607
+ <br /><br />
2608
+ FALSE is returned if (read-file) problems occur.
2609
+ <p class="label">Format</p>
2610
+ <p class="format">parse( mixed propertyText )</p>
2611
+ <p class="comment">
2612
+ propertyText = string/array,
2613
+ rcf2445 formatted property/properties,
2614
+ property name <b>must</b> begin (first) line</p>
2615
+ <p class="label">example</p>
2616
+ <p class="example">.. .
2617
+ $vevent = & $vcalendar->newComponent( 'vevent' );
2618
+ $e->parse( 'DTSTAMP:19970324T1200Z' );
2619
+ $e->parse( 'SEQUENCE:0' );
2620
+ $e->parse( 'ORGANIZER:MAILTO:jdoe@host1.com' );
2621
+ $e->parse( array(
2622
+ 'ATTENDEE;RSVP=TRUE:MAILTO:jsmith@host1.com',
2623
+ 'ATTENDEE;RSVP=TRUE:MAILTO:jsmith@host2.com',
2624
+ 'ATTENDEE;RSVP=TRUE:MAILTO:jsmith@host3.com',
2625
+ 'ATTENDEE;RSVP=TRUE:MAILTO:jsmith@host4.com' ));
2626
+ $e->parse( 'DTSTART:19970324T123000Z' );
2627
+ $e->parse( 'DTEND:19970324T210000Z' );
2628
+ $e->parse( 'CATEGORIES:MEETING,PROJECT' );
2629
+ $e->parse( 'CLASS:PUBLIC' );
2630
+ $e->parse( 'SUMMARY:Calendaring Interoperability Planning Meeting' );
2631
+ $e->parse( 'STATUS:DRAFT' );
2632
+ $e->parse( array(
2633
+ 'DESCRIPTION:Project xyz Review Meeting Minutes'
2634
+ ,'Agenda'
2635
+ ,'1. Review of project version 1.0 requirements.'
2636
+ ,'2. Definition of project processes.'
2637
+ ,'3. Review of project schedule.'
2638
+ ,'Participants: John Smith, Jane Doe, Jim Dandy'
2639
+ ,'- It was decided that the requirements need to be signed off by '.
2640
+ 'product marketing.'
2641
+ ,'- Project processes were accepted.'
2642
+ ,'- Project schedule needs to account for scheduled holidays and employee'.
2643
+ ' vacation time. Check with HR for specific dates.'
2644
+ ,'- New schedule will be distributed by Friday.'
2645
+ ,'- Next weeks meeting is cancelled. No meeting until 3/23.' ));
2646
+ $e->parse( 'LOCATION:LDB Lobby' );
2647
+ $e->parse(
2648
+ 'ATTACH;FMTTYPE=application/postscript:ftp://xyz.com/pub/conf/bkgrnd.ps' );
2649
+ $e->parse( array(
2650
+ 'BEGIN:VALARM',
2651
+ 'ACTION:AUDIO',
2652
+ 'TRIGGER;VALUE=DATE-TIME:19970224T070000Z',
2653
+ 'ATTACH;FMTTYPE=audio/basic:http://host.com/pub/audio-files/ssbanner.aud',
2654
+ 'REPEAT:4',
2655
+ 'DURATION:PT1H',
2656
+ 'X-alarm:non-standard ALARM property',
2657
+ 'END:VALARM' ));
2658
+ $e->parse(
2659
+ 'X-xomment:non-standard property will be displayed, comma escaped');
2660
+ .. .
2661
+ </p>
2662
+ <br />
2663
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
2664
+
2665
+
2666
+ <a name="setProperty_PROP"></a><h3>3.2.4 setProperty</h3>
2667
+ General set property function, simplifying insert of component properties. For properties where
2668
+ multiple occurrences are allowed, last parameter is an index, implementing replaceProperty functionality.<br />
2669
+ A successful update returns TRUE.
2670
+ <p class="label">Format</p>
2671
+ <p class="format">setProperty( string PropName, mixed Proparg_1 *[, mixed Proparg_n] )</p>
2672
+ <p class="comment">propName case independent, rfc2445 component property names,
2673
+ unknown propName will be regarded as <a href="#X-PROPERTY_PROP">X-property</a>.</p>
2674
+ <p class="label">Example</p>
2675
+ <p class="example">$vevent = & $vcalendar->newComponent( 'vevent' );
2676
+ $vevent->setProperty( &quot;dtstart&quot;
2677
+ , array(&quot;year&quot;=&gt;2007,&quot;month&quot;=&gt;4,&quot;day&quot;=&gt;1,&quot;hour&quot;=&gt;19));
2678
+ $vevent->setProperty( &quot;duration&quot;, 0, 0, 3 ));
2679
+ $vevent->setProperty( &quot;LOCATION&quot;, &quot;Central Plaza&quot; );
2680
+ $vevent->setProperty( &quot;summary&quot;, &quot;PHP summit&quot; );
2681
+ .. .
2682
+ </p>
2683
+ <br />
2684
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
2685
+
2686
+
2687
+ <a name="ACTION"></a><h3>3.2.5 ACTION</h3>
2688
+ This property defines the action to be invoked when an <a href="#VALARM">VALARM</a> is triggered,<br /> &quot;AUDIO&quot; / &quot;DISPLAY&quot; / &quot;EMAIL&quot; / &quot;PROCEDURE&quot;. This property is REQUIRED and MUST NOT occur more than once.
2689
+ <h5>Delete ACTION</h5>
2690
+ Remove ACTION from component.
2691
+ <p class="label">Format</p>
2692
+ <p class="format">deleteProperty( &quot;Action&quot; )</p>
2693
+ <p class="label">Example</p>
2694
+ <p class="example">$valarm->deleteProperty( &quot;Action&quot; );</p>
2695
+ <h5>Get ACTION</h5>
2696
+ Fetch property value.
2697
+ <p class="label">Format 1</p>
2698
+ <p class="format">getProperty( &quot;Action&quot; )</p>
2699
+ <p class="comment">output = actionValue <span class="ref">1</span></p>
2700
+ <p class="label">Format 2</p>
2701
+ <p class="format">getProperty( &quot;Action&quot;, FALSE , TRUE )</p>
2702
+ <p class="comment">output = array( &quot;value&quot; =&gt; actionValue<span class="ref">1</span>
2703
+ , &quot;params&quot; =&gt; xparam<span class="ref">2</span> )</p>
2704
+ <p class="label">Example</p>
2705
+ <p class="example">$action = $valarm->getProperty( &quot;action&quot; );</p>
2706
+ <h5>Set ACTION</h5>
2707
+ Insert property value.
2708
+ <p class="label">Format</p>
2709
+ <p class="format">setProperty( &quot;Action&quot;, actionValue [, xparam ] )</p>
2710
+ <p class="comment">actionValue<span class="ref">1</span> = one of &quot;AUDIO&quot; / &quot;DISPLAY&quot; / &quot;EMAIL&quot; / &quot;PROCEDURE&quot;
2711
+ xparam<span class="ref">2</span> = array( *[ xparamkey =&gt; xparamvalue ] )</p>
2712
+ <p class="label">Example</p>
2713
+ <p class="example">$valarm->setProperty( &quot;action&quot;, &quot;DISPLAY&quot; );</p>
2714
+ <br />
2715
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
2716
+
2717
+
2718
+ <a name="ATTACH"></a><h3>3.2.6 ATTACH</h3>
2719
+ The property provides the capability to associate a document object with a calendar component. The property is
2720
+ is REQUIRED and MUST NOT occur more than once in an &quot;ALARM&quot; (&quot;ACTION&quot; &quot;procedure&quot;),
2721
+ OPTIONAL and MUST NOT occur more than once in an &quot;ALARM&quot; (&quot;ACTION&quot; &quot;audio&quot;) and
2722
+ OPTIONAL and MAY occur more than once in <a href="#VEVENT">VEVENT</a>, <a href="#VTODO">VTODO</a>, <a href="#VJOURNAL">VJOURNAL</a> and <a href="#VALARM">VALARM</a> (&quot;ACTION&quot; &quot;email&quot;) components.
2723
+ <br /><br />
2724
+ The default value type for ATTACH is URI. The value type can also be set to BINARY to indicate inline binary encoded content information (params <span class="ref">2</span>).
2725
+ <h5>Delete ATTACH</h5>
2726
+ Remove ATTACH from component.
2727
+ <p class="label">Format</p>
2728
+ <p class="format">deleteProperty( &quot;ATTACH&quot; )</p>
2729
+ <p class="label">Example 1</p>
2730
+ <p class="example">$valarm->deleteProperty( &quot;ATTACH&quot; );</p>
2731
+ <p class="label">Example 2</p>
2732
+ Delete ATTACH property no 2.
2733
+ <p class="format">$valarm->deleteProperty( &quot;ATTACH&quot;, 2 );</p>
2734
+ <p class="label">Example 3</p>
2735
+ Deleting all ATTACH properties.
2736
+ <p class="example">while( $valarm->deleteProperty( &quot;ATTACH&quot; ))
2737
+ continue;</p>
2738
+ <h5>Get ATTACH</h5>
2739
+ Fetch property value.
2740
+ <p class="label">Format 1</p>
2741
+ <p class="format">getProperty( &quot;Attach&quot; )</p>
2742
+ <p class="comment">output = attachValue<span class="ref">1</span></p>
2743
+ <p class="label">Format 2</p>
2744
+ <p class="format">getProperty( &quot;ATTACH&quot;, propOrderNo/FALSE , TRUE )</p>
2745
+ <p class="comment">output = array( &quot;value&quot; =&gt; attachValue<span class="ref">1</span>
2746
+ , &quot;params&quot; =&gt; params<span class="ref">2</span> )</p>
2747
+ <p class="label">Format 3</p>
2748
+ <p class="format">getProperty( &quot;Attach&quot;, propOrderNo )</p>
2749
+ <p class="comment">Get propOrderNo ATTACH</p>
2750
+ <p class="label">Example</p>
2751
+ <p class="example">$attach = $valarm->getProperty( &quot;attach&quot; );</p>
2752
+ <h5>Set ATTACH</h5>
2753
+ Insert property value.
2754
+ <br />
2755
+ Parameters, if any, will be ordered as prescribed in rcf2445.
2756
+ <p class="label">Format</p>
2757
+ <p class="format">setProperty( &quot;attach&quot;, attachValue<span class="ref">1</span> [, params [, propOrderNo ]] )</p>
2758
+ <p class="comment">attachValue<span class="ref">1</span> = URI / inline binary encoded content information.
2759
+ params<span class="ref">2</span> = array( [ &quot;ENCODING&quot; =&gt; &quot;BASE64&quot;,
2760
+ &quot;VALUE&quot; =&gt; &quot;BINARY&quot; ]
2761
+ [, &quot;FMTTYPE&quot; =&gt; contentType ]
2762
+ [,&nbsp;xparam ] )
2763
+ contentType = The parameter value MUST be the TEXT for either
2764
+ an IANA registered content type or a non-standard
2765
+ content type.
2766
+ xparam = *[ xparamkey =&gt; xparamvalue ]
2767
+ propOrderNo = int ordernumber, 1=1st, 2=2nd etc</p>
2768
+ <p class="label">Example</p>
2769
+ <p class="example">$vevent->setProperty( &quot;attach&quot;
2770
+ , &quot;ftp://domain.com/pub/docs/agenda.doc&quot;
2771
+ , array( &quot;FMTTYPE&quot; =&gt; &quot;application/binary&quot; ));
2772
+ </p>
2773
+ <br />
2774
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
2775
+
2776
+
2777
+ <a name="ATTENDEE"></a><h3>3.2.7 ATTENDEE</h3>
2778
+ The property defines an "Attendee" within a calendar component and is OPTIONAL and MUST NOT occur more than once
2779
+ in a VALARM (&quot;ACTION&quot; &quot;email&quot;), OPTIONAL and MAY occur more than once in <a href="#VEVENT">VEVENT</a>, <a href="#VTODO">VTODO</a>, <a href="#VJOURNAL">VJOURNAL</a> and <a href="#VFREEBUSY">VFREEBUSY</a> components.
2780
+ <br /><br />
2781
+ This value type for ATTENDEE is URI, a calendar user address.
2782
+ <h5>Delete ATTENDEE</h5>
2783
+ Remove ATTENDEE from component.
2784
+ <p class="label">Format</p>
2785
+ <p class="format">deleteProperty( &quot;ATTENDEE&quot; )</p>
2786
+ <p class="label">Example 1</p>
2787
+ <p class="example">$valarm->deleteProperty( &quot;ATTENDEE&quot; );</p>
2788
+ <p class="label">Example 2</p>
2789
+ Delete ATTENDEE property no 2.
2790
+ <p class="example">$valarm->deleteProperty( &quot;ATTENDEE&quot;, 2 );</p>
2791
+ <p class="label">Example 3</p>
2792
+ Deleting all ATTENDEE properties.
2793
+ <p class="example">while( $valarm->deleteProperty( &quot;ATTENDEE&quot; ))
2794
+ continue;</p>
2795
+ <h5>Get ATTENDEE</h5>
2796
+ Fetch property value.
2797
+ <p class="label">Format 1</p>
2798
+ <p class="format">getProperty( &quot;Attendee&quot; )</p>
2799
+ <p class="comment">output = attendeeValue <span class="ref">1</span></p>
2800
+ <p class="label">Format 2</p>
2801
+ <p class="format">getProperty( &quot;ATTENDEE&quot;, propOrderNo/FALSE , TRUE )</p>
2802
+ <p class="comment">output = array( &quot;value&quot; =&gt; attendeeValue<span class="ref">1</span>
2803
+ , &quot;params&quot; =&gt; array( params<span class="ref">2</span> ))</p>
2804
+ <p class="label">Format 3</p>
2805
+ <p class="format">getProperty( &quot;ATTENDEE&quot;, propOrderNo )</p>
2806
+ <p class="comment">Get propOrderNo ATTENDEE</p>
2807
+ <p class="label">Example</p>
2808
+ <p class="example">$attendee = $valarm->getProperty( &quot;attendee&quot; );</p>
2809
+ <h5>Set ATTENDEE</h5>
2810
+ Insert property value. If exist, default parameter values are removed after input (params<span class="ref">2</span>).
2811
+ Property value must be prefixed by protocol (ftp://, http://,mailto:, file://.. . ref. rfc 1738 ), if missing, 'mailto:' is set (ex. indicating an internet mail address).
2812
+ Also MEMBER and DIR parameters must be prefixed by protocol. DELEGATED-TO, DELEGATED-FROM, SENT-BY parameters must use protocol 'mailto:', prefixed if missing (ex. indicating an internet mail address).
2813
+ <br />
2814
+ Parameters, if any, will be ordered as prescribed in rcf2445.
2815
+ <p class="label">Format</p>
2816
+ <p class="format">setProperty( &quot;attendee&quot;, attendeeValue [, params [, propOrderNo ]] )</p>
2817
+ <p class="comment">attendeeValue<span class="ref">1</span> = a calendar user address, a URI as defined by
2818
+ [RFC 1738] or any other IANA registered form
2819
+ for a URI.
2820
+ params<span class="ref">2</span> = array( [CUTYPE] [,MEMBER] [,ROLE] [,PARTSTAT]
2821
+ [,RVSP] [,DELEGATED-TO] [,DELEGATED-FROM]
2822
+ [,SENT-BY] [,CN] [,DIR] [,LANGUAGE]
2823
+ [,xparams] )
2824
+ CUTYPE = "CUTYPE" =&gt; &quot;INDIVIDUAL&quot;
2825
+ (An individual, <b>Default</b>)
2826
+ / &quot;GROUP&quot;
2827
+ (A group of individuals)
2828
+ / &quot;RESOURCE&quot;
2829
+ (A physical resource)
2830
+ / &quot;ROOM&quot;
2831
+ (A room resource)
2832
+ / &quot;UNKNOWN&quot;
2833
+ (Otherwise not known)
2834
+ / x-name
2835
+ (Experimental type)
2836
+ / iana-token
2837
+ (Other IANA registered type)
2838
+ MEMBER = "MEMBER" =&gt; array( *[ &quot;single member
2839
+ of the group or list membership&quot;])
2840
+ ROLE = "ROLE" =&gt; &quot;CHAIR&quot;
2841
+ (Indicates chair of the calendar
2842
+ entity)
2843
+ / &quot;REQ-PARTICIPANT&quot;
2844
+ (required participation, <b>Default</b>)
2845
+ / &quot;OPT-PARTICIPANT&quot;
2846
+ (optional participation)
2847
+ / &quot;NON-PARTICIPANT&quot;
2848
+ (information purposes only)
2849
+ / x-name
2850
+ (Experimental role)
2851
+ / iana-token
2852
+ (Other IANA role)
2853
+ PARTSTAT = &quot;PARTSTAT&quot; =&gt; &quot;NEEDS-ACTION&quot;
2854
+ (Event needs action, <b>Default</b>)
2855
+ / &quot;ACCEPTED&quot;
2856
+ (Event accepted)
2857
+ / &quot;DECLINED&quot;
2858
+ (Event declined)
2859
+ / &quot;TENTATIVE&quot;
2860
+ (Event tentatively accepted)
2861
+ / &quot;DELEGATED&quot;
2862
+ (Event delegated)
2863
+ / &quot;NEEDS-ACTION&quot;
2864
+ (To-do needs action, <b>Default</b>)
2865
+ / &quot;ACCEPTED&quot;
2866
+ (To-do accepted)
2867
+ / &quot;DECLINED&quot;
2868
+ (To-do declined)
2869
+ / &quot;TENTATIVE&quot;
2870
+ (To-do tentatively accepted)
2871
+ / &quot;DELEGATED&quot;
2872
+ (To-do delegated)
2873
+ / &quot;COMPLETED&quot;
2874
+ (To-do completed.
2875
+ <a href="#COMPLETED">COMPLETED</a> property
2876
+ has date/time completed)
2877
+ / &quot;IN-PROCESS&quot;
2878
+ (To-do in process of being completed)
2879
+ / &quot;NEEDS-ACTION&quot;
2880
+ (Journal needs action, <b>Default</b>)
2881
+ / &quot;ACCEPTED&quot;
2882
+ (Journal accepted)
2883
+ / &quot;DECLINED&quot;
2884
+ (Journal declined)
2885
+ / x-name
2886
+ (Experimental status)
2887
+ / iana-token
2888
+ (Other IANA registered status)
2889
+ RSVP = &quot;RSVP&quot; =&gt; &quot;TRUE&quot;
2890
+ / &quot;FALSE&quot;, <b>Default</b> (reply expectation)
2891
+ DELEGATED-TO = &quot;DELEGATED-TO&quot; =&gt; array(*[&quot;single calendar user
2892
+ to specified by the property
2893
+ has delegated participation&quot;])
2894
+ DELEGATED-FROM = &quot;DELEGATED-FROM&quot; =&gt; array( *[ &quot;single calendar user that
2895
+ have delegated their
2896
+ participation to the
2897
+ calendar user specified
2898
+ by the property&quot; ] )
2899
+ SENT-BY = &quot;SENT-BY&quot; =&gt; single calendar user that is
2900
+ acting on behalf
2901
+ of the calendar user
2902
+ specified by the property&quot;
2903
+ LANGUAGE = &quot;LANGUAGE&quot; =&gt; language for text values in CN parameter&quot;
2904
+ CN = &quot;CN&quot; =&gt; &quot;common name to be associated with the calendar
2905
+ user specified by the property&quot;
2906
+ DIR = &quot;DIR&quot; =&gt; &quot;reference to a directory entry associated with
2907
+ the calendar user specified by the property&quot;
2908
+ xparam = *[ xparamkey =&gt; xparamvalue ]
2909
+ propOrderNo = int ordernumber, 1=1st, 2=2nd etc</p>
2910
+ See rules in detail in RFC2445 - Internet Calendaring and Scheduling Core Object Specification (iCalendar) in <a href="http://www.kigkonsult.se/downloads/dl.php?f=rfc2445" title="RFC2445 in text format"><b>text</b></a> and <a href="http://www.kigkonsult.se/iCalcreator/iCalDictionary/index.html" title="RFC2445 in HTML format" target="_blank"><b>HTML</b></a> format.
2911
+ <p class="label">Example</p>
2912
+ <p class="example">$vevent->setProperty( &quot;attendee&quot;
2913
+ , &quot;attendee1@ical.net&quot;
2914
+ $vevent->setProperty( &quot;attendee&quot;
2915
+ , &quot;attendee2@ical.net&quot;
2916
+ , array( &quot;cutype&quot; =&gt; &quot;INDIVIDUAL&quot;
2917
+ , &quot;member&quot; =&gt; array( &quot;member1@ical.net&quot;
2918
+ , &quot;member2@ical.net&quot;
2919
+ , &quot;member3@ical.net&quot; )
2920
+ , &quot;role&quot; =&gt; &quot;CHAIR&quot;
2921
+ , &quot;PARTSTAT&quot; =&gt; &quot;ACCEPTED&quot;
2922
+ , &quot;RSVP&quot; =&gt; &quot;TRUE&quot;
2923
+ , &quot;DELEgated-to&quot; =&gt; array( &quot;part1@ical.net&quot;
2924
+ , &quot;part2@ical.net&quot;
2925
+ , &quot;part3@ical.net&quot; )
2926
+ , &quot;delegateD-FROM&quot; =&gt;array( &quot;cio@ical.net&quot;
2927
+ , &quot;vice.cio@ical.net&quot;)
2928
+ , &quot;SENT-BY&quot; =&gt; &quot;secretary@ical.net&quot;
2929
+ , &quot;LANGUAGE&quot; =&gt; &quot;us-EN&quot;
2930
+ , &quot;CN&quot; =&gt; &quot;John Doe&quot;
2931
+ , &quot;DIR&quot; =&gt; &quot;http://www.ical.net/info.doc&quot;
2932
+ , &quot;x-agenda&quot; =&gt; &quot;status reports&quot; <span class="comment">// xparam</span>
2933
+ , &quot;x-length&quot; =&gt; &quot;15 min&quot; )); <span class="comment">// xparam</span>
2934
+ </p>
2935
+ <br />
2936
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
2937
+
2938
+ <a name="CATEGORIES"></a><h3>3.2.8 CATEGORIES</h3>
2939
+ This property defines the categories for a calendar component and is OPTIONAL and MAY occur more than once in <a href="#VEVENT">VEVENT</a>, <a href="#VTODO">VTODO</a> and <a href="#VJOURNAL">VJOURNAL</a> components.<br /><br />
2940
+ The value type for CATEGORIES is TEXT.
2941
+ <h5>Delete CATEGORIES</h5>
2942
+ Remove CATEGORIES from component.
2943
+ <p class="label">Format</p>
2944
+ <p class="format">deleteProperty( &quot;CATEGORIES&quot; )</p>
2945
+ <p class="label">Example 1</p>
2946
+ <p class="example">$vevent->deleteProperty( &quot;CATEGORIES&quot; );</p>
2947
+ <p class="label">Example 2</p>
2948
+ Delete CATEGORIES property no 2.
2949
+ <p class="example">$vevent->deleteProperty( &quot;CATEGORIES&quot;, 2 );</p>
2950
+ <p class="label">Example 3</p>
2951
+ Deleting all CATEGORIES properties.
2952
+ <p class="example">while( $vevent->deleteProperty( &quot;CATEGORIES&quot; ))
2953
+ continue;</p>
2954
+ <h5>Get CATEGORIES</h5>
2955
+ Fetch property value.
2956
+ <p class="label">Format 1</p>
2957
+ <p class="format">getProperty( &quot;CATEGORIES&quot; )</p>
2958
+ <p class="comment">output = categoryValue<span class="ref">1</span></p>
2959
+ <p class="label">Format 2</p>
2960
+ <p class="format">getProperty( &quot;CATEGORIES&quot;, propOrderNo/FALSE , TRUE )</p>
2961
+ <p class="comment">output = array( &quot;value&quot; =&gt; categories<span class="ref">1</span>
2962
+ , &quot;params&quot; =&gt; params<span class="ref">2</span> )</p>
2963
+ <p class="label">Format 3</p>
2964
+ <p class="format">getProperty( &quot;CATEGORIES&quot;, propOrderNo )</p>
2965
+ <p class="comment">Get propOrderNo CATEGORIES</p>
2966
+ <p class="label">Example</p>
2967
+ <p class="example">$categories = $valarm->getProperty( &quot;categories&quot; );</p>
2968
+ <h5>Set CATEGORIES</h5>
2969
+ Insert property value.
2970
+ <br />
2971
+ Parameters, if any, will be ordered as prescribed in rcf2445.
2972
+ <p class="label">Format</p>
2973
+ <p class="format">setProperty( &quot;categories&quot;, mixed categories [, params [, propOrderNo ]] )</p>
2974
+ <p class="comment">categories<span class="ref">1</span> = string categoryValue / array( *categoryValue )
2975
+ categoryValue<span class="ref"> </span>= textual categories or subtypes of the calendar component,
2976
+ can be specified as a list of categories
2977
+ separated by the COMMA character
2978
+ params<span class="ref">2</span> = array( [&quot;LANGUAGE&quot; =&gt; &quot;&lt;lang&gt;&quot;][, xparam] )
2979
+ xparam<span class="ref"> </span> = *[ xparamkey =&gt; xparamvalue ]
2980
+ propOrderNo<span class="ref"> </span> = int ordernumber, 1=1st, 2=2nd etc</p>
2981
+ <p class="label">Example</p>
2982
+ <p class="example">$vevent->setProperty( &quot;categories&quot;, &quot;project_x&quot; );</p>
2983
+ <br />
2984
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
2985
+
2986
+
2987
+ <a name="CLASS"></a><h3>3.2.9 CLASS</h3>
2988
+ This property defines the access classification for a calendar component and is OPTIONAL
2989
+ and MUST NOT occur more than once in <a href="#VEVENT">VEVENT</a>, <a href="#VTODO">VTODO</a> and <a href="#VJOURNAL">VJOURNAL</a> components.
2990
+ <h5>Delete CLASS</h5>
2991
+ Remove CLASS from component.
2992
+ <p class="label">Format</p>
2993
+ <p class="format">deleteProperty( &quot;CLASS&quot; )</p>
2994
+ <p class="label">Example</p>
2995
+ <p class="example">$vjournal->deleteProperty( &quot;CLASS&quot; );</p>
2996
+ <h5>Get CLASS</h5>
2997
+ Fetch property value.
2998
+ <p class="label">Format 1</p>
2999
+ <p class="format">getProperty( &quot;CLASS&quot; )</p>
3000
+ <p class="comment">output = classValue<span class="ref">1</span></p>
3001
+ <p class="label">Format 2</p>
3002
+ <p class="format">getProperty( &quot;CLASS&quot;, FALSE , TRUE )</p>
3003
+ <p class="comment">output = array &quot;value&quot; =&gt; classValue<span class="ref">1</span>
3004
+ , &quot;params&quot; =&gt; xparam<span class="ref">2</span> )</p>
3005
+ <p class="label">Example</p>
3006
+ <p class="example">$class = $valarm->getProperty( &quot;class&quot; );</p>
3007
+ <h5>Set CLASS</h5>
3008
+ Insert property value.
3009
+ <p class="label">Format</p>
3010
+ <p class="format">setProperty( &quot;class&quot;, string classvalue [, xparam ] )</p>
3011
+ <p class="comment">classvalue<span class="ref">1</span> = &quot;PUBLIC&quot;
3012
+ / &quot;PRIVATE&quot;
3013
+ / &quot;CONFIDENTIAL&quot;
3014
+ / iana-token
3015
+ / x-name
3016
+ xparam<span class="ref">2</span> = array( *[ xparamkey =&gt; xparamvalue ] )</p>
3017
+ <p class="label">Example</p>
3018
+ <p class="example">$vevent->setProperty( &quot;class&quot;, &quot;CONFIDENTIAL&quot; );</p>
3019
+ <br />
3020
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
3021
+
3022
+ <a name="COMMENT"></a><h3>3.2.10 COMMENT</h3>
3023
+ This property specifies non-processing information intended to provide a comment to the calendar user
3024
+ and is OPTIONAL and MAY occur more than once in <a href="#VEVENT">VEVENT</a>, <a href="#VTODO">VTODO</a>, <a href="#VJOURNAL">VJOURNAL</a>, <a href="#VFREEBUSY">VFREEBUSY</a>, <a href="#VTIMEZONE">STANDARD</a> and <a href="#VTIMEZONE">DAYLIGHT</a> components.<br /><br />
3025
+ The value type for COMMENT is TEXT.
3026
+ <h5>Delete COMMENT</h5>
3027
+ Remove COMMENT from component.
3028
+ <p class="label">Format</p>
3029
+ <p class="format">deleteProperty( &quot;COMMENT&quot; )</p>
3030
+ <p class="label">Example 1</p>
3031
+ <p class="example">$vevent->deleteProperty( &quot;COMMENT&quot; );</p>
3032
+ <p class="label">Example 2</p>
3033
+ Delete COMMENT property no 2.
3034
+ <p class="example">$vevent->deleteProperty( &quot;COMMENT&quot;, 2 );</p>
3035
+ <p class="label">Example 3</p>
3036
+ Deleting all COMMENT properties.
3037
+ <p class="example">while( $vevent->deleteProperty( &quot;COMMENT&quot; ))
3038
+ continue;</p>
3039
+ <h5>Get COMMENT</h5>
3040
+ Fetch property value.
3041
+ <p class="label">Format 1</p>
3042
+ <p class="format">getProperty( &quot;COMMENT&quot; )</p>
3043
+ <p class="comment">output = commentValue<span class="ref">1</span></p>
3044
+ <p class="label">Format 2</p>
3045
+ <p class="format">getProperty( &quot;COMMENT&quot;, propOrderNo/FALSE , TRUE )</p>
3046
+ <p class="comment">output = array( &quot;value&quot; =&gt; commentValue<span class="ref">1</span>
3047
+ , &quot;params&quot; =&gt; params<span class="ref">2</span> )</p>
3048
+ <p class="label">Format 3</p>
3049
+ <p class="format">getProperty( &quot;COMMENT&quot;, propOrderNo )</p>
3050
+ <p class="comment">Get propOrderNo COMMENT</p>
3051
+ <p class="label">Example</p>
3052
+ <p class="example">$comment = $vevent->getProperty( &quot;comment&quot; );</p>
3053
+ <h5>Set COMMENT</h5>
3054
+ Insert property value.
3055
+ <br />
3056
+ Parameters, if any, will be ordered as prescribed in rcf2445.
3057
+ <p class="label">Format</p>
3058
+ <p class="format">setProperty( &quot;comment&quot;, commentValue [, params [, propOrderNo ]] )</p>
3059
+ <p class="comment">commentValue<span class="ref">1</span> = Value type Text
3060
+ params<span class="ref">2</span> = array( [&quot;ALTREP&quot; =&gt; &quot;&lt;an alternate text representation, URI&gt;&quot;]
3061
+ [, [&quot;LANGUAGE&quot; =&gt; &quot;&lt;lang&gt;&quot;]
3062
+ [, xparam] )
3063
+ xparam = *[ xparamkey =&gt; xparamvalue ]
3064
+ propOrderNo = int ordernumber, 1=1st, 2=2nd etc</p>
3065
+ <p class="label">Example</p>
3066
+ <p class="example">$vevent->setProperty( &quot;comment&quot;, &quot;this is a comment&quot; );</p>
3067
+ <br />
3068
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
3069
+
3070
+
3071
+ <a name="COMPLETED"></a><h3>3.2.11 COMPLETED</h3>
3072
+ This property defines the date and time that a <a href="#VTODO">VTODO</a> was actually completed and is OPTIONAL and MUST NOT occur more than once.<br /><br />
3073
+ The value type for COMPLETED is <a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME.
3074
+ <h5>Delete COMPLETED</h5>
3075
+ Remove COMPLETED from component.
3076
+ <p class="label">Format</p>
3077
+ <p class="format">deleteProperty( &quot;COMPLETED&quot; )</p>
3078
+ <p class="label">Example</p>
3079
+ <p class="example">$vtodo->deleteProperty( &quot;COMPLETED&quot; );</p>
3080
+ <h5>Get COMPLETED</h5>
3081
+ Fetch property value.
3082
+ <p class="label">Format 1</p>
3083
+ <p class="format">getProperty( &quot;COMPLETED&quot; )</p>
3084
+ <p class="comment">output = completedDate<span class="ref">1</span></p>
3085
+ <p class="label">Format 2</p>
3086
+ <p class="format">getProperty( &quot;COMPLETED&quot;, FALSE , TRUE )</p>
3087
+ <p class="comment">output = array( &quot;value&quot; =&gt; completedDate<span class="ref">1</span>
3088
+ , &quot;params&quot; =&gt; xparam<span class="ref">2</span> )</p>
3089
+ <p class="label">Example</p>
3090
+ <p class="example">$completed = $vtodo->getProperty( &quot;completed&quot; );</p>
3091
+ <h5>Set COMPLETED</h5>
3092
+ Insert property value. Input date is always a <a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME or, if &quot;offset&quot; parameter is used, converted to a <a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME.
3093
+ <p class="label">Format</p>
3094
+ <p class="format">setProperty( &quot;completed&quot;, completedDate [, xparam ] )</p>
3095
+ <p class="comment">completedDate<span class="ref">1</span> = array( &quot;year&quot; =&gt; int year
3096
+ , &quot;month&quot; =&gt; int month
3097
+ , &quot;day&quot; =&gt; int day
3098
+ [, &quot;hour&quot; =&gt; int hour
3099
+ , &quot;min&quot; =&gt; int min
3100
+ , &quot;sec&quot; =&gt; int sec
3101
+ , &quot;tz&quot; =&gt; offset ]] )
3102
+ completedDate = int year
3103
+ , int month
3104
+ , int day
3105
+ [, int hour
3106
+ , int min
3107
+ , int sec ]
3108
+ completedDate = array( int year
3109
+ , int month
3110
+ , int day
3111
+ [, int hour
3112
+ , int min
3113
+ , int sec
3114
+ [, offset ]] )
3115
+ completedDate = array ( &quot;timestamp&quot; =&gt; int timestamp [, &quot;tz&quot; => offset])
3116
+ completedDate = string datestring // <span class="ref">string date,
3117
+ acceptable by strtotime-command,
3118
+ ex. &nbsp;&quot;14 august 2006 16.00.00&quot;
3119
+ (notice <a class="ref" href="#date_restriction">date restriction</a>)</span>
3120
+ offset = (+/-)HHmm[ss], local date + UTC offset =&gt; <a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME
3121
+ xparam<span class="ref">2</span> = array( *[ xparamkey =&gt; xparamvalue ] )</p>
3122
+ <p class="label">Example 1</p>
3123
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;);
3124
+ $vcalendar = new vcalendar( $config );
3125
+ $vtodo = & $vcalendar->newComponent( 'vtodo' );
3126
+ .. .
3127
+ $vtodo->setProperty( &quot;completed&quot;, 2006, 8, 10, 10, 0, 0 );
3128
+ // <span class="ref">10 august 2006 10.00 UTC</span></p>
3129
+ <p class="label">Example 2</p>
3130
+ <p class="example">$date = array(&quot;year&quot; =&gt; 2006, &quot;month&quot; =&gt; 10, &quot;day&quot; =&gt; 10,
3131
+ &quot;hour&quot; =&gt; 10, &quot;min&quot; =&gt; 0, &quot;sec&quot; =&gt; 0, &quot;tz&quot; =&gt; &quot;+0200&quot;);
3132
+ // <span class="ref">local date + UTC offset =&gt; <a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME</span>
3133
+ $vtodo->setProperty( &quot;completed&quot;, $date );</p>
3134
+ <br />
3135
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
3136
+
3137
+
3138
+ <a name="CONTACT"></a><h3>3.2.12 CONTACT</h3>
3139
+ The property is used to represent textual contact information or alternately a reference to textual contact information associated with the calendar component. The property is OPTIONAL and MUST NOT occur more than once in a VFREEBUSY or MAY occur more than once in <a href="#VEVENT">VEVENT</a>, <a href="#VTODO">VTODO</a> and <a href="#VJOURNAL">VJOURNAL</a> components.<br /><br />
3140
+ The value type for CONTACT is TEXT.
3141
+ <h5>Delete CONTACT</h5>
3142
+ Remove CONTACT from component.
3143
+ <p class="label">Format</p>
3144
+ <p class="format">deleteProperty( &quot;CONTACT&quot; )</p>
3145
+ <p class="label">Example 1</p>
3146
+ <p class="example">$vevent->deleteProperty( &quot;CONTACT&quot; );</p>
3147
+ <p class="label">Example 2</p>
3148
+ Delete CONTACT property no 2.
3149
+ <p class="example">$vevent->deleteProperty( &quot;CONTACT&quot;, 2 );</p>
3150
+ <p class="label">Example 3</p>
3151
+ Deleting all CONTACT properties.
3152
+ <p class="example">while( $vevent->deleteProperty( &quot;CONTACT&quot; ))
3153
+ continue;</p>
3154
+ <h5>Get CONTACT</h5>
3155
+ Fetch property value.
3156
+ <p class="label">Format 1</p>
3157
+ <p class="format">getProperty( &quot;CONTACT&quot; )</p>
3158
+ <p class="comment">output = contactValue<span class="ref">1</span></p>
3159
+ <p class="label">Format 2</p>
3160
+ <p class="format">getProperty( &quot;CONTACT&quot;, propOrderNo/FALSE , TRUE )</p>
3161
+ <p class="comment">output = array( &quot;value&quot; =&gt; contactValue<span class="ref">1</span>
3162
+ , &quot;params&quot; =&gt; params<span class="ref">2</span> )</p>
3163
+ <p class="label">Format 3</p>
3164
+ <p class="format">getProperty( &quot;CONTACT&quot;, propOrderNo )</p>
3165
+ <p class="comment">Get propOrderNo CONTACT</p>
3166
+ <p class="label">Example</p>
3167
+ <p class="example">$contact = $vevent->getProperty( &quot;contact&quot; );</p>
3168
+ <h5>Set CONTACT</h5>
3169
+ Insert property value.
3170
+ <br />
3171
+ Parameters, if any, will be ordered as prescribed in rcf2445.
3172
+ <p class="label">Format</p>
3173
+ <p class="format">setproperty( &quot;contact&quot;, contactValue [, params [, propOrderNo ]] )</p>
3174
+ <p class="comment">contactValue<span class="ref">1</span> = Value type TEXT
3175
+ params<span class="ref">2</span> = array ( [&quot;ALTREP&quot; =&gt; &quot;&lt;an alternate text representation, URI&gt;&quot;]
3176
+ [, &quot;LANGUAGE&quot; =&gt; &quot;&lt;lang&gt;&quot;]
3177
+ [, xparam] )
3178
+ xparam = *[ xparamkey =&gt; xparamvalue ]
3179
+ propOrderNo = int ordernumber, 1=1st, 2=2nd etc</p>
3180
+ <p class="label">Example</p>
3181
+ <p class="example">$c->setProperty( &quot;contact&quot;, &quot;tel 012-34 56 789&quot; )</p>
3182
+ <br />
3183
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
3184
+
3185
+
3186
+ <a name="CREATED"></a><h3>3.2.13 CREATED</h3>
3187
+ This property specifies the date and time that the calendar information was created by the calendar user agent in the calendar store. Note: This is analogous to the creation date and time for a file in the file system. The property is OPTIONAL and MUST NOT occur more than once in <a href="#VEVENT">VEVENT</a>, <a href="#VTODO">VTODO</a> and <a href="#VJOURNAL">VJOURNAL</a> components.<br /><br />
3188
+ The value type for CREATED is <a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME.
3189
+ <h5>Delete CREATED</h5>
3190
+ Remove CREATED from component.
3191
+ <p class="label">Format</p>
3192
+ <p class="format">deleteProperty( &quot;CREATED&quot; )</p>
3193
+ <p class="label">Example</p>
3194
+ <p class="example">$vevent->deleteProperty( &quot;CREATED&quot; );</p>
3195
+ <h5>Get CREATED</h5>
3196
+ Fetch property value.
3197
+ <p class="label">Format 1</p>
3198
+ <p class="format">getProperty( &quot;CREATED&quot; )</p>
3199
+ <p class="comment">output = createdDate<span class="ref">1</span></p>
3200
+ <p class="label">Format 2</p>
3201
+ <p class="format">getProperty( &quot;CREATED&quot;, FALSE , TRUE )</p>
3202
+ <p class="comment">output = array( &quot;value&quot; =&gt; createdDate<span class="ref">1</span>
3203
+ , &quot;params&quot; =&gt; xparam<span class="ref">2</span> )</p>
3204
+ <p class="label">Example</p>
3205
+ <p class="example">$created = $vevent->getProperty( &quot;CREATED&quot; );</p>
3206
+ <h5>Set CREATED</h5>
3207
+ Insert property value. Input date is always a <a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME or, if &quot;offset&quot; parameter is used, converted to a <a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME.
3208
+ <p class="label">Format</p>
3209
+ <p class="format">setProperty( &quot;created&quot;, [ createdDate [, xparam ]] )</p>
3210
+ <p class="comment">createdDate<span class="ref">1</span> = array( &quot;year&quot; =&gt; int year
3211
+ , &quot;month&quot; =&gt; int month
3212
+ , &quot;day&quot; =&gt; int day
3213
+ [, &quot;hour&quot; =&gt; int hour
3214
+ , &quot;min&quot; =&gt; int min
3215
+ , &quot;sec&quot; =&gt; int sec
3216
+ , &quot;tz&quot; =&gt; offset ]] )
3217
+ createdDate = int year
3218
+ , int month
3219
+ , int day
3220
+ [, int hour
3221
+ , int min
3222
+ , int sec ]
3223
+ createdDate = array( int year
3224
+ , int month
3225
+ , int day
3226
+ [, int hour
3227
+ , int min
3228
+ , int sec
3229
+ [, offset ]] )
3230
+ createdDate = array ( &quot;timestamp&quot; =&gt; int timestamp [, &quot;tz&quot; => offset ])
3231
+ createdDate = string datestring // <span class="ref">string date,
3232
+ acceptable by strtotime-command,
3233
+ ex. &nbsp;&quot;14 august 2006 16.00.00&quot;
3234
+ (notice <a class="ref" href="#date_restriction">date restriction</a>)</span>
3235
+ offset = (+/-)HHmm[ss], local date + UTC offset =&gt; <a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME
3236
+ xparam<span class="ref">2</span> = array( *[ xparamkey =&gt; xparamvalue ] )</p>
3237
+ <p class="label">Example 1</p>
3238
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot; );
3239
+ $vcalendar = new vcalendar( $config );
3240
+ $vtodo = & $vcalendar->newComponent( 'vtodo' );
3241
+ .. .
3242
+ $vtodo->setProperty( &quot;created&quot;, 2006, 8, 11, 14, 30, 35 );
3243
+ // <span class="ref">11 august 2006 14.30.35 UTC</span> </p>
3244
+ <p class="label">Example 2</p>
3245
+ <p class="example">$date = array(&quot;year&quot; =&gt; 2006, &quot;month&quot; =&gt; 10, &quot;day&quot; =&gt; 10,
3246
+ &quot;hour&quot; =&gt; 10, &quot;min&quot; =&gt; 0, &quot;sec&quot; =&gt; 0, &quot;tz&quot; =&gt; &quot;+0200&quot;);
3247
+ // <span class="ref">local date + UTC offset =&gt; <a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME</span>
3248
+ $vtodo->setProperty( &quot;created&quot;, $date );
3249
+ .. .</p>
3250
+ <p class="label">Example 3</p>
3251
+ <p class="example">$vevent->setProperty( &quot;created&quot; );
3252
+ // <span class="ref">current UTC date-time is set if called without parameters</span></p>
3253
+ <br />
3254
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
3255
+
3256
+
3257
+ <a name="DESCRIPTION"></a><h3>3.2.14 DESCRIPTION</h3>
3258
+ This property provides a more complete textual description of the calendar component, than that provided by the <a href="#SUMMARY">SUMMARY</a> property (, analogous to a mail BODY). The property is OPTIONAL, MUST NOT occur more than once within <a href="#VEVENT">VEVENT</a>, <a href="#VTODO">VTODO</a> or <a href="#VALARM">VALARM</a> (PROCEDURE) but can be specified multiple times within a <a href="#VJOURNAL">VJOURNAL</a> calendar component. The property is REQUIRED in <a href="#VALARM">VALARM</a> (DISPLAY, EMAIL) component.<br /><br />
3259
+ The value type for DESCRIPTION is TEXT.
3260
+ <h5>Delete DESCRIPTION</h5>
3261
+ Remove DESCRIPTION from component.
3262
+ <p class="label">Format</p>
3263
+ <p class="format">deleteProperty( &quot;DESCRIPTION&quot; )</p>
3264
+ <p class="label">Example 1</p>
3265
+ <p class="example">$vevent->deleteProperty( &quot;DESCRIPTION&quot; );</p>
3266
+ <p class="label">Example 2</p>
3267
+ Delete DESCRIPTION property no 2.
3268
+ <p class="example">$vjournal->deleteProperty( &quot;DESCRIPTION&quot;, 2 );</p>
3269
+ <p class="label">Example 3</p>
3270
+ Deleting all DESCRIPTION properties.
3271
+ <p class="example">while( $vjournal->deleteProperty( &quot;DESCRIPTION&quot; ))
3272
+ continue;</p>
3273
+ <h5>Get DESCRIPTION</h5>
3274
+ Fetch property value.
3275
+ <p class="label">Format 1</p>
3276
+ <p class="format">getProperty( &quot;DESCRIPTION&quot; )</p>
3277
+ <p class="comment">output = descriptionValue<span class="ref">1</span></p>
3278
+ <p class="label">Format 2</p>
3279
+ <p class="format">getProperty( &quot;DESCRIPTION&quot;, FALSE , TRUE )</p>
3280
+ <p class="comment">output = array( &quot;value&quot; =&gt; descriptionValue<span class="ref">1</span>
3281
+ , &quot;params&quot; =&gt; params<span class="ref">2</span> )</p>
3282
+ <p class="label">Example</p>
3283
+ <p class="example">$description = $vevent->getProperty( &quot;description&quot; );</p>
3284
+ <h5>Set DESCRIPTION</h5>
3285
+ Insert property value.
3286
+ <br />
3287
+ Parameters, if any, will be ordered as prescribed in rcf2445.
3288
+ <p class="label">Format</p>
3289
+ <p class="format">setProperty( &quot;description&quot;, descriptionValue [, params [, propOrderNo ]] )</p>
3290
+ <p class="comment">descriptionValue<span class="ref">1</span> = Value type TEXT
3291
+ params<span class="ref">2</span> = array( [&quot;ALTREP&quot; =&gt; &quot;&lt;an alternate text representation, URI&gt;&quot;]
3292
+ [, &quot;LANGUAGE&quot; =&gt; &quot;&lt;lang&gt;&quot;]
3293
+ [, xparam] )
3294
+ xparam = *[ xparamkey =&gt; xparamvalue ]
3295
+ propOrderNo = int ordernumber, 1=1st, 2=2nd etc</p>
3296
+ <p class="label">Example</p>
3297
+ <p class="example">$vevent->setProperty( &quot;description&quot;, &quot;This is a description&quot; );</p>
3298
+ <br />
3299
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
3300
+
3301
+
3302
+ <a name="DTEND"></a><h3>3.2.15 DTEND</h3>
3303
+ This property specifies the date and time that a calendar component ends.
3304
+ The property is OPTIONAL and MUST NOT occur more than once in VFREEBUSY and VEVENT. In VEVENT, it only occurs
3305
+ if DURATION NOT occurs.
3306
+ <br /><br />
3307
+ The default value type for DTEND is DATE-TIME, can be set to a DATE value type.
3308
+ <br /><br />
3309
+ Notice that an end date without a time is in effect midnight of the day before the date, so for timeless dates, use the date following the event date for it to be correct. For an &quot;all-day event&quot; and using timeless dates, the DTEND is equal DTSTART plus one day, example all-day event (2007-12-01)<br />DTSTART;VALUE=DATE:20071201<br /> DTEND;VALUE=DATE:20071202.
3310
+ <h5>Delete DTEND</h5>
3311
+ Remove DTEND from component.
3312
+ <p class="label">Format</p>
3313
+ <p class="format">deleteProperty( &quot;DTEND&quot; )</p>
3314
+ <p class="label">Example</p>
3315
+ <p class="example">$vevent->deleteProperty( &quot;DTEND&quot; );</p>
3316
+ <h5>Get DTEND</h5>
3317
+ Fetch property value.
3318
+ <p class="label">Format 1</p>
3319
+ <p class="format">getProperty( &quot;DTEND&quot; )</p>
3320
+ <p class="comment">output = dtendDate<span class="ref">1</span></p>
3321
+ <p class="label">Format 2</p>
3322
+ <p class="format">getProperty( &quot;DTEND&quot;, FALSE , TRUE )</span>
3323
+ <p class="comment">output = array( &quot;value&quot; =&gt; dtendDate<span class="ref">1</span>
3324
+ , &quot;params&quot; =&gt; params<span class="ref">2</span> )</p>
3325
+ <p class="label">Example</p>
3326
+ <p class="example">$dtend = $vevent->getProperty( &quot;dtend&quot; );</p>
3327
+ <h5>Set DTEND</h5>
3328
+ Insert property value. If DATE value type is expected, &quot;VALUE&quot; = &quot;DATE&quot; <b>must</b> be set
3329
+ (in params<span class="ref">2</span>) otherwise DATE-TIME (default) value type is set.
3330
+ <br />
3331
+ <br />
3332
+ If no timezone parameter (tz or tzidparam below) is set (then local time is assumed) and config <a href="#dTZID">TZID</a> is set, date-time values will be set WITH timezone from config.
3333
+ <br />
3334
+ <br />
3335
+ Parameters, if any, will be ordered as prescribed in rcf2445.
3336
+ <p class="label">Format</p>
3337
+ <p class="format">setProperty( &quot;dtend&quot;, dtendDate [, params<span class="ref">2</span> ] )</span>
3338
+ <p class="comment">dtendDate<span class="ref">1</span> = array ( &quot;year&quot; =&gt; int year
3339
+ , &quot;month&quot; =&gt; int month
3340
+ , &quot;day&quot; =&gt; int day
3341
+ [, &quot;hour&quot; =&gt; int hour
3342
+ , &quot;min&quot; =&gt; int min
3343
+ , &quot;sec&quot; =&gt; int sec
3344
+ [, &quot;tz&quot; =&gt; mixed tz ]] )
3345
+ dtendDate = int year
3346
+ , int month
3347
+ , int day
3348
+ [, int hour
3349
+ , int min
3350
+ , int sec
3351
+ [, mixed tz ]]
3352
+ dtendDate = array( int year
3353
+ , int month
3354
+ , int day
3355
+ [, int hour
3356
+ , int min
3357
+ , int sec
3358
+ [, mixed tz ]] )
3359
+ dtendDate = array( &quot;timestamp&quot; =&gt; int timestamp [,&quot;tz&quot; =&gt; mixed tz])
3360
+ dtendDate = string datestring // <span class="ref">string date,
3361
+ acceptable by strtotime-command,
3362
+ ex.&nbsp;&quot;14 august 2006 16.00.00&quot;
3363
+ (notice <a class="ref" href="#date_restriction">date restriction</a>)</span>
3364
+ dtendDate : Within the "VFREEBUSY" calendar component,
3365
+ the time MUST be specified in the <a href="#DATE_WITH_UTC_TIME">UTC</a> time format.
3366
+ tz = &lt;timezone identifier&gt; / UTC offset
3367
+ (timezone will be used as tzidparam (below), if tzidparam not set)
3368
+ offset = (+/-)HHmm[ss], local date + UTC offset =&gt; <a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME
3369
+ params<span class="ref">2</span> = array([ tzidparam/datetimeparam/dateparam ] *[,xparams])
3370
+ tzidparam = &quot;TZID&quot; =&gt; &lt;timezone identifier&gt;
3371
+ // <span class="ref">output as local date-time with timezone identifier</span>
3372
+ datetimeparam = &quot;VALUE&quot; =&gt; &quot;DATE-TIME&quot; // <span class="ref">default, output as date-time</span>
3373
+ dateparam = &quot;VALUE&quot; =&gt; &quot;DATE&quot; // <span class="ref">output as DATE, ex. all-day event</span>
3374
+ xparams = xparamkey =&gt; xparamvalue</p>
3375
+ <p class="label">Example 1</p>
3376
+ <p class="example">$vevent->setProperty( &quot;dtend&quot;
3377
+ , 2006, 8, 11, 16, 30, 0 );
3378
+ <span class="ref">// 11 august 2006 16.30.00 local date</span></p>
3379
+ <p class="label">Example 2</p>
3380
+ <p class="example">$vfreebusy->setProperty( &quot;dtend&quot;
3381
+ , 2006, 8, 11, 16, 30, 0, &quot;-040000&quot; );
3382
+ <span class="ref">// 11 august 2006 16.30.00 -040000 :
3383
+ local date + UTC offset =&gt; <a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME</span></p>
3384
+ <p class="label">Example 3</p>
3385
+ <p class="example">$vevent->setProperty( &quot;dtend&quot;
3386
+ , array( 'year' =&gt;, 2006, 'month' =&gt; 8, 'day'=&gt; 11 )
3387
+ , array( 'VALUE' =&gt; 'DATE' ));
3388
+ <span class="ref">// end of one or more all-day events</span></p>
3389
+ <br />
3390
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
3391
+
3392
+
3393
+ <a name="DTSTAMP"></a><h3>3.2.16 DTSTAMP</h3>
3394
+ The property indicates the date/time that the instance of the iCalendar object was created and is OPTIONAL and MUST NOT occur more than once in <a href="#VEVENT">VEVENT</a>, <a href="#VTODO">VTODO</a>, <a href="#VJOURNAL">VJOURNAL</a> and <a href="#VFREEBUSY">VFREEBUSY</a> components. However, DTSTAMP is <b>AUTO</b> GENERATED in iCalcreator.
3395
+ <br /><br />
3396
+ DTSTAMP may be required when importing iCal files into some calendaring software<br />(MS etc.),
3397
+ as well as (calendar) <a href="#X-PROPERTY">x-properties</a> "X-WR-CALNAME", "X-WR-CALDESC" and<br />"X-WR-TIMEZONE",
3398
+ <a href="#METHOD">METHOD</a> property (value PUBLISH etc.) and (also auto created) <a href="#UID">UID</a> property.
3399
+ <br /><br />
3400
+ The value type for DTSTAMP is <a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME.
3401
+ <h5>Delete DTSTAMP</h5>
3402
+ If DTSTAMP if removed from a component, DTSTAMP will automatically be recreated when calendar output functions like <a href="#createCalendar">createCalendar</a>, <a href="#returnCalendar">returnCalendar</a> or <a href="#saveCalendar">saveCalendar</a> is executed.
3403
+ <p class="label">Format</p>
3404
+ <p class="format">deleteProperty( &quot;DTSTAMP&quot; )</p>
3405
+ <p class="label">Example</p>
3406
+ <p class="example">$vevent->deleteProperty( &quot;DTSTAMP&quot; );</p>
3407
+ <h5>Get DTSTAMP</h5>
3408
+ Fetch property value.
3409
+ <p class="label">Format 1</p>
3410
+ <p class="format">getProperty( &quot;DTSTAMP&quot; )</p>
3411
+ <p class="comment">output = dtstampDate<span class="ref">1</span></p>
3412
+ <p class="label">Format 2</p>
3413
+ <p class="format">getProperty( &quot;DTSTAMP&quot;, FALSE , TRUE )</p>
3414
+ <p class="comment">output = array( &quot;value&quot; =&gt; dtstampDate<span class="ref">1</span>
3415
+ , &quot;params&quot; =&gt; xparam<span class="ref">2</span> )</p>
3416
+ <p class="label">Example</p>
3417
+ <p class="example">$dtstamp = $vevent->getProperty( &quot;dtstamp&quot; );</p>
3418
+ <h5>Set DTSTAMP</h5>
3419
+ Insert property value. Input date is always a <a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME or, if &quot;offset&quot; parameter is used, converted to a <a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME.
3420
+ <p class="label">Format</p>
3421
+ <p class="format">setProperty( &quot;dtstamp&quot;, dtstampDate [, xparam ] )</p>
3422
+ <p class="comment">dtstampDate<span class="ref">1</span> = array( &quot;year&quot; =&gt; int year
3423
+ , &quot;month&quot; =&gt; int month
3424
+ , &quot;day&quot; =&gt; int day
3425
+ [, &quot;hour&quot; =&gt; int hour
3426
+ , &quot;min&quot; =&gt; int min
3427
+ , &quot;sec&quot; =&gt; int sec
3428
+ , &quot;tz&quot; =&gt; offset ]] )
3429
+ dtstampDate = int year
3430
+ , int month
3431
+ , int day
3432
+ [, int hour
3433
+ , int min
3434
+ , int sec ]
3435
+ dtstampDate = array( int year
3436
+ , int month
3437
+ , int day
3438
+ [, int hour
3439
+ , int min
3440
+ , int sec
3441
+ [, offset ]] )
3442
+ dtstampDate = array ( &quot;timestamp&quot; =&gt; int timestamp [, &quot;tz&quot; => offset ])
3443
+ dtstampDate = string datestring // <span class="ref">string date,
3444
+ acceptable by strtotime-command,
3445
+ ex. &nbsp;&quot;14 august 2006 16.00.00&quot;
3446
+ (notice <a class="ref" href="#date_restriction">date restriction</a>)</span>
3447
+ offset = (+/-)HHmm[ss], local date + UTC offset =&gt; <a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME
3448
+ xparam<span class="ref">2</span> = array( *[ xparamkey =&gt; xparamvalue ] )</p>
3449
+ <p class="label">Example 1</p>
3450
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot; );
3451
+ $vcalendar = new vcalendar( $config );
3452
+ $vtodo = & $vcalendar->newComponent( 'vtodo' );
3453
+ .. .
3454
+ $vtodo->setProperty( &quot;dstamp&quot;
3455
+ , 2006, 8, 11, 7, 30, 1 );
3456
+ <span class="ref">// 11 august 2006 07.30.01 UTC</span></p>
3457
+ <p class="label">Example 2</p>
3458
+ <p class="example">$date = array(&quot;year&quot; =&gt; 2006, &quot;month&quot; =&gt; 10, &quot;day&quot; =&gt; 10,
3459
+ &quot;hour&quot; =&gt; 10, &quot;min&quot; =&gt; 0, &quot;sec&quot; =&gt; 0, &quot;tz&quot; =&gt; &quot;+0200&quot;);
3460
+ // <span class="ref">local date + UTC offset =&gt; <a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME</span>
3461
+ $vtodo->setProperty( &quot;dtstamp&quot;, $date );
3462
+ .. .</p>
3463
+ <br />
3464
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
3465
+
3466
+ <a name="DTSTART"></a><h3>3.2.17 DTSTART</h3>
3467
+ This property specifies when the calendar component begins.<br />
3468
+ The property is OPTIONAL and MUST NOT occur more than once in <a href="#VEVENT">VEVENT</a>, <a href="#VTODO">VTODO</a>, <a href="#VJOURNAL">VJOURNAL</a> and <a href="#VFREEBUSY">VFREEBUSY</a> components.<br />
3469
+ The property is REQUIRED, but MUST NOT occur more than once in <a href="#VTIMEZONE">STANDARD</a> and <a href="#VTIMEZONE">DAYLIGHT</a> components.<br /><br />
3470
+ The default value type for DTSTART is DATE-TIME, can be set to a DATE value type.<br /><br />
3471
+ For an &quot;all-day event&quot; and using timeless dates, example (2007-12-01)<br />
3472
+ DTSTART;VALUE=DATE:20071201<br />
3473
+ DTEND;VALUE=DATE:20071202. // <span class="ref">opt., in effect midnight of the day <u>before</u> the date!!</span>
3474
+ <h5>Delete DTSTART</h5>
3475
+ Remove DTSTART from component.
3476
+ <p class="label">Format</p>
3477
+ <p class="format">deleteProperty( &quot;DTSTART&quot; )</p>
3478
+ <p class="label">Example</p>
3479
+ <p class="example">$vevent->deleteProperty( &quot;DTSTART&quot; );</p>
3480
+ <h5>Get DTSTART</h5>
3481
+ Fetch property value.
3482
+ <p class="label">Format 1</p>
3483
+ <p class="format">getProperty( &quot;DTSTART&quot; )</p>
3484
+ <p class="comment">output = dtstartDate<span class="ref">1</span></p>
3485
+ <p class="label">Format 2</p>
3486
+ <p class="format">getProperty( &quot;DTSTART&quot;, FALSE , TRUE )</p>
3487
+ <p class="comment">output = array( &quot;value&quot; =&gt; dtstartDate<span class="ref">1</span>
3488
+ , &quot;params&quot; =&gt; params<span class="ref">2</span> )</p>
3489
+ <p class="label">Example</p>
3490
+ <p class="example">$dtstart = $vevent->getProperty( &quot;dtstart&quot; );</p>
3491
+ <h5>Set DTSTART</h5>
3492
+ Insert property value. If DATE value type is expected, &quot;VALUE&quot; = &quot;DATE&quot; <b>must</b> be set (in params<span class="ref">2</span>) otherwise DATE-TIME (default) value type is set.
3493
+ <br />
3494
+ <br />
3495
+ If no timezone parameter (tz or tzidparam below) is set (then local time is assumed) and config <a href="#dTZID">TZID</a> is set, date-time values will be set WITH timezone from config.
3496
+ <br />
3497
+ <br />
3498
+ Parameters, if any, will be ordered as prescribed in rcf2445.
3499
+ <p class="label">Format</p>
3500
+ <p class="format">setProperty( &quot;dtstart&quot;, dtstartDate [, params ] )</p>
3501
+ <p class="comment">dtstartDate<span class="ref">1</span> = array( &quot;year&quot; =&gt; int year
3502
+ , &quot;month&quot; =&gt; int month
3503
+ , &quot;day&quot; =&gt; int day
3504
+ [, &quot;hour&quot; =&gt; int hour
3505
+ , &quot;min&quot; =&gt; int min
3506
+ , &quot;sec&quot; =&gt; int sec
3507
+ [, &quot;tz&quot; =&gt; mixed tz ]] )
3508
+ dtstartDate = int year
3509
+ , int month
3510
+ , int day
3511
+ [, int hour
3512
+ , int min
3513
+ , int sec
3514
+ [, mixed tz ]]
3515
+ dtstartDate = array( int year
3516
+ , int month
3517
+ , int day
3518
+ [, int hour
3519
+ , int min
3520
+ , int sec
3521
+ [, mixed tz ]] )
3522
+ dtstartDate = array(&quot;timestamp&quot; =&gt; int timestamp [, &quot;tz&quot; =&gt; mixed tz])
3523
+ dtstartDate = string datestring // <span class="ref">string date,
3524
+ acceptable by strtotime-command,
3525
+ ex.&nbsp;&quot;14 august 2006 16.00.00&quot;
3526
+ (notice <a class="ref" href="#date_restriction">date restriction</a>)</span>
3527
+ dtstartDate : Within the "VFREEBUSY" calendar component,
3528
+ the dtstartDate MUST be specified in the <a href="#DATE_WITH_UTC_TIME">UTC</a> time format.
3529
+ tz = &lt;timezone identifier&gt; / offset
3530
+ (timezone will be used as tzidparam (below), if tzidparam not set)
3531
+ offset = (+/-)HHmm[ss], local date + UTC offset =&gt; <a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME
3532
+ params<span class="ref">2</span> = array([ tzidparam/datetimeparam/dateparam ] *[, xparams])
3533
+ tzidparam = &quot;TZID&quot; =&gt; &lt;timezone identifier&gt;
3534
+ // <span class="ref">output as local date-time with timezone identifier</span>
3535
+ datetimeparam = &quot;VALUE&quot; =&gt; &quot;DATE-TIME&quot; // <span class="ref">default, output as date-time</span>
3536
+ dateparam = &quot;VALUE&quot; =&gt; &quot;DATE&quot; // <span class="ref">output as DATE, ex. all-day event</span>
3537
+ xparams = xparamkey =&gt; xparamvalue</p>
3538
+ <p class="label">Example 1</p>
3539
+ <p class="example">$vevent->setProperty( &quot;dstart&quot;
3540
+ , 2006, 8, 11, 7, 30, 1 );
3541
+ <span class="comment">// 11 august 2006 07.30.01 local date</span></p>
3542
+ <p class="label">Example 2</p>
3543
+ <p class="example">$vevent->setProperty( &quot;dstart&quot;
3544
+ , 2006, 8, 11, 16, 30, 0, &quot;-040000&quot; );
3545
+ <span class="comment">// 11 august 2006 16.30.00 -040000,
3546
+ // local date + UTC offset =&gt; <a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME</span></p>
3547
+ <p class="label">Example 3</p>
3548
+ <p class="example">$vevent->setProperty( &quot;dtstart&quot;
3549
+ , array( 'year' =&gt;, 2006, 'month' =&gt; 8, 'day'=&gt; 11 )
3550
+ , array( 'VALUE' =&gt; 'DATE' ));
3551
+ <span class="comment">// start of an all-day event, or a period of (entire) days</span></p>
3552
+ <br />
3553
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
3554
+
3555
+
3556
+ <a name="DUE"></a><h3>3.2.18 DUE</h3>
3557
+ This property defines the date and time when a <a href="#VTODO">VTODO</a> is expected to be completed
3558
+ and is OPTIONAL and MUST NOT occur more than once and only if DURATION NOT occurs.<br /><br />
3559
+ The default value type for DUE is DATE-TIME, can be set to a DATE value type.
3560
+ <h5>Delete DUE</h5>
3561
+ Remove DUE from component.
3562
+ <p class="label">Format</p>
3563
+ <p class="format">deleteProperty( &quot;DUE&quot; )</p>
3564
+ <p class="label">Example</p>
3565
+ <p class="example">$vtodo->deleteProperty( &quot;DUE&quot; );</p>
3566
+ <h5>Get DUE</h5>
3567
+ Fetch property value.
3568
+ <p class="label">Format 1</p>
3569
+ <p class="format">getProperty( &quot;DUE&quot; )</p>
3570
+ <p class="comment">output = dueDate<span class="ref">1</span></p>
3571
+ <p class="label">Format 2</p>
3572
+ <p class="format">getProperty( &quot;DUE&quot;, FALSE , TRUE )</p>
3573
+ <p class="comment">output = array( &quot;value&quot; =&gt; dueDate<span class="ref">1</span>
3574
+ , &quot;params&quot; =&gt; params<span class="ref">2</span> )</p>
3575
+ <p class="label">Example</p>
3576
+ <p class="example">$due = $vtodo->getProperty( &quot;due&quot; );</p>
3577
+ <h5>Set DUE</h5>
3578
+ Insert property value. If DATE value type is expected, &quot;VALUE&quot; = &quot;DATE&quot; <b>must</b> be set
3579
+ (in params<span class="ref">2</span>) otherwise DATE-TIME (default) value type is set.
3580
+ <br />
3581
+ <br />
3582
+ If no timezone parameter (tz or tzidparam below) is set (then local time is assumed) and config <a href="#dTZID">TZID</a> is set, date-time values will be set WITH timezone from config.
3583
+ <br />
3584
+ <br />
3585
+ Parameters, if any, will be ordered as prescribed in rcf2445.
3586
+ <p class="label">Format</p>
3587
+ <p class="format">setProperty( &quot;due&quot;, dueDate [, params ] )</p>
3588
+ <p class="comment">dueDate<span class="ref">1</span> = array( &quot;year&quot; =&gt; int year
3589
+ , &quot;month&quot; =&gt; int month
3590
+ , &quot;day&quot; =&gt; int day
3591
+ [, &quot;hour&quot; =&gt; int hour
3592
+ , &quot;min&quot; =&gt; int min
3593
+ , &quot;sec&quot; =&gt; int sec
3594
+ [, &quot;tz&quot; =&gt; mixed tz ]] )
3595
+ dueDate = int year
3596
+ , int month
3597
+ , int day
3598
+ [, int hour
3599
+ , int min
3600
+ , int sec
3601
+ [, mixed tz ]]
3602
+ dueDate = array( int year
3603
+ , int month
3604
+ , int day
3605
+ [, int hour
3606
+ , int min
3607
+ , int sec
3608
+ [, mixed tz ]] )
3609
+ dueDate = array( &quot;timestamp&quot; =&gt; int timestamp [, &quot;tz&quot; =&gt; mixed tz])
3610
+ dueDate = string datestring // <span class="ref">string date,
3611
+ acceptable by strtotime-command,
3612
+ ex.&nbsp;&quot;14 august 2006 16.00.00&quot;
3613
+ (notice <a class="ref" href="#date_restriction">date restriction</a>)</span>
3614
+ tz = &lt;timezone identifier&gt; / offset
3615
+ (timezone will be used as tzidparam (below), if tzidparam not set)
3616
+ offset = (+/-)HHmm[ss], local date + UTC offset =&gt; <a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME
3617
+ params<span class="ref">2</span> = array([ tzidparam/datetimeparam/dateparam ] *[, xparams])
3618
+ tzidparam = &quot;TZID&quot; =&gt; &lt;timezone identifier&gt;
3619
+ // <span class="ref">output as local date-time with timezone identifier</span>
3620
+ datetimeparam = &quot;VALUE&quot; =&gt; &quot;DATE-TIME&quot; // <span class="ref">default, output as date-time</span>
3621
+ dateparam = &quot;VALUE&quot; =&gt; &quot;DATE&quot; // <span class="ref">output as DATE, &quot;during the day&quot;</span>
3622
+ xparams = xparamkey =&gt; xparamvalue<p/>
3623
+ <p class="label">Example 1</p>
3624
+ <p class="example">$vtodo->setProperty( &quot;due&quot;
3625
+ , 2006, 8, 11, 18, 0, 0 );
3626
+ <span class="comment">// 11 august 2005 18.00.00 local date</span></p>
3627
+ <p class="label">Example 2</p>
3628
+ <p class="example">$vtodo->setProperty( &quot;due&quot;
3629
+ , 2006, 8, 11, 16, 30, 0, &quot;-040000&quot; );
3630
+ <span class="comment">// 11 august 2006 16.30.00 -040000
3631
+ // local date + UTC offset sets <a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME</span></p>
3632
+ <p class="label">Example 3</p>
3633
+ <p class="example">$vtodo->setProperty( &quot;due&quot;
3634
+ , array( 'year' =&gt;, 2006, 'month' =&gt; 8, 'day'=&gt; 11 )
3635
+ , array( 'VALUE' =&gt; 'DATE' ));
3636
+ <span class="comment">// due &quot;during the day&quot;</span></p>
3637
+ <br />
3638
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
3639
+
3640
+
3641
+ <a name="DURATION"></a><h3>3.2.19 DURATION</h3>
3642
+ The property specifies a positive duration of time<br />
3643
+ In a VEVENT it is OPTIONAL and MUST NOT occur more than once and MUST NOT occur in pair with DTEND. If one occurs, so MUST NOT the other.<br />
3644
+ In a VTODO it is OPTIONAL and MUST NOT occur more than once and MUST NOT occur in pair with DUE. If one occurs, so MUST NOT the other.<br />
3645
+ In a VFREEBUSY it is OPTIONAL and MUST NOT occur more than once.<br />
3646
+ In a VALARM it is OPTIONAL and MUST NOT occur more than once and MUST occur in pair with TRIGGER. If one occurs, so MUST the other.
3647
+ <h5>Delete DURATION</h5>
3648
+ Remove DURATION from component.
3649
+ <p class="label">Format</p>
3650
+ <p class="format">deleteProperty( &quot;DURATION&quot; )</p>
3651
+ <p class="label">Example</p>
3652
+ <p class="example">$valarm->deleteProperty( &quot;DURATION&quot; );</p>
3653
+ <h5>Get DURATION</h5>
3654
+ Fetch property value.
3655
+ <p class="label">Format 1</p>
3656
+ <p class="format">getProperty( &quot;DURATION&quot; )</p>
3657
+ <p class="comment">output = duration<span class="ref">1</span></p>
3658
+ <p class="label">Format 2</p>
3659
+ <p class="format">getProperty( &quot;DURATION&quot;, FALSE , TRUE )</p>
3660
+ <p class="comment">output = array( &quot;value&quot; =&gt; duration<span class="ref">1</span>
3661
+ , &quot;params&quot; =&gt; xparam<span class="ref">2</span> )</p>
3662
+ <p class="label">Example</p>
3663
+ <p class="example">$duration = $vtodo->getProperty( &quot;duration&quot; );</p>
3664
+ <p class="label">option</p>
3665
+ If a 4th argument is used and set to TRUE, returned output is in a DATE-TIME
3666
+ output format (like <a href="#DTEND">DTEND</a> / <a href="#DUE">DUE</a>), based on
3667
+ <a href="#DTSTART">DTSTART</a> value with added DURATION value.
3668
+ <h5>Set DURATION</h5>
3669
+ Insert property value.
3670
+ <p class="label">Format</p>
3671
+ <p class="format">setProperty( &quot;duration&quot;, duration [, xparam ] )</p>
3672
+ <p class="comment">
3673
+ duration<span class="ref">1</span> = array ( &quot;week&quot; =&gt; int week )
3674
+ duration<span class="ref">1</span> = array ( &quot;day&quot; =&gt; int day )
3675
+ [, &quot;hour&quot; =&gt; int hour
3676
+ , &quot;min&quot; =&gt; int min
3677
+ , &quot;sec&quot; =&gt; int sec ])
3678
+ duration = array ( &quot;sec&quot; =&gt; int sec )
3679
+ duration = array( int week/false
3680
+ [, int day/false
3681
+ [, int hour
3682
+ , int min
3683
+ , int sec ]] )
3684
+ duration = int week/false
3685
+ [, int day/false
3686
+ [, int hour
3687
+ , int min
3688
+ , int sec ]]
3689
+ duration = string dur-value = [&quot;+&quot;] &quot;P&quot; (dur-date/dur-time/dur-week)
3690
+ dur-date = dur-day [dur-time]
3691
+ dur-time = &quot;T&quot; (dur-hour / dur-minute / dur-second)
3692
+ dur-week = 1*DIGIT &quot;W&quot;
3693
+ dur-hour = 1*DIGIT &quot;H&quot; [dur-minute]
3694
+ dur-minute = 1*DIGIT &quot;M&quot; [dur-second]
3695
+ dur-second = 1*DIGIT &quot;S&quot;
3696
+ dur-day = 1*DIGIT &quot;D&quot;
3697
+ xparam<span class="ref">2</span> = array( *[ xparamkey =&gt; xparamvalue ] )</p>
3698
+ <p class="label">Example 1</p>
3699
+ <p class="example">$vtodo->setProperty &quot;duration&quot;
3700
+ , array( &quot;day&quot; =&gt; 1 )); </p>
3701
+ <p class="ref">// one day</p>
3702
+ <p class="label">Example 2</p>
3703
+ <p class="example">$vtodo->setProperty( &quot;duration&quot;
3704
+ , &quot;PT4H&quot; );
3705
+ <p class="ref"> // four hours</p>
3706
+ <br />
3707
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
3708
+
3709
+
3710
+ <a name="EXDATE"></a><h3>3.2.20 EXDATE</h3>
3711
+ This property defines the list of date/time exceptions for a recurring calendar component and is OPTIONAL and MAY occur more than once in <a href="#VEVENT">VEVENT</a>, <a href="#VTODO">VTODO</a>, <a href="#VJOURNAL">VJOURNAL</a> components.<br /><br />
3712
+ The default value type for EXDATE is DATE-TIME, can be set to a DATE value type.
3713
+ <h5>Delete EXDATE</h5>
3714
+ Remove EXDATE from component.
3715
+ <p class="label">Format</p>
3716
+ <p class="format">deleteProperty( &quot;EXDATE&quot; )</p>
3717
+ <p class="label">Example 1</p>
3718
+ <p class="example">$vtodo->deleteProperty( &quot;EXDATE&quot; );</p>
3719
+ <p class="label">Example 2</p>
3720
+ Delete EXDATE property no 2.
3721
+ <p class="example">$vjournal->deleteProperty( &quot;EXDATE&quot;, 2 );</p>
3722
+ <p class="label">Example 3</p>
3723
+ Deleting all EXDATE properties.
3724
+ <p class="example">while( $vjournal->deleteProperty( &quot;EXDATE&quot; ))
3725
+ continue;</p>
3726
+ <h5>Get EXDATE</h5>
3727
+ Fetch property value.
3728
+ <p class="label">Format 1</p>
3729
+ <p class="format">getProperty( &quot;EXDATE&quot; )<p>
3730
+ <p class="comment">output = exdates<span class="ref">1</span></p>
3731
+ <p class="label">Format 2</p>
3732
+ <p class="format">getProperty( &quot;exdate&quot;, propOrderNo/FALSE, TRUE )</p>
3733
+ <p class="comment">output = array( &quot;value&quot; =&gt; exdates<span class="ref">1</span>
3734
+ , &quot;params&quot; =&gt; xparams<span class="ref">2</span> )</p>
3735
+ <p class="label">Format 3</p>
3736
+ <p class="format">getProperty( &quot;EXDATE&quot;, propOrderNo )</p>
3737
+ <p class="comment">Get propOrderNo EXDATE</p>
3738
+ <p class="label">Example</p>
3739
+ <p class="example">$exdate = $vtodo->getProperty( &quot;exdate&quot; );</p>
3740
+ <h5>Set EXDATE</h5>
3741
+ Insert property value.<br />
3742
+ If &quot;TZID&quot; is set in params, ex. &quot;TZID&quot; = &quot;CET&quot;,
3743
+ all timezone or offset in dates are ignored and DATE-TIME value type is set.<br />
3744
+ If DATE value type is set in params (&quot;VALUE&quot; = &quot;DATE&quot;), all timezone or offset in dates are ignored.<br />
3745
+ If no &quot;VALUE&quot; parameter in params, DATE-TIME (default) value type is set.<br />
3746
+ If empty params and offset in 1st date, all remaining dates are set to UTC.<br />
3747
+ If no &quot;TZID&quot; is set in params and timezone in 1st date, all remaining dates are within this timezone and param &quot;TZID&quot; is set.<br />
3748
+ If none of the above rules are applicable, DATE-TIME and local date is set default.
3749
+ <br />
3750
+ Parameters, if any, will be ordered as prescribed in rcf2445.
3751
+ <p class="label">Format</p>
3752
+ <p class="format">setProperty( &quot;exdate&quot;, exdates [, xparams [, propOrderNo ]] )</p>
3753
+ <p class="comment">exdates<span class="ref">1</span> = array ( date *[, date ] )
3754
+ date = array( int year
3755
+ , int month
3756
+ , int day
3757
+ [, int hour
3758
+ , int min
3759
+ , int sec
3760
+ [, mixed tz ]] )
3761
+ date<span class="ref">1</span> = array( &quot;year&quot; =&gt; int year
3762
+ , &quot;month&quot; =&gt; int month
3763
+ , &quot;day&quot; =&gt; int day
3764
+ [, &quot;hour&quot; =&gt; int hour
3765
+ , &quot;min&quot; =&gt; int min
3766
+ , &quot;sec&quot; =&gt; int sec
3767
+ [, &quot;tz&quot; =&gt; mixed tz ]] )
3768
+ date = array( &quot;timestamp&quot; =&gt; int timestamp [, &quot;tz&quot; =&gt; mixed tz])
3769
+ date = string datestring // <span class="ref">string date,
3770
+ acceptable by strtotime-command,
3771
+ ex.&nbsp;&quot;14 august 2006 16.00.00&quot;
3772
+ (notice <a class="ref" href="#date_restriction">date restriction</a>)</span>
3773
+ tz = &lt;timezone identifier&gt; / offset
3774
+ (timezone will be used as tzidparam (below), if tzidparam not set)
3775
+ offset = (+/-)HHmm[ss], local date + UTC offset =&gt; <a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME
3776
+ params<span class="ref">2</span> = array([(datetimeparam/dateparam)&nbsp;/ tzidparam] [,xparam])
3777
+ datetimeparam = &quot;VALUE&quot; =&gt; &quot;DATE-TIME&quot; // <span class="ref">default, output as date-time</span>
3778
+ dateparam = &quot;VALUE&quot; =&gt; &quot;DATE&quot; // <span class="ref">output as DATE</span>
3779
+ tzidparam = &quot;TZID&quot; =&gt; &lt;timezone identifier&gt;
3780
+ xparams = *[ xparamkey =&gt; xparamvalue ]
3781
+ propOrderNo = int ordernumber, 1=1st, 2=2nd etc</p>
3782
+ <p class="label">Example 1</p>
3783
+ <p class="example">$vevent->setProperty( &quot;exdate&quot;
3784
+ , array( array( 2006, 8, 14, 16, 0, 0 ));
3785
+ <span class="ref">// >exclude 2006-08-14 16.00.00 (local date) from recurrence pattern</span></p>
3786
+ <p class="label">Example 2</p>
3787
+ <p class="example">$vevent->setProperty( &quot;exdate&quot;
3788
+ , array( array('year' =&gt;,2006,'month' =&gt; 8,'day'=&gt; 11))
3789
+ , array( 'VALUE' =&gt; 'DATE' ));
3790
+ <span class="ref">// exclude 2006-08-11 from recurrence pattern;</span></p>
3791
+ <br />
3792
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
3793
+
3794
+
3795
+ <a name="EXRULE"></a><h3>3.2.21 EXRULE</h3>
3796
+ This property defines a rule or repeating pattern for an exception to a recurrence set and is OPTIONAL and MAY occur more than once in <a href="#VEVENT">VEVENT</a>, <a href="#VTODO">VTODO</a>, <a href="#VJOURNAL">VJOURNAL</a> components.
3797
+ <h5>Delete EXRULE</h5>
3798
+ Remove EXRULE from component.
3799
+ <p class="label">Format</p>
3800
+ <p class="format">deleteProperty( &quot;EXRULE&quot; )</p>
3801
+ <p class="label">Example 1</p>
3802
+ <p class="example">$vtodo->deleteProperty( &quot;EXRULE&quot; );</p>
3803
+ <p class="label">Example 2</p>
3804
+ Delete EXRULE property no 2.
3805
+ <p class="example">$vjournal->deleteProperty( &quot;EXRULE&quot;, 2 );</p>
3806
+ <p class="label">Example 3</p>
3807
+ Deleting all EXRULE properties.
3808
+ <p class="example">while( $vjournal->deleteProperty( &quot;EXRULE&quot; ))
3809
+ continue;</p>
3810
+ <h5>Get EXRULE</h5>
3811
+ Fetch property value.
3812
+ <p class="label">Format 1</p>
3813
+ <p class="format">getProperty( &quot;EXRULE&quot; )</p>
3814
+ <p class="comment">output = recur<span class="ref">1</span></p>
3815
+ <p class="label">Format 2</p>
3816
+ <p class="format">getProperty( &quot;exrule&quot;, propOrderNo/FALSE, TRUE )</p>
3817
+ <p class="comment">output = array( &quot;value&quot; =&gt; recur<span class="ref">1</span>
3818
+ , &quot;params&quot; =&gt; xparam<span class="ref">2</span> )</p>
3819
+ <p class="label">Format 3</p>
3820
+ <p class="format">getProperty( &quot;EXRULE&quot;, propOrderNo )</p>
3821
+ <p class="comment">Get propOrderNo EXRULE</p>
3822
+ <p class="label">Example</p>
3823
+ <p class="example">$exrule = $vtodo->getProperty( &quot;exrule&quot; );</p>
3824
+ <h5>Set EXRULE</h5>
3825
+ Insert property value.
3826
+ <br />
3827
+ Parameters, will be ordered as prescribed in rcf2445.
3828
+ <p class="label">Format</p>
3829
+ <p class="format">setProperty( &quot;exrule&quot;, recur [, xparams [, propOrderNo ]] )</p>
3830
+ See rules in detail in RFC2445 - Internet Calendaring and Scheduling Core Object Specification (iCalendar) in <a href="http://www.kigkonsult.se/iCalcreator/downloads/dl.php?f=rfc2445" title="RFC2445 in text format"><b>text</b></a>
3831
+ and <a href="http://www.kigkonsult.se/iCalcreator/iCalDictionary/index.html" title="RFC2445 in HTML format" target="_blank"><b>HTML</b></a> format.
3832
+ <p class="comment">recur<span class="ref">1</span> = array( "FREQ"=&gt;freq
3833
+ // <span class="ref">either UNTIL or COUNT may appear in a &quot;recur&quot;,
3834
+ but UNTIL and COUNT MUST NOT occur in the same &quot;recur&quot;</span>
3835
+ [, &quot;UNTIL&quot; &quot;=&gt;&quot; >enddate ]
3836
+ [, &quot;COUNT&quot; &quot;=&gt;&quot; 1*DIGIT ]
3837
+ // <span class="ref">the rest of these keywords are optional,
3838
+ but MUST NOT occur more than once</span>
3839
+ [, &quot;INTERVAL&quot; &quot;=&gt;&quot; 1*DIGIT ]
3840
+ [, &quot;BYSECOND&quot; &quot;=&gt;&quot; byseclist ]
3841
+ [, &quot;BYMINUTE&quot; &quot;=&gt;&quot; byminlist ]
3842
+ [, &quot;BYHOUR&quot; &quot;=&gt;&quot; byhrlist ]
3843
+ [, &quot;BYDAY&quot; &quot;=&gt;&quot; bywdaylist ]
3844
+ [, &quot;BYMONTHDAY&quot; &quot;=&gt;&quot; bymodaylist ]
3845
+ [, &quot;BYYEARDAY&quot; &quot;=&gt;&quot; byyrdaylist ]
3846
+ [, &quot;BYWEEKNO&quot; &quot;=&gt;&quot; bywknolist ]
3847
+ [, &quot;BYMONTH&quot; &quot;=&gt;&quot; bymolist ]
3848
+ [, &quot;BYSETPOS&quot; &quot;=&gt;&quot; bysplist ]
3849
+ [, &quot;WKST&quot; &quot;=&gt;&quot; weekday ]
3850
+ [, x-name &quot;=&gt;&quot; text ] )
3851
+ freq = &quot;SECONDLY&quot; /
3852
+ &quot;MINUTELY&quot; /
3853
+ &quot;HOURLY&quot; /
3854
+ &quot;DAILY&quot; /
3855
+ &quot;WEEKLY&quot; /
3856
+ &quot;MONTHLY&quot; /
3857
+ &quot;YEARLY&quot;
3858
+ enddate = date
3859
+ enddate = / date-time ;An <a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME value
3860
+ byseclist = seconds
3861
+ byseclist = array(seconds *(, seconds ))
3862
+ seconds = 1DIGIT / 2DIGIT ;0 to 59
3863
+ byminlist = minutes
3864
+ byminlist = array( minutes *(, minutes ))
3865
+ minutes = 1DIGIT / 2DIGIT ;0 to 59
3866
+ byhrlist = hour
3867
+ byhrlist = array( hour *(, hour ))
3868
+ hour = 1DIGIT / 2DIGIT ;0 to 23
3869
+ bywdaylist = weekdaynum
3870
+ bywdaylist = array( weekdaynum *("," weekdaynum ))
3871
+ weekdaynum = array( [([plus] ordwk / minus ordwk)], &quot;DAY&quot; =&gt; weekday )
3872
+ plus = &quot;+&quot;
3873
+ minus = &quot;-&quot;
3874
+ ordwk = 1DIGIT / 2DIGIT ;1 to 53
3875
+ weekday = &quot;SU&quot; / &quot;MO&quot; / &quot;TU&quot; / &quot;WE&quot; / &quot;TH&quot; / &quot;FR&quot; / &quot;SA&quot;
3876
+ ; Corresponding to
3877
+ ; SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY,
3878
+ ; FRIDAY, SATURDAY and SUNDAY days of the week.
3879
+ bymodaylist = monthdaynum
3880
+ bymodaylist = array( monthdaynum *(, monthdaynum ))
3881
+ monthdaynum = ( [plus] ordmoday ) / ( minus ordmoday )
3882
+ ordmoday = 1DIGIT / 2DIGIT ;1 to 31
3883
+ byyrdaylist = yeardaynum
3884
+ byyrdaylist = array( yeardaynum *(, yeardaynum ))
3885
+ yeardaynum = ( [plus] ordyrday ) / ( minus ordyrday )
3886
+ ordyrday = 1DIGIT / 2DIGIT / 3DIGIT ;1 to 366
3887
+ bywknolist = weeknum
3888
+ bywknolist = array( weeknum *(, weeknum ))
3889
+ weeknum = ( [plus] ordwk ) / ( minus ordwk )
3890
+ bymolist = monthnum
3891
+ bymolist = array( monthnum *(, monthnum ))
3892
+ monthnum = 1DIGIT / 2DIGIT ;1 to 12
3893
+ bysplist = setposday
3894
+ bysplist = array( setposday *(, setposday ))
3895
+ setposday = yeardaynum</p>
3896
+ <p class="comment">
3897
+ xparam<span class="ref">2</span> = array( *[ xparamkey =&gt; xparamvalue ] )
3898
+ propOrderNo = int ordernumber, 1=1st, 2=2nd etc</p>
3899
+ <p class="label">Example</p>
3900
+ <p class="example">$vevent->setProperty(&nbsp;&quot;Exrule&quot;
3901
+ ,&nbsp;array( &quot;FREQ&quot; =&gt; &quot;MONTHLY&quot;
3902
+ , &quot;UNTIL&quot; =&gt; &quot;20060831&quot;
3903
+ // <span class="ref">DATE / DATE-TIME in <a href="#DATE_WITH_UTC_TIME">UTC</a> format; string/array, see <a href="#CREATED">CREATED</a> format</span>
3904
+ , &quot;INTERVAL&quot; =&gt; 2
3905
+ , &quot;WKST&quot; =&gt; &quot;SU&quot;
3906
+ , &quot;BYSECOND&quot; =&gt; 2
3907
+ , &quot;BYMINUTE&quot; =&gt; array( 2, -4, 6 ) // (*)
3908
+ , &quot;BYHOUR&quot; =&gt; array( 2, 4, -6 ) // (*)
3909
+ , &quot;BYMONTHDAY&quot; =&gt; -2 // (*)
3910
+ , &quot;BYYEARDAY&quot; =&gt; 2 // (*)
3911
+ , &quot;BYWEEKNO&quot; =&gt; array( 2, -4, 6 ) // (*)
3912
+ , &quot;BYMONTH&quot; =&gt; 2 // (*)
3913
+ , &quot;BYSETPOS&quot; =&gt; array( 2, -4, 6 ) // (*)
3914
+ , &quot;BYday&quot; =&gt; array( array(-2, &quot;DAY&quot; =&gt; &quot;WE&quot; )
3915
+ , array( 3, &quot;DAY&quot; =&gt; &quot;TH&quot;)
3916
+ , array( 5, &quot;DAY&quot; =&gt; &quot;FR&quot;)
3917
+ , array( &quot;DAY&quot; =&gt; &quot;MO&quot;))
3918
+ // (**)
3919
+ , &quot;X-NAME&quot; =&gt; &quot;x-value&quot; )
3920
+ , array( &quot;xparamkey&quot; =&gt; &quot;xparamValue&quot; ));
3921
+
3922
+ $vtodo->setProperty( >&quot;exrule&quot;
3923
+ , array( &quot;FREQ&quot; =&gt; &quot;WEEKLY&quot;
3924
+ , &quot;COUNT&quot; =&gt; 2
3925
+ , &quot;INTERVAL&quot; =&gt; 2
3926
+ , &quot;WKST&quot; =&gt; &quot;SU&quot;
3927
+ , &quot;BYSECOND&quot; =&gt; array( -2, 4, 6 ) // (*)
3928
+ , &quot;BYMINUTE&quot; =&gt; -2 // (*)
3929
+ , &quot;BYHOUR&quot; =&gt; 2 // (*)
3930
+ , &quot;BYMONTHDAY&quot; =&gt; array( 2, -4, 6 ) // (*)
3931
+ , &quot;BYYEARDAY&quot; =&gt; array( -2, 4, 6 ) // (*)
3932
+ , &quot;BYWEEKNO&quot; =&gt; -2 // (*)
3933
+ , &quot;BYMONTH&quot; =&gt; array( 2, 4, -6 ) // (*)
3934
+ , &quot;BYSETPOS&quot; =&gt; -2 // (*)
3935
+ , &quot;BYday&quot; =&gt; array( 5, &quot;DAY&quot; =&gt; &quot;WE&quot; )
3936
+ // (**)
3937
+ , &quot;X-NAME&quot; =&gt; &quot;x-value&quot; )
3938
+ , array( &quot;xparamkey&quot; =&gt; &quot;xparamValue&quot; ));
3939
+ //<span class="ref">(*) single value/array of values</span>
3940
+ //<span class="ref">(**) single value array /array of arrays</span>
3941
+ </p>
3942
+ <br />
3943
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
3944
+
3945
+
3946
+ <a name="FREEBUSY_PROP"></a><h3>3.2.22 FREEBUSY</h3>
3947
+ The property defines one or more free or busy time intervals in a <a href="#VFREEBUSY">VFREEBUSY</a> calendar component.<br /><br />
3948
+ The value type for FREEBUSY is PERIOD. A PERIOD is a DATE-TIME/DATE-TIME or a DATE-TIME/duration.
3949
+ <h5>Delete FREEBUSY</h5>
3950
+ Remove FREEBUSY from component.
3951
+ <p class="label">Format</p>
3952
+ <p class="format">deleteProperty( &quot;FREEBUSY&quot; )</p>
3953
+ <p class="label">Example 1</p>
3954
+ <p class="example">$vfreebusy->deleteProperty( &quot;FREEBUSY&quot; );</p>
3955
+ <p class="label">Example 2</p>
3956
+ Delete FREEBUSY property no 2.
3957
+ <p class="example">$vfreebusy->deleteProperty( &quot;FREEBUSY&quot;, 2 );</p>
3958
+ <p class="label">Example 3</p>
3959
+ Deleting all FREEBUSY properties.
3960
+ <p class="example">while( $vfreebusy->deleteProperty( &quot;FREEBUSY&quot; ))
3961
+ continue;</p>
3962
+ <h5>Get FREEBUSY</h5>
3963
+ Fetch property value.
3964
+ <p class="label">Format 1</p>
3965
+ <p class="format">getProperty( &quot;FREEBUSY&quot; )</p>
3966
+ <p class="comment">output = array( &quot;fbtyp&quot; =&gt; freebusytype<span class="ref">1</span> , periods<span class="ref">2</span> )</p>
3967
+ <p class="label">Format 3</p>
3968
+ <p class="format">getProperty( &quot;FREEBUSY&quot;, propOrderNo/FALSE , TRUE )</p>
3969
+ <p class="comment">output = array( &quot;value&quot; =&gt; array(&quot;fbtype&quot; =&gt; freebusytype<span class="ref">1</span> ,periods<span class="ref">2</span>)
3970
+ , &quot;params&quot; =&gt; xparams<span class="ref"> 3</span> )</p>
3971
+ <p class="label">Format 3</p>
3972
+ <p class="format">getProperty( &quot;FREEBUSY&quot;, propOrderNo )</p>
3973
+ <p class="comment">Get propOrderNo FREEBUSY</p>
3974
+ <p class="label">Example</p>
3975
+ <p class="example">$freebusy = $vfreebusy->getProperty( &quot;FREEBUSY&quot; );</p>
3976
+ <h5>Set FREEBUSY</h5>
3977
+ Insert property value. A FREEBUSY input date is always a <a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME.
3978
+ <p class="label">Format</p>
3979
+ <p class="format">setProperty( &quot;freebusy&quot;,freebusytype,fbperiods [,xparams [,propOrderNo ]] )</p>
3980
+ <p class="comment">freebusytype<span class="ref">1</span> = one of &quot;FREE&quot;
3981
+ / &quot;BUSY&quot; <b>Default</b>
3982
+ / &quot;BUSY-UNAVAILABLE&quot;
3983
+ / &quot;BUSY-TENTATIVE&quot;
3984
+ / x-name
3985
+ fbperiods = array( periods<span class="ref">2</span> )&nbsp;
3986
+ periods<span class="ref">2</span> = array( startdate, enddate/duration )
3987
+ *[, array( startdate, enddate/duration )]
3988
+ startdate/enddate = array( int year
3989
+ , int month
3990
+ , int day
3991
+ , int int hour
3992
+ , int min
3993
+ , int day )
3994
+ startdate/enddate = array( &quot;year&quot; =&gt; int year
3995
+ , &quot;month&quot; =&gt; int month
3996
+ , &quot;day&quot; =&gt; int day
3997
+ , &quot;hour&quot; =&gt; int hour
3998
+ , &quot;min&quot; =&gt; int min
3999
+ , &quot;sec&quot; =&gt; int sec ) // <span class="ref">output format</span>
4000
+ startdate/enddate = array( &quot;timestamp&quot; =&gt; int timestamp )
4001
+ startdate/enddate = string datestring // <span class="ref">string date,
4002
+ acceptable by strtotime-command,
4003
+ ex.&nbsp;&quot;14 august 2006 16.00.00&quot;
4004
+ (notice <a class="ref" href="#date_restriction">date restriction</a>)</span>
4005
+ startdate/enddate : date and time values MUST be an <a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME
4006
+ duration = array( int week/false
4007
+ [, int day/false
4008
+ , int hour
4009
+ , int min
4010
+ , int sec] )
4011
+ duration = array( &quot;week&quot; =&gt; int week/false
4012
+ [, &quot;day&quot; =&gt; int day/false
4013
+ [, &quot;hour&quot; =&gt; int hour
4014
+ , &quot;min&quot; =&gt; int min
4015
+ , &quot;sec&quot; =&gt; int sec ]] ); // <span class="ref">output format</span>
4016
+ duration = array( &quot;sec&quot; =&gt; int sec )
4017
+ duration = string dur-value
4018
+ = ([&quot;+&quot;]/&quot;-&quot;) &quot;P&quot; (dur-date/dur-time/dur-week)
4019
+ dur-date = dur-day [dur-time]
4020
+ dur-time = &quot;T&quot; (dur-hour / dur-minute / dur-second)
4021
+ dur-week = 1*DIGIT &quot;W&quot;
4022
+ dur-hour = 1*DIGIT &quot;H&quot; [dur-minute]
4023
+ dur-minute = 1*DIGIT &quot;M&quot; [dur-second]
4024
+ dur-second = 1*DIGIT &quot;S&quot;
4025
+ dur-day = 1*DIGIT &quot;D&quot;
4026
+ xparams<span class="ref">3</span> = array( *[ xparamkey =&gt; xparamvalue ] )
4027
+ propOrderNo = int ordernumber, 1=1st, 2=2nd etc</p>
4028
+ <p class="label">Example</p>
4029
+ See rules in detail in RFC2445 - Internet Calendaring and Scheduling Core Object Specification (iCalendar) in <a href="http://www.kigkonsult.se/downloads/dl.php?f=rfc2445" title="RFC2445 in text format"><b>text</b></a>
4030
+ and <a href="http://www.kigkonsult.se/iCalcreator/iCalDictionary/index.html" title="RFC2445 in HTML format" target="_blank"><b>HTML</b></a> format.
4031
+ <p class="example">$fdate1 = array ( 2001, 1, 1, 1, 1, 1 );
4032
+ alt.
4033
+ $fdate1 = array ( &quot;year&quot; =&gt; 2001
4034
+ , &quot;month&quot; =&gt; 1
4035
+ , &quot;day&quot; =&gt; 1
4036
+ , &quot;hour&quot; =&gt; 1
4037
+ , &quot;min&quot; =&gt; 1
4038
+ , &quot;sec&quot; =&gt; 1 );
4039
+ $fdate2 = array ( 2002, 2, 2, 2, 2, 2 );
4040
+ $fdate3 = array ( 2003, 3, 3, 3, 3, 3 );
4041
+ $fdate4 = &quot;4 April 2005 4:4:4&quot;;
4042
+ $fdate7 = array ( &quot;year&quot; =&gt; 2007
4043
+ , &quot;month&quot; =&gt; 7
4044
+ , &quot;day&quot; =&gt; 7 );
4045
+ $fdur6 = array ( &quot;week&quot; =&gt; 0
4046
+ , &quot;day&quot; =&gt; 5
4047
+ , &quot;hour&quot; =&gt; 5
4048
+ , &quot;min&quot; =&gt; 5
4049
+ , &quot;sec&quot; =&gt; 5 );
4050
+ $fdur7 = array ( 0, 0, 6 ); // <span class="ref">duration for 6 hours</span>
4051
+ $fdur8 = &quot;P2D&quot;; // <span class="ref">duration two days</span>
4052
+ $freebusy->setProperty &quot;freebusy&quot;
4053
+ , &quot;FREE&quot;
4054
+ , array( array( $fdate1, $fdate2 )
4055
+ , array( $fdate3, $fdur6 )
4056
+ , array( $fdate4, $fdate5 )));
4057
+ $freebusy->setProperty(&quot;freebusy&quot;
4058
+ , &quot;Busy&quot;
4059
+ , array( array( array( $fdate1, $fdate2 )
4060
+ , array( $fdate3, $fdur8 )
4061
+ , array( $fdate4, $fdur7 )
4062
+ , array( $fdate1, $fdate3 )));</p>
4063
+ <br />
4064
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
4065
+
4066
+
4067
+ <a name="GEO"></a><h3>3.2.23 GEO</h3>
4068
+ This property specifies information related to the global position for the activity specified by VEVENT and VTODO components and is OPTIONAL and MUST NOT occur more than once.
4069
+ <br /><br />
4070
+ Value type for latitude and longitude is FLOAT. &quot;Values for latitude and longitude shall be expressed as decimal fractions of degrees. Whole degrees of latitude shall be represented by a two-digit decimal number ranging from 0 through 90. Whole degrees of longitude shall be represented by a decimal number ranging from 0 through 180. When a decimal fraction of a degree is specified, it shall be separated from the whole number of degrees by a decimal point.&quot;
4071
+ <h5>Delete GEO</h5>
4072
+ Remove GEO from component.
4073
+ <p class="label">Format</p>
4074
+ <p class="format">deleteProperty( &quot;GEO&quot; )</p>
4075
+ <p class="label">Example</p>
4076
+ <p class="example">$vevent->deleteProperty( &quot;FREEBUSY&quot; );</p>
4077
+ <h5>Get GEO</h5>
4078
+ Fetch property value.
4079
+ <p class="label">Format 1</p>
4080
+ <p class="format">getProperty( &quot;GEO&quot; )</p>
4081
+ <p class="comment">output = array( &quot;latitude&quot; =&gt; &lt;latitude&gt;
4082
+ , &quot;longitude&quot; =&gt; &lt;longitude&gt;))</p>
4083
+ <p class="label">Format 2</p>
4084
+ <p class="format">getProperty( &quot;GEO&quot;, FALSE , TRUE )</p>
4085
+ <p class="comment">output = array( &quot;value&quot; =&gt; array ( &quot;latitude&quot; =&gt; &lt;latitude&gt;
4086
+ , &quot;longitude&quot; =&gt; &lt;longitude&gt;))
4087
+ , &quot;params&quot; =&gt; xparam <span class="ref">1</span> )</p>
4088
+ <p class="label">Example</p>
4089
+ <p class="example">$geo = $vevent->getProperty( &quot;GEO&quot; );</p>
4090
+ <h5>Set GEO</h5>
4091
+ Insert property value.
4092
+ <p class="label">Format</p>
4093
+ <p class="format">setProperty( &quot;geo&quot;, float latitude, float longitude [, xparam ] )</p>
4094
+ <p class="comment">xparam <span class="ref">1</span> = array( *[ xparamkey =&gt; xparamvalue ] )</p>
4095
+ <p class="label">Example</p>
4096
+ <p class="example">$vevent->setProperty( &quot;geo&quot;, 11.23456, -23.45678 );</p>
4097
+ <br />
4098
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
4099
+
4100
+
4101
+ <a name="LAST-MODIFIED"></a><h3>3.2.24 LAST-MODIFIED</h3>
4102
+ The property specifies the date and time that the information associated with the calendar component was last revised in the calendar store. The property is OPTIONAL and MUST NOT occur more than once in <a href="#VEVENT">VEVENT</a>, <a href="#VTODO">VTODO</a>, <a href="#VJOURNAL">VJOURNAL</a> and <a href="#VTIMEZONE">VTIMEZONE</a> components.<br /><br />
4103
+ The value type for LAST-MODIFIED is <a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME.
4104
+ <h5>Delete LAST-MODIFIED</h5>
4105
+ Remove LAST-MODIFIED from component.
4106
+ <p class="label">Format</p>
4107
+ <p class="format">deleteProperty( &quot;LAST-MODIFIED&quot; )</p>
4108
+ <p class="label">Example</p>
4109
+ <p class="example">$vevent->deleteProperty( &quot;LAST-MODIFIED&quot; );</p>
4110
+ <h5>Get LAST-MODIFIED</h5>
4111
+ Fetch property value.
4112
+ <p class="label">Format 1</p>
4113
+ <p class="format">getProperty( &quot;LAST-MODIFIED&quot; )</p>
4114
+ <p class="comment">output = moddate<span class="ref">1</span></p>
4115
+ <p class="label">Format 2</p>
4116
+ <p class="format">getProperty( &quot;LAST-MODIFIED&quot;, FALSE , TRUE )</p>
4117
+ <p class="comment">output = array( &quot;value&quot; =&gt; moddate<span class="ref">1</span>
4118
+ , &quot;params&quot; =&gt; xparam<span class="ref">2</span> )</p>
4119
+ <p class="label">Example</p>
4120
+ <p class="example">$lastMod = $vevent->getProperty( &quot;LAST-MODIFIED&quot; );</p>
4121
+ <h5>Set LAST-MODIFIED</h5>
4122
+ Insert property value. Input date is always a <a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME or, if &quot;offset&quot; parameter is used, converted to a <a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME.
4123
+ <p class="label">Format</p>
4124
+ <p class="format">setProperty( &quot;Last-Modified&quot; [, moddate [, xparam ]] )</p>
4125
+ <p class="comment">moddate<span class="ref">1</span> = array( &quot;year&quot; =&gt; int year
4126
+ , &quot;month&quot; =&gt; int month
4127
+ , &quot;day&quot; =&gt; int day
4128
+ [, &quot;hour&quot; =&gt; int hour
4129
+ , &quot;min&quot; =&gt; int min
4130
+ , &quot;sec&quot; =&gt; int sec
4131
+ , &quot;tz&quot; =&gt; offset ]] )
4132
+ completedDate = int year
4133
+ , int month
4134
+ , int day
4135
+ [, int hour
4136
+ , int min
4137
+ , int sec ]
4138
+ completedDate = array( int year
4139
+ , int month
4140
+ , int day
4141
+ [, int hour
4142
+ , int min
4143
+ , int sec
4144
+ [, offset ]] )
4145
+ completedDate = array ( &quot;timestamp&quot; =&gt; int timestamp [, &quot;tz&quot; => offset])
4146
+ completedDate = string datestring // <span class="ref">string date,
4147
+ acceptable by strtotime-command,
4148
+ ex. &nbsp;&quot;14 august 2006 16.00.00&quot;
4149
+ (notice <a class="ref" href="#date_restriction">date restriction</a>)</span>
4150
+ offset = (+/-)HHmm[ss], local date + UTC offset =&gt; <a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME
4151
+ xparam<span class="ref">2</span> = array( *[ xparamkey =&gt; xparamvalue ] )</p>
4152
+ <p class="label">Example 1</p>
4153
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot; );
4154
+ $vcalendar = new vcalendar( $config );
4155
+ $vtodo = & $vcalendar->newComponent( 'vtodo' );
4156
+ .. .
4157
+ $vtodo->setProperty(&quot;last-modified&quot;
4158
+ , <td>2006, 8, 14, 12, 1, 2 );
4159
+ <span class="ref">// 14 august 2006 12.01.02 UTC</span></p>
4160
+ <p class="label">Example 2</p>
4161
+ <p class="example">$date = array(&quot;year&quot; =&gt; 2006, &quot;month&quot; =&gt; 10, &quot;day&quot; =&gt; 10,
4162
+ &quot;hour&quot; =&gt; 10, &quot;min&quot; =&gt; 0, &quot;sec&quot; =&gt; 0, &quot;tz&quot; =&gt; &quot;+0200&quot;);
4163
+ <span class="ref">// local date + UTC offset =&gt; <a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME</span>
4164
+ $vtodo->setProperty( &quot;last-modified&quot;, $date );
4165
+ .. .</p>
4166
+ <p class="label">Example 3</p>
4167
+ <p class="example">$vevent->setProperty( &quot;last-modified&quot; );
4168
+ <span class="ref">// current UTC DATE-TIME is set if called without parameters</span></p>
4169
+ <br />
4170
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
4171
+
4172
+ <a name="LOCATION"></a><h3>3.2.25 LOCATION</h3>
4173
+ The property defines the intended venue for the activity defined by a calendar component. The property is OPTIONAL and MUST NOT occur more than once in <a href="#VEVENT">VEVENT</a> and <a href="#VTODO">VTODO</a> components.
4174
+ <br /><br />
4175
+ The value type for LOCATION is TEXT.
4176
+ <h5>Delete LOCATION</h5>
4177
+ Remove LOCATION from component.
4178
+ <p class="label">Format</p>
4179
+ <p class="format">deleteProperty( &quot;LOCATION&quot; )</p>
4180
+ <p class="label">Example</p>
4181
+ <p class="example">$vevent->deleteProperty( &quot;LOCATION&quot; );</p>
4182
+ <h5>Get LOCATION</h5>
4183
+ Fetch property value.
4184
+ <p class="label">Format 1</p>
4185
+ <p class="format">getProperty( &quot;LOCATION&quot; )</p>
4186
+ <p class="comment">output = location<span class="ref">1</span></p>
4187
+ <p class="label">Format 2</p>
4188
+ <p class="format">getProperty( &quot;LOCATION&quot;, FALSE , TRUE )</p>
4189
+ <p class="comment">output = array( &quot;value&quot; =&gt; location<span class="ref">1</span>
4190
+ , &quot;params&quot; =&gt; param<span class="ref">2</span> )</p>
4191
+ <p class="label">Example</p>
4192
+ <p class="example">$location = $vevent->getProperty( &quot;LOCATION&quot; );</p>
4193
+ <h5>Set LOCATION</h5>
4194
+ Insert property value.
4195
+ <br />
4196
+ Parameters, if any, will be ordered as prescribed in rcf2445.
4197
+ <p class="label">Format</p>
4198
+ <p class="format">setProperty( &quot;location&quot;, string location [, array param] )</p>
4199
+ <p class="comment">location<span class="ref">1</span> = Value type TEXT
4200
+ params<span class="ref">2</span> = array( [&quot;ALTREP&quot; =&gt; &quot;&lt;an alternate text representation, URI&gt;&quot;]
4201
+ [, &quot;LANGUAGE&quot; =&gt; &quot;&lt;lang&gt;&quot;]
4202
+ [, xparam ]
4203
+ xparam = *[ xparamkey =&gt; xparamvalue ]</p>
4204
+ <p class="label">Example</p>
4205
+ <p class="example">$vevent->setProperty( &quot;location&quot;, &quot;Buckingham Palace&quot; );</p>
4206
+ <br />
4207
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
4208
+
4209
+
4210
+ <a name="ORGANIZER"></a><h3>3.2.26 ORGANIZER</h3>
4211
+ The property defines the organizer for a calendar component and is OPTIONAL and MUST NOT occur more than once in <a href="#VEVENT">VEVENT</a>, <a href="#VTODO">VTODO</a>, <a href="#VJOURNAL">VJOURNAL</a> and <a href="#VFREEBUSY">VFREEBUSY</a> components.<br /><br />
4212
+ This value type for ORGANIZER is URI, a calendar user address.
4213
+ <h5>Delete ORGANIZER</h5>
4214
+ Remove ORGANIZER from component.
4215
+ <p class="label">Format</p>
4216
+ <p class="format">deleteProperty( &quot;ORGANIZER&quot; )</p>
4217
+ <p class="label">Example</p>
4218
+ <p class="example">$vevent->deleteProperty( &quot;ORGANIZER&quot; );</p>
4219
+ <h5>Get ORGANIZER</h5>
4220
+ Fetch property value.
4221
+ <p class="label">Format 1</p>
4222
+ <p class="format">getProperty( &quot;ORGANIZER&quot; )</p>
4223
+ <p class="comment">output = organizer<span class="ref">1</span></p>
4224
+ <p class="label">Format 2</p>
4225
+ <p class="format">getProperty( &quot;ORGANIZER&quot;, FALSE , TRUE )</p>
4226
+ <p class="comment">output = array( &quot;value&quot; =&gt; organizer<span class="ref">1</span>
4227
+ , &quot;params&quot; =&gt; params<span class="ref">2</span> )</p>
4228
+ <p class="label">Example</p>
4229
+ <p class="example">$organizer = $vevent->getProperty( &quot;ORGANIZER&quot; );</p>
4230
+ <h5>Set ORGANIZER</h5>
4231
+ Insert property value.
4232
+ Property value must be prefixed by protocol (ftp://, http://,mailto:, file://.. . ref. rfc 1738 ).
4233
+ Also DIR parameter must be prefixed by protocol.
4234
+ SENT-BY parameter must use protocol &quot;mailto:&quot;, prefixed if missing.
4235
+ <br />
4236
+ Parameters, if any, will be ordered as prescribed in rcf2445.
4237
+ <p class="label">Format</p>
4238
+ <p class="format">setProperty( &quot;organizer&quot;, organizer [, params] )</p>
4239
+ <p class="comment">organizer<span class="ref">1</span> = a calendar user address, a URI as defined by [RFC
4240
+ 1738] or any other IANA registered form for a URI.
4241
+ params<span class="ref">2</span> = array( [&quot;LANGUAGE&quot; =&gt; &quot;&lt;lang&gt;&quot;
4242
+ (applies to the CN parameter value) ]
4243
+ [, &quot;CN&quot; =&gt; &quot;common name to be associated
4244
+ with the calendar user
4245
+ specified by the property&quot;]
4246
+ [, &quot;DIR&quot; =&gt; &quot;reference to a directory
4247
+ entry associated with the calendar user
4248
+ specified by the property&quot; ]
4249
+ [, &quot;SENT-BY&quot; =&gt; &quot;single calendar user
4250
+ that is acting on behalf
4251
+ of the calendar user
4252
+ specified by the property&quot; ]
4253
+ [, xparam ]
4254
+ xparam = *[ xparamkey =&gt; xparamvalue ]</p>
4255
+ <p class="label">Example</p>
4256
+ <p class="example">
4257
+ $dir = &quot;ldap://domain.com:6666/o=3DDC%20Comp,c=3DUS??(cn=3DJohn%20Doe)&quot;;
4258
+ $vevent-&gt;setProperty( &quot;organizer&quot;
4259
+ , &quot;ical@domain.com&quot;
4260
+ , array( &quot;CN&quot; =&gt; &quot;John Doe&quot;
4261
+ , &quot;DIR&quot; =&gt; $dir
4262
+ , &quot;SENT-BY&quot; =&gt; &quot;secretary@domain.com&quot;
4263
+ , &quot;X-Key1&quot; =&gt; &quot;X-Value1&quot;
4264
+ , &quot;X-Key2&quot; =&gt; &quot;X-Value2&quot; ));</p>
4265
+ <br />
4266
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
4267
+
4268
+
4269
+ <a name="PERCENT-COMPLETE"></a><h3>3.2.27 PERCENT-COMPLETE</h3>
4270
+ This property is used by an assignee or delegatee of a <a href="#VTODO">VTODO</a> to convey the percent completion of a <a href="#VTODO">VTODO</a> to the Organizer and is OPTIONAL and MUST NOT occur more than once.<br /><br />
4271
+ The property value is a positive integer between zero and one hundred. A value of "0" indicates the <a href="#VTODO">VTODO</a> has not yet been started. A value of "100" indicates that the <a href="#VTODO">VTODO</a> has been completed. Integer values in between indicate the percent partially complete.
4272
+ <h5>Delete PERCENT-COMPLETE</h5>
4273
+ Remove PERCENT-COMPLETE from component.
4274
+ <p class="label">Format</p>
4275
+ <p class="format">deleteProperty( &quot;PERCENT-COMPLETE&quot; )</p>
4276
+ <p class="label">Example</p>
4277
+ <p class="example">$vtodo->deleteProperty( &quot;PERCENT-COMPLETE&quot; );</p>
4278
+ <h5>Get PERCENT-COMPLETE</h5>
4279
+ Fetch property value.
4280
+ <p class="label">Format 1</p>
4281
+ <p class="format">getProperty( &quot;PERCENT-COMPLETE&quot; )</p>
4282
+ <p class="comment">output = percent<span class="ref">1</span></p>
4283
+ <p class="label">Format 2</p>
4284
+ <p class="format">getProperty( &quot;PRIORITY&quot;, FALSE , TRUE )</p>
4285
+ <p class="comment">output = array( &quot;value&quot; =&gt; percent<span class="ref">1</span>
4286
+ , &quot;params&quot; =&gt; xparam<span class="ref">2</span> )</p>
4287
+ <p class="label">Example</p>
4288
+ <p class="example">$percent = $vtodo->getProperty( &quot;PERCENT-COMPLETE&quot; );</p>
4289
+ <h5>Set PERCENT-COMPLETE</h5>
4290
+ Insert property value.
4291
+ <p class="label">Format</p>
4292
+ <p class="format">setProperty( &quot;Percent-Complete&quot;, percent [, xparam ] )</p>
4293
+ <p class="comment">percent<span class="ref">1</span> = Value type INTEGER
4294
+ xparam<span class="ref">2</span> = array( *[ xparamkey =&gt; xparamvalue ] )</p>
4295
+ <p class="label">Example</p>
4296
+ <p class="example">$vtodo->setProperty( &quot;percent-complete&quot;, 90 );</p>
4297
+ <br />
4298
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
4299
+
4300
+
4301
+ <a name="PRIORITY"></a><h3>3.2.28 PRIORITY</h3>
4302
+ The property defines the relative priority for a calendar component and is OPTIONAL and MUST NOT occur more than once in <a href="#VEVENT">VEVENT</a> and <a href="#VTODO">VTODO</a> components.<br /><br />
4303
+ The priority is specified as an integer in the range zero to nine.<br />
4304
+ A value of zero (US-ASCII decimal 48) specifies an undefined priority.<br />
4305
+ A value of one (US-ASCII decimal 49) is the highest priority.<br />
4306
+ A value of two (US-ASCII decimal 50) is the second highest priority.<br />
4307
+ Subsequent numbers specify a decreasing ordinal priority.<br />
4308
+ A value of nine (US-ASCII decimal 58) is the lowest priority.
4309
+ <h5>Delete PRIORITY</h5>
4310
+ Remove PRIORITY from component.
4311
+ <p class="label">Format</p>
4312
+ <p class="format">deleteProperty( &quot;PRIORITY&quot; )</p>
4313
+ <p class="label">Example</p>
4314
+ <p class="example">$vevent->deleteProperty( &quot;PRIORITY&quot; );</p>
4315
+ <h5>Get PRIORITY</h5>
4316
+ Fetch property value.
4317
+ <p class="label">Format 1</p>
4318
+ <p class="format">getProperty( &quot;PRIORITY&quot; )</p>
4319
+ <p class="comment">output = priority<span class="ref">1</span></p>
4320
+ <p class="label">Format 2</p>
4321
+ <p class="format">getProperty( &quot;PRIORITY&quot;, FALSE , TRUE )</p>
4322
+ <p class="comment">output = array( &quot;value&quot; =&gt; priority<span class="ref">1</span>
4323
+ , &quot;params&quot; =&gt; xparam<span class="ref">2</span> )</p>
4324
+ <p class="label">Example</p>
4325
+ <p class="example">$priority = $vevent->getProperty( &quot;priority&quot; );</p>
4326
+ <h5>Set PRIORITY</h5>
4327
+ Insert property value.
4328
+ <p class="label">Format</p>
4329
+ <p class="format">setProperty( &quot;priority&quot;, priority [, xparam ] )</p>
4330
+ <p class="comment">priority<span class="ref">1</span> = Value type INTEGER
4331
+ xparam<span class="ref">2</span> = array( *[ xparamkey =&gt; xparamvalue ] )</p>
4332
+ <p class="label">Example</p>
4333
+ <p class="example">$vevent->setProperty( &quot;priority&quot;, 3 );</p>
4334
+ <br />
4335
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
4336
+
4337
+
4338
+ <a name="RDATE"></a><h3>3.2.29 RDATE</h3>
4339
+ This property defines the list of date/times for a recurrence set and is OPTIONAL and MAY occur more than once in <a href="#VEVENT">VEVENT</a>, <a href="#VTODO">VTODO</a>, <a href="#VJOURNAL">VJOURNAL</a>, <a href="#VTIMEZONE">STANDARD</a> and <a href="#VTIMEZONE">DAYLIGHT</a> components.<br /><br />
4340
+ The default value type for RDATE is DATE-TIME, can be set to DATE or PERIOD (params <span class="ref">2</span>).
4341
+ <h5>Delete RDATE</h5>
4342
+ Remove RDATE from component.
4343
+ <p class="label">Format</p>
4344
+ <p class="format">deleteProperty( &quot;RDATE&quot; )</p>
4345
+ <p class="label">Example 1</p>
4346
+ <p class="example">$vtodo->deleteProperty( &quot;RDATE&quot; );</p>
4347
+ <p class="label">Example 2</p>
4348
+ Delete RDATE property no 2.
4349
+ <p class="example">$vjournal->deleteProperty( &quot;RDATE&quot;, 2 );</p>
4350
+ <p class="label">Example 3</p>
4351
+ Deleting all RDATE properties.
4352
+ <p class="example">while( $vjournal->deleteProperty( &quot;RDATE&quot; ))
4353
+ continue;</p>
4354
+ <h5>Get RDATE</h5>
4355
+ Fetch property value.
4356
+ <p class="label">Format 1</p>
4357
+ <p class="format">getProperty( &quot;RDATE&quot; )</p>
4358
+ <p class="comment">output = dates<span class="ref">1</span></p>
4359
+ <p class="label">Format 2</p>
4360
+ <p class="format">getProperty( &quot;RDATE&quot;, propOrderNo/FALSE , TRUE )</p>
4361
+ <p class="comment">output = array( &quot;value&quot; =&gt; dates<span class="ref">1</span>
4362
+ , &quot;params&quot; =&gt; params<span class="ref">2</span> )</p>
4363
+ <p class="label">Format 3</p>
4364
+ <p class="format">getProperty( &quot;RDATE&quot;, propOrderNo )</p>
4365
+ <p class="comment">Get propOrderNo RDATE</p>
4366
+ <p class="label">Example</p>
4367
+ <p class="example">$rdates = $vevent->getProperty( &quot;RDATE&quot; );</p>
4368
+ <h5>Set RDATE</h5>
4369
+ Insert property value.<br />
4370
+ If &quot;TZID&quot; is set in params, ex. &quot;TZID&quot; = &quot;CET&quot;, all timezone or offset in dates are ignored and DATE-TIME value type is set.<br />
4371
+ If DATE value type is set in params (&quot;VALUE&quot; = &quot;DATE&quot;), all timezone or offset in dates are ignored.<br />
4372
+ If &quot;PERIOD&quot; is set in params (&quot;VALUE&quot; = &quot;PERIOD&quot;), DATE-TIME value type is set.<br />
4373
+ If no &quot;VALUE&quot; parameter in params, DATE-TIME (default) value type is set.<br />
4374
+ If empty params and offset in 1st date, all remaining dates are set to UTC.<br />
4375
+ If no &quot;TZID&quot; is set in params and timezone in 1st date, all remaining dates are within this timezone and param &quot;TZID&quot; is set.<br />
4376
+ If none of the above rules are applicable, DATE-TIME and local date is set default.
4377
+ <br />
4378
+ Parameters, if any, will be ordered as prescribed in rcf2445.
4379
+ <p class="label">Format</p>
4380
+ <p class="format">setProperty( &quot;rdate&quot;, dates [, params [, propOrderNo ]] )</p>
4381
+ <p class="comment">dates<span class="ref">1</span> = array ( date2 *[, date2 ] )
4382
+ date2 = date
4383
+ date2 = array( startdate, enddate/duration ) ]
4384
+ startdate = date
4385
+ enddate = date
4386
+ date = array( int year
4387
+ , int month
4388
+ , int day
4389
+ [, int int hour
4390
+ , int min
4391
+ , int day
4392
+ , mixed tz ] )
4393
+ date = array( &quot;year&quot; =&gt; int year
4394
+ , &quot;month&quot; =&gt; int month
4395
+ , &quot;day&quot; =&gt; int day
4396
+ [, &quot;hour&quot; =&gt; int hour
4397
+ , &quot;min&quot; =&gt; int min
4398
+ , &quot;sec&quot; =&gt; int sec
4399
+ [, &quot;tz&quot; =&gt; mixed tz ]] )
4400
+ // <span class="ref">output format</span>
4401
+ date = array( &quot;timestamp&quot; =&gt; int timestamp
4402
+ [, &quot;tz&quot; =&gt; mixed tz ] )
4403
+ date = string datestring // <span class="ref">string date,
4404
+ acceptable by strtotime-command,
4405
+ ex.&nbsp;&quot;14 august 2006 16.00.00&quot;
4406
+ (notice <a class="ref" href="#date_restriction">date restriction</a>)</span>
4407
+ tz = timezone / offset
4408
+ (timezone will be used as tzidparam, if tzidparam not exists)
4409
+ offset = (+/-)HHmm[ss], local date + UTC offset =&gt; <a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME
4410
+ duration = array( int week/false
4411
+ [, int day/false
4412
+ , int hour
4413
+ , int min
4414
+ , int sec] )
4415
+ duration = array([ &quot;week&quot; =&gt; int week/false ,] /
4416
+ [ &quot;day&quot; =&gt; int day/false
4417
+ [, &quot;hour&quot; =&gt; int hour
4418
+ , &quot;min&quot; =&gt; int min
4419
+ , &quot;sec&quot; =&gt; int sec ]] );
4420
+ // <span class="ref">output format, only used keys</span>
4421
+ duration = array( &quot;sec&quot; =&gt; int sec );
4422
+ duration = string format duration like &quot;P15DT5H0M20S&quot;
4423
+ params<span class="ref">2</span> = ([tzidparam ( / datetimeparam / dateparam / periodparam )]
4424
+ *[, xparams ] )
4425
+ tzidparam = &quot;TZID&quot; =&gt; &lt;timezone identifier&gt;
4426
+ // <span class="ref">output as local DATE-TIME with timezone identifier</span>
4427
+ datetimeparam = &quot;VALUE&quot; =&gt; &quot;DATE-TIME&quot; // <span class="ref">default, output as DATE-TIME</span>
4428
+ dateparam = &quot;VALUE&quot; =&gt; &quot;DATE&quot; // <span class="ref">output as DATE</span>
4429
+ periodparam = &quot;VALUE&quot; =&gt; &quot;PERIOD&quot; // <span class="ref">output as PERIOD (datetime)</span>
4430
+ xparams = xparamkey =&gt; xparamvalue
4431
+ propOrderNo = int ordernumber, 1=1st, 2=2nd etc</p>
4432
+ <p class="label">Example</p>
4433
+ See rules in detail in RFC2445 - Internet Calendaring and Scheduling Core Object Specification (iCalendar) in <a href="http://www.kigkonsult.se/downloads/dl.php?f=rfc2445" title="RFC2445 in text format"><b>text</b></a>
4434
+ and <a href="http://www.kigkonsult.se/iCalcreator/iCalDictionary/index.html" title="RFC2445 in HTML format" target="_blank"><b>HTML</b></a> format.<br />
4435
+ <p class="example">// $rdate1 = array ( 2001, 1, 1, 1, 1, 1 );
4436
+ // alt.
4437
+ $rdate1 = array( &quot;year&quot; =&gt; 2001
4438
+ , &quot;month&quot; =&gt; 1
4439
+ , &quot;day&quot; =&gt; 1
4440
+ , &quot;hour&quot; =&gt; 1
4441
+ , &quot;min&quot; =&gt; 1
4442
+ , &quot;sec&quot; =&gt; 1
4443
+ , &quot;tz&quot; =&gt; &quot;GMT&quot; );
4444
+ $rdate2 = array( 2002, 2, 2, 2, 2, 2, &quot;GMT&quot; );
4445
+ $rdate3 = &quot;3 March 2003 03.03.03&quot;;
4446
+ $rdate4 = array( 2004, 4, 4, 4, 4, 4, &quot;GMT&quot; );
4447
+ $rdate5 = array( 2005, 10, 5, 5, 5, 5 );
4448
+ $rdate8 = array( &quot;year&quot; =&gt; 2007, &quot;month&quot; =&gt; 7, &quot;day&quot; =&gt; 7 );
4449
+ $rdur6 = array( &quot;week&quot; =&gt; 0
4450
+ , &quot;day&quot; =&gt; 0
4451
+ , &quot;hour&quot; =&gt; 5
4452
+ , &quot;min&quot; =&gt; 5
4453
+ , &quot;sec&quot; =&gt; 5 );
4454
+ $rdur7 = array( 0, 0, 6 );
4455
+ <span class="comment">// duration for 6 hours</span>
4456
+ $rdur8 = array( &quot;week&quot; =&gt; 8 );
4457
+ <span class="comment">// duration for 8 weeks</span>
4458
+
4459
+ $vevent = & $vcalendar->newComponent( 'vevent' );
4460
+ $vevent->setProperty( &quot;rdate&quot;, array( $rdate1 ));
4461
+ <span class="comment">// one recurrence date, date in 7-params format (DATE-TIME)</span>
4462
+
4463
+ $vevent->setProperty( &quot;rdate&quot;, array( $rdate1, $rdate2 ));
4464
+ <span class="comment">// two dates, date 7-params format (DATE-TIME)</span>
4465
+
4466
+ $vevent->setProperty( &quot;rdate&quot;, array( array( $rdate1, $rdate2 )
4467
+ , array( $rdate3, $rdate4 ))
4468
+ , array( 'VALUE' => 'PERIOD' ));
4469
+ <span class="comment">// Both fromdate and enddate must have 7 params (DATE-TIME) !!!</span>
4470
+
4471
+ $vevent->setProperty( &quot;rdate&quot;, array( array( $rdate2, $rdur6 ))
4472
+ , array( 'VALUE' => 'PERIOD' ));
4473
+ <span class="comment">// one duration (fromdate-duration)</span>
4474
+
4475
+ $vevent->setProperty( &quot;rdate&quot;, array( array( $rdate1, $date2 )
4476
+ , array( $rdate3, $rdur7 ))
4477
+ , array( 'VALUE' => 'PERIOD' ));
4478
+ <span class="comment">// period, pairs of fromdate+enddate and fromdate-duration</span>
4479
+
4480
+ $vevent->setProperty( &quot;rdate&quot;, array( $rdate5, $date8 ))
4481
+ , array( 'VALUE' => 'DATE' ));
4482
+ <span class="comment">// dates in DATE format</span>
4483
+ .. .</p>
4484
+ <br />
4485
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
4486
+
4487
+
4488
+ <a name="RECURRENCE-ID"></a><h3>3.2.30 RECURRENCE-ID</h3>
4489
+ This property is used in conjunction with the <a href="#UID">UID</a> and <a href="#SEQUENCE">SEQUENCE</a> property to identify a specific instance of a recurring <a href="#VEVENT">VEVENT</a>, <a href="#VTODO">VTODO</a> or <a href="#VJOURNAL">VJOURNAL</a> calendar component and is OPTIONAL and MAY NOT occur more than once.<br /><br />
4490
+ The property value is the effective value of the <a href="#DTSTART">DTSTART</a> property of the recurrence instance. The default value type is DATE-TIME, can be set to DATE (params <span class="ref">2</span>).
4491
+ <h5>Delete RECURRENCE-ID</h5>
4492
+ Remove RECURRENCE-ID from component.
4493
+ <p class="label">Format</p>
4494
+ <p class="format">deleteProperty( &quot;RECURRENCE-ID&quot; )</p>
4495
+ <p class="label">Example</p>
4496
+ <p class="example">$vevent->deleteProperty( &quot;RECURRENCE-ID&quot; );</p>
4497
+ <h5>Get RECURRENCE-ID</h5>
4498
+ Fetch property value.
4499
+ <p class="label">Format 1</p>
4500
+ <p class="format">getProperty( &quot;RECURRENCE-ID&quot; )</p>
4501
+ <p class="comment">output = recurrIdDate<span class="ref">1</span></p>
4502
+ <p class="label">Format 2</p>
4503
+ <p class="format">getProperty( &quot;RECURRENCE-ID&quot;, FALSE , TRUE )</p>
4504
+ <p class="comment">output = array( &quot;value&quot; =&gt; recurrIdDate<span class="ref">1</span>
4505
+ , &quot;params&quot; =&gt; params<span class="ref">2</span> )</p>
4506
+ <p class="label">Example</p>
4507
+ <p class="example">$recurrDate = $vtodo->getProperty( &quot;RECURRENCE-ID&quot; );</p>
4508
+ <h5>Set RECURRENCE-ID</h5>
4509
+ Insert property value. If DATE value type is expected, &quot;VALUE&quot; = &quot;DATE&quot; <b>must</b> be set (in params<span class="ref">2</span>) otherwise DATE-TIME (default) value type is set.
4510
+ <br />
4511
+ <br />
4512
+ If no timezone parameter (tz or tzidparam below) is set (then local time is assumed) and config <a href="#dTZID">TZID</a> is set, date-time values will be set WITH timezone from config.
4513
+ <p class="label">Format</p>
4514
+ <p class="format">setProperty( &quot;recurrence-id&quot;, recurrIdDate [, params ] )</p>
4515
+ <p class="comment">recurrIdDate<span class="ref">1</span> = array( &quot;year&quot; =&gt; int year
4516
+ , &quot;month&quot; =&gt; int month
4517
+ , &quot;day&quot; =&gt; int day
4518
+ [, &quot;hour&quot; =&gt; int hour
4519
+ , &quot;min&quot; =&gt; int min
4520
+ , &quot;sec&quot; =&gt; int sec
4521
+ [, &quot;tz&quot; =&gt; mixed tz ]] )
4522
+ recurrIdDate = int year
4523
+ , int month
4524
+ , int day
4525
+ [, int hour
4526
+ , int min
4527
+ , int sec
4528
+ [, mixed tz ]]
4529
+ recurrIdDate = array( int year
4530
+ , int month
4531
+ , int day
4532
+ [, int hour
4533
+ , int min
4534
+ , int sec
4535
+ [, mixed tz ]] )
4536
+ recurrIdDate = array( &quot;timestamp&quot; =&gt; int timestamp
4537
+ [, &quot;tz&quot; =&gt; mixed tz ] )
4538
+ recurrIdDate = string datestring // <span class="ref">string date,
4539
+ acceptable by strtotime-command,
4540
+ ex. &quot;14 august 2006 16.00.00&quot;
4541
+ (notice <a class="ref" href="#date_restriction">date restriction</a>)</span>
4542
+ tz = timezone / offset
4543
+ (timezone will be used as tzidparam, if tzidparam not exists)
4544
+ offset = (+/-)HHmm[ss], local date + UTC offset =&gt; <a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME
4545
+ params<span class="ref">2</span> = array([ datetimeparam/dateparam/tzidparam ]
4546
+ [, rangeparam ]
4547
+ [, xparam ] )
4548
+ datetimeparam = &quot;VALUE&quot; =&gt; &quot;DATE-TIME&quot; // <span class="ref">default, output as DATE-TIME</span>
4549
+ dateparam = &quot;VALUE&quot; =&gt; &quot;DATE&quot; // <span class="ref">output as DATE</span>
4550
+ tzidparam = &quot;TZID&quot; =&gt; &lt;timezone identifier&gt;
4551
+ // <span class="ref">output as local date-time with timezone identifier</span>
4552
+ rangeparam = &quot;RANGE&quot; =&gt; ( "THISANDPRIOR" / "THISANDFUTURE" )
4553
+ // <span class="ref">range parameter</span>
4554
+ xparam = *[ xparamkey =&gt; xparamvalue ]</p>
4555
+ <p class="label">Example</p>
4556
+ <p class="example">$vtodo->setProperty( &quot;recurrence-id&quot;, &quot;3 March 2003 03.03.03&quot; );
4557
+ <span class="comment">// 3 march 2003 03.03.03 local time</span></p>
4558
+ <br />
4559
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
4560
+
4561
+
4562
+ <a name="RELATED-TO"></a><h3>3.2.31 RELATED-TO</h3>
4563
+ The property is used to represent a relationship or reference between one calendar component and another and is OPTIONAL and MAY occur more than once in <a href="#VEVENT">VEVENT</a>, <a href="#VTODO">VTODO</a>, <a href="#VJOURNAL">VJOURNAL</a> components.<br /><br />
4564
+ The property value consists of the persistent, globally unique identifier of another calendar component. This value would be represented in a calendar component by the <a href="#UID">UID</a> property.<br /><br />
4565
+ The value type for RELATED-TO is TEXT.
4566
+ <h5>Delete RELATED-TO</h5>
4567
+ Remove RELATED-TO from component.
4568
+ <p class="label">Format</p>
4569
+ <p class="format">deleteProperty( &quot;RELATED-TO&quot; )</p>
4570
+ <p class="label">Example 1</p>
4571
+ <p class="example">$vtodo->deleteProperty( &quot;RELATED-TO&quot; );</p>
4572
+ <p class="label">Example 2</p>
4573
+ Delete RELATED-TO property no 2.
4574
+ <p class="example">$vjournal->deleteProperty( &quot;RELATED-TO&quot;, 2 );</p>
4575
+ <p class="label">Example 3</p>
4576
+ Deleting all RELATED-TO properties.
4577
+ <p class="example">while( $vjournal->deleteProperty( &quot;RELATED-TO&quot; ))
4578
+ continue;</p>
4579
+ <h5>Get RELATED-TO</h5>
4580
+ Fetch property value.
4581
+ <p class="label">Format 1</p>
4582
+ <p class="format">getProperty( &quot;RELATED-TO&quot; )</p>
4583
+ <p class="comment">output = relid<span class="ref">1</span></p>
4584
+ <p class="label">Format 2</p>
4585
+ <p class="format">getProperty( &quot;RELATED-TO&quot;, propOrderNo/FALSE , TRUE )</p>
4586
+ <p class="comment">output = array( &quot;value&quot; =&gt; relid<span class="ref">1</span>
4587
+ , &quot;params&quot; =&gt; params<span class="ref">2</span> )</p>
4588
+ <p class="label">Format 3</p>
4589
+ <p class="format">getProperty( &quot;RELATED-TO&quot;, propOrderNo )</p>
4590
+ <p class="comment">Get propOrderNo RELATED-TO</p>
4591
+ <p class="label">Example</p>
4592
+ <p class="example">$relatedId = $vtodo->getProperty( &quot;RELATED-TO&quot; );</p>
4593
+ <h5>Set RELATED-TO</h5>
4594
+ Insert property value.
4595
+ <p class="label">Format</p>
4596
+ <p class="format">setProperty( &quot;Related-To&quot;, relid [, params [, propOrderNo ]] )</p>
4597
+ <p class="comment">relid<span class="ref">1</span> = Value type TEXT.
4598
+ params<span class="ref">2</span> = array( [ reltype ] [, xparam] )
4599
+ reltype = &quot;RELTYPE&quot; =&gt; (&quot;PARENT&quot; (Default)
4600
+ / &quot;CHILD&quot;
4601
+ / &quot;SIBLING&quot;
4602
+ / iana-token
4603
+ / x-name)
4604
+ xparam = *[ xparamkey =&gt; xparamvalue ]
4605
+ propOrderNo = int ordernumber, 1=1st, 2=2nd etc</p>
4606
+ <p class="label">Example</p>
4607
+ <p class="example">$vtodo->setProperty( &quot;related-to&quot;, &quot;19960401-080045-4000F192713@host.com&quot;);</p>
4608
+ <br />
4609
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
4610
+
4611
+ <a name="REPEAT"></a><h3>3.2.32 REPEAT</h3>
4612
+ This property defines the number of time the <a href="#VALARM">ALARM</a> should be repeated, after the initial trigger.
4613
+ If the <a href="#VALARM">ALARM</a> triggers more than once, then this property MUST be specified along with the <a href="#DURATION">DURATION</a> property.
4614
+ <h5>Delete REPEAT</h5>
4615
+ Remove REPEAT from component.
4616
+ <p class="label">Format</p>
4617
+ <p class="format">deleteProperty( &quot;REPEAT&quot; )</p>
4618
+ <p class="label">Example</p>
4619
+ <p class="example">$valarm->deleteProperty( &quot;REPEAT&quot; );</p>
4620
+ <h5>Get REPEAT</h5>
4621
+ Fetch property value.
4622
+ <p class="label">Format 1</p>
4623
+ <p class="format">getProperty( &quot;REPEAT&quot; )</p>
4624
+ <p class="comment">output = repeatTimes<span class="ref">1</span></p>
4625
+ <p class="label">Format 2</p>
4626
+ <p class="format">getProperty( &quot;REPEAT&quot;, FALSE , TRUE )</p>
4627
+ <p class="comment">output = array( &quot;value&quot; =&gt; repeatTimes<span class="ref">1</span>
4628
+ , &quot;params&quot; =&gt; xparam<span class="ref">2</span> )</p>
4629
+ <p class="label">Example</p>
4630
+ <p class="example">$repeat = $vtodo->getProperty( &quot;REPEAT&quot; );</p>
4631
+ <h5>Set REPEAT</h5>
4632
+ Insert property value.
4633
+ <p class="label">Format</p>
4634
+ <p class="format">setProperty( &quot;repeat&quot;, repeatTimes [, xparam ] )</p>
4635
+ <p class="comment">repeatTimes<span class="ref">1</span> = Value type INTEGER
4636
+ xparam<span class="ref">2</span> = array( *[ xparamkey =&gt; xparamvalue ] )</p>
4637
+ <p class="label">Example</p>
4638
+ <p class="example">$valarm->setProperty( &quot;repeat&quot;, 2 );</p>
4639
+ <br />
4640
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
4641
+
4642
+
4643
+ <a name="REQUEST-STATUS"></a><h3>3.2.33 REQUEST-STATUS</h3>
4644
+ This property defines the status code returned for a scheduling request and is OPTIONAL and MAY occur more than once in <a href="#VEVENT">VEVENT</a>, <a href="#VTODO">VTODO</a>, <a href="#VJOURNAL">VJOURNAL</a> and <a href="#VFREEBUSY">VFREEBUSY</a> components.
4645
+ <h5>Delete REQUEST-STATUS</h5>
4646
+ Remove REQUEST-STATUS from component.
4647
+ <p class="label">Format</p>
4648
+ <p class="format">deleteProperty( &quot;REQUEST-STATUS&quot; )</p>
4649
+ <p class="label">Example 1</p>
4650
+ <p class="example">$vtodo->deleteProperty( &quot;REQUEST-STATUS&quot; );</p>
4651
+ <p class="label">Example 2</p>
4652
+ Delete REQUEST-STATUS property no 2.
4653
+ <p class="example">$vjournal->deleteProperty( &quot;REQUEST-STATUS&quot;, 2 );</p>
4654
+ <p class="label">Example 3</p>
4655
+ Deleting all REQUEST-STATUS properties.
4656
+ <p class="example">while( $vjournal->deleteProperty( &quot;REQUEST-STATUS&quot; ))
4657
+ continue;</p>
4658
+ <h5>Get REQUEST-STATUS</h5>
4659
+ Fetch property value.
4660
+ <p class="label">Format 1</p>
4661
+ <p class="format">getProperty( &quot;REQUEST-STATUS&quot; )</p>
4662
+ <p class="comment">output = array( &quot;statcode&quot; =&gt; statcode<span class="ref">1</span>
4663
+ , &quot;text&quot; =&gt; errtext<span class="ref">2</span>
4664
+ [ , &quot;extdata&quot; =&gt; extraData<span class="ref"> 3</span> ] )</p>
4665
+ <p class="label">Format 2</p>
4666
+ <p class="format">getProperty( &quot;REQUEST-STATUS&quot;, propOrderNo/FALSE, TRUE )</p>
4667
+ <p class="comment">output = array( &quot;value&quot; =&gt; array( &quot;statcode&quot; =&gt; statcode<span class="ref">1</span>
4668
+ , &quot;text&quot; =&gt; errtext<span class="ref">2</span>
4669
+ [ , &quot;extdata&quot; =&gt; extraData<span class="ref">3</span> ] )
4670
+ , &quot;params&quot; =&gt; params<span class="ref">4</span> )</p>
4671
+ <p class="label">Format 3</p>
4672
+ <p class="format">getProperty( &quot;REQUEST-STATUS&quot;, propOrderNo )</p>
4673
+ <p class="comment">Get propOrderNo REQUEST-STATUS</p>
4674
+ <p class="label">Example</p>
4675
+ <p class="example">$requestStatus = $vtodo->getProperty( &quot;REQUEST-STATUS&quot; );</p>
4676
+ <h5>Set REQUEST-STATUS</h5>
4677
+ Insert property value.
4678
+ <p class="label">Format</p>
4679
+ <p class="format">setProperty( &quot;Request-Status&quot;
4680
+ , statcode, errtext [,extraData/FALSE [,params [,propOrderNo]]])</p>
4681
+ <p class="comment">statcode<span class="ref">1</span> = Hierarchical, numeric return status code
4682
+ (1*DIGIT *(&quot;.&quot; 1*DIGIT))
4683
+ errtext<span class="ref">2</span> = Textual status description
4684
+ extraData<span class="ref">3</span> = Textual exception data.
4685
+ For example, the offending property name and value
4686
+ or complete property line.
4687
+ params<span class="ref">4</span> = array( [&quot;LANGUAGE&quot; =&gt; &quot;&lt;lang&gt;&quot;] [, xparam ] )
4688
+ xparam = *[ xparamkey =&gt; xparamvalue ]
4689
+ propOrderNo = int ordernumber, 1=1st, 2=2nd etc</p>
4690
+ <p class="label">Example</p>
4691
+ <p class="example">$vfreebusy->setProperty(&quot;request-status&quot;
4692
+ , 2.0
4693
+ , &quot;Invalid property value&quot;
4694
+ , &quot;DTSTART:96-Apr-31&quot;);</p>
4695
+ <br />
4696
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
4697
+
4698
+
4699
+ <a name="RESOURCES"></a><h3>3.2.34 RESOURCES</h3>
4700
+ This property defines the equipment or resources anticipated for an activity specified by a calendar entity and is OPTIONAL and MAY occur more than once in <a href="#VEVENT">VEVENT</a> and <a href="#VTODO">VTODO</a> components.<br /><br />
4701
+ The value type for RESOURCES is TEXT.
4702
+ <h5>Delete RESOURCES</h5>
4703
+ Remove RESOURCES from component.
4704
+ <p class="label">Format</p>
4705
+ <p class="format">deleteProperty( &quot;RESOURCES&quot; )</p>
4706
+ <p class="label">Example 1</p>
4707
+ <p class="example">$vevent->deleteProperty( &quot;RESOURCES&quot; );</p>
4708
+ <p class="label">Example 2</p>
4709
+ Delete RESOURCES property no 2.
4710
+ <p class="example">$vevent->deleteProperty( &quot;RESOURCES&quot;, 2 );</p>
4711
+ <p class="label">Example 3</p>
4712
+ Deleting all RESOURCES properties.
4713
+ <p class="example">while( $vevent->deleteProperty( &quot;RESOURCES&quot; ))
4714
+ continue;</p>
4715
+ <h5>Get RESOURCES</h5>
4716
+ Fetch property value.
4717
+ <p class="label">Format 1</p>
4718
+ <p class="format">getProperty( &quot;RESOURCES&quot; )</p>
4719
+ <p class="comment">output = resources<span class="ref">1</span></p>
4720
+ <p class="label">Format 2</p>
4721
+ <p class="format">getProperty( &quot;RESOURCES&quot;, propOrderNo/FALSE, TRUE )</p>
4722
+ <p class="comment">output = array( &quot;value&quot; =&gt; resources<span class="ref">1</span>
4723
+ , &quot;params&quot; =&gt; params<span class="ref">2</span> )</p>
4724
+ <p class="label">Format 3</p>
4725
+ <p class="format">getProperty( &quot;RESOURCES&quot;, propOrderNo )</p>
4726
+ <p class="comment">Get propOrderNo RESOURCES</p>
4727
+ <p class="label">Example</p>
4728
+ <p class="example">$resources = $vtodo->getProperty( &quot;RESOURCES&quot; );</p>
4729
+ <h5>Set RESOURCES</h5>
4730
+ Insert property value.
4731
+ <br />
4732
+ Parameters, if any, will be ordered as prescribed in rcf2445.
4733
+ <p class="label">Format</p>
4734
+ <p class="format">setProperty( &quot;resources&quot;, resources [, params [, propOrderNo ]] )</p>
4735
+ <p class="comment">resources<span class="ref">1</span> = string resource / array( *resource )
4736
+ resource = textual resources or subtypes of the calendar component,
4737
+ can be specified as a list of resources
4738
+ separated by the COMMA character.
4739
+ params<span class="ref">2</span> = array([ &quot;ALTREP&quot; =&gt; &quot;&lt;an alternate text representation, URI&gt;&quot;]
4740
+ [, &quot;LANGUAGE&quot; =&gt; &quot;&lt;lang&gt;&quot;]
4741
+ [, xparam] )
4742
+ xparam = *[ xparamkey =&gt; xparamvalue ]
4743
+ propOrderNo = int ordernumber, 1=1st, 2=2nd etc</p>
4744
+ <p class="label">Example</p>
4745
+ <p class="example">$vevent->setProperty( &quot;resources&quot;, &quot;COMPUTER PROJECTOR&quot; );</p>
4746
+ <br />
4747
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
4748
+
4749
+
4750
+ <a name="RRULE"></a><h3>3.2.35 RRULE</h3>
4751
+ This property defines a rule or repeating pattern for recurring <a href="#VEVENT">EVENTs</a>, <a href="#VTODO">TODOs</a>, <a href="#VTIMEZONE">STANDARD</a> or <a href="#VTIMEZONE">DAYLIGHT</a> definitions and is OPTIONAL and MAY occur more than once.
4752
+ <h5>Delete RRULE</h5>
4753
+ Remove RRULE from component.
4754
+ <p class="label">Format</p>
4755
+ <p class="format">deleteProperty( &quot;RRULE&quot; )</p>
4756
+ <p class="label">Example 1</p>
4757
+ <p class="example">$vevent->deleteProperty( &quot;RRULE&quot; );</p>
4758
+ <p class="label">Example 2</p>
4759
+ Delete RRULE property no 2.
4760
+ <p class="example">$vevent->deleteProperty( &quot;RRULE&quot;, 2 );</p>
4761
+ <p class="label">Example 3</p>
4762
+ Deleting all RRULE properties.
4763
+ <p class="example">while( $vevent->deleteProperty( &quot;RRULE&quot; ))
4764
+ continue;</p>
4765
+ <h5>Get RRULE</h5>
4766
+ Fetch property value.
4767
+ <p class="label">Format 1</p>
4768
+ <p class="format">getProperty( &quot;RRULE&quot; )</p>
4769
+ <p class="comment">output = recur<span class="ref">1</span></p>
4770
+ <p class="label">Format 2</p>
4771
+ <p class="format">getProperty( &quot;RRULE&quot;, propOrderNo/FALSE, TRUE )</p>
4772
+ <p class="comment">output = array( &quot;value&quot; =&gt; recur<span class="ref">1</span>
4773
+ , &quot;params&quot; =&gt; xparams<span class="ref">2</span> )</p>
4774
+ <p class="label">Format 3</p>
4775
+ <p class="format">getProperty( &quot;RRULE&quot;, propOrderNo )</p>
4776
+ <p class="comment">Get propOrderNo RRULE</p>
4777
+ <p class="label">Example</p>
4778
+ <p class="example">$rrules = $vtodo->getProperty( &quot;RRULE&quot; );</p>
4779
+ <h5>Set RRULE</h5>
4780
+ Insert property value.
4781
+ <br />
4782
+ Parameters will be ordered as prescribed in rcf2445.
4783
+ <p class="label">Format</p>
4784
+ <p class="format">setProperty( &quot;rrule&quot;, recur [, xparams [, propOrderNo ]] )</p>
4785
+ <p>
4786
+ For rules example see <a href="#EXRULE">Exrule</a> format and in detail in RFC2445 - Internet Calendaring and Scheduling Core Object Specification (iCalendar) in <a href="http://www.kigkonsult.se/downloads/dl.php?f=rfc2445" title="RFC2445 in text format"><b>text</b></a>
4787
+ and <a href="http://www.kigkonsult.se/iCalcreator/iCalDictionary/index.html" title="RFC2445 in HTML format" target="_blank"><b>HTML</b></a> format.
4788
+ </p>
4789
+ <p class="comment">recur<span class="ref">1</span> = see <a href="#EXRULE">Exrule</a>
4790
+ xparams<span class="ref">2</span> = array( *[ xparamkey =&gt; xparamvalue ] )
4791
+ propOrderNo = int ordernumber, 1=1st, 2=2nd etc</p>
4792
+ <br />
4793
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
4794
+
4795
+ <a name="SEQUENCE"></a><h3>3.2.36 SEQUENCE</h3>
4796
+ This property defines the revision sequence number of the calendar component within a sequence of revisions.
4797
+ The property is OPTIONAL and MUST NOT occur more than once in <a href="#VEVENT">VEVENT</a>,
4798
+ <a href="#VTODO">VTODO</a> and <a href="#VJOURNAL">VJOURNAL</a> components.
4799
+ <br />
4800
+ <p class="quotes">
4801
+ It is monotonically incremented by the <a href="#ORGANIZER">ORGANIZER's</a> CUA (Calendar User Agent)
4802
+ each time the <a href="#ORGANIZER">ORGANIZER</a> makes a significant revision to the calendar component.
4803
+ When the <a href="#ORGANIZER">ORGANIZER</a> makes changes to one of the following properties, the
4804
+ sequence number MUST be incremented: <a href="#DTSTART">DTSTART</a>, <a href="#DTEND">DTEND</a>, <a href="#DUE">DUE</a>, <a href="#RDATE">RDATE</a>, <a href="#RRULE">RRULE</a>,
4805
+ <a href="#EXDATE">EXDATE</a>, <a href="#EXRULE">EXRULE</a>, <a href="#STATUS">STATUS</a>. In addition, changes made by the <a href="#ORGANIZER">ORGANIZER</a> to other
4806
+ properties can also force the sequence number to be incremented. The <a href="#ORGANIZER">ORGANIZER</a>
4807
+ CUA MUST increment the sequence number when ever it makes changes to
4808
+ properties in the calendar component that the <a href="#ORGANIZER">ORGANIZER</a> deems will jeopardize
4809
+ the validity of the participation status of the <a href="#ATTENDEE">Attendees</a>. For example, changing
4810
+ the location of a meeting from one locale to another distant locale could effectively
4811
+ impact the participation status of the <a href="#ATTENDEE">Attendees</a>.
4812
+ </p>
4813
+ <h5>Delete SEQUENCE</h5>
4814
+ Remove SEQUENCE from component.
4815
+ <p class="label">Format</p>
4816
+ <p class="format">deleteProperty( &quot;SEQUENCE&quot; )</p>
4817
+ <p class="label">Example</p>
4818
+ <p class="example">$vtodo->deleteProperty( &quot;SEQUENCE&quot; );</p>
4819
+ <h5>Get SEQUENCE</h5>
4820
+ Fetch property value.
4821
+ <p class="label">Format 1</p>
4822
+ <p class="format">getProperty( &quot;SEQUENCE&quot; )</p>
4823
+ <p class="comment">output = sequence<span class="ref">1</span></p>
4824
+ <p class="label">Format 2</p>
4825
+ <p class="format">getProperty( &quot;SEQUENCE&quot;, FALSE , TRUE )</p>
4826
+ <p class="comment">output = array( &quot;value&quot; =&gt; sequence<span class="ref">1</span>
4827
+ , &quot;params&quot; =&gt; xparam<span class="ref">2</span> )</p>
4828
+ <p class="label">Example</p>
4829
+ <p class="example">$sequence = $vtodo->getProperty( &quot;SEQUENCE&quot; );</p>
4830
+ <h5>Set SEQUENCE</h5>
4831
+ Insert property value.
4832
+ <p class="label">Format</p>
4833
+ <p class="format">setProperty( &quot;sequence&quot; [, sequence [, xparam ]] )</p>
4834
+ <p class="comment">sequence<span class="ref">1</span> = Value type INTEGER
4835
+ xparam<span class="ref">2</span> = array( *[ xparamkey =&gt; xparamvalue ] )</p>
4836
+ <p class="label">Example 1</p>
4837
+ <p class="example">$vevent->setProperty( &quot;sequence&quot;, 2 );
4838
+ <span class="comment">// set sequence number to 2</span></p>
4839
+ <p class="label">Example 2</p>
4840
+ <p class="example">$vevent->setProperty( &quot;sequence&quot; );
4841
+ <span class="comment">// force sequence number to be set to 1
4842
+ // or, if sequence exists, incremented by 1</span></p>
4843
+ <br />
4844
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
4845
+
4846
+
4847
+ <a name="STATUS"></a><h3>3.2.37 STATUS</h3>
4848
+ This property defines the overall status or confirmation for the calendar component. The property is OPTIONAL and MUST NOT occur more than once in <a href="#VEVENT">VEVENT</a>, <a href="#VTODO">VTODO</a> and <a href="#VJOURNAL">VJOURNAL</a> components.
4849
+ <h5>Delete STATUS</h5>
4850
+ Remove STATUS from component.
4851
+ <p class="label">Format</p>
4852
+ <p class="format">deleteProperty( &quot;STATUS&quot; )</p>
4853
+ <p class="label">Example</p>
4854
+ <p class="example">$vtodo->deleteProperty( &quot;STATUS&quot; );</p>
4855
+ <h5>Get STATUS</h5>
4856
+ Fetch property value.
4857
+ <p class="label">Format 1</p>
4858
+ <p class="format">getProperty( &quot;STATUS&quot; )</p>
4859
+ <p class="comment">output = status<span class="ref">1</span></p>
4860
+ <p class="label">Format 2</p>
4861
+ <p class="format">getProperty( &quot;STATUS&quot;, FALSE , TRUE )</p>
4862
+ <p class="comment">output = array( &quot;value&quot; =&gt; status<span class="ref">1</span>
4863
+ , &quot;params&quot; =&gt; xparam<span class="ref">2</span> )</p>
4864
+ <p class="label">Example</p>
4865
+ <p class="example">$status = $vtodo->getProperty( &quot;STATUS&quot; );</p>
4866
+ <h5>Set STATUS</h5>
4867
+ Insert property value.
4868
+ <p class="label">Format</p>
4869
+ <p class="format">setProperty( &quot;status&quot;, status [, xparam ] )</p>
4870
+ <p class="comment"> // <span class="ref">Status values for a <a href="#vevent">VEVENT</a></span>
4871
+ status<span class="ref">1</span> = &quot;TENTATIVE&quot; // <span class="ref">Indicates event is tentative</span>
4872
+ / &quot;CONFIRMED&quot; // <span class="ref">Indicates event is definite</span>
4873
+ / &quot;CANCELLED&quot; // <span class="ref">Indicates event was cancelled</span>
4874
+ // <span class="ref">Status values for <a href="#VTODO">VTODO</a></span>
4875
+ status<span class="ref">1</span> = &quot;NEEDS-ACTION&quot; // <span class="ref">Indicates to-do needs action</span>
4876
+ / &quot;COMPLETED&quot; // <span class="ref">Indicates to-do completed</span>
4877
+ / &quot;IN-PROCESS&quot; // <span class="ref">Indicates to-do in process of</span>
4878
+ / &quot;CANCELLED&quot; // <span class="ref">Indicates to-do was cancelled</span>
4879
+ // <span class="ref">Status values for <a href="#VJOURNAL">VJOURNAL</a></span>
4880
+ status<span class="ref">1</span> = &quot;DRAFT&quot; // <span class="ref">Indicates journal is draft</span>
4881
+ / &quot;FINAL&quot; // <span class="ref">Indicates journal is final</span>
4882
+ / &quot;CANCELLED&quot; // <span class="ref">Indicates journal is removed</span>
4883
+ xparam<span class="ref">2</span> = array( *[ xparamkey =&gt; xparamvalue ] )</p>
4884
+ <p class="label">Example</p>
4885
+ <p class="example">$vevent->setProperty( &quot;Status&quot;, &quot;COMPLETED&quot; );</p>
4886
+ <br />
4887
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
4888
+
4889
+
4890
+ <a name="SUMMARY"></a><h3>3.2.38 SUMMARY</h3>
4891
+ This property defines a short (&quot;one line&quot;) summary or subject for the calendar component. (In &quot;rfc2445, Recommended Practices&quot;, up to 255 characters) (, analogous to a mail SUBJECT). The property is OPTIONAL and MUST NOT occur more than once in <a href="#VEVENT">VEVENT</a>, <a href="#VTODO">VTODO</a> and <a href="#VJOURNAL">VJOURNAL</a> components. The property is REQUIRED and MUST occur once in <a href="#VALARM">VALARM</a> (EMAIL) calendar component.<br /><br />
4892
+ The value type for SUMMARY is TEXT.
4893
+ <h5>Delete SUMMARY</h5>
4894
+ Remove SUMMARY from component.
4895
+ <p class="label">Format</p>
4896
+ <p class="format">deleteProperty( &quot;SUMMARY&quot; )</p>
4897
+ <p class="label">Example</p>
4898
+ <p class="example">$vevent->deleteProperty( &quot;SUMMARY&quot; );</p>
4899
+ <h5>Get SUMMARY</h5>
4900
+ Fetch property value.
4901
+ <p class="label">Format 1</p>
4902
+ <p class="format">getProperty( &quot;SUMMARY&quot; )</p>
4903
+ <p class="comment">output = summary<span class="ref">1</span></p>
4904
+ <p class="label">Format 2</p>
4905
+ <p class="format">getProperty( &quot;SUMMARY&quot;, FALSE , TRUE )</p>
4906
+ <p class="comment">output = array( &quot;value&quot; =&gt; summary<span class="ref">1</span>
4907
+ , &quot;params&quot; =&gt; params<span class="ref">2</span> )</p>
4908
+ <p class="label">Example</p>
4909
+ <p class="example">$summary = $vtodo->getProperty( &quot;SUMMARY&quot; );</p>
4910
+ <h5>Set SUMMARY</h5>
4911
+ Insert property value.
4912
+ <br />
4913
+ Parameters, if any, will be ordered as prescribed in rcf2445.
4914
+ <p class="label">Format</p>
4915
+ <p class="format">setProperty( &quot;summary&quot;, summary [, params ] )</p>
4916
+ <p CLASS="comment">summary<span class="ref">1</span> = Value type TEXT,
4917
+ a short, one line summary about the activity or journal entry.
4918
+ params<span class="ref">2</span> = array( [&quot;ALTREP&quot; =&gt; &quot;&lt;an alternate text representation, URI&gt;&quot;]
4919
+ [, &quot;LANGUAGE&quot; =&gt; &quot;&lt;lang&gt;&quot;]
4920
+ [, xparam ] )
4921
+ xparam = *[ xparamkey =&gt; xparamvalue ]</p>
4922
+ <p class="label">Example</p>
4923
+ <p class="example">$vevent->setProperty( &quot;summary&quot;, &quot;This is a summary&quot; );</p>
4924
+ <br />
4925
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
4926
+
4927
+
4928
+ <a name="TRANSP"></a><h3>3.2.39 TRANSP</h3>
4929
+ This property defines whether an <a href="#VEVENT">EVENT</a> is transparent or not to busy time searches and is OPTIONAL and MUST NOT occur more than once.
4930
+ <h5>Delete TRANSP</h5>
4931
+ Remove TRANSP from component.
4932
+ <p class="label">Format</p>
4933
+ <p class="format">deleteProperty( &quot;TRANSP&quot; )</p>
4934
+ <p class="label">Example</p>
4935
+ <p class="example">$vevent->deleteProperty( &quot;TRANSP&quot; );</p>
4936
+ <h5>Get TRANSP</h5>
4937
+ Fetch property value.
4938
+ <p class="label">Format 1</p>
4939
+ <p class="format">getProperty( &quot;TRANSP&quot; )</p>
4940
+ <p class="comment">output = transp<span class="ref">1</span></p>
4941
+ <p class="label">Format 2</p>
4942
+ <p class="format">getProperty( &quot;TRANSP&quot;, FALSE , TRUE )</p>
4943
+ <p class="comment">output = array( &quot;value&quot; =&gt; transp<span class="ref">1</span>
4944
+ , &quot;params&quot; =&gt; xparam<span class="ref">2</span> )</p>
4945
+ <p class="label">Example</p>
4946
+ <p class="example">$transp = $vtodo->getProperty( &quot;TRANSP&quot; );</p>
4947
+ <h5>Set TRANSP</h5>
4948
+ Insert property value.
4949
+ <p class="label">Format</p>
4950
+ <p class="format">setProperty( &quot;transp&quot;, transp [, xparam ] )</p>
4951
+ <p class="comment">transp<span class="ref">1</span> = &quot;OPAQUE&quot; / &quot;TRANSPARENT&quot;
4952
+ xparam<span class="ref">2</span> = array( *[ xparamkey =&gt; xparamvalue ] )</p>
4953
+ <p class="label">Example</p>
4954
+ <p class="example">$vevent->setProperty( &quot;transp&quot;, &quot;TRANSPARENT&quot; );</p>
4955
+ <br />
4956
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
4957
+
4958
+
4959
+ <a name="TRIGGER"></a><h3>3.2.40 TRIGGER</h3>
4960
+ This property specifies when an <a href="#VALARM">ALARM</a> will trigger and is REQUIRED and MUST NOT occur more than once.<br /><br />
4961
+ The default value type is DURATION. The value type can be set to a DATE-TIME value type, in which case the value MUST specify an <a href="#DATE_WITH_UTC_TIME">UTC</a> formatted DATE-TIME value.
4962
+ <h5>Delete TRIGGER</h5>
4963
+ Remove TRIGGER from component.
4964
+ <p class="label">Format</p>
4965
+ <p class="format">deleteProperty( &quot;TRIGGER&quot; )</p>
4966
+ <p class="label">Example</p>
4967
+ <p class="example">$valarm->deleteProperty( &quot;TRIGGER&quot; );</p>
4968
+ <h5>Get TRIGGER</h5>
4969
+ Fetch property value.
4970
+ <p class="label">Format 1</p>
4971
+ <p class="format">getProperty( &quot;TRIGGER&quot; )</p>
4972
+ <p class="comment">output = duration/date</p>
4973
+ <p class="label">Format 2</p>
4974
+ <p class="format">getProperty( &quot;TRIGGER&quot;, FALSE , TRUE )</p>
4975
+ <p class="comment">output = array( &quot;value&quot; =&gt; duration<span class="ref">1</span>/date<span class="ref">3</span> )
4976
+ , &quot;params&quot; =&gt; params<span class="ref">4</span> )
4977
+ <p class="label">Example</p>
4978
+ <p class="example">$trigger = $vtodo->getProperty( &quot;TRIGGER&quot; );</p>
4979
+ <h5>Set TRIGGER</h5>
4980
+ Insert property value.
4981
+ <p class="label">Format 1</p>
4982
+ <p class="format">setProperty( &quot;trigger&quot;, duration<span class="ref">1</span> [, params<span class="ref">4</span> ] )</p>
4983
+ <p class="label">Format 2</p>
4984
+ <p class="format">setProperty( &quot;trigger&quot;, duration<span class="ref">2</span> [, params<span class="ref">4</span> ] )</p>
4985
+ <p class="label">Format 3</p>
4986
+ <p class="format">setProperty( &quot;trigger&quot;, date<span class="ref">3</span> [, params<span class="ref">4</span> ] )</p>
4987
+ <p class="label">Format</p>
4988
+ <p class="format">setProperty( &quot;trigger&quot;, int year/FALSE
4989
+ , int month/FALSE
4990
+ , int day/FALSE
4991
+ [, int week/FALSE
4992
+ [, int hour/FALSE
4993
+ , int min/FALSE
4994
+ , int sec/FALSE
4995
+ [, bool relatedStart=TRUE
4996
+ [, bool before=TRUE
4997
+ [, array params<span class="ref">4</span> ]]]]] )</p>
4998
+ <p class="comment">duration<span class="ref">1</span> = array( &quot;week&quot; =&gt; int week
4999
+ , &quot;relatedStart&quot; =&gt; bool relstart
5000
+ , &quot;before&quot; =&gt; bool before )
5001
+ duration<span class="ref">1</span> = array( &quot;day&quot; =&gt; int day
5002
+ , &quot;hour&quot; =&gt; int hour
5003
+ , &quot;min&quot; =&gt; int min
5004
+ , &quot;sec&quot; =&gt; int sec
5005
+ , &quot;relatedStart&quot; =&gt; bool relstart
5006
+ , &quot;before&quot; =&gt; bool before )
5007
+ relatedStart = TRUE : related start (default),
5008
+ FALSE : related end
5009
+ before = TRUE : before relatedStart (default),
5010
+ FALSE : after relatedStart
5011
+ duration<span class="ref">2</span> = string dur-value = ([&quot;+&quot;]/&quot;-&quot;)&quot;P&quot;(dur-date/dur-time/dur-week)
5012
+ dur-date = dur-day [dur-time]
5013
+ dur-time = &quot;T&quot; (dur-hour / dur-minute / dur-second)
5014
+ dur-week = 1*DIGIT &quot;W&quot;
5015
+ dur-day = 1*DIGIT &quot;D&quot;
5016
+ dur-hour = 1*DIGIT &quot;H&quot; [dur-minute]
5017
+ dur-minute = 1*DIGIT &quot;M&quot; [dur-second]
5018
+ dur-second = 1*DIGIT &quot;S&quot;
5019
+ date<span class="ref">3</span> = array( &quot;year&quot; =&gt; int year // <span class="ref"><a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME</span>
5020
+ , &quot;month&quot; =&gt; int month
5021
+ , &quot;day&quot; =&gt; int day
5022
+ [, &quot;hour&quot; =&gt; int hour
5023
+ , &quot;min&quot; =&gt; int min
5024
+ , &quot;sec&quot; =&gt; int sec ])
5025
+ date<span class="ref">3</span> = array ( &quot;timestamp&quot; =&gt; int timestamp ) // <span class="ref"><a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME</span>
5026
+ date<span class="ref">3</span> = string datestring // <span class="ref">string date,
5027
+ acceptable by strtotime-command,
5028
+ ex.&nbsp;&quot;14 august 2006 16.00.00&quot;
5029
+ (notice <a class="ref" href="#date_restriction">date restriction</a>)</span>
5030
+ // <span class="ref"><a href="#DATE_WITH_UTC_TIME">UTC</a> DATE-TIME</span>
5031
+ params<span class="ref">4</span> = array( [[ reltype [, trigRelparam ]] / datetimeparam ]
5032
+ [, xparams ] )
5033
+ reltyp = &quot;RELATED&quot; =&gt; &quot;START&quot; (default) / &quot;END&quot;
5034
+ trigRelparam = &quot;VALUE&quot; =&gt; &quot;DURATION&quot;
5035
+ datetimeparam= &quot;VALUE&quot; =&gt; &quot;DATE-TIME&quot;
5036
+ xparam = *[ xparamkey =&gt; xparamvalue ]</p>
5037
+ <p class="label">Example 1</p>
5038
+ <p class="example">$valarm->setProperty( &quot;trigger&quot;
5039
+ , FALSE, FALSE, FALSE, FALSE, 1, 2, 3 );
5040
+ <span class="comment">// duration, 1 hour 2 min 3 sec, before start</span></p>
5041
+ <p class="label">Example 2</p>
5042
+ <p class="example">$valarm->setProperty( &quot;trigger&quot;
5043
+ , array (&quot;hour&quot;=&gt;1,&quot;min&quot;=&gt;2,&quot;sec&quot;=&gt;3 );
5044
+ <span class="comment">// duration, 1 hour 2 min 3 sec, before start</span></p>
5045
+ <p class="label">Example 3</p>
5046
+ <p class="example">$valarm->setProperty( &quot;trigger&quot;
5047
+ , &quot;PT1H2M3S&quot; );
5048
+ <span class="comment">// duration, 1 hour 2 min 3 sec, before start</span></p>
5049
+ <p class="label">Example 4</p>
5050
+ <p class="example">$valarm->setProperty( &quot;trigger&quot;
5051
+ , FALSE, FALSE, FALSE, 1
5052
+ , FALSE, FALSE, FALSE, FALSE, FALSE );
5053
+ <span class="comment">// duration, 1 week after end</span></p>
5054
+ <p class="label">Example 5</p>
5055
+ <p class="example">$valarm->setProperty( &quot;trigger&quot;
5056
+ , array ( &quot;week&quot; =&gt; 1
5057
+ , &quot;relatedStart&quot; =&gt; FALSE
5058
+ , &quot;before&quot; =&gt; FALSE ));
5059
+ <span class="comment">// duration, 1 week after end</span></p>
5060
+ <p class="label">Example 6</p>
5061
+ <p class="example">$valarm->setProperty( &quot;trigger&quot;
5062
+ , &quot;P1W&quot;
5063
+ , array( &quot;related&quot; =&gt; &quot;END&quot; ));
5064
+ <span class="comment">// duration, 1 week after end</span></p>
5065
+ <p class="label">Example 7</p>
5066
+ <p class="example">$valarm->setProperty( &quot;trigger&quot;
5067
+ , array( &quot;year&quot; =&gt; 2007
5068
+ , &quot;month&quot; =&gt; 6
5069
+ , &quot;day&quot; =&gt; 5,
5070
+ , &quot;hour&quot; =&gt; 2
5071
+ , &quot;min&quot; =&gt; 2
5072
+ , &quot;sec&quot; =&gt; 3 ));</p>
5073
+ <br />
5074
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
5075
+
5076
+
5077
+ <a name="TZID"></a><h3>3.2.41 TZID</h3>
5078
+ This property specifies the text value that uniquely identifies the <a href="#VTIMEZONE">VTIMEZONE</a> calendar component and is REQUIRED, but MUST NOT occur more than once. <br /><br />
5079
+ The value type for TZID is TEXT.
5080
+ <h5>Delete TZID</h5>
5081
+ Remove TZID from component.
5082
+ <p class="label">Format</p>
5083
+ <p class="format">deleteProperty( &quot;TZID&quot; )</p>
5084
+ <p class="label">Example</p>
5085
+ <p class="example">$vtimezone->deleteProperty( &quot;TZID&quot; );</p>
5086
+ <h5>Get TZID</h5>
5087
+ Fetch property value.
5088
+ <p class="label">Format 1</p>
5089
+ <p class="format">getProperty( &quot;TZID&quot; )</p>
5090
+ <p class="comment">output = tzid<span class="ref">1</span></p>
5091
+ <p class="label">Format 2</p>
5092
+ <p class="format">getProperty( &quot;TZID&quot;, FALSE , TRUE )</p>
5093
+ <p class="comment">output = array( &quot;value&quot; =&gt; tzid<span class="ref">1</span>
5094
+ , &quot;params&quot; =&gt; xparam<span class="ref">2</span> )</p>
5095
+ <p class="label">Example</p>
5096
+ <p class="example">$tzid = $vtimezone->getProperty( &quot;TZID&quot; );</p>
5097
+ <h5>Set TZID</h5>
5098
+ Insert property value.
5099
+ <p class="label">Format</p>
5100
+ <p class="format">setProperty( &quot;tzid&quot;, tzid [, xparam ] )</p>
5101
+ <p class="comment">tzid<span class="ref">1</span> = Value type TEXT
5102
+ xparam<span class="ref">2</span> = array( *[ xparamkey =&gt; xparamvalue ] )</p>
5103
+ <p class="label">Example</p>
5104
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot; );
5105
+ $vcalendar = new vcalendar( $config );
5106
+ $vtimezone = & $vcalendar->newComponent( 'vtimezone' );
5107
+ $vtimezone->setProperty( &quot;tzid&quot;, &quot;US-Eastern&quot; );
5108
+ .. .</p>
5109
+ <br />
5110
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
5111
+
5112
+
5113
+ <a name="TZNAME"></a><h3>3.2.42 TZNAME</h3>
5114
+ This property specifies the customary designation for a <a href="#VTIMEZONE">STANDARD</a> or <a href="#VTIMEZONE">DAYLIGHT</a> description and is OPTIONAL and MAY occur more than once.<br /><br />
5115
+ The value type for TZNAME is TEXT.
5116
+ <h5>Delete TZNAME</h5>
5117
+ Remove TZNAME from component.
5118
+ <p class="label">Format</p>
5119
+ <p class="format">deleteProperty( &quot;TZNAME&quot; )</p>
5120
+ <p class="label">Example 1</p>
5121
+ <p class="example">$vtimezonestd->deleteProperty( &quot;TZNAME&quot; );</p>
5122
+ <p class="label">Example 2</p>
5123
+ Delete TZNAME property no 2.
5124
+ <p class="example">$vtimezonestd->deleteProperty( &quot;TZNAME&quot;, 2 );</p>
5125
+ <p class="label">Example 3</p>
5126
+ Deleting all TZNAME properties.
5127
+ <p class="example">while( $vtimezonestd->deleteProperty( &quot;TZNAME&quot; ))
5128
+ continue;</p>
5129
+ <h5>Get TZNAME</h5>
5130
+ Fetch property value.
5131
+ <p class="label">Format 1</p>
5132
+ <p class="format">getProperty( &quot;TZNAME&quot; )</p>
5133
+ <p class="comment">output = tzname<span class="ref">1</span></p>
5134
+ <p class="label">Format 2</p>
5135
+ <p class="format">getProperty( &quot;TZNAME&quot;, propOrderNo/FALSE, TRUE )</p>
5136
+ <p class="comment">output = array( &quot;value&quot; =&gt; tzname<span class="ref">1</span>
5137
+ , &quot;params&quot; =&gt; params<span class="ref">2</span> )</p>
5138
+ <p class="label">Format 3</p>
5139
+ <p class="format">getProperty( &quot;TZNAME&quot;, propOrderNo )</p>
5140
+ <p class="comment">Get propOrderNo TZNAME</p>
5141
+ <p class="label">Example</p>
5142
+ <p class="example">$tzname = $timezonestandard->getProperty( &quot;TZNAME&quot; );</p>
5143
+ <h5>Set TZNAME</h5>
5144
+ Insert property value.
5145
+ <p class="label">Format</p>
5146
+ <p class="format">setProperty( &quot;tzname&quot;, tzname [, params [, propOrderNo ]] )</p>
5147
+ <p class="comment">tzname<span class="ref">1</span> = Value type TEXT
5148
+ params<span class="ref">2</span> = array( [ &quot;LANGUAGE&quot; =&gt; &quot;&lt;lang&gt;&quot; ] [, xparam ] )
5149
+ xparam = *[ xparamkey =&gt; xparamvalue ]
5150
+ propOrderNo = int ordernumber, 1=1st, 2=2nd etc</p>
5151
+ <p class="label">Example</p>
5152
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot; );
5153
+ $vcalendar = new vcalendar( $config );
5154
+ $vtimezone = & $vcalendar->newComponent( 'vtimezone' );
5155
+ $vtimezone->setProperty( &quot;Tzid&quot;, &quot;US-Eastern&quot; );
5156
+ $vtimezone->setProperty( &quot;Last-Modified&quot;, &quot;19870101&quot; );
5157
+ $standard = & $vtimezone->newComponent( &quot;standard&quot; );
5158
+ $standard->setProperty( &quot;tzname&quot;, &quot;EST&quot; );
5159
+ .. .</p>
5160
+ <br />
5161
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
5162
+
5163
+
5164
+ <a name="TZOFFSETFROM"></a><h3>3.2.43 TZOFFSETFROM</h3>
5165
+ This property specifies the offset which is in use prior to this <a href="#VTIMEZONE">TIMEZONE</a> observance.
5166
+ The property is REQUIRED, but MUST NOT occur more than once in <a href="#VTIMEZONE">STANDARD</a> and <a href="#VTIMEZONE">DAYLIGHT</a> components.
5167
+ <h5>Delete TZOFFSETFROM</h5>
5168
+ Remove TZOFFSETFROM from component.
5169
+ <p class="label">Format</p>
5170
+ <p class="format">deleteProperty( &quot;TZOFFSETFROM&quot; )</p>
5171
+ <p class="label">Example</p>
5172
+ <p class="example">$vtimezonestd->deleteProperty( &quot;TZOFFSETFROM&quot; );</p>
5173
+ <h5>Get TZOFFSETFROM</h5>
5174
+ Fetch property value.
5175
+ <p class="label">Format 1</p>
5176
+ <p class="format">getProperty( &quot;TZOFFSETFROM&quot; )</p>
5177
+ <p class="comment">output = tzoffsetfrom<span class="ref">1</span></p>
5178
+ <p class="label">Format 2</p>
5179
+ <p class="format">getProperty( &quot;TZOFFSETFROM&quot;, FALSE , TRUE )</p>
5180
+ <p class="comment">output = array( &quot;value&quot; =&gt; tzoffsetfrom<span class="ref">1</span>
5181
+ , &quot;params&quot; =&gt; xparam<span class="ref">2</span> )</p>
5182
+ <p class="label">Example</p>
5183
+ <p class="example">$tzoffsetfrom = $timezonestandard->getProperty( &quot;TZOFFSETFROM&quot; );</p>
5184
+ <h5>Set TZOFFSETFROM</h5>
5185
+ Insert property value.
5186
+ <p class="label">Format</p>
5187
+ <p class="format">setProperty( &quot;tzoffsetfrom&quot;, tzoffsetfrom [, xparam ] )</p>
5188
+ <p class="comment">tzoffsetfrom<span class="ref">1</span> = (+/-)HHmm[ss], UTC offset
5189
+ xparam<span class="ref">2</span> = array( *[ xparamkey =&gt; xparamvalue ] )</p>
5190
+ <p class="label">Example</p>
5191
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot; );
5192
+ $vcalendar = new vcalendar( $config );
5193
+ $vtimezone = & $vcalendar->newComponent( 'vtimezone' );
5194
+ $vtimezone->setProperty( &quot;Tzid&quot;, &quot;US-Eastern&quot; );
5195
+ $vtimezone->setProperty( &quot;Last-Modified&quot;, &quot;19870101&quot; );
5196
+ $standard = & $vtimezone->newComponent( &quot;standard&quot; );
5197
+ $standard->setProperty( &quot;tzname&quot;, &quot;EST&quot; );
5198
+ $standard->setProperty( &quot;tzoffsetfrom&quot;, &quot;-0500&quot; );
5199
+ .. .</p>
5200
+ <br />
5201
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
5202
+
5203
+
5204
+ <a name="TZOFFSETTO"></a><h3>3.2.44 TZOFFSETTO</h3>
5205
+ This property specifies the offset which is in use in this <a href="#VTIMEZONE">TIMEZONE</a> observance.
5206
+ The property is REQUIRED, but MUST NOT occur more than once in <a href="#VTIMEZONE">STANDARD</a> and <a href="#VTIMEZONE">DAYLIGHT</a> components.
5207
+ <h5>Delete TZOFFSETTO</h5>
5208
+ Remove TZOFFSETTO from component.
5209
+ <p class="label">Format</p>
5210
+ <p class="format">deleteProperty( &quot;TZOFFSETTO&quot; )</p>
5211
+ <p class="label">Example</p>
5212
+ <p class="example">$daylight->deleteProperty( &quot;TZOFFSETTO&quot; );</p>
5213
+ <h5>Get TZOFFSETTO</h5>
5214
+ Fetch property value.
5215
+ <p class="label">Format 1</p>
5216
+ <p class="format">getProperty( &quot;TZOFFSETTO&quot; )</p>
5217
+ <p class="comment">output = tzoffsetto<span class="ref">1</span></p>
5218
+ <p class="label">Format 2</p>
5219
+ <p class="format">getProperty( &quot;TZOFFSETTO&quot;, FALSE , TRUE )</p>
5220
+ <p class="comment">output = array( &quot;value&quot; =&gt; tzoffsetto<span class="ref">1</span>
5221
+ , &quot;params&quot; =&gt; xparam<span class="ref">2</span> )</p>
5222
+ <p class="label">Example</p>
5223
+ <p class="example">$tzoffsetto = $timezonestandard->getProperty( &quot;TZOFFSETTO&quot; );</p>
5224
+ <h5>Set TZOFFSETTO</h5>
5225
+ Insert property value.
5226
+ <p class="label">Format</p>
5227
+ <p class="format">setproperty( &quot;tzoffsetto&quot;, tzoffsetto [, xparam ] )</p>
5228
+ <p class="comment">tzoffsetto<span class="ref">1</span> = (+/-)HHmm[ss], UTC offset
5229
+ xparam<span class="ref">2</span> = array( *[ xparamkey =&gt; xparamvalue ] )</p>
5230
+ <p class="label">Example</p>
5231
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot; );
5232
+ $vcalendar = new vcalendar( $config );
5233
+ $vtimezone = & $vcalendar->newComponent( 'vtimezone' );
5234
+ $vtimezone->setProperty( &quot;Tzid&quot;, &quot;US-Eastern&quot; );
5235
+ $vtimezone->setProperty( &quot;Last-Modified&quot;, &quot;19870101&quot; );
5236
+ $standard = & $vtimezone->newComponent( &quot;standard&quot; );
5237
+ .. .
5238
+ $daylight = & $vtimezone->newComponent( &quot;daylight&quot; );
5239
+ $daylight->setProperty( &quot;tzoffsetto&quot;, &quot;1345&quot; );
5240
+ .. .</p>
5241
+ <br />
5242
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
5243
+
5244
+
5245
+ <a name="TZURL"></a><h3>3.2.45 TZURL</h3>
5246
+ The TZURL provides a means for a <a href="#VTIMEZONE">VTIMEZONE</a> component to point to
5247
+ a network location that can be used to retrieve an up-to-date version of itself. The property
5248
+ is OPTIONAL and MUST NOT occur more than once.
5249
+ <h5>Delete TZURL</h5>
5250
+ Remove TZURL from component.
5251
+ <p class="label">Format</p>
5252
+ <p class="format">deleteProperty( &quot;TZURL&quot; )</p>
5253
+ <p class="label">Example</p>
5254
+ <p class="example">$vtimezone->deleteProperty( &quot;TZURL&quot; );</p>
5255
+ <h5>Get TZURL</h5>
5256
+ Fetch property value.
5257
+ <p class="label">Format 1</p>
5258
+ <p class="format">getProperty( &quot;TZURL&quot; )</p>
5259
+ <p class="comment">output = tzurl<span class="ref">1</span></p>
5260
+ <p class="label">Format 2</p>
5261
+ <p class="format">getProperty( &quot;TZURL&quot;, FALSE , TRUE )</p>
5262
+ <p class="comment">output = array( &quot;value&quot; =&gt; tzurl<span class="ref">1</span>
5263
+ , &quot;params&quot; =&gt; xparam<span class="ref">2</span> )</p>
5264
+ <p class="label">Example</p>
5265
+ <p class="example">$tzurl = $timezonestandard->getProperty( &quot;TZURL&quot; );</p>
5266
+ <h5>Set TZURL</h5>
5267
+ Insert property value.
5268
+ <p class="label">Format</p>
5269
+ <p class="format">setProperty( &quot;tzurl&quot;, tzurl [, xparam ] )</p>
5270
+ <p class="comment">tzurl<span class="ref">1</span> = Value type URI
5271
+ xparam<span class="ref">2</span> = array( *[ xparamkey =&gt; xparamvalue ] )</p>
5272
+ <p class="label">Example</p>
5273
+ <p class="example">$tz = &quot;http://zones.stds_r_us.net/tz/US-Eastern&quot; );
5274
+ $config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot; );
5275
+ $vcalendar = new vcalendar( $config );
5276
+ $vtimezone = & $vcalendar->newComponent( 'vtimezone' );
5277
+ $vtimezone->setProperty( &quot;Tzid&quot;, &quot;US-Eastern&quot; );
5278
+ $vtimezone->setProperty( &quot;Last-Modified&quot;, &quot;19870101T000000&quot; );
5279
+ $vtimezone->setProperty( &quot;tzurl&quot;, $tz );
5280
+ .. .
5281
+ .. .</p>
5282
+ <br />
5283
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
5284
+
5285
+
5286
+ <a name="UID"></a><h3>3.2.46 UID</h3>
5287
+ The persistent, globally <b>U</b>nique <b>ID</b>entifier for the calendar component.
5288
+ The property is OPTIONAL and MUST NOT occur more than once in <a href="#VEVENT">VEVENT</a>, <a href="#VTODO">VTODO</a>, <a href="#VJOURNAL">VJOURNAL</a> and <a href="#VFREEBUSY">VFREEBUSY</a> components.<br />
5289
+ However, UID is <b>AUTOMATICALLY</b> generated in iCalcreator and configuration <a href="#Unique_id">unique_id</a>, is used when auto-creating component UID.
5290
+ <br />
5291
+ <br />
5292
+ UID generated format :
5293
+ <p class="format">date(&quot;Ymd\THisT&quot;).&quot;-&quot;.[microSec][random].&quot;@&quot;.<a href="#Unique_id">unique_id</a>
5294
+ </p>
5295
+ microSec = microseconds, 4 pos<br />
5296
+ random = 6 characters aA-zZ, 0-9
5297
+ <p class="label">Example</p>
5298
+ <p class="example">&quot;20070803T194810CEST-0123U3PXiX@domain.com&quot;</p>
5299
+ UID may be required when importing iCal files into some calendaring software (MS etc.),
5300
+ as well as (calendar) <a href="#X-PROPERTY">x-properties</a> "X-WR-CALNAME", "X-WR-CALDESC" and "X-WR-TIMEZONE",
5301
+ <a href="#METHOD">METHOD</a> property (value PUBLISH etc.) and (also auto created) <a href="#DTSTAMP">DTSTAMP</a> property.
5302
+ <br /><br />
5303
+ The value type for UID is TEXT.
5304
+ <h5>Delete UID</h5>
5305
+ If UID is remove from a component, UID will automatically be recreated when calendar output functions like <a href="#createCalendar">createCalendar</a>, <a href="#returnCalendar">returnCalendar</a> or <a href="#saveCalendar">saveCalendar</a> is executed.
5306
+ <p class="label">Format</p>
5307
+ <p class="format">deleteProperty( &quot;UID&quot; )</p>
5308
+ <p class="label">Example</p>
5309
+ <p class="example">$vevent->deleteProperty( &quot;UID&quot; );</p>
5310
+ <h5>Get UID</h5>
5311
+ Fetch property value.
5312
+ <p class="label">Format 1</p>
5313
+ <p class="format">getProperty( &quot;UID&quot; )</p>
5314
+ <p class="comment">output = uid<span class="ref">1</span></p>
5315
+ <p class="label">Format 2</p>
5316
+ <p class="format">getProperty( &quot;UID&quot;, FALSE , TRUE )</p>
5317
+ <p class="comment">output = array( &quot;value&quot; =&gt; uid<span class="ref">1</span>
5318
+ , &quot;params&quot; =&gt; xparam<span class="ref">2</span> )</p>
5319
+ <p class="label">Example</p>
5320
+ <p class="example">$uid = $vevent->getProperty( &quot;UID&quot; );</p>
5321
+ <h5>Set UID</h5>
5322
+ Insert property value, overrides any previously set or auto-created UID.<br />
5323
+ Do <b>NOT</b> use an integer UID or only a component name in UID (ex. &quot;vevent&quot;), this may cause malfunction in <a href="#setComponent">setComponent</a> with index or UID argument.
5324
+ <p class="label">Format</p>
5325
+ <p class="format">setProperty( &quot;uid&quot;, uid [, xparam ] )</p>
5326
+ <p class="comment">uid<span class="ref">1</span> = Value type TEXT
5327
+ xparam<span class="ref">2</span> = array( *[ xparamkey =&gt; xparamvalue ] )</p>
5328
+ <p class="label">Example</p>
5329
+ <p class="example">$vevent->setProperty(&quot;uid&quot;,&quot;20070803T194810CEST-0123U3PXiX@domain.com&quot;);</p>
5330
+ <br />
5331
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
5332
+
5333
+
5334
+ <a name="URL"></a><h3>3.2.47 URL</h3>
5335
+ This property defines a Uniform Resource Locator (URL) associated with the iCalendar object.
5336
+ The property is OPTIONAL and MUST NOT occur more than once in <a href="#VEVENT">VEVENT</a>, <a href="#VTODO">VTODO</a>, <a href="#VJOURNAL">VJOURNAL</a> and <a href="#VFREEBUSY">VFREEBUSY</a> components.
5337
+ <h5>Delete URL</h5>
5338
+ Remove URL from component.
5339
+ <p class="label">Format</p>
5340
+ <p class="format">deleteProperty( &quot;URL&quot; )</p>
5341
+ <p class="label">Example</p>
5342
+ <p class="example">$vevent->deleteProperty( &quot;URL&quot; );</p>
5343
+ <h5>Get URL</h5>
5344
+ Fetch property value.
5345
+ <p class="label">Format 1</p>
5346
+ <p class="format">getProperty( &quot;URL&quot; )</p>
5347
+ <p class="comment">output = url<span class="ref">1</span></p>
5348
+ <p class="label">Format 2</p>
5349
+ <p class="format">getProperty( &quot;URL&quot;, FALSE , TRUE )</p>
5350
+ <p class="comment">output = array &quot;value&quot; =&gt; url<span class="ref">1</span>
5351
+ , &quot;params&quot; =&gt; xparam<span class="ref">2</span> )</p>
5352
+ <p class="label">Example</p>
5353
+ <p class="example">$url = $vevent->getProperty( &quot;URL&quot; );</p>
5354
+ <h5>Set URL</h5>
5355
+ Insert property value.<br/>
5356
+ <p class="label">Format</p>
5357
+ <p class="format">setProperty( &quot;url&quot;, url [, xparam ] )</p>
5358
+ <p class="comment">url<span class="ref">1</span> = Value type URI
5359
+ xparam<span class="ref">2</span> = array( *[ xparamkey =&gt; xparamvalue ] (</p>
5360
+ <p class="label">Example</p>
5361
+ <p class="example">$vtodo->setProperty( &quot;url&quot;, &quot;http://www.icaldomain.net&quot; );</p>
5362
+ <br />
5363
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
5364
+
5365
+
5366
+ <a name="X-PROPERTY_PROP"></a><h3>3.2.48 X-PROPERTY</h3>
5367
+ A calendar, non-standard property with a TEXT value and a name with an &quot;X-&quot; prefix. In a calendar,
5368
+ an x-prop, with an unique name, can occur only once but the number of x-props are unlimited.
5369
+ <br />
5370
+ <h5>Delete X-PROPERTY</h5>
5371
+ Remove X-PROPERTY from component.
5372
+ <p class="label">Format</p>
5373
+ <p class="format">deleteProperty( &quot;&lt;X-PROPERTY&gt;&quot; )</p>
5374
+ <p class="label">Example 1</p>
5375
+ <p class="example">$vevent->deleteProperty( &quot;&lt;X-PROPERTY&gt;&quot; );</p>
5376
+ <p class="label">Example 2</p>
5377
+ Deleting all x-properties.
5378
+ <p class="example">while( $vevent->deleteProperty())
5379
+ continue;</p>
5380
+ <h5>Get X-property</h5>
5381
+ Fetch property value.
5382
+ <p class="label">Format 1</p>
5383
+ <p class="format">getProperty( &quot;&lt;X-PROPERTY&gt;&quot; )</p>
5384
+ <p class="comment">output = array( propertyName<span class="ref">1</span>
5385
+ , propertyData<span class="ref">2</span> )</p>
5386
+ <p class="label">Format 2</p>
5387
+ <p class="format">getProperty()</p>
5388
+ <p class="comment">output = array( propertyName<span class="ref">1</span>
5389
+ , propertyData<span class="ref">2</span> )</p>
5390
+ <p class="label">Format 3</p>
5391
+ <p class="format">getProperty( FALSE, propOrderNo/FALSE, TRUE )</p>
5392
+ <p class="comment">output = array( propertyName<span class="ref">1</span>
5393
+ , array ( &quot;value&quot; =&gt; propertyData<span class="ref">2</span> )
5394
+ , &quot;params&quot; =&gt; params<span class="ref">&nbsp;3</span>))</p>
5395
+ <p class="label">Format 4</p>
5396
+ <p class="format">getProperty( FALSE, propOrderNo )</p>
5397
+ <p class="comment">Get propOrderNo X-property</p>
5398
+
5399
+ <p class="label">Example 1</p>
5400
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;,
5401
+ &quot;filename&quot;, &quot;file.ics&quot; ); );
5402
+ $vcalendar = new vcalendar( $config );
5403
+ $vcalendar->parse();
5404
+ if( FALSE !== ( $d = $vcalendar->getProperty( 'X-WR-TIMEZONE' )))
5405
+ echo $d[1];
5406
+ .. .</p>
5407
+ <p class="comment"> // $xprop = array( propertyName<span class="ref">1</span>, propertyData<span class="ref">2</span> )</p>
5408
+
5409
+ <p class="label">Example 2</p>
5410
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;,
5411
+ &quot;filename&quot;, &quot;file.ics&quot; ); );
5412
+ $vcalendar = new vcalendar( $config );
5413
+ $vcalendar->parse();
5414
+ while( $xprop = $vcalendar->getProperty( )) {
5415
+ .. .</p>
5416
+ <p class="comment"> // $xprop = array( propertyName<span class="ref">1</span>, propertyData<span class="ref">2</span> )</p>
5417
+
5418
+ <p class="label">Example 3</p>
5419
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;,
5420
+ &quot;filename&quot;, &quot;file.ics&quot; ); );
5421
+ $vcalendar = new vcalendar( $config );
5422
+ $vcalendar->parse();
5423
+ while( $xprop = $vcalendar->getProperty( &quot;X-ABC-MMSUBJ&quot; )) {
5424
+ .. .</p>
5425
+ <p class="comment"> // $xprop = array( &quot;X-ABC-MMSUBJ&quot;, propertyData<span class="ref">2</span> )</p>
5426
+ <p class="label">Example 4</p>
5427
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;,
5428
+ &quot;filename&quot;, &quot;file.ics&quot; ); );
5429
+ $vcalendar = new vcalendar( $config );
5430
+ $vcalendar->parse();
5431
+ while( $xprop = $vcalendar->getProperty( FALSE, FALSE, TRUE )) {
5432
+ .. .</p>
5433
+ <p class="comment"> // $xprop = array( propertyName<span class="ref">1</span>
5434
+ // , array( &quot;value&quot; =&gt; propertyData<span class="ref">2</span> )
5435
+ // , &quot;params&quot; =&gt; params<span class="ref">&nbsp;3</span> )</p>
5436
+ <h5>Set X-property</h5>
5437
+ Insert property name and value. If an x-prop with the same name already exists, it will be replaced.
5438
+ <p class="label">Format</p>
5439
+ <p class="format">setProperty( propertyName, propertyData [, params ] )</p>
5440
+ <p class="comment">propertyName<span class="ref">1</span> = Any property name with a &quot;X-&quot; prefix
5441
+ propertyData<span class="ref">2</span> = Value type TEXT
5442
+ params<span class="ref">3</span> = array( [&quot;LANGUAGE&quot; =&gt; &quot;&lt;lang&gt;&quot;] [, xparam] )
5443
+ xparam = *[ xparamkey =&gt; xparamvalue ]</p>
5444
+ propOrderNo = int ordernumber, 1=1st, 2=2nd etc</p>
5445
+ <p class="label">Example</p>
5446
+ <p class="example">$component->setProperty(&quot;X-ABC-MMSUBJ&quot;,&quot;http://load.noise.org/mysubj.wav&quot;);</p>
5447
+ <br />
5448
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_object_property_function_list">[up]</a>
5449
+
5450
+
5451
+
5452
+ <a NAME="Calendar_component_configuration_functions"></a><h2>3.3 Calendar Component configuration functions</h2>
5453
+
5454
+ <a name="Language_PROP"></a><h3>3.3.1 Language</h3>
5455
+ Language for specific calendar component as defined in [RFC 1766].<br />
5456
+ Language set at component level can be overridden by specific component property parameter.<br />
5457
+ A successful &quot;setConfig&quot; returns TRUE.
5458
+ <h5>Get language</h5>
5459
+ Language for calendar (only if language is set at component level).
5460
+ <p class="label">Format</p>
5461
+ <p class="format">getConfig( &quot;language&quot; )</p>
5462
+ <p class="label">Example</p>
5463
+ <p class="example">$lang = $vevent->getConfig( &quot;language&quot; );</p>
5464
+ <h5>Set LANGUAGE</h5>
5465
+ <p class="label">Format</p>
5466
+ <p class="format">setConfig( &quot;language&quot;, string &lt;lang&gt; )</p>
5467
+ <p class="label">Example</p>
5468
+ <p class="example">$vevent->setConfig( &quot;language&quot;, &quot;en&quot; );</p>
5469
+ <br />
5470
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_configuration_functions">[up]</a>
5471
+
5472
+ <a name="Calendar_component_object_misc_functions"></a><h2>3.4 Calendar component object misc. functions</h2>
5473
+ Calendar component subcomponent functions
5474
+
5475
+ <a name="deleteComponent_PROP"></a><h4>3.4.1 deleteComponent</h4>
5476
+ Remove subcomponent from component.
5477
+ <p class="label">Format</p>
5478
+ <p class="format">deleteComponent( int orderNumber )</p>
5479
+ <p class="comment">Remove component with order number (1st=1, 2nd=2.. .).</p>
5480
+ <p class="format">deleteComponent( string componentType [, int componentSuborderNumber])</p>
5481
+ <p class="comment">Remove component with component type (ex. &quot;vevent&quot;)
5482
+ and order 1 alt. suborder number.</p>
5483
+ <p class="format">deleteComponent( string <a href="#UID">UID</a> )</p>
5484
+ <p class="comment">Remove component with <a href="#UID">UID</a>.
5485
+ N.B <a href="#UID">UID</a> is NOT set for <a href="#VALARM">ALARM</a> / <a href="#VTIMEZONE">timezone</a> components.</p>
5486
+ <p class="label">Example 1</p>
5487
+ Delete first subcomponent.
5488
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;,
5489
+ &quot;filename&quot;, &quot;file.ics&quot; ); );
5490
+ $vcalendar = new vcalendar( $config );
5491
+ $vcalendar->parse();
5492
+ $comp1 = $vcalendar->getComponent();
5493
+ $comp1->deleteComponent( 1 );
5494
+ .. .</p>
5495
+ <p class="label">Example 2</p>
5496
+ Delete all subcomponents.
5497
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;,
5498
+ &quot;filename&quot;, &quot;file.ics&quot; ); );
5499
+ $vcalendar = new vcalendar( $config );
5500
+ $vcalendar->parse();
5501
+ $comp1 = $vcalendar->getComponent();
5502
+ while( $comp1->deleteComponent( 'valarm' )
5503
+ continue;
5504
+ .. .</p>
5505
+ <br />
5506
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_configuration_functions">[up]</a>
5507
+
5508
+ <a name="getComponent_PROP"></a><h4>3.4.2 getComponent</h4>
5509
+ Get subComponent from component.
5510
+ <p class="label">Format 1</p>
5511
+ <p class="format">getComponent()</p>
5512
+ <p class="comment">Get next component until end-of-components.</p>
5513
+ <p class="label">Format 2</p>
5514
+ <p class="format">getComponent( int orderNumber )</p>
5515
+ <p class="comment">Get component with order number (1st=1, 2nd=2.. .).</p>
5516
+ <p class="label">Format 3</p>
5517
+ <p class="format">getComponent( string componentType [, int componentSuborderNumber])</p>
5518
+ <p class="comment">Get (next) component with component type (until end-of-components)
5519
+ alt. component with component type and suborder number (1st=1, 2nd=2..).</p>
5520
+ <p class="label">Format 4</p>
5521
+ <p class="format">getComponent( string <a href="#UID">UID</a> )</p>
5522
+ <p class="comment">Get component with <a href="#UID">UID</a>.
5523
+ N.B <a href="#UID">UID</a> is NOT set for <a href="#VALARM">ALARM</a> / <a href="#VTIMEZONE">timezone</a> components.</p>
5524
+ <p class="label">Example</p>
5525
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot;,
5526
+ &quot;filename&quot;, &quot;file.ics&quot; ); );
5527
+ $vcalendar = new vcalendar( $config );
5528
+ $vcalendar->parse();
5529
+ $comp1 = $vcalendar->getComponent());
5530
+ while( $subComp = $comp1->getComponent()) {
5531
+ .. .</p>
5532
+ <br />
5533
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_configuration_functions">[up]</a>
5534
+
5535
+ <a name="newComponent"></a><h4>3.4.3 newComponent</h4>
5536
+ Create subcomponent (<a href="#VALARM">ALARN</a> / <a href="#VTIMEZONE">VTIMEZONE STANDARD</a> / <a href="#VTIMEZONE">VTIMEZONE DAYLIGHT</a>)
5537
+ using a component factory-method, returning a reference to the new component.
5538
+ <p class="label">Format</p>
5539
+ <p class="format">newComponent( string componentType )</p>
5540
+ <p class="label">Example 1</p>
5541
+ <p class="example">$config = array( 'unique_id' => 'domain.org' );
5542
+ $vcalendar = new vcalendar( $config );
5543
+ ...
5544
+ $vevent = & $vcalendar->newComponent( 'vevent' );
5545
+ $vevent->setProperty( &quot;dtstart&quot; // <span class="ref">add some <a href="#VEVENT">EVENT</a> properties</span>
5546
+ , 2006, 12, 24, 19, 30, 00 );
5547
+ $vevent->setProperty(.. .
5548
+ ...
5549
+ $valarm = & $vevent->newComponent( 'valarm' );
5550
+ $valarm->setProperty( &quot;trigger&quot;, .. .
5551
+ ...
5552
+ </p>
5553
+ <p class="label">Example 2</p>
5554
+ <p class="example">$config = array( 'unique_id' => 'domain.org' );
5555
+ $vcalendar = new vcalendar( $config );
5556
+ ...
5557
+ $vtimezone = & $vcalendar->newComponent( 'vtimezone' );
5558
+ $vtimezone->setProperty(.. .
5559
+ ...
5560
+ $standard = & $vtimezone->newComponent( 'standard' );
5561
+ $standard->setProperty(.. .
5562
+ ...
5563
+ $daylight = & $vtimezone->newComponent( 'daylight' );
5564
+ $daylight->setProperty(.. .
5565
+ ...
5566
+ </p>
5567
+
5568
+ <br />
5569
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_configuration_functions">[up]</a>
5570
+
5571
+ <a name="setComponent_PROP"></a><h4>3.4.4 setComponent</h4>
5572
+ Add calendar component to calendar or replace/update component in calendar.
5573
+ <p class="label">Format 1</p>
5574
+ <p class="format">setComponent( component )
5575
+ addSubComponent( component ) // <span class="ref">alias</span></p>
5576
+ <p class="comment">Insert last in component chain.</p>
5577
+ <p class="label">Format 2</p>
5578
+ <p class="format">setComponent( component, int orderNumber )</p>
5579
+ <p class="comment">Replace component with order number(1st=1, 2nd=2.. .).
5580
+ If orderNumber is not found, component is inserted last in chain.</p>
5581
+ <p class="label">Format 3</p>
5582
+ <p class="format">setComponent( component, string componentType [,component suborder number])</p>
5583
+ <p class="comment">Replace component with component type and component order number.
5584
+ if orderNumber is not found, component is inserted last in chain. </p>
5585
+ <p class="label">Example</p>
5586
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot; );
5587
+ $vcalendar = new vcalendar( $config ); // <span class="ref">initiate new CALENDAR</span>
5588
+ .. .
5589
+ $vevent = new vevent();
5590
+ $vevent->setProperty( &quot;dtstart&quot; // <span class="ref">add some <a href="#VEVENT">EVENT</a> properties</span>
5591
+ , 2006, 12, 24, 19, 30, 00 );
5592
+ $vevent->setProperty(.. .
5593
+ .. .
5594
+ $valarm = new valarm();
5595
+ $valarm->setProperty( &quot;trigger&quot;, .. .
5596
+ .. .
5597
+ $vevent->setComponent( $valarm );
5598
+ $vcalendar->setComponent( $vevent );
5599
+ .. .
5600
+ </p>
5601
+ <br />
5602
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a> <a href="#Calendar_component_configuration_functions">[up]</a>
5603
+
5604
+ <a name="iCalUtilityFunctions"></a><h1>4. iCalUtilityFunctions</a></h1>
5605
+ iCalUtilityFunctions.class.php contains static functions used by iCalcreator,
5606
+ also usable outside the iCalcreator class. Only function createTimezone is described here,
5607
+ please examine the class file for other functions.
5608
+ <br />
5609
+ <br />
5610
+ <a name="createTimezone"></a><h4>4.1 createTimezone</a></h4>
5611
+ The function, applied on a iCalcrator instance (as argument) creates very simple
5612
+ vtimezone and standard/daylight components. (PHP 5 >= 5.2.0)
5613
+ <p class="label">Format</p>
5614
+ <p class="format">createTimezone( calendar, timezone [, xprops ] )</p>
5615
+ <p class="comment">calendar = iCalcreator instance
5616
+ timezone = an PHP (DateTimeZone) valid timezone
5617
+ xprops = array( *[ x-propName =&gt; value ] ), timezone non-standard properties
5618
+ </p>
5619
+ <p class="label">Example</p>
5620
+ <p class="example">$config = array( &quot;unique_id&quot; =&gt; &quot;domain.com&quot; );
5621
+ $vcalendar = new vcalendar( $config );
5622
+ .. .
5623
+ $PHPtz = 'Europe/Stockholm';
5624
+ $xprops = array( 'X-LIC-LOCATION' => $PHPtz );
5625
+ iCalUtilityFunctions::createTimezone( $vcalendar,
5626
+ $PHPtz,
5627
+ $xprops );
5628
+ .. .
5629
+ </p>
5630
+ Output (from createCalendar or returnCalendar functions):<br />
5631
+ <span class="ref">
5632
+ BEGIN:VTIMEZONE<br />
5633
+ TZID:Europe/Stockholm<br />
5634
+ X-LIC-LOCATION:Europe/Stockholm<br />
5635
+ BEGIN:STANDARD<br />
5636
+ DTSTART:20101031T020000<br />
5637
+ TZOFFSETFROM:+0200<br />
5638
+ TZOFFSETTO:+0100<br />
5639
+ RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10<br />
5640
+ TZNAME:CET<br />
5641
+ END:STANDARD<br />
5642
+ BEGIN:DAYLIGHT<br />
5643
+ DTSTART:20100328T030000<br />
5644
+ TZOFFSETFROM:+0100<br />
5645
+ TZOFFSETTO:+0200<br />
5646
+ RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3<br />
5647
+ TZNAME:CEST<br />
5648
+ END:DAYLIGHT<br />
5649
+ END:VTIMEZONE
5650
+ </span>
5651
+ <br />
5652
+ <br />
5653
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a>
5654
+
5655
+
5656
+ <a name="Copyright_and_Licence"></a><h1>5. COPYRIGHT AND LICENSE</h1>
5657
+ <h2>Copyright</h2>
5658
+ iCalcreator class <br />
5659
+ copyright (c) 2007-2011 Kjell-Inge Gustafsson, kigkonsult<br />
5660
+ www.kigkonsult.Se/iCalcreator/index.php<br />
5661
+ ical@kigkonsult.se<br />
5662
+
5663
+ <h2>License</h2>
5664
+
5665
+ This library is free software; you can redistribute it and/or
5666
+ modify it under the terms of the GNU Lesser General Public
5667
+ License as published by the Free Software Foundation; either
5668
+ version 2.1 of the License, or (at your option) any later version.
5669
+ <br /><br />
5670
+ This library is distributed in the hope that it will be useful,
5671
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
5672
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5673
+ Lesser General Public License for more details.
5674
+ <br /><br />
5675
+ You should have received a copy of the GNU Lesser General Public
5676
+ License along with this library; if not, write to the Free Software
5677
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
5678
+ or download it <a href="http://www.kigkonsult.se/downloads/dl.php?f=LGPL">here</a>.
5679
+ <br />
5680
+ <br />
5681
+ <a href="#INDEX">[index]</a> <a href="#top">[top]</a>
5682
+ </body>
5683
+ </html>
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_i
4
  Tags: calendar, event, events, ics, ics calendar, ical-feed, ics feed, wordpress ics importer, wordpress ical importer, upcoming events, todo, notes, journal, freebusy, availability, web calendar, web events, webcal, google calendar, ical, iCalendar, all-in-one, ai1ec, google calendar sync, ical sync, events sync, holiday calendar, calendar 2011, events 2011, widget, events widget, upcoming events widget, calendar widget, agenda widget
5
  Requires at least: 3.1.3
6
  Tested up to: 3.3
7
- Stable tag: 1.2.3
8
 
9
  An event calendar system with month, week, agenda views, upcoming events widget, color-coded categories, recurrence, and import/export of .ics feeds.
10
 
@@ -57,6 +57,9 @@ The All-in-One Event Calendar Plugin also has a few features that will prove use
57
  * [**Get Premium Support »**](http://theseednetwork.com/get-supported) from [The Seed Studio](http://theseednetwork.com/)
58
 
59
  == Changelog ==
 
 
 
60
  = Version 1.2.3 =
61
  * Improvement: Days of the week in month recurrence [#170](http://trac.the-seed.ca/ticket/170)
62
  * Improvement: Make Month view, Week view compatible with touchscreen devices [#210](http://trac.the-seed.ca/ticket/210)
4
  Tags: calendar, event, events, ics, ics calendar, ical-feed, ics feed, wordpress ics importer, wordpress ical importer, upcoming events, todo, notes, journal, freebusy, availability, web calendar, web events, webcal, google calendar, ical, iCalendar, all-in-one, ai1ec, google calendar sync, ical sync, events sync, holiday calendar, calendar 2011, events 2011, widget, events widget, upcoming events widget, calendar widget, agenda widget
5
  Requires at least: 3.1.3
6
  Tested up to: 3.3
7
+ Stable tag: 1.2.4
8
 
9
  An event calendar system with month, week, agenda views, upcoming events widget, color-coded categories, recurrence, and import/export of .ics feeds.
10
 
57
  * [**Get Premium Support »**](http://theseednetwork.com/get-supported) from [The Seed Studio](http://theseednetwork.com/)
58
 
59
  == Changelog ==
60
+ = Version 1.2.4 =
61
+ * Improvement: Added a lower version of iCalcreator for environments with PHP versions below 5.3.0
62
+
63
  = Version 1.2.3 =
64
  * Improvement: Days of the week in month recurrence [#170](http://trac.the-seed.ca/ticket/170)
65
  * Improvement: Make Month view, Week view compatible with touchscreen devices [#210](http://trac.the-seed.ca/ticket/210)