MoParser::parseIntoCache()   B
last analyzed

Complexity

Conditions 7
Paths 24

Size

Total Lines 49
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 28
CRAP Score 7

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 31
c 2
b 0
f 0
dl 0
loc 49
ccs 28
cts 28
cp 1
rs 8.4906
cc 7
nc 24
nop 1
crap 7
1
<?php
2
3
declare(strict_types=1);
4
5
namespace PhpMyAdmin\MoTranslator;
6
7
use PhpMyAdmin\MoTranslator\Cache\CacheInterface;
8
9
use function is_readable;
10
11
final class MoParser
12
{
13
    /**
14
     * None error.
15
     */
16
    public const ERROR_NONE = 0;
17
18
    /**
19
     * File does not exist.
20
     */
21
    public const ERROR_DOES_NOT_EXIST = 1;
22
23
    /**
24
     * File has bad magic number.
25
     */
26
    public const ERROR_BAD_MAGIC = 2;
27
28
    /**
29
     * Error while reading file, probably too short.
30
     */
31
    public const ERROR_READING = 3;
32
33
    /**
34
     * Big endian mo file magic bytes.
35
     */
36
    public const MAGIC_BE = "\x95\x04\x12\xde";
37
38
    /**
39
     * Little endian mo file magic bytes.
40
     */
41
    public const MAGIC_LE = "\xde\x12\x04\x95";
42
43
    /**
44
     * Parse error code (0 if no error).
45
     */
46
    public int $error = self::ERROR_NONE;
47
48
    public function __construct(private readonly string|null $filename = null)
49
    {
50 819
    }
51
52 819
    /**
53 117
     * Parses .mo file and stores results to `$cache`
54
     */
55
    public function parseIntoCache(CacheInterface $cache): void
56
    {
57
        if ($this->filename === null) {
58 798
            return;
59
        }
60 798
61 28
        if (! is_readable($this->filename)) {
62
            $this->error = self::ERROR_DOES_NOT_EXIST;
63
64 784
            return;
65 224
        }
66
67 224
        $stream = new StringReader($this->filename);
68
69
        try {
70 560
            $magic = $stream->read(0, 4);
71
            if ($magic === self::MAGIC_LE) {
72
                $unpack = 'V';
73 560
            } elseif ($magic === self::MAGIC_BE) {
74 546
                $unpack = 'N';
75 434
            } else {
76 112
                $this->error = self::ERROR_BAD_MAGIC;
77 98
78
                return;
79 14
            }
80
81 14
            /* Parse header */
82
            $total = $stream->readint($unpack, 8);
83
            $originals = $stream->readint($unpack, 12);
84
            $translations = $stream->readint($unpack, 16);
85 532
86 532
            /* get original and translations tables */
87 490
            $totalTimesTwo = (int) ($total * 2);// Fix for issue #36 on ARM
88
            $tableOriginals = $stream->readintarray($unpack, $originals, $totalTimesTwo);
89
            $tableTranslations = $stream->readintarray($unpack, $translations, $totalTimesTwo);
90 490
91 490
            /* read all strings to the cache */
92 476
            for ($i = 0; $i < $total; ++$i) {
93
                $iTimesTwo = $i * 2;
94
                $iPlusOne = $iTimesTwo + 1;
95 476
                $iPlusTwo = $iTimesTwo + 2;
96 476
                $original = $stream->read($tableOriginals[$iPlusTwo], $tableOriginals[$iPlusOne]);
97 476
                $translation = $stream->read($tableTranslations[$iPlusTwo], $tableTranslations[$iPlusOne]);
98 476
                $cache->set($original, $translation);
99 476
            }
100 476
        } catch (ReaderException) {
101 476
            $this->error = self::ERROR_READING;
102
103 70
            return;
104 70
        }
105
    }
106
}
107