]> git.agnieray.net Git - galette.git/commitdiff
Make dynamic file fields work on contributions and transactions
authorJohan Cwiklinski <johan@x-tnd.be>
Mon, 25 Sep 2023 16:25:08 +0000 (18:25 +0200)
committerJohan Cwiklinski <johan@x-tnd.be>
Mon, 25 Sep 2023 16:28:52 +0000 (18:28 +0200)
closes #1697

galette/includes/routes/management.routes.php
galette/includes/routes/members.routes.php
galette/lib/Galette/Controllers/Crud/DynamicFieldsController.php
galette/lib/Galette/Controllers/Crud/MembersController.php
galette/lib/Galette/Entity/DynamicFieldsHandle.php
galette/lib/Galette/Features/Dynamics.php
galette/lib/Galette/Features/Replacements.php
galette/lib/Galette/Repository/DynamicFieldsSet.php
galette/templates/default/components/dynamic_fields.html.twig
galette/templates/default/elements/display_dynamic_fields.html.twig

index 8f0fef8005c105057974f8a03ee4f4dd08f21072..d6df52b5e650c6d6daf20a1b3e696da82d0399ee 100644 (file)
@@ -412,3 +412,8 @@ $app->post(
     '/payment-type/edit/{id:\d+}',
     [Crud\PaymentTypeController::class, 'doEdit']
 )->setname('editPaymentType')->add($authenticate);
+
+$app->get(
+    '/{form_name:adh|contrib|trans}/{id:\d+}/file/{fid:\d+}/{pos:\d+}/{name}',
+    [Crud\DynamicFieldsController::class, 'getDynamicFile']
+)->setName('getDynamicFile')->add($authenticate);
index 803bf94f2f97a8051309c8db36a1e9085f8b4fcf..6b35a8484b3c26beed71c9a7be8065a4fc66c64a 100644 (file)
@@ -223,11 +223,6 @@ $app->post(
     [Crud\GroupsController::class, 'ajaxMembers']
 )->setName('ajaxGroupMembers')->add($authenticate);
 
-$app->get(
-    '/member/{id:\d+}/file/{fid:\d+}/{pos:\d+}/{name}',
-    [Crud\MembersController::class, 'getDynamicFile']
-)->setName('getDynamicFile')->add($authenticate);
-
 $app->get(
     '/members/mass-change',
     [Crud\MembersController::class, 'massChange']
index 4fec63e72a3ebe47c175ddca11208e39e195f795..6d5ac798d9f35f40aa403af2fa5c9dc083b25876 100644 (file)
@@ -36,6 +36,7 @@
 
 namespace Galette\Controllers\Crud;
 
+use Galette\IO\File;
 use Galette\Repository\DynamicFieldsSet;
 use Throwable;
 use Galette\Controllers\CrudController;
@@ -273,6 +274,126 @@ class DynamicFieldsController extends CrudController
         return $response;
     }
 
+    /**
+     * Get a dynamic file
+     *
+     * @param Request  $request   PSR Request
+     * @param Response $response  PSR Response
+     * @param string   $form_name Form name
+     * @param integer  $id        Object ID
+     * @param integer  $fid       Dynamic fields ID
+     * @param integer  $pos       Dynamic field position
+     * @param string   $name      File name
+     *
+     * @return Response
+     */
+    public function getDynamicFile(
+        Request $request,
+        Response $response,
+        string $form_name,
+        int $id,
+        int $fid,
+        int $pos,
+        string $name
+    ): Response {
+        $object_class = DynamicFieldsSet::getClasses()[$form_name];
+        if ($object_class === 'Galette\Entity\Adherent') {
+            $object = new $object_class($this->zdb);
+        } else {
+            $object = new $object_class($this->zdb, $this->login);
+        }
+
+        $object
+            ->disableAllDeps()
+            ->enableDep('dynamics')
+            ->load($id);
+
+        $denied = null;
+        if (!$object->canShow($this->login)) {
+            $fields = $object->getDynamicFields()->getFields();
+            if (!isset($fields[$fid])) {
+                //field does not exist or access is forbidden
+                $denied = true;
+            } else {
+                $denied = false;
+            }
+        }
+
+        if ($denied === true) {
+            $this->flash->addMessage(
+                'error_detected',
+                _T("You do not have permission for requested URL.")
+            );
+
+            $route_name = 'member';
+            if ($form_name == 'contrib') {
+                $route_name = 'contribution';
+            } elseif ($route_name == 'trans') {
+                $route_name = 'transaction';
+            }
+            return $response
+                ->withHeader(
+                    'Location',
+                    $this->routeparser->urlFor(
+                        $route_name,
+                        ['id' => $id]
+                    )
+                );
+        }
+
+        $filename = str_replace(
+            [
+                '%form',
+                '%oid',
+                '%fid',
+                '%pos'
+            ],
+            [
+                $form_name,
+                $id,
+                $fid,
+                $pos
+            ],
+            '%form_%oid_field_%fid_value_%pos'
+        );
+
+        if (file_exists(GALETTE_FILES_PATH . $filename)) {
+            $type = File::getMimeType(GALETTE_FILES_PATH . $filename);
+
+            $response = $response->withHeader('Content-Description', 'File Transfer')
+                ->withHeader('Content-Type', $type)
+                ->withHeader('Content-Disposition', 'attachment;filename="' . $name . '"')
+                ->withHeader('Pragma', 'no-cache')
+                ->withHeader('Content-Transfer-Encoding', 'binary')
+                ->withHeader('Expires', '0')
+                ->withHeader('Cache-Control', 'must-revalidate')
+                ->withHeader('Pragma', 'public');
+
+            $stream = fopen('php://memory', 'r+');
+            fwrite($stream, file_get_contents(GALETTE_FILES_PATH . $filename));
+            rewind($stream);
+
+            return $response->withBody(new \Slim\Psr7\Stream($stream));
+        } else {
+            Analog::log(
+                'A request has been made to get a dynamic file named `' .
+                $filename . '` that does not exists.',
+                Analog::WARNING
+            );
+
+            $this->flash->addMessage(
+                'error_detected',
+                _T("The file does not exists or cannot be read :(")
+            );
+
+            return $response
+                ->withHeader(
+                    'Location',
+                    $this->routeparser->urlFor('member', ['id' => $id])
+                );
+        }
+    }
+
     // /CRUD - Read
     // CRUD - Update
 
index dee07fba797afbe3c1c147107dc9153c1bd0ca71..f98093c42c03461b1e018f96d7cf148f310f0eed 100644 (file)
@@ -53,7 +53,6 @@ use Galette\Entity\FieldsConfig;
 use Galette\Entity\Social;
 use Galette\Filters\AdvancedMembersList;
 use Galette\Filters\MembersList;
-use Galette\IO\File;
 use Galette\Repository\Groups;
 use Galette\Repository\Members;
 use Galette\Repository\PaymentTypes;
@@ -423,110 +422,6 @@ class MembersController extends CrudController
             ->withHeader('Location', $this->routeparser->urlFor('publicList', ['type' => $type]));
     }
 
-    /**
-     * Get a dynamic file
-     *
-     * @param Request  $request  PSR Request
-     * @param Response $response PSR Response
-     * @param integer  $id       Member ID
-     * @param integer  $fid      Dynamic fields ID
-     * @param integer  $pos      Dynamic field position
-     * @param string   $name     File name
-     *
-     * @return Response
-     */
-    public function getDynamicFile(
-        Request $request,
-        Response $response,
-        int $id,
-        int $fid,
-        int $pos,
-        string $name
-    ): Response {
-        $member = new Adherent($this->zdb);
-        $member
-            ->disableAllDeps()
-            ->enableDep('dynamics')
-            ->load($id);
-
-        $denied = null;
-        if (!$member->canShow($this->login)) {
-            $fields = $member->getDynamicFields()->getFields();
-            if (!isset($fields[$fid])) {
-                //field does not exist or access is forbidden
-                $denied = true;
-            } else {
-                $denied = false;
-            }
-        }
-
-        if ($denied === true) {
-            $this->flash->addMessage(
-                'error_detected',
-                _T("You do not have permission for requested URL.")
-            );
-
-            return $response
-                ->withHeader(
-                    'Location',
-                    $this->routeparser->urlFor(
-                        'member',
-                        ['id' => $id]
-                    )
-                );
-        }
-
-        $filename = str_replace(
-            [
-                '%mid',
-                '%fid',
-                '%pos'
-            ],
-            [
-                $id,
-                $fid,
-                $pos
-            ],
-            'member_%mid_field_%fid_value_%pos'
-        );
-
-        if (file_exists(GALETTE_FILES_PATH . $filename)) {
-            $type = File::getMimeType(GALETTE_FILES_PATH . $filename);
-
-            $response = $response->withHeader('Content-Description', 'File Transfer')
-                ->withHeader('Content-Type', $type)
-                ->withHeader('Content-Disposition', 'attachment;filename="' . $name . '"')
-                ->withHeader('Pragma', 'no-cache')
-                ->withHeader('Content-Transfer-Encoding', 'binary')
-                ->withHeader('Expires', '0')
-                ->withHeader('Cache-Control', 'must-revalidate')
-                ->withHeader('Pragma', 'public');
-
-            $stream = fopen('php://memory', 'r+');
-            fwrite($stream, file_get_contents(GALETTE_FILES_PATH . $filename));
-            rewind($stream);
-
-            return $response->withBody(new \Slim\Psr7\Stream($stream));
-        } else {
-            Analog::log(
-                'A request has been made to get a dynamic file named `' .
-                $filename . '` that does not exists.',
-                Analog::WARNING
-            );
-
-            $this->flash->addMessage(
-                'error_detected',
-                _T("The file does not exists or cannot be read :(")
-            );
-
-            return $response
-                ->withHeader(
-                    'Location',
-                    $this->routeparser->urlFor('member', ['id' => $id])
-                );
-        }
-    }
-
     /**
      * Members list
      *
index c2cc6e115350ed11bc5db3773fdd02d11d52a927..dd6d51bba27349700b1c209b9e29971ac75744ce 100644 (file)
@@ -104,19 +104,7 @@ class DynamicFieldsHandle
      */
     public function load($object)
     {
-        switch (get_class($object)) {
-            case 'Galette\Entity\Adherent':
-                $this->form_name = 'adh';
-                break;
-            case 'Galette\Entity\Contribution':
-                $this->form_name = 'contrib';
-                break;
-            case 'Galette\Entity\Transaction':
-                $this->form_name = 'trans';
-                break;
-            default:
-                throw new \RuntimeException('Class ' . get_class($object) . ' does not handle dynamic fields!');
-        }
+        $this->form_name = $object->getFormName();
 
         try {
             $this->item_id = $object->id;
index aecbc4be3fc83df775fe95f356a2997d1affce41..f3ad505788c634f980e512d031a25a4d5e134f3e 100644 (file)
@@ -36,6 +36,7 @@
 
 namespace Galette\Features;
 
+use Galette\Repository\DynamicFieldsSet;
 use Throwable;
 use Analog\Analog;
 use Galette\DynamicFields\File;
@@ -306,8 +307,13 @@ trait Dynamics
                 continue;
             }
 
+            $form_name = $this->getFormName();
+            if ($form_name === 'adh') {
+                $form_name = 'member'; //for compatibility with existing files
+            }
             $new_filename = sprintf(
-                'member_%d_field_%d_value_%d',
+                '%s_%d_field_%d_value_%d',
+                $form_name,
                 $this->id,
                 $field_id,
                 $val_index
@@ -376,4 +382,14 @@ trait Dynamics
         }
         return $this->dynamicsCheck($dfields, [], []);
     }
+
+    /**
+     * Get form name
+     *
+     * @return string
+     */
+    public function getFormName(): string
+    {
+        return array_search(get_class($this), DynamicFieldsSet::getClasses());
+    }
 }
index 7d585f14413bb1d163e492bbb1ce87bc55a3720e..bfd0bb9c6d19e0c73cd6a37208e59cebc3730f8b 100644 (file)
@@ -753,6 +753,7 @@ trait Replacements
                                 $this->routeparser->urlFor(
                                     'getDynamicFile',
                                     [
+                                        'form_name' => $form_name,
                                         'id' => $object->id,
                                         'fid' => $field_id,
                                         'pos' => ++$pos,
index 7bb1b4861b57dd0dea1d70407b1e15196b6ae872..c2e309a1a8ccb8b42e0500177e6907fb237531cf 100644 (file)
@@ -73,6 +73,20 @@ class DynamicFieldsSet
         $this->login = $login;
     }
 
+    /**
+     * Get form names and associated classes
+     *
+     * @return string[]
+     */
+    public static function getClasses(): array
+    {
+        return [
+            'adh' => 'Galette\Entity\Adherent',
+            'contrib' => 'Galette\Entity\Contribution',
+            'trans' => 'Galette\Entity\Transaction'
+        ];
+    }
+
     /**
      * Get fields list for one form
      *
index d3c5bd0ddcd33aac6d5a155e45b4e940211e25c8..40e45a7b4c7f5aa6d9295b16e220cc904a382351 100644 (file)
@@ -79,7 +79,7 @@
                 </div>
             {% elseif get_class(field) == 'Galette\\DynamicFields\\File' %}
                 {% if object.id and valuedata %}
-                <a href="{{ url_for("getDynamicFile", {"id": object.id, "fid": field.getId(), "pos": loop, "name": valuedata}) }}">
+                <a href="{{ url_for("getDynamicFile", {"form_name": object.getFormName(), "id": object.id, "fid": field.getId(), "pos": loop, "name": valuedata}) }}">
                     {{ valuedata }}
                     <i class="external alternate icon"></i>
                 </a>
index 37583d2401847fbe2fe429ccb77087c231989c5a..4c2c3bd0b8fc9bd2a6f736b1a943718299191929 100644 (file)
@@ -35,7 +35,7 @@
                         {{ _T("No") }}
                                 {% endif %}
                             {% elseif get_class(field) == 'Galette\\DynamicFields\\File' %}
-                                <a href="{{ url_for("getDynamicFile", {"id": object.id, "fid": field.getId(), "pos": loop.index, "name": value}) }}">{{ value }}</a>
+                                <a href="{{ url_for("getDynamicFile", {"form_name": object.getFormName(), "id": object.id, "fid": field.getId(), "pos": loop.index, "name": value}) }}">{{ value }}</a>
                             {% elseif get_class(field) == 'Galette\\DynamicFields\\Line' and callstatic("Galette\\Core\\GaletteMail", "isValidEmail", value) %}
                                 <a href="mailto:{{ value }}">{{ value }}</a>
                             {% elseif get_class(field) == 'Galette\\DynamicFields\\Line' and callstatic("Galette\\Core\\GaletteMail", "isUrl", value) %}