152. EPMO Open Source Coordination Office Redaction File Detail Report

Produced by Araxis Merge on 3/13/2019 2:49:54 PM Central Daylight Time. See www.araxis.com for information about Merge. This report uses XHTML and CSS2, and is best viewed with a modern standards-compliant browser. For optimum results when printing this report, use landscape orientation and enable printing of background images and colours in your browser.

152.1 Files compared

# Location File Last Modified
1 C:\AraxisMergeCompare\Pri_un\DSM\Direct_Webmail\application\libraries\patient_data Patient_id.php Tue Mar 12 21:55:40 2019 UTC
2 C:\AraxisMergeCompare\Pri_re\DSM-scrubbed\Direct_Webmail\application\libraries\patient_data Patient_id.php Wed Mar 13 04:49:14 2019 UTC

152.2 Comparison summary

Description Between
Files 1 and 2
Text Blocks Lines
Unchanged 2 926
Changed 1 2
Inserted 0 0
Removed 0 0

152.3 Comparison options

Whitespace
Character case Differences in character case are significant
Line endings Differences in line endings (CR and LF characters) are ignored
CR/LF characters Not shown in the comparison detail

152.4 Active regular expressions

No regular expressions were active.

152.5 Comparison detail

  1   <?php  if  ( ! define d('BASEPAT H')) exit( 'No direct  script ac cess allow ed');
  2  
  3   /**
  4   * @package  direct-pr oject-inno vation-ini tiative
  5   * @subpack age librar ies
  6   */ /** */
  7  
  8   require_li brary('pat ient_data/ soap_call' );
  9  
  10   /**
  11   * Looks up  patients  in the Mas ter Vetera ns Index a nd returns  a set of  matching p atients.
  12   *
  13   * @package  direct-pr oject-inno vation-ini tiative
  14   * @subpack age librar ies
  15   */ 
  16   class Pati ent_id ext ends Soap_ call {
  17   #TODO - NE ED A WSDL  URI 
  18           va r $wsdl_ur i = MVI_PA TIENT_SEAR CH_WSDL;
  19           va r $endpoin t_uri = MV I_PATIENT_ SEARCH_END POINT;
  20           va r $process ing_code =  MVI_PROCE SSING_CODE ; //indica tes why we 're making  this call  - will be  D for deb ugging, T  for traini ng, P for  production  systems
  21           va r $mvi_id_ code = '2. 16.840.1.1 13883.4.34 9'; //may  change dep ending on  dev/prod s ystem - ma ke sure to  check wit h MVI
  22           va r $vler_di rect_id_co de = '1.2. 840.114350 .1.13.0.1. 7.1.1'; // an ID code  indicatin g our syst em. I'm gu essing we' ll be assi gned this  when we're  approved  to interac t with the m?  this s hould prob ably be a  constant.   
  23           va r $vler_di rect_site_ key = '200 DSM'; //ke y for Dire ct Secure  Messaging
  24           va r $interac tion_id =  '2.16.840. 1.113883.1 .6'; //see ms to be a nother id  that we'll  be assign ed when we 're author ized to in teract wti h the syst em, but I' m not sure  on this.   
  25           
  26           pr otected $u nique_tran saction_id ; //autoge nerated ev ery time t he request  is genera ted
  27           pr otected $u nique_quer y_id; //au togenerate d every ti me the req uest is ge nerated
  28           pr otected $u ser; //set  in the co nstructor
  29           
  30           pu blic funct ion __cons truct(){
  31                    pare nt::__cons truct();
  32                    $thi s->user =  User::find _from_sess ion();
  33                    $thi s->curl_op tions = ar ray(
  34                             CURLOP T_SSLCERT  => TLS_SER VER_CERT_P ATH,
  35                             CURLOP T_SSLKEY = > TLS_SERV ER_KEY_PAT H,
  36                             CURLOP T_SSL_VERI FYHOST =>  TLS_SERVER _VERIFYHOS T,
  37                             CURLOP T_SSL_VERI FYPEER =>  TLS_SERVER _VERIFYPEE R,
  38                    );
  39           }        
  40           
  41           // returns fa lse if it  encountere d an error , or an ar ray of pat ient data  if the cal l was succ essful
  42           fu nction pat ients_matc hing_crite ria($crite ria){                   
  43                    if(e mpty($crit eria) || ! is_array($ criteria))  return $t his->CI->e rror->shou ld_be_a_no nempty_arr ay($criter ia);
  44                    
  45                    //ch eck that t he require d fields h ave been p rovided
  46                    fore ach( array ('given_na me', 'fami ly_name',  'social_se curity_num ber') as $ required_f ield){
  47                             if(!$t his->CI->i s->nonempt y_string(t rim($crite ria[$requi red_field] )))
  48                                      return $ this->CI-> error->sho uld_be_a_n onempty_st ring($crit eria[$requ ired_field ]);
  49                             $this- >$required _field = $ criteria[$ required_f ield];
  50                    }
  51                    
  52                    //ma ke sure th at the ssn  really is  an ssn an d format i t for our  query
  53                    #TOD O - Test p atients pr obably wil l not have  valid SSN s, we need  the abili ty to turn  this off  via some s ort of tes ting mode,  etc.                
  54                    if(! $this->CI- >is->strin g_like_a_s ocial_secu rity_numbe r($criteri a['social_ security_n umber'])) 
  55                             return  $this->CI ->error->s hould_be_a _social_se curity_num ber($crite ria['socia l_security _number']) ;
  56                    $thi s->social_ security_n umber = st r_replace( '-', '', $ this->soci al_securit y_number);
  57                    
  58                    //ch eck for op tional fie lds fields
  59                    if(! empty($cri teria['gen der']) &&  in_array(s trtoupper( $criteria[ 'gender']) , array('M ', 'F', 'U ')))
  60                             $this- >gender =  $criteria[ 'gender'];
  61                    if(! empty($cri teria['dat e_of_birth '])){
  62                             if(!$t his->CI->i s->mysql_d ate($crite ria['date_ of_birth'] )) return  $this->CI- >error->sh ould_be_an _x($criter ia['date_o f_birth'],  'date for matted YYY Y-MM-DD');
  63                             $this- >date_of_b irth = str _replace(' -', '', $c riteria['d ate_of_bir th']);
  64                    }
  65                    
  66                    retu rn $this-> _find_pati ents();
  67           }
  68           
  69           // returns fa lse if it  encountere d an error , or a Pat ient objec t if the c all was su ccessful
  70           fu nction pat ient_match ing_id($pa tient_id){
  71                    if(! $this->CI- >is->nonem pty_string ($patient_ id)) retur n $this->C I->error-> should_be_ a_nonempty _string($p atient_id) ;
  72                    $thi s->patient _id = $pat ient_id;
  73                    $thi s->xml_tem plate = '_ patient_de mographics ';
  74                    
  75                    $pat ients = $t his->_find _patients( );
  76                    if(! is_array($ patients))  return fa lse;
  77                    
  78                    if(c ount($pati ents) > 1)  {
  79                             log_me ssage('err or', 'MVI  returned m ore than o ne result  for search  by patien t id for ' .$this->CI ->error->d escribe($p atient_id) .', expect ing only o ne'); 
  80                    }
  81                    
  82                    retu rn element ($patient_ id, $patie nts); 
  83           }        
  84           
  85           /* * Extends  parent to  ensure tha t {@link u nique_quer y_id} is g enerated e very time  that we ge nerate the  request * /       
  86           fu nction req uest_as_xm l(){
  87                    $thi s->unique_ transactio n_id = sha 1(sha1($th is->vler_d irect_site _key . mic rotime())) ;
  88                    $thi s->unique_ query_id =  sha1($thi s->vler_di rect_site_ key . micr otime());
  89                    retu rn parent: :request_a s_xml();
  90           }
  91           
  92   ////////// ////////// ////////// ////////// //
  93   //  PROTEC TED METHOD S
  94   ////////// ////////// ////////// ////////// //
  95           
  96           pr otected fu nction _fi nd_patient s(){
  97   #                if(i s_on_local ()) return  $this->mo ck_patient s();
  98                    
  99                    //ma ke the act ual call
  100                    $res ponse_data  = $this-> call();
  101                    if(e mpty($resp onse_data) ) return f alse; //en countered  error whil e trying t o make the  call; cal l() will p rovide err or message
  102                    
  103   #TODO - co nfirm enco ding
  104   #TODO - re cognize to o many pat ients
  105   #TODO - re cognize no  patients            
  106                    //se t up objec t to parse  the respo nse data a s xml
  107                    $dom  = new DOM Document(' 1.0', 'UTF -8');
  108                    $dom ->encoding  = 'utf-8' ;
  109                    $dom ->formatOu tput = FAL SE;
  110                    $dom ->preserve WhiteSpace  = TRUE;
  111                    $dom ->substitu teEntities  = TRUE;
  112                    $dom ->loadXML( $response_ data);
  113                    
  114                    //se arch for t he <subjec t> element s that rep resent pat ients.
  115                    #TOD O - RECOGN IZE A RESP ONSE WITH  NO PATIENS T
  116                    $xpa th = new D OMXPath($d om);    
  117                    $xpa th->regist erNamespac e('x', 'ur n:hl7-org: v3'); //ar gsblargle.   Looks li ke PHP won 't let us  add a name space with out an ide ntifier, s o we'll us e the all- purposeful  x.
  118                     $xpath->re gisterName space('idm ', 'http:/ / URL           . DOMAIN . EXT ');
  119                    
  120   #                $xpa th->regist erNamespac e('xsi', ' http://www .w3.org/20 01/XMLSche ma-instanc e');
  121                    $pat ient_nodes  = $xpath- >query('// idm:PRPA_I N201306UV0 2/x:contro lActProces s//x:patie nt');                
  122  
  123                    if(! is_a($pati ent_nodes,  'DOMNodeL ist') || ! $this->CI- >is->nonze ro_unsigne d_integer( $patient_n odes->leng th)){                              
  124                             //chec k to see i f we have  an AA ackn owledgment  - if not,  there was  something  wrong wit h our quer y
  125                             $accep tability_a cknowledge ment = $xp ath->query ('//idm:PR PA_IN20130 6UV02/x:ac knowledgem ent/x:type Code[@code ="AA"]');      
  126                             if(!$t his->CI->i s->nonzero _unsigned_ integer($a cceptabili ty_acknowl edgement-> length)){
  127                                      log_mess age('debug ', 'MVI in dicates th at our sea rch query  was malfor med');
  128                                      return f alse;
  129                             }
  130                             
  131                             //we m ight not h ave patien t nodes ju st because  there are  no result s
  132                             $not_f ound = $xp ath->query ('//idm:PR PA_IN20130 6UV02/x:co ntrolActPr ocess/x:qu eryAck/x:q ueryRespon seCode[@co de="NF"]') ;
  133                             if($th is->CI->is ->nonzero_ unsigned_i nteger($no t_found->l ength)){
  134                                      return a rray(); // no patient s found, n o need for  an error  message
  135                             }                                  
  136                             
  137                             //chec k to see i f we have  a QE query  error - i f we have  AA + QE, t hen there  were too m any patien ts returne d
  138                             $query _error = $ xpath->que ry('//idm: PRPA_IN201 306UV02/x: controlAct Process/x: queryAck/x :queryResp onseCode[@ code="QE"] ');
  139                             if($th is->CI->is ->nonzero_ unsigned_i nteger($qu ery_error- >length)){
  140                                      $this->f eedback_me ssages[] =  'Your sea rch matche d more pat ients than  could be  returned.   Please na rrow your  search ter ms and try  again.';
  141                                      return f alse;
  142                             }        
  143  
  144                             if(!is _a($patien t_nodes, ' DOMNodeLis t')) retur n $this->C I->error-> warning('U nknown err or: unable  to parse  MVI respon se');                         
  145                    }
  146  
  147                    $pat ients = ar ray();
  148                    fore ach($patie nt_nodes a s $patient _node){
  149                             #TODO  - prefix,  suffix
  150                             #TODO  - assignin g facility ?
  151                             #TODO  - Legal na mes vs ali ases/maide n names
  152                             #TODO  - Include  current ad dress in r esults?
  153                             
  154                             $patie nt = new P atient($pa tient_node , $xpath);
  155                             if(!em pty($patie nt->icn()) )
  156                                      $patient s[$patient ->icn()] =  $patient;  //patient s aren't r eally pati ents if we  can't fin d their IC N
  157  
  158                    }
  159                    
  160                    retu rn $patien ts;
  161           }
  162                    
  163           // for testin g purposes
  164           pr otected fu nction moc k_patients (){
  165   # CHECK WI TH MARGARE T BEFORE D ELETING -  SHE HAS SP ECIFIC CAS ES SHE'S T ESTING USI NG THIS DA TA             
  166                    $moc k_data = a rray( '101 2663662V72 9834' => a rray( 'giv en_names'  => array(' NWHINELVEN '), 
  167                                                                                                                                'famil y_name' =>  'NWHINZZZ TESTPATIEN T',
  168                                                                                                                                'ssn'  => '111223 333',
  169                                                                                                                               ),
  170                                                                                                                              
  171                                                                '123 456789' =>  array( 'g iven_names ' => array ('Cecilia' , 'Helena' ), 
  172                                                                                                              'f amily_name ' => 'Payn e-Gaposchk in',
  173                                                                                                              'p refix' =>  'Dr.',
  174                                                                                                              'g ender' =>  'f',
  175                                                                                                              'a ssigning_f acility' = > 'Harvard  Universit y', //Need  to find o ut what th e actual f ormat for  this will  be
  176                                                                                                              'i d_state' = > 'Deactiv ated', //f ormat?
  177                                                                                                              'd ate_of_bir th' => '19 000510', / / 5/10/190 0 //note t hat this c an apparen tly be a r ange of da tes - we'l l need to  know how t o parse it .  Also, d ates befor e 1970 - d o they use  negatives ?
  178                                                                                                              'd ate_of_dea th' => '19 791207', / / 12/7/197 9
  179                                                                                                              's sn' => '11 1111111',
  180                                                                                                             ),
  181                                                                                                              
  182                                                                '987 654321' =>  array( 'g iven_names ' => array ('Bonnie',  'Jeanne')
  183                                                                                                              'f amily_name ' => 'Dunb ar',
  184                                                                                                              'p refix' =>  'Dr.',
  185                                                                                                              'g ender' =>  'f',
  186                                                                                                              'a ssigning_f acility' = > 'NASA',  //Need to  find out w hat the ac tual forma t for this  will be
  187                                                                                                              'i d_state' = > 'Tempora ry', //for mat?
  188                                                                                                              'd ate_of_bir th' => '19 490303', / / 3/3/1949
  189                                                                                                              's sn' => '22 2222222',
  190                                                                                                             ),
  191                                                                '654 321987' =>  array( 'g iven_names ' => array ('Eugene',  'Francis' ), 
  192                                                                                                              'f amily_name ' => 'Kran z',
  193                                                                                                              'p refix' =>  'Mr.',
  194                                                                                                              'g ender' =>  'm',
  195                                                                                                              'a ssigning_f acility' = > 'NASA',  //Need to  find out w hat the ac tual forma t for this  will be
  196                                                                                                              'i d_state' = > 'Permane nt', //for mat?
  197                                                                                                              'd ate_of_bir th' => '19 330817', / / 8/17/193 3
  198                                                                                                              's sn' => '33 333333',
  199                                                                                                             ),
  200                                                                '754 321987' =>  array( 'g iven_names ' => array ('Edward')
  201                                                                                                              'f amily_name ' => 'Sabi ne',
  202                                                                                                              'p refix' =>  'Sir',
  203                                                                                                              's uffix' =>  'KCB FRS',
  204                                                                                                              'g ender' =>  'm',
  205                                                                                                              'a ssigning_f acility' = > 'Royal M ilitary Ac ademy', // Need to fi nd out wha t the actu al format  for this w ill be
  206                                                                                                              'i d_state' = > 'Deactiv ated', //f ormat?
  207                                                                                                              'd ate_of_bir th' => '17 881014', / / 10/14/17 88
  208                                                                                                              'd ate_of_dea th' => '18 830626', / /6/26/1883
  209                                                                                                              's sn' => '44 44444444'
  210                                                                                                             ),
  211                                                                '754 321887' =>  array( 'g iven_names ' => array ('Eden'), 
  212                                                                                                              'f amily_name ' => 'Atwo od',
  213                                                                                                              'g ender' =>  'u',
  214                                                                                                              'a ssigning_f acility' = > 'Concord  Records',  //Need to  find out  what the a ctual form at for thi s will be
  215                                                                                                              'i d_state' = > 'Permane nt', //for mat?
  216                                                                                                              'd ate_of_bir th' => '19 690111', / / 1/11/196 9
  217                                                                                                              's sn' => '55 55555555'
  218                                                                                                             ),
  219                                                                '754 321888' =>  array( 'g iven_names ' => array ('Marie',  'Charlotte ', 'Amalie ', 'Ernest ine', 'Wil helmine',  'Philippin e'), 
  220                                                                                                              's uffix' =>  'H.R.H.',
  221                                                                                                              'g ender' =>  'f',
  222                                                                                                              'a ssigning_f acility' = > 'House o f Saxe-Got ha-Altenbu rg', 
  223                                                                                                              'i d_state' = > 'Deactiv ated', //f ormat?
  224                                                                                                              'd ate_of_bir th' => -68 89030019,  // 9/11/17 51
  225                                                                                                              'd ate_of_dea th' => -45 02748419,  // 4/25/18 27
  226                                                                                                             ),
  227                                                                '794 321888' =>  array( 'g iven_names ' => array ('Johannes  Müller')
  228                                                                                                              'f amily_name ' => 'von  Königsber g',
  229                                                                                                              'g ender' =>  'm',
  230                                                                                                              'a ssigning_f acility' = > 'Holy Ro man Empire ', 
  231                                                                                                              'i d_state' = > 'Deactiv ated', //f ormat?
  232                                                                                                              'd ate_of_bir th' => -16 837817219,  // 6/6/14 36
  233                                                                                                              'd ate_of_dea th' => -15 572921219,  // 7/6/14 76
  234                                                                                                             ),                                                                                                                                                                                                                                                     
  235                                                                                                                              
  236                                                                                                                                                                                                                       
  237                                                ); 
  238  
  239                    
  240                    fore ach($mock_ data as $i cn => $dat a){
  241                             $data[ 'icn'] = $ icn;
  242                             $mock_ data[$icn]  = new Pat ient($data );
  243                    }
  244                    
  245                    retu rn $mock_d ata;               
  246           }        
  247           
  248  
  249   }
  250  
  251   #TODO - ab andon this  class or  put it in  its own li brary (mod el?)
  252   class Pati ent{
  253           pr otected $d om_element
  254           
  255           // raw vars a re exactly  the value  given by  ICN; these  will be f ormatted e lsewhere
  256           pr otected $r aw_icn;
  257           pr otected $r aw_ssn;
  258           
  259           pr otected $r aw_prefix;
  260           pr otected $r aw_given_n ames;
  261           pr otected $r aw_family_ name;
  262           pr otected $r aw_suffix;
  263           
  264           pr otected $r aw_gender;
  265           pr otected $r aw_assigni ng_facilit y;
  266           pr otected $r aw_date_of _birth; // formatted  YYYYMMDD o r YYYYMMDD HHMMSS
  267           pr otected $r aw_date_of _death; // formatted  YYYYMMDD o r YYYYMMDD HHMMSS
  268           pr otected $r aw_id_stat e; 
  269           
  270           
  271           fu nction __c onstruct($ patient_no de_or_valu es = array (), $xpath =null){
  272                    $thi s->is = ge t_instance ()->is;
  273                    $thi s->error =  get_insta nce()->err or;
  274                    
  275                    if(i s_a($patie nt_node_or _values, ' DOMElement ')){
  276                             $this- >xpath = $ xpath;
  277                             $this- >load_valu es_from_do m_element( $patient_n ode_or_val ues);
  278                    }els eif(is_arr ay($patien t_node_or_ values))
  279                             $this- >load_valu es_from_ar ray($patie nt_node_or _values);
  280                    else  
  281                             return  $this->er ror->shoul d_be_an_ar ray_or_DOM Element_ob ject($pati ent_node_o r_values);
  282                             
  283           }
  284           
  285           pu blic funct ion hidden _field_mar kup($root_ tag_name =  'patient' ){
  286                    if(! $this->is- >nonempty_ string_wit h_no_white space($roo t_tag_name )) return  $this->err or->should _be_a_none mpty_strin g_with_no_ whitespace ($root_tag _name);
  287                    
  288                    $mar kup = '';
  289                    fore ach($this- >raw_value s as $prop erty => $v alue){
  290                             if(!is _null($val ue)) $mark up .= form _hidden($r oot_tag_na me.'['.$pr operty.']' , $value);
  291                    }
  292                    
  293                    retu rn $markup ;
  294           }
  295           
  296           pu blic funct ion raw_va lues(){
  297                    $val ues = get_ object_var s($this);
  298                    unse t($values[ 'is'], $va lues['erro r'], $valu es['dom_el ement'], $ values['xp ath']); // these are  not useful  values to  output
  299                    fore ach($value s as $prop erty => $v alue){
  300                             if(str ing_begins _with('raw _', $prope rty)){
  301                                      $values[ strip_from _beginning ('raw_', $ property)]  = $value;
  302                                      unset($v alues[$pro perty]);
  303                             }
  304                    }
  305                    retu rn $values ;
  306           }
  307           
  308           pu blic funct ion values (){
  309                    $val ues = get_ object_var s($this);
  310                    unse t($values[ 'is'], $va lues['erro r'], $valu es['dom_el ement'], $ values['xp ath']); // these are  not useful  values to  output
  311                    fore ach($value s as $prop erty => $v alue){
  312                             if(str ing_begins _with('raw _', $prope rty)){       
  313                                      $non_raw _property  = strip_fr om_beginni ng('raw_',  $property );                      
  314                                      if(!arra y_key_exis ts($non_ra w_property , $values) )
  315                                               $values[$n on_raw_pro perty] = $ this->$non _raw_prope rty;
  316                                      unset($v alues[$pro perty]);
  317                             }
  318                    }
  319                    retu rn $values ;
  320           }
  321                    
  322           // ////////// ////////// /
  323           //  DOM-PARSI NG METHODS
  324           // ////////// ////////// /
  325           
  326           
  327           pr otected fu nction loa d_values_f rom_dom_el ement($dom _element){
  328                    if(! is_a($dom_ element, ' DOMElement ')) return  get_insta nce()->err or->should _be_a_DOME lement_obj ect($dom_e lement);
  329                    if($ dom_elemen t->tagName  != 'patie nt') retur n get_inst ance()->er ror->shoul d_be_a_pat ient_DOMEl ement_obje ct($dom_el ement);
  330                    
  331                    $thi s->dom_ele ment = $do m_element;
  332  
  333                    $thi s->raw_icn  = $this-> value_for_ attribute( 'extension ', 'x:id[@ root="'.ge t_instance ()->patien t_id->mvi_ id_code.'" ]');
  334   #                $thi s->raw_ssn  = $this-> value_for_ attribute( 'extension ', 'x:id[@ root="2.16 .840.1.113 883.4.1"]' );
  335                    $thi s->raw_ssn  = $this-> value_for_ attribute( 'extension ', 'x:pati entPerson/ x:asOtherI Ds[@classC ode="SSN"] /x:id[@roo t="2.16.84 0.1.113883 .4.1"]');
  336                    $thi s->raw_id_ state = $t his->value _for_attri bute('code ', 'x:stat usCode[@co de]');
  337                    $thi s->raw_dat e_of_birth  = $this-> value_for_ attribute( 'value', ' x:patientP erson/x:bi rthTime[@v alue]');
  338                    $thi s->raw_dat e_of_death  = $this-> value_for_ attribute( 'value', ' x:patientP erson/x:de ceasedTime [@value]') ;
  339                    $thi s->raw_gen der = $thi s->value_f or_attribu te('code',  'x:patien tPerson/x: administra tiveGender Code[@code ]');
  340                    $thi s->raw_giv en_names =  $this->va lues_for_t ag('x:pati entPerson/ x:name[@us e="L"]/x:g iven');
  341                    $thi s->raw_fam ily_name =  $this->va lue_for_ta g('x:patie ntPerson/x :name[@use ="L"]/x:fa mily');
  342                    $thi s->raw_pre fix = $thi s->value_f or_tag('x: patientPer son/x:name [@use="L"] /x:prefix' );  
  343                    $thi s->raw_suf fix = $thi s->value_f or_tag('x: patientPer son/x:name [@use="L"] /x:suffix' );           
  344           }
  345           
  346           pr otected fu nction val ue_for_att ribute($at tribute, $ xpath_for_ tag){
  347                    $val ues = $thi s->values_ for_attrib ute($attri bute, $xpa th_for_tag );
  348                    if(! is_array($ values)) r eturn fals e; //we en countered  an error
  349                    if(c ount($valu es) > 1) $ this->erro r->warning ('More tha n one tag  with attri bute '.$at tribute.'  matched '. $xpath_for _tag.'; ig noring all  but the f irst');
  350                    retu rn first_e lement($va lues);
  351           }
  352           
  353           pr otected fu nction val ues_for_at tribute($a ttribute,  $xpath_for _tag){
  354                    if(! $this->is- >nonempty_ string($at tribute))  return $th is->error- >should_be _a_nonempt y_string($ attribute) ;
  355                    if(! $this->is- >nonempty_ string($xp ath_for_ta g)) return  $this->er ror->shoul d_be_a_non empty_stri ng($xpath_ for_tag);
  356           
  357                    $xpa th_results  = $this-> xpath->que ry($xpath_ for_tag, $ this->dom_ element);
  358                    
  359                    if(! is_a($xpat h_results,  'DOMNodeL ist') || $ xpath_resu lts->lengt h < 1) ret urn array( );
  360                    
  361                    $val ues = arra y();
  362                    fore ach($xpath _results a s $xpath_r esult){                                           
  363                             if($xp ath_result ->hasAttri bute($attr ibute)) 
  364                                      $values[ ] = $xpath _result->g etAttribut e($attribu te);
  365                    }
  366                    retu rn $values ;
  367           }
  368           
  369           pr otected fu nction val ue_for_tag ($xpath_fo r_tag){
  370                    $val ues = $thi s->values_ for_tag($x path_for_t ag);
  371                    if(! is_array($ values)) r eturn fals e; //we en countered  an error
  372                    if(c ount($valu es) > 1) $ this->erro r->warning ('More tha n one tag  matched '. $xpath_for _tag.'; ig noring all  but the f irst');
  373                    retu rn first_e lement($va lues);
  374           
  375           }
  376           
  377           pr otected fu nction val ues_for_ta g($xpath_f or_tag){
  378                    if(! $this->is- >nonempty_ string($xp ath_for_ta g)) return  $this->er ror->shoul d_be_a_non empty_stri ng($xpath_ for_tag);
  379           
  380                    $xpa th_results  = $this-> xpath->que ry($xpath_ for_tag, $ this->dom_ element);
  381                    if(! is_a($xpat h_results,  'DOMNodeL ist') || $ xpath_resu lts->lengt h < 1) ret urn array( );
  382                    
  383                    $val ues = arra y();
  384                    fore ach($xpath _results a s $xpath_r esult){
  385                             $value s[] = $xpa th_result- >textConte nt;
  386                    }
  387           
  388                    retu rn $values ;
  389           }
  390           
  391           fu nction ful l_name(){
  392                    $nam e = implod e_nonempty (' ', arra y($this->p refix, imp lode(' ',  $this->giv en_names),  $this->fa mily_name) );
  393                    if(! empty($thi s->raw_suf fix)) $nam e .= ', '. $this->suf fix;
  394                    retu rn $name;
  395           }
  396           
  397           fu nction dat e_of_birth (){
  398                    if(e mpty($this ->raw_date _of_birth) ) return ' Unknown';
  399                    retu rn $this-> human_read able_date( $this->raw _date_of_b irth);
  400           }
  401           
  402           fu nction dat e_of_death (){
  403                    if(e mpty($this ->raw_date _of_death) ) return ' &mdash;';
  404                    retu rn $this-> human_read able_date( $this->raw _date_of_d eath);
  405           }
  406           
  407           fu nction gen der(){
  408                    retu rn element (strtouppe r($this->r aw_gender) , array('F ' => 'Fema le', 'M' = > 'Male',  'U' => 'Un differenti ated'));
  409           }
  410  
  411           fu nction icn (){
  412                    if(! string_con tains('^',  (string)$ this->raw_ icn)) retu rn $this-> raw_icn; / /just in c ase they e ver start  formatting  this diff erently
  413                    retu rn substr( $this->raw _icn, 0, s trpos($thi s->raw_icn , '^'));
  414           }
  415  
  416           fu nction id_ state(){
  417                    retu rn ucfirst ($this->ra w_id_state );
  418           }        
  419           
  420           fu nction ssn (){
  421                    $ssn  = $this-> raw_ssn;
  422                    if(e mpty($ssn)  || !is_st ring($ssn) ) return ' &mdash;';
  423                    
  424                    if(s tring_cont ains('^',  $ssn))
  425                             $ssn =  substr($s sn, 0, str pos($ssn,  '^'));
  426                    retu rn substr( $ssn, 0, 3 ).'-'.subs tr($ssn, 3 , 2).'-'.s ubstr($ssn , 5, 4);
  427           }
  428           
  429           pr otected fu nction hum an_readabl e_date($ti mestamp){
  430                    if(e mpty($time stamp) ||  !is_numeri c($timesta mp) || str len($times tamp) < 8)  return fa lse; //we  don't know  what to d o with it  if we don' t have YYY YMMDD
  431                    
  432                    //MV I doesn't  use unix t imestamps  - they ret urn dates  as YYYYMMD D or YYYYM MDDHHMMSSS
  433                    $yea r = substr ($timestam p, 0, 4);
  434                    $mon th = subst r($timesta mp, 4, 2);
  435                    $day  = substr( $timestamp , 6, 2);
  436                    
  437                    retu rn $month. '/'.$day.' /'.$year;
  438           }
  439           
  440           pr otected fu nction loa d_values_f rom_array( $values){
  441                    fore ach($value s as $prop erty => $v alue){
  442                             $raw_p roperty =  'raw_'.$pr operty;
  443                             if(pro perty_exis ts(get_cla ss($this),  $raw_prop erty))
  444                                      $this->$ raw_proper ty = $valu e;
  445                             else
  446                                      $this->$ property =  $value;
  447                    }
  448           }
  449           
  450           fu nction __g et($proper ty){
  451                    $raw _property  = 'raw_'.$ property;        
  452                    
  453                    if(m ethod_exis ts(get_cla ss($this),  $property ))
  454                             return  $this->$p roperty();
  455                    else if(propert y_exists(g et_class($ this), $pr operty))
  456                             return  $this->$p roperty; / /we're hit ting this  because we 're out of  scope, bu t we don't  mind givi ng read-on ly access               
  457                    else if(propert y_exists(g et_class($ this), $ra w_property ))
  458                             return  $this->$r aw_propert y;    
  459  
  460                    get_ instance() ->error->p roperty_do es_not_exi st($proper ty, get_cl ass($this) , 1);
  461                    retu rn null;
  462           }        
  463           
  464   }