@@ -27,6 +27,9 @@ class ResultSet implements \Iterator, IRowContainer
2727 /** @var \PDOStatement|NULL */
2828 private $ pdoStatement ;
2929
30+ /** @var IRowNormalizer */
31+ private $ rowNormalizer ;
32+
3033 /** @var IRow */
3134 private $ result ;
3235
@@ -48,14 +51,18 @@ class ResultSet implements \Iterator, IRowContainer
4851 /** @var array */
4952 private $ types ;
5053
54+ /** @var callable|NULL */
55+ private $ rowFactory ;
56+
5157
52- public function __construct (Connection $ connection , $ queryString , array $ params )
58+ public function __construct (Connection $ connection , $ queryString , array $ params, IRowNormalizer $ normalizer )
5359 {
5460 $ time = microtime (TRUE );
5561 $ this ->connection = $ connection ;
5662 $ this ->supplementalDriver = $ connection ->getSupplementalDriver ();
5763 $ this ->queryString = $ queryString ;
5864 $ this ->params = $ params ;
65+ $ this ->rowNormalizer = $ normalizer ;
5966
6067 try {
6168 if (substr ($ queryString , 0 , 2 ) === ':: ' ) {
@@ -116,6 +123,16 @@ public function getParameters()
116123 return $ this ->params ;
117124 }
118125
126+ /**
127+ * @return array
128+ */
129+ public function getColumnTypes ()
130+ {
131+ if ($ this ->types === NULL ) {
132+ $ this ->types = (array ) $ this ->supplementalDriver ->getColumnTypes ($ this ->pdoStatement );
133+ }
134+ return $ this ->types ;
135+ }
119136
120137 /**
121138 * @return int
@@ -145,47 +162,24 @@ public function getTime()
145162
146163
147164 /**
148- * Normalizes result row.
149- * @param array
150- * @return array
165+ * @param IRowNormalizer|NULL
166+ * @return static
151167 */
152- public function normalizeRow ( $ row )
168+ public function setRowNormalizer ( $ normalizer )
153169 {
154- if ($ this ->types === NULL ) {
155- $ this ->types = (array ) $ this ->supplementalDriver ->getColumnTypes ($ this ->pdoStatement );
156- }
157-
158- foreach ($ this ->types as $ key => $ type ) {
159- $ value = $ row [$ key ];
160- if ($ value === NULL || $ value === FALSE || $ type === IStructure::FIELD_TEXT ) {
161-
162- } elseif ($ type === IStructure::FIELD_INTEGER ) {
163- $ row [$ key ] = is_float ($ tmp = $ value * 1 ) ? $ value : $ tmp ;
164-
165- } elseif ($ type === IStructure::FIELD_FLOAT ) {
166- if (($ pos = strpos ($ value , '. ' )) !== FALSE ) {
167- $ value = rtrim (rtrim ($ pos === 0 ? "0 $ value " : $ value , '0 ' ), '. ' );
168- }
169- $ float = (float ) $ value ;
170- $ row [$ key ] = (string ) $ float === $ value ? $ float : $ value ;
171-
172- } elseif ($ type === IStructure::FIELD_BOOL ) {
173- $ row [$ key ] = ((bool ) $ value ) && $ value !== 'f ' && $ value !== 'F ' ;
174-
175- } elseif ($ type === IStructure::FIELD_DATETIME || $ type === IStructure::FIELD_DATE || $ type === IStructure::FIELD_TIME ) {
176- $ row [$ key ] = new Nette \Utils \DateTime ($ value );
177-
178- } elseif ($ type === IStructure::FIELD_TIME_INTERVAL ) {
179- preg_match ('#^(-?)(\d+)\D(\d+)\D(\d+)\z# ' , $ value , $ m );
180- $ row [$ key ] = new \DateInterval ("PT $ m [2 ]H $ m [3 ]M $ m [4 ]S " );
181- $ row [$ key ]->invert = (int ) (bool ) $ m [1 ];
170+ $ this ->rowNormalizer = $ normalizer ;
171+ return $ this ;
172+ }
182173
183- } elseif ($ type === IStructure::FIELD_UNIX_TIMESTAMP ) {
184- $ row [$ key ] = Nette \Utils \DateTime::from ($ value );
185- }
186- }
187174
188- return $ this ->supplementalDriver ->normalizeRow ($ row );
175+ /**
176+ * Set a factory to create fetched object instances. These should implements the IRow interface.
177+ * @return self
178+ */
179+ public function setRowFactory (callable $ callback )
180+ {
181+ $ this ->rowFactory = $ callback ;
182+ return $ this ;
189183 }
190184
191185
@@ -255,10 +249,19 @@ public function fetch()
255249 return FALSE ;
256250 }
257251
258- $ row = new Row ;
259- foreach ($ this ->normalizeRow ($ data ) as $ key => $ value ) {
260- if ($ key !== '' ) {
261- $ row ->$ key = $ value ;
252+ if ($ this ->rowNormalizer !== NULL ) {
253+ $ data = $ this ->rowNormalizer ->normalizeRow ($ data , $ this );
254+ }
255+
256+ if ($ this ->rowFactory ) {
257+ $ row = call_user_func ($ this ->rowFactory , $ data );
258+ }
259+ else {
260+ $ row = new Row ;
261+ foreach ($ data as $ key => $ value ) {
262+ if ($ key !== '' ) {
263+ $ row ->$ key = $ value ;
264+ }
262265 }
263266 }
264267
0 commit comments