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 / CalAddressFactory.php

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

632 lines 23.0 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 InvalidArgumentException;
34 use Kigkonsult\Icalcreator\Vcalendar;
35
36 use function array_change_key_case;
37 use function count;
38 use function ctype_digit;
39 use function explode;
40 use function in_array;
41 use function is_array;
42 use function method_exists;
43 use function sprintf;
44 use function strcasecmp;
45 use function strpos;
46 use function strtoupper;
47 use function substr;
48 use function trim;
49
50 /**
51 * iCalcreator attendee support class
52 *
53 * @author Kjell-Inge Gustafsson, kigkonsult <ical@kigkonsult.se>
54 * @since 2.29.21 2019-06-20
55 */
56 class CalAddressFactory
57 {
58 /**
59 * @var array
60 * @access private
61 * @static
62 */
63 private static $ParamArrayKeys = [
64 Vcalendar::MEMBER,
65 Vcalendar::DELEGATED_TO,
66 Vcalendar::DELEGATED_FROM,
67 ];
68
69 /**
70 * @var string Prefix for Ical cal-address etc
71 * @access private
72 * @static
73 *
74 */
75 private static $MAILTOCOLON = 'MAILTO:';
76 private static $AT = '@';
77
78 /**
79 * Assert cal-address (i.e. MAILTO.prefixed)
80 *
81 * @param string $calAddress
82 * @throws InvalidArgumentException
83 * @static
84 * @since 2.27.8 - 2019-03-18
85 */
86 public static function assertCalAddress( $calAddress )
87 {
88 static $DOT = '.';
89 static $XDOT = 'x.';
90 static $ERRMSG = 'Invalid email %s';
91 // if( false == strpos( $calAddress, self::$AT )) {
92 // throw new InvalidArgumentException( sprintf( $ERRMSG, $calAddress ));
93 // }
94 $domain = StringFactory::after( self::$AT, $calAddress );
95 if( false === strpos( StringFactory::before( self::$AT, $calAddress ), $DOT )) {
96 $namePart = self::extractNamepartFromEmail( $calAddress );
97 $testAddress = $XDOT . $namePart . self::$AT . $domain;
98 }
99 else {
100 $testAddress = self::removeMailtoPrefix( $calAddress );
101 }
102 // if( ! filter_var( $testAddress, FILTER_VALIDATE_EMAIL )) {
103 // throw new InvalidArgumentException( sprintf( $ERRMSG, $calAddress ));
104 // }
105 }
106
107 /**
108 * Return conformed cal-address (i.e. MAILTO.prefixed)
109 *
110 * @param string $calAddress
111 * @return string
112 * @static
113 * @since 2.27.8 - 2019-03-17
114 */
115 public static function conformCalAddress( $calAddress )
116 {
117 if( ! empty( $calAddress ) &&
118 ( 0 == strcasecmp( self::$MAILTOCOLON, substr( $calAddress, 0, 7 )))) {
119 $calAddress = self::$MAILTOCOLON . substr( $calAddress, 7 );
120 }
121 return $calAddress;
122 }
123
124 /**
125 * Return bool true if email has leading MAILTO:
126 *
127 * @param string $email
128 * @return bool
129 * @access private
130 * @static
131 * @since 2.27.8 - 2019-03-17
132 */
133 private static function hasMailtoPrefix( $email )
134 {
135 return ( 0 == strcasecmp( self::$MAILTOCOLON, substr( $email, 0, 7 )));
136 }
137
138 /**
139 * Return email without prefix (anycase) 'MAILTO;
140 *
141 * @param string $email
142 * @return string
143 * @static
144 * @since 2.27.8 - 2019-03-17
145 */
146 public static function removeMailtoPrefix( $email )
147 {
148 if( self::hasMailtoPrefix( $email )) {
149 return substr( $email, 7 );
150 }
151 return $email;
152 }
153
154 /**
155 * Return bool true if parameter EMAIL equals ATTENDEE/ORGANIZER value
156 *
157 * @param string $value
158 * @param array $params
159 * @static
160 * @since 2.29.11 - 2019-08-30
161 */
162 public static function sameValueAndEMAILparam( $value, & $params )
163 {
164 if( isset( $params[Vcalendar::EMAIL] ) &&
165 ( 0 == strcasecmp(
166 self::removeMailtoPrefix( $value ),
167 self::removeMailtoPrefix( $params[Vcalendar::EMAIL] ))
168 )) {
169 unset( $params[Vcalendar::EMAIL] );
170 } // end if
171 }
172
173 /**
174 * Extract namePart from email
175 *
176 * @param string $email
177 * @return string
178 * @static
179 * @since 2.27.8 - 2019-03-20
180 */
181 public static function extractNamepartFromEmail( $email )
182 {
183 if( self::hasMailtoPrefix( $email )) {
184 return StringFactory::before( self::$AT, substr( $email, 7 ));
185 }
186 return StringFactory::before( self::$AT, $email );
187 }
188
189 /**
190 * Return cal-addresses and (hopefully) name parts
191 *
192 * From ATTENDEEs and ORGANIZERs, name part from CONTACTs
193 * @param Vcalendar $calendar iCalcreator Vcalendar instance
194 * @param array $properties
195 * @param bool $inclParams fetch from values or include from parameters
196 * @return array
197 * @static
198 * @since 2.27.8 - 2019-03-18
199 */
200 public static function getCalAddresses(
201 Vcalendar $calendar,
202 array $properties = null,
203 $inclParams = false )
204 {
205 static $ALLOWEDPROPERTIES = [
206 Vcalendar::ATTENDEE,
207 Vcalendar::CONTACT,
208 Vcalendar::ORGANIZER
209 ];
210 if( empty( $properties )) {
211 $searchProperties = $ALLOWEDPROPERTIES;
212 }
213 else {
214 $searchProperties = [];
215 foreach( $properties as $property ) {
216 if( in_array( $property, $ALLOWEDPROPERTIES )) {
217 $searchProperties[] = $property;
218 }
219 }
220 }
221 $output = [];
222 foreach( $searchProperties as $propName ) {
223 if( $inclParams ) {
224 $output = array_merge(
225 $output,
226 self::getCalAdressesAllFromProperty( $calendar, $propName )
227 );
228 }
229 else {
230 $output = array_merge(
231 $output,
232 self::getCalAdressValuesFromProperty( $calendar, $propName )
233 );
234 }
235 } // end foreach
236 sort( $output );
237 $output = array_unique( $output );
238 return $output;
239 }
240
241 /**
242 * Return value and parameters cal-addresses from Vcalendar property
243 *
244 * From one of ATTENDEEs and ORGANIZERs, name part from CONTACTs
245 * @param Vcalendar $calendar iCalcreator Vcalendar instance
246 * @param string $propName
247 * @return array
248 * @static
249 * @since 2.29.11 - 2019-08-30
250 */
251 public static function getCalAdressesAllFromProperty(
252 Vcalendar $calendar,
253 $propName
254 ) {
255 $calendar->reset();
256 $output = [];
257 $method = Vcalendar::getGetMethodName( $propName );
258 while( $comp = $calendar->getComponent()) {
259 if( ! method_exists( $comp, $method )) {
260 continue;
261 }
262 switch( $propName ) {
263 case Vcalendar::ATTENDEE :
264 while(( false !== ( $propValue = $comp->{$method}( null, true ))) &&
265 ! empty( $propValue )) {
266 $value = self::removeMailtoPrefix( $propValue[Util::$LCvalue] );
267 if( ! in_array( $value, $output )) {
268 $output[] = $value;
269 }
270 foreach( $propValue[Util::$LCparams] as $pLabel => $pValue ) {
271 switch( $pLabel ) {
272 case Vcalendar::MEMBER: // fall through
273 case Vcalendar::DELEGATED_TO: // fall through
274 case Vcalendar::DELEGATED_FROM:
275 $params2[$pLabel] = [];
276 foreach( $pValue as $pValue2 ) {
277 $pValue2 = self::removeMailtoPrefix(
278 trim( $pValue2, StringFactory::$QQ )
279 );
280 if( ! in_array( $pValue2, $output )) {
281 $output[] = $pValue2;
282 }
283 } // end foreach
284 break;
285 case Vcalendar::EMAIL : // fall through
286 case Vcalendar::SENT_BY :
287 $pValue2 = self::removeMailtoPrefix(
288 trim( $pValue, StringFactory::$QQ )
289 );
290 if( ! in_array( $pValue2, $output )) {
291 $output[] = $pValue2;
292 }
293 break;
294 } // end switch
295 } // end foreach
296 } // end while
297 break;
298 case Vcalendar::ORGANIZER :
299 if(( false === ( $propValue = $comp->{$method}( true ))) ||
300 empty( $propValue )) {
301 break;
302 }
303 $value = self::removeMailtoPrefix( $propValue[Util::$LCvalue] );
304 if( ! in_array( $value, $output )) {
305 $output[] = $value;
306 }
307 foreach( [ Vcalendar::EMAIL, Vcalendar::SENT_BY ] as $key ) {
308 if( isset( $propValue[Util::$LCparams][$key] ) ) {
309 $value = self::removeMailtoPrefix(
310 $propValue[Util::$LCparams][$key]
311 );
312 if( ! in_array( $value, $output ) ) {
313 $output[] = $value;
314 }
315 }
316 } // end foreach
317 break;
318 case Vcalendar::CONTACT :
319 while(( false !== ( $propValue = $comp->{$method}( null, true ))) &&
320 ! empty( $propValue )) {
321 $value =
322 ( false !==
323 ( $pos = strpos( $propValue[Util::$LCvalue], Util::$COMMA ))
324 )
325 ? StringFactory::before( Util::$COMMA, $propValue[Util::$LCvalue] )
326 : $propValue[Util::$LCvalue];
327 try {
328 self::assertCalAddress( $value );
329 }
330 catch( InvalidArgumentException $e ) {
331 continue;
332 }
333 if( ! in_array( $value, $output )) {
334 $output[] = $value;
335 }
336 } // end while
337 break;
338 } // end switch
339 } // end while
340 sort( $output );
341 $output = array_unique( $output );
342 return $output;
343 }
344
345 /**
346 * Return value cal-addresses from Vcalendar property
347 *
348 * From one of ATTENDEEs and ORGANIZERs, name part from CONTACTs
349 * @param Vcalendar $calendar iCalcreator Vcalendar instance
350 * @param string $propName
351 * @return array
352 * @static
353 * @since 2.27.8 - 2019-03-18
354 */
355 public static function getCalAdressValuesFromProperty(
356 Vcalendar $calendar,
357 $propName
358 ) {
359 $output = [];
360 foreach( $calendar->getProperty( $propName ) as $propValue => $counts ) {
361 $propValue = self::removeMailtoPrefix( $propValue );
362 if( false !== strpos( $propValue, Util::$COMMA )) {
363 $propValue = StringFactory::before( Util::$COMMA, $propValue );
364 }
365 try {
366 self::assertCalAddress( $propValue );
367 }
368 catch( InvalidArgumentException $e ) {
369 continue;
370 }
371 if( ! in_array( $propValue, $output )) {
372 $output[] = $propValue;
373 }
374 } // end foreach
375 sort( $output );
376 $output = array_unique( $output );
377 return $output;
378 }
379
380 /**
381 * Return quoted item
382 *
383 * @param array $item
384 * @return string
385 * @access private
386 * @static
387 * @since 2.27.11 - 2019-01-03
388 */
389 private static function getQuotedItem( $item )
390 {
391 static $FMTQVALUE = '"%s"';
392 return sprintf( $FMTQVALUE, $item );
393 }
394
395 /**
396 * Return string of comma-separated quoted array members
397 *
398 * @param array $list
399 * @return string
400 * @access private
401 * @static
402 * @since 2.27.11 - 2019-01-03
403 */
404 private static function getQuotedListItems( array $list )
405 {
406 foreach( $list as & $v ) {
407 $v = self::getQuotedItem( $v );
408 }
409 return implode( Util::$COMMA, $list );
410 }
411
412 /**
413 * Return formatted output for calendar component property attendee
414 *
415 * @param array $params
416 * @param string $compType
417 * @param string $lang
418 * @return array
419 * @throws InvalidArgumentException
420 * @static
421 * @since 2.29.11 - 2019-08-30
422 */
423 public static function inputPrepAttendeeParams( $params, $compType, $lang )
424 {
425 static $XX = 'X-';
426 static $NoParamComps = [ Vcalendar::VFREEBUSY, Vcalendar::VALARM ];
427 $params2 = [];
428 if( is_array( $params )) {
429 $params = array_change_key_case( $params, CASE_UPPER );
430 foreach( $params as $pLabel => $optParamValue ) {
431 if( ! StringFactory::isXprefixed( $pLabel ) &&
432 Util::isCompInList( $compType, $NoParamComps )) {
433 continue;
434 }
435 if( ctype_digit((string) $pLabel )) { // ??
436 $pLabel = $XX . $pLabel;
437 }
438 switch( $pLabel ) {
439 case Vcalendar::MEMBER: // fall through
440 case Vcalendar::DELEGATED_TO: // fall through
441 case Vcalendar::DELEGATED_FROM:
442 $params2[$pLabel] = [];
443 foreach( (array) $optParamValue as $optParamValue2 ) {
444 $optParamValue2 =
445 self::conformCalAddress(
446 trim( $optParamValue2, StringFactory::$QQ )
447 );
448 self::assertCalAddress( $optParamValue2 );
449 $params2[$pLabel][] = $optParamValue2;
450 } // end foreach
451 break;
452 case Vcalendar::EMAIL : // fall through
453 case Vcalendar::SENT_BY :
454 $optParamValue =
455 self::conformCalAddress(
456 trim( $optParamValue, StringFactory::$QQ )
457 );
458 self::assertCalAddress( $optParamValue );
459 $params2[$pLabel] = $optParamValue;
460 break;
461 default:
462 $params2[$pLabel] = trim( $optParamValue, StringFactory::$QQ );
463 break;
464 } // end switch( $pLabel.. .
465 } // end foreach( $params as $pLabel => $optParamValue )
466 } // end if( is_array($params ))
467 // remove defaults
468 ParameterFactory::ifExistRemove(
469 $params2,
470 Vcalendar::CUTYPE,
471 Vcalendar::INDIVIDUAL
472 );
473 ParameterFactory::ifExistRemove(
474 $params2,
475 Vcalendar::PARTSTAT,
476 Vcalendar::NEEDS_ACTION
477 );
478 ParameterFactory::ifExistRemove(
479 $params2,
480 Vcalendar::ROLE,
481 Vcalendar::REQ_PARTICIPANT
482 );
483 ParameterFactory::ifExistRemove(
484 $params2,
485 Vcalendar::RSVP,
486 Vcalendar::FALSE
487 );
488 // check language setting
489 if( isset( $params2[Vcalendar::CN] ) &&
490 ! isset( $params2[Vcalendar::LANGUAGE] ) &&
491 ! empty( $lang )) {
492 $params2[Vcalendar::LANGUAGE] = $lang;
493 }
494 return $params2;
495 }
496
497 /**
498 * Return formatted output for calendar component property attendee
499 *
500 * @param array $attendeeData
501 * @param bool $allowEmpty
502 * @return string
503 * @static
504 * @since 2.29.11 - 2019-08-30
505 */
506 public static function outputFormatAttendee( array $attendeeData, $allowEmpty )
507 {
508 static $AllKeys = [
509 Vcalendar::CUTYPE,
510 Vcalendar::MEMBER,
511 Vcalendar::ROLE,
512 Vcalendar::PARTSTAT,
513 Vcalendar::RSVP,
514 Vcalendar::DELEGATED_TO,
515 Vcalendar::DELEGATED_FROM,
516 Vcalendar::SENT_BY,
517 Vcalendar::EMAIL,
518 Vcalendar::DIR,
519 Vcalendar::CN,
520 Vcalendar::LANGUAGE
521 ];
522 static $KEYGRP1 = [ Vcalendar::ROLE, Vcalendar::PARTSTAT, Vcalendar::RSVP ];
523 static $KEYGRP2 = [ Vcalendar::DELEGATED_TO, Vcalendar::DELEGATED_FROM ];
524 static $KEYGRP3 = [ Vcalendar::SENT_BY, Vcalendar::EMAIL ];
525 static $KEYGRP4 = [ Vcalendar::CN, Vcalendar::LANGUAGE ];
526 static $FMTKEYVALUE = ';%s=%s';
527 static $FMTDIREQ = ';%s=%s%s%s';
528 $output = null;
529 foreach( $attendeeData as $ax => $attendeePart ) {
530 if( empty( $attendeePart[Util::$LCvalue] )) {
531 if( $allowEmpty ) {
532 $output .= StringFactory::createElement( Vcalendar::ATTENDEE );
533 }
534 continue;
535 }
536 $attributes = $content = null;
537 foreach( $attendeePart as $pLabel => $pValue ) {
538 if( Util::$LCvalue == $pLabel ) {
539 $content .= $pValue;
540 continue;
541 }
542 if(( Util::$LCparams != $pLabel ) ||
543 ( ! is_array( $pValue ))) {
544 continue;
545 }
546 foreach( $pValue as $pLabel2 => $pValue2 ) { // fix (opt) quotes
547 if( is_array( $pValue2 ) ||
548 in_array( $pLabel2, self::$ParamArrayKeys )) {
549 continue;
550 } // all but DELEGATED-FROM, DELEGATED-TO, MEMBER
551 if(( false !== strpos( $pValue2, Util::$COLON )) ||
552 ( false !== strpos( $pValue2, Util::$SEMIC )) ||
553 ( false !== strpos( $pValue2, Util::$COMMA ))) {
554 $pValue[$pLabel2] = self::getQuotedItem( $pValue2 );
555 }
556 } // end foreach
557 /* set attendee parameters in (almost) rfc2445 order */
558 if( isset( $pValue[Vcalendar::CUTYPE] )) {
559 $attributes .= sprintf( $FMTKEYVALUE, Vcalendar::CUTYPE, $pValue[Vcalendar::CUTYPE] );
560 }
561 if( isset( $pValue[Vcalendar::MEMBER] )) {
562 $attributes .= sprintf(
563 $FMTKEYVALUE,
564 Vcalendar::MEMBER,
565 self::getQuotedListItems( $pValue[Vcalendar::MEMBER] )
566 );
567 }
568 foreach( $KEYGRP1 as $key ) { // ROLE, PARTSTAT, RSVP
569 if( isset( $pValue[$key] ) ) {
570 $attributes .= sprintf( $FMTKEYVALUE, $key, $pValue[$key] );
571 }
572 } // end foreach
573 foreach( $KEYGRP2 as $key ) { // DELEGATED_TO, DELEGATED_FROM
574 if( isset( $pValue[$key] ) ) {
575 $attributes .= sprintf( $FMTKEYVALUE, $key, self::getQuotedListItems( $pValue[$key] ));
576 }
577 } // end foreach
578 foreach( $KEYGRP3 as $key ) { // SENT_BY, EMAIL
579 if( isset( $pValue[$key] ) ) {
580 $attributes .= sprintf( $FMTKEYVALUE, $key, self::getQuotedListItems( [ $pValue[$key] ] ));
581 }
582 } // end foreach
583 if( isset( $pValue[Vcalendar::DIR] )) {
584 $delim = ( false === strpos( $pValue[Vcalendar::DIR], StringFactory::$QQ )) ? StringFactory::$QQ : null;
585 $attributes .= sprintf( $FMTDIREQ, Vcalendar::DIR, $delim, $pValue[Vcalendar::DIR], $delim );
586 }
587 foreach( $KEYGRP4 as $key ) { // CN, LANGUAGE
588 if( isset( $pValue[$key] )) {
589 $attributes .= sprintf( $FMTKEYVALUE, $key, $pValue[$key] );
590 }
591 } // end foreach
592 $xParams = [];
593 foreach( $pValue as $pLabel2 => $pValue2 ) {
594 if( ! in_array( $pLabel2, $AllKeys )) {
595 $xParams[$pLabel2] = $pValue2;
596 }
597 }
598 if( ! empty( $xParams )) {
599 ksort( $xParams, SORT_STRING );
600 foreach( $xParams as $pLabel2 => $pValue2 ) {
601 $attributes .= sprintf( $FMTKEYVALUE, $pLabel2, $pValue2 );
602 }
603 }
604 } // end foreach( $attendeePart )) as $pLabel => $pValue )
605 $output .= StringFactory::createElement( Vcalendar::ATTENDEE, $attributes, $content );
606 } // end foreach( $attendeeData as $ax => $attendeePart )
607 return $output;
608 }
609
610 /**
611 * Return value and parameters from parsed row and propAttr
612 *
613 * @param string $row
614 * @param array $propAttr
615 * @return array
616 * @since 2.27.11 - 2019-01-04
617 */
618 public static function parseAttendee( $row, array $propAttr )
619 {
620 foreach( $propAttr as $pix => $attr ) {
621 if( ! in_array( strtoupper( $pix ), self::$ParamArrayKeys )) {
622 continue;
623 } // 'MEMBER', 'DELEGATED-TO', 'DELEGATED-FROM'
624 $attr2 = explode( Util::$COMMA, $attr );
625 if( 1 < count( $attr2 )) {
626 $propAttr[$pix] = $attr2;
627 }
628 }
629 return [ $row, $propAttr ];
630 }
631 }
632