]> git.agnieray.net Git - galette.git/blobdiff - galette/lib/Galette/Features/Replacements.php
Add pre_footer in replacements; closes #1808
[galette.git] / galette / lib / Galette / Features / Replacements.php
index 8521aebcc9c09f31ea2e0cec3f5faaf80bb4a4c0..391f1907fe50253c8b44c7574b3ad99338dd2891 100644 (file)
@@ -7,7 +7,7 @@
  *
  * PHP version 5
  *
- * Copyright © 2020-2021 The Galette Team
+ * Copyright © 2020-2023 The Galette Team
  *
  * This file is part of Galette (http://galette.tuxfamily.org).
  *
  * You should have received a copy of the GNU General Public License
  * along with Galette. If not, see <http://www.gnu.org/licenses/>.
  *
- * @category  Entity
+ * @category  Features
  * @package   Galette
  *
  * @author    Johan Cwiklinski <johan@x-tnd.be>
- * @copyright 2020-2021 The Galette Team
+ * @copyright 2020-2023 The Galette Team
  * @license   http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
  * @link      http://galette.eu
  * @since     2020-12-20
@@ -40,14 +40,20 @@ use Galette\Core\Db;
 use Galette\Core\Login;
 use Galette\Core\Logo;
 use Galette\Core\Preferences;
+use Galette\DynamicFields\Choice;
+use Galette\DynamicFields\Separator;
 use Galette\Entity\Adherent;
 use Galette\Entity\Contribution;
 use Galette\Entity\PdfModel;
+use Galette\Entity\Reminder;
+use Galette\Entity\Texts;
 use Galette\Repository\DynamicFieldsSet;
 use Galette\DynamicFields\DynamicField;
 use Analog\Analog;
 use NumberFormatter;
-use Slim\Router;
+use PHPMailer\PHPMailer\PHPMailer;
+use Slim\Routing\RouteParser;
+use DI\Attribute\Inject;
 
 /**
  * Replacements feature
@@ -56,7 +62,7 @@ use Slim\Router;
  * @name      Replacements
  * @package   Galette
  * @author    Johan Cwiklinski <johan@x-tnd.be>
- * @copyright 2020-2021 The Galette Team
+ * @copyright 2020-2023 The Galette Team
  * @license   http://www.gnu.org/licenses/gpl-3.0.html GPL License 3.0 or (at your option) any later version
  * @link      http://galette.eu
  * @since     2020-12-20
@@ -67,62 +73,80 @@ trait Replacements
     private $patterns = [];
     private $replaces = [];
     private $dynamic_patterns = [];
+    private ?PHPMailer $mail = null;
 
     /**
-     * @Inject("db")
      * @var Db
      */
+    #[Inject("zdb")]
     protected $zdb;
 
     /**
-     * @Inject("login")
      * @var Login
      */
+    #[Inject("login")]
     protected $login;
 
     /**
-     * @Inject("preferences")
      * @var Preferences
      */
+    #[Inject("preferences")]
     protected $preferences;
 
     /**
-     * @Inject
-     * @var Router
+     * @var RouteParser
      */
-    protected $router;
+    protected $routeparser;
 
     /**
      * Get dynamic patterns
      *
-     * @param string $form_name Dynamic form name
+     * @param string  $form_name Dynamic form name
+     * @param boolean $legacy    Whether to load legacy patterns
      *
      * @return array
      */
-    public function getDynamicPatterns(string $form_name): array
+    public function getDynamicPatterns(string $form_name, bool $legacy = true): array
     {
-        if (isset($this->dynamic_patterns[$form_name])) {
-            return $this->dynamic_patterns[$form_name];
-        }
-
         $fields = new DynamicFieldsSet($this->zdb, $this->login);
         $dynamic_fields = $fields->getList($form_name);
 
         $dynamic_patterns = [];
         foreach ($dynamic_fields as $dynamic_field) {
-            $key = strtoupper('_DYNFIELD_' . $dynamic_field->getId() . '_' . $form_name);
-            foreach (['LABEL', 'INPUT'] as $capability) {
-                $dynamic_patterns[strtolower($capability . $key)] = [
+            //no pattern for separators
+            if ($dynamic_field instanceof  Separator) {
+                continue;
+            }
+            $key = strtoupper('DYNFIELD_' . $dynamic_field->getId() . '_' . $form_name);
+            $capabilities = [
+                'LABEL',
+                ''
+            ];
+            if (!($this instanceof Texts) && ($legacy === true || $dynamic_field instanceof Choice)) {
+                $capabilities[] = 'INPUT';
+            }
+            foreach ($capabilities as $capability) {
+                $skey = sprintf('%s_%s', $capability, $key);
+                switch ($capability) {
+                    case 'LABEL':
+                        $title = _T('Label for dynamic field "%s"');
+                        break;
+                    case 'INPUT':
+                        $title = _T('Form entry for dynamic field "%s"');
+                        break;
+                    case '':
+                    case 'VALUE':
+                    default:
+                        $skey = $key;
+                        $title = _T('Value for dynamic field "%s"');
+                        break;
+                }
+                $dynamic_patterns[strtolower($skey)] = [
                     'title' => sprintf(
-                        ($capability == 'LABEL' ? _T('Label for dynamic field "%s"')
-                        : _T('Input for dynamic field "%s"')),
+                        $title,
                         $dynamic_field->getName()
                     ),
-                    'pattern'   => sprintf(
-                        '/{%s%s}/',
-                        $capability,
-                        $key
-                    )
+                    'pattern'   => sprintf('/{%s}/', $skey)
                 ];
             }
         }
@@ -205,12 +229,17 @@ trait Replacements
                 'pattern'          => '/{ASSO_LOGO}/',
             ],
             'date_now'              => [
+                //TRANS: see https://www.php.net/manual/datetime.format.php
                 'title'     => _T('Current date (Y-m-d)'),
                 'pattern'   => '/{DATE_NOW}/'
             ],
             'login_uri'             => [
                 'title'     => _T("Galette's login URI"),
                 'pattern'   => '/{LOGIN_URI}/'
+            ],
+            'asso_footer' => [
+                'title'     => trim(trim(_T("Footer text:"), ':')),
+                'pattern'   => '/{ASSO_FOOTER}/'
             ]
         ];
     }
@@ -224,7 +253,7 @@ trait Replacements
      */
     protected function getMemberPatterns(bool $legacy = true): array
     {
-        $dynamic_patterns = $this->getDynamicPatterns('adh');
+        $dynamic_patterns = $this->getDynamicPatterns('adh', $legacy);
         $m_patterns = [
             'adh_title'         => [
                 'title'     => _('Title'),
@@ -234,6 +263,10 @@ trait Replacements
                 'title'     => _T("Member's ID"),
                 'pattern'   => '/{ID_ADH}/',
             ],
+            'adh_num'            =>  [
+                'title'     => _T("Member number"),
+                'pattern'   => '/{NUM_ADH}/',
+            ],
             'adh_name'          =>  [
                 'title'     => _T("Name"),
                 'pattern'    => '/{NAME_ADH}/',
@@ -274,6 +307,10 @@ trait Replacements
                 'title'     => _T("Address"),
                 'pattern'   => '/{ADDRESS_ADH}/',
             ],
+            'adh_address_multi'    => [
+                'title'     => sprintf('%s (%s)', _T('Address'), _T('with break lines')),
+                'pattern'   => '/{ADDRESS_ADH_MULTI}/',
+            ],
             'adh_zip'           =>  [
                 'title'     => _T("Zipcode"),
                 'pattern'   => '/{ZIP_ADH}/',
@@ -361,7 +398,7 @@ trait Replacements
      */
     protected function getContributionPatterns($legacy = true): array
     {
-        $dynamic_patterns = $this->getDynamicPatterns('contrib');
+        $dynamic_patterns = $this->getDynamicPatterns('contrib', $legacy);
 
         $c_patterns = [
             'contrib_label'     => [
@@ -422,16 +459,33 @@ trait Replacements
             }
 
             $c_patterns['__contrib_label'] = [
-                'title'     => $c_patterns['contrib_label'],
+                'title'     => $c_patterns['contrib_label']['title'],
                 'pattern'   => '/{CONTRIB_TYPE}/'
             ];
         }
 
         //handle DEADLINE alias
+        $c_patterns['deadline'] = [
+            'title'     => $c_patterns['contrib_edate']['title'],
+            'pattern'   => '/{DEADLINE}/'
+        ];
 
         return $c_patterns + $dynamic_patterns;
     }
 
+    /**
+     * Set mail instance
+     *
+     * @param PHPMailer $mail PHPMailer instance
+     *
+     * @return self
+     */
+    public function setMail(PHPMailer $mail): self
+    {
+        $this->mail = $mail;
+        return $this;
+    }
+
     /**
      * Set main replacements
      *
@@ -449,11 +503,17 @@ trait Replacements
         }
 
         $logo = new Logo();
-        $logo_elt = '<img' .
-            ' src="' . $this->preferences->getURL() . $this->router->pathFor('logo') . '"' .
-            ' width="' . $logo->getOptimalWidth() . '"' .
-            ' height="' . $logo->getOptimalHeight() . '"' .
-            '/>';
+        if ($this->mail !== null) {
+            $logo_content = $this->preferences->getURL() . $this->routeparser->urlFor('logo');
+        } else {
+            $logo_content = '@' . base64_encode(file_get_contents($logo->getPath()));
+        }
+        $logo_elt = sprintf(
+            '<img src="%1$s" width="%2$s" height="%3$s" alt="" />',
+            $logo_content,
+            $logo->getOptimalWidth(),
+            $logo->getOptimalHeight()
+        );
 
         $this->setReplacements(
             array(
@@ -463,8 +523,10 @@ trait Replacements
                 'asso_address_multi' => $address_multi,
                 'asso_website'       => $website,
                 'asso_logo'          => $logo_elt,
+                //TRANS: see https://www.php.net/manual/datetime.format.php
                 'date_now'           => date(_T('Y-m-d')),
-                'login_uri'          => $this->preferences->getURL() . $this->router->pathFor('login'),
+                'login_uri'          => $this->preferences->getURL() . $this->routeparser->urlFor('login'),
+                'asso_footer'        => $this->preferences->pref_footer
             )
         );
 
@@ -501,6 +563,7 @@ trait Replacements
         $c_replacements['__contrib_label'] = $c_replacements['contrib_label'];
 
         //handle DEADLINE alias
+        $c_replacements['deadline'] = null;
 
         $this->setReplacements($c_replacements);
 
@@ -517,7 +580,7 @@ trait Replacements
      *
      * @param Contribution $contrib Contribution
      *
-     * @return PdfModel
+     * @return self
      */
     public function setContribution(Contribution $contrib): self
     {
@@ -546,6 +609,7 @@ trait Replacements
         $c_replacements['__contrib_label'] = $c_replacements['contrib_label'];
 
         //handle DEADLINE alias
+        $c_replacements['deadline'] = $c_replacements['contrib_edate'];
 
         $this->setReplacements($c_replacements);
 
@@ -562,16 +626,14 @@ trait Replacements
      *
      * @param Adherent $member Member
      *
-     * @return PdfModel
+     * @return self
      */
     public function setMember(Adherent $member): self
     {
         global $login;
 
-        $address = $member->address;
-        if ($member->address_continuation !== '') {
-            $address .= '<br/>' . $member->address_continuation;
-        }
+        $address = $member->getAddress();
+        $address_multi = preg_replace("/\n/", "<br>", $address);
 
         if ($member->isMan()) {
             $gender = _T("Man");
@@ -597,6 +659,7 @@ trait Replacements
             array(
                 'adh_title'         => $member->stitle,
                 'adh_id'            => $member->id,
+                'adh_num'           => $member->number,
                 'adh_name'          => $member->sfullname,
                 'adh_last_name'     => $member->name,
                 'adh_first_name'    => $member->surname,
@@ -607,18 +670,20 @@ trait Replacements
                 'adh_profession'    => $member->job,
                 'adh_company'       => $member->company_name,
                 'adh_address'       => $address,
-                'adh_zip'           => $member->zipcode,
-                'adh_town'          => $member->town,
-                'adh_country'       => $member->country,
+                'adh_address_multi' => $address_multi,
+                'adh_zip'           => $member->getZipcode(),
+                'adh_town'          => $member->getTown(),
+                'adh_country'       => $member->getCountry(),
                 'adh_phone'         => $member->phone,
                 'adh_mobile'        => $member->gsm,
+                //always take current member email, to be sure.
                 'adh_email'         => $member->email,
                 'adh_login'         => $member->login,
                 'adh_main_group'    => $main_group,
                 'adh_groups'        => $group_list,
                 'adh_dues'          => $member->getDues(),
                 'days_remaining'    => $member->days_remaining,
-                'days_expired'      => ($member->days_remaining * -1),
+                'days_expired'      => (int)$member->days_remaining + 1,
                 //Handle COMPANY_NAME_ADH... https://bugs.galette.eu/issues/1530
                 '_adh_company'      => $member->company_name,
                 //Handle old names for variables ... https://bugs.galette.eu/issues/1393
@@ -644,7 +709,7 @@ trait Replacements
      * @param array  $dynamic_fields Dynamic fields
      * @param mixed  $object         Related object (Adherent, Contribution, ...)
      *
-     * @return PdfModel
+     * @return self
      */
     public function setDynamicFields(string $form_name, array $dynamic_fields, $object): self
     {
@@ -655,46 +720,81 @@ trait Replacements
             $pattern = trim($dynamic_pattern['pattern'], '/');
             $key   = strtolower(rtrim(ltrim($pattern, '{'), '}'));
             $value = '';
-            if (preg_match("/^{DYNFIELD_([0-9]+)_$uform_name}$/", $pattern, $match)) {
-                /** dynamic field first value */
-                $field_id = $match[1];
-                if ($object !== null) {
-                    $values = $object->getDynamicFields()->getValues($field_id);
-                    $value = $values[1];
-                } else {
-                    $value = '';
-                }
-            }
+
             if (preg_match("/^{LABEL_DYNFIELD_([0-9]+)_$uform_name}$/", $pattern, $match)) {
                 /** dynamic field label */
                 $field_id = $match[1];
                 $value    = $dynamic_fields[$field_id]->getName();
             }
-            if (preg_match("/^{INPUT_DYNFIELD_([0-9]+)_$uform_name}$/", $pattern, $match)) {
-                /** dynamic field input form element */
-                $field_id    = $match[1];
+            if (preg_match("/^{(INPUT_|VALUE_)?DYNFIELD_([0-9]+)_$uform_name}$/", $pattern, $match)) {
+                /** dynamic field value */
+                $capacity = trim($match[1], '_');
+                $field_id    = $match[2];
                 $field_name  = $dynamic_fields[$field_id]->getName();
                 $field_type  = $dynamic_fields[$field_id]->getType();
+                $field_values = [];
                 if ($object !== null) {
-                    $field_values = $object->getDynamicFields()->getValues($field_id);
-                    $field_value = $field_values[0]['field_val'];
+                    $all_values = $object->getDynamicFields()->getValues($field_id);
+                    foreach ($all_values as $field_value) {
+                        $field_values[$field_value['field_val']] = $field_value['text_val'] ?? $field_value['field_val'];
+                    }
                 } else {
-                    $field_value = '';
+                    $field_values = [];
                 }
 
                 switch ($field_type) {
                     case DynamicField::CHOICE:
                         $choice_values = $dynamic_fields[$field_id]->getValues();
-                        foreach ($choice_values as $choice_idx => $choice_value) {
-                            $value .= $choice_value . '&nbsp;';
+                        if ($capacity == 'INPUT') {
+                            foreach ($choice_values as $choice_idx => $choice_value) {
+                                $value .= '<input type="radio" class="box" name="' . $field_name . '" value="' . $field_id . '"';
+                                if (isset($field_values[$choice_idx])) {
+                                    $value .= ' checked="checked"';
+                                }
+                                $value .= ' disabled="disabled">' . $choice_value . '&nbsp;';
+                            }
+                        } else {
+                            foreach ($field_values as $field_value) {
+                                $value .= $field_value;
+                            }
+                        }
+                        break;
+                    case DynamicField::BOOLEAN:
+                        foreach ($field_values as $field_value) {
+                            $value .= ($field_value ? _T("Yes") : _T("No"));
+                        }
+                        break;
+                    case DynamicField::FILE:
+                        $pos = 0;
+                        foreach ($field_values as $field_value) {
+                            if (empty($field_value)) {
+                                continue;
+                            }
+                            $spattern = (($this instanceof Texts) ?
+                                '%3$s (%1$s%2$s)' :
+                                '<a href="%1$s%2$s">%3$s</a>'
+                            );
+                            $value .= sprintf(
+                                $spattern,
+                                $this->preferences->getURL(),
+                                $this->routeparser->urlFor(
+                                    'getDynamicFile',
+                                    [
+                                        'form_name' => $form_name,
+                                        'id' => $object->id,
+                                        'fid' => $field_id,
+                                        'pos' => ++$pos,
+                                        'name' => $field_value
+                                    ]
+                                ),
+                                $field_value
+                            );
                         }
                         break;
                     case DynamicField::TEXT:
                     case DynamicField::LINE:
                     case DynamicField::DATE:
-                    case DynamicField::BOOLEAN:
-                    case DynamicField::FILE:
-                        $value .= $field_value;
+                        $value .= implode('<br/>', $field_values);
                         break;
                 }
             }
@@ -778,15 +878,15 @@ trait Replacements
     }
 
     /**
-     * Set Router dependency
+     * Set RouteParser dependency
      *
-     * @param Router $router Router instance
+     * @param RouteParser $routeparser RouteParser instance
      *
      * @return $this
      */
-    public function setRouter(Router $router): self
+    public function setRouteparser(RouteParser $routeparser): self
     {
-        $this->router = $router;
+        $this->routeparser = $routeparser;
         return $this;
     }
 
@@ -799,8 +899,6 @@ trait Replacements
      */
     protected function proceedReplacements(string $source): string
     {
-        $replaced = $source;
-
         //handle translations
         $callback = static function ($matches) {
             return _T($matches[1]);
@@ -840,7 +938,7 @@ trait Replacements
             $replaced
         );
 
-        return $replaced;
+        return trim($replaced);
     }
 
     /**