Skip to content

Commit cc710d5

Browse files
authored
Merge pull request #16 from mennodekker/master
Partial fix #15 - labels no longer trimmed for multibyte chars
2 parents d21727c + 3fec102 commit cc710d5

File tree

3 files changed

+65
-4
lines changed

3 files changed

+65
-4
lines changed

src/Sav/Record/Variable.php

+12-3
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,17 @@ public function write(Buffer $buffer)
140140
$buffer->writeString($this->name, 8);
141141

142142
if ($hasLabel) {
143+
// Maxlength is 255 bytes, since we write utf8 a char can be multiple bytes
143144
$labelLength = min(mb_strlen($this->label), 255);
144-
$buffer->writeInt($labelLength);
145-
$buffer->writeString($this->label, Utils::roundUp($labelLength, 4));
145+
$label = mb_substr($this->label, 0, $labelLength);
146+
$labelLengthBytes = mb_strlen($label, '8bit');
147+
while ($labelLengthBytes > 255) {
148+
// Strip one char, can be multiple bytes
149+
$label = mb_substr($this->label, 0, -1);
150+
$labelLengthBytes = mb_strlen($label, '8bit');
151+
}
152+
$buffer->writeInt($labelLengthBytes);
153+
$buffer->writeString($label, Utils::roundUp($labelLengthBytes, 4));
146154
}
147155

148156
// TODO: test
@@ -156,7 +164,8 @@ public function write(Buffer $buffer)
156164
}
157165
}
158166

159-
$this->writeBlank($buffer, $seg0width);
167+
// I think we don't need an empty record
168+
//$this->writeBlank($buffer, $seg0width);
160169

161170
// Write additional segments for very long string variables.
162171
if (self::isVeryLong($this->width)) {

tests/SavRandomReadWriteTest.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,8 @@ public function testWriteRead($data)
126126
// )
127127
// );
128128
// }
129-
$index += $var['width'] > 0 ? Utils::widthToOcts($var['width']) : 1;
129+
//$index += $var['width'] > 0 ? Utils::widthToOcts($var['width']) : 1;
130+
$index++;
130131
}
131132

132133
// TODO: valueLabels

tests/WriteMultibyteTest.php

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
3+
namespace SPSS\Tests;
4+
5+
use SPSS\Sav\Reader;
6+
use SPSS\Sav\Writer;
7+
8+
class WriteMultibyteTest extends TestCase
9+
{
10+
11+
public function testMultiByteLabel()
12+
{
13+
$data = [
14+
'header' => [
15+
'prodName' => '@(#) IBM SPSS STATISTICS',
16+
'layoutCode' => 2,
17+
'creationDate' => date('d M y'),
18+
'creationTime' => date('H:i:s'),
19+
],
20+
'variables' => [
21+
[
22+
'name' => 'longname_longerthanexpected',
23+
'label' => 'Data zákończenia',
24+
'width' => 16,
25+
'format' => 1,
26+
],
27+
[
28+
'name' => 'ccc',
29+
'label' => '12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901233á',
30+
'format' => 5,
31+
'values' => [
32+
1 => 'Panel',
33+
],
34+
],
35+
],
36+
];
37+
$writer = new Writer($data);
38+
39+
$buffer = $writer->getBuffer();
40+
$buffer->rewind();
41+
42+
$reader = Reader::fromString($buffer->getStream())->read();
43+
44+
// Sort name
45+
$this->assertEquals($data['variables'][0]['label'], $reader->variables[0]->label);
46+
47+
// Long name
48+
$this->assertEquals(mb_substr($data['variables'][1]['label'], 0, -1), $reader->variables[1]->label);
49+
}
50+
51+
}

0 commit comments

Comments
 (0)