Net_HL7
[ class tree: Net_HL7 ] [ index: Net_HL7 ] [ all elements ]

Source for file Message.php

Documentation is available at Message.php

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
  3. // +----------------------------------------------------------------------+
  4. // | PHP version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 2004 D.A.Dokter                                        |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 3.0 of the PHP license,       |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available through the world-wide-web at the following url:           |
  11. // | http://www.php.net/license/3_0.txt.                                  |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Authors: D.A.Dokter <dokter@w20e.com>                                |
  17. // +----------------------------------------------------------------------+
  18. //
  19. // $Id: Message.php,v 1.8 2004/08/06 07:38:54 wyldebeast Exp $
  20.  
  21. require_once 'Net/HL7/Segment.php';
  22. require_once 'Net/HL7.php';
  23.  
  24.  
  25. /**
  26.  * Class specifying the HL7 message, both request and response.
  27.  *
  28.  * In general one needn't create an instance of the Net_HL7_Message
  29.  * class directly, but use the Net_HL7 factory class to create one.
  30.  * When adding segments, note that the segment index starts
  31.  * at 0, so to get the first segment, do
  32.  * <code>$msg->getSegmentByIndex(0)</code>.
  33.  *
  34.  * The segment separator defaults to \015. To change this, set the
  35.  * global variable $_Net_HL7_SEGMENT_SEPARATOR.
  36.  *
  37.  * @version    $Revision: 1.8 $
  38.  * @author     D.A.Dokter <dokter@w20e.com>
  39.  * @access     public
  40.  * @category   Networking
  41.  * @package    Net_HL7
  42.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  43.  */
  44. class Net_HL7_Message {
  45.  
  46.     /**
  47.      * Array holding all segements of this message.
  48.      */
  49.     var $_segments;
  50.  
  51.     /**
  52.      * local value for segment separator
  53.      */
  54.     var $_segmentSeparator;
  55.     var $_fieldSeparator;
  56.     var $_componentSeparator;
  57.     var $_subcomponentSeparator;
  58.     var $_repetitionSeparator;
  59.     var $_escapeChar;
  60.     var $_hl7Version;
  61.  
  62.  
  63.     /**
  64.      * Constructor for Net_HL7_Message. Consider using the HL7 factory
  65.      * to obtain a message instead.
  66.      *
  67.      * The constructor takes an optional string argument that is a string
  68.      * representation of a HL7 message. If the string representation is not a
  69.      * valid HL7 message. according to the specifications, undef is returned
  70.      * instead of a new instance. This means that segments should be
  71.      * separated within the message with the segment separator (defaults to
  72.      * \015) or a newline, and segments should be syntactically correct.
  73.      * When using the string argument constructor, make sure that you have
  74.      * escaped any characters that would have special meaning in PHP.
  75.      *
  76.      * The control characters and field separator will take the values from
  77.      * the MSH segment, if set. Otherwise defaults will be used. Changing the
  78.      * MSH fields specifying the field separator and control characters after
  79.      * the MSH has been added to the message will result in setting these
  80.      * values for the message.
  81.      *
  82.      * If the message couldn't be created, for example due to a erroneous HL7
  83.      * message string, an error is raised.
  84.      */
  85.     function Net_HL7_Message($msgStr ""$hl7Globals = array())
  86.     {
  87.         
  88.         //Array holding the segments
  89.         $this->_segments = array();
  90.         
  91.         // Control characters and other HL7 properties
  92.         //
  93.         !empty($hl7Globals["SEGMENT_SEPARATOR"]
  94.             $this->_segmentSeparator $hl7Globals["SEGMENT_SEPARATOR":
  95.             $this->_segmentSeparator "\015";
  96.         !empty($hl7Globals["FIELD_SEPARATOR"]
  97.             $this->_fieldSeparator $hl7Globals["FIELD_SEPARATOR":
  98.             $this->_fieldSeparator "|";
  99.         !empty($hl7Globals["COMPONENT_SEPARATOR"]
  100.             $this->_componentSeparator $hl7Globals["COMPONENT_SEPARATOR":
  101.             $this->_componentSeparator "^";
  102.         !empty($hl7Globals["SUBCOMPONENT_SEPARATOR"]
  103.             $this->_subcomponentSeparator $hl7Globals["SUBCOMPONENT_SEPARATOR":
  104.             $this->_subcomponentSeparator "&";
  105.         !empty($hl7Globals["REPETITION_SEPARATOR"]
  106.             $this->_repetitionSeparator $hl7Globals["REPETITION_SEPARATOR":
  107.             $this->_repetitionSeparator "~";
  108.         !empty($hl7Globals["ESCAPE_CHAR"]
  109.             $this->_escapeChar $hl7Globals["ESCAPE_CHAR":
  110.             $this->_escapeChar "\\";
  111.         !empty($hl7Globals["HL7_VERSION"]
  112.             $this->_hl7Version $hl7Globals["HL7_VERSION":
  113.             $this->_hl7Version "2.2";
  114.  
  115.     
  116.         // If an HL7 string is given to the constructor, parse it.
  117.         if ($msgStr{
  118.  
  119.             $segments preg_split("/[\n\\" $this->_segmentSeparator "]/"$msgStr-1PREG_SPLIT_NO_EMPTY);
  120.  
  121.             // The first segment should be the control segment
  122.             //
  123.             preg_match("/^([A-Z0-9]{3})(.)(.)(.)(.)(.)(.)/"$segments[0]$matches);
  124.       
  125.             $hdr $matches[1];
  126.             $fldSep $matches[2];
  127.             $compSep $matches[3];
  128.             $repSep $matches[4];
  129.             $esc $matches[5];
  130.             $subCompSep $matches[6];
  131.             $fldSepCtrl $matches[7];
  132.       
  133.             // Check whether field separator is repeated after 4 control characters
  134.             //
  135.             if ($fldSep != $fldSepCtrl{
  136.     
  137.                 trigger_error("Not a valid message: field separator invalid"E_USER_ERROR);
  138.             }
  139.       
  140.             // Set field separator based on control segment
  141.             $this->_fieldSeparator        $fldSep;
  142.       
  143.             // Set other separators
  144.             $this->_componentSeparator    $compSep
  145.             $this->_subcomponentSeparator $subCompSep;
  146.             $this->_escapeChar            $esc;
  147.             $this->_repetitionSeparator   $repSep;
  148.       
  149.             // Do all segments
  150.             //
  151.             for ($i = 0; $i count($segments)$i++{
  152.  
  153.                 $fields preg_split("/\\" $this->_fieldSeparator "/"$segments[$i]);
  154.                 $name array_shift($fields);
  155.     
  156.                 // Now decompose fields if necessary, into arrays
  157.                 //
  158.                 for ($j = 0; $j count($fields)$j++{
  159.       
  160.                     // Skip control field
  161.                     if ($i == 0 && $j == 0{
  162.                         continue;
  163.                     }
  164.       
  165.                     $comps preg_split("/\\" $this->_componentSeparator ."/"$fields[$j]-1PREG_SPLIT_NO_EMPTY);
  166.       
  167.                     for ($k = 0; $k count($comps)$k++{
  168.         
  169.                         $subComps preg_split("/\\" $this->_subcomponentSeparator "/"$comps[$k]);
  170.         
  171.                         // Make it a ref or just the value
  172.                         (count($subComps== 1($comps[$k$subComps[0]($comps[$k$subComps);
  173.                     }
  174.       
  175.                     (count($comps== 1($fields[$j$comps[0]($fields[$j$comps);
  176.                 }
  177.     
  178.                 $seg;    
  179.                 $segClass = "Net_HL7_Segments_$name";
  180.     
  181.                 // Let's see whether it's the a special segment
  182.                 //
  183.                 if (@include_once "Net/HL7/Segments/$name.php"{
  184.                     array_unshift($fields$this->_fieldSeparator);
  185.  
  186.                     $seg =new $segClass($fields);
  187.                 else {
  188.                     $seg =new Net_HL7_Segment($name$fields);
  189.                 }
  190.     
  191.                 if (!$seg
  192.                     trigger_error("Segment not created"E_USER_WARNING);
  193.                 }
  194.     
  195.                 $this->addSegment($seg);
  196.             }
  197.         }
  198.     }
  199.  
  200.   
  201.     /**
  202.      * Add a segment.
  203.      *
  204.      * The segment will be added to the end of the message. The
  205.      * segment should be an instance of Net_HL7_Segment.
  206.      *
  207.      * @param object An instance of Net_HL7_Segment
  208.      * @return boolean 
  209.      * @access public
  210.      * @see Net_HL7_Segment
  211.      */
  212.     function addSegment(&$segment
  213.     
  214.         if (!is_a($segment"Net_HL7_Segment")) {
  215.             trigger_error("The object is not a Net_HL7_Segment"E_USER_WARNING)
  216.         }
  217.  
  218.         if (count($this->_segments== 0{
  219.             $this->_resetCtrl($segment);
  220.         }
  221.     
  222.         array_push($this->_segments&$segment);
  223.  
  224.         return true;
  225.     }
  226.  
  227.  
  228.     /**
  229.      * Insert a segment.
  230.      *
  231.      * The segment should be an instance of Net_HL7_Segment. If the
  232.      * index is not given, nothing happens.
  233.      * 
  234.      * @param object An instance of Net_HL7_Segment
  235.      * @param int Index where segment is inserted
  236.      * @return boolean 
  237.      * @access public
  238.      * @see Net_HL7_Segment
  239.      */
  240.     function insertSegment(&$segment$idx ""
  241.     {
  242.         if ((!$idx|| ($idx count($this->_segments))) {
  243.             trigger_error("Index out of range"E_USER_WARNING);
  244.             return false;
  245.         }
  246.  
  247.         if (!is_a($segment"Net_HL7_Segment")) {
  248.             trigger_error("The object is not a Net_HL7_Segment"E_USER_WARNING)
  249.             return false;
  250.         }
  251.  
  252.         if ($idx == 0{
  253.             $this->_resetCtrl($segment);
  254.             array_unshift($this->_segments&$segment);
  255.         elseif ($idx == count($this->_segments)) {
  256.             array_push($this->_segments&$segment);
  257.         else {
  258.             $this->_segments 
  259.                 array_merge(
  260.                             array_slice($this->_segments0$idx),
  261.                             array(&$segment),
  262.                             array_slice($this->_segments$idx)
  263.                             );
  264.         }
  265.  
  266.         return true;
  267.     }
  268.  
  269.  
  270.     /**
  271.      * Return the segment specified by $index.
  272.      *
  273.      * Segment count within the message starts at 0.
  274.      *
  275.      * @param int Index where segment is inserted
  276.      * @return object An instance of Net_HL7_Segment
  277.      * @access public
  278.      * @see Net_HL7_Segment
  279.      */
  280.     function &getSegmentByIndex($index
  281.     {
  282.         if ($index >= count($this->_segments)) {
  283.             return NULL;
  284.         }
  285.  
  286.         return $this->_segments[$index];
  287.     }
  288.  
  289.  
  290.     /**
  291.      * Return an array of all segments with the given name
  292.      *
  293.      * @param mixed Segment name
  294.      * @return array List of segments identified by name
  295.      * @access public
  296.      */
  297.     function getSegmentsByName($name
  298.     {
  299.         $segmentsByName = array();
  300.  
  301.         foreach ($this->_segments as $seg{
  302.  
  303.             if ($seg->getName(== $name{
  304.                 array_push($segmentsByName$seg);
  305.             }
  306.         }
  307.     
  308.         return $segmentsByName;
  309.     }
  310.  
  311.  
  312.     /**
  313.      * Remove the segment indexed by $index.
  314.      *
  315.      * If it doesn't exist, nothing happens, if it does, all segments
  316.      * after this one will be moved one index up.
  317.      *
  318.      * @param int Index where segment is removed
  319.      * @return boolean 
  320.      * @access public
  321.      */
  322.     function removeSegmentByIndex($index
  323.     {
  324.         if ($index count($this->_segments)) {
  325.             array_splice($this->_segments$index1);
  326.         }
  327.  
  328.         return true;
  329.     }
  330.  
  331.  
  332.     /**
  333.      * Set the segment on index.
  334.      *
  335.      * If index is out of range, or not provided, do nothing. Setting
  336.      * MSH on index 0 will revalidate field separator, control
  337.      * characters and hl7 version, based on MSH(1), MSH(2) and
  338.      * MSH(12).
  339.      *
  340.      * @param object An instance of Net_HL7_Segment
  341.      * @param int Index where segment is set
  342.      * @return boolean 
  343.      * @access public
  344.      * @see Net_HL7_Segment
  345.      */
  346.     function setSegment(&$segment$idx
  347.     {  
  348.         if ((!isset($idx)) || $idx count($this->_segments)) 
  349.             trigger_error("Index out of range"E_USER_WARNING);
  350.             return false;
  351.         };
  352.  
  353.         if (!is_a($segment"Net_HL7_Segment")) {
  354.             trigger_error("The object is not a Net_HL7_Segment"E_USER_WARNING)
  355.             return false;
  356.         }
  357.     
  358.         if ($segment->getName(== "MSH" && $idx == 0
  359.             $this->_resetCtrl($segment);
  360.         }
  361.     
  362.         $this->_segments[$idx&$segment;
  363.  
  364.         return true;
  365.     }
  366.   
  367.   
  368.     /**
  369.      * After change of MSH, reset control fields
  370.      * 
  371.      * @param object An instance of Net_HL7_Segment
  372.      * @return boolean 
  373.      * @access private
  374.      * @see Net_HL7_Segment
  375.      */
  376.     function _resetCtrl(&$segment
  377.     {  
  378.         if ($segment->getField(1)) {
  379.             $this->_fieldSeparator $segment->getField(1);
  380.         }
  381.     
  382.         if (preg_match("/(.)(.)(.)(.)/"$segment->getField(2)$matches)) {
  383.             $this->_componentSeparator    $matches[1];
  384.             $this->_repetitionSeparator   $matches[2];
  385.             $this->_escapeChar            $matches[3];
  386.             $this->_subcomponentSeparator $matches[4];
  387.         }
  388.     
  389.         if ($segment->getField(12)) {
  390.             $this->hl7Version $segment->getField(12);
  391.         }
  392.  
  393.         return true;
  394.     }
  395.  
  396.  
  397.     /**
  398.      * Return an array containing all segments in the right order.
  399.      *
  400.      * @return array List of all segments
  401.      * @access public
  402.      */
  403.     function getSegments(
  404.     {
  405.         return $this->_segments;
  406.     }
  407.  
  408.  
  409.     /**
  410.      * Return a string representation of this message.
  411.      *
  412.      * This can be used to send the message over a socket to an HL7
  413.      * server. To print to other output, use the $pretty argument as
  414.      * some true value. This will not use the default segment
  415.      * separator, but '\n' instead.
  416.      * 
  417.      * @param boolean Whether to use \n as separator or default (\r).
  418.      * @return mixed String representation of HL7 message
  419.      * @access public
  420.      */
  421.     function toString($pretty = False)
  422.     {  
  423.         $msg "";
  424.  
  425.         // Make sure MSH(1) and MSH(2) are ok, even if someone has changed
  426.         // these values 
  427.         //
  428.         $msh $this->_segments[0];
  429.  
  430.         $this->_resetCtrl($msh);
  431.  
  432.         foreach ($this->_segments as $seg{
  433.  
  434.             $msg .= $seg->getName($this->_fieldSeparator;
  435.  
  436.             foreach ($seg->getFields(($seg->getName(!= "MSH" ? 1 : 2)) as $fld{
  437.     
  438.                 if (is_array($fld)) {
  439.       
  440.                     for ($i = 0; $i count($fld)$i++{
  441.         
  442.                         (is_array($fld[$i])) ($msg .= join($this->_subcomponentSeparator$fld[$i])) :
  443.                             ($msg .= $fld[$i]);
  444.         
  445.         
  446.                         if ($i (count($fld- 1)) {
  447.                             $msg .= $this->_componentSeparator;
  448.                         }
  449.                     }
  450.                 else {
  451.                     $msg .= $fld;
  452.                 }
  453.     
  454.                 $msg .= $this->_fieldSeparator;
  455.             }
  456.       
  457.             ($pretty($msg .= "\n"($msg .= $this->_segmentSeparator);
  458.         }
  459.     
  460.         return $msg;
  461.     }
  462.  
  463.  
  464.     /**
  465.      * Get the segment identified by index as string, using the
  466.      * messsages separators.
  467.      *
  468.      * @param int Index for segment to get
  469.      * @return mixed String representation of segment
  470.      * @access public
  471.      * @see Net_HL7_Segment
  472.      */
  473.     function getSegmentAsString($index
  474.     {
  475.         $seg $this->getSegmentByIndex($index);
  476.  
  477.         if ($seg == NULL{
  478.             return NULL;
  479.         }
  480.  
  481.         $segStr $seg->getName($this->_fieldSeparator;
  482.  
  483.         foreach ($seg->getFields(($seg->getName(!= "MSH" ? 1 : 2)) as $fld{
  484.       
  485.             if (is_array($fld)) {
  486.     
  487.                 for ($i = 0; $i count($fld)$i++{
  488.       
  489.                     (is_array($fld[$i])) ($segStr .= join($this->_subcomponentSeparator$fld[$i])) :
  490.                         ($segStr .= $fld[$i]);
  491.       
  492.       
  493.                     if ($i (count($fld- 1)) {
  494.                         $segStr .= $this->_componentSeparator;
  495.                     }
  496.                 }
  497.             else {
  498.                 $segStr .= $fld;
  499.             }
  500.       
  501.             $segStr .= $this->_fieldSeparator;
  502.         }
  503.  
  504.         return $segStr;
  505.     }
  506.  
  507.  
  508.     /**
  509.      * Get the field identified by $fldIndex from segment $segIndex.
  510.      * 
  511.      * Returns empty string if field is not set.
  512.      *
  513.      * @param int Index for segment to get
  514.      * @param int Index for field to get
  515.      * @return mixed String representation of field
  516.      * @access public
  517.      */
  518.     function getSegmentFieldAsString($segIndex$fldIndex
  519.     {
  520.         $seg $this->getSegmentByIndex($segIndex);    
  521.  
  522.         if ($seg == NULL{
  523.             return NULL;
  524.         }
  525.  
  526.         $fld $seg->getField($fldIndex);
  527.  
  528.         if (!$fld{
  529.             return "";
  530.         }
  531.  
  532.         $fldStr "";
  533.  
  534.         if (is_array($fld)) {
  535.       
  536.             for ($i = 0; $i count($fld)$i++{
  537.     
  538.                 (is_array($fld[$i])) ($fldStr .= join($this->_subcomponentSeparator$fld[$i])) :
  539.                     ($fldStr .= $fld[$i]);
  540.     
  541.     
  542.                 if ($i (count($fld- 1)) {
  543.                     $fldStr .= $this->_componentSeparator;
  544.                 }
  545.             }
  546.         else {
  547.             $fldStr .= $fld;
  548.         }
  549.  
  550.         return $fldStr;
  551.     }
  552.  
  553. }
  554. ?>

Documentation generated on Mon, 11 Mar 2019 15:32:35 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.