Completed
Pull Request — 5.3.0-dev (#2492)
by Jeroen
11:49
created

Model   A

Complexity

Total Complexity 33

Size/Duplication

Total Lines 307
Duplicated Lines 0 %

Test Coverage

Coverage 43.18%

Importance

Changes 0
Metric Value
dl 0
loc 307
ccs 38
cts 88
cp 0.4318
rs 9.3999
c 0
b 0
f 0
wmc 33

13 Methods

Rating   Name   Duplication   Size   Complexity  
A addNumber() 0 22 2
B generatePassword() 0 72 6
A getThumbnailFolders() 0 3 1
A generateThumbnails() 0 3 1
A deleteThumbnails() 0 3 1
A getMockSession() 0 7 2
A getSession() 0 16 3
A requestIsAvailable() 0 4 2
B getUTCTimestamp() 0 21 5
A getModules() 0 16 3
A getAkismet() 0 14 2
A getUTCDate() 0 8 3
A getRequest() 0 7 2
1
<?php
2
3
namespace Common\Core;
4
5
use ForkCMS\App\BaseModel;
6
use ForkCMS\Utility\Thumbnails;
7
use InvalidArgumentException;
8
use RuntimeException;
9
use Symfony\Component\HttpFoundation\Request;
10
use Symfony\Component\HttpFoundation\Session\Session;
11
use Symfony\Component\HttpFoundation\Session\SessionInterface;
12
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
13
use TijsVerkoyen\Akismet\Akismet;
14
15
/**
16
 * This class will initiate the frontend-application
17
 */
18
class Model extends BaseModel
19
{
20
    const HOME_PAGE_ID = 1;
21
    const ERROR_PAGE_ID = 404;
22
23
    /**
24
     * Cached modules
25
     *
26
     * @var array
27
     */
28
    protected static $modules = [];
29
30
    /**
31
     * Add a number to the string
32
     *
33
     * @param string $string The string where the number will be appended to.
34
     *
35
     * @return string
36
     */
37
    public static function addNumber(string $string): string
38
    {
39
        // split
40
        $chunks = explode('-', $string);
41
42
        // count the chunks
43
        $count = count($chunks);
44
45
        // get last chunk
46
        $last = $chunks[$count - 1];
47
48
        // is numeric
49
        if (!\SpoonFilter::isNumeric($last)) {
50
            // not numeric, so add -2
51
            return $string . '-2';
52
        }
53
54
        // remove last chunk
55
        array_pop($chunks);
56
57
        // join together, and increment the last one
58
        return implode('-', $chunks) . '-' . ((int) $last + 1);
59
    }
60
61
    /**
62
     * Generate a totally random but readable/speakable password
63
     *
64
     * @param int $length The maximum length for the password to generate.
65
     * @param bool $uppercaseAllowed Are uppercase letters allowed?
66
     * @param bool $lowercaseAllowed Are lowercase letters allowed?
67
     *
68
     * @return string
69
     */
70
    public static function generatePassword(
71
        int $length = 6,
72
        bool $uppercaseAllowed = true,
73
        bool $lowercaseAllowed = true
74
    ): string {
75
        // list of allowed vowels and vowel sounds
76
        $vowels = ['a', 'e', 'i', 'u', 'ae', 'ea'];
77
78
        // list of allowed consonants and consonant sounds
79
        $consonants = [
80
            'b',
81
            'c',
82
            'd',
83
            'g',
84
            'h',
85
            'j',
86
            'k',
87
            'm',
88
            'n',
89
            'p',
90
            'r',
91
            's',
92
            't',
93
            'u',
94
            'v',
95
            'w',
96
            'tr',
97
            'cr',
98
            'fr',
99
            'dr',
100
            'wr',
101
            'pr',
102
            'th',
103
            'ch',
104
            'ph',
105
            'st',
106
        ];
107
108
        $consonantsCount = count($consonants);
109
        $vowelsCount = count($vowels);
110
        $pass = '';
111
        $tmp = '';
112
113
        // create temporary pass
114
        for ($i = 0; $i < $length; ++$i) {
115
            $tmp .= ($consonants[random_int(0, $consonantsCount - 1)] .
116
                     $vowels[random_int(0, $vowelsCount - 1)]);
117
        }
118
119
        // reformat the pass
120
        for ($i = 0; $i < $length; ++$i) {
121
            if (random_int(0, 1) === 1) {
122
                $pass .= mb_strtoupper($tmp[$i]);
123
124
                continue;
125
            }
126
127
            $pass .= $tmp[$i];
128
        }
129
130
        // reformat it again, if uppercase isn't allowed
131
        if (!$uppercaseAllowed) {
132
            $pass = mb_strtolower($pass);
133
        }
134
135
        // reformat it again, if uppercase isn't allowed
136
        if (!$lowercaseAllowed) {
137
            $pass = mb_strtoupper($pass);
138
        }
139
140
        // return pass
141
        return $pass;
142
    }
143
144
    /**
145
     * Generate thumbnails based on the folders in the path
146
     * Use
147
     *  - 128x128 as foldername to generate an image where the width will be
148
     *      128px and the height will be 128px
149
     *  - 128x as foldername to generate an image where the width will be
150
     *      128px, the height will be calculated based on the aspect ratio.
151
     *  - x128 as foldername to generate an image where the height will be
152
     *      128px, the width will be calculated based on the aspect ratio.
153
     *
154
     * @param string $path The path wherein the thumbnail-folders will be stored.
155
     * @param string $sourceFile The location of the source file
156
     *
157
     * @deprecated Please use the service `forkcms.utility.thumbnails` instead.
158
     */
159
    public static function generateThumbnails(string $path, string $sourceFile): void
160
    {
161
        self::get(Thumbnails::class)->generate($path, $sourceFile);
162
    }
163
164
    /**
165
     * Delete thumbnails based on the folders in the path
166
     *
167
     * @param string $path The path wherein the thumbnail-folders exist.
168
     * @param string|null $thumbnail The filename to be deleted.
169
     *
170
     * @deprecated Please use the service `forkcms.utility.thumbnails` instead.
171
     */
172 1
    public static function deleteThumbnails(string $path, ?string $thumbnail): void
173
    {
174 1
        self::get(Thumbnails::class)->delete($path, $thumbnail);
175 1
    }
176
177
    /**
178
     * Get the thumbnail folders
179
     *
180
     * @param string $path The path
181
     * @param bool $includeSource Should the source-folder be included in the return-array.
182
     *
183
     * @return array
184
     *
185
     * @deprecated Please use the service `forkcms.utility.thumbnails` instead.
186
     */
187 6
    public static function getThumbnailFolders(string $path, bool $includeSource = false): array
188
    {
189 6
        return self::get(Thumbnails::class)->getFolders($path, $includeSource);
190
    }
191
192
    /**
193
     * Get the UTC date in a specific format. Use this method when inserting dates in the database!
194
     *
195
     * @param string $format The format to return the timestamp in. Default is MySQL datetime format.
196
     * @param int $timestamp The timestamp to use, if not provided the current time will be used.
197
     *
198
     * @return string
199
     */
200 48
    public static function getUTCDate(string $format = null, int $timestamp = null): string
201
    {
202 48
        $format = ($format !== null) ? (string) $format : 'Y-m-d H:i:s';
203 48
        if ($timestamp === null) {
204 44
            return gmdate($format);
205
        }
206
207 5
        return gmdate($format, $timestamp);
208
    }
209
210
    /**
211
     * Get the UTC timestamp for a date/time object combination.
212
     *
213
     * @param \SpoonFormDate $date An instance of \SpoonFormDate.
214
     * @param \SpoonFormTime $time An instance of \SpoonFormTime.
215
     *
216
     * @throws \Exception If provided $date, $time or both are invalid
217
     *
218
     * @return int
219
     */
220 1
    public static function getUTCTimestamp(\SpoonFormDate $date, \SpoonFormTime $time = null): int
221
    {
222
        // validate date/time object
223 1
        if (!$date->isValid() || ($time !== null && !$time->isValid())
224
        ) {
225
            throw new \Exception('You need to provide two objects that actually contain valid data.');
226
        }
227
228 1
        $year = gmdate('Y', $date->getTimestamp());
229 1
        $month = gmdate('m', $date->getTimestamp());
230 1
        $day = gmdate('j', $date->getTimestamp());
231 1
        $hour = 0;
232 1
        $minute = 0;
233
234 1
        if ($time !== null) {
235
            // define hour & minute
236 1
            list($hour, $minute) = explode(':', $time->getValue());
237
        }
238
239
        // make and return timestamp
240 1
        return mktime($hour, $minute, 0, $month, $day, $year);
0 ignored issues
show
Bug introduced by
$month of type string is incompatible with the type integer expected by parameter $month of mktime(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

240
        return mktime($hour, $minute, 0, /** @scrutinizer ignore-type */ $month, $day, $year);
Loading history...
Bug introduced by
It seems like $hour can also be of type string; however, parameter $hour of mktime() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

240
        return mktime(/** @scrutinizer ignore-type */ $hour, $minute, 0, $month, $day, $year);
Loading history...
Bug introduced by
It seems like $minute can also be of type string; however, parameter $minute of mktime() does only seem to accept integer, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

240
        return mktime($hour, /** @scrutinizer ignore-type */ $minute, 0, $month, $day, $year);
Loading history...
Bug introduced by
$day of type string is incompatible with the type integer expected by parameter $day of mktime(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

240
        return mktime($hour, $minute, 0, $month, /** @scrutinizer ignore-type */ $day, $year);
Loading history...
Bug introduced by
$year of type string is incompatible with the type integer expected by parameter $year of mktime(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

240
        return mktime($hour, $minute, 0, $month, $day, /** @scrutinizer ignore-type */ $year);
Loading history...
241
    }
242
243 62
    public static function getModules(): array
244
    {
245
        // validate cache
246 62
        if (!empty(self::$modules)) {
247 61
            return self::$modules;
248
        }
249
250
        // get all modules
251 1
        $modules = (array) self::getContainer()->get('database')->getColumn('SELECT m.name FROM modules AS m');
252
253
        // add modules to the cache
254 1
        foreach ($modules as $module) {
255 1
            self::$modules[] = $module;
256
        }
257
258 1
        return self::$modules;
259
    }
260
261 87
    public static function getRequest(): Request
262
    {
263 87
        if (!self::requestIsAvailable()) {
264
            throw new RuntimeException('No request available');
265
        }
266
267 87
        return self::getContainer()->get('request_stack')->getCurrentRequest();
268
    }
269
270 87
    public static function requestIsAvailable(): bool
271
    {
272 87
        return self::getContainer()->has('request_stack')
273 87
               && self::getContainer()->get('request_stack')->getCurrentRequest() !== null;
274
    }
275
276
    protected static function getAkismet(): Akismet
277
    {
278
        $akismetKey = self::get('fork.settings')->get('Core', 'akismet_key');
279
280
        // invalid key, so we can't detect spam
281
        if (empty($akismetKey)) {
282
            throw new InvalidArgumentException('no akismet key found');
283
        }
284
285
        $akismet = new Akismet($akismetKey, SITE_URL);
286
        $akismet->setTimeOut(10);
287
        $akismet->setUserAgent('Fork CMS/' . FORK_VERSION);
288
289
        return $akismet;
290
    }
291
292 81
    public static function getSession(): SessionInterface
293
    {
294 81
        if (!self::requestIsAvailable()) {
295
            return self::getMockSession();
0 ignored issues
show
Deprecated Code introduced by
The function Common\Core\Model::getMockSession() has been deprecated: This has been added to fix an issue but should be fixed properly in fork 6.0.0 ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

295
            return /** @scrutinizer ignore-deprecated */ self::getMockSession();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
296
        }
297
298 81
        $request = self::getRequest();
299 81
        if ($request->hasSession()) {
300 81
            return $request->getSession();
301
        }
302
303
        $session = new Session();
304
        $session->start();
305
        $request->setSession($session);
306
307
        return $session;
308
    }
309
310
    /**
311
     * This method will return a mock session that will be only available while the code is running.
312
     * It is used for instance in the console
313
     *
314
     * @deprecated This has been added to fix an issue but should be fixed properly in fork 6.0.0
315
     *
316
     * @return Session
317
     */
318
    private static function getMockSession(): Session
319
    {
320
        if (!self::getContainer()->has('fork.mock.session')) {
321
            self::getContainer()->set('fork.mock.session', new Session(new MockArraySessionStorage()));
322
        }
323
324
        return self::get('fork.mock.session');
325
    }
326
}
327