nystudio107 /
craft-icalendar
| 1 | <?php |
||
| 2 | /** |
||
| 3 | * iCalendar plugin for Craft CMS 3.x |
||
|
0 ignored issues
–
show
Coding Style
introduced
by
Loading history...
|
|||
| 4 | * |
||
| 5 | * Tools for parsing & formatting the RFC 2445 iCalendar (.ics) specification |
||
| 6 | * |
||
| 7 | * @link https://nystudio107.com |
||
|
0 ignored issues
–
show
|
|||
| 8 | * @copyright Copyright (c) 2018 nystudio107 |
||
|
0 ignored issues
–
show
|
|||
| 9 | */ |
||
|
0 ignored issues
–
show
|
|||
| 10 | |||
| 11 | namespace nystudio107\icalendar\services; |
||
| 12 | |||
| 13 | use craft\base\Component; |
||
| 14 | |||
| 15 | /** |
||
|
0 ignored issues
–
show
|
|||
| 16 | * @author nystudio107 |
||
|
0 ignored issues
–
show
Content of the @author tag must be in the form "Display Name <[email protected]>"
Loading history...
|
|||
| 17 | * @package ICalendar |
||
|
0 ignored issues
–
show
|
|||
| 18 | * @since 1.0.0 |
||
|
0 ignored issues
–
show
|
|||
| 19 | */ |
||
|
0 ignored issues
–
show
|
|||
| 20 | class Convert extends Component |
||
| 21 | { |
||
| 22 | // Constants |
||
| 23 | // ========================================================================= |
||
| 24 | |||
| 25 | protected const RFC2455_EOL = "\r\n"; |
||
| 26 | protected const RFC2455_TAB = "\t"; |
||
| 27 | protected const RFC2455_LITERAL_NEWLINE = '\n'; |
||
| 28 | protected const MAX_OCTETS = 75; |
||
| 29 | |||
| 30 | // Public Methods |
||
| 31 | // ========================================================================= |
||
| 32 | |||
| 33 | /** |
||
| 34 | * Format the passed in $text as per the iCalendar RFC 2445 spec: |
||
| 35 | * https://icalendar.org/validator.html |
||
| 36 | * |
||
| 37 | * @param string $text |
||
|
0 ignored issues
–
show
|
|||
| 38 | * |
||
| 39 | * @return string |
||
| 40 | */ |
||
| 41 | public function rfc2445(string $text): string |
||
| 42 | { |
||
| 43 | $result = ''; |
||
| 44 | // Normalize the line breaks |
||
| 45 | $text = str_replace(["\n", "\r\r\n"], self::RFC2455_EOL, $text); |
||
| 46 | // Handle rich text field output, such as from Redactor, which may have line or paragraph breaks |
||
| 47 | $text = str_replace(["</p>\r", "</P>\r"], self::RFC2455_LITERAL_NEWLINE . self::RFC2455_LITERAL_NEWLINE, $text); |
||
| 48 | $text = str_replace(["<br>\r", "<BR>\r", "<br />\r", "<BR />\r"], self::RFC2455_LITERAL_NEWLINE, $text); |
||
| 49 | // Split the text into separate lines |
||
| 50 | $lines = explode(self::RFC2455_EOL, $text); |
||
| 51 | foreach ($lines as $key => $line) { |
||
| 52 | $result .= $this->icalSplit('', $line) . self::RFC2455_EOL; |
||
| 53 | } |
||
| 54 | |||
| 55 | return $result; |
||
| 56 | } |
||
| 57 | |||
| 58 | // Protected Methods |
||
| 59 | // ========================================================================= |
||
| 60 | |||
| 61 | /** |
||
| 62 | * Split the lines into RFC 2445 compatible line breaks so that no line |
||
| 63 | * is longer than 75 octets |
||
| 64 | * Adapted from: https://gist.github.com/hugowetterberg/81747 |
||
| 65 | * |
||
| 66 | * @param string $preamble |
||
|
0 ignored issues
–
show
|
|||
| 67 | * @param string $value |
||
|
0 ignored issues
–
show
|
|||
| 68 | * |
||
| 69 | * @return string |
||
| 70 | */ |
||
| 71 | protected function icalSplit(string $preamble, string $value): string |
||
| 72 | { |
||
| 73 | $value = trim($value); |
||
| 74 | $value = strip_tags($value); |
||
| 75 | $value = html_entity_decode($value); |
||
| 76 | $value = preg_replace('/\n+/', ' ', $value); |
||
| 77 | $value = preg_replace('/\s{2,}/', ' ', $value); |
||
| 78 | $preamble_len = mb_strlen($preamble); |
||
| 79 | $lines = []; |
||
| 80 | while (mb_strlen($value) > (self::MAX_OCTETS - $preamble_len)) { |
||
| 81 | $space = (self::MAX_OCTETS - $preamble_len); |
||
| 82 | $mbcc = $space; |
||
| 83 | while ($mbcc) { |
||
| 84 | $line = mb_substr($value, 0, $mbcc); |
||
| 85 | $oct = mb_strlen($line); |
||
| 86 | if ($oct > $space) { |
||
| 87 | $mbcc -= $oct - $space; |
||
| 88 | } else { |
||
| 89 | $lines[] = $line; |
||
| 90 | $preamble_len = 1; // Still take the tab into account |
||
| 91 | $value = mb_substr($value, $mbcc); |
||
| 92 | break; |
||
| 93 | } |
||
| 94 | } |
||
| 95 | } |
||
| 96 | if (!empty($value)) { |
||
| 97 | $lines[] = $value; |
||
| 98 | } |
||
| 99 | |||
| 100 | return implode(self::RFC2455_EOL . self::RFC2455_TAB, $lines); |
||
| 101 | } |
||
| 102 | } |
||
| 103 |