DBCRecord   A
last analyzed

Complexity

Total Complexity 15

Size/Duplication

Total Lines 122
Duplicated Lines 0 %

Test Coverage

Coverage 92.86%

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 50
c 4
b 0
f 0
dl 0
loc 122
ccs 39
cts 42
cp 0.9286
rs 10
wmc 15

2 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 16 3
C read() 0 53 12
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Wowstack\Dbc;
6
7
/**
8
 * Implements a single record within a DBC file.
9
 */
10
class DBCRecord
11
{
12
    /**
13
     * @var DBC
14
     */
15
    protected $dbcFile = null;
16
17
    /**
18
     * @var int
19
     */
20
    protected $position = 0;
21
22
    /**
23
     * @var int
24
     */
25
    protected $recordOffset = 0;
26
27
    /**
28
     * @var int
29
     */
30
    protected $recordSize = 0;
31
32
    /**
33
     * @var resource|bool
34
     */
35
    protected $fileHandle = null;
36
37
    /**
38
     * @var mixed
39
     */
40
    protected $data = null;
41
42
    /**
43
     * @var int
44
     */
45
    protected $identifier = 0;
46
47
    /**
48
     * Constructs a new DBC row.
49
     *
50
     * @param DBC $dbcFile
51
     * @param int $position
52
     */
53 5
    public function __construct(DBC $dbcFile, int $position)
54
    {
55 5
        $this->dbcFile = $dbcFile;
56 5
        $this->position = $position;
57
58 5
        $this->recordSize = $this->dbcFile->getRecordSize();
59 5
        $this->recordOffset = DBC::HEADER_SIZE + $this->position * $this->recordSize;
60 5
        $this->fileHandle = $this->dbcFile->getFileHandle();
61
62 5
        if (false === $this->fileHandle) {
63
            throw new DBCException('DBC file is not readable.');
64
        }
65
66 5
        fseek($this->fileHandle, $this->recordOffset);
0 ignored issues
show
Bug introduced by
It seems like $this->fileHandle can also be of type true; however, parameter $handle of fseek() does only seem to accept resource, 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

66
        fseek(/** @scrutinizer ignore-type */ $this->fileHandle, $this->recordOffset);
Loading history...
67 5
        if ($this->recordSize > 0) {
68 5
            $this->data = fread($this->fileHandle, $this->recordSize);
0 ignored issues
show
Bug introduced by
It seems like $this->fileHandle can also be of type true; however, parameter $handle of fread() does only seem to accept resource, 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

68
            $this->data = fread(/** @scrutinizer ignore-type */ $this->fileHandle, $this->recordSize);
Loading history...
69
        }
70 5
    }
71
72
    /**
73
     * Reads the current row into key/value array.
74
     *
75
     * @return array
76
     *
77
     * @throws DBCException
78
     */
79 4
    public function read(): array
80
    {
81 4
        $map = $this->dbcFile->getMap();
82 4
        if (empty($map)) {
83 1
            throw new DBCException('DBCRecord can not be read without a mapping');
84
        }
85
86 3
        $format = [];
87 3
        $strings = [];
88 3
        $foreignKeys = [];
89 3
        $fields = $map->getParsedFields();
90
91 3
        foreach ($fields as $fieldName => $fieldData) {
92 3
            $format[] = $fieldData['format'];
93 3
            if ('string' === $fieldData['type'] || 'localized_string' === $fieldData['type']) {
94 2
                $strings[] = $fieldName;
95
            }
96 3
            if ('foreign_key' === $fieldData['type']) {
97 3
                $foreignKeys[] = $fieldName;
98
            }
99
        }
100
101 3
        $format = implode('/', $format);
102 3
        $data = unpack($format, $this->data);
103
104
        // This ensure that string fields will be empty strings instead of 0.
105 3
        foreach ($strings as $string) {
106 2
            $stringPointer = $data[$string];
107 2
            if ($data[$string] > 0) {
108
                try {
109 2
                    $data[$string] = $this->dbcFile->getString($data[$string]);
110
                } catch (DBCException $dbcException) {
111
                    $data[$string] = '';
112 2
                    $this->dbcFile->addError('string', $this->position, $string, 'String pointer not found at offset '.$stringPointer);
0 ignored issues
show
Coding Style introduced by
Concat operator must be surrounded by a single space
Loading history...
Coding Style introduced by
This line exceeds maximum limit of 120 characters; contains 135 characters

Overly long lines are hard to read on any screen. Most code styles therefor impose a maximum limit on the number of characters in a line.

Loading history...
113
                }
114
            } else {
115 2
                $data[$string] = '';
116
            }
117
        }
118
119
        // This ensures fields containing references to other tables will be nulled
120
        // if they do not contain a valid reference.
121 3
        foreach ($foreignKeys as $foreignKey) {
122 1
            if ($data[$foreignKey] <= 0) {
123 1
                $data[$foreignKey] = null;
124
            }
125
        }
126
127
        $data = array_filter($data, function ($key) {
0 ignored issues
show
Bug introduced by
It seems like $data can also be of type false; however, parameter $input of array_filter() does only seem to accept array, 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

127
        $data = array_filter(/** @scrutinizer ignore-type */ $data, function ($key) {
Loading history...
128 3
            return false === strpos($key, '_checksum') && false === strpos($key, '_unused');
129 3
        }, ARRAY_FILTER_USE_KEY);
130
131 3
        return $data;
132
    }
133
}
134