function parse($data) { parent::parse($data); if ($this->data === "" || $this->data === null) { // === $message->nullValue) { // nullValue ("") or null ?? if ($this->required) { $this->error(CHL7v2Exception::FIELD_EMPTY, $this->getPathString(), $this); } } else { if ($this->forbidden) { $this->error(CHL7v2Exception::FIELD_FORBIDDEN, $this->data, $this); } } $message = $this->getMessage(); $items = CHL7v2::split($message->repetitionSeparator, $this->data, $this->keep()); /* // Ce test ne semble pas etre valide, car meme si maxOccurs n'est pas unbounded, // on en trouve souvent plusieurs occurences if (!$this->unbounded && count($items) > 1) { mbTrace($this); $this->error(CHL7v2Exception::TOO_MANY_FIELD_ITEMS, $this->name, $this); }*/ $this->items = array(); foreach ($items as $i => $components) { $_field_item = new CHL7v2FieldItem($this, $this->meta_spec, $i); $_field_item->parse($components); $this->items[] = $_field_item; } $this->validate(); }
/** * Get table description * * @param string $table Table HL7 * @param string $hl7Value HL7 value * * @return string */ static function getDescription($table, $hl7Value) { if ($value = CHL7v2::getTableDescription($table, $hl7Value)) { return $value; } return null; }
/** * Validate data in the field * * @return bool true if the component is valid */ function validate() { $props = $this->getProps(); if ($props instanceof CHL7v2DataTypeComposite) { foreach ($this->children as $child) { if (!$child->validate()) { $this->invalid = true; } } } else { // length $length = strlen($this->data); if ($this->length && $length > $this->length) { $this->error(CHL7v2Exception::DATA_TOO_LONG, var_export($this->data, true) . " ({$length} / {$this->length})", $this); $this->invalid = true; } // table if ($this->table && $this->data !== "") { $entries = CHL7v2::getTable($this->table, false, true); if (!empty($entries)) { if (!array_key_exists($this->data, $entries)) { $this->error(CHL7v2Exception::UNKNOWN_TABLE_ENTRY, "'{$this->data}' (table {$this->table})", $this, CHL7v2Error::E_WARNING); $this->invalid = true; } else { $this->value_description = $entries[$this->data]; } } } if (!$props->validate($this->data, $this->getField())) { //$this->error(CHL7v2Exception::INVALID_DATA_FORMAT, $this->data, $this); $this->invalid = true; return false; } } return true; }
function parse($data, $parse_body = true, CInteropActor $actor = null) { $this->actor = $actor; try { self::isWellFormed($data, $this->strict_segment_terminator); } catch (CHL7v2Exception $e) { $this->error($e->getMessage(), $e->extraData); //return false; } // remove all chars before MSH $msh_pos = strpos($data, self::$header_segment_name); if ($msh_pos === false) { throw new CHL7v2Exception(CHL7v2Exception::SEGMENT_INVALID_SYNTAX, $data); } $data = substr($data, $msh_pos); $data = self::fixRawER7($data, $this->strict_segment_terminator); parent::parse($data); $message = $this->data; // 4 to 7 if (!isset($message[7])) { throw new CHL7v2Exception(CHL7v2Exception::SEGMENT_INVALID_SYNTAX, $message); } $this->fieldSeparator = $message[3]; $nextDelimiter = strpos($message, $this->fieldSeparator, 4); if ($nextDelimiter > 4) { // usually ^ $this->componentSeparator = $message[4]; } if ($nextDelimiter > 5) { // usually ~ $this->repetitionSeparator = $message[5]; } if ($nextDelimiter > 6) { // usually \ $this->escapeCharacter = $message[6]; } if ($nextDelimiter > 7) { // usually & $this->subcomponentSeparator = $message[7]; } // replace the special case of ^~& with ^~\& if ("^~&|" == substr($message, 4, 4)) { $this->escapeCharacter = "\\"; $this->subcomponentSeparator = "&"; $this->repetitionSeparator = "~"; $this->componentSeparator = "^"; } $this->initEscapeSequences(); $this->lines = CHL7v2::split($this->segmentTerminator, $this->data); // we extract the first line info "by hand" $first_line = CHL7v2::split($this->fieldSeparator, reset($this->lines)); if (!isset($first_line[11])) { throw new CHL7v2Exception(CHL7v2Exception::SEGMENT_INVALID_SYNTAX, $message); } // version if (array_key_exists(16, $first_line)) { $this->parseRawVersion($first_line[11], $first_line[16]); } else { $this->parseRawVersion($first_line[11]); } // message type $message_type = explode($this->componentSeparator, $first_line[8]); if ($message_type[0]) { $this->name = $message_type[0]; if ($this->name == "ACK") { $this->event_name = $message_type[0]; } else { if (isset($message_type[2]) && $message_type[2] && !preg_match("/^[A-Z]{3}_[A-Z\\d]{2}\\d\$/", $message_type[2])) { throw new CHL7v2Exception(CHL7v2Exception::WRONG_MESSAGE_TYPE, $message_type[2]); } if (strlen($message_type[0]) != 3 || strlen($message_type[1]) != 3) { $msg = $message_type[0] . $this->componentSeparator . $message_type[1]; throw new CHL7v2Exception(CHL7v2Exception::WRONG_MESSAGE_TYPE, $msg); } $this->event_name = $message_type[0] . $message_type[1]; } } else { $this->event_name = preg_replace("/[^A-Z0-9]/", "", $message_type[2]); $this->name = substr($message_type[2], 0, 3); } if (!($spec = $this->getSpecs())) { throw new CHL7v2Exception(CHL7v2Exception::UNKNOWN_MSG_CODE); } $this->description = $spec->queryTextNode("description"); $this->readHeader(); if ($parse_body) { $this->readSegments(); } }
/** * parse the mdata * * @param string $data data * @param bool $parse_body parse the body * * @throws CHL7v2Exception * * @return void */ function parse($data, $parse_body = true) { try { self::isWellFormed($data, $this->strict_segment_terminator); } catch (CHL7v2Exception $e) { $this->error($e->getMessage(), $e->extraData); //return false; } // remove all chars before H $h_pos = strpos($data, self::$header_segment_name); if ($h_pos === false) { throw new CHL7v2Exception(CHL7v2Exception::SEGMENT_INVALID_SYNTAX, $data); } $data = substr($data, $h_pos); $data = self::fixRawER7($data, $this->strict_segment_terminator); // handle "A" segments $field_sep = preg_quote($this->fieldSeparator); $patt = "/[\r\n]+A{$field_sep}([^\r\n]+)/s"; $data = preg_replace($patt, "\\1", $data); // remove "C" segments $patt = "/[\r\n]+C{$field_sep}([^\r\n]+)/s"; $data = preg_replace($patt, "", $data); parent::parse($data); $message = $this->data; // 2 to 5 if (!isset($message[5])) { throw new CHL7v2Exception(CHL7v2Exception::SEGMENT_INVALID_SYNTAX, $message); } $this->fieldSeparator = $message[1]; $nextDelimiter = strpos($message, $this->fieldSeparator, 2); if ($nextDelimiter > 4) { // usually ^ $this->componentSeparator = $message[2]; } if ($nextDelimiter > 3) { // usually ~ $this->repetitionSeparator = $message[3]; } if ($nextDelimiter > 4) { // usually \ $this->escapeCharacter = $message[4]; } if ($nextDelimiter > 5) { // usually & $this->subcomponentSeparator = $message[5]; } // replace the special case of ^~& with ^~\& if ("^~&|" == substr($message, 2, 4)) { $this->escapeCharacter = "\\"; $this->subcomponentSeparator = "&"; $this->repetitionSeparator = "~"; $this->componentSeparator = "^"; } $this->initEscapeSequences(); $this->lines = CHL7v2::split($this->segmentTerminator, $this->data); // we extract the first line info "by hand" $first_line = CHL7v2::split($this->fieldSeparator, reset($this->lines)); if (!isset($first_line[12])) { throw new CHL7v2Exception(CHL7v2Exception::SEGMENT_INVALID_SYNTAX, $message); } // version $this->parseRawVersion($first_line[12]); // message type $message_type = explode($this->componentSeparator, $first_line[6]); $this->name = $message_type[0]; $this->event_name = $message_type[0]; if (!($spec = $this->getSpecs())) { throw new CHL7v2Exception(CHL7v2Exception::UNKNOWN_MSG_CODE); } $this->description = $spec->queryTextNode("description"); $this->readHeader(); // type liaison //$type_liaison if ($parse_body) { $this->readSegments(); } }
/** * Get PV2.45 : operation * * @param CInteropReceiver $receiver Receiver * @param CSejour $sejour Admit * * @return array|null */ function getPV245(CInteropReceiver $receiver, CSejour $sejour) { $operation = $sejour->loadRefFirstOperation(); $operation->loadRefPlageOp(); $value = null; if (!empty($receiver->_configs["build_PV2_45"])) { $value = $receiver->_configs["build_PV2_45"]; } // Advance Directive Code switch ($value) { // Transmission de l'intervention case 'operation': if (!$operation) { return null; } $datetime = CHL7v2::getDateTime($operation->_datetime); $type_anesth = new CIdSante400(); if ($operation->type_anesth) { $tag_hl7 = $receiver->_tag_hl7; $type_anesth = CIdSante400::getMatch("CTypeAnesth", $tag_hl7, null, $operation->type_anesth); } $idex_chir = CIdSante400::getMatchFor($operation->loadRefChir(), $receiver->_tag_mediuser); $anesth = $operation->loadRefAnesth(); $idex_anesth = new CIdSante400(); if ($anesth->_id) { $idex_anesth = CIdSante400::getMatchFor($anesth, $receiver->_tag_mediuser); } $libelle = $operation->libelle; $PV2_45_2 = ""; // Datetime if ($datetime) { $PV2_45_2 .= "{$datetime}"; } $PV2_45_2 .= "#"; // Type anesth if ($type_anesth->id400) { $PV2_45_2 .= "{$type_anesth->id400}"; } $PV2_45_2 .= "#"; // Idex chir if ($idex_chir->id400) { $PV2_45_2 .= "{$idex_chir->id400}"; } $PV2_45_2 .= "#"; // Idex anesth if ($idex_anesth->id400) { $PV2_45_2 .= "{$idex_anesth->id400}"; } $PV2_45_2 .= "#"; // Libelle if ($libelle) { $PV2_45_2 .= "{$libelle}"; } if (CModule::getActive("mvsante")) { $PV2_45_2 .= CMVSante::getPV245($receiver, $sejour, $operation); } return array(array(null, $PV2_45_2)); default: return null; } }
function readSegments() { $specs = $this->getSpecs(); /** * Premier segment/groupe dans le fichier de spec * * @var CHL7v2DOMElement $current_node */ $current_node = $specs->query("/message/segments/*")->item(0); /** * Groupe courant dans lequel on va placer les CHL7v2Segment créés * * @var CHL7v2SegmentGroup $current_group */ $current_group = $this; //$lines_count = count($this->lines); $n = 100000; // pour eviter les boucles infinies ! while ($n-- && trim($this->getCurrentLine())) { if (!$current_node) { $segment_error = new CHL7v2Segment($current_group); $segment_error->name = $this->getCurrentLineHeader(); $this->error(CHL7v2Exception::UNEXPECTED_SEGMENT, $this->getCurrentLine(), $segment_error); break; } switch ($current_node->nodeName) { // SEGMENT // case "segment": CHL7v2::d($current_node->getSegmentHeader() . " " . $current_node->state(), "red"); $handled = false; if ($this->getCurrentLineHeader() == "") { break 2; } $seg_schema = $this->getSchema(self::PREFIX_SEGMENT_NAME, $this->getCurrentLineHeader(), $this->getMessage()->extension); if ($seg_schema == false) { $segment_error = new CHL7v2Segment($current_group); $segment_error->name = $this->getCurrentLineHeader(); $this->error(CHL7v2Exception::UNKOWN_SEGMENT_TYPE, $this->getCurrentLine(), $segment_error); break 2; } // Si la spec correspond a la ligne courante if ($this->getCurrentLineHeader() == $current_node->getSegmentHeader()) { $this->handleLine($current_node, $current_group); $current_node->markNotEmpty(); $handled = true; } elseif (!$current_node->isRequired()) { CHL7v2::d(" --> Segment non présent et non requis"); list($current_node, $current_group) = self::getNext($current_node, $current_group); break; } else { if (!$current_node->getParent() || $current_node->getParent()->isOpen()) { CHL7v2::d(" --> !!!!!!!!!!!!!!!!! Segment non present et groupe requis"); $this->error(CHL7v2Exception::SEGMENT_MISSING, $current_node->nodeValue); } } // le segment est multiple, on reste sur lui if ($handled && $current_node->isUnbounded()) { CHL7v2::d(" --> Segment multiple"); } else { CHL7v2::d(" --> Segment unique, passage au suivant"); list($current_node, $current_group) = self::getNext($current_node, $current_group); } break; // GROUP // // GROUP // case "group": CHL7v2::d($current_group->name . " " . $current_node->state(), "red"); $current_node->markEmpty(); if ($current_node->isUnbounded() || !$current_node->isUsed()) { $current_node->setAttribute("mbOpen", 0); CHL7v2::d(" --> Groupe multiple ou pas encore utilisé, on entre dedans"); $current_group = new CHL7v2SegmentGroup($current_group, $current_node); $current_node = $current_node->getFirstChild(); } else { CHL7v2::d(" --> Groupe utilisé ou pas multiple, on prend le parent ou frere"); list($current_node, $current_group) = self::getNext($current_node, $current_group); } break; // custom attributes, should never get there // custom attributes, should never get there default: CHL7v2::d($current_node->getName()); $current_node = $current_node->getNextSibling(); break; } } $this->purgeEmptyGroups(); // pas forcément utile : mais ceci donne tous les segments dans // l'ordre de parcours, comme si on le faisait recursivement // $c = $specs->xpath("//segment | //group"); }
/** * Build MSH segement * * @param CHL7v2Event $event Event * * @return null */ function build(CHL7v2Event $event) { parent::build($event); $message = $event->message; // Dans le cas d'un segment MSH la création peut-être soit : receiver / sender (ack) $actor = isset($event->_sender->_id) ? $event->_sender : $event->_receiver; $actor->loadRefGroup(); $actor->loadConfigValues(); $data = array(); // MSH-1: Field Separator (ST) $data[] = $message->fieldSeparator; // MSH-2: Encoding Characters (ST) $data[] = substr($message->getEncodingCharacters(), 1); // MSH-3: Sending Application (HD) (optional) $data[] = CAppUI::conf("hl7 sending_application"); // MSH-4: Sending Facility (HD) (optional) $data[] = CAppUI::conf("hl7 sending_facility"); // MSH-5: Receiving Application (HD) (optional) $data[] = isset($actor->_configs["receiving_application"]) ? $actor->_configs["receiving_application"] : $actor->nom; // MSH-6: Receiving Facility (HD) (optional) $data[] = isset($actor->_configs["receiving_facility"]) ? $actor->_configs["receiving_facility"] : $actor->nom; // MSH-7: Date/Time Of Message (TS) $data[] = CMbDT::dateTime(); // MSH-8: Security (ST) (optional) $data[] = null; // MSH-9: Message Type (MSG) $data[] = $event->msg_codes; // MSH-10: Message Control ID (ST) $data[] = $event->_exchange_hl7v2->_id; // MSH-11: Processing ID (PT) // Table 103 // D - Debugging // P - Production // T - Training $data[] = CAppUI::conf("instance_role") == "prod" ? "P" : "D"; // MSH-12: Version ID (VID) $data[] = CHL7v2::prepareHL7Version($event->version); // MSH-13: Sequence Number (NM) (optional) $data[] = null; // MSH-14: Continuation Pointer (ST) (optional) $data[] = null; // MSH-15: Accept Acknowledgment Type (ID) (optional) // Table 155 // AL - Always // NE - Never // ER - Error/reject conditions only // SU - Successful completion only $data[] = null; // MSH-16: Application Acknowledgment Type (ID) (optional) // Table 155 // AL - Always // NE - Never // ER - Error/reject conditions only // SU - Successful completion only $data[] = null; // MSH-17: Country Code (ID) (optional) // FRA = 250 $data[] = CHL7v2TableEntry::mapTo("399", "250"); // MSH-18: Character Set (ID) (optional repeating) $encoding = isset($actor->_configs["encoding"]) ? $actor->_configs["encoding"] : "UTF-8"; $data[] = CHL7v2TableEntry::mapTo("211", $encoding); // MSH-19: Principal Language Of Message (CE) (optional) $data[] = array("FR"); // MSH-20: Alternate Character Set Handling Scheme (ID) (optional) $data[] = null; // MSH-21: Message Profile Identifier (EI) (optional repeating) $data[] = null; $this->fill($data); }
/** * Get the HL7v2 mapping table values * * @param string $table The table to get * @param boolean $from_mb Get the reversed table (MB => HL7) * @param bool $get_description Return the escriptions instead of the value * * @return array The table */ static function getTable($table, $from_mb = true, $get_description = false) { if (self::$ds === null) { return; } if (self::$ds === false) { self::$ds = CSQLDataSource::get("hl7v2"); } static $tables = array(); if (isset($tables[$table][$from_mb])) { return $tables[$table][$from_mb]; } $where = array("number" => self::$ds->prepare("=%", $table)); if ($from_mb) { $cols = array("code_mb_from", $get_description ? "description" : "code_hl7_to"); } else { $cols = array("code_hl7_from", $get_description ? "description" : "code_mb_to"); } $req = new CRequest(); $req->addSelect($cols); $req->addTable("table_entry"); $req->addWhere($where); $result = self::$ds->loadHashList($req->makeSelect()); if (!$get_description) { $tables[$table][$from_mb] = $result; } return $result; }
/** * Populating QPD-3 demographics fields * * @param CMbObject $object Object * @param string $mb_field Field spec * @param string $hl7_field The number of a field * @param null $mapTo Map to table HL7 * * @return array */ function setDemographicsFields(CMbObject $object, $mb_field, $hl7_field, $mapTo = null) { if (!$object->{$mb_field}) { return; } $seg = null; switch ($object->_class) { case "CPatient": $seg = "PID"; break; case "CSejour": $seg = "PV1"; break; default: } if (!$seg) { return; } $value = $mapTo ? CHL7v2TableEntry::mapTo($mapTo, $object->{$mb_field}) : $object->{$mb_field}; $spec = $object->_specs[$mb_field]; if ($spec instanceof CDateSpec || $spec instanceof CBirthDateSpec) { $value = CHL7v2::getDate($value); } return array("@{$seg}.{$hl7_field}", $value); }