Skip to content

Commit e54c693

Browse files
authored
Merge pull request #135 from johanib/feature/fix1
Add support for parsing duplicated segments, closes #134
2 parents fe5d6b6 + 749c2e9 commit e54c693

File tree

4 files changed

+117
-14
lines changed

4 files changed

+117
-14
lines changed

src/EDI/Reader.php

+52-13
Original file line numberDiff line numberDiff line change
@@ -174,10 +174,9 @@ public function readEdiDataValueReq($filter, int $l1, $l2 = false)
174174
* @param bool $required if required, but no exist, register error
175175
* @return string|null
176176
*/
177-
public function readEdiDataValue($filter, int $l1, $l2 = false, bool $required = false)
177+
public function readEdiDataValue($filter, int $l1, $l2 = false, bool $required = false, int $offset = null)
178178
{
179-
$segment = false;
180-
$segment_count = 0;
179+
$found_segments = [];
181180
$segment_name = $filter;
182181
$filter_elements = false;
183182
if (\is_array($filter)) {
@@ -221,24 +220,23 @@ public function readEdiDataValue($filter, int $l1, $l2 = false, bool $required =
221220
continue;
222221
}
223222
}
224-
$segment = $edi_row;
225-
$segment_count++;
223+
$found_segments[] = $edi_row;
226224
}
227225
}
228226

229-
// no segment found
230-
if (! $segment) {
231-
if ($required) {
232-
$this->errors[] = 'Segment "'.$segment_name.'" no exist';
227+
try {
228+
if ($offset !== null) {
229+
$segment = $this->getOffsetSegmentFromResult($found_segments, $offset, $required, $segment_name);
230+
} else {
231+
$segment = $this->getSegmentFromResult($found_segments, $required, $segment_name);
233232
}
233+
} catch (ReaderException $e) {
234+
$this->errors[] = $e->getMessage();
234235

235236
return null;
236237
}
237238

238-
// found more than one segment - error
239-
if ($segment_count > 1) {
240-
$this->errors[] = 'Segment "'.$segment_name.'" is ambiguous';
241-
239+
if ($segment === false) {
242240
return null;
243241
}
244242

@@ -561,4 +559,45 @@ private static function unwrap($string)
561559
}
562560
}
563561
}
562+
563+
/**
564+
* @param array $matchingSegments
565+
* @param int $offset
566+
* @param bool $required
567+
* @param mixed $segment_name
568+
*
569+
* @return false|mixed
570+
*/
571+
private function getOffsetSegmentFromResult(array $matchingSegments, int $offset, bool $required, mixed $segment_name): mixed
572+
{
573+
if (isset($matchingSegments[$offset])) {
574+
return $matchingSegments[$offset];
575+
}
576+
577+
if ($required) {
578+
throw new ReaderException('Segment "' . $segment_name . '" does not exist at offset "' . $offset . '"');
579+
}
580+
581+
return false;
582+
}
583+
584+
/**
585+
* @param array $matchingSegments
586+
* @param mixed $segment_name
587+
*
588+
* @return false|mixed
589+
*/
590+
private function getSegmentFromResult(array $matchingSegments, bool $required, mixed $segment_name): mixed
591+
{
592+
// found more than one segment - error
593+
if (count($matchingSegments) > 1) {
594+
throw new ReaderException('Segment "' . $segment_name . '" is ambiguous');
595+
}
596+
597+
if ($required && !isset($matchingSegments[0])) {
598+
throw new ReaderException('Segment "' . $segment_name . '" no exist');
599+
}
600+
601+
return $matchingSegments[0] ?? false;
602+
}
564603
}

src/EDI/ReaderException.php

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace EDI;
6+
7+
use RuntimeException;
8+
9+
class ReaderException extends RuntimeException
10+
{
11+
}

tests/EDITest/ReaderTest.php

+44-1
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
namespace EDITest;
66

7-
use EDI\Reader;
87
use EDI\Parser;
8+
use EDI\Reader;
99

1010
/**
1111
* @internal
@@ -102,4 +102,47 @@ public function testSplitMultiMessage()
102102
$messageType = $r->readUNHmessageType();
103103
static::assertSame('PAORES', $messageType);
104104
}
105+
106+
public function testReadsMultiSegmentsByOffset()
107+
{
108+
$p = new Parser();
109+
$p->setStrict(true);
110+
$p->load(__DIR__ . '/../files/example_multiline.edi');
111+
$r = new Reader($p);
112+
113+
$lines = [];
114+
for ($i = 0; $i < 10; $i++) {
115+
$line = $r->readEdiDataValue(['FTX', [1 => 'AAI']], 4, false, false, $i);
116+
if ($line !== null) {
117+
$lines[] = $line;
118+
}
119+
}
120+
121+
self::assertSame(
122+
[
123+
0 => [
124+
0 => 'PLS ENSURE TO TAKE OUR APPROVAL PRIOR STUFFING ANY NON HAZ CHEMICA',
125+
1 => 'LS',
126+
],
127+
1 => [
128+
0 => 'THE SHIPPER SHALL NOT BE RESPONSIBLE FOR ANY COSTS/DELAYS OCCUR',
129+
1 => 'DUE TO INTERVENTION OF CUSTOMS.',
130+
],
131+
132+
],
133+
$lines
134+
);
135+
}
136+
137+
public function testAddsErrorOnMissingRequiredOffest()
138+
{
139+
$p = new Parser();
140+
$p->setStrict(true);
141+
$p->load(__DIR__ . '/../files/example_multiline.edi');
142+
$r = new Reader($p);
143+
$line = $r->readEdiDataValue(['FTX', [1 => 'AAI']], 4, false, true, 99);
144+
self::assertSame(['Segment "FTX" does not exist at offset "99"'], $r->errors());
145+
self::assertNull($line);
146+
}
147+
105148
}

tests/files/example_multiline.edi

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
UNB+UNOB:2+CARRIER+RECEIVER-ID+999818:999+251'
2+
UNH+0001+IFTMBC:D:00B:UN'
3+
BGM+770+AAA99970929+9'
4+
TSR+30+2:::2'
5+
FTX+AAI+++PLS ENSURE TO TAKE OUR APPROVAL PRIOR STUFFING ANY NON HAZ CHEMICA:LS'
6+
FTX+ABV+++THIS BOOKING CONFIRMATION IS SUBJECT TO SEALING'
7+
FTX+AAI+++THE SHIPPER SHALL NOT BE RESPONSIBLE FOR ANY COSTS/DELAYS OCCUR
8+
:DUE TO INTERVENTION OF CUSTOMS.'
9+
UNT+10+0001'
10+
UNZ+1+251'

0 commit comments

Comments
 (0)