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