diff --git a/README.md b/README.md index fb7d151..f5e59f8 100644 --- a/README.md +++ b/README.md @@ -5,13 +5,13 @@ License

-**Important: "new Message()" is deprecated and could be removed in a future release. Use HL7 factory class instead. See documents below

+**Important: "new Message()" is deprecated and could be removed in a future release. Use HL7 factory class instead. See documents below**

Final releases for old PHP versions:
-> PHP 7.0/7.1 => [1.5.4](https://github.com/senaranya/HL7/tree/1.5.4)
-> PHP 7.2 => [2.0.2](https://github.com/senaranya/HL7/tree/2.0.2)
--> PHP 7.4 => [2.1.7](https://github.com/senaranya/HL7/tree/2.1.7)** --> PHP 8.1 => [3.1.7](https://github.com/senaranya/HL7/tree/3.1.7)** +-> PHP 7.4 => [2.1.7](https://github.com/senaranya/HL7/tree/2.1.7)
+-> PHP 8.1 => [3.1.7](https://github.com/senaranya/HL7/tree/3.1.7) ## Introduction @@ -24,19 +24,11 @@ composer require aranyasen/hl7 ``` ## Usage -### Import library -```php -// First, import classes from the library as needed... -use Aranyasen\HL7; // HL7 factory class -use Aranyasen\HL7\Message; // If Message is used -use Aranyasen\HL7\Segment; // If Segment is used -use Aranyasen\HL7\Segments\MSH; // If MSH is used -// ... and so on -``` ### Parsing ```php // Create a Message object from a HL7 string +use Aranyasen\HL7; $message = HL7::from("MSH|^~\\&|1|")->create(); $message = HL7::from("MSH|^~\\&|1|\rPID|||abcd|\r")->create(); // Creates Message object with two segments with \r as segment ending (\n can also be used) @@ -52,22 +44,27 @@ $message->getFirstSegmentInstance('ABC'); // Returns the first ABC segment. Same $message->hasSegment('ABC'); // return true or false based on whether PID is present in the $message object // Check if a message is empty -$message = HL7::create(); -$message->isempty(); // Returns true +$message = HL7::build()->create(); +$message->removeSegmentsByName('MSH') +$message->isEmpty(); // Returns true ``` ### Composing new messages ```php // The class `HL7` can be used to build HL7 object. It is a factory class with various helper methods to help build a hl7. -$message = HL7::build()->create(); // Creates an empty message - -// The HL7 factory class provides methods that can be chained together in a fluent fashion +$message = HL7::build()->create(); // Creates a Message containing MSH segment with default separators, version etc. +``` +#### Configuring HL7 messages +```php +// The HL7 factory class provides methods that can be chained together in a fluent fashion. These can be used to +// override the defaults $message = HL7::build() - ->withComponentSeparator('#') - ->withFieldSeparator('-') + ->withComponentSeparator('#') // Use # as the component separator instead of the default ^ + ->withFieldSeparator('-') // Use - as the field separator instead of the default | + ->withSegmentSeparator('\r\n') // Override segment separator + ->withHL7Version('2.3') // Use HL7 version 2.3 ->create(); ``` -#### Configuring HL7 messages ```php // Creating multiple message objects may have an unexpected side effect: segments start with wrong index values (Check tests/MessageTest for explanation)... // So to reset segment indices to 1: @@ -81,7 +78,7 @@ $hl7String = "MSH|^~\&|||||||ORU^R01|00001|P|2.3.1|\n" . "OBX|1||11^AA|\n" . "OB $message = HL7::from($hl7String) ->autoIncrementIndices(false) ->create(); -// $message now contains both OBXs with given indexes in the string +// $message now contains both OBXs with 1 as the index, instead of 1 and 2 ``` ```php // Ensure empty sub-fields are not removed @@ -91,16 +88,12 @@ $pv1 = $message->getSegmentByIndex(1); $fields = $pv1->getField(3); // $fields is ['', 'AAAA1', '', '', 'BB'] // Create/send message with segment-ending bar character (|) removed +use Aranyasen\HL7\Message; $message = new Message("MSH|^~\\&|1|\nABC|||xxx\n", ['SEGMENT_ENDING_BAR' => false]); $message->toString(true); // Returns "MSH|^~\&|1\nABC|||xxx\n" (new Connection($ip, $port))->send($message); // Sends the message without ending bar-characters (details on Connection below) - -// Specify custom values for separators, HL7 version etc. -$message = HL7::from("MSH|^~\\&|1|\rPV1|1|O|^AAAA1^^^BB|") - ->withSegmentSeparator('\r\n') - ->withHL7Version('2.3') - ->create(); - +``` +```php // Segment with separator character (~) creates sub-arrays containing each sub-segment $message = HL7::from("MSH|^~\&|||||||ADT^A01||P|2.3.1|\nPID|||3^0~4^1")->create(); // Creates [[3,0], [4,1]] @@ -116,10 +109,12 @@ $message = HL7::from("MSH|^~\&|||||||ADT^A01||P|2.3.1|\nPID|||3^0~4^1") // Once a message object is created, we can now add, insert, set segments and fields. // Create a MSH segment and add to message object +use Aranyasen\HL7\Segments\MSH; $msh = new MSH(); $message->addSegment($msh); // Message is: "MSH|^~\&|||||20171116140058|||2017111614005840157||2.3|\n" // Create a custom segment +use Aranyasen\HL7\Segment; $abc = new Segment('ABC'); $abc->setField(1, 'xyz'); $abc->setField(2, 0); @@ -129,6 +124,7 @@ $message->insertSegment($abc, 1); // Message is now: "MSH|^~\&|||||2017111614005 // Create a defined segment (To know which segments are defined in this package, look into Segments/ directory) // Advantages of defined segments over custom ones (shown above) are 1) Helpful setter methods, 2) Auto-incrementing segment index +use Aranyasen\HL7\Segments\PID; $pid = new PID(); // Automatically creates PID segment, and adds segment index at PID.1 $pid->setPatientName([$lastname, $firstname, $middlename, $suffix]); // Use a setter method to add patient's name at standard position (PID.5) $pid->setField('abcd', 5); // Apart from standard setter methods, you can manually set a value at any position too @@ -156,6 +152,7 @@ echo $response->toString(true); // Prints ACK from the listener ### ACK Handle ACK message returned from a remote HL7 listener... ```php +use Aranyasen\HL7\Connection; $ack = (new Connection($ip, $port))->send($message); // Send a HL7 to remote listener $returnString = $ack->toString(true); if (strpos($returnString, 'MSH') === false) { @@ -173,6 +170,7 @@ else { ``` Create an ACK response from a given HL7 message: ```php +use Aranyasen\HL7\Messages\ACK; $msg = HL7::from("MSH|^~\\&|1|\rABC|1||^AAAA1^^^BB|")->keepEmptySubfields()->create(); $ackResponse = new ACK($msg); ``` diff --git a/UPGRADE.md b/UPGRADE.md index 9c701dc..5ad7288 100644 --- a/UPGRADE.md +++ b/UPGRADE.md @@ -4,6 +4,7 @@ - In `insertSegment()` method, only MSH can be inserted now in the 0th index - Replaced all `InvalidArgumentException` with `HL7Exception`, so update the catches accordingly - Dropped support for PHP 8.1. Minimum version required is now 8.2. So if your project can not be upgraded to 8.2, you'll need to continue using 3.x version + - `withSegmentSeparator` in HL7 accepts CRLF (\r\n) as argument. Any other multi-character separator will continue to throw exception ### Non-breaking changes - Using `new Message()` is deprecated, and might be removed in a future version. Use HL7 factory to create a new HL7 object instead. See readme on how to use it - `setSegment` method is deprecated. Use `insertSegment` instead diff --git a/src/HL7.php b/src/HL7.php index 606a19d..a00a3c9 100644 --- a/src/HL7.php +++ b/src/HL7.php @@ -149,7 +149,10 @@ public function withFieldSeparator(string $value): self */ public function withSegmentSeparator(string $value): self { - $this->checkIfSingleCharacter($value); + $value = str_replace(['\r', '\n'], ["\r", "\n"], $value); + if ($value !== "\r\n") { + $this->checkIfSingleCharacter($value); + } return $this->setGlobal('SEGMENT_SEPARATOR', $value); } diff --git a/tests/HL7Test.php b/tests/HL7Test.php index 45c692d..8bf2d6d 100644 --- a/tests/HL7Test.php +++ b/tests/HL7Test.php @@ -166,8 +166,7 @@ class HL7Test extends TestCase */ #[Test] public function repetition_separation_character_can_be_ignored(): void { - $message = Hl7::from("MSH|^~\&|||||||ADT^A01||P|2.3.1|\nPID|||3^0~4^1") - ->create(); + $message = Hl7::from("MSH|^~\&|||||||ADT^A01||P|2.3.1|\nPID|||3^0~4^1")->create(); self::assertIsArray( $message->getSegmentByIndex(1)->getField(3), 'By default repetition should be split into array' @@ -185,6 +184,30 @@ class HL7Test extends TestCase { $this->expectException(HL7Exception::class); $this->expectExceptionMessage("Parameter should be a single character. Received: 'aa'"); - HL7::build()->withSegmentSeparator('aa'); + HL7::build()->withEscapeCharacter('aa')->create(); + } + + /** @throws HL7Exception */ + #[Test] public function it_accepts_crlf_as_segment_separator(): void + { + $message = HL7::from("MSH|^~\\&|1|") + ->withSegmentSeparator("\r\n") // With double-quotes + ->create(); + $this->assertSame($message->toString(true), "MSH|^~\\&|1|\r\n"); + + $message = HL7::from("MSH|^~\\&|1|") + ->withSegmentSeparator('\r\n') // With single-quotes + ->create(); + $this->assertSame($message->toString(true), "MSH|^~\\&|1|\r\n"); + } + + /** @throws HL7Exception */ + #[Test] public function any_other_multi_char_segment_separator_throws_exception(): void + { + $this->expectException(HL7Exception::class); + $this->expectExceptionMessage("Parameter should be a single character. Received: 'aa'"); + HL7::from("MSH|^~\\&|1|") + ->withSegmentSeparator('aa') + ->create(); } }