]> git.agnieray.net Git - galette.git/commitdiff
Add DateHelper for setting/getting dates
authorJohan Cwiklinski <johan@x-tnd.be>
Mon, 15 Apr 2024 20:24:23 +0000 (22:24 +0200)
committerJohan Cwiklinski <johan@x-tnd.be>
Tue, 16 Apr 2024 19:16:41 +0000 (21:16 +0200)
Add a setDateFilter for filtering specials formats

12 files changed:
galette/lib/Galette/Core/Pagination.php
galette/lib/Galette/Entity/Contribution.php
galette/lib/Galette/Entity/ScheduledPayment.php
galette/lib/Galette/Entity/Transaction.php
galette/lib/Galette/Features/EntityHelper.php [deleted file]
galette/lib/Galette/Filters/AdvancedMembersList.php
galette/lib/Galette/Filters/ContributionsList.php
galette/lib/Galette/Filters/HistoryList.php
galette/lib/Galette/Filters/ScheduledPaymentsList.php
galette/lib/Galette/Filters/TransactionsList.php
galette/lib/Galette/Helpers/DatesHelper.php [new file with mode: 0644]
galette/lib/Galette/Helpers/EntityHelper.php [new file with mode: 0644]

index e58edeae6fa1c521348ebc2bde7fb0f0e5606731..66a5b2130502c668cdf35d770b48b6b1ee1241dd 100644 (file)
@@ -22,7 +22,6 @@
 namespace Galette\Core;
 
 use Slim\Routing\RouteParser;
-use Slim\Slim;
 use Analog\Analog;
 use Laminas\Db\Sql\Select;
 use Slim\Views\Twig;
@@ -50,6 +49,8 @@ abstract class Pagination
     private ?int $counter = null;
     protected ?Twig $view;
     protected ?RouteParser $routeparser;
+    /** @var array<string> */
+    protected array $errors = [];
 
     public const ORDER_ASC = 'ASC';
     public const ORDER_DESC = 'DESC';
index 07d355158833eb15bbf466fae4ffb7079f1a1f9b..bf3d2c088cf8d3709a909791bb3c23c8a39d1ce9 100644 (file)
@@ -35,7 +35,7 @@ use Galette\IO\ExternalScript;
 use Galette\IO\PdfContribution;
 use Galette\Repository\PaymentTypes;
 use Galette\Features\Dynamics;
-use Galette\Features\EntityHelper;
+use Galette\Helpers\EntityHelper;
 
 /**
  * Contribution class for galette
index f9a7ac9956f6bbaa9017f83652d34de53174a0fd..e006db868a64f0e9e74dd84b64867120491448e8 100644 (file)
@@ -23,7 +23,7 @@ namespace Galette\Entity;
 
 use ArrayObject;
 use DateTime;
-use Galette\Features\EntityHelper;
+use Galette\Helpers\EntityHelper;
 use Laminas\Db\Sql\Expression;
 use Laminas\Db\Sql\Predicate\IsNull;
 use Laminas\Db\Sql\Predicate\Operator;
index 979d539a1378596e3ebda4a0bf511cba48f84aac..eff0968c6af995cc32ae2b597099574d5383e6c8 100644 (file)
@@ -32,7 +32,7 @@ use Galette\Core\Db;
 use Galette\Core\History;
 use Galette\Core\Login;
 use Galette\Features\Dynamics;
-use Galette\Features\EntityHelper;
+use Galette\Helpers\EntityHelper;
 
 /**
  * Transaction class for galette
diff --git a/galette/lib/Galette/Features/EntityHelper.php b/galette/lib/Galette/Features/EntityHelper.php
deleted file mode 100644 (file)
index 5fa8af2..0000000
+++ /dev/null
@@ -1,190 +0,0 @@
-<?php
-
-/**
- * Copyright © 2003-2024 The Galette Team
- *
- * This file is part of Galette (https://galette.eu).
- *
- * Galette is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Galette is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Galette. If not, see <http://www.gnu.org/licenses/>.
- */
-
-namespace Galette\Features;
-
-use DateTime;
-use Galette\Entity\Adherent;
-use Galette\Repository\DynamicFieldsSet;
-use Throwable;
-use Analog\Analog;
-use Galette\DynamicFields\File;
-use Galette\DynamicFields\Date;
-use Galette\DynamicFields\Boolean;
-use Galette\Entity\DynamicFieldsHandle;
-
-/**
- * Dynamics fields trait
- *
- * @author Johan Cwiklinski <johan@x-tnd.be>
- */
-
-trait EntityHelper
-{
-    /**
-     * Fields configuration. Each field is an array and must reflect:
-     * array(
-     *   (string)label,
-     *   (string)propname
-     * )
-     *
-     * @var array<string, array<string, string>>
-     */
-    protected array $fields;
-
-    /** @var string[] */
-    //protected array $forbidden_fields = [];
-
-    /** @var string[] */
-    //protected array $virtual_fields = [];
-
-    /**
-     * Set fields, must populate $this->fields
-     *
-     * @return self
-     */
-    abstract protected function setFields(): self;
-
-    /**
-     * Get fields
-     *
-     * @return array<string, array<string, string>>
-     */
-    public function getFields(): array
-    {
-        return $this->fields;
-    }
-
-    /**
-     * Global isset method
-     * Required for twig to access properties via __get
-     *
-     * @param string $name name of the property we want to retrieve
-     *
-     * @return bool
-     */
-    public function __isset(string $name): bool
-    {
-        if (in_array($name, ($this->forbidden_fields ?? []))) {
-            return false;
-        }
-
-        $virtual_fields = [];
-        if (isset($this->virtual_fields)) {
-            $virtual_fields = $this->virtual_fields;
-        }
-        return (in_array($name, $virtual_fields) || property_exists($this, $name));
-    }
-
-    /**
-     * Get field label
-     *
-     * @param string $field Field name
-     * @param string $entry Array entry to use (defaults to "label")
-     *
-     * @return string
-     */
-    public function getFieldLabel(string $field, string $entry = 'label'): string
-    {
-        $label = $this->fields[$field][$entry] ?? $field;
-        //replace "&nbsp;"
-        $label = str_replace('&nbsp;', ' ', $label);
-        //remove trailing ':' and then trim
-        $label = trim(trim($label, ':'));
-        return $label;
-    }
-
-    /**
-     * Set a Date
-     *
-     * @param string $field Field to store date
-     * @param string $value Date to store
-     *
-     * @return self
-     */
-    protected function setDate(string $field, string $value): self
-    {
-        try {
-            $date = \DateTime::createFromFormat(__("Y-m-d"), $value);
-            if ($date === false) {
-                //try with non localized date
-                $date = \DateTime::createFromFormat("Y-m-d", $value);
-                if ($date === false) {
-                    throw new \Exception('Incorrect format');
-                }
-            }
-            if (isset($this->fields[$field]['propname'])) {
-                $propname = $this->fields[$field]['propname'];
-            } else {
-                $propname = $field;
-            }
-            $this->$propname = $date->format('Y-m-d');
-        } catch (Throwable $e) {
-            Analog::log(
-                'Wrong date format. field: ' . $field .
-                ', value: ' . $field . ', expected fmt: ' .
-                __("Y-m-d") . ' | ' . $e->getMessage(),
-                Analog::INFO
-            );
-            $this->errors[] = sprintf(
-                //TRANS: %1$s is the date format, %2$s is the field name
-                _T('- Wrong date format (%1$s) for %2$s!'),
-                __("Y-m-d"),
-                $this->getFieldLabel($field)
-            );
-        }
-        return $this;
-    }
-
-    /**
-     * Get a date
-     *
-     * @param string $field      Field name to retrieve
-     * @param bool   $formatted  Get formatted date, or DateTime object
-     * @param bool   $translated Get translated or db value
-     *
-     * @return string|DateTime|null
-     */
-    public function getDate(string $field, bool $formatted = true, bool $translated = true): string|DateTime|null
-    {
-        if ($this->$field !== null && $this->$field != '') {
-            try {
-                $date = new \DateTime($this->$field);
-                if ($formatted === false) {
-                    return $date;
-                }
-                if ($translated === false) {
-                    return $date->format('Y-m-d');
-                }
-                return $date->format(__('Y-m-d'));
-            } catch (Throwable $e) {
-                //oops, we've got a bad date :/
-                Analog::log(
-                    'Bad date (' . $this->$field . ') | ' .
-                    $e->getMessage(),
-                    Analog::INFO
-                );
-                return $this->$field;
-            }
-        }
-        return null;
-    }
-}
index 852d935cd162e2b6738470f0e85531614ce21db7..1b80c04173a284e89724439cc7e876d916965ed9 100644 (file)
 
 namespace Galette\Filters;
 
+use Galette\Helpers\DatesHelper;
 use Throwable;
 use Analog\Analog;
 use Galette\Entity\Status;
 use Galette\Entity\ContributionsTypes;
-use Galette\Entity\Contribution;
 use Galette\Repository\Members;
 use Galette\DynamicFields\DynamicField;
 use Galette\Repository\PaymentTypes;
@@ -79,6 +79,8 @@ use Galette\Repository\PaymentTypes;
 
 class AdvancedMembersList extends MembersList
 {
+    use DatesHelper;
+
     public const OP_AND = 0;
     public const OP_OR = 1;
 
@@ -324,21 +326,7 @@ class AdvancedMembersList extends MembersList
                     case 'contrib_begin_date_end':
                     case 'contrib_end_date_begin':
                     case 'contrib_end_date_end':
-                        try {
-                            if ($this->$name !== null) {
-                                $d = new \DateTime($this->$name);
-                                return $d->format(__("Y-m-d"));
-                            }
-                        } catch (Throwable $e) {
-                            //oops, we've got a bad date :/
-                            Analog::log(
-                                'Bad date (' . $this->$name . ') | ' .
-                                $e->getMessage(),
-                                Analog::INFO
-                            );
-                            return $this->$name;
-                        }
-                        break;
+                        return $this->getDate($name);
                     case 'rcreation_date_begin':
                     case 'rcreation_date_end':
                     case 'rmodif_date_begin':
@@ -354,7 +342,7 @@ class AdvancedMembersList extends MembersList
                     case 'rcontrib_end_date_begin':
                     case 'rcontrib_end_date_end':
                         $rname = substr($name, 1);
-                        return $this->$rname;
+                        return $this->getDate($rname, true, false);
                     case 'search_fields':
                         $search_fields = array_merge($this->memberslist_fields, $this->advancedmemberslist_fields);
                         $key = array_search('selected', $search_fields);
@@ -443,21 +431,7 @@ class AdvancedMembersList extends MembersList
                 case 'contrib_begin_date_end':
                 case 'contrib_end_date_begin':
                 case 'contrib_end_date_end':
-                    if ($value !== null && trim($value) !== '') {
-                        try {
-                            $d = \DateTime::createFromFormat(__("Y-m-d"), $value);
-                            if ($d === false) {
-                                throw new \Exception('Incorrect format');
-                            }
-                            $this->$name = $d->format('Y-m-d');
-                        } catch (Throwable $e) {
-                            Analog::log(
-                                'Incorrect date format for ' . $name .
-                                '! was: ' . $value,
-                                Analog::WARNING
-                            );
-                        }
-                    }
+                    $this->setFilterDate($name, $value, str_contains($name, 'begin'));
                     break;
                 case 'contrib_min_amount':
                 case 'contrib_max_amount':
index c07ef4b042d9ff6f3eb59055942a88794c0cbe88..2e8eeea42d9b04d34b9fbab7f0e70ae1995860ea 100644 (file)
@@ -21,6 +21,7 @@
 
 namespace Galette\Filters;
 
+use Galette\Helpers\DatesHelper;
 use Throwable;
 use Analog\Analog;
 use Galette\Core\Pagination;
@@ -46,6 +47,8 @@ use Galette\Core\Pagination;
 
 class ContributionsList extends Pagination
 {
+    use DatesHelper;
+
     public const ORDERBY_DATE = 0;
     public const ORDERBY_BEGIN_DATE = 1;
     public const ORDERBY_END_DATE = 2;
@@ -154,33 +157,12 @@ class ContributionsList extends Pagination
                 switch ($name) {
                     case 'start_date_filter':
                     case 'end_date_filter':
-                        if ($this->$name === null) {
-                            return $this->$name;
-                        }
-                        try {
-                            $d = \DateTime::createFromFormat(__("Y-m-d"), $this->$name);
-                            if ($d === false) {
-                                //try with non localized date
-                                $d = \DateTime::createFromFormat("Y-m-d", $this->$name);
-                                if ($d === false) {
-                                    throw new \Exception('Incorrect format');
-                                }
-                            }
-                            return $d->format(__("Y-m-d"));
-                        } catch (Throwable $e) {
-                            //oops, we've got a bad date :/
-                            Analog::log(
-                                'Bad date (' . $this->$name . ') | ' .
-                                $e->getMessage(),
-                                Analog::INFO
-                            );
-                            return $this->$name;
-                        }
+                        return $this->getDate($name);
                     case 'rstart_date_filter':
                     case 'rend_date_filter':
                         //same as above, but raw format
                         $rname = substr($name, 1);
-                        return $this->$rname;
+                        return $this->getDate($rname, true, false);
                     default:
                         return $this->$name;
                 }
@@ -236,79 +218,7 @@ class ContributionsList extends Pagination
             switch ($name) {
                 case 'start_date_filter':
                 case 'end_date_filter':
-                    try {
-                        if ($value !== '') {
-                            $y = \DateTime::createFromFormat(__("Y"), $value);
-                            if ($y !== false) {
-                                $month = 1;
-                                $day = 1;
-                                if ($name === 'end_date_filter') {
-                                    $month = 12;
-                                    $day = 31;
-                                }
-                                $y->setDate(
-                                    (int)$y->format('Y'),
-                                    $month,
-                                    $day
-                                );
-                                $this->$name = $y->format('Y-m-d');
-                            }
-
-                            $ym = \DateTime::createFromFormat(__("Y-m"), $value);
-                            if ($y === false && $ym !== false) {
-                                $day = 1;
-                                if ($name === 'end_date_filter') {
-                                    $day = (int)$ym->format('t');
-                                }
-                                $ym->setDate(
-                                    (int)$ym->format('Y'),
-                                    (int)$ym->format('m'),
-                                    $day
-                                );
-                                $this->$name = $ym->format('Y-m-d');
-                            }
-
-                            $d = \DateTime::createFromFormat(__("Y-m-d"), $value);
-                            if ($y === false && $ym === false && $d !== false) {
-                                $this->$name = $d->format('Y-m-d');
-                            }
-
-                            if ($y === false && $ym === false && $d === false) {
-                                $formats = array(
-                                    __("Y"),
-                                    __("Y-m"),
-                                    __("Y-m-d"),
-                                );
-
-                                $field = null;
-                                if ($name === 'start_date_filter') {
-                                    $field = _T("start date filter");
-                                }
-                                if ($name === 'end_date_filter') {
-                                    $field = _T("end date filter");
-                                }
-
-                                throw new \Exception(
-                                    sprintf(
-                                        //TRANS: %1$s is field name, %2$s is list of known date formats
-                                        _T('Unknown date format for %1$s.<br/>Know formats are: %2$s'),
-                                        $field,
-                                        implode(', ', $formats)
-                                    )
-                                );
-                            }
-                        } else {
-                            $this->$name = null;
-                        }
-                    } catch (Throwable $e) {
-                        Analog::log(
-                            'Wrong date format. field: ' . $name .
-                            ', value: ' . $value . ', expected fmt: ' .
-                            __("Y-m-d") . ' | ' . $e->getMessage(),
-                            Analog::INFO
-                        );
-                        throw $e;
-                    }
+                    $this->setFilterDate($name, $value, $name === 'start_date_filter');
                     break;
                 default:
                     $this->$name = $value;
index eb4dff20c4dfa445b9405cf4f7ed5821dfa68968..ecdba337af9f005bcfc9004c464b1fb2a8c2cb38 100644 (file)
@@ -21,6 +21,7 @@
 
 namespace Galette\Filters;
 
+use Galette\Helpers\DatesHelper;
 use Throwable;
 use Analog\Analog;
 use Galette\Core\Pagination;
@@ -40,6 +41,8 @@ use Galette\Core\Pagination;
 
 class HistoryList extends Pagination
 {
+    use DatesHelper;
+
     public const ORDERBY_DATE = 0;
     public const ORDERBY_IP = 1;
     public const ORDERBY_USER = 2;
@@ -118,25 +121,12 @@ class HistoryList extends Pagination
             if (in_array($name, $this->list_fields)) {
                 switch ($name) {
                     case 'raw_start_date_filter':
-                        return $this->start_date_filter;
+                        return $this->getDate('start_date_filter', true, false);
                     case 'raw_end_date_filter':
-                        return $this->end_date_filter;
+                        return $this->getDate('end_date_filter', true, false);
                     case 'start_date_filter':
                     case 'end_date_filter':
-                        try {
-                            if ($this->$name !== null) {
-                                $d = new \DateTime($this->$name);
-                                return $d->format(__("Y-m-d"));
-                            }
-                        } catch (Throwable $e) {
-                            //oops, we've got a bad date :/
-                            Analog::log(
-                                'Bad date (' . $this->$name . ') | ' .
-                                $e->getMessage(),
-                                Analog::INFO
-                            );
-                        }
-                        return $this->$name;
+                        return $this->getDate($name);
                     default:
                         return $this->$name;
                 }
@@ -192,79 +182,7 @@ class HistoryList extends Pagination
             switch ($name) {
                 case 'start_date_filter':
                 case 'end_date_filter':
-                    try {
-                        if ($value !== '') {
-                            $y = \DateTime::createFromFormat(__("Y"), $value);
-                            if ($y !== false) {
-                                $month = 1;
-                                $day = 1;
-                                if ($name === 'end_date_filter') {
-                                    $month = 12;
-                                    $day = 31;
-                                }
-                                $y->setDate(
-                                    (int)$y->format('Y'),
-                                    $month,
-                                    $day
-                                );
-                                $this->$name = $y->format('Y-m-d');
-                            }
-
-                            $ym = \DateTime::createFromFormat(__("Y-m"), $value);
-                            if ($y === false && $ym !== false) {
-                                $day = 1;
-                                if ($name === 'end_date_filter') {
-                                    $day = (int)$ym->format('t');
-                                }
-                                $ym->setDate(
-                                    (int)$ym->format('Y'),
-                                    (int)$ym->format('m'),
-                                    $day
-                                );
-                                $this->$name = $ym->format('Y-m-d');
-                            }
-
-                            $d = \DateTime::createFromFormat(__("Y-m-d"), $value);
-                            if ($y === false && $ym === false && $d !== false) {
-                                $this->$name = $d->format('Y-m-d');
-                            }
-
-                            if ($y === false && $ym === false && $d === false) {
-                                $formats = array(
-                                    __("Y"),
-                                    __("Y-m"),
-                                    __("Y-m-d"),
-                                );
-
-                                $field = null;
-                                if ($name === 'start_date_filter') {
-                                    $field = _T("start date filter");
-                                }
-                                if ($name === 'end_date_filter') {
-                                    $field = _T("end date filter");
-                                }
-
-                                throw new \Exception(
-                                    sprintf(
-                                        //TRANS: %1$s is field name, %2$s is list of known date formats
-                                        _T('Unknown date format for %1$s.<br/>Know formats are: %2$s'),
-                                        $field,
-                                        implode(', ', $formats)
-                                    )
-                                );
-                            }
-                        } else {
-                            $this->$name = null;
-                        }
-                    } catch (Throwable $e) {
-                        Analog::log(
-                            'Wrong date format. field: ' . $name .
-                            ', value: ' . $value . ', expected fmt: ' .
-                            __("Y-m-d") . ' | ' . $e->getMessage(),
-                            Analog::INFO
-                        );
-                        throw $e;
-                    }
+                    $this->setFilterDate($name, $value, $name === 'start_date_filter');
                     break;
                 default:
                     $this->$name = $value;
index c59754aad67ea1a016bd7cb341f97d7bb7919c3d..2b316d515db14cfc6b93144891f0c240b490ed50 100644 (file)
@@ -21,6 +21,7 @@
 
 namespace Galette\Filters;
 
+use Galette\Helpers\DatesHelper;
 use Throwable;
 use Analog\Analog;
 use Galette\Core\Pagination;
@@ -42,6 +43,8 @@ use Galette\Core\Pagination;
 
 class ScheduledPaymentsList extends Pagination
 {
+    use DatesHelper;
+
     public const ORDERBY_DATE = 0;
     public const ORDERBY_MEMBER = 1;
     public const ORDERBY_SCHEDULED_DATE = 2;
@@ -136,33 +139,12 @@ class ScheduledPaymentsList extends Pagination
                 switch ($name) {
                     case 'start_date_filter':
                     case 'end_date_filter':
-                        if ($this->$name === null) {
-                            return $this->$name;
-                        }
-                        try {
-                            $d = \DateTime::createFromFormat(__("Y-m-d"), $this->$name);
-                            if ($d === false) {
-                                //try with non localized date
-                                $d = \DateTime::createFromFormat("Y-m-d", $this->$name);
-                                if ($d === false) {
-                                    throw new \Exception('Incorrect format');
-                                }
-                            }
-                            return $d->format(__("Y-m-d"));
-                        } catch (Throwable $e) {
-                            //oops, we've got a bad date :/
-                            Analog::log(
-                                'Bad date (' . $this->$name . ') | ' .
-                                $e->getMessage(),
-                                Analog::INFO
-                            );
-                            return $this->$name;
-                        }
+                        return $this->getDate($name);
                     case 'rstart_date_filter':
                     case 'rend_date_filter':
                         //same as above, but raw format
                         $rname = substr($name, 1);
-                        return $this->$rname;
+                        return $this->getDate($rname, true, false);
                     default:
                         return $this->$name;
                 }
@@ -213,79 +195,7 @@ class ScheduledPaymentsList extends Pagination
             switch ($name) {
                 case 'start_date_filter':
                 case 'end_date_filter':
-                    try {
-                        if ($value !== '') {
-                            $y = \DateTime::createFromFormat(__("Y"), $value);
-                            if ($y !== false) {
-                                $month = 1;
-                                $day = 1;
-                                if ($name === 'end_date_filter') {
-                                    $month = 12;
-                                    $day = 31;
-                                }
-                                $y->setDate(
-                                    (int)$y->format('Y'),
-                                    $month,
-                                    $day
-                                );
-                                $this->$name = $y->format('Y-m-d');
-                            }
-
-                            $ym = \DateTime::createFromFormat(__("Y-m"), $value);
-                            if ($y === false && $ym !== false) {
-                                $day = 1;
-                                if ($name === 'end_date_filter') {
-                                    $day = (int)$ym->format('t');
-                                }
-                                $ym->setDate(
-                                    (int)$ym->format('Y'),
-                                    (int)$ym->format('m'),
-                                    $day
-                                );
-                                $this->$name = $ym->format('Y-m-d');
-                            }
-
-                            $d = \DateTime::createFromFormat(__("Y-m-d"), $value);
-                            if ($y === false && $ym === false && $d !== false) {
-                                $this->$name = $d->format('Y-m-d');
-                            }
-
-                            if ($y === false && $ym === false && $d === false) {
-                                $formats = array(
-                                    __("Y"),
-                                    __("Y-m"),
-                                    __("Y-m-d"),
-                                );
-
-                                $field = null;
-                                if ($name === 'start_date_filter') {
-                                    $field = _T("start date filter");
-                                }
-                                if ($name === 'end_date_filter') {
-                                    $field = _T("end date filter");
-                                }
-
-                                throw new \Exception(
-                                    sprintf(
-                                        //TRANS: %1$s is field name, %2$s is list of known date formats
-                                        _T('Unknown date format for %1$s.<br/>Know formats are: %2$s'),
-                                        $field,
-                                        implode(', ', $formats)
-                                    )
-                                );
-                            }
-                        } else {
-                            $this->$name = null;
-                        }
-                    } catch (Throwable $e) {
-                        Analog::log(
-                            'Wrong date format. field: ' . $name .
-                            ', value: ' . $value . ', expected fmt: ' .
-                            __("Y-m-d") . ' | ' . $e->getMessage(),
-                            Analog::INFO
-                        );
-                        throw $e;
-                    }
+                    $this->setFilterDate($name, $value, $name === 'start_date_filter');
                     break;
                 default:
                     $this->$name = $value;
index 49186a09461c23345155885745f67e02a87674dc..bc4d7e48558815fbe7d399059d26df948d89724c 100644 (file)
@@ -21,6 +21,7 @@
 
 namespace Galette\Filters;
 
+use Galette\Helpers\DatesHelper;
 use Throwable;
 use Analog\Analog;
 use Galette\Core\Pagination;
@@ -41,6 +42,8 @@ use Galette\Core\Pagination;
 
 class TransactionsList extends Pagination
 {
+    use DatesHelper;
+
     public const ORDERBY_DATE = 0;
     public const ORDERBY_MEMBER = 3;
     public const ORDERBY_AMOUNT = 5;
@@ -116,33 +119,12 @@ class TransactionsList extends Pagination
                 switch ($name) {
                     case 'start_date_filter':
                     case 'end_date_filter':
-                        if ($this->$name === null) {
-                            return $this->$name;
-                        }
-                        try {
-                            $d = \DateTime::createFromFormat(__("Y-m-d"), $this->$name);
-                            if ($d === false) {
-                                //try with non localized date
-                                $d = \DateTime::createFromFormat("Y-m-d", $this->$name);
-                                if ($d === false) {
-                                    throw new \Exception('Incorrect format');
-                                }
-                            }
-                            return $d->format(__("Y-m-d"));
-                        } catch (Throwable $e) {
-                            //oops, we've got a bad date :/
-                            Analog::log(
-                                'Bad date (' . $this->$name . ') | ' .
-                                $e->getMessage(),
-                                Analog::INFO
-                            );
-                            return $this->$name;
-                        }
+                        return $this->getDate($name);
                     case 'rstart_date_filter':
                     case 'rend_date_filter':
                         //same as above, but raw format
                         $rname = substr($name, 1);
-                        return $this->$rname;
+                        return $this->getDate($rname, true, false);
                     default:
                         return $this->$name;
                 }
@@ -198,79 +180,7 @@ class TransactionsList extends Pagination
             switch ($name) {
                 case 'start_date_filter':
                 case 'end_date_filter':
-                    try {
-                        if ($value !== '') {
-                            $y = \DateTime::createFromFormat(__("Y"), $value);
-                            if ($y !== false) {
-                                $month = 1;
-                                $day = 1;
-                                if ($name === 'end_date_filter') {
-                                    $month = 12;
-                                    $day = 31;
-                                }
-                                $y->setDate(
-                                    (int)$y->format('Y'),
-                                    $month,
-                                    $day
-                                );
-                                $this->$name = $y->format('Y-m-d');
-                            }
-
-                            $ym = \DateTime::createFromFormat(__("Y-m"), $value);
-                            if ($y === false && $ym !== false) {
-                                $day = 1;
-                                if ($name === 'end_date_filter') {
-                                    $day = (int)$ym->format('t');
-                                }
-                                $ym->setDate(
-                                    (int)$ym->format('Y'),
-                                    (int)$ym->format('m'),
-                                    $day
-                                );
-                                $this->$name = $ym->format('Y-m-d');
-                            }
-
-                            $d = \DateTime::createFromFormat(__("Y-m-d"), $value);
-                            if ($y === false && $ym === false && $d !== false) {
-                                $this->$name = $d->format('Y-m-d');
-                            }
-
-                            if ($y === false && $ym === false && $d === false) {
-                                $formats = array(
-                                    __("Y"),
-                                    __("Y-m"),
-                                    __("Y-m-d"),
-                                );
-
-                                $field = null;
-                                if ($name === 'start_date_filter') {
-                                    $field = _T("start date filter");
-                                }
-                                if ($name === 'end_date_filter') {
-                                    $field = _T("end date filter");
-                                }
-
-                                throw new \Exception(
-                                    sprintf(
-                                        //TRANS: %1$s is field name, %2$s is list of known date formats
-                                        _T('Unknown date format for %1$s.<br/>Know formats are: %2$s'),
-                                        $field,
-                                        implode(', ', $formats)
-                                    )
-                                );
-                            }
-                        } else {
-                            $this->$name = null;
-                        }
-                    } catch (Throwable $e) {
-                        Analog::log(
-                            'Wrong date format. field: ' . $name .
-                            ', value: ' . $value . ', expected fmt: ' .
-                            __("Y-m-d") . ' | ' . $e->getMessage(),
-                            Analog::INFO
-                        );
-                        throw $e;
-                    }
+                    $this->setFilterDate($name, $value, $name === 'start_date_filter');
                     break;
                 default:
                     $this->$name = $value;
diff --git a/galette/lib/Galette/Helpers/DatesHelper.php b/galette/lib/Galette/Helpers/DatesHelper.php
new file mode 100644 (file)
index 0000000..3f30b57
--- /dev/null
@@ -0,0 +1,230 @@
+<?php
+
+/**
+ * Copyright © 2003-2024 The Galette Team
+ *
+ * This file is part of Galette (https://galette.eu).
+ *
+ * Galette is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Galette is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Galette. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace Galette\Helpers;
+
+use DateTime;
+use Throwable;
+use Analog\Analog;
+
+/**
+ * Entity helper trait
+ *
+ * @author Johan Cwiklinski <johan@x-tnd.be>
+ */
+
+trait DatesHelper
+{
+    /**
+     * Set a Date
+     *
+     * @param string $field Field to store date
+     * @param string $value Date to store
+     *
+     * @return self
+     */
+    protected function setDate(string $field, string $value): self
+    {
+        try {
+            //first, try with localized date
+            $date = DateTime::createFromFormat(__("Y-m-d"), $value);
+            if ($date === false) {
+                //try with non localized date
+                $date = DateTime::createFromFormat("Y-m-d", $value);
+                if ($date === false) {
+                    throw new \Exception('Incorrect format');
+                }
+            }
+
+            if (method_exists($this, 'getFieldPropertyName')) {
+                $fieldPropertyName = $this->getFieldPropertyName($field);
+            } else {
+                $fieldPropertyName = $field;
+            }
+            $this->$fieldPropertyName = $date->format('Y-m-d');
+        } catch (Throwable $e) {
+            Analog::log(
+                'Wrong date format. field: ' . $field .
+                ', value: ' . $field . ', expected fmt: ' .
+                __("Y-m-d") . ' | ' . $e->getMessage(),
+                Analog::INFO
+            );
+
+            if (method_exists($this, 'getFieldLabel')) {
+                $fieldLabel = $this->getFieldLabel($field);
+            } else {
+                $fieldLabel = $field;
+            }
+
+            $this->errors[] = sprintf(
+                //TRANS: %1$s is the date format, %2$s is the field name
+                _T('- Wrong date format (%1$s) for %2$s!'),
+                __("Y-m-d"),
+                $fieldLabel
+            );
+        }
+
+        return $this;
+    }
+
+    /**
+     * Set a Date for filtering
+     *
+     * @param string $field Field to store date
+     * @param string $value Date to store
+     * @param bool   $start Is a start date (or is a end date))
+     *
+     * @return self
+     */
+    protected function setFilterDate(string $field, string $value, bool $start): self
+    {
+        $formats = array(
+            __("Y"),
+            __("Y-m"),
+            __("Y-m-d"),
+        );
+
+        try {
+            if ($value !== '') {
+                $y = \DateTime::createFromFormat(__("Y"), $value);
+                if ($y !== false) {
+                    $month = 1;
+                    $day = 1;
+                    if ($start === false) {
+                        $month = 12;
+                        $day = 31;
+                    }
+                    $y->setDate(
+                        (int)$y->format('Y'),
+                        $month,
+                        $day
+                    );
+                    $this->$field = $y->format('Y-m-d');
+                    return $this;
+                }
+
+                $ym = \DateTime::createFromFormat(__("Y-m"), $value);
+                if ($ym !== false) {
+                    $day = 1;
+                    if ($start === false) {
+                        $day = (int)$ym->format('t');
+                    }
+                    $ym->setDate(
+                        (int)$ym->format('Y'),
+                        (int)$ym->format('m'),
+                        $day
+                    );
+                    $this->$field = $ym->format('Y-m-d');
+                    return $this;
+                }
+
+                $d = \DateTime::createFromFormat(__("Y-m-d"), $value);
+                if ($d !== false) {
+                    $this->$field = $d->format('Y-m-d');
+                    return $this;
+                }
+
+                $field = null;
+                if ($start === true) {
+                    $field = _T("start date filter");
+                } else {
+                    $field = _T("end date filter");
+                }
+
+                throw new \Exception(
+                    sprintf(
+                    //TRANS: %1$s is field name, %2$s is list of known date formats
+                        _T('Unknown date format for %1$s.<br/>Know formats are: %2$s'),
+                        $field,
+                        implode(', ', $formats)
+                    )
+                );
+            } else {
+                $this->$field = null;
+            }
+        } catch (Throwable $e) {
+            Analog::log(
+                'Wrong date format. field: ' . $field .
+                ', value: ' . $value . ', known formats: ' .
+                implode(', ', $formats) . ' | ' . $e->getMessage(),
+                Analog::INFO
+            );
+
+            if (method_exists($this, 'getFieldLabel')) {
+                $fieldLabel = $this->getFieldLabel($field);
+            } else {
+                $fieldLabel = $field;
+            }
+
+            $this->errors[] = sprintf(
+                //TRANS: %1$s is the date format, %2$s is the field name
+                _T('- Wrong date format (%1$s) for %2$s!'),
+                implode(', ', $formats),
+                $fieldLabel
+            );
+
+            throw $e;
+        }
+
+        return $this;
+    }
+
+    /**
+     * Get a date
+     *
+     * @param string $field      Field name to retrieve
+     * @param bool   $formatted  Get formatted date, or DateTime object
+     * @param bool   $translated Get translated or db value
+     *
+     * @return string|DateTime|null
+     */
+    public function getDate(string $field, bool $formatted = true, bool $translated = true): string|DateTime|null
+    {
+        if (method_exists($this, 'getFieldPropertyName')) {
+            $fieldPropertyName = $this->getFieldPropertyName($field);
+        } else {
+            $fieldPropertyName = $field;
+        }
+
+        if ($this->$fieldPropertyName !== null && $this->$fieldPropertyName != '') {
+            try {
+                $date = new DateTime($this->$fieldPropertyName);
+                if ($formatted === false) {
+                    return $date;
+                }
+                if ($translated === false) {
+                    return $date->format('Y-m-d');
+                }
+                return $date->format(__('Y-m-d'));
+            } catch (Throwable $e) {
+                //oops, we've got a bad date :/
+                Analog::log(
+                    'Bad date (' . $this->$fieldPropertyName . ') | ' .
+                    $e->getMessage(),
+                    Analog::INFO
+                );
+                return $this->$fieldPropertyName;
+            }
+        }
+
+        return null;
+    }
+}
diff --git a/galette/lib/Galette/Helpers/EntityHelper.php b/galette/lib/Galette/Helpers/EntityHelper.php
new file mode 100644 (file)
index 0000000..6f268ef
--- /dev/null
@@ -0,0 +1,124 @@
+<?php
+
+/**
+ * Copyright © 2003-2024 The Galette Team
+ *
+ * This file is part of Galette (https://galette.eu).
+ *
+ * Galette is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Galette is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Galette. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+namespace Galette\Helpers;
+
+use DateTime;
+use Throwable;
+use Analog\Analog;
+
+/**
+ * Entity helper trait
+ *
+ * @author Johan Cwiklinski <johan@x-tnd.be>
+ */
+
+trait EntityHelper
+{
+    use DatesHelper;
+
+    /**
+     * Fields configuration. Each field is an array and must reflect:
+     * array(
+     *   (string)label,
+     *   (string)property name
+     * )
+     *
+     * @var array<string, array<string, string>>
+     */
+    protected array $fields;
+
+    /** @var string[] */
+    //protected array $forbidden_fields = [];
+
+    /** @var string[] */
+    //protected array $virtual_fields = [];
+
+    /**
+     * Set fields, must populate $this->fields
+     *
+     * @return self
+     */
+    abstract protected function setFields(): self;
+
+    /**
+     * Get fields
+     *
+     * @return array<string, array<string, string>>
+     */
+    public function getFields(): array
+    {
+        return $this->fields;
+    }
+
+    /**
+     * Global isset method
+     * Required for twig to access properties via __get
+     *
+     * @param string $name name of the property we want to retrieve
+     *
+     * @return bool
+     */
+    public function __isset(string $name): bool
+    {
+        if (in_array($name, ($this->forbidden_fields ?? []))) {
+            return false;
+        }
+
+        $virtual_fields = [];
+        if (isset($this->virtual_fields)) {
+            $virtual_fields = $this->virtual_fields;
+        }
+        return (in_array($name, $virtual_fields) || property_exists($this, $name));
+    }
+
+    /**
+     * Get field label
+     *
+     * @param string $field Field name
+     * @param string $entry Array entry to use (defaults to "label")
+     *
+     * @return string
+     */
+    public function getFieldLabel(string $field, string $entry = 'label'): string
+    {
+        $label = $this->fields[$field][$entry] ?? $field;
+        //replace "&nbsp;"
+        $label = str_replace('&nbsp;', ' ', $label);
+        //remove trailing ':' and then trim
+        return trim(trim($label, ':'));
+    }
+
+    /**
+     * Get property name for given field
+     *
+     * @param string $field Field
+     *
+     * @return string
+     */
+    protected function getFieldPropertyName(string $field): string
+    {
+        if (isset($this->fields[$field]['propname'])) {
+            return $this->fields[$field]['propname'];
+        }
+        return $field;
+    }
+}