Total Complexity | 63 |
Total Lines | 380 |
Duplicated Lines | 0 % |
Changes | 4 | ||
Bugs | 0 | Features | 0 |
Complex classes like FunctionsPrintFacts often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use FunctionsPrintFacts, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
49 | class FunctionsPrintFacts |
||
50 | { |
||
51 | /** |
||
52 | * print a source linked to a fact (2 SOUR) |
||
53 | * this function is called by the FunctionsPrintFacts::print_fact function and other functions to |
||
54 | * print any source information attached to the fact |
||
55 | * |
||
56 | * @param Tree $tree |
||
57 | * @param string $factrec The fact record to look for sources in |
||
58 | * @param int $level The level to look for sources at |
||
59 | * |
||
60 | * @return string HTML text |
||
61 | */ |
||
62 | public static function printFactSources(Tree $tree, string $factrec, int $level): string |
||
139 | } |
||
140 | |||
141 | /** |
||
142 | * Print the links to media objects |
||
143 | * |
||
144 | * @param Tree $tree |
||
145 | * @param string $factrec |
||
146 | * @param int $level |
||
147 | * |
||
148 | * @return void |
||
149 | */ |
||
150 | public static function printMediaLinks(Tree $tree, string $factrec, int $level): void |
||
151 | { |
||
152 | $nlevel = $level + 1; |
||
|
|||
153 | if (preg_match_all("/$level OBJE @(.*)@/", $factrec, $omatch, PREG_SET_ORDER) === 0) { |
||
154 | return; |
||
155 | } |
||
156 | $objectNum = 0; |
||
157 | while ($objectNum < count($omatch)) { |
||
158 | $media_id = $omatch[$objectNum][1]; |
||
159 | $media = Registry::mediaFactory()->make($media_id, $tree); |
||
160 | if ($media) { |
||
161 | if ($media->canShow()) { |
||
162 | echo '<div class="d-flex align-items-center"><div class="p-1">'; |
||
163 | foreach ($media->mediaFiles() as $media_file) { |
||
164 | echo $media_file->displayImage(100, 100, 'contain', []); |
||
165 | } |
||
166 | echo '</div>'; |
||
167 | echo '<div>'; |
||
168 | echo '<a href="', e($media->url()), '">', $media->fullName(), '</a>'; |
||
169 | echo '<p>'; |
||
170 | |||
171 | foreach ($media->facts(['SOUR']) as $fact) { |
||
172 | echo view('fact-gedcom-fields', ['gedcom' => $fact->gedcom(), 'hierarchy' => [$media->tag()], 'tree' => $tree]); |
||
173 | } |
||
174 | |||
175 | foreach ($media->facts(['NOTE']) as $fact) { |
||
176 | echo view('fact-gedcom-fields', ['gedcom' => $fact->gedcom(), 'hierarchy' => [$media->tag()], 'tree' => $tree]); |
||
177 | } |
||
178 | |||
179 | echo '</div>'; //close div "media-display-title" |
||
180 | echo '</div>'; //close div "media-display" |
||
181 | } |
||
182 | } elseif ($tree->getPreference('HIDE_GEDCOM_ERRORS') === '1') { |
||
183 | echo '<p class="alert alert-danger">', $media_id, '</p>'; |
||
184 | } |
||
185 | $objectNum++; |
||
186 | } |
||
187 | } |
||
188 | |||
189 | /** |
||
190 | * Print a row for the sources tab on the individual page. |
||
191 | * |
||
192 | * @param Fact $fact |
||
193 | * @param int $level |
||
194 | * |
||
195 | * @return void |
||
196 | */ |
||
197 | public static function printMainSources(Fact $fact, int $level): void |
||
198 | { |
||
199 | $factrec = $fact->gedcom(); |
||
200 | $tree = $fact->record()->tree(); |
||
201 | |||
202 | $nlevel = $level + 1; |
||
203 | if ($fact->isPendingAddition()) { |
||
204 | $styleadd = 'wt-new'; |
||
205 | $can_edit = $level === 1 && $fact->canEdit(); |
||
206 | } elseif ($fact->isPendingDeletion()) { |
||
207 | $styleadd = 'wt-old'; |
||
208 | $can_edit = false; |
||
209 | } else { |
||
210 | $styleadd = ''; |
||
211 | $can_edit = $level === 1 && $fact->canEdit(); |
||
212 | } |
||
213 | |||
214 | // -- find source for each fact |
||
215 | preg_match_all('/(?:^|\n)(' . $level . ' SOUR (.*)(?:\n[' . $nlevel . '-9] .*)*)/', $fact->gedcom(), $matches, PREG_SET_ORDER); |
||
216 | |||
217 | foreach ($matches as $match) { |
||
218 | $srec = $match[1]; |
||
219 | $sid = $match[2]; |
||
220 | $source = Registry::sourceFactory()->make(trim($sid, '@'), $tree); |
||
221 | // Allow access to "1 SOUR @non_existent_source@", so it can be corrected/deleted |
||
222 | if (!$source || $source->canShow()) { |
||
223 | if ($level > 1) { |
||
224 | echo '<tr class="wt-level-two-source collapse">'; |
||
225 | } else { |
||
226 | echo '<tr>'; |
||
227 | } |
||
228 | echo '<th class="'; |
||
229 | if ($level > 1) { |
||
230 | echo 'rela '; |
||
231 | } |
||
232 | echo $styleadd, '">'; |
||
233 | echo $fact->label(); |
||
234 | if ($can_edit) { |
||
235 | echo view('fact-edit-links', ['fact' => $fact, 'url' => null]); |
||
236 | } |
||
237 | echo '</th>'; |
||
238 | echo '<td class="', $styleadd, '">'; |
||
239 | if ($source) { |
||
240 | echo '<a href="', e($source->url()), '">', $source->fullName(), '</a>'; |
||
241 | // 2 RESN tags. Note, there can be more than one, such as "privacy" and "locked" |
||
242 | if (preg_match_all("/\n2 RESN (.+)/", $factrec, $rmatches)) { |
||
243 | $label = Registry::elementFactory()->make($fact->tag() . ':RESN')->label(); |
||
244 | foreach ($rmatches[1] as $rmatch) { |
||
245 | echo '<br><span class="label">', $label, ':</span> <span class="field">'; |
||
246 | switch ($rmatch) { |
||
247 | case 'none': |
||
248 | // Note: "2 RESN none" is not valid gedcom, and the GUI will not let you add it. |
||
249 | // However, webtrees privacy rules will interpret it as "show an otherwise private fact to public". |
||
250 | echo '<i class="icon-resn-none"></i> ', I18N::translate('Show to visitors'); |
||
251 | break; |
||
252 | case 'privacy': |
||
253 | echo '<i class="icon-resn-privacy"></i> ', I18N::translate('Show to members'); |
||
254 | break; |
||
255 | case 'confidential': |
||
256 | echo '<i class="icon-resn-confidential"></i> ', I18N::translate('Show to managers'); |
||
257 | break; |
||
258 | case 'locked': |
||
259 | echo '<i class="icon-resn-locked"></i> ', I18N::translate('Only managers can edit'); |
||
260 | break; |
||
261 | default: |
||
262 | echo $rmatch; |
||
263 | break; |
||
264 | } |
||
265 | echo '</span>'; |
||
266 | } |
||
267 | } |
||
268 | echo self::printSourceStructure($tree, self::getSourceStructure($srec)); |
||
269 | echo '<div class="indent">'; |
||
270 | self::printMediaLinks($tree, $srec, $nlevel); |
||
271 | if ($nlevel === 2) { |
||
272 | self::printMediaLinks($tree, $source->gedcom(), 1); |
||
273 | } |
||
274 | echo FunctionsPrint::printFactNotes($tree, $srec, $nlevel); |
||
275 | echo '</div>'; |
||
276 | } else { |
||
277 | echo $sid; |
||
278 | } |
||
279 | echo '</td></tr>'; |
||
280 | } |
||
281 | } |
||
282 | } |
||
283 | |||
284 | /** |
||
285 | * Print SOUR structure |
||
286 | * This function prints the input array of SOUR sub-records built by the |
||
287 | * getSourceStructure() function. |
||
288 | * |
||
289 | * @param Tree $tree |
||
290 | * @param array<string|array<string>> $textSOUR |
||
291 | * |
||
292 | * @return string |
||
293 | */ |
||
294 | public static function printSourceStructure(Tree $tree, array $textSOUR): string |
||
295 | { |
||
296 | $html = ''; |
||
297 | |||
298 | if ($textSOUR['PAGE'] !== '') { |
||
299 | $html .= Registry::elementFactory()->make('INDI:SOUR:PAGE')->labelValue($textSOUR['PAGE'], $tree); |
||
300 | } |
||
301 | |||
302 | if ($textSOUR['EVEN'] !== '') { |
||
303 | $html .= Registry::elementFactory()->make('INDI:SOUR:EVEN')->labelValue($textSOUR['EVEN'], $tree); |
||
304 | |||
305 | if ($textSOUR['ROLE']) { |
||
306 | $html .= Registry::elementFactory()->make('INDI:SOUR:EVEN:ROLE')->labelValue($textSOUR['ROLE'], $tree); |
||
307 | } |
||
308 | } |
||
309 | |||
310 | if ($textSOUR['DATE'] !== '') { |
||
311 | $html .= Registry::elementFactory()->make('INDI:SOUR:DATA:DATE')->labelValue($textSOUR['DATE'], $tree); |
||
312 | } |
||
313 | |||
314 | foreach ($textSOUR['TEXT'] as $text) { |
||
315 | $html .= Registry::elementFactory()->make('INDI:SOUR:DATA:TEXT')->labelValue($text, $tree); |
||
316 | } |
||
317 | |||
318 | if ($textSOUR['QUAY'] !== '') { |
||
319 | $html .= Registry::elementFactory()->make('INDI:SOUR:QUAY')->labelValue($textSOUR['QUAY'], $tree); |
||
320 | } |
||
321 | |||
322 | return '<div class="indent">' . $html . '</div>'; |
||
323 | } |
||
324 | |||
325 | /** |
||
326 | * Extract SOUR structure from the incoming Source sub-record |
||
327 | * The output array is defined as follows: |
||
328 | * $textSOUR['PAGE'] = Source citation |
||
329 | * $textSOUR['EVEN'] = Event type |
||
330 | * $textSOUR['ROLE'] = Role in event |
||
331 | * $textSOUR['DATA'] = place holder (no text in this sub-record) |
||
332 | * $textSOUR['DATE'] = Entry recording date |
||
333 | * $textSOUR['TEXT'] = (array) Text from source |
||
334 | * $textSOUR['QUAY'] = Certainty assessment |
||
335 | * |
||
336 | * @param string $srec |
||
337 | * |
||
338 | * @return array<array<string>> |
||
339 | */ |
||
340 | public static function getSourceStructure(string $srec): array |
||
341 | { |
||
342 | // Set up the output array |
||
343 | $textSOUR = [ |
||
344 | 'PAGE' => '', |
||
345 | 'EVEN' => '', |
||
346 | 'ROLE' => '', |
||
347 | 'DATE' => '', |
||
348 | 'TEXT' => [], |
||
349 | 'QUAY' => '', |
||
350 | ]; |
||
351 | |||
352 | preg_match_all('/^\d (PAGE|EVEN|ROLE|DATE|TEXT|QUAY) ?(.*(\n\d CONT.*)*)$/m', $srec, $matches, PREG_SET_ORDER); |
||
353 | |||
354 | foreach ($matches as $match) { |
||
355 | $tag = $match[1]; |
||
356 | $value = $match[2]; |
||
357 | $value = preg_replace('/\n\d CONT ?/', "\n", $value); |
||
358 | |||
359 | if ($tag === 'TEXT') { |
||
360 | $textSOUR[$tag][] = $value; |
||
361 | } else { |
||
362 | $textSOUR[$tag] = $value; |
||
363 | } |
||
364 | } |
||
365 | |||
366 | return $textSOUR; |
||
367 | } |
||
368 | |||
369 | /** |
||
370 | * Print a row for the media tab on the individual page. |
||
371 | * |
||
372 | * @param Fact $fact |
||
373 | * @param int $level |
||
374 | * |
||
375 | * @return void |
||
376 | */ |
||
377 | public static function printMainMedia(Fact $fact, int $level): void |
||
429 | } |
||
430 | } |
||
431 | } |
||
432 | } |
||
433 |