Skip to content

Commit

Permalink
Standardize code as per PSR-12 (#65)
Browse files Browse the repository at this point in the history
* Bugfix: MSH for an ACK should be created with same global vars as MSG
* Add linter in CI config
* Fix linting issue in CI
* Update badge
  • Loading branch information
senaranya authored Nov 1, 2021
1 parent c6cb76e commit d41b4c6
Show file tree
Hide file tree
Showing 24 changed files with 189 additions and 184 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/main_ci.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: HL7 library
name: tests

on:
push:
Expand Down Expand Up @@ -36,7 +36,7 @@ jobs:
- name: Install dependencies
run: composer install --dev --prefer-dist --no-progress
# - name: Run linter
# run: composer run-script lint
- name: Run linter
run: composer run-script lint
- name: Run test suite
run: composer run-script test
11 changes: 6 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
Contributions are more than welcome! Please review issues if you want to pick up from existing tickets. New tickets/features/CRs are welcome!

Contributors are requested to add or update phpdoc for any new or existing methods being worked on.

It'll be great if you update the API documentation as well (else I'll do it for you), in case if a phpdoc is changed.
* Contributions are more than welcome!
* Please review [issues](https://github.com/senaranya/HL7/issues) if you want to pick up from existing tickets. New tickets/features/CRs/PRs are welcome!
* The goal of this library is to keep it generic and minimal. The focus should only be on basic HL7-related operations like creation/parsing/sending/receiving etc. No project-specific business logic should be included.
* This library follows PSR-12 standards for coding style. You may use [phpcs](https://github.com/squizlabs/PHP_CodeSniffer#getting-started) to verify your code.
* Add unit tests for code changes/updates. There are a number of existing tests, follow those as reference
* Contributors are requested to add or update phpdoc for any new or existing methods being worked on. After updating/adding, please update the API documentation as well (details below)

##### Generate/update API documentation (in Markdown format) from docblocks
* Install [clean/phpdoc-md](https://github.com/clean/phpdoc-md): `composer require --dev clean/phpdoc-md`
Expand Down
15 changes: 8 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<p align="center">
<a href="https://github.com/senaranya/HL7/actions"><img src="https://github.com/senaranya/hl7/actions/workflows/main_ci.yml/badge.svg?branch=master" alt="Build Status"></a>
<a href="https://github.com/senaranya/HL7/actions"><img src="https://github.com/senaranya/hl7/actions/workflows/main_ci.yml/badge.svg?branch=master" alt="CI Status"></a>
<a href="https://packagist.org/packages/aranyasen/hl7"><img src="https://poser.pugx.org/aranyasen/hl7/downloads" alt="Total Downloads"></a>
<a href="https://packagist.org/packages/aranyasen/hl7"><img src="https://poser.pugx.org/aranyasen/hl7/v/stable" alt="Latest Stable Version"></a>
<a href="https://packagist.org/packages/aranyasen/hl7"><img src="https://poser.pugx.org/aranyasen/hl7/license" alt="License"></a>
Expand Down Expand Up @@ -127,10 +127,10 @@ if (strpos($returnString, 'MSH') === false) {
$msa = $ack->getSegmentsByName('MSA')[0];
$ackCode = $msa->getAcknowledgementCode();
if ($ackCode[1] === 'A') {
echo "Recieved ACK from remote\n";
echo "Received ACK from remote\n";
}
else {
echo "Recieved NACK from remote\n";
echo "Received NACK from remote\n";
echo "Error text: " . $msa->getTextMessage();
}
```
Expand Down Expand Up @@ -166,7 +166,8 @@ All segment level getter/setter APIs can be used in two ways -
`$pid->setPatientName('John Doe', 6)` -> Set patient name at 6th position in PID segment
`$pid->getPatientAddress(12)` -> Get patient address from 12th position

### TODOs
* Data Validation
* Search by regex and return segment/field/index
* Define more segments
### Issues
Bug reports and feature requests can be submitted on the [Github Issue Tracker](https://github.com/senaranya/HL7/issues).

### Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md) for information.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
},
"scripts": {
"test": "vendor/bin/phpunit tests/ --coverage-text",
"lint": "vendor/bin/phpcs src/"
"lint": "vendor/bin/phpcs --standard=psr12 src/"
},
"extra": {
"branch-alias": {
Expand Down
2 changes: 1 addition & 1 deletion src/Exceptions/HL7ConnectionException.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@
class HL7ConnectionException extends Exception
{

}
}
2 changes: 1 addition & 1 deletion src/Exceptions/HL7Exception.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@
class HL7Exception extends Exception
{

}
}
11 changes: 6 additions & 5 deletions src/HL7/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ public function __construct(string $host, int $port, int $timeout = 10)
throw new HL7ConnectionException('Please install ext-sockets to run Connection');
}
$this->setSocket($host, $port, $timeout);
$this->MESSAGE_PREFIX = "\013";
$this->MESSAGE_SUFFIX = "\034\015";
$this->MESSAGE_PREFIX = "\013"; # Octal 13 (Hex: 0B): Vertical Tab
$this->MESSAGE_SUFFIX = "\034\015"; # 34 (Hex: 1C): file separator character, 15 (Hex: 0D): Carriage return
$this->timeout = $timeout;
}

Expand Down Expand Up @@ -147,7 +147,9 @@ public function send(Message $msg, string $responseCharEncoding = 'UTF-8', bool
break;
}
if ((time() - $startTime) > $this->timeout) {
throw new HL7ConnectionException("Response partially received. Timed out listening for end-of-message from server");
throw new HL7ConnectionException(
"Response partially received. Timed out listening for end-of-message from server"
);
}
}

Expand Down Expand Up @@ -181,8 +183,7 @@ private function close(): void
{
try {
socket_close($this->socket);
}
catch (Exception $e) {
} catch (Exception $e) {
echo 'Failed to close socket: ' . socket_strerror(socket_last_error()) . PHP_EOL;
}
}
Expand Down
49 changes: 24 additions & 25 deletions src/HL7/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,21 +61,27 @@ class Message
* If the message couldn't be created, for example due to a erroneous HL7 message string, an error is raised.
* @param string|null $msgStr
* @param array|null $hl7Globals Set control characters or HL7 properties. e.g., ['HL7_VERSION' => '2.5']
* @param bool $keepEmptySubFields Set this to true to retain empty sub fields
* @param bool $keepEmptySubFields Set this to true to retain empty sub-fields
* @param bool $resetIndices Reset Indices of each segment to 1.
* @param bool $autoIncrementIndices True: auto-increment for each instance of same segment.
* @param bool|null $doNotSplitRepetition If true, repeated segments will be in single array instead of sub-arrays. Since this is non-standard, it may be removed in future
* @param bool|null $doNotSplitRepetition If true, repeated segments will be in single array instead of sub-arrays.
* Note: Since this is non-standard, it may be removed in future!
* @throws HL7Exception
* @throws \ReflectionException
*/
public function __construct(string $msgStr = null, array $hl7Globals = null, bool $keepEmptySubFields = false, bool $resetIndices = false, bool $autoIncrementIndices = true, bool $doNotSplitRepetition = null)
{
public function __construct(
string $msgStr = null,
array $hl7Globals = null,
bool $keepEmptySubFields = false,
bool $resetIndices = false,
bool $autoIncrementIndices = true,
bool $doNotSplitRepetition = null
) {
// Array holding the segments
$this->segments = [];

// Control characters and other HL7 properties
$this->segmentSeparator = $hl7Globals['SEGMENT_SEPARATOR'] ?? '\n';
$this->segmentEndingBar = $hl7Globals['SEGMENT_ENDING_BAR'] ?? true; // Bar (|) at end of each segment. Default: Present
$this->segmentEndingBar = $hl7Globals['SEGMENT_ENDING_BAR'] ?? true; // '|' at end of each segment
$this->fieldSeparator = $hl7Globals['FIELD_SEPARATOR'] ?? '|';
$this->componentSeparator = $hl7Globals['COMPONENT_SEPARATOR'] ?? '^';
$this->subcomponentSeparator = $hl7Globals['SUBCOMPONENT_SEPARATOR'] ?? '&';
Expand Down Expand Up @@ -136,12 +142,10 @@ public function __construct(string $msgStr = null, array $hl7Globals = null, boo
if ($segmentName === 'MSH') {
array_unshift($fields, $this->fieldSeparator); # First field for MSH is '|'
$segment = new $className($fields);
}
else {
} else {
$segment = new $className($fields, $autoIncrementIndices);
}
}
else {
} else {
$segment = new Segment($segmentName, $fields);
}

Expand Down Expand Up @@ -179,7 +183,7 @@ public function addSegment(Segment $segment): bool
* @param null|int $index Index where segment is inserted
* @throws \InvalidArgumentException
*/
public function insertSegment(Segment $segment, $index = null): void
public function insertSegment(Segment $segment, int $index = null): void
{
if ($index > count($this->segments)) {
throw new InvalidArgumentException("Index out of range. Index: $index, Total segments: " .
Expand All @@ -189,11 +193,9 @@ public function insertSegment(Segment $segment, $index = null): void
if ($index === 0) {
$this->resetCtrl($segment);
array_unshift($this->segments, $segment);
}
elseif ($index === count($this->segments)) {
} elseif ($index === count($this->segments)) {
$this->segments[] = $segment;
}
else {
} else {
$this->segments =
array_merge(
array_slice($this->segments, 0, $index),
Expand Down Expand Up @@ -388,7 +390,7 @@ public function toString(bool $pretty = false)

/**
* Convert Segment object to string
* @param $seg
* @param Segment $seg
* @return string
*/
public function segmentToString(Segment $seg): string
Expand All @@ -400,9 +402,9 @@ public function segmentToString(Segment $seg): string
foreach ($fields as $field) {
if (is_array($field)) {
foreach ($field as $index => $value) {
is_array($field[$index])
? ($segmentString .= implode($this->subcomponentSeparator, $field[$index]))
: ($segmentString .= $field[$index]);
is_array($value)
? ($segmentString .= implode($this->subcomponentSeparator, $value))
: ($segmentString .= $value);

if ($index < (count($field) - 1)) {
$segmentString .= $this->componentSeparator;
Expand All @@ -422,7 +424,6 @@ public function segmentToString(Segment $seg): string
* Reset index attribute of each given segment, so when those are added the indices start from 1
*
* @return void
* @throws \ReflectionException
*/
public function resetSegmentIndices(): void
{
Expand Down Expand Up @@ -450,7 +451,7 @@ private function extractComponentsFromFields(string $field, bool $keepEmptySubFi
: PREG_SPLIT_NO_EMPTY;

if ((strpos($field, $this->repetitionSeparator) !== false) && (! $this->doNotSplitRepetition)) {
$components = preg_split("/\\".$this->repetitionSeparator.'/', $field, -1, $pregFlags);
$components = preg_split("/\\" . $this->repetitionSeparator . '/', $field, -1, $pregFlags);
$fields = [];
foreach ($components as $index => $component) {
$fields[$index] = $this->extractComponentsFromFields($component, $keepEmptySubFields);
Expand All @@ -461,17 +462,15 @@ private function extractComponentsFromFields(string $field, bool $keepEmptySubFi

$components = preg_split("/\\" . $this->componentSeparator . '/', $field, -1, $pregFlags);
foreach ($components as $index => $component) {
$subComps = preg_split("/\\" . $this->subcomponentSeparator . '/', $components[$index]);
$subComps = preg_split("/\\" . $this->subcomponentSeparator . '/', $component);
// Make it a ref or just the value
$components[$index] = count($subComps) === 1
? $subComps[0]
: $subComps;
}

$field = count($components) === 1
return count($components) === 1
? $components[0]
: $components;

return $field;
}
}
17 changes: 8 additions & 9 deletions src/HL7/MessageHelpersTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ public function getSegmentAsString(int $index): ?string
*
* @param int $segmentIndex Index for segment to get
* @param int $fieldIndex Index for field to get
* @return mixed String representation of field
* @return null|string String representation of field
* @access public
*/
public function getSegmentFieldAsString(int $segmentIndex, int $fieldIndex)
public function getSegmentFieldAsString(int $segmentIndex, int $fieldIndex): ?string
{
$segment = $this->getSegmentByIndex($segmentIndex);

Expand All @@ -51,17 +51,16 @@ public function getSegmentFieldAsString(int $segmentIndex, int $fieldIndex)
$fieldString = null;

if (\is_array($field)) {
foreach ($field as $i => $iValue) {
\is_array($field[$i])
? ($fieldString .= implode($this->subcomponentSeparator, $field[$i]))
: ($fieldString .= $field[$i]);
foreach ($field as $i => $value) {
\is_array($value)
? ($fieldString .= implode($this->subcomponentSeparator, $value))
: ($fieldString .= $value);

if ($i < (\count($field) - 1)) {
$fieldString .= $this->componentSeparator;
}
}
}
else {
} else {
$fieldString .= $field;
}

Expand Down Expand Up @@ -163,7 +162,7 @@ public function getFirstSegmentInstance(string $segment)
*/
public function removeSegment(Segment $segment, bool $reIndex = false): void
{
if(($key = array_search($segment, $this->segments, true)) !== false) {
if (($key = array_search($segment, $this->segments, true)) !== false) {
unset($this->segments[$key]);
}

Expand Down
21 changes: 9 additions & 12 deletions src/HL7/Messages/ACK.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class ACK extends Message
*
* @param Message|null $req
* @param MSH|null $reqMsh
* @param array $hl7Globals Set control characters or HL7 properties. e.g., ['HL7_VERSION' => '2.5']
* @param array|null $hl7Globals Set control characters or HL7 properties. e.g., ['HL7_VERSION' => '2.5']
* @throws \Exception
* @throws \InvalidArgumentException
*/
Expand All @@ -34,14 +34,12 @@ public function __construct(Message $req = null, MSH $reqMsh = null, array $hl7G
$msh = $req->getSegmentByIndex(0);

if ($msh) {
$msh = new MSH($msh->getFields(1));
$msh = new MSH($msh->getFields(1), $hl7Globals);
} else {
$msh = new MSH(null, $hl7Globals);
}
else {
$msh = new MSH();
}
}
else {
$msh = new MSH();
} else {
$msh = new MSH(null, $hl7Globals);
}

$msa = new MSA();
Expand All @@ -51,8 +49,7 @@ public function __construct(Message $req = null, MSH $reqMsh = null, array $hl7G
if ($req && ($msh->getField(15) || $msh->getField(16))) {
$this->ACK_TYPE = 'E';
$msa->setAcknowledgementCode('CA');
}
else {
} else {
$this->ACK_TYPE = 'N';
$msa->setAcknowledgementCode('AA');
}
Expand All @@ -79,8 +76,8 @@ public function __construct(Message $req = null, MSH $reqMsh = null, array $hl7G
* This denotes: accept, general error and reject respectively. The ACK module will determine the right answer mode
* (normal or enhanced) based upon the request, if not provided. The message provided in $msg will be set in MSA 3.
*
* @param string $code Code to use in acknowledgement
* @param string $msg Acknowledgement message
* @param string $code Code to use in acknowledgement
* @param string|null $msg Acknowledgement message
* @return boolean
* @access public
*/
Expand Down
4 changes: 1 addition & 3 deletions src/HL7/Request.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
<?php


namespace Aranyasen\HL7;


class Request
{

}
}
4 changes: 1 addition & 3 deletions src/HL7/Response.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
<?php


namespace Aranyasen\HL7;


class Response
{

}
}
10 changes: 5 additions & 5 deletions src/HL7/Segment.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ class Segment
/**
* Create a segment.
*
* A segment may be created with just a name or a name and an array of field
* values. The segment name should be a standard HL7 segment (e.g. MSH / PID etc.) that is three characters long, and
* upper case. If an array is given, all fields will be filled from that array. Note that for composed fields and
* sub-components, the array may hold sub-arrays and sub-sub-arrays. Repeated fields can not be supported the same
* way, since we can't distinguish between composed fields and repeated fields.
* A segment may be created with just a name or a name and an array of field values. The segment name should be a
* standard HL7 segment (e.g. MSH / PID etc.) that is three characters long, and upper case. If an array is given,
* all fields will be filled from that array. Note that for composed fields and sub-components, the array may hold
* sub-arrays and sub-sub-arrays. Repeated fields can not be supported the same way, since we can't distinguish
* between composed fields and repeated fields.
*
* Example:
* ```php
Expand Down
1 change: 0 additions & 1 deletion src/HL7/Segments/EQU.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,4 @@ public function getAlertLevel(int $position = 4)
{
return $this->getField($position);
}

}
Loading

0 comments on commit d41b4c6

Please sign in to comment.