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