ILIAS  trunk Revision v11.0_alpha-1715-g7fc467680fb
All Data Structures Namespaces Files Functions Variables Enumerations Enumerator Modules Pages
PostingReplySubjectBuilder.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
22 
24 {
25  private const EXPECTED_REPLY_PREFIX_END = ':';
29  private const EXPECTED_NUMBER_WRAPPER_CHAR_END = ')';
30 
32  private static ?array $f = null;
33 
34  private string $reply_prefix;
36 
41  public function __construct(string $reply_prefix, string $optimized_repeated_reply_prefix)
42  {
43  $this->reply_prefix = trim($reply_prefix);
44  $this->optimized_repeated_reply_prefix = trim($optimized_repeated_reply_prefix);
45 
46  if (self::$f === null) {
47  self::$f = [
48  'strpos' => function (string $haystack, string $needle, ?int $offset = 0) {
49  return function_exists('mb_strpos') ? mb_strpos($haystack, $needle, $offset, 'UTF-8') : strpos(
50  $haystack,
51  $needle,
52  $offset
53  );
54  },
55  'strrpos' => function (string $haystack, string $needle, ?int $offset = 0) {
56  return function_exists('mb_strrpos') ? mb_strrpos($haystack, $needle, $offset, 'UTF-8') : strrpos(
57  $haystack,
58  $needle,
59  $offset
60  );
61  },
62  'strlen' => function (string $string): int {
63  return function_exists('mb_strlen') ? mb_strlen($string, 'UTF-8') : strlen($string);
64  },
65  'substr' => function (string $string, int $start, ?int $length = null): string {
66  return function_exists('mb_substr') ? mb_substr($string, $start, $length, 'UTF-8') : substr(
67  $string,
68  $start,
69  $length
70  );
71  }
72  ];
73  }
74  }
75 
76  public function build(string $subject_of_parent_posting): string
77  {
78  $subject_of_parent_posting = trim($subject_of_parent_posting);
79  $subject_of_reply = '';
80 
81  $reply_prefix = $this->reply_prefix;
82  if ((self::$f['substr'])(
83  $reply_prefix,
84  -((self::$f['strlen'])(self::EXPECTED_REPLY_PREFIX_END))
85  ) !== self::EXPECTED_REPLY_PREFIX_END) {
86  $reply_prefix .= self::EXPECTED_REPLY_PREFIX_END;
87  }
88 
89  $optimized_repeated_reply_prefix = $this->optimized_repeated_reply_prefix;
90  if ((self::$f['substr'])(
91  $optimized_repeated_reply_prefix,
92  -((self::$f['strlen'])(self::EXPECTED_REPLY_PREFIX_END))
93  ) !== self::EXPECTED_REPLY_PREFIX_END) {
94  $optimized_repeated_reply_prefix .= self::EXPECTED_REPLY_PREFIX_END;
95  }
96 
97  $optimized_repeated_reply_prefix_start = substr_replace(
98  $reply_prefix,
99  self::EXPECTED_NUMBER_WRAPPER_CHAR_START,
100  (self::$f['strrpos'])($reply_prefix, self::EXPECTED_REPLY_PREFIX_END),
101  (self::$f['strlen'])(self::EXPECTED_REPLY_PREFIX_END)
102  );
103 
104  $optimized_repeated_reply_prefix_begin_pattern = preg_quote(
105  (self::$f['substr'])(
106  $optimized_repeated_reply_prefix_start,
107  0,
108  (self::$f['strrpos'])(
109  $optimized_repeated_reply_prefix_start,
110  self::EXPECTED_NUMBER_WRAPPER_CHAR_START
111  )
112  ),
113  '/'
114  );
115 
116  $optimized_repeated_reply_prefix_regex = implode('', [
117  '/^',
118  $optimized_repeated_reply_prefix_begin_pattern,
119  '\s*?' . self::EXPECTED_NUMBER_WRAPPER_CHAR_START_PATTERN . '\s*?\d+\s*?' . self::EXPECTED_NUMBER_WRAPPER_CHAR_END_PATTERN,
120  '/'
121  ]);
122 
123  if (preg_match($optimized_repeated_reply_prefix_regex, $subject_of_parent_posting)) {
124  // i.e. $subj_of_parent_posting = "Re(12):" or "Re (12):"
126  $subject_of_parent_posting
127  );
128  } else {
129  // i.e. $subj_of_parent_posting = "Re: Re: Re: ..."
130  $subject_of_reply = $this->handleSubjectWithoutReplyPrefixOrRepeatedReplyPrefix(
131  $subject_of_parent_posting,
132  $reply_prefix,
133  $optimized_repeated_reply_prefix
134  );
135  }
136 
137  return $subject_of_reply;
138  }
139 
141  string $subject_of_parent_posting,
142  string $effective_reply_prefix,
143  string $effective_optimized_repeated_reply_prefix
144  ): string {
145  $subject_of_reply = $subject_of_parent_posting;
146 
147  $reply_prefix_start = (self::$f['substr'])(
148  $effective_reply_prefix,
149  0,
150  -(self::$f['strlen'])(self::EXPECTED_REPLY_PREFIX_END)
151  );
152 
153  $repeated_reply_prefix_regex = implode('', [
154  '/^',
155  '(' . preg_quote($reply_prefix_start, '/') . '\s*' . self::EXPECTED_REPLY_PREFIX_END . '\s*)+',
156  '/'
157  ]);
158 
159  $matches = null;
160  preg_match($repeated_reply_prefix_regex, $subject_of_parent_posting, $matches);
161  $number_of_repetitions = isset($matches[0]) ?
162  preg_match_all(
163  '/' . preg_quote($reply_prefix_start, '/') . '\s*' . self::EXPECTED_REPLY_PREFIX_END . '\s*/',
164  $matches[0]
165  ) : 0;
166 
167  if ($number_of_repetitions >= 1) {
168  // i.e. $final_subject = "Re: Re: Re: ... " -> "Re(4):"
169  $number_of_repetitions++;
170  $subject_of_reply = sprintf(
171  $effective_optimized_repeated_reply_prefix,
172  $number_of_repetitions
173  ) . ' ' . trim(str_replace($matches[0], '', $subject_of_parent_posting));
174  } elseif ($number_of_repetitions === 0) {
175  // the first reply to a thread
176  $subject_of_reply = $effective_reply_prefix . ' ' . $subject_of_parent_posting;
177  }
178 
179  return $subject_of_reply;
180  }
181 
182  private function handleSubjectStartsWithOptimizedRepetitionReplyPattern(string $subject_of_parent_posting): string
183  {
184  $subject_of_reply = $subject_of_parent_posting;
185 
186  $wrapper_start_pos = (self::$f['strpos'])($subject_of_parent_posting, self::EXPECTED_NUMBER_WRAPPER_CHAR_START);
187  $wrapper_end_pos = (self::$f['strpos'])($subject_of_parent_posting, self::EXPECTED_NUMBER_WRAPPER_CHAR_END);
188 
189  if ($wrapper_start_pos === false || $wrapper_end_pos === false || $wrapper_end_pos < $wrapper_start_pos) {
190  return $subject_of_reply;
191  }
192 
193  $length = $wrapper_end_pos - $wrapper_start_pos;
194  $wrapper_start_pos++;
195 
196  $txt_num_replies = (self::$f['substr'])($subject_of_parent_posting, $wrapper_start_pos, $length - 1);
197  if (is_numeric($txt_num_replies) && $txt_num_replies > 0) {
198  $number_of_replies = ((int) trim($txt_num_replies)) + 1;
199  $subject_of_reply = (self::$f['substr'])(
200  $subject_of_parent_posting,
201  0,
202  $wrapper_start_pos
203  ) . $number_of_replies . (self::$f['substr'])(
204  $subject_of_parent_posting,
205  $wrapper_end_pos
206  );
207  }
208 
209  return $subject_of_reply;
210  }
211 }
handleSubjectWithoutReplyPrefixOrRepeatedReplyPrefix(string $subject_of_parent_posting, string $effective_reply_prefix, string $effective_optimized_repeated_reply_prefix)
handleSubjectStartsWithOptimizedRepetitionReplyPattern(string $subject_of_parent_posting)
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
__construct(string $reply_prefix, string $optimized_repeated_reply_prefix)