Scrutinizer GitHub App not installed

We could not synchronize checks via GitHub's checks API since Scrutinizer's GitHub App is not installed for this repository.

Install GitHub App

GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Passed
Push — master ( 27474d...53316b )
by Sebastian
02:38
created

Helper::getBeUser()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 13
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 11
nc 2
nop 0
dl 0
loc 13
rs 9.9
c 0
b 0
f 0

1 Method

Rating   Name   Duplication   Size   Complexity  
A Helper::getCleanString() 0 10 1
1
<?php
2
namespace Kitodo\Dlf\Common;
3
4
/**
5
 * (c) Kitodo. Key to digital objects e.V. <[email protected]>
6
 *
7
 * This file is part of the Kitodo and TYPO3 projects.
8
 *
9
 * @license GNU General Public License version 3 or later.
10
 * For the full copyright and license information, please read the
11
 * LICENSE.txt file that was distributed with this source code.
12
 */
13
14
/**
15
 * Helper class for the 'dlf' extension
16
 *
17
 * @author Sebastian Meyer <[email protected]>
18
 * @author Henrik Lochmann <[email protected]>
19
 * @package TYPO3
20
 * @subpackage dlf
21
 * @access public
22
 */
23
class Helper {
24
    /**
25
     * The extension key
26
     *
27
     * @var string
28
     * @access public
29
     */
30
    public static $extKey = 'dlf';
31
32
    /**
33
     * The locallang array for flash messages
34
     *
35
     * @var array
36
     * @access protected
37
     */
38
    protected static $messages = [];
39
40
    /**
41
     * Generates a flash message and adds it to a message queue.
42
     *
43
     * @access public
44
     *
45
     * @param string $message: The body of the message
46
     * @param string $title: The title of the message
47
     * @param integer $severity: The message's severity
48
     * @param boolean $session: Should the message be saved in the user's session?
49
     * @param string $queue: The queue's unique identifier
50
     *
51
     * @return \TYPO3\CMS\Core\Messaging\FlashMessageQueue The queue the message was added to
52
     */
53
    public static function addMessage($message, $title, $severity, $session = FALSE, $queue = 'kitodo.default.flashMessages') {
54
        $flashMessageService = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessageService::class);
55
        $flashMessageQueue = $flashMessageService->getMessageQueueByIdentifier($queue);
56
        $flashMessage = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(
57
            \TYPO3\CMS\Core\Messaging\FlashMessage::class,
58
            $message,
59
            $title,
60
            $severity,
61
            $session
62
        );
63
        $flashMessageQueue->enqueue($flashMessage);
64
        return $flashMessageQueue;
65
    }
66
67
    /**
68
     * Check if given identifier is a valid identifier of the German National Library
69
     *
70
     * @access public
71
     *
72
     * @param string $id: The identifier to check
73
     * @param string $type: What type is the identifier supposed to be?
74
     *                      Possible values: PPN, IDN, PND, ZDB, SWD, GKD
75
     *
76
     * @return boolean Is $id a valid GNL identifier of the given $type?
77
     */
78
    public static function checkIdentifier($id, $type) {
79
        $digits = substr($id, 0, 8);
80
        $checksum = 0;
81
        for ($i = 0, $j = strlen($digits); $i < $j; $i++) {
82
            $checksum += (9 - $i) * intval(substr($digits, $i, 1));
83
        }
84
        $checksum = (11 - ($checksum % 11)) % 11;
85
        switch (strtoupper($type)) {
86
            case 'PPN':
87
            case 'IDN':
88
            case 'PND':
89
                if ($checksum == 10) {
90
                    $checksum = 'X';
91
                }
92
                if (!preg_match('/[0-9]{8}[0-9X]{1}/i', $id)) {
93
                    return FALSE;
94
                } elseif (strtoupper(substr($id, -1, 1)) != $checksum) {
95
                    return FALSE;
96
                }
97
                break;
98
            case 'ZDB':
99
                if ($checksum == 10) {
100
                    $checksum = 'X';
101
                }
102
                if (!preg_match('/[0-9]{8}-[0-9X]{1}/i', $id)) {
103
                    return FALSE;
104
                } elseif (strtoupper(substr($id, -1, 1)) != $checksum) {
105
                    return FALSE;
106
                }
107
                break;
108
            case 'SWD':
109
                $checksum = 11 - $checksum;
110
                if (!preg_match('/[0-9]{8}-[0-9]{1}/i', $id)) {
111
                    return FALSE;
112
                } elseif ($checksum == 10) {
113
                    return self::checkIdentifier(($digits + 1).substr($id, -2, 2), 'SWD');
114
                } elseif (substr($id, -1, 1) != $checksum) {
115
                    return FALSE;
116
                }
117
                break;
118
            case 'GKD':
119
                $checksum = 11 - $checksum;
120
                if ($checksum == 10) {
121
                    $checksum = 'X';
122
                }
123
                if (!preg_match('/[0-9]{8}-[0-9X]{1}/i', $id)) {
124
                    return FALSE;
125
                } elseif (strtoupper(substr($id, -1, 1)) != $checksum) {
126
                    return FALSE;
127
                }
128
                break;
129
        }
130
        return TRUE;
131
    }
132
133
    /**
134
     * Decrypt encrypted value with given control hash
135
     *
136
     * @access public
137
     *
138
     * @param string $encrypted: The encrypted value to decrypt
139
     * @param string $hash: The control hash for decrypting
140
     *
141
     * @return mixed The decrypted value or NULL on error
142
     */
143
    public static function decrypt($encrypted, $hash) {
144
        $decrypted = NULL;
0 ignored issues
show
Unused Code introduced by
The assignment to $decrypted is dead and can be removed.
Loading history...
145
        if (empty($encrypted)
146
            || empty($hash)) {
147
            self::devLog('Invalid parameters given for decryption', DEVLOG_SEVERITY_ERROR);
148
            return;
149
        }
150
        if (empty($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'])) {
151
            self::devLog('No encryption key set in TYPO3 configuration', DEVLOG_SEVERITY_ERROR);
152
            return;
153
        }
154
        $iv = substr(md5($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey']), 0, openssl_cipher_iv_length('BF-CFB'));
155
        $decrypted = openssl_decrypt($encrypted, 'BF-CFB', substr($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'], 0, 56), 0, $iv);
156
        $salt = substr($hash, 0, 10);
157
        $hashed = $salt.substr(sha1($salt.$decrypted), -10);
158
        if ($hashed !== $hash) {
159
            self::devLog('Invalid hash "'.$hash.'" given for decryption', DEVLOG_SEVERITY_WARNING);
160
            return;
161
        }
162
        return $decrypted;
163
    }
164
165
    /**
166
     * Add a message to the TYPO3 developer log
167
     *
168
     * @access public
169
     *
170
     * @param string $message: The message to log
171
     * @param integer $severity: The severity of the message
172
     *                           0 is info, 1 is notice, 2 is warning, 3 is fatal error, -1 is "OK" message
173
     *
174
     * @return void
175
     */
176
    public static function devLog($message, $severity = 0) {
177
        if (TYPO3_DLOG) {
178
            $stacktrace = debug_backtrace(0, 2);
179
            // Set some defaults.
180
            $caller = 'Kitodo\Dlf\Default\UnknownClass::unknownMethod';
181
            $args = [];
182
            $data = [];
183
            if (!empty($stacktrace[1])) {
184
                $caller = $stacktrace[1]['class'].$stacktrace[1]['type'].$stacktrace[1]['function'];
185
                foreach ($stacktrace[1]['args'] as $arg) {
186
                    if (is_bool($arg)) {
187
                        $args[] = ($arg ? 'TRUE' : 'FALSE');
188
                    } elseif (is_scalar($arg)) {
189
                        $args[] = (string) $arg;
190
                    } elseif (is_null($arg)) {
191
                        $args[] = 'NULL';
192
                    } elseif (is_array($arg)) {
193
                        $args[] = '[data]';
194
                        $data[] = $arg;
195
                    } elseif (is_object($arg)) {
196
                        $args[] = '['.get_class($arg).']';
197
                        $data[] = $arg;
198
                    }
199
                }
200
            }
201
            $arguments = '('.implode(', ', $args).')';
202
            $additionalData = (empty($data) ? FALSE : $data);
203
            \TYPO3\CMS\Core\Utility\GeneralUtility::devLog('['.$caller.$arguments.'] '.$message, self::$extKey, $severity, $additionalData);
204
        }
205
    }
206
207
    /**
208
     * Encrypt the given string
209
     *
210
     * @access public
211
     *
212
     * @param string $string: The string to encrypt
213
     *
214
     * @return array Array with encrypted string and control hash
215
     */
216
    public static function encrypt($string) {
217
        if (empty($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'])) {
218
            self::devLog('No encryption key set in TYPO3 configuration', DEVLOG_SEVERITY_ERROR);
219
            return;
220
        }
221
        $iv = substr(md5($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey']), 0, openssl_cipher_iv_length('BF-CFB'));
222
        $encrypted = openssl_encrypt($string, 'BF-CFB', substr($GLOBALS['TYPO3_CONF_VARS']['SYS']['encryptionKey'], 0, 56), 0, $iv);
223
        $salt = substr(md5(uniqid(rand(), TRUE)), 0, 10);
224
        $hash = $salt.substr(sha1($salt.$string), -10);
225
        return ['encrypted' => $encrypted, 'hash' => $hash];
226
    }
227
228
    /**
229
     * Get the unqualified name of a class
230
     *
231
     * @access public
232
     *
233
     * @param string $qualifiedClassname: The qualified class name from get_class()
234
     *
235
     * @return string The unqualified class name
236
     */
237
    public static function getUnqualifiedClassName($qualifiedClassname) {
238
        $nameParts = explode('\\', $qualifiedClassname);
239
        return end($nameParts);
240
    }
241
242
    /**
243
     * Clean up a string to use in an URL.
244
     *
245
     * @access public
246
     *
247
     * @param string $string: The string to clean up
248
     *
249
     * @return string The cleaned up string
250
     */
251
    public static function getCleanString($string) {
252
        // Convert to lowercase.
253
        $string = strtolower($string);
254
        // Remove non-alphanumeric characters.
255
        $string = preg_replace('/[^a-z0-9_\s-]/', '', $string);
256
        // Remove multiple dashes or whitespaces.
257
        $string = preg_replace('/[\s-]+/', ' ', $string);
258
        // Convert whitespaces and underscore to dash.
259
        $string = preg_replace('/[\s_]/', '-', $string);
260
        return $string;
261
    }
262
263
    /**
264
     * Get the registered hook objects for a class
265
     *
266
     * @access public
267
     *
268
     * @param string $scriptRelPath: The path to the class file
269
     *
270
     * @return array Array of hook objects for the class
271
     */
272
    public static function getHookObjects($scriptRelPath) {
273
        $hookObjects = [];
274
        if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][self::$extKey.'/'.$scriptRelPath]['hookClass'])) {
275
            foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS'][self::$extKey.'/'.$scriptRelPath]['hookClass'] as $classRef) {
276
                $hookObjects[] = &\TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance($classRef);
277
            }
278
        }
279
        return $hookObjects;
280
    }
281
282
    /**
283
     * Get the "index_name" for an UID
284
     *
285
     * @access public
286
     *
287
     * @param integer $uid: The UID of the record
288
     * @param string $table: Get the "index_name" from this table
289
     * @param integer $pid: Get the "index_name" from this page
290
     *
291
     * @return string "index_name" for the given UID
292
     */
293
    public static function getIndexNameFromUid($uid, $table, $pid = -1) {
294
        // Sanitize input.
295
        $uid = max(intval($uid), 0);
296
        if (!$uid
297
            || !in_array($table, ['tx_dlf_collections', 'tx_dlf_libraries', 'tx_dlf_metadata', 'tx_dlf_structures', 'tx_dlf_solrcores'])) {
298
            self::devLog('Invalid UID "'.$uid.'" or table "'.$table.'"', DEVLOG_SEVERITY_ERROR);
299
            return '';
300
        }
301
        $where = '';
302
        // Should we check for a specific PID, too?
303
        if ($pid !== -1) {
304
            $pid = max(intval($pid), 0);
305
            $where = ' AND '.$table.'.pid='.$pid;
306
        }
307
        // Get index_name from database.
308
        $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
309
            $table.'.index_name AS index_name',
310
            $table,
311
            $table.'.uid='.$uid
312
                .$where
313
                .self::whereClause($table),
314
            '',
315
            '',
316
            '1'
317
        );
318
        if ($GLOBALS['TYPO3_DB']->sql_num_rows($result) > 0) {
319
            $resArray = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result);
320
            return $resArray['index_name'];
321
        } else {
322
            self::devLog('No "index_name" with UID '.$uid.' and PID '.$pid.' found in table "'.$table.'"', DEVLOG_SEVERITY_WARNING);
323
            return '';
324
        }
325
    }
326
327
    /**
328
     * Get language name from ISO code
329
     *
330
     * @access public
331
     *
332
     * @param string $code: ISO 639-1 or ISO 639-2/B language code
333
     *
334
     * @return string Localized full name of language or unchanged input
335
     */
336
    public static function getLanguageName($code) {
337
        // Analyze code and set appropriate ISO table.
338
        $isoCode = strtolower(trim($code));
339
        if (preg_match('/^[a-z]{3}$/', $isoCode)) {
340
            $file = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath(self::$extKey).'Resources/Private/Data/iso-639-2b.xml';
341
        } elseif (preg_match('/^[a-z]{2}$/', $isoCode)) {
342
            $file = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath(self::$extKey).'Resources/Private/Data/iso-639-1.xml';
343
        } else {
344
            // No ISO code, return unchanged.
345
            return $code;
346
        }
347
        // Load ISO table and get localized full name of language.
348
        if (TYPO3_MODE === 'FE') {
0 ignored issues
show
introduced by
The condition Kitodo\Dlf\Common\TYPO3_MODE === 'FE' is always false.
Loading history...
349
            $iso639 = $GLOBALS['TSFE']->readLLfile($file);
350
            if (!empty($iso639['default'][$isoCode])) {
351
                $lang = $GLOBALS['TSFE']->getLLL($isoCode, $iso639);
352
            }
353
        } elseif (TYPO3_MODE === 'BE') {
0 ignored issues
show
introduced by
The condition Kitodo\Dlf\Common\TYPO3_MODE === 'BE' is always true.
Loading history...
354
            $iso639 = $GLOBALS['LANG']->includeLLFile($file, FALSE, TRUE);
355
            if (!empty($iso639['default'][$isoCode])) {
356
                $lang = $GLOBALS['LANG']->getLLL($isoCode, $iso639, FALSE);
357
            }
358
        } else {
359
            self::devLog('Unexpected TYPO3_MODE "'.TYPO3_MODE.'"', DEVLOG_SEVERITY_ERROR);
360
            return $code;
361
        }
362
        if (!empty($lang)) {
363
            return $lang;
364
        } else {
365
            self::devLog('Language code "'.$code.'" not found in ISO-639 table', DEVLOG_SEVERITY_NOTICE);
366
            return $code;
367
        }
368
    }
369
370
    /**
371
     * Wrapper function for getting localized messages in frontend and backend
372
     *
373
     * @access public
374
     *
375
     * @param string $key: The locallang key to translate
376
     * @param boolean $hsc: Should the result be htmlspecialchar()'ed?
377
     * @param string $default: Default return value if no translation is available
378
     *
379
     * @return string The translated string or the given key on failure
380
     */
381
    public static function getMessage($key, $hsc = FALSE, $default = '') {
382
        // Set initial output to default value.
383
        $translated = (string) $default;
384
        // Load common messages file.
385
        if (empty(self::$messages)) {
386
            $file = \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::extPath(self::$extKey, 'Resources/Private/Language/FlashMessages.xml');
387
            if (TYPO3_MODE === 'FE') {
0 ignored issues
show
introduced by
The condition Kitodo\Dlf\Common\TYPO3_MODE === 'FE' is always false.
Loading history...
388
                self::$messages = $GLOBALS['TSFE']->readLLfile($file);
389
            } elseif (TYPO3_MODE === 'BE') {
0 ignored issues
show
introduced by
The condition Kitodo\Dlf\Common\TYPO3_MODE === 'BE' is always true.
Loading history...
390
                self::$messages = $GLOBALS['LANG']->includeLLFile($file, FALSE, TRUE);
391
            } else {
392
                self::devLog('Unexpected TYPO3_MODE "'.TYPO3_MODE.'"', DEVLOG_SEVERITY_ERROR);
393
            }
394
        }
395
        // Get translation.
396
        if (!empty(self::$messages['default'][$key])) {
397
            if (TYPO3_MODE === 'FE') {
0 ignored issues
show
introduced by
The condition Kitodo\Dlf\Common\TYPO3_MODE === 'FE' is always false.
Loading history...
398
                $translated = $GLOBALS['TSFE']->getLLL($key, self::$messages);
399
            } elseif (TYPO3_MODE === 'BE') {
0 ignored issues
show
introduced by
The condition Kitodo\Dlf\Common\TYPO3_MODE === 'BE' is always true.
Loading history...
400
                $translated = $GLOBALS['LANG']->getLLL($key, self::$messages, FALSE);
401
            } else {
402
                self::devLog('Unexpected TYPO3_MODE "'.TYPO3_MODE.'"', DEVLOG_SEVERITY_ERROR);
403
            }
404
        }
405
        // Escape HTML characters if applicable.
406
        if ($hsc) {
407
            $translated = htmlspecialchars($translated);
408
        }
409
        return $translated;
410
    }
411
412
    /**
413
     * Get the UID for a given "index_name"
414
     *
415
     * @access public
416
     *
417
     * @param integer $index_name: The index_name of the record
418
     * @param string $table: Get the "index_name" from this table
419
     * @param integer $pid: Get the "index_name" from this page
420
     *
421
     * @return string "uid" for the given index_name
422
     */
423
    public static function getUidFromIndexName($index_name, $table, $pid = -1) {
424
        if (!$index_name
425
            || !in_array($table, ['tx_dlf_collections', 'tx_dlf_libraries', 'tx_dlf_metadata', 'tx_dlf_structures', 'tx_dlf_solrcores'])) {
426
            self::devLog('Invalid UID '.$index_name.' or table "'.$table.'"', DEVLOG_SEVERITY_ERROR);
427
            return '';
428
        }
429
        $where = '';
430
        // Should we check for a specific PID, too?
431
        if ($pid !== -1) {
432
            $pid = max(intval($pid), 0);
433
            $where = ' AND '.$table.'.pid='.$pid;
434
        }
435
        // Get index_name from database.
436
        $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
437
            $table.'.uid AS uid',
438
            $table,
439
            $table.'.index_name="'.$index_name.'"'
440
                .$where
441
                .self::whereClause($table),
442
            '',
443
            '',
444
            '1'
445
        );
446
        if ($GLOBALS['TYPO3_DB']->sql_num_rows($result) > 0) {
447
            $resArray = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result);
448
            return $resArray['uid'];
449
        } else {
450
            self::devLog('No UID for given index_name "'.$index_name.'" and PID '.$pid.' found in table "'.$table.'"', DEVLOG_SEVERITY_WARNING);
451
            return '';
452
        }
453
    }
454
455
    /**
456
     * Get the URN of an object
457
     * @see http://www.persistent-identifier.de/?link=316
458
     *
459
     * @access public
460
     *
461
     * @param string $base: The namespace and base URN
462
     * @param string $id: The object's identifier
463
     *
464
     * @return string Uniform Resource Name as string
465
     */
466
    public static function getURN($base, $id) {
467
        $concordance = [
468
            '0' => 1,
469
            '1' => 2,
470
            '2' => 3,
471
            '3' => 4,
472
            '4' => 5,
473
            '5' => 6,
474
            '6' => 7,
475
            '7' => 8,
476
            '8' => 9,
477
            '9' => 41,
478
            'a' => 18,
479
            'b' => 14,
480
            'c' => 19,
481
            'd' => 15,
482
            'e' => 16,
483
            'f' => 21,
484
            'g' => 22,
485
            'h' => 23,
486
            'i' => 24,
487
            'j' => 25,
488
            'k' => 42,
489
            'l' => 26,
490
            'm' => 27,
491
            'n' => 13,
492
            'o' => 28,
493
            'p' => 29,
494
            'q' => 31,
495
            'r' => 12,
496
            's' => 32,
497
            't' => 33,
498
            'u' => 11,
499
            'v' => 34,
500
            'w' => 35,
501
            'x' => 36,
502
            'y' => 37,
503
            'z' => 38,
504
            '-' => 39,
505
            ':' => 17,
506
        ];
507
        $urn = strtolower($base.$id);
508
        if (preg_match('/[^a-z0-9:-]/', $urn)) {
509
            self::devLog('Invalid chars in given parameters', DEVLOG_SEVERITY_WARNING);
510
            return '';
511
        }
512
        $digits = '';
513
        for ($i = 0, $j = strlen($urn); $i < $j; $i++) {
514
            $digits .= $concordance[substr($urn, $i, 1)];
515
        }
516
        $checksum = 0;
517
        for ($i = 0, $j = strlen($digits); $i < $j; $i++) {
518
            $checksum += ($i + 1) * intval(substr($digits, $i, 1));
519
        }
520
        $checksum = substr(intval($checksum / intval(substr($digits, -1, 1))), -1, 1);
521
        return $base.$id.$checksum;
522
    }
523
524
    /**
525
     * Check if given ID is a valid Pica Production Number (PPN)
526
     *
527
     * @access public
528
     *
529
     * @param string $id: The identifier to check
530
     *
531
     * @return boolean Is $id a valid PPN?
532
     */
533
    public static function isPPN($id) {
534
        return self::checkIdentifier($id, 'PPN');
535
    }
536
537
    /**
538
     * Load value from user's session.
539
     *
540
     * @access public
541
     *
542
     * @param string $key: Session data key for retrieval
543
     *
544
     * @return mixed Session value for given key or NULL on failure
545
     */
546
    public static function loadFromSession($key) {
547
        // Cast to string for security reasons.
548
        $key = (string) $key;
549
        if (!$key) {
550
            self::devLog('Invalid key "'.$key.'" for session data retrieval', DEVLOG_SEVERITY_WARNING);
551
            return;
552
        }
553
        // Get the session data.
554
        if (TYPO3_MODE === 'FE') {
0 ignored issues
show
introduced by
The condition Kitodo\Dlf\Common\TYPO3_MODE === 'FE' is always false.
Loading history...
555
            return $GLOBALS['TSFE']->fe_user->getKey('ses', $key);
556
        } elseif (TYPO3_MODE === 'BE') {
0 ignored issues
show
introduced by
The condition Kitodo\Dlf\Common\TYPO3_MODE === 'BE' is always true.
Loading history...
557
            return $GLOBALS['BE_USER']->getSessionData($key);
558
        } else {
559
            self::devLog('Unexpected TYPO3_MODE "'.TYPO3_MODE.'"', DEVLOG_SEVERITY_ERROR);
560
            return;
561
        }
562
    }
563
564
    /**
565
     * Process a data and/or command map with TYPO3 core engine as admin.
566
     *
567
     * @access public
568
     *
569
     * @param array $data: Data map
570
     * @param array $cmd: Command map
571
     * @param boolean $reverseOrder: Should the data map be reversed?
572
     * @param boolean $cmdFirst: Should the command map be processed first?
573
     *
574
     * @return array Array of substituted "NEW..." identifiers and their actual UIDs.
575
     */
576
    public static function processDBasAdmin(array $data = [], array $cmd = [], $reverseOrder = FALSE, $cmdFirst = FALSE) {
577
        if (TYPO3_MODE === 'BE'
578
            && $GLOBALS['BE_USER']->isAdmin()) {
579
            // Instantiate TYPO3 core engine.
580
            $dataHandler = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\DataHandling\DataHandler::class);
581
            // Load data and command arrays.
582
            $dataHandler->start($data, $cmd);
583
            // Process command map first if default order is reversed.
584
            if (!empty($cmd)
585
                && $cmdFirst) {
586
                $dataHandler->process_cmdmap();
587
            }
588
            // Process data map.
589
            if (!empty($data)) {
590
                $dataHandler->reverseOrder = $reverseOrder;
591
                $dataHandler->process_datamap();
592
            }
593
            // Process command map if processing order is not reversed.
594
            if (!empty($cmd)
595
                && !$cmdFirst) {
596
                $dataHandler->process_cmdmap();
597
            }
598
            return $dataHandler->substNEWwithIDs;
599
        } else {
600
            self::devLog('Current backend user has no admin privileges', DEVLOG_SEVERITY_ERROR);
601
            return [];
602
        }
603
    }
604
605
    /**
606
     * Fetches and renders all available flash messages from the queue.
607
     *
608
     * @access public
609
     *
610
     * @param string $queue: The queue's unique identifier
611
     *
612
     * @return string All flash messages in the queue rendered as HTML.
613
     */
614
    public static function renderFlashMessages($queue = 'kitodo.default.flashMessages') {
615
        $flashMessageService = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Core\Messaging\FlashMessageService::class);
616
        $flashMessageQueue = $flashMessageService->getMessageQueueByIdentifier($queue);
617
        // \TYPO3\CMS\Core\Messaging\FlashMessage::getMessageAsMarkup() uses htmlspecialchars()
618
        // on all messages, but we have messages with HTML tags. Therefore we copy the official
619
        // implementation and remove the htmlspecialchars() call on the message body.
620
        $content = '';
621
        $flashMessages = $flashMessageQueue->getAllMessagesAndFlush();
622
        if (!empty($flashMessages)) {
623
            $content .= '<div class="typo3-messages">';
624
            foreach ($flashMessages as $flashMessage) {
625
                $messageTitle = $flashMessage->getTitle();
626
                $markup = [];
627
                $markup[] = '<div class="alert '.htmlspecialchars($flashMessage->getClass()).'">';
628
                $markup[] = '    <div class="media">';
629
                $markup[] = '        <div class="media-left">';
630
                $markup[] = '            <span class="fa-stack fa-lg">';
631
                $markup[] = '                <i class="fa fa-circle fa-stack-2x"></i>';
632
                $markup[] = '                <i class="fa fa-'.htmlspecialchars($flashMessage->getIconName()).' fa-stack-1x"></i>';
633
                $markup[] = '            </span>';
634
                $markup[] = '        </div>';
635
                $markup[] = '        <div class="media-body">';
636
                if (!empty($messageTitle)) {
637
                    $markup[] = '            <h4 class="alert-title">'.htmlspecialchars($messageTitle).'</h4>';
638
                }
639
                $markup[] = '            <p class="alert-message">'.$flashMessage->getMessage().'</p>'; // Removed htmlspecialchars() here.
640
                $markup[] = '        </div>';
641
                $markup[] = '    </div>';
642
                $markup[] = '</div>';
643
                $content .= implode('', $markup);
644
            }
645
            $content .= '</div>';
646
        }
647
        return $content;
648
    }
649
650
    /**
651
     * Save given value to user's session.
652
     *
653
     * @access public
654
     *
655
     * @param mixed $value: Value to save
656
     * @param string $key: Session data key for saving
657
     *
658
     * @return boolean TRUE on success, FALSE on failure
659
     */
660
    public static function saveToSession($value, $key) {
661
        // Cast to string for security reasons.
662
        $key = (string) $key;
663
        if (!$key) {
664
            self::devLog('Invalid key "'.$key.'" for session data saving', DEVLOG_SEVERITY_WARNING);
665
            return FALSE;
666
        }
667
        // Save value in session data.
668
        if (TYPO3_MODE === 'FE') {
0 ignored issues
show
introduced by
The condition Kitodo\Dlf\Common\TYPO3_MODE === 'FE' is always false.
Loading history...
669
            $GLOBALS['TSFE']->fe_user->setKey('ses', $key, $value);
670
            $GLOBALS['TSFE']->fe_user->storeSessionData();
671
            return TRUE;
672
        } elseif (TYPO3_MODE === 'BE') {
0 ignored issues
show
introduced by
The condition Kitodo\Dlf\Common\TYPO3_MODE === 'BE' is always true.
Loading history...
673
            $GLOBALS['BE_USER']->setAndSaveSessionData($key, $value);
674
            return TRUE;
675
        } else {
676
            self::devLog('Unexpected TYPO3_MODE "'.TYPO3_MODE.'"', DEVLOG_SEVERITY_ERROR);
677
            return FALSE;
678
        }
679
    }
680
681
    /**
682
     * This translates an internal "index_name"
683
     *
684
     * @access public
685
     *
686
     * @param string $index_name: The internal "index_name" to translate
687
     * @param string $table: Get the translation from this table
688
     * @param string $pid: Get the translation from this page
689
     *
690
     * @return string Localized label for $index_name
691
     */
692
    public static function translate($index_name, $table, $pid) {
693
        // Load labels into static variable for future use.
694
        static $labels = [];
695
        // Sanitize input.
696
        $pid = max(intval($pid), 0);
697
        if (!$pid) {
698
            self::devLog('Invalid PID '.$pid.' for translation', DEVLOG_SEVERITY_WARNING);
699
            return $index_name;
700
        }
701
        // Check if "index_name" is an UID.
702
        if (\TYPO3\CMS\Core\Utility\MathUtility::canBeInterpretedAsInteger($index_name)) {
703
            $index_name = self::getIndexNameFromUid($index_name, $table, $pid);
704
        }
705
        /* $labels already contains the translated content element, but with the index_name of the translated content element itself
706
         * and not with the $index_name of the original that we receive here. So we have to determine the index_name of the
707
         * associated translated content element. E.g. $labels['title0'] != $index_name = title. */
708
        // First fetch the uid of the received index_name
709
        $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
710
            'uid, l18n_parent',
711
            $table,
712
            'pid='.$pid
713
                .' AND index_name="'.$index_name.'"'
714
                .self::whereClause($table, TRUE),
715
            '',
716
            '',
717
            ''
718
        );
719
        if ($GLOBALS['TYPO3_DB']->sql_num_rows($result) > 0) {
720
            // Now we use the uid of the l18_parent to fetch the index_name of the translated content element.
721
            $resArray = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result);
722
            $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
723
                'index_name',
724
                $table,
725
                'pid='.$pid
726
                    .' AND uid='.$resArray['l18n_parent']
727
                    .' AND sys_language_uid='.intval($GLOBALS['TSFE']->sys_language_content)
728
                    .self::whereClause($table, TRUE),
729
                '',
730
                '',
731
                ''
732
            );
733
            if ($GLOBALS['TYPO3_DB']->sql_num_rows($result) > 0) {
734
                // If there is an translated content element, overwrite the received $index_name.
735
                $resArray = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result);
736
                $index_name = $resArray['index_name'];
737
            }
738
        }
739
        // Check if we already got a translation.
740
        if (empty($labels[$table][$pid][$GLOBALS['TSFE']->sys_language_content][$index_name])) {
741
            // Check if this table is allowed for translation.
742
            if (in_array($table, ['tx_dlf_collections', 'tx_dlf_libraries', 'tx_dlf_metadata', 'tx_dlf_structures'])) {
743
                $additionalWhere = ' AND sys_language_uid IN (-1,0)';
744
                if ($GLOBALS['TSFE']->sys_language_content > 0) {
745
                    $additionalWhere = ' AND (sys_language_uid IN (-1,0) OR (sys_language_uid='.intval($GLOBALS['TSFE']->sys_language_content).' AND l18n_parent=0))';
746
                }
747
                // Get labels from database.
748
                $result = $GLOBALS['TYPO3_DB']->exec_SELECTquery(
749
                    '*',
750
                    $table,
751
                    'pid='.$pid
752
                        .$additionalWhere
753
                        .self::whereClause($table, TRUE),
754
                    '',
755
                    '',
756
                    ''
757
                );
758
                if ($GLOBALS['TYPO3_DB']->sql_num_rows($result) > 0) {
759
                    while ($resArray = $GLOBALS['TYPO3_DB']->sql_fetch_assoc($result)) {
760
                        // Overlay localized labels if available.
761
                        if ($GLOBALS['TSFE']->sys_language_content > 0) {
762
                            $resArray = $GLOBALS['TSFE']->sys_page->getRecordOverlay($table, $resArray, $GLOBALS['TSFE']->sys_language_content, $GLOBALS['TSFE']->sys_language_contentOL);
763
                        }
764
                        if ($resArray) {
765
                            $labels[$table][$pid][$GLOBALS['TSFE']->sys_language_content][$resArray['index_name']] = $resArray['label'];
766
                        }
767
                    }
768
                } else {
769
                    self::devLog('No translation with PID '.$pid.' available in table "'.$table.'" or translation not accessible', DEVLOG_SEVERITY_NOTICE);
770
                }
771
            } else {
772
                self::devLog('No translations available for table "'.$table.'"', DEVLOG_SEVERITY_WARNING);
773
            }
774
        }
775
        if (!empty($labels[$table][$pid][$GLOBALS['TSFE']->sys_language_content][$index_name])) {
776
            return $labels[$table][$pid][$GLOBALS['TSFE']->sys_language_content][$index_name];
777
        } else {
778
            return $index_name;
779
        }
780
    }
781
782
    /**
783
     * This returns the additional WHERE clause of a table based on its TCA configuration
784
     *
785
     * @access public
786
     *
787
     * @param string $table: Table name as defined in TCA
788
     * @param boolean $showHidden: Ignore the hidden flag?
789
     *
790
     * @return string Additional WHERE clause
791
     */
792
    public static function whereClause($table, $showHidden = FALSE) {
793
        if (TYPO3_MODE === 'FE') {
0 ignored issues
show
introduced by
The condition Kitodo\Dlf\Common\TYPO3_MODE === 'FE' is always false.
Loading history...
794
            // Table "tx_dlf_formats" always has PID 0.
795
            if ($table == 'tx_dlf_formats') {
796
                return \TYPO3\CMS\Backend\Utility\BackendUtility::deleteClause($table);
797
            }
798
            // Should we ignore the record's hidden flag?
799
            $ignoreHide = -1;
800
            if ($showHidden) {
801
                $ignoreHide = 1;
802
            }
803
            // $GLOBALS['TSFE']->sys_page is not always available in frontend.
804
            if (is_object($GLOBALS['TSFE']->sys_page)) {
805
                return $GLOBALS['TSFE']->sys_page->enableFields($table, $ignoreHide);
806
            } else {
807
                $pageRepository = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance(\TYPO3\CMS\Frontend\Page\PageRepository::class);
808
                $GLOBALS['TSFE']->includeTCA();
809
                return $pageRepository->enableFields($table, $ignoreHide);
810
            }
811
        } elseif (TYPO3_MODE === 'BE') {
0 ignored issues
show
introduced by
The condition Kitodo\Dlf\Common\TYPO3_MODE === 'BE' is always true.
Loading history...
812
            return \TYPO3\CMS\Backend\Utility\BackendUtility::deleteClause($table);
813
        } else {
814
            self::devLog('Unexpected TYPO3_MODE "'.TYPO3_MODE.'"', DEVLOG_SEVERITY_ERROR);
815
            return ' AND 1=-1';
816
        }
817
    }
818
819
    /**
820
     * This is a static class, thus no instances should be created
821
     *
822
     * @access private
823
     */
824
    private function __construct() {}
825
}
826