r111592 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r111591‎ | r111592 | r111593 >
Date:22:56, 15 February 2012
Author:jeroendedauw
Status:ok
Tags:
Comment:
Move to EP untill slush ends
Modified paths:
  • /trunk/extensions/EducationProgram/includes/DBDataObject.php (added) (history)
  • /trunk/phase3/includes/DBDataObject.php (deleted) (history)

Diff [purge]

Index: trunk/phase3/includes/DBDataObject.php
@@ -1,640 +0,0 @@
2 -<?php
3 -
4 -/**
5 - * Abstract base class for representing objects that are stored in some DB table.
6 - * This is basically an ORM-like wrapper around rows in database tables that
7 - * aims to be both simple and very flexible. It is centered around an associative
8 - * array of fields and various methods to do common interaction with the database.
9 - *
10 - * These methods must be implemented in deriving classes:
11 - * * getDBTable
12 - * * getFieldPrefix
13 - * * getFieldTypes
14 - *
15 - * These methods are likely candidates for overriding:
16 - * * getDefaults
17 - * * remove
18 - * * insert
19 - * * saveExisting
20 - * * loadSummaryFields
21 - * * getSummaryFields
22 - *
23 - * Main instance methods:
24 - * * getField(s)
25 - * * setField(s)
26 - * * save
27 - * * remove
28 - *
29 - * Main static methods:
30 - * * select
31 - * * update
32 - * * delete
33 - * * count
34 - * * has
35 - * * selectRow
36 - * * selectFields
37 - * * selectFieldsRow
38 - *
39 - * @since 1.20
40 - *
41 - * @file DBDataObject.php
42 - *
43 - * @licence GNU GPL v2 or later
44 - * @author Jeroen De Dauw < jeroendedauw@gmail.com >
45 - */
46 -abstract class DBDataObject {
47 -
48 - /**
49 - * The fields of the object.
50 - * field name (w/o prefix) => value
51 - *
52 - * @since 1.20
53 - * @var array
54 - */
55 - protected $fields = array( 'id' => null );
56 -
57 - /**
58 - * @since 1.20
59 - * @var DBTable
60 - */
61 - protected $table;
62 -
63 - /**
64 - * If the object should update summaries of linked items when changed.
65 - * For example, update the course_count field in universities when a course in courses is deleted.
66 - * Settings this to false can prevent needless updating work in situations
67 - * such as deleting a university, which will then delete all it's courses.
68 - *
69 - * @since 1.20
70 - * @var bool
71 - */
72 - protected $updateSummaries = true;
73 -
74 - /**
75 - * Indicates if the object is in summary mode.
76 - * This mode indicates that only summary fields got updated,
77 - * which allows for optimizations.
78 - *
79 - * @since 1.20
80 - * @var bool
81 - */
82 - protected $inSummaryMode = false;
83 -
84 - /**
85 - * Constructor.
86 - *
87 - * @since 1.20
88 - *
89 - * @param DBTable $table
90 - * @param array|null $fields
91 - * @param boolean $loadDefaults
92 - */
93 - public function __construct( DBTable $table, $fields = null, $loadDefaults = false ) {
94 - $this->table = $table;
95 -
96 - if ( !is_array( $fields ) ) {
97 - $fields = array();
98 - }
99 -
100 - if ( $loadDefaults ) {
101 - $fields = array_merge( $this->table->getDefaults(), $fields );
102 - }
103 -
104 - $this->setFields( $fields );
105 - }
106 -
107 - /**
108 - * Load the specified fields from the database.
109 - *
110 - * @since 1.20
111 - *
112 - * @param array|null $fields
113 - * @param boolean $override
114 - * @param boolean $skipLoaded
115 - *
116 - * @return bool Success indicator
117 - */
118 - public function loadFields( $fields = null, $override = true, $skipLoaded = false ) {
119 - if ( is_null( $this->getId() ) ) {
120 - return false;
121 - }
122 -
123 - if ( is_null( $fields ) ) {
124 - $fields = array_keys( $this->table->getFieldTypes() );
125 - }
126 -
127 - if ( $skipLoaded ) {
128 - $fields = array_diff( $fields, array_keys( $this->fields ) );
129 - }
130 -
131 - if ( count( $fields ) > 0 ) {
132 - $result = $this->table->rawSelectRow(
133 - $this->table->getPrefixedFields( $fields ),
134 - array( $this->table->getPrefixedField( 'id' ) => $this->getId() ),
135 - array( 'LIMIT' => 1 )
136 - );
137 -
138 - if ( $result !== false ) {
139 - $this->setFields( $this->table->getFieldsFromDBResult( $result ), $override );
140 - return true;
141 - }
142 -
143 - return false;
144 - }
145 -
146 - return true;
147 - }
148 -
149 - /**
150 - * Gets the value of a field.
151 - *
152 - * @since 1.20
153 - *
154 - * @param string $name
155 - * @param mixed $default
156 - *
157 - * @throws MWException
158 - * @return mixed
159 - */
160 - public function getField( $name, $default = null ) {
161 - if ( $this->hasField( $name ) ) {
162 - return $this->fields[$name];
163 - } elseif ( !is_null( $default ) ) {
164 - return $default;
165 - } else {
166 - throw new MWException( 'Attempted to get not-set field ' . $name );
167 - }
168 - }
169 -
170 - /**
171 - * Gets the value of a field but first loads it if not done so already.
172 - *
173 - * @since 1.20
174 - *
175 - * @param string$name
176 - *
177 - * @return mixed
178 - */
179 - public function loadAndGetField( $name ) {
180 - if ( !$this->hasField( $name ) ) {
181 - $this->loadFields( array( $name ) );
182 - }
183 -
184 - return $this->getField( $name );
185 - }
186 -
187 - /**
188 - * Remove a field.
189 - *
190 - * @since 1.20
191 - *
192 - * @param string $name
193 - */
194 - public function removeField( $name ) {
195 - unset( $this->fields[$name] );
196 - }
197 -
198 - /**
199 - * Returns the objects database id.
200 - *
201 - * @since 1.20
202 - *
203 - * @return integer|null
204 - */
205 - public function getId() {
206 - return $this->getField( 'id' );
207 - }
208 -
209 - /**
210 - * Sets the objects database id.
211 - *
212 - * @since 1.20
213 - *
214 - * @param integer|null $id
215 - */
216 - public function setId( $id ) {
217 - return $this->setField( 'id', $id );
218 - }
219 -
220 - /**
221 - * Gets if a certain field is set.
222 - *
223 - * @since 1.20
224 - *
225 - * @param string $name
226 - *
227 - * @return boolean
228 - */
229 - public function hasField( $name ) {
230 - return array_key_exists( $name, $this->fields );
231 - }
232 -
233 - /**
234 - * Gets if the id field is set.
235 - *
236 - * @since 1.20
237 - *
238 - * @return boolean
239 - */
240 - public function hasIdField() {
241 - return $this->hasField( 'id' )
242 - && !is_null( $this->getField( 'id' ) );
243 - }
244 -
245 - /**
246 - * Sets multiple fields.
247 - *
248 - * @since 1.20
249 - *
250 - * @param array $fields The fields to set
251 - * @param boolean $override Override already set fields with the provided values?
252 - */
253 - public function setFields( array $fields, $override = true ) {
254 - foreach ( $fields as $name => $value ) {
255 - if ( $override || !$this->hasField( $name ) ) {
256 - $this->setField( $name, $value );
257 - }
258 - }
259 - }
260 -
261 - /**
262 - * Gets the fields => values to write to the table.
263 - *
264 - * @since 1.20
265 - *
266 - * @return array
267 - */
268 - protected function getWriteValues() {
269 - $values = array();
270 -
271 - foreach ( $this->table->getFieldTypes() as $name => $type ) {
272 - if ( array_key_exists( $name, $this->fields ) ) {
273 - $value = $this->fields[$name];
274 -
275 - switch ( $type ) {
276 - case 'array':
277 - $value = (array)$value;
278 - case 'blob':
279 - $value = serialize( $value );
280 - }
281 -
282 - $values[$this->table->getPrefixedField( $name )] = $value;
283 - }
284 - }
285 -
286 - return $values;
287 - }
288 -
289 - /**
290 - * Serializes the object to an associative array which
291 - * can then easily be converted into JSON or similar.
292 - *
293 - * @since 1.20
294 - *
295 - * @param null|array $fields
296 - * @param boolean $incNullId
297 - *
298 - * @return array
299 - */
300 - public function toArray( $fields = null, $incNullId = false ) {
301 - $data = array();
302 - $setFields = array();
303 -
304 - if ( !is_array( $fields ) ) {
305 - $setFields = $this->getSetFieldNames();
306 - } else {
307 - foreach ( $fields as $field ) {
308 - if ( $this->hasField( $field ) ) {
309 - $setFields[] = $field;
310 - }
311 - }
312 - }
313 -
314 - foreach ( $setFields as $field ) {
315 - if ( $incNullId || $field != 'id' || $this->hasIdField() ) {
316 - $data[$field] = $this->getField( $field );
317 - }
318 - }
319 -
320 - return $data;
321 - }
322 -
323 - /**
324 - * Load the default values, via getDefaults.
325 - *
326 - * @since 1.20
327 - *
328 - * @param boolean $override
329 - */
330 - public function loadDefaults( $override = true ) {
331 - $this->setFields( $this->table->getDefaults(), $override );
332 - }
333 -
334 - /**
335 - * Writes the answer to the database, either updating it
336 - * when it already exists, or inserting it when it doesn't.
337 - *
338 - * @since 1.20
339 - *
340 - * @return boolean Success indicator
341 - */
342 - public function save() {
343 - if ( $this->hasIdField() ) {
344 - return $this->saveExisting();
345 - } else {
346 - return $this->insert();
347 - }
348 - }
349 -
350 - /**
351 - * Updates the object in the database.
352 - *
353 - * @since 1.20
354 - *
355 - * @return boolean Success indicator
356 - */
357 - protected function saveExisting() {
358 - $dbw = wfGetDB( DB_MASTER );
359 -
360 - $success = $dbw->update(
361 - $this->table->getDBTable(),
362 - $this->getWriteValues(),
363 - array( $this->table->getPrefixedField( 'id' ) => $this->getId() ),
364 - __METHOD__
365 - );
366 -
367 - return $success;
368 - }
369 -
370 - /**
371 - * Inserts the object into the database.
372 - *
373 - * @since 1.20
374 - *
375 - * @return boolean Success indicator
376 - */
377 - protected function insert() {
378 - $dbw = wfGetDB( DB_MASTER );
379 -
380 - $result = $dbw->insert(
381 - $this->table->getDBTable(),
382 - $this->getWriteValues(),
383 - __METHOD__,
384 - array( 'IGNORE' )
385 - );
386 -
387 - if ( $result ) {
388 - $this->setField( 'id', $dbw->insertId() );
389 - }
390 -
391 - return $result;
392 - }
393 -
394 - /**
395 - * Removes the object from the database.
396 - *
397 - * @since 1.20
398 - *
399 - * @return boolean Success indicator
400 - */
401 - public function remove() {
402 - $this->beforeRemove();
403 -
404 - $success = $this->table->delete( array( 'id' => $this->getId() ) );
405 -
406 - if ( $success ) {
407 - $this->onRemoved();
408 - }
409 -
410 - return $success;
411 - }
412 -
413 - /**
414 - * Gets called before an object is removed from the database.
415 - *
416 - * @since 1.20
417 - */
418 - protected function beforeRemove() {
419 - $this->loadFields( $this->getBeforeRemoveFields(), false, true );
420 - }
421 -
422 - /**
423 - * Before removal of an object happens, @see beforeRemove gets called.
424 - * This method loads the fields of which the names have been returned by this one (or all fields if null is returned).
425 - * This allows for loading info needed after removal to get rid of linked data and the like.
426 - *
427 - * @since 1.20
428 - *
429 - * @return array|null
430 - */
431 - protected function getBeforeRemoveFields() {
432 - return array();
433 - }
434 -
435 - /**
436 - * Gets called after successfull removal.
437 - * Can be overriden to get rid of linked data.
438 - *
439 - * @since 1.20
440 - */
441 - protected function onRemoved() {
442 - $this->setField( 'id', null );
443 - }
444 -
445 - /**
446 - * Return the names and values of the fields.
447 - *
448 - * @since 1.20
449 - *
450 - * @return array
451 - */
452 - public function getFields() {
453 - return $this->fields;
454 - }
455 -
456 - /**
457 - * Return the names of the fields.
458 - *
459 - * @since 1.20
460 - *
461 - * @return array
462 - */
463 - public function getSetFieldNames() {
464 - return array_keys( $this->fields );
465 - }
466 -
467 - /**
468 - * Sets the value of a field.
469 - * Strings can be provided for other types,
470 - * so this method can be called from unserialization handlers.
471 - *
472 - * @since 1.20
473 - *
474 - * @param string $name
475 - * @param mixed $value
476 - *
477 - * @throws MWException
478 - */
479 - public function setField( $name, $value ) {
480 - $fields = $this->table->getFieldTypes();
481 -
482 - if ( array_key_exists( $name, $fields ) ) {
483 - switch ( $fields[$name] ) {
484 - case 'int':
485 - $value = (int)$value;
486 - break;
487 - case 'float':
488 - $value = (float)$value;
489 - break;
490 - case 'bool':
491 - if ( is_string( $value ) ) {
492 - $value = $value !== '0';
493 - } elseif ( is_int( $value ) ) {
494 - $value = $value !== 0;
495 - }
496 - break;
497 - case 'array':
498 - if ( is_string( $value ) ) {
499 - $value = unserialize( $value );
500 - }
501 -
502 - if ( !is_array( $value ) ) {
503 - $value = array();
504 - }
505 - break;
506 - case 'blob':
507 - if ( is_string( $value ) ) {
508 - $value = unserialize( $value );
509 - }
510 - break;
511 - case 'id':
512 - if ( is_string( $value ) ) {
513 - $value = (int)$value;
514 - }
515 - break;
516 - }
517 -
518 - $this->fields[$name] = $value;
519 - } else {
520 - throw new MWException( 'Attempted to set unknown field ' . $name );
521 - }
522 - }
523 -
524 - /**
525 - * Add an amount (can be negative) to the specified field (needs to be numeric).
526 - *
527 - * @since 1.20
528 - *
529 - * @param string $field
530 - * @param integer $amount
531 - *
532 - * @return boolean Success indicator
533 - */
534 - public function addToField( $field, $amount ) {
535 - if ( $amount == 0 ) {
536 - return true;
537 - }
538 -
539 - if ( !$this->hasIdField() ) {
540 - return false;
541 - }
542 -
543 - $absoluteAmount = abs( $amount );
544 - $isNegative = $amount < 0;
545 -
546 - $dbw = wfGetDB( DB_MASTER );
547 -
548 - $fullField = $this->table->getPrefixedField( $field );
549 -
550 - $success = $dbw->update(
551 - $this->table->getDBTable(),
552 - array( "$fullField=$fullField" . ( $isNegative ? '-' : '+' ) . $absoluteAmount ),
553 - array( $this->table->getPrefixedField( 'id' ) => $this->getId() ),
554 - __METHOD__
555 - );
556 -
557 - if ( $success && $this->hasField( $field ) ) {
558 - $this->setField( $field, $this->getField( $field ) + $amount );
559 - }
560 -
561 - return $success;
562 - }
563 -
564 - /**
565 - * Return the names of the fields.
566 - *
567 - * @since 1.20
568 - *
569 - * @return array
570 - */
571 - public function getFieldNames() {
572 - return array_keys( $this->table->getFieldTypes() );
573 - }
574 -
575 - /**
576 - * Computes and updates the values of the summary fields.
577 - *
578 - * @since 1.20
579 - *
580 - * @param array|string|null $summaryFields
581 - */
582 - public function loadSummaryFields( $summaryFields = null ) {
583 -
584 - }
585 -
586 - /**
587 - * Sets the value for the @see $updateSummaries field.
588 - *
589 - * @since 1.20
590 - *
591 - * @param boolean $update
592 - */
593 - public function setUpdateSummaries( $update ) {
594 - $this->updateSummaries = $update;
595 - }
596 -
597 - /**
598 - * Sets the value for the @see $inSummaryMode field.
599 - *
600 - * @since 1.20
601 - *
602 - * @param boolean $summaryMode
603 - */
604 - public function setSummaryMode( $summaryMode ) {
605 - $this->inSummaryMode = $summaryMode;
606 - }
607 -
608 - /**
609 - * Return if any fields got changed.
610 - *
611 - * @since 1.20
612 - *
613 - * @param DBDataObject $object
614 - * @param boolean $excludeSummaryFields When set to true, summary field changes are ignored.
615 - *
616 - * @return boolean
617 - */
618 - protected function fieldsChanged( DBDataObject $object, $excludeSummaryFields = false ) {
619 - foreach ( $this->fields as $name => $value ) {
620 - $excluded = $excludeSummaryFields && in_array( $name, $this->table->getSummaryFields() );
621 -
622 - if ( !$excluded && $object->getField( $name ) !== $value ) {
623 - return true;
624 - }
625 - }
626 -
627 - return false;
628 - }
629 -
630 - /**
631 - * Returns the table this DBDataObject is a row in.
632 - *
633 - * @since 1.20
634 - *
635 - * @return DBTable
636 - */
637 - public function getTable() {
638 - return $this->table;
639 - }
640 -
641 -}
Index: trunk/extensions/EducationProgram/includes/DBDataObject.php
@@ -0,0 +1,640 @@
 2+<?php
 3+
 4+/**
 5+ * Abstract base class for representing objects that are stored in some DB table.
 6+ * This is basically an ORM-like wrapper around rows in database tables that
 7+ * aims to be both simple and very flexible. It is centered around an associative
 8+ * array of fields and various methods to do common interaction with the database.
 9+ *
 10+ * These methods must be implemented in deriving classes:
 11+ * * getDBTable
 12+ * * getFieldPrefix
 13+ * * getFieldTypes
 14+ *
 15+ * These methods are likely candidates for overriding:
 16+ * * getDefaults
 17+ * * remove
 18+ * * insert
 19+ * * saveExisting
 20+ * * loadSummaryFields
 21+ * * getSummaryFields
 22+ *
 23+ * Main instance methods:
 24+ * * getField(s)
 25+ * * setField(s)
 26+ * * save
 27+ * * remove
 28+ *
 29+ * Main static methods:
 30+ * * select
 31+ * * update
 32+ * * delete
 33+ * * count
 34+ * * has
 35+ * * selectRow
 36+ * * selectFields
 37+ * * selectFieldsRow
 38+ *
 39+ * @since 1.20
 40+ *
 41+ * @file DBDataObject.php
 42+ *
 43+ * @licence GNU GPL v2 or later
 44+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 45+ */
 46+abstract class DBDataObject {
 47+
 48+ /**
 49+ * The fields of the object.
 50+ * field name (w/o prefix) => value
 51+ *
 52+ * @since 1.20
 53+ * @var array
 54+ */
 55+ protected $fields = array( 'id' => null );
 56+
 57+ /**
 58+ * @since 1.20
 59+ * @var DBTable
 60+ */
 61+ protected $table;
 62+
 63+ /**
 64+ * If the object should update summaries of linked items when changed.
 65+ * For example, update the course_count field in universities when a course in courses is deleted.
 66+ * Settings this to false can prevent needless updating work in situations
 67+ * such as deleting a university, which will then delete all it's courses.
 68+ *
 69+ * @since 1.20
 70+ * @var bool
 71+ */
 72+ protected $updateSummaries = true;
 73+
 74+ /**
 75+ * Indicates if the object is in summary mode.
 76+ * This mode indicates that only summary fields got updated,
 77+ * which allows for optimizations.
 78+ *
 79+ * @since 1.20
 80+ * @var bool
 81+ */
 82+ protected $inSummaryMode = false;
 83+
 84+ /**
 85+ * Constructor.
 86+ *
 87+ * @since 1.20
 88+ *
 89+ * @param DBTable $table
 90+ * @param array|null $fields
 91+ * @param boolean $loadDefaults
 92+ */
 93+ public function __construct( DBTable $table, $fields = null, $loadDefaults = false ) {
 94+ $this->table = $table;
 95+
 96+ if ( !is_array( $fields ) ) {
 97+ $fields = array();
 98+ }
 99+
 100+ if ( $loadDefaults ) {
 101+ $fields = array_merge( $this->table->getDefaults(), $fields );
 102+ }
 103+
 104+ $this->setFields( $fields );
 105+ }
 106+
 107+ /**
 108+ * Load the specified fields from the database.
 109+ *
 110+ * @since 1.20
 111+ *
 112+ * @param array|null $fields
 113+ * @param boolean $override
 114+ * @param boolean $skipLoaded
 115+ *
 116+ * @return bool Success indicator
 117+ */
 118+ public function loadFields( $fields = null, $override = true, $skipLoaded = false ) {
 119+ if ( is_null( $this->getId() ) ) {
 120+ return false;
 121+ }
 122+
 123+ if ( is_null( $fields ) ) {
 124+ $fields = array_keys( $this->table->getFieldTypes() );
 125+ }
 126+
 127+ if ( $skipLoaded ) {
 128+ $fields = array_diff( $fields, array_keys( $this->fields ) );
 129+ }
 130+
 131+ if ( count( $fields ) > 0 ) {
 132+ $result = $this->table->rawSelectRow(
 133+ $this->table->getPrefixedFields( $fields ),
 134+ array( $this->table->getPrefixedField( 'id' ) => $this->getId() ),
 135+ array( 'LIMIT' => 1 )
 136+ );
 137+
 138+ if ( $result !== false ) {
 139+ $this->setFields( $this->table->getFieldsFromDBResult( $result ), $override );
 140+ return true;
 141+ }
 142+
 143+ return false;
 144+ }
 145+
 146+ return true;
 147+ }
 148+
 149+ /**
 150+ * Gets the value of a field.
 151+ *
 152+ * @since 1.20
 153+ *
 154+ * @param string $name
 155+ * @param mixed $default
 156+ *
 157+ * @throws MWException
 158+ * @return mixed
 159+ */
 160+ public function getField( $name, $default = null ) {
 161+ if ( $this->hasField( $name ) ) {
 162+ return $this->fields[$name];
 163+ } elseif ( !is_null( $default ) ) {
 164+ return $default;
 165+ } else {
 166+ throw new MWException( 'Attempted to get not-set field ' . $name );
 167+ }
 168+ }
 169+
 170+ /**
 171+ * Gets the value of a field but first loads it if not done so already.
 172+ *
 173+ * @since 1.20
 174+ *
 175+ * @param string$name
 176+ *
 177+ * @return mixed
 178+ */
 179+ public function loadAndGetField( $name ) {
 180+ if ( !$this->hasField( $name ) ) {
 181+ $this->loadFields( array( $name ) );
 182+ }
 183+
 184+ return $this->getField( $name );
 185+ }
 186+
 187+ /**
 188+ * Remove a field.
 189+ *
 190+ * @since 1.20
 191+ *
 192+ * @param string $name
 193+ */
 194+ public function removeField( $name ) {
 195+ unset( $this->fields[$name] );
 196+ }
 197+
 198+ /**
 199+ * Returns the objects database id.
 200+ *
 201+ * @since 1.20
 202+ *
 203+ * @return integer|null
 204+ */
 205+ public function getId() {
 206+ return $this->getField( 'id' );
 207+ }
 208+
 209+ /**
 210+ * Sets the objects database id.
 211+ *
 212+ * @since 1.20
 213+ *
 214+ * @param integer|null $id
 215+ */
 216+ public function setId( $id ) {
 217+ return $this->setField( 'id', $id );
 218+ }
 219+
 220+ /**
 221+ * Gets if a certain field is set.
 222+ *
 223+ * @since 1.20
 224+ *
 225+ * @param string $name
 226+ *
 227+ * @return boolean
 228+ */
 229+ public function hasField( $name ) {
 230+ return array_key_exists( $name, $this->fields );
 231+ }
 232+
 233+ /**
 234+ * Gets if the id field is set.
 235+ *
 236+ * @since 1.20
 237+ *
 238+ * @return boolean
 239+ */
 240+ public function hasIdField() {
 241+ return $this->hasField( 'id' )
 242+ && !is_null( $this->getField( 'id' ) );
 243+ }
 244+
 245+ /**
 246+ * Sets multiple fields.
 247+ *
 248+ * @since 1.20
 249+ *
 250+ * @param array $fields The fields to set
 251+ * @param boolean $override Override already set fields with the provided values?
 252+ */
 253+ public function setFields( array $fields, $override = true ) {
 254+ foreach ( $fields as $name => $value ) {
 255+ if ( $override || !$this->hasField( $name ) ) {
 256+ $this->setField( $name, $value );
 257+ }
 258+ }
 259+ }
 260+
 261+ /**
 262+ * Gets the fields => values to write to the table.
 263+ *
 264+ * @since 1.20
 265+ *
 266+ * @return array
 267+ */
 268+ protected function getWriteValues() {
 269+ $values = array();
 270+
 271+ foreach ( $this->table->getFieldTypes() as $name => $type ) {
 272+ if ( array_key_exists( $name, $this->fields ) ) {
 273+ $value = $this->fields[$name];
 274+
 275+ switch ( $type ) {
 276+ case 'array':
 277+ $value = (array)$value;
 278+ case 'blob':
 279+ $value = serialize( $value );
 280+ }
 281+
 282+ $values[$this->table->getPrefixedField( $name )] = $value;
 283+ }
 284+ }
 285+
 286+ return $values;
 287+ }
 288+
 289+ /**
 290+ * Serializes the object to an associative array which
 291+ * can then easily be converted into JSON or similar.
 292+ *
 293+ * @since 1.20
 294+ *
 295+ * @param null|array $fields
 296+ * @param boolean $incNullId
 297+ *
 298+ * @return array
 299+ */
 300+ public function toArray( $fields = null, $incNullId = false ) {
 301+ $data = array();
 302+ $setFields = array();
 303+
 304+ if ( !is_array( $fields ) ) {
 305+ $setFields = $this->getSetFieldNames();
 306+ } else {
 307+ foreach ( $fields as $field ) {
 308+ if ( $this->hasField( $field ) ) {
 309+ $setFields[] = $field;
 310+ }
 311+ }
 312+ }
 313+
 314+ foreach ( $setFields as $field ) {
 315+ if ( $incNullId || $field != 'id' || $this->hasIdField() ) {
 316+ $data[$field] = $this->getField( $field );
 317+ }
 318+ }
 319+
 320+ return $data;
 321+ }
 322+
 323+ /**
 324+ * Load the default values, via getDefaults.
 325+ *
 326+ * @since 1.20
 327+ *
 328+ * @param boolean $override
 329+ */
 330+ public function loadDefaults( $override = true ) {
 331+ $this->setFields( $this->table->getDefaults(), $override );
 332+ }
 333+
 334+ /**
 335+ * Writes the answer to the database, either updating it
 336+ * when it already exists, or inserting it when it doesn't.
 337+ *
 338+ * @since 1.20
 339+ *
 340+ * @return boolean Success indicator
 341+ */
 342+ public function save() {
 343+ if ( $this->hasIdField() ) {
 344+ return $this->saveExisting();
 345+ } else {
 346+ return $this->insert();
 347+ }
 348+ }
 349+
 350+ /**
 351+ * Updates the object in the database.
 352+ *
 353+ * @since 1.20
 354+ *
 355+ * @return boolean Success indicator
 356+ */
 357+ protected function saveExisting() {
 358+ $dbw = wfGetDB( DB_MASTER );
 359+
 360+ $success = $dbw->update(
 361+ $this->table->getDBTable(),
 362+ $this->getWriteValues(),
 363+ array( $this->table->getPrefixedField( 'id' ) => $this->getId() ),
 364+ __METHOD__
 365+ );
 366+
 367+ return $success;
 368+ }
 369+
 370+ /**
 371+ * Inserts the object into the database.
 372+ *
 373+ * @since 1.20
 374+ *
 375+ * @return boolean Success indicator
 376+ */
 377+ protected function insert() {
 378+ $dbw = wfGetDB( DB_MASTER );
 379+
 380+ $result = $dbw->insert(
 381+ $this->table->getDBTable(),
 382+ $this->getWriteValues(),
 383+ __METHOD__,
 384+ array( 'IGNORE' )
 385+ );
 386+
 387+ if ( $result ) {
 388+ $this->setField( 'id', $dbw->insertId() );
 389+ }
 390+
 391+ return $result;
 392+ }
 393+
 394+ /**
 395+ * Removes the object from the database.
 396+ *
 397+ * @since 1.20
 398+ *
 399+ * @return boolean Success indicator
 400+ */
 401+ public function remove() {
 402+ $this->beforeRemove();
 403+
 404+ $success = $this->table->delete( array( 'id' => $this->getId() ) );
 405+
 406+ if ( $success ) {
 407+ $this->onRemoved();
 408+ }
 409+
 410+ return $success;
 411+ }
 412+
 413+ /**
 414+ * Gets called before an object is removed from the database.
 415+ *
 416+ * @since 1.20
 417+ */
 418+ protected function beforeRemove() {
 419+ $this->loadFields( $this->getBeforeRemoveFields(), false, true );
 420+ }
 421+
 422+ /**
 423+ * Before removal of an object happens, @see beforeRemove gets called.
 424+ * This method loads the fields of which the names have been returned by this one (or all fields if null is returned).
 425+ * This allows for loading info needed after removal to get rid of linked data and the like.
 426+ *
 427+ * @since 1.20
 428+ *
 429+ * @return array|null
 430+ */
 431+ protected function getBeforeRemoveFields() {
 432+ return array();
 433+ }
 434+
 435+ /**
 436+ * Gets called after successfull removal.
 437+ * Can be overriden to get rid of linked data.
 438+ *
 439+ * @since 1.20
 440+ */
 441+ protected function onRemoved() {
 442+ $this->setField( 'id', null );
 443+ }
 444+
 445+ /**
 446+ * Return the names and values of the fields.
 447+ *
 448+ * @since 1.20
 449+ *
 450+ * @return array
 451+ */
 452+ public function getFields() {
 453+ return $this->fields;
 454+ }
 455+
 456+ /**
 457+ * Return the names of the fields.
 458+ *
 459+ * @since 1.20
 460+ *
 461+ * @return array
 462+ */
 463+ public function getSetFieldNames() {
 464+ return array_keys( $this->fields );
 465+ }
 466+
 467+ /**
 468+ * Sets the value of a field.
 469+ * Strings can be provided for other types,
 470+ * so this method can be called from unserialization handlers.
 471+ *
 472+ * @since 1.20
 473+ *
 474+ * @param string $name
 475+ * @param mixed $value
 476+ *
 477+ * @throws MWException
 478+ */
 479+ public function setField( $name, $value ) {
 480+ $fields = $this->table->getFieldTypes();
 481+
 482+ if ( array_key_exists( $name, $fields ) ) {
 483+ switch ( $fields[$name] ) {
 484+ case 'int':
 485+ $value = (int)$value;
 486+ break;
 487+ case 'float':
 488+ $value = (float)$value;
 489+ break;
 490+ case 'bool':
 491+ if ( is_string( $value ) ) {
 492+ $value = $value !== '0';
 493+ } elseif ( is_int( $value ) ) {
 494+ $value = $value !== 0;
 495+ }
 496+ break;
 497+ case 'array':
 498+ if ( is_string( $value ) ) {
 499+ $value = unserialize( $value );
 500+ }
 501+
 502+ if ( !is_array( $value ) ) {
 503+ $value = array();
 504+ }
 505+ break;
 506+ case 'blob':
 507+ if ( is_string( $value ) ) {
 508+ $value = unserialize( $value );
 509+ }
 510+ break;
 511+ case 'id':
 512+ if ( is_string( $value ) ) {
 513+ $value = (int)$value;
 514+ }
 515+ break;
 516+ }
 517+
 518+ $this->fields[$name] = $value;
 519+ } else {
 520+ throw new MWException( 'Attempted to set unknown field ' . $name );
 521+ }
 522+ }
 523+
 524+ /**
 525+ * Add an amount (can be negative) to the specified field (needs to be numeric).
 526+ *
 527+ * @since 1.20
 528+ *
 529+ * @param string $field
 530+ * @param integer $amount
 531+ *
 532+ * @return boolean Success indicator
 533+ */
 534+ public function addToField( $field, $amount ) {
 535+ if ( $amount == 0 ) {
 536+ return true;
 537+ }
 538+
 539+ if ( !$this->hasIdField() ) {
 540+ return false;
 541+ }
 542+
 543+ $absoluteAmount = abs( $amount );
 544+ $isNegative = $amount < 0;
 545+
 546+ $dbw = wfGetDB( DB_MASTER );
 547+
 548+ $fullField = $this->table->getPrefixedField( $field );
 549+
 550+ $success = $dbw->update(
 551+ $this->table->getDBTable(),
 552+ array( "$fullField=$fullField" . ( $isNegative ? '-' : '+' ) . $absoluteAmount ),
 553+ array( $this->table->getPrefixedField( 'id' ) => $this->getId() ),
 554+ __METHOD__
 555+ );
 556+
 557+ if ( $success && $this->hasField( $field ) ) {
 558+ $this->setField( $field, $this->getField( $field ) + $amount );
 559+ }
 560+
 561+ return $success;
 562+ }
 563+
 564+ /**
 565+ * Return the names of the fields.
 566+ *
 567+ * @since 1.20
 568+ *
 569+ * @return array
 570+ */
 571+ public function getFieldNames() {
 572+ return array_keys( $this->table->getFieldTypes() );
 573+ }
 574+
 575+ /**
 576+ * Computes and updates the values of the summary fields.
 577+ *
 578+ * @since 1.20
 579+ *
 580+ * @param array|string|null $summaryFields
 581+ */
 582+ public function loadSummaryFields( $summaryFields = null ) {
 583+
 584+ }
 585+
 586+ /**
 587+ * Sets the value for the @see $updateSummaries field.
 588+ *
 589+ * @since 1.20
 590+ *
 591+ * @param boolean $update
 592+ */
 593+ public function setUpdateSummaries( $update ) {
 594+ $this->updateSummaries = $update;
 595+ }
 596+
 597+ /**
 598+ * Sets the value for the @see $inSummaryMode field.
 599+ *
 600+ * @since 1.20
 601+ *
 602+ * @param boolean $summaryMode
 603+ */
 604+ public function setSummaryMode( $summaryMode ) {
 605+ $this->inSummaryMode = $summaryMode;
 606+ }
 607+
 608+ /**
 609+ * Return if any fields got changed.
 610+ *
 611+ * @since 1.20
 612+ *
 613+ * @param DBDataObject $object
 614+ * @param boolean $excludeSummaryFields When set to true, summary field changes are ignored.
 615+ *
 616+ * @return boolean
 617+ */
 618+ protected function fieldsChanged( DBDataObject $object, $excludeSummaryFields = false ) {
 619+ foreach ( $this->fields as $name => $value ) {
 620+ $excluded = $excludeSummaryFields && in_array( $name, $this->table->getSummaryFields() );
 621+
 622+ if ( !$excluded && $object->getField( $name ) !== $value ) {
 623+ return true;
 624+ }
 625+ }
 626+
 627+ return false;
 628+ }
 629+
 630+ /**
 631+ * Returns the table this DBDataObject is a row in.
 632+ *
 633+ * @since 1.20
 634+ *
 635+ * @return DBTable
 636+ */
 637+ public function getTable() {
 638+ return $this->table;
 639+ }
 640+
 641+}
Property changes on: trunk/extensions/EducationProgram/includes/DBDataObject.php
___________________________________________________________________
Added: svn:mergeinfo
1642 Merged /branches/JSTesting/includes/DBDataObject.php:r100352-107913
2643 Merged /branches/REL1_15/phase3/includes/DBDataObject.php:r51646
3644 Merged /branches/wmf/1.18wmf1/includes/DBDataObject.php:r97508
4645 Merged /branches/sqlite/includes/DBDataObject.php:r58211-58321
5646 Merged /branches/new-installer/phase3/includes/DBDataObject.php:r43664-66004
6647 Merged /branches/wmf-deployment/includes/DBDataObject.php:r53381
Added: svn:eol-style
7648 + native

Follow-up revisions

RevisionCommit summaryAuthorDate
r111594follow up r111591 r111592jeroendedauw22:59, 15 February 2012

Status & tagging log