Passed
Pull Request — developer (#17588)
by
unknown
16:03
created

Layout::truncateHtml()   B

Complexity

Conditions 10
Paths 19

Size

Total Lines 45
Code Lines 38

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 110

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 38
c 1
b 0
f 0
dl 0
loc 45
ccs 0
cts 0
cp 0
rs 7.6666
cc 10
nc 19
nop 4
crap 110

How to fix   Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/**
4
 * Layout class.
5
 *
6
 * @package App
7
 *
8
 * @copyright YetiForce S.A.
9
 * @license   YetiForce Public License 6.5 (licenses/LicenseEN.txt or yetiforce.com)
10
 * @author    Mariusz Krzaczkowski <[email protected]>
11
 * @author    Radosław Skrzypczak <[email protected]>
12
13
14
15
16
namespace App;
17
18
/**
19
 * Layout class.
20
 */
21
class Layout
22 2
{
23
    /**
24 2
     * Get active layout name.
25 2
     *
26
     * @return string
27 1
     */
28
    public static function getActiveLayout()
29
    {
30
        if (Session::has('layout')) {
31
            return Session::get('layout');
32
        }
33
        return \App\Config::main('defaultLayout');
34
    }
35
36
    /**
37 1
     * Set the active layout name.
38
     *
39 1
     * @param string $layoutName
40 1
     * @return void
41 1
     * @throws \InvalidArgumentException
42 1
     */
43 1
    public static function setActiveLayout(string $layoutName): void
44
    {
45
        if (in_array($layoutName, array_keys(self::getAllLayouts()), true)) {
46 1
            Session::set('layout', $layoutName);
47
        } else {
48 1
            throw new \InvalidArgumentException('Invalid layout name.');
49 1
        }
50 1
    }
51
52 1
    /**
53
     * Get file from layout.
54
     *
55
     * @param string $name
56
     *
57
     * @return string
58
     */
59
    public static function getLayoutFile($name)
60 2
    {
61
        $basePath = 'layouts' . '/' . \App\Config::main('defaultLayout') . '/';
62 2
        $filePath = \Vtiger_Loader::resolveNameToPath('~' . $basePath . $name);
63
        if (is_file($filePath)) {
64 2
            if (!IS_PUBLIC_DIR) {
65
                $basePath = 'public_html/' . $basePath;
66 2
            }
67 1
            return $basePath . $name;
68
        }
69 2
        $basePath = 'layouts' . '/' . \Vtiger_Viewer::getDefaultLayoutName() . '/';
70
        if (!IS_PUBLIC_DIR) {
71
            $basePath = 'public_html/' . $basePath;
72
        }
73
        return $basePath . $name;
74
    }
75
76
    /**
77
     * Gets layout paths.
78
     *
79
     * @return array
80 2
     */
81
    public static function getLayoutPaths(): array
82 2
    {
83 2
        $basePrefix = 'layouts/' . self::getActiveLayout() . \DIRECTORY_SEPARATOR;
84 1
        $defaultPrefix = 'layouts/' . \Vtiger_Viewer::getDefaultLayoutName() . \DIRECTORY_SEPARATOR;
85
        $layoutsPath = [];
86 2
87 2
        if (\App\Config::performance('LOAD_CUSTOM_FILES')) {
88
            $layoutsPath['custom/'] = 'custom/';
89 2
            $layoutsPath["custom/{$basePrefix}"] = "custom/{$basePrefix}";
90
            $layoutsPath["custom/{$defaultPrefix}"] = "custom/{$defaultPrefix}";
91
        }
92
        $layoutsPath[''] = '';
93
        $layoutsPath[$basePrefix] = $basePrefix;
94
        $layoutsPath[$defaultPrefix] = $defaultPrefix;
95
96
        return $layoutsPath;
97
    }
98
99 1
    /**
100
     * Get all layouts list.
101 1
     *
102
     * @return string[]
103
     */
104
    public static function getAllLayouts()
105
    {
106
        $all = (new \App\Db\Query())->select(['name', 'label'])->from('vtiger_layout')->all();
107
        $folders = [
108
            'basic' => Language::translate('LBL_DEFAULT'),
0 ignored issues
show
Bug introduced by
The type Language was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
109
        ];
110
        foreach ($all as $row) {
111
            $folders[$row['name']] = Language::translate($row['label']);
112 1
        }
113
        return $folders;
114 1
    }
115
116
    /**
117
     * Get metadata for a specific layout.
118
     *
119
     * @param string $layoutName
120
     * @return array
121
     */
122
    public static function getLayoutMetadata(string $layoutName): array
123
    {
124 1
        $metadata = [
125
            'name' => $layoutName,
126 1
            'creation_date' => 'unknown',
127
            'author' => 'unknown',
128
            'version' => '1.0',
129
        ];
130
        
131
        // Example placeholder for fetching real metadata.
132
        // You can replace this with actual data retrieval logic.
133
        // $layout = (new \App\Db\Query())->select(['creation_date', 'author', 'version'])
134
        //     ->from('vtiger_layout_metadata')->where(['name' => $layoutName])->one();
135
        // if ($layout) {
136
        //     $metadata = $layout;
137
        // }
138
139
        return $metadata;
140
    }
141
142
    /**
143
     * Get layout files of a specific type.
144
     *
145
     * @param string $fileType
146
     * @return array
147
     */
148
    public static function getLayoutFilesByType(string $fileType): array
149
    {
150
        $layoutsPath = self::getLayoutPaths();
151
        $files = [];
152
153
        foreach ($layoutsPath as $prefix => $path) {
154
            $directory = __DIR__ . '/' . $path;
155
            if (is_dir($directory)) {
156
                foreach (glob($directory . '*.' . $fileType) as $file) {
157
                    $files[] = str_replace(__DIR__ . '/', '', $file);
158
                }
159
            }
160
        }
161
162
        return $files;
163
    }
164
165
    /**
166
     * Validate if the layout exists.
167
     *
168
     * @param string $layoutName
169
     * @return bool
170
     */
171
    public static function validateLayout(string $layoutName): bool
172
    {
173
        return in_array($layoutName, array_keys(self::getAllLayouts()), true);
174
    }
175
176
    /**
177
     * Get public url from file.
178
     *
179
     * @param string $name
180
     * @param bool   $full
181
     *
182
     * @return string
183
     */
184
    public static function getPublicUrl($name, $full = false)
185
    {
186
        $basePath = '';
187
        if ($full) {
188
            $basePath .= \App\Config::main('site_URL');
189
        }
190
        if (!IS_PUBLIC_DIR) {
191
            $basePath .= 'public_html/';
192
        }
193
        return $basePath . $name;
194
    }
195
196
    /**
197
     * The function get path to the image.
198
     *
199
     * @param string $imageName
200
     *
201
     * @return array
202
     */
203
    public static function getImagePath($imageName)
204
    {
205
        return \Vtiger_Theme::getImagePath($imageName);
0 ignored issues
show
Bug Best Practice introduced by
The expression return Vtiger_Theme::getImagePath($imageName) returns the type false|string which is incompatible with the documented return type array.
Loading history...
206
    }
207
208
    /**
209
     * Function takes a template path.
210
     *
211
     * @param string $templateName
212
     * @param string $moduleName
213
     *
214
     * @return string
215
     */
216
    public static function getTemplatePath(string $templateName, string $moduleName = ''): string
217
    {
218
        return \Vtiger_Viewer::getInstance()->getTemplatePath($templateName, $moduleName);
219
    }
220
221
    /**
222
     * Check if template exists.
223
     *
224
     * @param string $templateName
225
     * @param string $moduleName
226
     *
227
     * @return bool
228
     */
229
    public static function checkTemplatePath(string $templateName, string $moduleName = ''): bool
230
    {
231
        self::getTemplatePath($templateName, $moduleName);
232
        return file_exists(\Vtiger_Viewer::$completeTemplatePath);
233
    }
234
235
    /**
236
     * Get unique id for HTML ids.
237
     *
238
     * @param string $name
239
     *
240
     * @return string
241
     */
242
    public static function getUniqueId($name = '')
243
    {
244
        return str_replace([' ', '"', "'"], '', $name) . random_int(100, 99999);
245
    }
246
247
    /**
248
     * Truncating plain text and adding a button showing all the text.
249
     *
250
     * @param string $text
251
     * @param int    $length
252
     * @param bool   $showIcon
253
     * @param bool   $nl2br
254
     *
255
     * @return string
256
     */
257
    public static function truncateText(string $text, int $length, bool $showIcon = false, bool $nl2br = false): string
258
    {
259
        if (\mb_strlen($text) < $length) {
260
            return $nl2br ? nl2br($text) : $text;
261
        }
262
        $teaser = Purifier::encodeHtml(TextUtils::textTruncate($text, $length));
0 ignored issues
show
Bug introduced by
The type Purifier was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
Bug introduced by
The type TextUtils was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
263
        $text = Purifier::encodeHtml($text);
264
        if ($showIcon) {
265
            $btn = '<span class="mdi mdi-overscan"></span>';
266
        } else {
267
            $btn = Language::translate('LBL_MORE_BTN');
268
        }
269
        return "<div class=\"js-more-content c-text-divider\"><pre class=\"teaserContent u-pre\">$teaser</pre><span class=\"fullContent d-none\"><pre class=\"u-pre\">$text</pre></span><span class=\"text-right\"><button type=\"button\" class=\"btn btn-link btn-sm p-0 js-more\">{$btn}</button></span></div>";
270
    }
271
272
    /**
273
     * Truncating HTML and adding a button showing all the text.
274
     *
275
     * @param string $html
276
     * @param string $size
277
     * @param int    $length
278
     * @param mixed  $showBtn
279
     *
280
     * @return string
281
     */
282
    public static function truncateHtml(?string $html, ?string $size = 'medium', ?int $length = 200, $showBtn = false): string
283
    {
284
        if (empty($html)) {
285
            return '';
286
        }
287
        $teaser = $css = $btn = '';
288
        $loadData = $iframe = true;
289
        $btnTemplate = function (string $popoverText = '', ?string $btnClass = '', string $data = 'data-iframe="true"'): string {
290
            $popoverText = \App\Language::translate($popoverText);
291
            return "<a href=\"#\" class=\"js-more noLinkBtn font-weight-lighter js-popover-tooltip ml-2 {$btnClass}\" {$data} data-content=\"{$popoverText}\"><span class=\"mdi mdi-overscan\"></span></a>";
292
        };
293
        $iframeClass = 'modal-iframe js-modal-iframe';
294
        switch ($size) {
295
            case 'full':
296
                $iframeClass = 'js-iframe-full-height';
297
                break;
298
            case 'medium':
299
                $btn = $btnTemplate('LBL_FULLSCREEN', 'c-btn-floating-right-bottom btn btn-primary');
300
                break;
301
            case 'mini':
302
                $btn = $btnTemplate('LBL_SHOW_ORIGINAL_CONTENT');
303
                $css = 'display: none;';
304
                $teaser = TextUtils::textTruncate(trim(strip_tags($html)), $length);
305
                $loadData = false;
306
                break;
307
            case 'miniHtml':
308
                $btn = $btnTemplate('LBL_SHOW_ORIGINAL_CONTENT', '', 'data-modal-size="modal-md"');
309
                $css = 'display: none;';
310
                $teaserBefore = str_replace('<br>', '', $html);
311
                $teaser = TextUtils::htmlTruncateByWords(str_replace('<br>', '', $teaserBefore), $length);
312
                if (false === $showBtn && $teaserBefore == $teaser) {
313
                    $html = $btn = '';
314
                }
315
                $iframe = false;
316
                break;
317
            default:
318
                break;
319
        }
320
        if ($iframe) {
321
            $html = Purifier::encodeHtml($html);
322
            $content = "<div class=\"js-iframe-content\">{$teaser}<iframe sandbox=\"allow-same-origin allow-popups allow-popups-to-escape-sandbox\" class=\"w-100 {$iframeClass}\" frameborder=\"0\" style=\"{$css}\" " . ($loadData ? 'srcdoc' : 'srcdoctemp') . "=\"{$html}\"></iframe>";
323
        } else {
324
            $content = "<div class=\"js-more-content\">{$teaser}<div class=\"w-100 {$iframeClass} fullContent\" style=\"{$css}\">{$html}</div>";
325
        }
326
        return $content . $btn . '</div>';
327
    }
328
}
329