Header::read()   A
last analyzed

Complexity

Conditions 5
Paths 3

Size

Total Lines 29
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 18
c 1
b 0
f 0
nc 3
nop 1
dl 0
loc 29
ccs 0
cts 22
cp 0
crap 30
rs 9.3554
1
<?php
2
3
namespace SPSS\Sav\Record;
4
5
use SPSS\Buffer;
6
use SPSS\Exception;
7
use SPSS\Sav\Record;
8
9
class Header extends Record
10
{
11
    const NORMAL_REC_TYPE = '$FL2';
12
    const ZLIB_REC_TYPE = '$FL3';
13
14
    /**
15
     * @var string Record type code,
16
     * either ‘$FL2’ for system files with uncompressed data or data compressed with simple bytecode compression,
17
     * or ‘$FL3’ for system files with ZLIB compressed data.
18
     * This is truly a character field that uses the character encoding as other strings.
19
     * Thus, in a file with an ASCII-based character encoding this field contains 24 46 4c 32 or 24 46 4c 33,
20
     * and in a file with an EBCDIC-based encoding this field contains 5b c6 d3 f2.
21
     * (No EBCDIC-based ZLIB-compressed files have been observed.)
22
     */
23
    public $recType = self::NORMAL_REC_TYPE;
24
25
    /**
26
     * @var string Product identification string.
27
     * This always begins with the characters ‘@(#) SPSS DATA FILE’.
28
     * The string is truncated if it would be longer than 60 characters;
29
     * otherwise it is padded on the right with spaces.
30
     */
31
    public $prodName = '@(#) SPSS DATA FILE';
32
33
    /**
34
     * @var int Normally set to 2, although a few system files have been spotted in the wild with a value of 3 here.
35
     */
36
    public $layoutCode = 2;
37
38
    /**
39
     * @var int Number of data elements per case.
40
     * This is the number of variables, except that long string variables add extra data elements (one for every 8 characters after the first 8).
41
     * Further, system files written by some systems set this value to -1.
42
     * In general, it is unsafe for systems reading system files to rely upon this value.
43
     */
44
    public $nominalCaseSize = 0;
45
46
    /**
47
     * @var int
48
     * Set to
49
     * 0 if the data in the file is not compressed,
50
     * 1 if the data is compressed with simple bytecode compression,
51
     * 2 if the data is ZLIB compressed.
52
     * This field has value 2 if and only if recType is ‘$FL3’.
53
     */
54
    public $compression = 1;
55
56
    /**
57
     * @var int If one of the variables in the data set is used as a weighting variable,
58
     * set to the dictionary index of that variable, plus 1 (see Dictionary Index).
59
     * Otherwise, set to 0.
60
     */
61
    public $weightIndex = 0;
62
63
    /**
64
     * @var int Set to the number of cases in the file if it is known, or -1 otherwise.
65
     * In the general case it is not possible to determine the number of cases that will be output to a system file at the time
66
     * that the header is written.
67
     * The way that this is dealt with is by writing the entire system file,
68
     * including the header, then seeking back to the beginning of the file and writing just the ncases field.
69
     * For files in which this is not valid, the seek operation fails.
70
     * In this case, ncases remains -1.
71
     */
72
    public $casesCount = -1;
73
74
    /**
75
     * @var int Compression bias, ordinarily set to 100.
76
     * Only integers between 1 - bias and 251 - bias can be compressed.
77
     * By assuming that its value is 100.
78
     */
79
    public $bias = 100;
80
81
    /**
82
     * @var string Date of creation of the system file, in ‘dd mmm yy’ format,
83
     * with the month as standard English abbreviations, using an initial capital letter and following with lowercase.
84
     * If the date is not available then this field is arbitrarily set to ‘01 Jan 70’.
85
     */
86
    public $creationDate = '01 Jan 70';
87
88
    /**
89
     * @var string Time of creation of the system file, in ‘hh:mm:ss’ format and using 24-hour time.
90
     * If the time is not available then this field is arbitrarily set to ‘00:00:00’.
91
     */
92
    public $creationTime = '00:00:00';
93
94
    /**
95
     * @var string File label declared by the user (64 chars).
96
     * Padded on the right with spaces.
97
     */
98
    public $fileLabel;
99
100
    /**
101
     * @param Buffer $buffer
102
     * @throws Exception
103
     */
104
    public function read(Buffer $buffer)
105
    {
106
        $this->recType = $buffer->readString(4);
0 ignored issues
show
Documentation Bug introduced by
It seems like $buffer->readString(4) can also be of type false. However, the property $recType is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
107
        if (! ($this->recType == self::NORMAL_REC_TYPE || $this->recType == self::ZLIB_REC_TYPE)) {
108
            throw new Exception('Read header error: this is not a valid SPSS file. Does not start with $FL2 or $FL3.');
109
        }
110
        $this->prodName = trim($buffer->readString(60));
0 ignored issues
show
Bug introduced by
It seems like $buffer->readString(60) can also be of type false; however, parameter $str of trim() does only seem to accept string, 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

110
        $this->prodName = trim(/** @scrutinizer ignore-type */ $buffer->readString(60));
Loading history...
111
        $this->layoutCode = $buffer->readInt();
112
113
        // layoutCode should be 2 or 3.
114
        // If not swap bytes and check again which would then indicate big-endian
115
        if ($this->layoutCode != 2 && $this->layoutCode != 3) {
116
            // try to flip to big-endian mode and read again
117
            $buffer->isBigEndian = true;
118
            $buffer->skip(-4);
119
            $this->layoutCode = $buffer->readInt();
120
        }
121
122
        $this->nominalCaseSize = $buffer->readInt();
123
        $this->compression = $buffer->readInt();
124
        $this->weightIndex = $buffer->readInt();
125
        $this->casesCount = $buffer->readInt();
126
        $this->bias = $buffer->readDouble();
127
        $this->creationDate = $buffer->readString(9);
0 ignored issues
show
Documentation Bug introduced by
It seems like $buffer->readString(9) can also be of type false. However, the property $creationDate is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
128
        $this->creationTime = $buffer->readString(8);
0 ignored issues
show
Documentation Bug introduced by
It seems like $buffer->readString(8) can also be of type false. However, the property $creationTime is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
129
        $this->fileLabel = trim($buffer->readString(64));
130
131
        // 3-byte padding to make the header a multiple of 32 bits in length.
132
        $buffer->skip(3);
133
    }
134
135
    /**
136
     * @param Buffer $buffer
137
     */
138
    public function write(Buffer $buffer)
139
    {
140
        $buffer->write($this->recType);
141
        $buffer->writeString($this->prodName, 60);
142
        $buffer->writeInt($this->layoutCode);
143
        $buffer->writeInt($this->nominalCaseSize);
144
        $buffer->writeInt($this->compression);
145
        $buffer->writeInt($this->weightIndex);
146
        $buffer->writeInt($this->casesCount);
147
        $buffer->writeDouble($this->bias);
148
        $buffer->writeString($this->creationDate, 9);
149
        $buffer->writeString($this->creationTime, 8);
150
        $buffer->writeString($this->fileLabel, 64);
151
        $buffer->writeNull(3);
152
    }
153
}
154