Passed
Pull Request — master (#518)
by Stefano
02:47
created

LinkHelper::sortField()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 7
rs 10
1
<?php
2
/**
3
 * BEdita, API-first content management framework
4
 * Copyright 2018 ChannelWeb Srl, Chialab Srl
5
 *
6
 * This file is part of BEdita: you can redistribute it and/or modify
7
 * it under the terms of the GNU Lesser General Public License as published
8
 * by the Free Software Foundation, either version 3 of the License, or
9
 * (at your option) any later version.
10
 *
11
 * See LICENSE.LGPL or <http://gnu.org/licenses/lgpl-3.0.html> for more details.
12
 */
13
namespace App\View\Helper;
14
15
use Cake\Core\Configure;
16
use Cake\Core\Plugin;
17
use Cake\Filesystem\Folder;
18
use Cake\Routing\Router;
19
use Cake\Utility\Hash;
20
use Cake\View\Helper;
21
22
/**
23
 * Helper class to generate links or link tags
24
 *
25
 * @property \Cake\View\Helper\HtmlHelper $Html
26
 */
27
class LinkHelper extends Helper
28
{
29
30
    /**
31
     * List of helpers used by this helper
32
     *
33
     * @var array
34
     */
35
    public $helpers = ['Html'];
36
37
    /**
38
     * API base URL
39
     *
40
     * @var string
41
     */
42
    protected $apiBaseUrl = null;
43
44
    /**
45
     * WebApp base URL
46
     *
47
     * @var string
48
     */
49
    protected $webBaseUrl = null;
50
51
    /**
52
     * Request Query params
53
     *
54
     * @var array
55
     */
56
    protected $query = [];
57
58
    /**
59
     * {@inheritDoc}
60
     *
61
     * Init API and WebAPP base URL
62
     * @codeCoverageIgnore
63
     */
64
    public function initialize(array $config)
65
    {
66
        $this->apiBaseUrl = Configure::read('API.apiBaseUrl');
67
        $this->webBaseUrl = Router::fullBaseUrl();
68
        $this->query = $this->getView()->getRequest()->getQueryParams();
69
    }
70
71
    /**
72
     * Transform API url in web app URL, preserving path part.
73
     * Extremely simple for now
74
     *
75
     * @param string $apiUrl Api url
76
     * @return void
77
     */
78
    public function fromAPI($apiUrl): void
79
    {
80
        echo str_replace($this->apiBaseUrl, $this->webBaseUrl, $apiUrl);
81
    }
82
83
    /**
84
     * Returns sort url by field direction
85
     *
86
     * @param string $field the Field.
87
     * @param bool $resetPage flag to reset pagination.
88
     * @return string
89
     */
90
    public function sortUrl($field, $resetPage = true): string
91
    {
92
        $sort = (string)Hash::get($this->query, 'sort');
93
        $sort = $this->sortValue($field, $sort);
94
        $replace = compact('sort');
95
        $currentPage = Hash::get($this->query, 'page');
96
        if (isset($currentPage) && $resetPage) {
97
            $replace['page'] = 1;
98
        }
99
100
        return $this->replaceQueryParams($replace);
101
    }
102
103
    /**
104
     * Define sort query string value using sort string and current
105
     * 'sort' value
106
     *
107
     * @param string $field Field to sort.
108
     * @param string $sort Current sort value
109
     * @return string
110
     */
111
    protected function sortValue(string $field, string $currentSort): string
112
    {
113
        $sort = $this->sortField($field); // <= ascendant order
114
        if ($currentSort === $sort) { // it was ascendant sort
115
            $sort = '-' . $sort; // <= descendant order
116
        }
117
118
        return $sort;
119
    }
120
121
    /**
122
     * Retrieve 'sort' field from field name.
123
     *
124
     * @param string $field Field name.
125
     * @return string
126
     */
127
    protected function sortField(string $field): string
128
    {
129
        if ($field === 'date_ranges') {
130
            return 'date_ranges_min_start_date';
131
        }
132
133
        return $field;
134
    }
135
136
    /**
137
     * Returns sort class by field direction
138
     *
139
     * @param string $field the Field.
140
     * @return string
141
     */
142
    public function sortClass(string $field): string
143
    {
144
        $sort = (string)Hash::get($this->query, 'sort');
145
        if (empty($sort)) {
146
            return '';
147
        }
148
        $sortField = $this->sortField($field);
149
        if ($sort === $sortField) { // it was ascendant sort
150
            return 'sort down';
151
        }
152
        if ($sort === ('-' . $sortField)) { // it was descendant sort
153
            return 'sort up';
154
        }
155
156
        return '';
157
    }
158
159
    /**
160
     * Pagination link for page
161
     *
162
     * @param int $page destination page.
163
     * @return void
164
     */
165
    public function page($page): void
166
    {
167
        echo $this->replaceQueryParams(['page' => $page]);
168
    }
169
170
    /**
171
     * Pagination link for page size
172
     *
173
     * @param int $pageSize new page size.
174
     * @return void
175
     */
176
    public function pageSize($pageSize): void
177
    {
178
        echo $this->replaceQueryParams(['page_size' => $pageSize]);
179
    }
180
181
    /**
182
     * Return url for current page
183
     *
184
     * @param array $options options for query
185
     * @return string url
186
     */
187
    public function here($options = []): string
188
    {
189
        $here = $this->webBaseUrl . $this->getView()->getRequest()->getAttribute('here');
190
        if (empty($this->query) || !empty($options['no-query'])) {
191
            return $here;
192
        }
193
194
        if (isset($options['exclude'])) {
195
            unset($this->query[$options['exclude']]);
196
        }
197
        $q = http_build_query($this->query);
198
        if (!empty($q)) {
199
            return $here . '?' . $q;
200
        }
201
202
        return $here;
203
    }
204
205
    /**
206
     * Replace query parameters on current request.
207
     *
208
     * @param array $queryParams list of query params to replace.
209
     * @return string new uri
210
     */
211
    private function replaceQueryParams(array $queryParams): string
212
    {
213
        $request = $this->getView()->getRequest();
214
        $query = array_merge($this->query, $queryParams);
215
216
        return (string)$request->getUri()->withQuery(http_build_query($query));
217
    }
218
219
    /**
220
     * Include plugin js and css bundles.
221
     *
222
     * @return void
223
     */
224
    public function pluginsBundle(): void
225
    {
226
        $plugins = Configure::read('Plugins', []);
227
        foreach (['js', 'css'] as $extension) {
228
            foreach ($plugins as $plugin => $v) {
229
                echo $this->pluginAsset($plugin, $extension);
230
            }
231
        }
232
    }
233
234
    /**
235
     * Return js/css plugin asset by plugin and extension
236
     *
237
     * @param string $plugin The plugin
238
     * @param string $extension the extension
239
     * @return string
240
     */
241
    public function pluginAsset(string $plugin, string $extension): string
242
    {
243
        $path = sprintf('%swebroot%s%s%s%s.plugin.%s', Plugin::path($plugin), DS, $extension, DS, $plugin, $extension);
244
        if (!file_exists($path)) {
245
            return '';
246
        }
247
        $method = ($extension === 'js') ? 'script' : 'css';
248
249
        return $this->Html->{$method}(sprintf('%s.%s.plugin.%s', $plugin, $plugin, $extension));
250
    }
251
252
    /**
253
     * Include statically imported JS splitted vendors.
254
     *
255
     * @param array $filter list of file name filters
256
     * @return void
257
     */
258
    public function jsBundle(array $filter = []): void
259
    {
260
        $jsFiles = $this->findFiles($filter, 'js');
261
        foreach ($jsFiles as $jsFile) {
262
            echo $this->Html->script(sprintf('%s', $jsFile));
263
        }
264
    }
265
266
    /**
267
     * Include statically imported CSS splitted vendors.
268
     *
269
     * @param array $filter list of file name filters
270
     * @return void
271
     */
272
    public function cssBundle(array $filter = []): void
273
    {
274
        $cssFiles = $this->findFiles($filter, 'css');
275
        foreach ($cssFiles as $cssFile) {
276
            echo $this->Html->css(sprintf('%s', $cssFile));
277
        }
278
    }
279
280
    /**
281
     * find files under webroot directory specifing a ordered list of filters and the file type
282
     * to search for
283
     *
284
     * @param array $filter list of file name filters
285
     * @param string $type file type (js/css)
286
287
     * @return array files found
288
     */
289
    protected function findFiles(array $filter, string $type): array
290
    {
291
        $files = [];
292
        $filesPath = WWW_ROOT . $type;
293
        if (!file_exists($filesPath)) {
294
            return [];
295
        }
296
297
        $dir = new Folder($filesPath);
298
299
        $filesFound = $dir->find('.*\.' . $type);
300
        if (!empty($filter)) {
301
            foreach ($filter as $filterName) {
302
                foreach ($filesFound as $fileName) {
303
                    if (strpos($fileName, $filterName) !== false) {
304
                        $files[] = sprintf('%s', $fileName);
305
                    }
306
                }
307
            }
308
        } else {
309
            foreach ($filesFound as $fileName) {
310
                $files[] = sprintf('%s', $fileName);
311
            }
312
        }
313
314
        return $files;
315
    }
316
317
    /**
318
     * Build object nav
319
     *
320
     * @param array $data Object nav data
321
     * @return string
322
     */
323
    public function objectNav($data): string
324
    {
325
        $prev = '‹';
326
        $next = '›';
327
        $objectType = Hash::get($data, 'object_type', null);
328
        if (!empty($data['prev'])) {
329
            $prev = $this->Html->link(
330
                $prev,
331
                [
332
                    '_name' => 'modules:view',
333
                    'object_type' => $objectType,
334
                    'id' => $data['prev'],
335
                ]
336
            );
337
        }
338
        if (!empty($data['next'])) {
339
            $next = $this->Html->link(
340
                $next,
341
                [
342
                    '_name' => 'modules:view',
343
                    'object_type' => $objectType,
344
                    'id' => $data['next'],
345
                ]
346
            );
347
        }
348
        $index = Hash::get($data, 'index', 0);
349
        $total = Hash::get($data, 'total', 0);
350
        $counts = sprintf('<div>%d / %d</div>', $index, $total);
351
352
        return sprintf('<div class="listobjnav">%s%s%s</div>', $prev, $next, $counts);
353
    }
354
}
355