PluginProbe
Import Social Events / 1.9.0
Import Social Events v1.9.0
1.9.1 1.9.0 trunk 1.0.0 1.0.1 1.1.0 1.1.1 1.1.2 1.1.3 1.1.4 1.1.5 1.2.0 1.3.0 1.4.0 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.6.0 1.6.1 1.6.10 1.6.11 1.6.12 All 61 releases
import-facebook-events / includes / lib / icalcreator / src / Util / RexdateFactory.php

RexdateFactory.php in Import Social Events 1.9.0, at includes/lib/icalcreator/src/Util/RexdateFactory.php

524 lines 19.7 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * iCalcreator, the PHP class package managing iCal (rfc2445/rfc5445) calendar information.
4 *
5 * copyright (c) 2007-2021 Kjell-Inge Gustafsson, kigkonsult, All rights reserved
6 * Link https://kigkonsult.se
7 * Package iCalcreator
8 * Version 2.30
9 * License Subject matter of licence is the software iCalcreator.
10 * The above copyright, link, package and version notices,
11 * this licence notice and the invariant [rfc5545] PRODID result use
12 * as implemented and invoked in iCalcreator shall be included in
13 * all copies or substantial portions of the iCalcreator.
14 *
15 * iCalcreator is free software: you can redistribute it and/or modify
16 * it under the terms of the GNU Lesser General Public License as published
17 * by the Free Software Foundation, either version 3 of the License,
18 * or (at your option) any later version.
19 *
20 * iCalcreator is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU Lesser General Public License for more details.
24 *
25 * You should have received a copy of the GNU Lesser General Public License
26 * along with iCalcreator. If not, see <https://www.gnu.org/licenses/>.
27 *
28 * This file is a part of iCalcreator.
29 */
30
31 namespace Kigkonsult\Icalcreator\Util;
32
33 use DateTime;
34 use DateTimeInterface;
35 use DateInterval;
36 use Exception;
37 use InvalidArgumentException;
38 use Kigkonsult\Icalcreator\Vcalendar;
39
40 use function array_keys;
41 use function count;
42 use function explode;
43 use function is_array;
44 use function reset;
45 use function substr;
46 use function usort;
47 use function var_export; // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_var_export
48
49 /**
50 * iCalcreator EXDATE/RDATE support class
51 *
52 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
53 * @since 2.29.16 2020-01-24
54 */
55 class RexdateFactory
56 {
57 /**
58 * @var array
59 * @static
60 */
61 private static $DEFAULTVALUEDATETIME = [
62 Vcalendar::VALUE => Vcalendar::DATE_TIME
63 ];
64
65 /**
66 * @var string
67 * @static
68 */
69 private static $REXDATEERR = 'Unknown %s value (#%d) : %s';
70
71 /**
72 * Return formatted output for calendar component property data value type recur
73 *
74 * @param array $exdateData
75 * @param bool $allowEmpty
76 * @return string
77 * @throws Exception
78 * @throws InvalidArgumentException
79 * @static
80 * @since 2.29.2 2019-06-23
81 */
82 public static function formatExdate( $exdateData, $allowEmpty )
83 {
84 static $SORTER1 = [
85 'Kigkonsult\Icalcreator\Util\SortFactory',
86 'sortExdate1',
87 ];
88 static $SORTER2 = [
89 'Kigkonsult\Icalcreator\Util\SortFactory',
90 'sortExdate2',
91 ];
92 $output = null;
93 $exdates = [];
94 foreach(( array_keys( $exdateData )) as $ex ) {
95 $theExdate = $exdateData[$ex];
96 if( empty( $theExdate[Util::$LCvalue] )) {
97 if( $allowEmpty ) {
98 $output .= StringFactory::createElement( Vcalendar::EXDATE );
99 }
100 continue;
101 }
102 if( 1 < count( $theExdate[Util::$LCvalue] )) {
103 usort( $theExdate[Util::$LCvalue], $SORTER1 );
104 }
105 $exdates[] = $theExdate;
106 } // end foreach
107 if( 1 < count( $exdates )) {
108 usort( $exdates, $SORTER2 );
109 }
110 foreach(( array_keys( $exdates )) as $ex ) {
111 $theExdate = $exdates[$ex];
112 $isValueDate = ParameterFactory::isParamsValueSet(
113 $theExdate,
114 Vcalendar::DATE
115 );
116 $isLocalTime = isset( $theExdate[Util::$LCparams][Util::$ISLOCALTIME] );
117 $content = null;
118 foreach(( array_keys( $theExdate[Util::$LCvalue] )) as $eix ) {
119 $formatted = DateTimeFactory::dateTime2Str(
120 $theExdate[Util::$LCvalue][$eix],
121 $isValueDate,
122 $isLocalTime
123 );
124 $content .= ( 0 < $eix ) ? Util::$COMMA . $formatted : $formatted;
125 } // end foreach
126 $output .= StringFactory::createElement(
127 Vcalendar::EXDATE,
128 ParameterFactory::createParams( $theExdate[Util::$LCparams] ),
129 $content
130 );
131 } // end foreach(( array_keys( $exdates...
132 return $output;
133 }
134
135 /**
136 * Return prepared calendar component property exdate input
137 *
138 * @param string[]|DateTimeInterface[] $exdates
139 * @param array $params
140 * @return mixed array|bool
141 * @throws Exception
142 * @throws InvalidArgumentException
143 * @static
144 * @since 2.29.16 2020-01-24
145 */
146 public static function prepInputExdate( $exdates, $params = null )
147 {
148 $output = [
149 Util::$LCvalue => [],
150 Util::$LCparams => ParameterFactory::setParams(
151 $params,
152 self::$DEFAULTVALUEDATETIME
153 )
154 ];
155 $isValueDate = ParameterFactory::isParamsValueSet( $output, Vcalendar::DATE );
156 $paramTZid = ParameterFactory::getParamTzid( $output );
157 $forceUTC = ( Vcalendar::UTC == $paramTZid );
158 $isLocalTime = false;
159 if( ! empty( $paramTZid )) {
160 if( DateTimeZoneFactory::hasOffset( $paramTZid )) {
161 $paramTZid = DateTimeZoneFactory::getTimeZoneNameFromOffset( $paramTZid );
162 }
163 else {
164 DateTimeZoneFactory::assertDateTimeZone( $paramTZid );
165 }
166 }
167 foreach(( array_keys( $exdates )) as $eix ) {
168 $theExdate = DateTimeFactory::cnvrtDateTimeInterface( $exdates[$eix] );
169 $wDate = null;
170 switch( true ) {
171 case ( $theExdate instanceof DateTime ) :
172 $wDate = DateTimeFactory::conformDateTime(
173 $theExdate,
174 $isValueDate,
175 $forceUTC,
176 $paramTZid
177 );
178 break;
179 case ( DateTimeFactory::isStringAndDate( $theExdate )) : // ex. 2006-08-03 10:12:18
180 $wDate = DateTimeFactory::conformStringDate(
181 $theExdate,
182 $isValueDate,
183 $forceUTC,
184 $isLocalTime,
185 $paramTZid
186 );
187 break;
188 default:
189 throw new InvalidArgumentException(
190 sprintf(
191 self::$REXDATEERR, // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
192 Vcalendar::EXDATE, // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
193 $eix, // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
194 var_export( $theExdate, true ) // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped, WordPress.PHP.DevelopmentFunctions.error_log_var_export
195 )
196 );
197 break;
198 } // end switch
199 $output[Util::$LCvalue][] = $wDate;
200 } // end foreach(( array_keys( $exdates...
201 if( 0 >= count( $output[Util::$LCvalue] )) {
202 return false;
203 }
204 DateTimeFactory::conformDateTimeParams(
205 $output[Util::$LCparams], $isValueDate, $isLocalTime, $paramTZid
206 );
207 return $output;
208 }
209
210 /**
211 * Return formatted output for calendar component property rdate
212 *
213 * @param array $rdateData
214 * @param bool $allowEmpty
215 * @param string $compType
216 * @return string
217 * @static
218 * @throws Exception
219 * @since 2.29.2 - 2019-06-27
220 */
221 public static function formatRdate( $rdateData, $allowEmpty, $compType )
222 {
223 static $SORTER1 = [
224 'Kigkonsult\Icalcreator\Util\SortFactory',
225 'sortRdate1',
226 ];
227 static $SORTER2 = [
228 'Kigkonsult\Icalcreator\Util\SortFactory',
229 'sortRdate2',
230 ];
231 $utcTime = Util::isCompInList( $compType, Vcalendar::$TZCOMPS );
232 $output = null;
233 $rDates = [];
234 foreach(( array_keys( $rdateData )) as $rpix ) {
235 $theRdate = $rdateData[$rpix];
236 if( empty( $theRdate[Util::$LCvalue] )) {
237 if( $allowEmpty ) {
238 $output .= StringFactory::createElement( Vcalendar::RDATE );
239 }
240 continue;
241 }
242 if( $utcTime ) {
243 unset( $theRdate[Util::$LCparams][Vcalendar::TZID] );
244 }
245 if( 1 < count( $theRdate[Util::$LCvalue] )) {
246 usort( $theRdate[Util::$LCvalue], $SORTER1 );
247 }
248 $rDates[] = $theRdate;
249 } // end foreach
250 if( 1 < count( $rDates )) {
251 usort( $rDates, $SORTER2 );
252 }
253 foreach(( array_keys( $rDates )) as $rpix ) {
254 $theRdate = $rDates[$rpix];
255 $isValueDate = ParameterFactory::isParamsValueSet(
256 $theRdate,
257 Vcalendar::DATE
258 );
259 $isLocalTime = isset( $theRdate[Util::$LCparams][Util::$ISLOCALTIME] );
260 $attributes = ParameterFactory::createParams( $theRdate[Util::$LCparams] );
261 $cnt = count( $theRdate[Util::$LCvalue] );
262 $content = null;
263 $rno = 1;
264 foreach(( array_keys( $theRdate[Util::$LCvalue] )) as $rix ) {
265 $rdatePart = $theRdate[Util::$LCvalue][$rix];
266 $contentPart = null;
267 if( is_array( $rdatePart ) &&
268 ParameterFactory::isParamsValueSet( $theRdate, Vcalendar::PERIOD )) {
269 // PERIOD part 1
270 $contentPart = DateTimeFactory::dateTime2Str(
271 $rdatePart[0],
272 $isValueDate,
273 $isLocalTime
274 );
275 $contentPart .= '/';
276 // PERIOD part 2
277 if( DateIntervalFactory::isDateIntervalArrayInvertSet( $rdatePart[1] )) { // fix pre 7.0.5 bug
278 try {
279 $dateInterval =
280 DateIntervalFactory::DateIntervalArr2DateInterval(
281 $rdatePart[1]
282 );
283 }
284 catch( Exception $e ) {
285 throw $e;
286 }
287 $contentPart .= DateIntervalFactory::dateInterval2String(
288 $dateInterval
289 );
290 }
291 else { // date-time
292 $contentPart .=
293 DateTimeFactory::dateTime2Str(
294 $rdatePart[1],
295 $isValueDate,
296 $isLocalTime
297 );
298 }
299
300 } // PERIOD end
301 else { // SINGLE date start
302 $contentPart = DateTimeFactory::dateTime2Str(
303 $rdatePart,
304 $isValueDate,
305 $isLocalTime
306 );
307 }
308 $content .= $contentPart;
309 if( $rno < $cnt ) {
310 $content .= Util::$COMMA;
311 }
312 $rno++;
313 } // end foreach(( array_keys( $theRdate[Util::$LCvalue]...
314 $output .= StringFactory::createElement(
315 Vcalendar::RDATE,
316 $attributes,
317 $content
318 );
319 } // foreach(( array_keys( $rDates...
320 return $output;
321 }
322
323 /**
324 * Return value and parameters from parsed row and propAttr
325 *
326 * @param string $row
327 * @param array $propAttr
328 * @return array
329 * @since 2.27.11 - 2019-01-04
330 */
331 public static function parseRexdate( $row, array $propAttr )
332 {
333 static $SS = '/';
334 if( empty( $row )) {
335 return [ null, $propAttr ];
336 }
337 $values = explode( Util::$COMMA, $row );
338 foreach( $values as $vix => $value ) {
339 if( false === strpos( $value, $SS )) {
340 continue;
341 }
342 $value2 = explode( $SS, $value );
343 if( 1 < count( $value2 )) {
344 $values[$vix] = $value2;
345 }
346 } // end foreach
347 return [ $values, $propAttr ];
348 }
349
350 /**
351 * Return prepared calendar component property rdate input
352 *
353 * @param array $rDates
354 * @param array $params
355 * @return array
356 * @throws InvalidArgumentException
357 * @throws Exception
358 * @static
359 * @since 2.29.16 2020-01-24
360 */
361 public static function prepInputRdate( array $rDates, $params=null )
362 {
363 $output = [
364 Util::$LCparams => ParameterFactory::setParams(
365 $params,
366 self::$DEFAULTVALUEDATETIME
367 )
368 ];
369 $isValuePeriod = ParameterFactory::isParamsValueSet(
370 $output,
371 Vcalendar::PERIOD
372 );
373 $isValueDate = ParameterFactory::isParamsValueSet(
374 $output,
375 Vcalendar::DATE
376 );
377 $isLocalTime = isset( $params[Util::$ISLOCALTIME] );
378 if( $isLocalTime ) {
379 $isValuePeriod = $isValueDate = false;
380 $paramTZid = Vcalendar::UTC;
381 }
382 else {
383 $paramTZid = ParameterFactory::getParamTzid( $output );
384 if( ! empty( $paramTZid )) {
385 if( DateTimeZoneFactory::hasOffset( $paramTZid )) {
386 $paramTZid =
387 DateTimeZoneFactory::getTimeZoneNameFromOffset( $paramTZid );
388 }
389 else {
390 DateTimeZoneFactory::assertDateTimeZone( $paramTZid );
391 }
392 }
393 }
394 $forceUTC = ( Vcalendar::UTC == $paramTZid );
395 foreach( $rDates as $rpix => $theRdate ) {
396 switch( true ) {
397 case $isValuePeriod : // PERIOD
398 list( $wDate, $paramTZid ) = self::getPeriod(
399 $theRdate,
400 $rpix,
401 $isValueDate,
402 $paramTZid,
403 $isLocalTime
404 );
405 $output[Util::$LCvalue][] = $wDate;
406 break;
407 case ( $theRdate instanceof DateTimeInterface ) : // SINGLE DateTime
408 $theRdate = DateTimeFactory::cnvrtDateTimeInterface( $theRdate );
409 $output[Util::$LCvalue][] = DateTimeFactory::conformDateTime(
410 $theRdate, $isValueDate, $forceUTC, $paramTZid
411 );
412 break;
413 case ( DateTimeFactory::isStringAndDate( $theRdate )) : // SINGLE string gmdate(time)
414 $output[Util::$LCvalue][] = DateTimeFactory::conformStringDate(
415 $theRdate,
416 $isValueDate,
417 $forceUTC,
418 $isLocalTime,
419 $paramTZid
420 );
421 break;
422 default :
423 throw new InvalidArgumentException(
424 sprintf(
425 self::$REXDATEERR, // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
426 Vcalendar::RDATE, $rpix, // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
427 var_export( $theRdate, true ) // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped, WordPress.PHP.DevelopmentFunctions.error_log_var_export
428 )
429 );
430 } // end switch
431 } // end foreach( $rDates as $rpix => $theRdate )
432 DateTimeFactory::conformDateTimeParams(
433 $output[Util::$LCparams], $isValueDate, $isLocalTime, $paramTZid
434 );
435 return $output;
436 }
437
438 /**
439 * Return managed period (dateTime/dateTime or dateTime/dateInterval)
440 *
441 * @param array $period
442 * @param int $rpix
443 * @param bool $isValueDate
444 * @param string $paramTZid
445 * @param bool $isLocalTime
446 * @return array
447 * @throws Exception
448 * @throws InvalidArgumentException
449 * @static
450 * @since 2.29.16 2020-01-24
451 */
452 private static function getPeriod(
453 array $period,
454 $rpix,
455 $isValueDate,
456 & $paramTZid,
457 & $isLocalTime
458 ) {
459 $forceUTC = ( Vcalendar::UTC == $paramTZid );
460 $wDate = [];
461 $perX = -1;
462 foreach( $period as $rix => $rPeriod ) {
463 $perX += 1;
464 if( $rPeriod instanceof DateInterval ) {
465 $wDate[$perX] = (array) $rPeriod; // fix pre 7.0.5 bug
466 continue;
467 }
468 if( is_array( $rPeriod ) && ( 1 == count( $rPeriod )) &&
469 DateTimeFactory::isStringAndDate( reset( $rPeriod ))) { // text-date
470 $rPeriod = reset( $rPeriod );
471 }
472 switch( true ) {
473 case ( $rPeriod instanceof DateTimeInterface ) :
474 $rPeriod = DateTimeFactory::cnvrtDateTimeInterface( $rPeriod );
475 $wDate[$perX] = DateTimeFactory::conformDateTime(
476 $rPeriod,
477 $isValueDate,
478 $forceUTC,
479 $paramTZid
480 );
481 if( empty( $paramTZid ) && ! $isLocalTime ) {
482 $paramTZid = $wDate[$perX]->getTimezone()->getName();
483 }
484 break;
485 case DateIntervalFactory::isStringAndDuration( $rPeriod ) : // string format duration
486 if( DateIntervalFactory::$P != $rPeriod[0] ) {
487 $rPeriod = substr( $rPeriod, 1 );
488 }
489 try {
490 $wDate[$perX] =
491 (array) DateIntervalFactory::conformDateInterval(
492 new DateInterval( $rPeriod )
493 );
494 }
495 catch( Exception $e ) {
496 throw $e;
497 }
498 continue 2;
499 break;
500 case ( DateTimeFactory::isStringAndDate( $rPeriod )) : // text date ex. 2006-08-03 10:12:18
501 $wDate[$perX] = DateTimeFactory::conformStringDate(
502 $rPeriod,
503 $isValueDate,
504 $forceUTC,
505 $isLocalTime,
506 $paramTZid
507 );
508 break;
509 default :
510 throw new InvalidArgumentException(
511 sprintf(
512 self::$REXDATEERR, // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
513 Vcalendar::RDATE, // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
514 $rpix, // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped
515 var_export( $rPeriod, true ) // phpcs:ignore WordPress.Security.EscapeOutput.ExceptionNotEscaped, WordPress.PHP.DevelopmentFunctions.error_log_var_export
516 )
517 );
518 break;
519 } // end switch
520 } // end foreach( $theRdate as $rix => $rPeriod )
521 return [ $wDate, $paramTZid ];
522 }
523 }
524