| 1 |  |  | <?php | 
            
                                                                                                            
                            
            
                                    
            
            
                | 2 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 3 |  |  | namespace SPSS\Sav\Record; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 4 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 5 |  |  | use SPSS\Buffer; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 6 |  |  | use SPSS\Exception; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 7 |  |  | use SPSS\Sav\Record; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 8 |  |  | use SPSS\Utils; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 9 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 10 |  |  | /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 11 |  |  |  * The value label records documented in this section are used for numeric and short string variables only. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 12 |  |  |  * Long string variables may have value labels, but their value labels are recorded using a different record type | 
            
                                                                                                            
                            
            
                                    
            
            
                | 13 |  |  |  * | 
            
                                                                                                            
                            
            
                                    
            
            
                | 14 |  |  |  * @see \SPSS\Sav\Record\Info\LongStringValueLabels | 
            
                                                                                                            
                            
            
                                    
            
            
                | 15 |  |  |  */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 16 |  |  | class ValueLabel extends Record | 
            
                                                                                                            
                            
            
                                    
            
            
                | 17 |  |  | { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 18 |  |  |     const TYPE = 3; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 19 |  |  |     const LABEL_MAX_LENGTH = 255; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 20 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 21 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 22 |  |  |      * @var array | 
            
                                                                                                            
                            
            
                                    
            
            
                | 23 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 24 |  |  |     public $labels = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 25 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 26 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 27 |  |  |      * @var array | 
            
                                                                                                            
                            
            
                                    
            
            
                | 28 |  |  |      * A list of dictionary indexes of variables to which to apply the value labels | 
            
                                                                                                            
                            
            
                                    
            
            
                | 29 |  |  |      * String variables wider than 8 bytes may not be specified in this list. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 30 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 31 |  |  |     public $indexes = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 32 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 33 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 34 |  |  |      * @var Variable[] | 
            
                                                                                                            
                            
            
                                    
            
            
                | 35 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 36 |  |  |     protected $variables = []; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 37 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 38 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 39 |  |  |      * @param array $variables | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 40 |  |  |      */ | 
            
                                                                        
                            
            
                                    
            
            
                | 41 |  |  |     public function setVariables($variables) | 
            
                                                                        
                            
            
                                    
            
            
                | 42 |  |  |     { | 
            
                                                                        
                            
            
                                    
            
            
                | 43 |  |  |         $this->variables = $variables; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 44 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 45 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 46 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 47 |  |  |      * @param Buffer $buffer | 
            
                                                                                                            
                            
            
                                    
            
            
                | 48 |  |  |      * @throws Exception | 
            
                                                                                                            
                            
            
                                    
            
            
                | 49 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 50 |  |  |     public function read(Buffer $buffer) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 51 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 52 |  |  |         /** @var int $labelCount Number of value labels present in this record. */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 53 |  |  |         $labelCount = $buffer->readInt(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 54 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 55 |  |  |         for ($i = 0; $i < $labelCount; $i++) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 56 |  |  |             // A numeric value or a short string value padded as necessary to 8 bytes in length. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 57 |  |  |             $value = $buffer->readDouble(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 58 |  |  |             $labelLength = ord($buffer->read(1)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 59 |  |  |             $label = $buffer->readString(Utils::roundUp($labelLength + 1, 8) - 1); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 60 |  |  |             $this->labels[] = [ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 61 |  |  |                 'value' => $value, | 
            
                                                                                                            
                            
            
                                    
            
            
                | 62 |  |  |                 'label' => rtrim($label), | 
                            
                    |  |  |  | 
                                                                                        
                                                                                     | 
            
                                                                                                            
                            
            
                                    
            
            
                | 63 |  |  |             ]; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 64 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 65 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 66 |  |  |         // The value label variables record is always immediately followed after a value label record. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 67 |  |  |         $recType = $buffer->readInt(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 68 |  |  |         if ($recType != 4) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 69 |  |  |             throw new Exception( | 
            
                                                                                                            
                            
            
                                    
            
            
                | 70 |  |  |                 sprintf('Error reading Variable Index record: bad record type [%s]. Expecting Record Type 4.', $recType) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 71 |  |  |             ); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 72 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 73 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 74 |  |  |         // Number of variables that the associated value labels from the value label record are to be applied. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 75 |  |  |         $varCount = $buffer->readInt(); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 76 |  |  |         for ($i = 0; $i < $varCount; $i++) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 77 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 78 |  |  |             $varIndex = $buffer->readInt() - 1; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 79 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 80 |  |  |             // Decode values for short variables | 
            
                                                                                                            
                            
            
                                    
            
            
                | 81 |  |  |             if (isset($this->variables[$varIndex])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 82 |  |  |                 $varWidth = $this->variables[$varIndex]->width; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 83 |  |  |                 if ($varWidth > 0) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 84 |  |  |                     foreach ($this->labels as $labelIdx => $label) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 85 |  |  |                         $this->labels[$labelIdx]['value'] = rtrim(Utils::doubleToString($label['value'])); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 86 |  |  |                     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 87 |  |  |                 } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 88 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 89 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 90 |  |  |             $this->indexes[] = $varIndex; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 91 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 92 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 93 |  |  |     } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 94 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 95 |  |  |     /** | 
            
                                                                                                            
                            
            
                                    
            
            
                | 96 |  |  |      * @param Buffer $buffer | 
            
                                                                                                            
                            
            
                                    
            
            
                | 97 |  |  |      */ | 
            
                                                                                                            
                            
            
                                    
            
            
                | 98 |  |  |     public function write(Buffer $buffer) | 
            
                                                                                                            
                            
            
                                    
            
            
                | 99 |  |  |     { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 100 |  |  |         $convertToDouble = false; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 101 |  |  |         $varIndex = reset($this->indexes); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 102 |  |  |         if ($varIndex !== false && isset($this->variables[$varIndex - 1])) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 103 |  |  |             $varWidth = $this->variables[$varIndex - 1]->width; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 104 |  |  |             $convertToDouble = $varWidth > 0; | 
            
                                                                                                            
                            
            
                                    
            
            
                | 105 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 106 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 107 |  |  |         // Value label record. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 108 |  |  |         $buffer->writeInt(self::TYPE); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 109 |  |  |         $buffer->writeInt(count($this->labels)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 110 |  |  |         foreach ($this->labels as $item) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 111 |  |  |             $labelLength = min(mb_strlen($item['label']), self::LABEL_MAX_LENGTH); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 112 |  |  |             $label = mb_substr($item['label'], 0, $labelLength); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 113 |  |  |             $labelLengthBytes = mb_strlen($label, '8bit'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 114 |  |  |             while ($labelLengthBytes > 255) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 115 |  |  |                 // Strip one char, can be multiple bytes | 
            
                                                                                                            
                            
            
                                    
            
            
                | 116 |  |  |                 $label = mb_substr($label, 0, -1); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 117 |  |  |                 $labelLengthBytes = mb_strlen($label, '8bit'); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 118 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 119 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 120 |  |  |             if ($convertToDouble) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 121 |  |  |                 $item['value'] = Utils::stringToDouble($item['value']); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 122 |  |  |             } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 123 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 124 |  |  |             $buffer->writeDouble($item['value']); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 125 |  |  |             $buffer->write(chr($labelLengthBytes)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 126 |  |  |             $buffer->writeString($label, Utils::roundUp($labelLengthBytes + 1, 8) - 1); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 127 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 128 |  |  |  | 
            
                                                                                                            
                            
            
                                    
            
            
                | 129 |  |  |         // Value label variable record. | 
            
                                                                                                            
                            
            
                                    
            
            
                | 130 |  |  |         $buffer->writeInt(4); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 131 |  |  |         $buffer->writeInt(count($this->indexes)); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 132 |  |  |         foreach ($this->indexes as $varIndex) { | 
            
                                                                                                            
                            
            
                                    
            
            
                | 133 |  |  |             $buffer->writeInt($varIndex); | 
            
                                                                                                            
                            
            
                                    
            
            
                | 134 |  |  |         } | 
            
                                                                                                            
                            
            
                                    
            
            
                | 135 |  |  |     } | 
            
                                                                                                            
                                                                
            
                                    
            
            
                | 136 |  |  | } | 
            
                                                        
            
                                    
            
            
                | 137 |  |  |  |