]> git.agnieray.net Git - galette.git/blob - galette/lib/Galette/Features/Replacements.php
bb4aa0ed98e81c31c8d797271adc386765f073ca
[galette.git] / galette / lib / Galette / Features / Replacements.php
1 <?php
2
3 /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
4
5 /**
6 * Replacements feature
7 *
8 * PHP version 5
9 *
10 * Copyright © 2020-2021 The Galette Team
11 *
12 * This file is part of Galette (http://galette.tuxfamily.org).
13 *
14 * Galette is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation, either version 3 of the License, or
17 * (at your option) any later version.
18 *
19 * Galette is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with Galette. If not, see <http://www.gnu.org/licenses/>.
26 *
27 * @category Entity
28 * @package Galette
29 *
30 * @author Johan Cwiklinski <johan@x-tnd.be>
31 * @copyright 2020-2021 The Galette Team
32 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
33 * @link http://galette.eu
34 * @since 2020-12-20
35 */
36
37 namespace Galette\Features;
38
39 use Galette\Core\Db;
40 use Galette\Core\Login;
41 use Galette\Core\Logo;
42 use Galette\Core\Preferences;
43 use Galette\Entity\Adherent;
44 use Galette\Entity\Contribution;
45 use Galette\Entity\PdfModel;
46 use Galette\Repository\DynamicFieldsSet;
47 use Galette\DynamicFields\DynamicField;
48 use Analog\Analog;
49 use NumberFormatter;
50 use Slim\Router;
51
52 /**
53 * Replacements feature
54 *
55 * @category Features
56 * @name Replacements
57 * @package Galette
58 * @author Johan Cwiklinski <johan@x-tnd.be>
59 * @copyright 2020-2021 The Galette Team
60 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
61 * @link http://galette.eu
62 * @since 2020-12-20
63 */
64
65 trait Replacements
66 {
67 public static $RENDER_TXT = 0;
68 public static $RENDER_HTML = 1;
69 private $patterns = [];
70 private $replaces = [];
71 private $dynamic_patterns = [];
72
73 /**
74 * @Inject("db")
75 * @var Db
76 */
77 protected $zdb;
78
79 /**
80 * @Inject("login")
81 * @var Login
82 */
83 protected $login;
84
85 /**
86 * @Inject("preferences")
87 * @var Preferences
88 */
89 protected $preferences;
90
91 /**
92 * @Inject
93 * @var Router
94 */
95 protected $router;
96
97 /**
98 * Get dynamic patterns
99 *
100 * @param string $form_name Dynamic form name
101 *
102 * @return array
103 */
104 public function getDynamicPatterns(string $form_name): array
105 {
106 if (isset($this->dynamic_patterns[$form_name])) {
107 return $this->dynamic_patterns[$form_name];
108 }
109
110 $fields = new DynamicFieldsSet($this->zdb, $this->login);
111 $dynamic_fields = $fields->getList($form_name);
112
113 $dynamic_patterns = [];
114 foreach ($dynamic_fields as $dynamic_field) {
115 $key = strtoupper('_DYNFIELD_' . $dynamic_field->getId() . '_' . $form_name);
116 foreach (['LABEL', 'INPUT'] as $capability) {
117 $dynamic_patterns[strtolower($capability . $key)] = [
118 'title' => sprintf(
119 ($capability == 'LABEL' ? _T('Label for dynamic field "%s"')
120 : _T('Input for dynamic field "%s"')),
121 $dynamic_field->getName()
122 ),
123 'pattern' => sprintf(
124 '/{%s%s}/',
125 $capability,
126 $key
127 )
128 ];
129 }
130 }
131
132 $this->dynamic_patterns[$form_name] = $dynamic_patterns;
133 return $this->dynamic_patterns[$form_name];
134 }
135
136 /**
137 * Set patterns
138 *
139 * @param array $patterns Patterns to add
140 *
141 * @return $this
142 */
143 protected function setPatterns(array $patterns): self
144 {
145 $toset = [];
146 foreach ($patterns as $key => $info) {
147 if (is_array($info)) {
148 $toset[$key] = $info['pattern'];
149 } else {
150 $toset[$key] = $info;
151 }
152 }
153
154 $this->patterns = array_merge(
155 $this->patterns,
156 $toset
157 );
158
159 return $this;
160 }
161
162 /**
163 * Set replacements
164 *
165 * @param array $replaces Replacements to add
166 *
167 * @return void
168 */
169 public function setReplacements(array $replaces): void
170 {
171 $this->replaces = array_merge(
172 $this->replaces,
173 $replaces
174 );
175 }
176
177 /**
178 * Get main patterns
179 *
180 * @return array
181 */
182 protected function getMainPatterns(): array
183 {
184 return [
185 'asso_name' => [
186 'title' => _T('Your organisation name'),
187 'pattern' => '/{ASSO_NAME}/'
188 ],
189 'asso_slogan' => [
190 'title' => _T('Your organisation slogan'),
191 'pattern' => '/{ASSO_SLOGAN}/'
192 ],
193 'asso_address' => [
194 'title' => _T('Your organisation address'),
195 'pattern' => '/{ASSO_ADDRESS}/',
196 ],
197 'asso_address_multi' => [
198 'title' => sprintf('%s (%s)', _T('Your organisation address'), _T('with break lines')),
199 'pattern' => '/{ASSO_ADDRESS_MULTI}/',
200 ],
201 'asso_website' => [
202 'title' => _T('Your organisation website'),
203 'pattern' => '/{ASSO_WEBSITE}/',
204 ],
205 'asso_logo' => [
206 'title' => _T('Your organisation logo'),
207 'pattern' => '/{ASSO_LOGO}/',
208 ],
209 'date_now' => [
210 'title' => _T('Current date (Y-m-d)'),
211 'pattern' => '/{DATE_NOW}/'
212 ],
213 'login_uri' => [
214 'title' => _T("Galette's login URI"),
215 'pattern' => '/{LOGIN_URI}/'
216 ]
217 ];
218 }
219
220 /**
221 * Get patterns for a member
222 *
223 * @param boolean $legacy Whether to load legacy patterns
224 *
225 * @return array
226 */
227 protected function getMemberPatterns(bool $legacy = true): array
228 {
229 $dynamic_patterns = $this->getDynamicPatterns('adh');
230 $m_patterns = [
231 'adh_title' => [
232 'title' => _('Title'),
233 'pattern' => '/{TITLE_ADH}/',
234 ],
235 'adh_id' => [
236 'title' => _T("Member's ID"),
237 'pattern' => '/{ID_ADH}/',
238 ],
239 'adh_name' => [
240 'title' => _T("Name"),
241 'pattern' => '/{NAME_ADH}/',
242 ],
243 'adh_last_name' => [
244 'title' => _T('Last name'),
245 'pattern' => '/{LAST_NAME_ADH}/',
246 ],
247 'adh_first_name' => [
248 'title' => _T('First name'),
249 'pattern' => '/{FIRST_NAME_ADH}/',
250 ],
251 'adh_nickname' => [
252 'title' => _T('Nickname'),
253 'pattern' => '/{NICKNAME_ADH}/',
254 ],
255 'adh_gender' => [
256 'title' => _T('Gender'),
257 'pattern' => '/{GENDER_ADH}/',
258 ],
259 'adh_birth_date' => [
260 'title' => _T('Birth date'),
261 'pattern' => '/{ADH_BIRTH_DATE}/',
262 ],
263 'adh_birth_place' => [
264 'title' => _T('Birth place'),
265 'pattern' => '/{ADH_BIRTH_PLACE}/',
266 ],
267 'adh_profession' => [
268 'title' => _T('Profession'),
269 'pattern' => '/{PROFESSION_ADH}/',
270 ],
271 'adh_company' => [
272 'title' => _T("Company name"),
273 'pattern' => '/{COMPANY_ADH}/',
274 ],
275 'adh_address' => [
276 'title' => _T("Address"),
277 'pattern' => '/{ADDRESS_ADH}/',
278 ],
279 'adh_zip' => [
280 'title' => _T("Zipcode"),
281 'pattern' => '/{ZIP_ADH}/',
282 ],
283 'adh_town' => [
284 'title' => _T("Town"),
285 'pattern' => '/{TOWN_ADH}/',
286 ],
287 'adh_country' => [
288 'title' => _T('Country'),
289 'pattern' => '/{COUNTRY_ADH}/',
290 ],
291 'adh_phone' => [
292 'title' => _T('Phone'),
293 'pattern' => '/{PHONE_ADH}/',
294 ],
295 'adh_mobile' => [
296 'title' => _T('GSM'),
297 'pattern' => '/{MOBILE_ADH}/',
298 ],
299 'adh_email' => [
300 'title' => _T('Email'),
301 'pattern' => '/{EMAIL_ADH}/',
302 ],
303 'adh_login' => [
304 'title' => _T('Login'),
305 'pattern' => '/{LOGIN_ADH}/',
306 ],
307 'adh_main_group' => [
308 'title' => _T("Member's main group"),
309 'pattern' => '/{GROUP_ADH}/',
310 ],
311 'adh_groups' => [
312 'title' => _T("Member's groups (as list)"),
313 'pattern' => '/{GROUPS_ADH}/'
314 ],
315 'adh_dues' => [
316 'title' => _T('Member state of dues'),
317 'pattern' => '/{ADH_DUES}/'
318 ],
319 'days_remaining' => [
320 'title' => _T('Membership remaining days'),
321 'pattern' => '/{DAYS_REMAINING}/',
322 ],
323 'days_expired' => [
324 'title' => _T('Membership expired since'),
325 'pattern' => '/{DAYS_EXPIRED}/',
326 ]
327 ];
328
329 if ($legacy === true) {
330 $m_patterns += [
331 '_adh_company' => [
332 'title' => _T("Company name"),
333 'pattern' => '/{COMPANY_NAME_ADH}/',
334 ],
335 '_adh_last_name' => [
336 'title' => _T('Last name'),
337 'pattern' => '/{LASTNAME_ADH}/',
338 ],
339 '_adh_first_name' => [
340 'title' => _T('First name'),
341 'pattern' => '/{FIRSTNAME_ADH}/',
342 ],
343 '_adh_login' => [
344 'title' => _T('Login'),
345 'pattern' => '/{LOGIN}/',
346 ],
347 '_adh_email' => [
348 'title' => _T('Email'),
349 'pattern' => '/{MAIL_ADH}/',
350 ],
351 ];
352 }
353
354 return $m_patterns + $dynamic_patterns;
355 }
356
357 /**
358 * Get patterns for a contribution
359 *
360 * @param boolean $legacy Whether to load legacy patterns
361 *
362 * @return array
363 */
364 protected function getContributionPatterns($legacy = true): array
365 {
366 $dynamic_patterns = $this->getDynamicPatterns('contrib');
367
368 $c_patterns = [
369 'contrib_label' => [
370 'title' => _T('Contribution label'),
371 'pattern' => '/{CONTRIB_LABEL}/',
372 ],
373 'contrib_amount' => [
374 'title' => _T('Amount'),
375 'pattern' => '/{CONTRIB_AMOUNT}/',
376 ],
377 'contrib_amount_letters' => [
378 'title' => _T('Amount (in letters)'),
379 'pattern' => '/{CONTRIB_AMOUNT_LETTERS}/',
380 ],
381 'contrib_date' => [
382 'title' => _T('Full date'),
383 'pattern' => '/{CONTRIB_DATE}/',
384 ],
385 'contrib_year' => [
386 'title' => _T('Contribution year'),
387 'pattern' => '/{CONTRIB_YEAR}/',
388 ],
389 'contrib_comment' => [
390 'title' => _T('Comment'),
391 'pattern' => '/{CONTRIB_COMMENT}/',
392 ],
393 'contrib_bdate' => [
394 'title' => _T('Begin date'),
395 'pattern' => '/{CONTRIB_BEGIN_DATE}/',
396 ],
397 'contrib_edate' => [
398 'title' => _T('End date'),
399 'pattern' => '/{CONTRIB_END_DATE}/',
400 ],
401 'contrib_id' => [
402 'title' => _T('Contribution id'),
403 'pattern' => '/{CONTRIB_ID}/',
404 ],
405 'contrib_payment' => [
406 'title' => _T('Payment type'),
407 'pattern' => '/{CONTRIB_PAYMENT_TYPE}/'
408 ],
409 'contrib_info' => [
410 'title' => _T('Contribution information'),
411 'pattern' => '/{CONTRIB_INFO}/'
412 ]
413 ];
414
415 if ($legacy === true) {
416 foreach ($c_patterns as $key => $pattern) {
417 $nkey = '_' . $key;
418 $pattern['pattern'] = str_replace(
419 'CONTRIB_',
420 'CONTRIBUTION_',
421 $pattern['pattern']
422 );
423 $c_patterns[$nkey] = $pattern;
424 }
425
426 $c_patterns['__contrib_label'] = [
427 'title' => $c_patterns['contrib_label'],
428 'pattern' => '/{CONTRIB_TYPE}/'
429 ];
430 }
431
432 //handle DEADLINE alias
433
434 return $c_patterns + $dynamic_patterns;
435 }
436
437 /**
438 * Set main replacements
439 *
440 * @return $this
441 */
442 public function setMain(): self
443 {
444 $address = $this->preferences->getPostalAddress();
445 $address_multi = preg_replace("/\n/", "<br>", $address);
446
447 $website = '';
448 if ($this->preferences->pref_website !== '') {
449 $website = '<a href="' . $this->preferences->pref_website . '">' .
450 $this->preferences->pref_website . '</a>';
451 }
452
453 $logo = new Logo();
454 $logo_elt = '<img' .
455 ' src="' . $this->preferences->getURL() . $this->router->pathFor('logo') . '"' .
456 ' width="' . $logo->getOptimalWidth() . '"' .
457 ' height="' . $logo->getOptimalHeight() . '"' .
458 '/>';
459
460 $this->setReplacements(
461 array(
462 'asso_name' => $this->preferences->pref_nom,
463 'asso_slogan' => $this->preferences->pref_slogan,
464 'asso_address' => $address,
465 'asso_address_multi' => $address_multi,
466 'asso_website' => $website,
467 'asso_logo' => $logo_elt,
468 'date_now' => date(_T('Y-m-d')),
469 'login_uri' => $this->preferences->getURL() . $this->router->pathFor('login'),
470 )
471 );
472
473 return $this;
474 }
475
476 /**
477 * Set contribution and proceed related replacements
478 *
479 * @return $this
480 */
481 public function setNoContribution(): self
482 {
483 global $login;
484
485 $c_replacements = [
486 'contrib_label' => null,
487 'contrib_amount' => null,
488 'contrib_amount_letters' => null,
489 'contrib_date' => null,
490 'contrib_year' => null,
491 'contrib_comment' => null,
492 'contrib_bdate' => null,
493 'contrib_edate' => null,
494 'contrib_id' => null,
495 'contrib_payment' => null,
496 'contrib_info' => null
497 ];
498
499 foreach ($c_replacements as $key => $replacement) {
500 $nkey = '_' . $key;
501 $c_replacements[$nkey] = $replacement;
502 }
503 $c_replacements['__contrib_label'] = $c_replacements['contrib_label'];
504
505 //handle DEADLINE alias
506
507 $this->setReplacements($c_replacements);
508
509 /** the list of all dynamic fields */
510 $fields = new DynamicFieldsSet($this->zdb, $login);
511 $dynamic_fields = $fields->getList('contrib');
512 $this->setDynamicFields('contrib', $dynamic_fields, null);
513
514 return $this;
515 }
516
517 /**
518 * Set contribution and proceed related replacements
519 *
520 * @param Contribution $contrib Contribution
521 *
522 * @return PdfModel
523 */
524 public function setContribution(Contribution $contrib): self
525 {
526 global $login, $i18n;
527
528 $formatter = new NumberFormatter($i18n->getID(), NumberFormatter::SPELLOUT);
529
530 $c_replacements = [
531 'contrib_label' => $contrib->type->libelle,
532 'contrib_amount' => $contrib->amount,
533 'contrib_amount_letters' => $formatter->format($contrib->amount),
534 'contrib_date' => $contrib->date,
535 'contrib_year' => $contrib->raw_date->format('Y'),
536 'contrib_comment' => $contrib->info,
537 'contrib_bdate' => $contrib->begin_date,
538 'contrib_edate' => $contrib->end_date,
539 'contrib_id' => $contrib->id,
540 'contrib_payment' => $contrib->spayment_type,
541 'contrib_info' => $contrib->info
542 ];
543
544 foreach ($c_replacements as $key => $replacement) {
545 $nkey = '_' . $key;
546 $c_replacements[$nkey] = $replacement;
547 }
548 $c_replacements['__contrib_label'] = $c_replacements['contrib_label'];
549
550 //handle DEADLINE alias
551
552 $this->setReplacements($c_replacements);
553
554 /** the list of all dynamic fields */
555 $fields = new DynamicFieldsSet($this->zdb, $login);
556 $dynamic_fields = $fields->getList('contrib');
557 $this->setDynamicFields('contrib', $dynamic_fields, $contrib);
558
559 return $this;
560 }
561
562 /**
563 * Set member and proceed related replacements
564 *
565 * @param Adherent $member Member
566 *
567 * @return PdfModel
568 */
569 public function setMember(Adherent $member): self
570 {
571 global $login;
572
573 $address = $member->address;
574 if ($member->address_continuation !== '') {
575 $address .= '<br/>' . $member->address_continuation;
576 }
577
578 if ($member->isMan()) {
579 $gender = _T("Man");
580 } elseif ($member->isWoman()) {
581 $gender = _T("Woman");
582 } else {
583 $gender = _T("Unspecified");
584 }
585
586 $member_groups = $member->groups;
587 $main_group = _T("None");
588 $group_list = _T("None");
589 if (is_array($member_groups) && count($member_groups) > 0) {
590 $main_group = $member_groups[0]->getName();
591 $group_list = '<ul>';
592 foreach ($member_groups as $group) {
593 $group_list .= '<li>' . $group->getName() . '</li>';
594 }
595 $group_list .= '</ul>';
596 }
597
598 $this->setReplacements(
599 array(
600 'adh_title' => $member->stitle,
601 'adh_id' => $member->id,
602 'adh_name' => $member->sfullname,
603 'adh_last_name' => $member->name,
604 'adh_first_name' => $member->surname,
605 'adh_nickname' => $member->nickname,
606 'adh_gender' => $gender,
607 'adh_birth_date' => $member->birthdate,
608 'adh_birth_place' => $member->birth_place,
609 'adh_profession' => $member->job,
610 'adh_company' => $member->company_name,
611 'adh_address' => $address,
612 'adh_zip' => $member->zipcode,
613 'adh_town' => $member->town,
614 'adh_country' => $member->country,
615 'adh_phone' => $member->phone,
616 'adh_mobile' => $member->gsm,
617 'adh_email' => $member->email,
618 'adh_login' => $member->login,
619 'adh_main_group' => $main_group,
620 'adh_groups' => $group_list,
621 'adh_dues' => $member->getDues(),
622 'days_remaining' => $member->days_remaining,
623 'days_expired' => ($member->days_remaining * -1),
624 //Handle COMPANY_NAME_ADH... https://bugs.galette.eu/issues/1530
625 '_adh_company' => $member->company_name,
626 //Handle old names for variables ... https://bugs.galette.eu/issues/1393
627 '_adh_last_name' => $member->name,
628 '_adh_first_name' => $member->surname,
629 '_adh_login' => $member->login,
630 '_adh_email' => $member->email
631 )
632 );
633
634 /** the list of all dynamic fields */
635 $fields = new DynamicFieldsSet($this->zdb, $login);
636 $dynamic_fields = $fields->getList('adh');
637 $this->setDynamicFields('adh', $dynamic_fields, $member);
638
639 return $this;
640 }
641
642 /**
643 * Set dynamic fields and proceed related replacements
644 *
645 * @param string $form_name Form name
646 * @param array $dynamic_fields Dynamic fields
647 * @param mixed $object Related object (Adherent, Contribution, ...)
648 *
649 * @return PdfModel
650 */
651 public function setDynamicFields(string $form_name, array $dynamic_fields, $object): self
652 {
653 $uform_name = strtoupper($form_name);
654 $render = ($this instanceof PdfModel && ($object->id == null) ? self::$RENDER_HTML : self::$RENDER_TXT);
655
656 $dynamic_patterns = $this->getDynamicPatterns($form_name);
657 foreach ($dynamic_patterns as $dynamic_pattern) {
658 $pattern = trim($dynamic_pattern['pattern'], '/');
659 $key = strtolower(rtrim(ltrim($pattern, '{'), '}'));
660 $value = '';
661 if (preg_match("/^{DYNFIELD_([0-9]+)_$uform_name}$/", $pattern, $match)) {
662 /** dynamic field first value */
663 $field_id = $match[1];
664 if ($object !== null) {
665 $values = $object->getDynamicFields()->getValues($field_id);
666 $value = $values[1];
667 } else {
668 $value = '';
669 }
670 }
671 if (preg_match("/^{LABEL_DYNFIELD_([0-9]+)_$uform_name}$/", $pattern, $match)) {
672 /** dynamic field label */
673 $field_id = $match[1];
674 $value = $dynamic_fields[$field_id]->getName();
675 }
676 if (preg_match("/^{INPUT_DYNFIELD_([0-9]+)_$uform_name}$/", $pattern, $match)) {
677 /** dynamic field input form element */
678 $field_id = $match[1];
679 $field_name = $dynamic_fields[$field_id]->getName();
680 $field_type = $dynamic_fields[$field_id]->getType();
681 if ($object !== null) {
682 $field_values = $object->getDynamicFields()->getValues($field_id);
683 $field_value = $field_values[0]['field_val'];
684 } else {
685 $field_value = '';
686 }
687
688 switch ($field_type) {
689 case DynamicField::TEXT:
690 if ($render == self::$RENDER_HTML) {
691 $value .= '<textarea' .
692 ' id="' . $field_name . '"' .
693 ' name="' . $field_name . '"' .
694 ' value="' . $field_value . '"' .
695 '/>';
696 } else {
697 $value .= $field_value;
698 }
699 break;
700 case DynamicField::LINE:
701 if ($render == self::$RENDER_HTML) {
702 $value .= '<input type="text"' .
703 ' id="' . $field_name . '"' .
704 ' name="' . $field_name . '"' .
705 ' value="' . $field_value . '"' .
706 ' size="20" maxlength="30"/>';
707 } else {
708 $value .= $field_value;
709 }
710 break;
711 case DynamicField::CHOICE:
712 $choice_values = $dynamic_fields[$field_id]->getValues();
713 foreach ($choice_values as $choice_idx => $choice_value) {
714 if ($render == self::$RENDER_HTML) {
715 $value .= '<input type="radio"' .
716 ' id="' . $field_name . '"' .
717 ' name="' . $field_name . '"' .
718 ' value="' . $choice_value . '"';
719 if ($choice_idx == $field_value) {
720 $value .= ' checked="checked"';
721 }
722 $value .= '/>';
723 $value .= $choice_value;
724 $value .= '&nbsp;';
725 } else {
726 $value .= $choice_value;
727 $value .= '&nbsp;';
728 }
729 }
730 break;
731 case DynamicField::DATE:
732 if ($render == self::$RENDER_HTML) {
733 $value .= '<input type="text" name="' .
734 $field_name . '" value="' .
735 $field_value .
736 '" size="10" />';
737 } else {
738 $value .= $field_value;
739 }
740 break;
741 case DynamicField::BOOLEAN:
742 if ($render == self::$RENDER_HTML) {
743 $value .= '<input type="checkbox"' .
744 ' name="' . $field_name . '"' .
745 ' value="1"';
746 if ($field_value == 1) {
747 $value .= ' checked="checked"';
748 }
749 $value .= '/>';
750 } else {
751 $value .= $field_value;
752 }
753 break;
754 case DynamicField::FILE:
755 if ($render == self::$RENDER_HTML) {
756 $value .= '<input type="text" name="' .
757 $field_name . '" value="' .
758 $field_value . '" />';
759 } else {
760 $value .= $field_value;
761 }
762 break;
763 }
764 }
765
766 $this->setReplacements(array($key => $value));
767 Analog::log("adding dynamic replacement $key => $value", Analog::DEBUG);
768 }
769
770 return $this;
771 }
772
773 /**
774 * Build legend array
775 *
776 * @return array
777 */
778 public function getLegend(): array
779 {
780 $legend = [];
781
782 $legend['main'] = [
783 'title' => _T('Main information'),
784 'patterns' => $this->getMainPatterns()
785 ];
786
787 $legend['member'] = [
788 'title' => _T('Member information'),
789 'patterns' => $this->getMemberPatterns(false)
790 ];
791
792 return $legend;
793 }
794
795 /**
796 * Get configured replacements
797 *
798 * @return array
799 */
800 public function getReplacements(): array
801 {
802 return $this->replaces;
803 }
804
805 /**
806 * Set Db dependency
807 *
808 * @param Db $db Db instance
809 *
810 * @return $this
811 */
812 public function setDb(Db $db): self
813 {
814 $this->zdb = $db;
815 return $this;
816 }
817
818 /**
819 * Set Login dependency
820 *
821 * @param Login $login Login instance
822 *
823 * @return $this
824 */
825 public function setLogin(Login $login): self
826 {
827 $this->login = $login;
828 return $this;
829 }
830
831 /**
832 * Set Preferences dependency
833 *
834 * @param Preferences $preferences Preferences instance
835 *
836 * @return $this
837 */
838 public function setPreferences(Preferences $preferences): self
839 {
840 $this->preferences = $preferences;
841 return $this;
842 }
843
844 /**
845 * Set Router dependency
846 *
847 * @param Router $router Router instance
848 *
849 * @return $this
850 */
851 public function setRouter(Router $router): self
852 {
853 $this->router = $router;
854 return $this;
855 }
856
857 /**
858 * Proceed replacement on given entry
859 *
860 * @param string $source Source string
861 *
862 * @return string
863 */
864 protected function proceedReplacements(string $source): string
865 {
866 $replaced = $source;
867
868 //handle translations
869 $callback = static function ($matches) {
870 return _T($matches[1]);
871 };
872 $replaced = preg_replace_callback(
873 '/_T\("([^\"]+)"\)/',
874 $callback,
875 $source
876 );
877
878 //order matters
879 ksort($this->patterns, SORT_NATURAL);
880 ksort($this->replaces, SORT_NATURAL);
881
882 if (array_keys($this->patterns) !== array_keys($this->replaces)) {
883 throw new \RuntimeException('Patterns and replacements does not match!');
884 }
885
886 //handle replacements
887 $replaced = preg_replace(
888 $this->patterns,
889 $this->replaces,
890 $replaced
891 );
892
893 //handle translations with replacements
894 $repl_callback = static function ($matches) {
895 return str_replace(
896 $matches[1],
897 $matches[2],
898 $matches[3]
899 );
900 };
901 $replaced = preg_replace_callback(
902 '/str_replace\(\'([^,]+)\', ?\'([^,]+)\', ?\'(.*)\'\)/',
903 $repl_callback,
904 $replaced
905 );
906
907 return $replaced;
908 }
909
910 /**
911 * Get patterns
912 *
913 * @return array
914 */
915 public function getPatterns(): array
916 {
917 return $this->patterns;
918 }
919 }