@@ -12,15 +12,25 @@ class CellValueFormatter
1212{
1313 /** Definition of all possible cell types */
1414 const CELL_TYPE_STRING = 'string ' ;
15- const CELL_TYPE_BOOLEAN = 'boolean ' ;
1615 const CELL_TYPE_FLOAT = 'float ' ;
16+ const CELL_TYPE_BOOLEAN = 'boolean ' ;
17+ const CELL_TYPE_DATE = 'date ' ;
18+ const CELL_TYPE_TIME = 'time ' ;
19+ const CELL_TYPE_CURRENCY = 'currency ' ;
20+ const CELL_TYPE_PERCENTAGE = 'percentage ' ;
21+ const CELL_TYPE_VOID = 'void ' ;
1722
1823 /** Definition of XML nodes names used to parse data */
1924 const XML_NODE_P = 'p ' ;
2025 const XML_NODE_S = 'text:s ' ;
2126
2227 /** Definition of XML attribute used to parse data */
2328 const XML_ATTRIBUTE_TYPE = 'office:value-type ' ;
29+ const XML_ATTRIBUTE_VALUE = 'office:value ' ;
30+ const XML_ATTRIBUTE_BOOLEAN_VALUE = 'office:boolean-value ' ;
31+ const XML_ATTRIBUTE_DATE_VALUE = 'office:date-value ' ;
32+ const XML_ATTRIBUTE_TIME_VALUE = 'office:time-value ' ;
33+ const XML_ATTRIBUTE_CURRENCY = 'office:currency ' ;
2434 const XML_ATTRIBUTE_C = 'text:c ' ;
2535
2636 /** @var \Box\Spout\Common\Escaper\ODS Used to unescape XML data */
@@ -38,45 +48,36 @@ public function __construct()
3848 /**
3949 * Returns the (unescaped) correctly marshalled, cell value associated to the given XML node.
4050 * @TODO Add other types !!
51+ * @see http://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part1.html#refTable13
4152 *
4253 * @param \DOMNode $node
43- * @return string|int|float|bool The value associated with the cell (or empty string if cell's type is undefined)
54+ * @return string|int|float|bool|\DateTime|\DateInterval|null The value associated with the cell, empty string if cell's type is void/ undefined, null on error
4455 */
4556 public function extractAndFormatNodeValue ($ node )
4657 {
4758 $ cellType = $ node ->getAttribute (self ::XML_ATTRIBUTE_TYPE );
48- $ pNodeValue = $ this ->getFirstPNodeValue ($ node );
4959
5060 switch ($ cellType ) {
5161 case self ::CELL_TYPE_STRING :
5262 return $ this ->formatStringCellValue ($ node );
5363 case self ::CELL_TYPE_FLOAT :
54- return $ this ->formatFloatCellValue ($ pNodeValue );
64+ return $ this ->formatFloatCellValue ($ node );
5565 case self ::CELL_TYPE_BOOLEAN :
56- return $ this ->formatBooleanCellValue ($ pNodeValue );
66+ return $ this ->formatBooleanCellValue ($ node );
67+ case self ::CELL_TYPE_DATE :
68+ return $ this ->formatDateCellValue ($ node );
69+ case self ::CELL_TYPE_TIME :
70+ return $ this ->formatTimeCellValue ($ node );
71+ case self ::CELL_TYPE_CURRENCY :
72+ return $ this ->formatCurrencyCellValue ($ node );
73+ case self ::CELL_TYPE_PERCENTAGE :
74+ return $ this ->formatPercentageCellValue ($ node );
75+ case self ::CELL_TYPE_VOID :
5776 default :
5877 return '' ;
5978 }
6079 }
6180
62- /**
63- * Returns the value of the first "<text:p>" node within the given node.
64- *
65- * @param \DOMNode $node
66- * @return string Value for the first "<text:p>" node or empty string if no "<text:p>" found
67- */
68- protected function getFirstPNodeValue ($ node )
69- {
70- $ nodeValue = '' ;
71- $ pNodes = $ node ->getElementsByTagName (self ::XML_NODE_P );
72-
73- if ($ pNodes ->length > 0 ) {
74- $ nodeValue = $ pNodes ->item (0 )->nodeValue ;
75- }
76-
77- return $ nodeValue ;
78- }
79-
8081 /**
8182 * Returns the cell String value.
8283 *
@@ -110,27 +111,87 @@ protected function formatStringCellValue($node)
110111 }
111112
112113 /**
113- * Returns the cell Numeric value from string of nodeValue .
114+ * Returns the cell Numeric value from the given node .
114115 *
115- * @param string $pNodeValue
116+ * @param \DOMNode $node
116117 * @return int|float The value associated with the cell
117118 */
118- protected function formatFloatCellValue ($ pNodeValue )
119+ protected function formatFloatCellValue ($ node )
119120 {
120- $ cellValue = is_int ($ pNodeValue ) ? intval ($ pNodeValue ) : floatval ($ pNodeValue );
121+ $ nodeValue = $ node ->getAttribute (self ::XML_ATTRIBUTE_VALUE );
122+ $ cellValue = is_int ($ nodeValue ) ? intval ($ nodeValue ) : floatval ($ nodeValue );
121123 return $ cellValue ;
122124 }
123125
124126 /**
125- * Returns the cell Boolean value from a specific node's Value .
127+ * Returns the cell Boolean value from the given node.
126128 *
127- * @param string $pNodeValue
129+ * @param \DOMNode $node
128130 * @return bool The value associated with the cell
129131 */
130- protected function formatBooleanCellValue ($ pNodeValue )
132+ protected function formatBooleanCellValue ($ node )
131133 {
134+ $ nodeValue = $ node ->getAttribute (self ::XML_ATTRIBUTE_BOOLEAN_VALUE );
132135 // !! is similar to boolval()
133- $ cellValue = !!$ pNodeValue ;
136+ $ cellValue = !!$ nodeValue ;
134137 return $ cellValue ;
135138 }
139+
140+ /**
141+ * Returns the cell Date value from the given node.
142+ *
143+ * @param \DOMNode $node
144+ * @return \DateTime|null The value associated with the cell or NULL if invalid date value
145+ */
146+ protected function formatDateCellValue ($ node )
147+ {
148+ try {
149+ $ nodeValue = $ node ->getAttribute (self ::XML_ATTRIBUTE_DATE_VALUE );
150+ return new \DateTime ($ nodeValue );
151+ } catch (\Exception $ e ) {
152+ return null ;
153+ }
154+ }
155+
156+ /**
157+ * Returns the cell Time value from the given node.
158+ *
159+ * @param \DOMNode $node
160+ * @return \DateInterval|null The value associated with the cell or NULL if invalid time value
161+ */
162+ protected function formatTimeCellValue ($ node )
163+ {
164+ try {
165+ $ nodeValue = $ node ->getAttribute (self ::XML_ATTRIBUTE_TIME_VALUE );
166+ return new \DateInterval ($ nodeValue );
167+ } catch (\Exception $ e ) {
168+ return null ;
169+ }
170+ }
171+
172+ /**
173+ * Returns the cell Currency value from the given node.
174+ *
175+ * @param \DOMNode $node
176+ * @return string The value associated with the cell (e.g. "100 USD" or "9.99 EUR")
177+ */
178+ protected function formatCurrencyCellValue ($ node )
179+ {
180+ $ value = $ node ->getAttribute (self ::XML_ATTRIBUTE_VALUE );
181+ $ currency = $ node ->getAttribute (self ::XML_ATTRIBUTE_CURRENCY );
182+
183+ return "$ value $ currency " ;
184+ }
185+
186+ /**
187+ * Returns the cell Percentage value from the given node.
188+ *
189+ * @param \DOMNode $node
190+ * @return int|float The value associated with the cell
191+ */
192+ protected function formatPercentageCellValue ($ node )
193+ {
194+ // percentages are formatted like floats
195+ return $ this ->formatFloatCellValue ($ node );
196+ }
136197}
0 commit comments