Browse code

Add opened attribute to downloads to highlight new files

Benjamin Roth authored on09/05/2025 11:18:14
Showing1 changed files
... ...
@@ -77,6 +77,7 @@ class SecureDownloadsController extends AbstractContentElementController
77 77
         {
78 78
             if ($SecFile->pid == $this->User->id)
79 79
             {
80
+                $this->db->update('tl_member_secureDownloads', ['opened' => time()], ['id' => $SecFile->id]);
80 81
                 Controller::sendFileToBrowser($path);
81 82
             } else {
82 83
                 return new Response('',403);
... ...
@@ -110,6 +111,7 @@ class SecureDownloadsController extends AbstractContentElementController
110 111
             }
111 112
 
112 113
             // Single files
114
+            $SecureFile = SecureDownloadsModel::findBy(["uuid = ?"],[$objFiles->uuid]);
113 115
             if ($objFiles->type == 'file')
114 116
             {
115 117
                 $File = new File($objFiles->path);
... ...
@@ -165,7 +167,8 @@ class SecureDownloadsController extends AbstractContentElementController
165 167
                     'meta'      => $arrMeta,
166 168
                     'extension' => $File->extension,
167 169
                     'path'      => $File->dirname,
168
-                    'mtime'     => $File->mtime
170
+                    'mtime'     => $File->mtime,
171
+                    'opened'      => ($SecureFile !== null ? $SecureFile->opened : 0)
169 172
                 );
170 173
 
171 174
                 $auxDate[] = $File->mtime;
... ...
@@ -241,7 +244,8 @@ class SecureDownloadsController extends AbstractContentElementController
241 244
                         'mime'      => $File->mime,
242 245
                         'meta'      => $arrMeta,
243 246
                         'extension' => $File->extension,
244
-                        'path'      => $File->dirname
247
+                        'path'      => $File->dirname,
248
+                        'opened'      => ($SecureFile !== null ? $SecureFile->opened : 0)
245 249
                     );
246 250
 
247 251
                     $auxDate[] = $File->mtime;
Browse code

Revert "Sort files descending based on creation time in content element"

This reverts commit d0f8331c46e0426095111c9e201a293a6fd68c6b.

Benjamin Roth authored on25/09/2023 11:51:03
Showing1 changed files
... ...
@@ -86,7 +86,7 @@ class SecureDownloadsController extends AbstractContentElementController
86 86
         // Get member files for authenticated user
87 87
         $strLocale = $request->getLocale();
88 88
         $allowedDownload = StringUtil::trimsplit(',', strtolower(\Config::get('allowedDownload')));
89
-        $UserFiles = $this->db->executeQuery("SELECT uuid FROM tl_member_secureDownloads WHERE pid = ? ORDER BY ctime DESC",[$this->User->id]);
89
+        $UserFiles = $this->db->executeQuery("SELECT uuid FROM tl_member_secureDownloads WHERE pid = ?",[$this->User->id]);
90 90
 
91 91
         // Return if there are no files
92 92
         if ($UserFiles->rowCount() < 1)
Browse code

Sort files descending based on creation time in content element

Benjamin Roth authored on25/09/2023 11:46:47
Showing1 changed files
... ...
@@ -86,7 +86,7 @@ class SecureDownloadsController extends AbstractContentElementController
86 86
         // Get member files for authenticated user
87 87
         $strLocale = $request->getLocale();
88 88
         $allowedDownload = StringUtil::trimsplit(',', strtolower(\Config::get('allowedDownload')));
89
-        $UserFiles = $this->db->executeQuery("SELECT uuid FROM tl_member_secureDownloads WHERE pid = ?",[$this->User->id]);
89
+        $UserFiles = $this->db->executeQuery("SELECT uuid FROM tl_member_secureDownloads WHERE pid = ? ORDER BY ctime DESC",[$this->User->id]);
90 90
 
91 91
         // Return if there are no files
92 92
         if ($UserFiles->rowCount() < 1)
Browse code

Implement BE wildcard template for content element

Benjamin Roth authored on02/08/2023 11:08:19
Showing1 changed files
... ...
@@ -12,6 +12,7 @@ declare(strict_types=1);
12 12
 
13 13
 namespace vonRotenberg\MemberfilesBundle\Controller\Frontend\ContentElement;
14 14
 
15
+use Contao\BackendTemplate;
15 16
 use Contao\Config;
16 17
 use Contao\ContentModel;
17 18
 use Contao\Controller;
... ...
@@ -29,6 +30,7 @@ use Contao\Template;
29 30
 use Doctrine\DBAL\Connection;
30 31
 use Symfony\Component\HttpFoundation\Request;
31 32
 use Symfony\Component\HttpFoundation\Response;
33
+use Symfony\Contracts\Translation\TranslatorInterface;
32 34
 use vonRotenberg\MemberfilesBundle\Model\SecureDownloadsModel;
33 35
 
34 36
 /**
... ...
@@ -49,6 +51,14 @@ class SecureDownloadsController extends AbstractContentElementController
49 51
         $this->User = FrontendUser::getInstance();
50 52
     }
51 53
 
54
+    public function __invoke(Request $request, ContentModel $model, string $section, array $classes = null): Response
55
+    {
56
+        if (System::getContainer()->get('contao.routing.scope_matcher')->isBackendRequest($request)) {
57
+            return $this->getBackendWildcard($model);
58
+        }
59
+        return parent::__invoke($request, $model, $section, $classes); // TODO: Change the autogenerated stub
60
+    }
61
+
52 62
 
53 63
     protected function getResponse(Template $template, ContentModel $model, Request $request): Response
54 64
     {
... ...
@@ -268,4 +278,31 @@ class SecureDownloadsController extends AbstractContentElementController
268 278
 
269 279
         return $template->getResponse();
270 280
     }
281
+
282
+    protected function getBackendWildcard(ContentModel $element): Response
283
+    {
284
+        $href = $this->container->get('router')->generate(
285
+            'contao_backend',
286
+            ['do' => 'themes', 'table' => 'tl_module', 'act' => 'edit', 'id' => $element->id]
287
+        );
288
+
289
+        $name = $this->container->get('translator')->trans('FMD.'.$this->getType().'.0', [], 'contao_modules');
290
+
291
+        $template = new BackendTemplate('be_wildcard');
292
+        $template->wildcard = '### '.strtoupper($name).' ###';
293
+        $template->id = $element->id;
294
+        $template->link = $element->name;
295
+        $template->href = $href;
296
+
297
+        return new Response($template->parse());
298
+    }
299
+
300
+    public static function getSubscribedServices(): array
301
+    {
302
+        $services = parent::getSubscribedServices();
303
+
304
+        $services['translator'] = TranslatorInterface::class;
305
+
306
+        return $services;
307
+    }
271 308
 }
Browse code

Update

Benjamin Roth authored on01/08/2023 10:07:08
Showing1 changed files
... ...
@@ -74,7 +74,7 @@ class SecureDownloadsController extends AbstractContentElementController
74 74
         }
75 75
 
76 76
         // Get member files for authenticated user
77
-        $objPage = $this->getPageModel();
77
+        $strLocale = $request->getLocale();
78 78
         $allowedDownload = StringUtil::trimsplit(',', strtolower(\Config::get('allowedDownload')));
79 79
         $UserFiles = $this->db->executeQuery("SELECT uuid FROM tl_member_secureDownloads WHERE pid = ?",[$this->User->id]);
80 80
 
... ...
@@ -109,7 +109,7 @@ class SecureDownloadsController extends AbstractContentElementController
109 109
                     continue;
110 110
                 }
111 111
 
112
-                $arrMeta = $objFiles->current()->getMetaData($objPage->language);
112
+                $arrMeta = $objFiles->current()->getMetaData($strLocale);
113 113
 
114 114
                 if (empty($arrMeta))
115 115
                 {
... ...
@@ -117,7 +117,7 @@ class SecureDownloadsController extends AbstractContentElementController
117 117
                     {
118 118
                         continue;
119 119
                     }
120
-                    elseif (($objPage->rootFallbackLanguage !== null && ($arrMeta = $objFiles->current()->getMetaData($objPage->rootFallbackLanguage)) === null) || $arrMeta === null)
120
+                    elseif (($arrMeta = $objFiles->current()->getMetaData('en')) === null || $arrMeta === null)
121 121
                     {
122 122
                         $arrMeta = [];
123 123
                     }
... ...
@@ -186,7 +186,7 @@ class SecureDownloadsController extends AbstractContentElementController
186 186
                         continue;
187 187
                     }
188 188
 
189
-                    $arrMeta = $objSubfiles->current()->getMetaData($objPage->language);
189
+                    $arrMeta = $objSubfiles->current()->getMetaData($strLocale);
190 190
 
191 191
                     if (empty($arrMeta))
192 192
                     {
... ...
@@ -194,7 +194,7 @@ class SecureDownloadsController extends AbstractContentElementController
194 194
                         {
195 195
                             continue;
196 196
                         }
197
-                        elseif (($objPage->rootFallbackLanguage !== null && ($arrMeta = $objSubfiles->current()->getMetaData($objPage->rootFallbackLanguage)) === null) || $arrMeta === null)
197
+                        elseif (($arrMeta = $objSubfiles->current()->getMetaData('en')) === null || $arrMeta === null)
198 198
                         {
199 199
                             $arrMeta = [];
200 200
                         }
Browse code

Update

Benjamin Roth authored on28/07/2023 10:19:32
Showing1 changed files
... ...
@@ -45,11 +45,6 @@ class SecureDownloadsController extends AbstractContentElementController
45 45
 
46 46
     public function __construct(Connection $db)
47 47
     {
48
-        if (!System::getContainer()->get('contao.security.token_checker')->hasFrontendUser())
49
-        {
50
-            return new Response('',403);
51
-        }
52
-
53 48
         $this->db = $db;
54 49
         $this->User = FrontendUser::getInstance();
55 50
     }
... ...
@@ -57,6 +52,12 @@ class SecureDownloadsController extends AbstractContentElementController
57 52
 
58 53
     protected function getResponse(Template $template, ContentModel $model, Request $request): Response
59 54
     {
55
+        // The module is only accessible for authenticated members
56
+        if (!System::getContainer()->get('contao.security.token_checker')->hasFrontendUser())
57
+        {
58
+            return new Response('',403);
59
+        }
60
+
60 61
         // Handle file requests
61 62
         if (
62 63
             ($path = Input::get('file', true)) !== null
... ...
@@ -72,6 +73,7 @@ class SecureDownloadsController extends AbstractContentElementController
72 73
             }
73 74
         }
74 75
 
76
+        // Get member files for authenticated user
75 77
         $objPage = $this->getPageModel();
76 78
         $allowedDownload = StringUtil::trimsplit(',', strtolower(\Config::get('allowedDownload')));
77 79
         $UserFiles = $this->db->executeQuery("SELECT uuid FROM tl_member_secureDownloads WHERE pid = ?",[$this->User->id]);
Browse code

Update

Benjamin Roth authored on26/07/2023 21:23:35
Showing1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,269 @@
1
+<?php
2
+
3
+declare(strict_types=1);
4
+
5
+/*
6
+ * This file is part of eSales Media SinglereisenBundle
7
+ *
8
+ * (c) Benjamin Roth
9
+ *
10
+ * @license proprietary
11
+ */
12
+
13
+namespace vonRotenberg\MemberfilesBundle\Controller\Frontend\ContentElement;
14
+
15
+use Contao\Config;
16
+use Contao\ContentModel;
17
+use Contao\Controller;
18
+use Contao\CoreBundle\Controller\ContentElement\AbstractContentElementController;
19
+use Contao\CoreBundle\ServiceAnnotation\ContentElement;
20
+use Contao\Environment;
21
+use Contao\File;
22
+use Contao\FilesModel;
23
+use Contao\FrontendUser;
24
+use Contao\Image;
25
+use Contao\Input;
26
+use Contao\StringUtil;
27
+use Contao\System;
28
+use Contao\Template;
29
+use Doctrine\DBAL\Connection;
30
+use Symfony\Component\HttpFoundation\Request;
31
+use Symfony\Component\HttpFoundation\Response;
32
+use vonRotenberg\MemberfilesBundle\Model\SecureDownloadsModel;
33
+
34
+/**
35
+ * @ContentElement(SecureDownloadsController::TYPE, category="files")
36
+ */
37
+class SecureDownloadsController extends AbstractContentElementController
38
+{
39
+    public const TYPE = 'secure_downloads';
40
+
41
+    /** @var Connection */
42
+    protected $db;
43
+
44
+    protected $User;
45
+
46
+    public function __construct(Connection $db)
47
+    {
48
+        if (!System::getContainer()->get('contao.security.token_checker')->hasFrontendUser())
49
+        {
50
+            return new Response('',403);
51
+        }
52
+
53
+        $this->db = $db;
54
+        $this->User = FrontendUser::getInstance();
55
+    }
56
+
57
+
58
+    protected function getResponse(Template $template, ContentModel $model, Request $request): Response
59
+    {
60
+        // Handle file requests
61
+        if (
62
+            ($path = Input::get('file', true)) !== null
63
+            && ($File = FilesModel::findByPath($path)) !== null
64
+            && ($SecFile = $SecFile = SecureDownloadsModel::findBy(["uuid = ?"],[$File->uuid])) !== null
65
+        )
66
+        {
67
+            if ($SecFile->pid == $this->User->id)
68
+            {
69
+                Controller::sendFileToBrowser($path);
70
+            } else {
71
+                return new Response('',403);
72
+            }
73
+        }
74
+
75
+        $objPage = $this->getPageModel();
76
+        $allowedDownload = StringUtil::trimsplit(',', strtolower(\Config::get('allowedDownload')));
77
+        $UserFiles = $this->db->executeQuery("SELECT uuid FROM tl_member_secureDownloads WHERE pid = ?",[$this->User->id]);
78
+
79
+        // Return if there are no files
80
+        if ($UserFiles->rowCount() < 1)
81
+        {
82
+            return new Response();
83
+        }
84
+
85
+        $arrUuid = $UserFiles->fetchFirstColumn();
86
+
87
+        if (($objFiles = FilesModel::findMultipleByUuids($arrUuid)) === null)
88
+        {
89
+            return new Response();
90
+        }
91
+
92
+        while ($objFiles->next())
93
+        {
94
+            // Continue if the files has been processed or does not exist
95
+            if (isset($files[$objFiles->path]) || !file_exists(TL_ROOT . '/' . $objFiles->path))
96
+            {
97
+                continue;
98
+            }
99
+
100
+            // Single files
101
+            if ($objFiles->type == 'file')
102
+            {
103
+                $File = new File($objFiles->path);
104
+
105
+                if (!in_array($File->extension, $allowedDownload) || preg_match('/^meta(_[a-z]{2})?\.txt$/', $File->basename))
106
+                {
107
+                    continue;
108
+                }
109
+
110
+                $arrMeta = $objFiles->current()->getMetaData($objPage->language);
111
+
112
+                if (empty($arrMeta))
113
+                {
114
+                    if ($model->metaIgnore)
115
+                    {
116
+                        continue;
117
+                    }
118
+                    elseif (($objPage->rootFallbackLanguage !== null && ($arrMeta = $objFiles->current()->getMetaData($objPage->rootFallbackLanguage)) === null) || $arrMeta === null)
119
+                    {
120
+                        $arrMeta = [];
121
+                    }
122
+                }
123
+
124
+                // Use the file name as title if none is given
125
+                if (empty($arrMeta['title']))
126
+                {
127
+                    $arrMeta['title'] = StringUtil::specialchars($File->basename);
128
+                }
129
+
130
+                $strHref = Environment::get('request');
131
+
132
+                // Remove an existing file parameter (see #5683)
133
+                if (preg_match('/(&(amp;)?|\?)file=/', $strHref))
134
+                {
135
+                    $strHref = preg_replace('/(&(amp;)?|\?)file=[^&]+/', '', $strHref);
136
+                }
137
+
138
+                $strHref .= ((Config::get('disableAlias') || strpos($strHref, '?') !== false) ? '&amp;' : '?') . 'file=' . System::urlEncode($objFiles->path);
139
+
140
+                // Add the image
141
+                $files[$objFiles->path] = array
142
+                (
143
+                    'id'        => $objFiles->id,
144
+                    'uuid'      => $objFiles->uuid,
145
+                    'name'      => $File->basename,
146
+                    'title'     => StringUtil::specialchars(sprintf($GLOBALS['TL_LANG']['MSC']['download'], $File->basename)),
147
+                    'link'      => $arrMeta['title'] ?? '',
148
+                    'caption'   => $arrMeta['caption'] ?? '',
149
+                    'href'      => $strHref,
150
+                    'filesize'  => System::getReadableSize($File->filesize, 1),
151
+                    'icon'      => Image::getPath($File->icon),
152
+                    'mime'      => $File->mime,
153
+                    'meta'      => $arrMeta,
154
+                    'extension' => $File->extension,
155
+                    'path'      => $File->dirname,
156
+                    'mtime'     => $File->mtime
157
+                );
158
+
159
+                $auxDate[] = $File->mtime;
160
+            }
161
+
162
+            // Folders
163
+            else
164
+            {
165
+                $objSubfiles = FilesModel::findByPid($objFiles->uuid);
166
+
167
+                if ($objSubfiles === null)
168
+                {
169
+                    continue;
170
+                }
171
+
172
+                while ($objSubfiles->next())
173
+                {
174
+                    // Skip subfolders
175
+                    if ($objSubfiles->type == 'folder')
176
+                    {
177
+                        continue;
178
+                    }
179
+
180
+                    $File = new File($objSubfiles->path);
181
+
182
+                    if (!in_array($File->extension, $allowedDownload) || preg_match('/^meta(_[a-z]{2})?\.txt$/', $File->basename))
183
+                    {
184
+                        continue;
185
+                    }
186
+
187
+                    $arrMeta = $objSubfiles->current()->getMetaData($objPage->language);
188
+
189
+                    if (empty($arrMeta))
190
+                    {
191
+                        if ($model->metaIgnore)
192
+                        {
193
+                            continue;
194
+                        }
195
+                        elseif (($objPage->rootFallbackLanguage !== null && ($arrMeta = $objSubfiles->current()->getMetaData($objPage->rootFallbackLanguage)) === null) || $arrMeta === null)
196
+                        {
197
+                            $arrMeta = [];
198
+                        }
199
+                    }
200
+
201
+                    // Use the file name as title if none is given
202
+                    if (empty($arrMeta['title']))
203
+                    {
204
+                        $arrMeta['title'] = StringUtil::specialchars($File->basename);
205
+                    }
206
+
207
+                    $strHref = Environment::get('request');
208
+
209
+                    // Remove an existing file parameter (see #5683)
210
+                    if (preg_match('/(&(amp;)?|\?)file=/', $strHref))
211
+                    {
212
+                        $strHref = preg_replace('/(&(amp;)?|\?)file=[^&]+/', '', $strHref);
213
+                    }
214
+
215
+                    $strHref .= ((Config::get('disableAlias') || strpos($strHref, '?') !== false) ? '&amp;' : '?') . 'file=' . System::urlEncode($objSubfiles->path);
216
+
217
+                    // Add the image
218
+                    $files[$objSubfiles->path] = array
219
+                    (
220
+                        'id'        => $objSubfiles->id,
221
+                        'uuid'      => $objSubfiles->uuid,
222
+                        'name'      => $File->basename,
223
+                        'title'     => StringUtil::specialchars(sprintf($GLOBALS['TL_LANG']['MSC']['download'], $File->basename)),
224
+                        'link'      => $arrMeta['title'] ?? '',
225
+                        'caption'   => $arrMeta['caption'] ?? '',
226
+                        'href'      => $strHref,
227
+                        'filesize'  => System::getReadableSize($File->filesize, 1),
228
+                        'icon'      => Image::getPath($File->icon),
229
+                        'mime'      => $File->mime,
230
+                        'meta'      => $arrMeta,
231
+                        'extension' => $File->extension,
232
+                        'path'      => $File->dirname
233
+                    );
234
+
235
+                    $auxDate[] = $File->mtime;
236
+                }
237
+            }
238
+        }
239
+
240
+        // Sort array
241
+        switch ($model->sortBy)
242
+        {
243
+            default:
244
+            case 'name_asc':
245
+                uksort($files, 'basename_natcasecmp');
246
+                break;
247
+
248
+            case 'name_desc':
249
+                uksort($files, 'basename_natcasercmp');
250
+                break;
251
+
252
+            case 'date_asc':
253
+                array_multisort($files, SORT_NUMERIC, $auxDate, SORT_ASC);
254
+                break;
255
+
256
+            case 'date_desc':
257
+                array_multisort($files, SORT_NUMERIC, $auxDate, SORT_DESC);
258
+                break;
259
+
260
+            case 'random':
261
+                shuffle($files);
262
+                break;
263
+        }
264
+
265
+        $template->files = array_values($files);
266
+
267
+        return $template->getResponse();
268
+    }
269
+}