r111261 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r111260‎ | r111261 | r111262 >
Date:21:23, 11 February 2012
Author:jeroendedauw
Status:deferred
Tags:
Comment:
EPDBObject -> DBDataObject
Modified paths:
  • /trunk/extensions/EducationProgram/EducationProgram.php (modified) (history)
  • /trunk/extensions/EducationProgram/actions/EPEditAction.php (modified) (history)
  • /trunk/extensions/EducationProgram/actions/EPViewAction.php (modified) (history)
  • /trunk/extensions/EducationProgram/actions/ViewCourseAction.php (modified) (history)
  • /trunk/extensions/EducationProgram/actions/ViewOrgAction.php (modified) (history)
  • /trunk/extensions/EducationProgram/includes/DBDataObject.php (added) (history)
  • /trunk/extensions/EducationProgram/includes/EPArticle.php (modified) (history)
  • /trunk/extensions/EducationProgram/includes/EPCA.php (modified) (history)
  • /trunk/extensions/EducationProgram/includes/EPCourse.php (modified) (history)
  • /trunk/extensions/EducationProgram/includes/EPCoursePager.php (modified) (history)
  • /trunk/extensions/EducationProgram/includes/EPDBObject.php (deleted) (history)
  • /trunk/extensions/EducationProgram/includes/EPOA.php (modified) (history)
  • /trunk/extensions/EducationProgram/includes/EPOrg.php (modified) (history)
  • /trunk/extensions/EducationProgram/includes/EPOrgPager.php (modified) (history)
  • /trunk/extensions/EducationProgram/includes/EPPager.php (modified) (history)
  • /trunk/extensions/EducationProgram/includes/EPRevision.php (modified) (history)
  • /trunk/extensions/EducationProgram/includes/EPRevisionedObject.php (modified) (history)
  • /trunk/extensions/EducationProgram/includes/EPRevisions.php (modified) (history)
  • /trunk/extensions/EducationProgram/includes/EPRoleObject.php (modified) (history)
  • /trunk/extensions/EducationProgram/pages/EPPage.php (modified) (history)
  • /trunk/extensions/EducationProgram/specials/SpecialCA.php (modified) (history)
  • /trunk/extensions/EducationProgram/specials/SpecialEPPage.php (modified) (history)
  • /trunk/extensions/EducationProgram/specials/SpecialOA.php (modified) (history)
  • /trunk/extensions/EducationProgram/specials/SpecialStudent.php (modified) (history)

Diff [purge]

Index: trunk/extensions/EducationProgram/EducationProgram.php
@@ -75,7 +75,7 @@
7676
7777 $wgAutoloadClasses['EPCourse'] = dirname( __FILE__ ) . '/includes/EPCourse.php';
7878 $wgAutoloadClasses['EPCoursePager'] = dirname( __FILE__ ) . '/includes/EPCoursePager.php';
79 -$wgAutoloadClasses['EPDBObject'] = dirname( __FILE__ ) . '/includes/EPDBObject.php';
 79+$wgAutoloadClasses['DBDataObject'] = dirname( __FILE__ ) . '/includes/DBDataObject.php';
8080 $wgAutoloadClasses['EPInstructor'] = dirname( __FILE__ ) . '/includes/EPInstructor.php';
8181 $wgAutoloadClasses['EPLogFormatter'] = dirname( __FILE__ ) . '/includes/EPLogFormatter.php';
8282 $wgAutoloadClasses['EPOrg'] = dirname( __FILE__ ) . '/includes/EPOrg.php';
@@ -151,15 +151,15 @@
152152 $wgSpecialPageGroups['OnlineAmbassadorProfile'] = 'education';
153153
154154 // DB object classes
155 -$egEPDBObjects = array();
156 -$egEPDBObjects['EPRevision'] = array( 'table' => 'ep_revisions', 'prefix' => 'rev_' );
157 -$egEPDBObjects['EPOrg'] = array( 'table' => 'ep_orgs', 'prefix' => 'org_' );
158 -$egEPDBObjects['EPCourse'] = array( 'table' => 'ep_courses', 'prefix' => 'course_' );
159 -$egEPDBObjects['EPStudent'] = array( 'table' => 'ep_students', 'prefix' => 'student_' );
160 -$egEPDBObjects['EPOA'] = array( 'table' => 'ep_oas', 'prefix' => 'oa_' );
161 -$egEPDBObjects['EPCA'] = array( 'table' => 'ep_cas', 'prefix' => 'ca_' );
162 -$egEPDBObjects['EPArticle'] = array( 'table' => 'ep_articles', 'prefix' => 'article_' );
163 -$egEPDBObjects[] = array( 'table' => 'ep_users_per_course', 'prefix' => 'upc_' );
 155+$egDBDataObjects = array();
 156+$egDBDataObjects['EPRevision'] = array( 'table' => 'ep_revisions', 'prefix' => 'rev_' );
 157+$egDBDataObjects['EPOrg'] = array( 'table' => 'ep_orgs', 'prefix' => 'org_' );
 158+$egDBDataObjects['EPCourse'] = array( 'table' => 'ep_courses', 'prefix' => 'course_' );
 159+$egDBDataObjects['EPStudent'] = array( 'table' => 'ep_students', 'prefix' => 'student_' );
 160+$egDBDataObjects['EPOA'] = array( 'table' => 'ep_oas', 'prefix' => 'oa_' );
 161+$egDBDataObjects['EPCA'] = array( 'table' => 'ep_cas', 'prefix' => 'ca_' );
 162+$egDBDataObjects['EPArticle'] = array( 'table' => 'ep_articles', 'prefix' => 'article_' );
 163+$egDBDataObjects[] = array( 'table' => 'ep_users_per_course', 'prefix' => 'upc_' );
164164
165165 define( 'EP_STUDENT', 0 );
166166 define( 'EP_INSTRUCTOR', 1 );
Index: trunk/extensions/EducationProgram/pages/EPPage.php
@@ -1,7 +1,7 @@
22 <?php
33
44 /**
5 - * Abstract Page for interacting with a EPDBObject.
 5+ * Abstract Page for interacting with a DBDataObject.
66 *
77 * @since 0.1
88 *
Index: trunk/extensions/EducationProgram/actions/ViewCourseAction.php
@@ -22,7 +22,7 @@
2323 return 'EPCourse';
2424 }
2525
26 - protected function displayPage( EPDBObject $course ) {
 26+ protected function displayPage( DBDataObject $course ) {
2727 parent::displayPage( $course );
2828
2929 $out = $this->getOutput();
@@ -59,7 +59,7 @@
6060 *
6161 * @return array
6262 */
63 - protected function getSummaryData( EPDBObject $course ) {
 63+ protected function getSummaryData( DBDataObject $course ) {
6464 $stats = array();
6565
6666 $orgName = EPOrg::selectFieldsRow( 'name', array( 'id' => $course->getField( 'org_id' ) ) );
Index: trunk/extensions/EducationProgram/actions/EPViewAction.php
@@ -1,7 +1,7 @@
22 <?php
33
44 /**
5 - * Abstract action for viewing EPDBObject items.
 5+ * Abstract action for viewing DBDataObject items.
66 *
77 * @since 0.1
88 *
@@ -15,7 +15,7 @@
1616 abstract class EPViewAction extends FormlessAction {
1717
1818 /**
19 - * Returns the class name of the EPDBObject this action handles.
 19+ * Returns the class name of the DBDataObject this action handles.
2020 *
2121 * @since 0.1
2222 *
@@ -126,9 +126,9 @@
127127 *
128128 * @since 0.1
129129 *
130 - * @param EPDBObject $object
 130+ * @param DBDataObject $object
131131 */
132 - protected function displayPage( EPDBObject $object ) {
 132+ protected function displayPage( DBDataObject $object ) {
133133 $this->displayNavigation();
134134 $this->displaySummary( $object );
135135 }
@@ -163,11 +163,11 @@
164164 *
165165 * @since 0.1
166166 *
167 - * @param EPDBObject $item
 167+ * @param DBDataObject $item
168168 * @param boolean $collapsed
169169 * @param array $summaryData
170170 */
171 - protected function displaySummary( EPDBObject $item, $collapsed = false, array $summaryData = null ) {
 171+ protected function displaySummary( DBDataObject $item, $collapsed = false, array $summaryData = null ) {
172172 $out = $this->getOutput();
173173
174174 $class = 'wikitable ep-summary mw-collapsible';
@@ -209,11 +209,11 @@
210210 *
211211 * @since 0.1
212212 *
213 - * @param EPDBObject $item
 213+ * @param DBDataObject $item
214214 *
215215 * @return array
216216 */
217 - protected function getSummaryData( EPDBObject $item ) {
 217+ protected function getSummaryData( DBDataObject $item ) {
218218 return array();
219219 }
220220
Index: trunk/extensions/EducationProgram/actions/ViewOrgAction.php
@@ -22,7 +22,7 @@
2323 return 'EPOrg';
2424 }
2525
26 - protected function displayPage( EPDBObject $org ) {
 26+ protected function displayPage( DBDataObject $org ) {
2727 parent::displayPage( $org );
2828
2929 $out = $this->getOutput();
@@ -47,7 +47,7 @@
4848 *
4949 * @return array
5050 */
51 - protected function getSummaryData( EPDBObject $org ) {
 51+ protected function getSummaryData( DBDataObject $org ) {
5252 $stats = array();
5353
5454 $stats['name'] = $org->getField( 'name' );
Index: trunk/extensions/EducationProgram/actions/EPEditAction.php
@@ -424,11 +424,11 @@
425425 *$title = SpecialPage::getTitleFor( $this->itemPage, $this->subPage )->getLocalURL();
426426 * @since 0.1
427427 *
428 - * @param EPDBObject $item
 428+ * @param DBDataObject $item
429429 * @param string $name
430430 * @param string $value This is a string, since it comes from request data, but might be a number or other type.
431431 */
432 - protected function handleUnknownField( EPDBObject $item, $name, $value ) {
 432+ protected function handleUnknownField( DBDataObject $item, $name, $value ) {
433433 // Override to use.
434434 }
435435
Index: trunk/extensions/EducationProgram/specials/SpecialOA.php
@@ -62,7 +62,7 @@
6363 *
6464 * @return array
6565 */
66 - protected function getSummaryData( EPDBObject $oa ) {
 66+ protected function getSummaryData( DBDataObject $oa ) {
6767 $stats = array();
6868
6969 return $stats;
Index: trunk/extensions/EducationProgram/specials/SpecialEPPage.php
@@ -141,11 +141,11 @@
142142 *
143143 * @since 0.1
144144 *
145 - * @param EPDBObject $item
 145+ * @param DBDataObject $item
146146 * @param boolean $collapsed
147147 * @param array $summaryData
148148 */
149 - protected function displaySummary( EPDBObject $item, $collapsed = false, array $summaryData = null ) {
 149+ protected function displaySummary( DBDataObject $item, $collapsed = false, array $summaryData = null ) {
150150 $out = $this->getOutput();
151151
152152 $class = 'wikitable ep-summary mw-collapsible';
@@ -187,11 +187,11 @@
188188 *
189189 * @since 0.1
190190 *
191 - * @param EPDBObject $item
 191+ * @param DBDataObject $item
192192 *
193193 * @return array
194194 */
195 - protected function getSummaryData( EPDBObject $item ) {
 195+ protected function getSummaryData( DBDataObject $item ) {
196196 return array();
197197 }
198198
Index: trunk/extensions/EducationProgram/specials/SpecialCA.php
@@ -62,7 +62,7 @@
6363 *
6464 * @return array
6565 */
66 - protected function getSummaryData( EPDBObject $ca ) {
 66+ protected function getSummaryData( DBDataObject $ca ) {
6767 $stats = array();
6868
6969 return $stats;
Index: trunk/extensions/EducationProgram/specials/SpecialStudent.php
@@ -73,7 +73,7 @@
7474 *
7575 * @return array
7676 */
77 - protected function getSummaryData( EPDBObject $student ) {
 77+ protected function getSummaryData( DBDataObject $student ) {
7878 $stats = array();
7979
8080 $id = $student->getUser()->getId();
Index: trunk/extensions/EducationProgram/includes/EPDBObject.php
@@ -1,1288 +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 - * * getFieldTypes
12 - *
13 - * These methods are likely candidates for overriding:
14 - * * getDefaults
15 - * * remove
16 - * * insert
17 - * * saveExisting
18 - * * loadSummaryFields
19 - * * getSummaryFields
20 - *
21 - * Deriving classes must register their table and field prefix in $egEPDBObjects.
22 - * Syntax: $egEPDBObjects['DrivingClassName'] = array( 'table' => 'table_name', 'prefix' => 'fieldprefix_' );
23 - * Example: $egEPDBObjects['EPOrg'] = array( 'table' => 'ep_orgs', 'prefix' => 'org_' );
24 - *
25 - * Main instance methods:
26 - * * getField(s)
27 - * * setField(s)
28 - * * save
29 - * * remove
30 - *
31 - * Main static methods:
32 - * * select
33 - * * update
34 - * * delete
35 - * * count
36 - * * has
37 - * * selectRow
38 - * * selectFields
39 - * * selectFieldsRow
40 - *
41 - * @since 0.1
42 - *
43 - * @file EPDBObject.php
44 - * @ingroup EducationProgram
45 - *
46 - * @licence GNU GPL v3 or later
47 - * @author Jeroen De Dauw < jeroendedauw@gmail.com >
48 - */
49 -abstract class EPDBObject {
50 -
51 - /**
52 - * The fields of the object.
53 - * field name (w/o prefix) => value
54 - *
55 - * @since 0.1
56 - * @var array
57 - */
58 - protected $fields = array( 'id' => null );
59 -
60 - /**
61 - * If the object should update summaries of linked items when changed.
62 - * For example, update the course_count field in universities when a course in courses is deleted.
63 - * Settings this to false can prevent needless updating work in situations
64 - * such as deleting a university, which will then delete all it's courses.
65 - *
66 - * @since 0.1
67 - * @var bool
68 - */
69 - protected $updateSummaries = true;
70 -
71 - /**
72 - * Indicates if the object is in summary mode.
73 - * This mode indicates that only summary fields got updated,
74 - * which allows for optimizations.
75 - *
76 - * @since 0.1
77 - * @var bool
78 - */
79 - protected $inSummaryMode = false;
80 -
81 -
82 - /**
83 - * The database connection to use for read operations.
84 - * Can be changed via @see setReadDb.
85 - *
86 - * @since 0.2
87 - * @var integer DB_ enum
88 - */
89 - protected static $readDb = DB_SLAVE;
90 -
91 - /**
92 - * Returns the name of the database table objects of this type are stored in.
93 - *
94 - * @since 0.1
95 - *
96 - * @throws MWException
97 - * @return string
98 - */
99 - public static function getDBTable() {
100 - global $egEPDBObjects;
101 - if ( array_key_exists( get_called_class(), $egEPDBObjects ) ) {
102 - return $egEPDBObjects[get_called_class()]['table'];
103 - }
104 - else {
105 - throw new MWException( 'Class "' . get_called_class() . '" not found in $egEPDBObjects' );
106 - }
107 - }
108 -
109 - /**
110 - * Gets the db field prefix.
111 - *
112 - * @since 0.1
113 - *
114 - * @throws MWException
115 - * @return string
116 - */
117 - protected static function getFieldPrefix() {
118 - global $egEPDBObjects;
119 - if ( array_key_exists( get_called_class(), $egEPDBObjects ) ) {
120 - return $egEPDBObjects[get_called_class()]['prefix'];
121 - }
122 - else {
123 - throw new MWException( 'Class "' . get_called_class() . '" not found in $egEPDBObjects' );
124 - }
125 - }
126 -
127 - /**
128 - * Returns an array with the fields and their types this object contains.
129 - * This corresponds directly to the fields in the database, without prefix.
130 - *
131 - * field name => type
132 - *
133 - * Allowed types:
134 - * * id
135 - * * str
136 - * * int
137 - * * float
138 - * * bool
139 - * * array
140 - *
141 - * @since 0.1
142 - *
143 - * @throws MWException
144 - * @return array
145 - */
146 - protected static function getFieldTypes() {
147 - throw new MWException( 'Class did not implement getFieldTypes' );
148 - }
149 -
150 - /**
151 - * Returns a list of default field values.
152 - * field name => field value
153 - *
154 - * @since 0.1
155 - *
156 - * @return array
157 - */
158 - public static function getDefaults() {
159 - return array();
160 - }
161 -
162 - /**
163 - * Returns a list of the summary fields.
164 - * These are fields that cache computed values, such as the amount of linked objects of $type.
165 - * This is relevant as one might not want to do actions such as log changes when these get updated.
166 - *
167 - * @since 0.1
168 - *
169 - * @return array
170 - */
171 - public static function getSummaryFields() {
172 - return array();
173 - }
174 -
175 - /**
176 - * Constructor.
177 - *
178 - * @since 0.1
179 - *
180 - * @param array|null $fields
181 - * @param boolean $loadDefaults
182 - */
183 - public function __construct( $fields = null, $loadDefaults = false ) {
184 - if ( !is_array( $fields ) ) {
185 - $fields = array();
186 - }
187 -
188 - if ( $loadDefaults ) {
189 - $fields = array_merge( $this->getDefaults(), $fields );
190 - }
191 -
192 - $this->setFields( $fields );
193 - }
194 -
195 - /**
196 - * Load the specified fields from the database.
197 - *
198 - * @since 0.1
199 - *
200 - * @param array|null $fields
201 - * @param boolean $override
202 - * @param boolean $skipLoaded
203 - *
204 - * @return Success indicator
205 - */
206 - public function loadFields( $fields = null, $override = true, $skipLoaded = false ) {
207 - if ( is_null( $this->getId() ) ) {
208 - return false;
209 - }
210 -
211 - if ( is_null( $fields ) ) {
212 - $fields = array_keys( $this->getFieldTypes() );
213 - }
214 -
215 - if ( $skipLoaded ) {
216 - $loadedFields = array_keys( $this->fields );
217 - $fields = array_filter( $fields, function( $field ) use ( $loadedFields ) {
218 - return !in_array( $field, $loadedFields );
219 - } );
220 - }
221 -
222 - if ( count( $fields ) > 0 ) {
223 - $results = $this->rawSelect(
224 - $this->getPrefixedFields( $fields ),
225 - array( $this->getPrefixedField( 'id' ) => $this->getId() ),
226 - array( 'LIMIT' => 1 )
227 - );
228 -
229 - foreach ( $results as $result ) {
230 - $this->setFields( $this->getFieldsFromDBResult( $result ), $override );
231 - return true;
232 - }
233 -
234 - return false;
235 - }
236 -
237 - return true;
238 - }
239 -
240 - /**
241 - * Gets the value of a field.
242 - *
243 - * @since 0.1
244 - *
245 - * @param string $name
246 - * @param mixed $default
247 - *
248 - * @throws MWException
249 - * @return mixed
250 - */
251 - public function getField( $name, $default = null ) {
252 - if ( $this->hasField( $name ) ) {
253 - return $this->fields[$name];
254 - } elseif ( !is_null( $default ) ) {
255 - return $default;
256 - } else {
257 - throw new MWException( 'Attempted to get not-set field ' . $name );
258 - }
259 - }
260 -
261 - /**
262 - * Gets the value of a field but first loads it if not done so already.
263 - *
264 - * @since 0.1
265 - *
266 - * @param string$name
267 - *
268 - * @return mixed
269 - */
270 - public function loadAndGetField( $name ) {
271 - if ( !$this->hasField( $name ) ) {
272 - $this->loadFields( array( $name ) );
273 - }
274 -
275 - return $this->getField( $name );
276 - }
277 -
278 - /**
279 - * Remove a field.
280 - *
281 - * @since 0.1
282 - *
283 - * @param string $name
284 - */
285 - public function removeField( $name ) {
286 - unset( $this->fields[$name] );
287 - }
288 -
289 - /**
290 - * Returns the objects database id.
291 - *
292 - * @since 0.1
293 - *
294 - * @return integer|null
295 - */
296 - public function getId() {
297 - return $this->getField( 'id' );
298 - }
299 -
300 - /**
301 - * Sets the objects database id.
302 - *
303 - * @since 0.1
304 - *
305 - * @param integer|null $id
306 - */
307 - public function setId( $id ) {
308 - return $this->setField( 'id', $id );
309 - }
310 -
311 - /**
312 - * Gets if a certain field is set.
313 - *
314 - * @since 0.1
315 - *
316 - * @param string $name
317 - *
318 - * @return boolean
319 - */
320 - public function hasField( $name ) {
321 - return array_key_exists( $name, $this->fields );
322 - }
323 -
324 - /**
325 - * Gets if the id field is set.
326 - *
327 - * @since 0.1
328 - *
329 - * @return boolean
330 - */
331 - public function hasIdField() {
332 - return $this->hasField( 'id' )
333 - && !is_null( $this->getField( 'id' ) );
334 - }
335 -
336 - /**
337 - * Sets multiple fields.
338 - *
339 - * @since 0.1
340 - *
341 - * @param array $fields The fields to set
342 - * @param boolean $override Override already set fields with the provided values?
343 - */
344 - public function setFields( array $fields, $override = true ) {
345 - foreach ( $fields as $name => $value ) {
346 - if ( $override || !$this->hasField( $name ) ) {
347 - $this->setField( $name, $value );
348 - }
349 - }
350 - }
351 -
352 - /**
353 - * Gets the fields => values to write to the table.
354 - *
355 - * @since 0.1
356 - *
357 - * @return array
358 - */
359 - protected function getWriteValues() {
360 - $values = array();
361 -
362 - foreach ( $this->getFieldTypes() as $name => $type ) {
363 - if ( array_key_exists( $name, $this->fields ) ) {
364 - $value = $this->fields[$name];
365 -
366 - switch ( $type ) {
367 - case 'array':
368 - $value = (array)$value;
369 - case 'blob':
370 - $value = serialize( $value );
371 - }
372 -
373 - $values[$this->getFieldPrefix() . $name] = $value;
374 - }
375 - }
376 -
377 - return $values;
378 - }
379 -
380 - /**
381 - * Serializes the object to an associative array which
382 - * can then easily be converted into JSON or similar.
383 - *
384 - * @since 0.1
385 - *
386 - * @param null|array $fields
387 - * @param boolean $incNullId
388 - *
389 - * @return array
390 - */
391 - public function toArray( $fields = null, $incNullId = false ) {
392 - $data = array();
393 - $setFields = array();
394 -
395 - if ( !is_array( $fields ) ) {
396 - $setFields = $this->getSetFieldNames();
397 - } else {
398 - foreach ( $fields as $field ) {
399 - if ( $this->hasField( $field ) ) {
400 - $setFields[] = $field;
401 - }
402 - }
403 - }
404 -
405 - foreach ( $setFields as $field ) {
406 - if ( $incNullId || $field != 'id' || $this->hasIdField() ) {
407 - $data[$field] = $this->getField( $field );
408 - }
409 - }
410 -
411 - return $data;
412 - }
413 -
414 - /**
415 - * Load the default values, via getDefaults.
416 - *
417 - * @since 0.1
418 - *
419 - * @param boolean $override
420 - */
421 - public function loadDefaults( $override = true ) {
422 - $this->setFields( $this->getDefaults(), $override );
423 - }
424 -
425 - /**
426 - * Writes the answer to the database, either updating it
427 - * when it already exists, or inserting it when it doesn't.
428 - *
429 - * @since 0.1
430 - *
431 - * @return boolean Success indicator
432 - */
433 - public function save() {
434 - if ( $this->hasIdField() ) {
435 - return $this->saveExisting();
436 - } else {
437 - return $this->insert();
438 - }
439 - }
440 -
441 - /**
442 - * Updates the object in the database.
443 - *
444 - * @since 0.1
445 - *
446 - * @return boolean Success indicator
447 - */
448 - protected function saveExisting() {
449 - $dbw = wfGetDB( DB_MASTER );
450 -
451 - $success = $dbw->update(
452 - $this->getDBTable(),
453 - $this->getWriteValues(),
454 - array( $this->getFieldPrefix() . 'id' => $this->getId() ),
455 - __METHOD__
456 - );
457 -
458 - return $success;
459 - }
460 -
461 - /**
462 - * Inserts the object into the database.
463 - *
464 - * @since 0.1
465 - *
466 - * @return boolean Success indicator
467 - */
468 - protected function insert() {
469 - $dbw = wfGetDB( DB_MASTER );
470 -
471 - $result = $dbw->insert(
472 - $this->getDBTable(),
473 - $this->getWriteValues(),
474 - __METHOD__,
475 - array( 'IGNORE' )
476 - );
477 -
478 - if ( $result ) {
479 - $this->setField( 'id', $dbw->insertId() );
480 - }
481 -
482 - return $result;
483 - }
484 -
485 - /**
486 - * Removes the object from the database.
487 - *
488 - * @since 0.1
489 - *
490 - * @return boolean Success indicator
491 - */
492 - public function remove() {
493 - $this->beforeRemove();
494 -
495 - $success = static::delete( array( 'id' => $this->getId() ) );
496 -
497 - if ( $success ) {
498 - $this->onRemoved();
499 - }
500 -
501 - return $success;
502 - }
503 -
504 - /**
505 - * Gets called before an object is removed from the database.
506 - *
507 - * @since 0.1
508 - */
509 - protected function beforeRemove() {
510 - $this->loadFields( $this->getBeforeRemoveFields(), false, true );
511 - }
512 -
513 - /**
514 - * Before removal of an object happens, @see beforeRemove gets called.
515 - * This method loads the fields of which the names have been returned by this one (or all fields if null is returned).
516 - * This allows for loading info needed after removal to get rid of linked data and the like.
517 - *
518 - * @since 0.1
519 - *
520 - * @return array|null
521 - */
522 - protected function getBeforeRemoveFields() {
523 - return array();
524 - }
525 -
526 - /**
527 - * Gets called after successfull removal.
528 - * Can be overriden to get rid of linked data.
529 - *
530 - * @since 0.1
531 - */
532 - protected function onRemoved() {
533 - $this->setField( 'id', null );
534 - }
535 -
536 - /**
537 - * Return the names and values of the fields.
538 - *
539 - * @since 0.1
540 - *
541 - * @return array
542 - */
543 - public function getFields() {
544 - return $this->fields;
545 - }
546 -
547 - /**
548 - * Return the names of the fields.
549 - *
550 - * @since 0.1
551 - *
552 - * @return array
553 - */
554 - public function getSetFieldNames() {
555 - return array_keys( $this->fields );
556 - }
557 -
558 - /**
559 - * Sets the value of a field.
560 - * Strings can be provided for other types,
561 - * so this method can be called from unserialization handlers.
562 - *
563 - * @since 0.1
564 - *
565 - * @param string $name
566 - * @param mixed $value
567 - *
568 - * @throws MWException
569 - */
570 - public function setField( $name, $value ) {
571 - $fields = $this->getFieldTypes();
572 -
573 - if ( array_key_exists( $name, $fields ) ) {
574 - switch ( $fields[$name] ) {
575 - case 'int':
576 - $value = (int)$value;
577 - break;
578 - case 'float':
579 - $value = (float)$value;
580 - break;
581 - case 'bool':
582 - if ( is_string( $value ) ) {
583 - $value = $value !== '0';
584 - } elseif ( is_int( $value ) ) {
585 - $value = $value !== 0;
586 - }
587 - break;
588 - case 'array':
589 - if ( is_string( $value ) ) {
590 - $value = unserialize( $value );
591 - }
592 -
593 - if ( !is_array( $value ) ) {
594 - $value = array();
595 - }
596 - break;
597 - case 'blob':
598 - if ( is_string( $value ) ) {
599 - $value = unserialize( $value );
600 - }
601 - break;
602 - case 'id':
603 - if ( is_string( $value ) ) {
604 - $value = (int)$value;
605 - }
606 - break;
607 - }
608 -
609 - $this->fields[$name] = $value;
610 - } else {
611 - throw new MWException( 'Attempted to set unknown field ' . $name );
612 - }
613 - }
614 -
615 - /**
616 - * Get a new instance of the class from an array.
617 - *
618 - * @since 0.1
619 - *
620 - * @param array $data
621 - * @param boolean $loadDefaults
622 - *
623 - * @return EPDBObject
624 - */
625 - public static function newFromArray( array $data, $loadDefaults = false ) {
626 - return new static( $data, $loadDefaults );
627 - }
628 -
629 - /**
630 - * Get the database type used for read operations.
631 - *
632 - * @since 0.2
633 - * @return integer DB_ enum
634 - */
635 - public static function getReadDb() {
636 - return self::$readDb;
637 - }
638 -
639 - /**
640 - * Set the database type to use for read operations.
641 - *
642 - * @param integer $db
643 - *
644 - * @since 0.2
645 - */
646 - public static function setReadDb( $db ) {
647 - self::$readDb = $db;
648 - }
649 -
650 - /**
651 - * Gets if the object can take a certain field.
652 - *
653 - * @since 0.1
654 - *
655 - * @param string $name
656 - *
657 - * @return boolean
658 - */
659 - public static function canHasField( $name ) {
660 - return array_key_exists( $name, static::getFieldTypes() );
661 - }
662 -
663 - /**
664 - * Takes in a field or array of fields and returns an
665 - * array with their prefixed versions, ready for db usage.
666 - *
667 - * @since 0.1
668 - *
669 - * @param array|string $fields
670 - *
671 - * @return array
672 - */
673 - public static function getPrefixedFields( array $fields ) {
674 - foreach ( $fields as &$field ) {
675 - $field = static::getPrefixedField( $field );
676 - }
677 -
678 - return $fields;
679 - }
680 -
681 - /**
682 - * Takes in a field and returns an it's prefixed version, ready for db usage.
683 - * If the field needs to be prefixed for another table, provide an array in the form
684 - * array( 'tablename', 'fieldname' )
685 - * Where table name is registered in $egEPDBObjects.
686 - *
687 - * @since 0.1
688 - *
689 - * @param string|array $field
690 - *
691 - * @return string
692 - * @throws MWException
693 - */
694 - public static function getPrefixedField( $field ) {
695 - static $prefixes = false;
696 -
697 - if ( $prefixes === false ) {
698 - foreach ( $GLOBALS['egEPDBObjects'] as $classInfo ) {
699 - $prefixes[$classInfo['table']] = $classInfo['prefix'];
700 - }
701 - }
702 -
703 - if ( is_array( $field ) && count( $field ) > 1 ) {
704 - if ( array_key_exists( $field[0], $prefixes ) ) {
705 - $prefix = $prefixes[$field[0]];
706 - $field = $field[1];
707 - }
708 - else {
709 - throw new MWException( 'Tried to prefix field with unknown table "' . $field[0] . '"' );
710 - }
711 - }
712 - else {
713 - $prefix = static::getFieldPrefix();
714 - }
715 -
716 - return $prefix . $field;
717 - }
718 -
719 - /**
720 - * Takes in an associative array with field names as keys and
721 - * their values as value. The field names are prefixed with the
722 - * db field prefix.
723 - *
724 - * Field names can also be provided as an array with as first element a table name, such as
725 - * $conditions = array(
726 - * array( array( 'tablename', 'fieldname' ), $value ),
727 - * );
728 - *
729 - * @since 0.1
730 - *
731 - * @param array $values
732 - *
733 - * @return array
734 - */
735 - public static function getPrefixedValues( array $values ) {
736 - $prefixedValues = array();
737 -
738 - foreach ( $values as $field => $value ) {
739 - if ( is_integer( $field ) ) {
740 - if ( is_array( $value ) ) {
741 - $field = $value[0];
742 - $value = $value[1];
743 - }
744 - else {
745 - $value = explode( ' ', $value, 2 );
746 - $value[0] = static::getPrefixedField( $value[0] );
747 - $prefixedValues[] = implode( ' ', $value );
748 - continue;
749 - }
750 - }
751 -
752 - $prefixedValues[static::getPrefixedField( $field )] = $value;
753 - }
754 -
755 - return $prefixedValues;
756 - }
757 -
758 - /**
759 - * Get an array with fields from a database result,
760 - * that can be fed directly to the constructor or
761 - * to setFields.
762 - *
763 - * @since 0.1
764 - *
765 - * @param object $result
766 - *
767 - * @return array
768 - */
769 - public static function getFieldsFromDBResult( $result ) {
770 - $result = (array)$result;
771 - return array_combine(
772 - static::unprefixFieldNames( array_keys( $result ) ),
773 - array_values( $result )
774 - );
775 - }
776 -
777 - /**
778 - * Takes a field name with prefix and returns the unprefixed equivalent.
779 - *
780 - * @since 0.1
781 - *
782 - * @param string $fieldName
783 - *
784 - * @return string
785 - */
786 - public static function unprefixFieldName( $fieldName ) {
787 - return substr( $fieldName, strlen( static::getFieldPrefix() ) );
788 - }
789 -
790 - /**
791 - * Takes an array of field names with prefix and returns the unprefixed equivalent.
792 - *
793 - * @since 0.1
794 - *
795 - * @param array $fieldNames
796 - *
797 - * @return array
798 - */
799 - public static function unprefixFieldNames( array $fieldNames ) {
800 - return array_map( 'static::unprefixFieldName', $fieldNames );
801 - }
802 -
803 - /**
804 - * Get a new instance of the class from a database result.
805 - *
806 - * @since 0.1
807 - *
808 - * @param stdClass $result
809 - *
810 - * @return EPDBObject
811 - */
812 - public static function newFromDBResult( stdClass $result ) {
813 - return static::newFromArray( static::getFieldsFromDBResult( $result ) );
814 - }
815 -
816 - /**
817 - * Removes the object from the database.
818 - *
819 - * @since 0.1
820 - *
821 - * @param array $conditions
822 - *
823 - * @return boolean Success indicator
824 - */
825 - public static function delete( array $conditions ) {
826 - return wfGetDB( DB_MASTER )->delete(
827 - static::getDBTable(),
828 - static::getPrefixedValues( $conditions )
829 - );
830 - }
831 -
832 - /**
833 - * Add an amount (can be negative) to the specified field (needs to be numeric).
834 - *
835 - * @since 0.1
836 - *
837 - * @param string $field
838 - * @param integer $amount
839 - *
840 - * @return boolean Success indicator
841 - */
842 - public static function addToField( $field, $amount ) {
843 - if ( $amount == 0 ) {
844 - return true;
845 - }
846 -
847 - if ( !static::hasIdField() ) {
848 - return false;
849 - }
850 -
851 - $absoluteAmount = abs( $amount );
852 - $isNegative = $amount < 0;
853 -
854 - $dbw = wfGetDB( DB_MASTER );
855 -
856 - $fullField = static::getPrefixedField( $field );
857 -
858 - $success = $dbw->update(
859 - static::getDBTable(),
860 - array( "$fullField=$fullField" . ( $isNegative ? '-' : '+' ) . $absoluteAmount ),
861 - array( static::getPrefixedField( 'id' ) => static::getId() ),
862 - __METHOD__
863 - );
864 -
865 - if ( $success && static::hasField( $field ) ) {
866 - static::setField( $field, static::getField( $field ) + $amount );
867 - }
868 -
869 - return $success;
870 - }
871 -
872 - /**
873 - * Selects the the specified fields of the records matching the provided
874 - * conditions and returns them as EPDBObject. Field names get prefixed.
875 - *
876 - * @since 0.1
877 - *
878 - * @param array|string|null $fields
879 - * @param array $conditions
880 - * @param array $options
881 - * @param array $joinConds
882 - *
883 - * @return array of self
884 - */
885 - public static function select( $fields = null, array $conditions = array(), array $options = array(), array $joinConds = array() ) {
886 - $result = static::selectFields( $fields, $conditions, $options, $joinConds, false );
887 -
888 - $objects = array();
889 -
890 - foreach ( $result as $record ) {
891 - $objects[] = static::newFromArray( $record );
892 - }
893 -
894 - return $objects;
895 - }
896 -
897 - /**
898 - * Selects the the specified fields of the records matching the provided
899 - * conditions and returns them as associative arrays.
900 - * Provided field names get prefixed.
901 - * Returned field names will not have a prefix.
902 - *
903 - * When $collapse is true:
904 - * If one field is selected, each item in the result array will be this field.
905 - * If two fields are selected, each item in the result array will have as key
906 - * the first field and as value the second field.
907 - * If more then two fields are selected, each item will be an associative array.
908 - *
909 - * @since 0.1
910 - *
911 - * @param array|string|null $fields
912 - * @param array $conditions
913 - * @param array $options
914 - * @param array $joinConds
915 - * @param boolean $collapse Set to false to always return each result row as associative array.
916 - *
917 - * @return array of array
918 - */
919 - public static function selectFields( $fields = null, array $conditions = array(), array $options = array(), array $joinConds = array(), $collapse = true ) {
920 - if ( is_null( $fields ) ) {
921 - $fields = array_keys( static::getFieldTypes() );
922 - }
923 - else {
924 - $fields = (array)$fields;
925 - }
926 -
927 - $tables = array( static::getDBTable() );
928 - $joinConds = static::getProcessedJoinConds( $joinConds, $tables );
929 -
930 - $result = static::rawSelect(
931 - static::getPrefixedFields( $fields ),
932 - static::getPrefixedValues( $conditions ),
933 - $options,
934 - $joinConds,
935 - $tables
936 - );
937 -
938 - $objects = array();
939 -
940 - foreach ( $result as $record ) {
941 - $objects[] = static::getFieldsFromDBResult( $record );
942 - }
943 -
944 - if ( $collapse ) {
945 - if ( count( $fields ) === 1 ) {
946 - $objects = array_map( function( $object ) { return array_shift( $object ); } , $objects );
947 - }
948 - elseif ( count( $fields ) === 2 ) {
949 - $o = array();
950 -
951 - foreach ( $objects as $object ) {
952 - $o[array_shift( $object )] = array_shift( $object );
953 - }
954 -
955 - $objects = $o;
956 - }
957 - }
958 -
959 - return $objects;
960 - }
961 -
962 - /**
963 - * Process the join conditions. This includes prefixing table and field names,
964 - * and adding of needed tables.
965 - *
966 - * @since 0.1
967 - *
968 - * @param array $joinConds Join conditions without prefixes and fields in array rather then string with equals sign.
969 - * @param array $tables List of tables to which the extra needed ones get added.
970 - *
971 - * @return array Join conditions ready to be fed to MediaWikis native select function.
972 - */
973 - protected static function getProcessedJoinConds( array $joinConds, array &$tables ) {
974 - $conds = array();
975 -
976 - foreach ( $joinConds as $table => $joinCond ) {
977 - if ( !in_array( $table, $tables ) ) {
978 - $tables[] = $table;
979 - }
980 -
981 - $cond = array( $joinCond[0], array() );
982 -
983 - foreach ( $joinCond[1] as $joinCondPart ) {
984 - $parts = array(
985 - static::getPrefixedField( $joinCondPart[0] ),
986 - static::getPrefixedField( $joinCondPart[1] ),
987 - );
988 -
989 - if ( !in_array( $joinCondPart[0][0], $tables ) ) {
990 - $tables[] = $joinCondPart[0][0];
991 - }
992 -
993 - if ( !in_array( $joinCondPart[1][0], $tables ) ) {
994 - $tables[] = $joinCondPart[1][0];
995 - }
996 -
997 - $cond[1][] = implode( '=', $parts );
998 - }
999 -
1000 - $conds[$table] = $cond;
1001 - }
1002 -
1003 - return $conds;
1004 - }
1005 -
1006 - /**
1007 - * Selects the the specified fields of the first matching record.
1008 - * Field names get prefixed.
1009 - *
1010 - * @since 0.1
1011 - *
1012 - * @param array|string|null $fields
1013 - * @param array $conditions
1014 - * @param array $options
1015 - * @param array $joinConds
1016 - *
1017 - * @return EPBObject|false
1018 - */
1019 - public static function selectRow( $fields = null, array $conditions = array(), array $options = array(), array $joinConds = array() ) {
1020 - $options['LIMIT'] = 1;
1021 -
1022 - $objects = static::select( $fields, $conditions, $options, $joinConds );
1023 -
1024 - return count( $objects ) > 0 ? $objects[0] : false;
1025 - }
1026 -
1027 - /**
1028 - * Selects the the specified fields of the first record matching the provided
1029 - * conditions and returns it as an associative array, or false when nothing matches.
1030 - * This method makes use of selectFields and expects the same parameters and
1031 - * returns the same results (if there are any, if there are none, this method returns false).
1032 - * @see EPDBObject::selectFields
1033 - *
1034 - * @since 0.1
1035 - *
1036 - * @param array|string|null $fields
1037 - * @param array $conditions
1038 - * @param array $options
1039 - * @param array $joinConds
1040 - * @param boolean $collapse Set to false to always return each result row as associative array.
1041 - *
1042 - * @return mixed|array|false
1043 - */
1044 - public static function selectFieldsRow( $fields = null, array $conditions = array(), array $options = array(), array $joinConds = array(), $collapse = true ) {
1045 - $options['LIMIT'] = 1;
1046 -
1047 - $objects = static::selectFields( $fields, $conditions, $options, $joinConds, $collapse );
1048 -
1049 - return count( $objects ) > 0 ? $objects[0] : false;
1050 - }
1051 -
1052 - /**
1053 - * Returns if there is at least one record matching the provided conditions.
1054 - * Condition field names get prefixed.
1055 - *
1056 - * @since 0.1
1057 - *
1058 - * @param array $conditions
1059 - *
1060 - * @return boolean
1061 - */
1062 - public static function has( array $conditions = array() ) {
1063 - return static::selectRow( array( 'id' ), $conditions ) !== false;
1064 - }
1065 -
1066 - /**
1067 - * Returns the amount of matching records.
1068 - * Condition field names get prefixed.
1069 - *
1070 - * @since 0.1
1071 - *
1072 - * @param array $conditions
1073 - * @param array $options
1074 - *
1075 - * @return integer
1076 - */
1077 - public static function count( array $conditions = array(), array $options = array() ) {
1078 - $res = static::rawSelect(
1079 - array( 'COUNT(*) AS rowcount' ),
1080 - static::getPrefixedValues( $conditions ),
1081 - $options
1082 - )->fetchObject();
1083 -
1084 - return $res->rowcount;
1085 - }
1086 -
1087 - /**
1088 - * Selects the the specified fields of the records matching the provided
1089 - * conditions. Field names do NOT get prefixed.
1090 - *
1091 - * @since 0.1
1092 - *
1093 - * @param array $fields
1094 - * @param array $conditions
1095 - * @param array $options
1096 - * @param array $joinConds
1097 - * @param array $tables
1098 - *
1099 - * @return ResultWrapper
1100 - */
1101 - public static function rawSelect( array $fields, array $conditions = array(), array $options = array(), array $joinConds = array(), array $tables = null ) {
1102 - if ( is_null( $tables ) ) {
1103 - $tables = static::getDBTable();
1104 - }
1105 -
1106 - $dbr = wfGetDB( static::getReadDb() );
1107 -
1108 - return $dbr->select(
1109 - $tables,
1110 - $fields,
1111 - count( $conditions ) == 0 ? '' : $conditions,
1112 - __METHOD__,
1113 - $options,
1114 - $joinConds
1115 - );
1116 - }
1117 -
1118 - /**
1119 - * Update the records matching the provided conditions by
1120 - * setting the fields that are keys in the $values param to
1121 - * their corresponding values.
1122 - *
1123 - * @since 0.1
1124 - *
1125 - * @param array $values
1126 - * @param array $conditions
1127 - *
1128 - * @return boolean Success indicator
1129 - */
1130 - public static function update( array $values, array $conditions = array() ) {
1131 - $dbw = wfGetDB( DB_MASTER );
1132 -
1133 - return $dbw->update(
1134 - static::getDBTable(),
1135 - static::getPrefixedValues( $values ),
1136 - static::getPrefixedValues( $conditions ),
1137 - __METHOD__
1138 - );
1139 - }
1140 -
1141 - /**
1142 - * Return the names of the fields.
1143 - *
1144 - * @since 0.1
1145 - *
1146 - * @return array
1147 - */
1148 - public static function getFieldNames() {
1149 - return array_keys( static::getFieldTypes() );
1150 - }
1151 -
1152 - /**
1153 - * Returns an array with the fields and their descriptions.
1154 - *
1155 - * field name => field description
1156 - *
1157 - * @since 0.1
1158 - *
1159 - * @return array
1160 - */
1161 - public static function getFieldDescriptions() {
1162 - return array();
1163 - }
1164 -
1165 - /**
1166 - * Get API parameters for the fields supported by this object.
1167 - *
1168 - * @since 0.1
1169 - *
1170 - * @param boolean $requireParams
1171 - * @param boolean $setDefaults
1172 - *
1173 - * @return array
1174 - */
1175 - public static function getAPIParams( $requireParams = false, $setDefaults = false ) {
1176 - $typeMap = array(
1177 - 'id' => 'integer',
1178 - 'int' => 'integer',
1179 - 'float' => 'NULL',
1180 - 'str' => 'string',
1181 - 'bool' => 'integer',
1182 - 'array' => 'string',
1183 - 'blob' => 'string',
1184 - );
1185 -
1186 - $params = array();
1187 - $defaults = static::getDefaults();
1188 -
1189 - foreach ( static::getFieldTypes() as $field => $type ) {
1190 - if ( $field == 'id' ) {
1191 - continue;
1192 - }
1193 -
1194 - $hasDefault = array_key_exists( $field, $defaults );
1195 -
1196 - $params[$field] = array(
1197 - ApiBase::PARAM_TYPE => $typeMap[$type],
1198 - ApiBase::PARAM_REQUIRED => $requireParams && !$hasDefault
1199 - );
1200 -
1201 - if ( $type == 'array' ) {
1202 - $params[$field][ApiBase::PARAM_ISMULTI] = true;
1203 - }
1204 -
1205 - if ( $setDefaults && $hasDefault ) {
1206 - $default = is_array( $defaults[$field] ) ? implode( '|', $defaults[$field] ) : $defaults[$field];
1207 - $params[$field][ApiBase::PARAM_DFLT] = $default;
1208 - }
1209 - }
1210 -
1211 - return $params;
1212 - }
1213 -
1214 - /**
1215 - * Computes and updates the values of the summary fields.
1216 - *
1217 - * @since 0.1
1218 - *
1219 - * @param array|string|null $summaryFields
1220 - */
1221 - public function loadSummaryFields( $summaryFields = null ) {
1222 -
1223 - }
1224 -
1225 - /**
1226 - * Computes the values of the summary fields of the objects matching the provided conditions.
1227 - *
1228 - * @since 0.1
1229 - *
1230 - * @param array|string|null $summaryFields
1231 - * @param array $conditions
1232 - */
1233 - public static function updateSummaryFields( $summaryFields = null, array $conditions = array() ) {
1234 - self::setReadDb( DB_MASTER );
1235 -
1236 - foreach ( self::select( null, $conditions ) as /* EPDBObject */ $item ) {
1237 - $item->loadSummaryFields( $summaryFields );
1238 - $item->setSummaryMode( true );
1239 - $item->saveExisting();
1240 - }
1241 -
1242 - self::setReadDb( DB_SLAVE );
1243 - }
1244 -
1245 - /**
1246 - * Sets the value for the @see $updateSummaries field.
1247 - *
1248 - * @since 0.1
1249 - *
1250 - * @param boolean $update
1251 - */
1252 - public function setUpdateSummaries( $update ) {
1253 - $this->updateSummaries = $update;
1254 - }
1255 -
1256 - /**
1257 - * Sets the value for the @see $inSummaryMode field.
1258 - *
1259 - * @since 0.1
1260 - *
1261 - * @param boolean $update
1262 - */
1263 - public function setSummaryMode( $summaryMode ) {
1264 - $this->inSummaryMode = $summaryMode;
1265 - }
1266 -
1267 - /**
1268 - * Return if any fields got changed.
1269 - *
1270 - * @since 0.1
1271 - *
1272 - * @param EPDBObject $object
1273 - * @param boolean $excludeSummaryFields When set to true, summary field changes are ignored.
1274 - *
1275 - * @return boolean
1276 - */
1277 - protected function fieldsChanged( EPDBObject $object, $excludeSummaryFields = false ) {
1278 - foreach ( $this->fields as $name => $value ) {
1279 - $excluded = $excludeSummaryFields && in_array( $name, $this->getSummaryFields() );
1280 -
1281 - if ( !$excluded && $object->getField( $name ) !== $value ) {
1282 - return true;
1283 - }
1284 - }
1285 -
1286 - return false;
1287 - }
1288 -
1289 -}
Index: trunk/extensions/EducationProgram/includes/EPOrgPager.php
@@ -137,7 +137,7 @@
138138 * (non-PHPdoc)
139139 * @see EPPager::getControlLinks()
140140 */
141 - protected function getControlLinks( EPDBObject $item ) {
 141+ protected function getControlLinks( DBDataObject $item ) {
142142 $links = parent::getControlLinks( $item );
143143
144144 $links[] = $item->getLink( 'view', wfMsgHtml( 'view' ) );
Index: trunk/extensions/EducationProgram/includes/EPCoursePager.php
@@ -184,7 +184,7 @@
185185 * (non-PHPdoc)
186186 * @see EPPager::getControlLinks()
187187 */
188 - protected function getControlLinks( EPDBObject $item ) {
 188+ protected function getControlLinks( DBDataObject $item ) {
189189 $links = parent::getControlLinks( $item );
190190
191191 $links[] = $item->getLink( 'view', wfMsgHtml( 'view' ) );
Index: trunk/extensions/EducationProgram/includes/EPRevisions.php
@@ -1,7 +1,7 @@
22 <?php
33
44 /**
5 - * Static class for storing and retrieving revisions of EPDBObjects.
 5+ * Static class for storing and retrieving revisions of DBDataObjects.
66 *
77 * @since 0.1
88 *
Index: trunk/extensions/EducationProgram/includes/DBDataObject.php
@@ -0,0 +1,1288 @@
 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+ * * getFieldTypes
 12+ *
 13+ * These methods are likely candidates for overriding:
 14+ * * getDefaults
 15+ * * remove
 16+ * * insert
 17+ * * saveExisting
 18+ * * loadSummaryFields
 19+ * * getSummaryFields
 20+ *
 21+ * Deriving classes must register their table and field prefix in $egDBDataObjects.
 22+ * Syntax: $egDBDataObjects['DrivingClassName'] = array( 'table' => 'table_name', 'prefix' => 'fieldprefix_' );
 23+ * Example: $egDBDataObjects['EPOrg'] = array( 'table' => 'ep_orgs', 'prefix' => 'org_' );
 24+ *
 25+ * Main instance methods:
 26+ * * getField(s)
 27+ * * setField(s)
 28+ * * save
 29+ * * remove
 30+ *
 31+ * Main static methods:
 32+ * * select
 33+ * * update
 34+ * * delete
 35+ * * count
 36+ * * has
 37+ * * selectRow
 38+ * * selectFields
 39+ * * selectFieldsRow
 40+ *
 41+ * @since 0.1
 42+ *
 43+ * @file DBDataObject.php
 44+ * @ingroup EducationProgram
 45+ *
 46+ * @licence GNU GPL v3 or later
 47+ * @author Jeroen De Dauw < jeroendedauw@gmail.com >
 48+ */
 49+abstract class DBDataObject {
 50+
 51+ /**
 52+ * The fields of the object.
 53+ * field name (w/o prefix) => value
 54+ *
 55+ * @since 0.1
 56+ * @var array
 57+ */
 58+ protected $fields = array( 'id' => null );
 59+
 60+ /**
 61+ * If the object should update summaries of linked items when changed.
 62+ * For example, update the course_count field in universities when a course in courses is deleted.
 63+ * Settings this to false can prevent needless updating work in situations
 64+ * such as deleting a university, which will then delete all it's courses.
 65+ *
 66+ * @since 0.1
 67+ * @var bool
 68+ */
 69+ protected $updateSummaries = true;
 70+
 71+ /**
 72+ * Indicates if the object is in summary mode.
 73+ * This mode indicates that only summary fields got updated,
 74+ * which allows for optimizations.
 75+ *
 76+ * @since 0.1
 77+ * @var bool
 78+ */
 79+ protected $inSummaryMode = false;
 80+
 81+
 82+ /**
 83+ * The database connection to use for read operations.
 84+ * Can be changed via @see setReadDb.
 85+ *
 86+ * @since 0.2
 87+ * @var integer DB_ enum
 88+ */
 89+ protected static $readDb = DB_SLAVE;
 90+
 91+ /**
 92+ * Returns the name of the database table objects of this type are stored in.
 93+ *
 94+ * @since 0.1
 95+ *
 96+ * @throws MWException
 97+ * @return string
 98+ */
 99+ public static function getDBTable() {
 100+ global $egDBDataObjects;
 101+ if ( array_key_exists( get_called_class(), $egDBDataObjects ) ) {
 102+ return $egDBDataObjects[get_called_class()]['table'];
 103+ }
 104+ else {
 105+ throw new MWException( 'Class "' . get_called_class() . '" not found in $egDBDataObjects' );
 106+ }
 107+ }
 108+
 109+ /**
 110+ * Gets the db field prefix.
 111+ *
 112+ * @since 0.1
 113+ *
 114+ * @throws MWException
 115+ * @return string
 116+ */
 117+ protected static function getFieldPrefix() {
 118+ global $egDBDataObjects;
 119+ if ( array_key_exists( get_called_class(), $egDBDataObjects ) ) {
 120+ return $egDBDataObjects[get_called_class()]['prefix'];
 121+ }
 122+ else {
 123+ throw new MWException( 'Class "' . get_called_class() . '" not found in $egDBDataObjects' );
 124+ }
 125+ }
 126+
 127+ /**
 128+ * Returns an array with the fields and their types this object contains.
 129+ * This corresponds directly to the fields in the database, without prefix.
 130+ *
 131+ * field name => type
 132+ *
 133+ * Allowed types:
 134+ * * id
 135+ * * str
 136+ * * int
 137+ * * float
 138+ * * bool
 139+ * * array
 140+ *
 141+ * @since 0.1
 142+ *
 143+ * @throws MWException
 144+ * @return array
 145+ */
 146+ protected static function getFieldTypes() {
 147+ throw new MWException( 'Class did not implement getFieldTypes' );
 148+ }
 149+
 150+ /**
 151+ * Returns a list of default field values.
 152+ * field name => field value
 153+ *
 154+ * @since 0.1
 155+ *
 156+ * @return array
 157+ */
 158+ public static function getDefaults() {
 159+ return array();
 160+ }
 161+
 162+ /**
 163+ * Returns a list of the summary fields.
 164+ * These are fields that cache computed values, such as the amount of linked objects of $type.
 165+ * This is relevant as one might not want to do actions such as log changes when these get updated.
 166+ *
 167+ * @since 0.1
 168+ *
 169+ * @return array
 170+ */
 171+ public static function getSummaryFields() {
 172+ return array();
 173+ }
 174+
 175+ /**
 176+ * Constructor.
 177+ *
 178+ * @since 0.1
 179+ *
 180+ * @param array|null $fields
 181+ * @param boolean $loadDefaults
 182+ */
 183+ public function __construct( $fields = null, $loadDefaults = false ) {
 184+ if ( !is_array( $fields ) ) {
 185+ $fields = array();
 186+ }
 187+
 188+ if ( $loadDefaults ) {
 189+ $fields = array_merge( $this->getDefaults(), $fields );
 190+ }
 191+
 192+ $this->setFields( $fields );
 193+ }
 194+
 195+ /**
 196+ * Load the specified fields from the database.
 197+ *
 198+ * @since 0.1
 199+ *
 200+ * @param array|null $fields
 201+ * @param boolean $override
 202+ * @param boolean $skipLoaded
 203+ *
 204+ * @return Success indicator
 205+ */
 206+ public function loadFields( $fields = null, $override = true, $skipLoaded = false ) {
 207+ if ( is_null( $this->getId() ) ) {
 208+ return false;
 209+ }
 210+
 211+ if ( is_null( $fields ) ) {
 212+ $fields = array_keys( $this->getFieldTypes() );
 213+ }
 214+
 215+ if ( $skipLoaded ) {
 216+ $loadedFields = array_keys( $this->fields );
 217+ $fields = array_filter( $fields, function( $field ) use ( $loadedFields ) {
 218+ return !in_array( $field, $loadedFields );
 219+ } );
 220+ }
 221+
 222+ if ( count( $fields ) > 0 ) {
 223+ $results = $this->rawSelect(
 224+ $this->getPrefixedFields( $fields ),
 225+ array( $this->getPrefixedField( 'id' ) => $this->getId() ),
 226+ array( 'LIMIT' => 1 )
 227+ );
 228+
 229+ foreach ( $results as $result ) {
 230+ $this->setFields( $this->getFieldsFromDBResult( $result ), $override );
 231+ return true;
 232+ }
 233+
 234+ return false;
 235+ }
 236+
 237+ return true;
 238+ }
 239+
 240+ /**
 241+ * Gets the value of a field.
 242+ *
 243+ * @since 0.1
 244+ *
 245+ * @param string $name
 246+ * @param mixed $default
 247+ *
 248+ * @throws MWException
 249+ * @return mixed
 250+ */
 251+ public function getField( $name, $default = null ) {
 252+ if ( $this->hasField( $name ) ) {
 253+ return $this->fields[$name];
 254+ } elseif ( !is_null( $default ) ) {
 255+ return $default;
 256+ } else {
 257+ throw new MWException( 'Attempted to get not-set field ' . $name );
 258+ }
 259+ }
 260+
 261+ /**
 262+ * Gets the value of a field but first loads it if not done so already.
 263+ *
 264+ * @since 0.1
 265+ *
 266+ * @param string$name
 267+ *
 268+ * @return mixed
 269+ */
 270+ public function loadAndGetField( $name ) {
 271+ if ( !$this->hasField( $name ) ) {
 272+ $this->loadFields( array( $name ) );
 273+ }
 274+
 275+ return $this->getField( $name );
 276+ }
 277+
 278+ /**
 279+ * Remove a field.
 280+ *
 281+ * @since 0.1
 282+ *
 283+ * @param string $name
 284+ */
 285+ public function removeField( $name ) {
 286+ unset( $this->fields[$name] );
 287+ }
 288+
 289+ /**
 290+ * Returns the objects database id.
 291+ *
 292+ * @since 0.1
 293+ *
 294+ * @return integer|null
 295+ */
 296+ public function getId() {
 297+ return $this->getField( 'id' );
 298+ }
 299+
 300+ /**
 301+ * Sets the objects database id.
 302+ *
 303+ * @since 0.1
 304+ *
 305+ * @param integer|null $id
 306+ */
 307+ public function setId( $id ) {
 308+ return $this->setField( 'id', $id );
 309+ }
 310+
 311+ /**
 312+ * Gets if a certain field is set.
 313+ *
 314+ * @since 0.1
 315+ *
 316+ * @param string $name
 317+ *
 318+ * @return boolean
 319+ */
 320+ public function hasField( $name ) {
 321+ return array_key_exists( $name, $this->fields );
 322+ }
 323+
 324+ /**
 325+ * Gets if the id field is set.
 326+ *
 327+ * @since 0.1
 328+ *
 329+ * @return boolean
 330+ */
 331+ public function hasIdField() {
 332+ return $this->hasField( 'id' )
 333+ && !is_null( $this->getField( 'id' ) );
 334+ }
 335+
 336+ /**
 337+ * Sets multiple fields.
 338+ *
 339+ * @since 0.1
 340+ *
 341+ * @param array $fields The fields to set
 342+ * @param boolean $override Override already set fields with the provided values?
 343+ */
 344+ public function setFields( array $fields, $override = true ) {
 345+ foreach ( $fields as $name => $value ) {
 346+ if ( $override || !$this->hasField( $name ) ) {
 347+ $this->setField( $name, $value );
 348+ }
 349+ }
 350+ }
 351+
 352+ /**
 353+ * Gets the fields => values to write to the table.
 354+ *
 355+ * @since 0.1
 356+ *
 357+ * @return array
 358+ */
 359+ protected function getWriteValues() {
 360+ $values = array();
 361+
 362+ foreach ( $this->getFieldTypes() as $name => $type ) {
 363+ if ( array_key_exists( $name, $this->fields ) ) {
 364+ $value = $this->fields[$name];
 365+
 366+ switch ( $type ) {
 367+ case 'array':
 368+ $value = (array)$value;
 369+ case 'blob':
 370+ $value = serialize( $value );
 371+ }
 372+
 373+ $values[$this->getFieldPrefix() . $name] = $value;
 374+ }
 375+ }
 376+
 377+ return $values;
 378+ }
 379+
 380+ /**
 381+ * Serializes the object to an associative array which
 382+ * can then easily be converted into JSON or similar.
 383+ *
 384+ * @since 0.1
 385+ *
 386+ * @param null|array $fields
 387+ * @param boolean $incNullId
 388+ *
 389+ * @return array
 390+ */
 391+ public function toArray( $fields = null, $incNullId = false ) {
 392+ $data = array();
 393+ $setFields = array();
 394+
 395+ if ( !is_array( $fields ) ) {
 396+ $setFields = $this->getSetFieldNames();
 397+ } else {
 398+ foreach ( $fields as $field ) {
 399+ if ( $this->hasField( $field ) ) {
 400+ $setFields[] = $field;
 401+ }
 402+ }
 403+ }
 404+
 405+ foreach ( $setFields as $field ) {
 406+ if ( $incNullId || $field != 'id' || $this->hasIdField() ) {
 407+ $data[$field] = $this->getField( $field );
 408+ }
 409+ }
 410+
 411+ return $data;
 412+ }
 413+
 414+ /**
 415+ * Load the default values, via getDefaults.
 416+ *
 417+ * @since 0.1
 418+ *
 419+ * @param boolean $override
 420+ */
 421+ public function loadDefaults( $override = true ) {
 422+ $this->setFields( $this->getDefaults(), $override );
 423+ }
 424+
 425+ /**
 426+ * Writes the answer to the database, either updating it
 427+ * when it already exists, or inserting it when it doesn't.
 428+ *
 429+ * @since 0.1
 430+ *
 431+ * @return boolean Success indicator
 432+ */
 433+ public function save() {
 434+ if ( $this->hasIdField() ) {
 435+ return $this->saveExisting();
 436+ } else {
 437+ return $this->insert();
 438+ }
 439+ }
 440+
 441+ /**
 442+ * Updates the object in the database.
 443+ *
 444+ * @since 0.1
 445+ *
 446+ * @return boolean Success indicator
 447+ */
 448+ protected function saveExisting() {
 449+ $dbw = wfGetDB( DB_MASTER );
 450+
 451+ $success = $dbw->update(
 452+ $this->getDBTable(),
 453+ $this->getWriteValues(),
 454+ array( $this->getFieldPrefix() . 'id' => $this->getId() ),
 455+ __METHOD__
 456+ );
 457+
 458+ return $success;
 459+ }
 460+
 461+ /**
 462+ * Inserts the object into the database.
 463+ *
 464+ * @since 0.1
 465+ *
 466+ * @return boolean Success indicator
 467+ */
 468+ protected function insert() {
 469+ $dbw = wfGetDB( DB_MASTER );
 470+
 471+ $result = $dbw->insert(
 472+ $this->getDBTable(),
 473+ $this->getWriteValues(),
 474+ __METHOD__,
 475+ array( 'IGNORE' )
 476+ );
 477+
 478+ if ( $result ) {
 479+ $this->setField( 'id', $dbw->insertId() );
 480+ }
 481+
 482+ return $result;
 483+ }
 484+
 485+ /**
 486+ * Removes the object from the database.
 487+ *
 488+ * @since 0.1
 489+ *
 490+ * @return boolean Success indicator
 491+ */
 492+ public function remove() {
 493+ $this->beforeRemove();
 494+
 495+ $success = static::delete( array( 'id' => $this->getId() ) );
 496+
 497+ if ( $success ) {
 498+ $this->onRemoved();
 499+ }
 500+
 501+ return $success;
 502+ }
 503+
 504+ /**
 505+ * Gets called before an object is removed from the database.
 506+ *
 507+ * @since 0.1
 508+ */
 509+ protected function beforeRemove() {
 510+ $this->loadFields( $this->getBeforeRemoveFields(), false, true );
 511+ }
 512+
 513+ /**
 514+ * Before removal of an object happens, @see beforeRemove gets called.
 515+ * This method loads the fields of which the names have been returned by this one (or all fields if null is returned).
 516+ * This allows for loading info needed after removal to get rid of linked data and the like.
 517+ *
 518+ * @since 0.1
 519+ *
 520+ * @return array|null
 521+ */
 522+ protected function getBeforeRemoveFields() {
 523+ return array();
 524+ }
 525+
 526+ /**
 527+ * Gets called after successfull removal.
 528+ * Can be overriden to get rid of linked data.
 529+ *
 530+ * @since 0.1
 531+ */
 532+ protected function onRemoved() {
 533+ $this->setField( 'id', null );
 534+ }
 535+
 536+ /**
 537+ * Return the names and values of the fields.
 538+ *
 539+ * @since 0.1
 540+ *
 541+ * @return array
 542+ */
 543+ public function getFields() {
 544+ return $this->fields;
 545+ }
 546+
 547+ /**
 548+ * Return the names of the fields.
 549+ *
 550+ * @since 0.1
 551+ *
 552+ * @return array
 553+ */
 554+ public function getSetFieldNames() {
 555+ return array_keys( $this->fields );
 556+ }
 557+
 558+ /**
 559+ * Sets the value of a field.
 560+ * Strings can be provided for other types,
 561+ * so this method can be called from unserialization handlers.
 562+ *
 563+ * @since 0.1
 564+ *
 565+ * @param string $name
 566+ * @param mixed $value
 567+ *
 568+ * @throws MWException
 569+ */
 570+ public function setField( $name, $value ) {
 571+ $fields = $this->getFieldTypes();
 572+
 573+ if ( array_key_exists( $name, $fields ) ) {
 574+ switch ( $fields[$name] ) {
 575+ case 'int':
 576+ $value = (int)$value;
 577+ break;
 578+ case 'float':
 579+ $value = (float)$value;
 580+ break;
 581+ case 'bool':
 582+ if ( is_string( $value ) ) {
 583+ $value = $value !== '0';
 584+ } elseif ( is_int( $value ) ) {
 585+ $value = $value !== 0;
 586+ }
 587+ break;
 588+ case 'array':
 589+ if ( is_string( $value ) ) {
 590+ $value = unserialize( $value );
 591+ }
 592+
 593+ if ( !is_array( $value ) ) {
 594+ $value = array();
 595+ }
 596+ break;
 597+ case 'blob':
 598+ if ( is_string( $value ) ) {
 599+ $value = unserialize( $value );
 600+ }
 601+ break;
 602+ case 'id':
 603+ if ( is_string( $value ) ) {
 604+ $value = (int)$value;
 605+ }
 606+ break;
 607+ }
 608+
 609+ $this->fields[$name] = $value;
 610+ } else {
 611+ throw new MWException( 'Attempted to set unknown field ' . $name );
 612+ }
 613+ }
 614+
 615+ /**
 616+ * Get a new instance of the class from an array.
 617+ *
 618+ * @since 0.1
 619+ *
 620+ * @param array $data
 621+ * @param boolean $loadDefaults
 622+ *
 623+ * @return DBDataObject
 624+ */
 625+ public static function newFromArray( array $data, $loadDefaults = false ) {
 626+ return new static( $data, $loadDefaults );
 627+ }
 628+
 629+ /**
 630+ * Get the database type used for read operations.
 631+ *
 632+ * @since 0.2
 633+ * @return integer DB_ enum
 634+ */
 635+ public static function getReadDb() {
 636+ return self::$readDb;
 637+ }
 638+
 639+ /**
 640+ * Set the database type to use for read operations.
 641+ *
 642+ * @param integer $db
 643+ *
 644+ * @since 0.2
 645+ */
 646+ public static function setReadDb( $db ) {
 647+ self::$readDb = $db;
 648+ }
 649+
 650+ /**
 651+ * Gets if the object can take a certain field.
 652+ *
 653+ * @since 0.1
 654+ *
 655+ * @param string $name
 656+ *
 657+ * @return boolean
 658+ */
 659+ public static function canHasField( $name ) {
 660+ return array_key_exists( $name, static::getFieldTypes() );
 661+ }
 662+
 663+ /**
 664+ * Takes in a field or array of fields and returns an
 665+ * array with their prefixed versions, ready for db usage.
 666+ *
 667+ * @since 0.1
 668+ *
 669+ * @param array|string $fields
 670+ *
 671+ * @return array
 672+ */
 673+ public static function getPrefixedFields( array $fields ) {
 674+ foreach ( $fields as &$field ) {
 675+ $field = static::getPrefixedField( $field );
 676+ }
 677+
 678+ return $fields;
 679+ }
 680+
 681+ /**
 682+ * Takes in a field and returns an it's prefixed version, ready for db usage.
 683+ * If the field needs to be prefixed for another table, provide an array in the form
 684+ * array( 'tablename', 'fieldname' )
 685+ * Where table name is registered in $egDBDataObjects.
 686+ *
 687+ * @since 0.1
 688+ *
 689+ * @param string|array $field
 690+ *
 691+ * @return string
 692+ * @throws MWException
 693+ */
 694+ public static function getPrefixedField( $field ) {
 695+ static $prefixes = false;
 696+
 697+ if ( $prefixes === false ) {
 698+ foreach ( $GLOBALS['egDBDataObjects'] as $classInfo ) {
 699+ $prefixes[$classInfo['table']] = $classInfo['prefix'];
 700+ }
 701+ }
 702+
 703+ if ( is_array( $field ) && count( $field ) > 1 ) {
 704+ if ( array_key_exists( $field[0], $prefixes ) ) {
 705+ $prefix = $prefixes[$field[0]];
 706+ $field = $field[1];
 707+ }
 708+ else {
 709+ throw new MWException( 'Tried to prefix field with unknown table "' . $field[0] . '"' );
 710+ }
 711+ }
 712+ else {
 713+ $prefix = static::getFieldPrefix();
 714+ }
 715+
 716+ return $prefix . $field;
 717+ }
 718+
 719+ /**
 720+ * Takes in an associative array with field names as keys and
 721+ * their values as value. The field names are prefixed with the
 722+ * db field prefix.
 723+ *
 724+ * Field names can also be provided as an array with as first element a table name, such as
 725+ * $conditions = array(
 726+ * array( array( 'tablename', 'fieldname' ), $value ),
 727+ * );
 728+ *
 729+ * @since 0.1
 730+ *
 731+ * @param array $values
 732+ *
 733+ * @return array
 734+ */
 735+ public static function getPrefixedValues( array $values ) {
 736+ $prefixedValues = array();
 737+
 738+ foreach ( $values as $field => $value ) {
 739+ if ( is_integer( $field ) ) {
 740+ if ( is_array( $value ) ) {
 741+ $field = $value[0];
 742+ $value = $value[1];
 743+ }
 744+ else {
 745+ $value = explode( ' ', $value, 2 );
 746+ $value[0] = static::getPrefixedField( $value[0] );
 747+ $prefixedValues[] = implode( ' ', $value );
 748+ continue;
 749+ }
 750+ }
 751+
 752+ $prefixedValues[static::getPrefixedField( $field )] = $value;
 753+ }
 754+
 755+ return $prefixedValues;
 756+ }
 757+
 758+ /**
 759+ * Get an array with fields from a database result,
 760+ * that can be fed directly to the constructor or
 761+ * to setFields.
 762+ *
 763+ * @since 0.1
 764+ *
 765+ * @param object $result
 766+ *
 767+ * @return array
 768+ */
 769+ public static function getFieldsFromDBResult( $result ) {
 770+ $result = (array)$result;
 771+ return array_combine(
 772+ static::unprefixFieldNames( array_keys( $result ) ),
 773+ array_values( $result )
 774+ );
 775+ }
 776+
 777+ /**
 778+ * Takes a field name with prefix and returns the unprefixed equivalent.
 779+ *
 780+ * @since 0.1
 781+ *
 782+ * @param string $fieldName
 783+ *
 784+ * @return string
 785+ */
 786+ public static function unprefixFieldName( $fieldName ) {
 787+ return substr( $fieldName, strlen( static::getFieldPrefix() ) );
 788+ }
 789+
 790+ /**
 791+ * Takes an array of field names with prefix and returns the unprefixed equivalent.
 792+ *
 793+ * @since 0.1
 794+ *
 795+ * @param array $fieldNames
 796+ *
 797+ * @return array
 798+ */
 799+ public static function unprefixFieldNames( array $fieldNames ) {
 800+ return array_map( 'static::unprefixFieldName', $fieldNames );
 801+ }
 802+
 803+ /**
 804+ * Get a new instance of the class from a database result.
 805+ *
 806+ * @since 0.1
 807+ *
 808+ * @param stdClass $result
 809+ *
 810+ * @return DBDataObject
 811+ */
 812+ public static function newFromDBResult( stdClass $result ) {
 813+ return static::newFromArray( static::getFieldsFromDBResult( $result ) );
 814+ }
 815+
 816+ /**
 817+ * Removes the object from the database.
 818+ *
 819+ * @since 0.1
 820+ *
 821+ * @param array $conditions
 822+ *
 823+ * @return boolean Success indicator
 824+ */
 825+ public static function delete( array $conditions ) {
 826+ return wfGetDB( DB_MASTER )->delete(
 827+ static::getDBTable(),
 828+ static::getPrefixedValues( $conditions )
 829+ );
 830+ }
 831+
 832+ /**
 833+ * Add an amount (can be negative) to the specified field (needs to be numeric).
 834+ *
 835+ * @since 0.1
 836+ *
 837+ * @param string $field
 838+ * @param integer $amount
 839+ *
 840+ * @return boolean Success indicator
 841+ */
 842+ public static function addToField( $field, $amount ) {
 843+ if ( $amount == 0 ) {
 844+ return true;
 845+ }
 846+
 847+ if ( !static::hasIdField() ) {
 848+ return false;
 849+ }
 850+
 851+ $absoluteAmount = abs( $amount );
 852+ $isNegative = $amount < 0;
 853+
 854+ $dbw = wfGetDB( DB_MASTER );
 855+
 856+ $fullField = static::getPrefixedField( $field );
 857+
 858+ $success = $dbw->update(
 859+ static::getDBTable(),
 860+ array( "$fullField=$fullField" . ( $isNegative ? '-' : '+' ) . $absoluteAmount ),
 861+ array( static::getPrefixedField( 'id' ) => static::getId() ),
 862+ __METHOD__
 863+ );
 864+
 865+ if ( $success && static::hasField( $field ) ) {
 866+ static::setField( $field, static::getField( $field ) + $amount );
 867+ }
 868+
 869+ return $success;
 870+ }
 871+
 872+ /**
 873+ * Selects the the specified fields of the records matching the provided
 874+ * conditions and returns them as DBDataObject. Field names get prefixed.
 875+ *
 876+ * @since 0.1
 877+ *
 878+ * @param array|string|null $fields
 879+ * @param array $conditions
 880+ * @param array $options
 881+ * @param array $joinConds
 882+ *
 883+ * @return array of self
 884+ */
 885+ public static function select( $fields = null, array $conditions = array(), array $options = array(), array $joinConds = array() ) {
 886+ $result = static::selectFields( $fields, $conditions, $options, $joinConds, false );
 887+
 888+ $objects = array();
 889+
 890+ foreach ( $result as $record ) {
 891+ $objects[] = static::newFromArray( $record );
 892+ }
 893+
 894+ return $objects;
 895+ }
 896+
 897+ /**
 898+ * Selects the the specified fields of the records matching the provided
 899+ * conditions and returns them as associative arrays.
 900+ * Provided field names get prefixed.
 901+ * Returned field names will not have a prefix.
 902+ *
 903+ * When $collapse is true:
 904+ * If one field is selected, each item in the result array will be this field.
 905+ * If two fields are selected, each item in the result array will have as key
 906+ * the first field and as value the second field.
 907+ * If more then two fields are selected, each item will be an associative array.
 908+ *
 909+ * @since 0.1
 910+ *
 911+ * @param array|string|null $fields
 912+ * @param array $conditions
 913+ * @param array $options
 914+ * @param array $joinConds
 915+ * @param boolean $collapse Set to false to always return each result row as associative array.
 916+ *
 917+ * @return array of array
 918+ */
 919+ public static function selectFields( $fields = null, array $conditions = array(), array $options = array(), array $joinConds = array(), $collapse = true ) {
 920+ if ( is_null( $fields ) ) {
 921+ $fields = array_keys( static::getFieldTypes() );
 922+ }
 923+ else {
 924+ $fields = (array)$fields;
 925+ }
 926+
 927+ $tables = array( static::getDBTable() );
 928+ $joinConds = static::getProcessedJoinConds( $joinConds, $tables );
 929+
 930+ $result = static::rawSelect(
 931+ static::getPrefixedFields( $fields ),
 932+ static::getPrefixedValues( $conditions ),
 933+ $options,
 934+ $joinConds,
 935+ $tables
 936+ );
 937+
 938+ $objects = array();
 939+
 940+ foreach ( $result as $record ) {
 941+ $objects[] = static::getFieldsFromDBResult( $record );
 942+ }
 943+
 944+ if ( $collapse ) {
 945+ if ( count( $fields ) === 1 ) {
 946+ $objects = array_map( function( $object ) { return array_shift( $object ); } , $objects );
 947+ }
 948+ elseif ( count( $fields ) === 2 ) {
 949+ $o = array();
 950+
 951+ foreach ( $objects as $object ) {
 952+ $o[array_shift( $object )] = array_shift( $object );
 953+ }
 954+
 955+ $objects = $o;
 956+ }
 957+ }
 958+
 959+ return $objects;
 960+ }
 961+
 962+ /**
 963+ * Process the join conditions. This includes prefixing table and field names,
 964+ * and adding of needed tables.
 965+ *
 966+ * @since 0.1
 967+ *
 968+ * @param array $joinConds Join conditions without prefixes and fields in array rather then string with equals sign.
 969+ * @param array $tables List of tables to which the extra needed ones get added.
 970+ *
 971+ * @return array Join conditions ready to be fed to MediaWikis native select function.
 972+ */
 973+ protected static function getProcessedJoinConds( array $joinConds, array &$tables ) {
 974+ $conds = array();
 975+
 976+ foreach ( $joinConds as $table => $joinCond ) {
 977+ if ( !in_array( $table, $tables ) ) {
 978+ $tables[] = $table;
 979+ }
 980+
 981+ $cond = array( $joinCond[0], array() );
 982+
 983+ foreach ( $joinCond[1] as $joinCondPart ) {
 984+ $parts = array(
 985+ static::getPrefixedField( $joinCondPart[0] ),
 986+ static::getPrefixedField( $joinCondPart[1] ),
 987+ );
 988+
 989+ if ( !in_array( $joinCondPart[0][0], $tables ) ) {
 990+ $tables[] = $joinCondPart[0][0];
 991+ }
 992+
 993+ if ( !in_array( $joinCondPart[1][0], $tables ) ) {
 994+ $tables[] = $joinCondPart[1][0];
 995+ }
 996+
 997+ $cond[1][] = implode( '=', $parts );
 998+ }
 999+
 1000+ $conds[$table] = $cond;
 1001+ }
 1002+
 1003+ return $conds;
 1004+ }
 1005+
 1006+ /**
 1007+ * Selects the the specified fields of the first matching record.
 1008+ * Field names get prefixed.
 1009+ *
 1010+ * @since 0.1
 1011+ *
 1012+ * @param array|string|null $fields
 1013+ * @param array $conditions
 1014+ * @param array $options
 1015+ * @param array $joinConds
 1016+ *
 1017+ * @return EPBObject|false
 1018+ */
 1019+ public static function selectRow( $fields = null, array $conditions = array(), array $options = array(), array $joinConds = array() ) {
 1020+ $options['LIMIT'] = 1;
 1021+
 1022+ $objects = static::select( $fields, $conditions, $options, $joinConds );
 1023+
 1024+ return count( $objects ) > 0 ? $objects[0] : false;
 1025+ }
 1026+
 1027+ /**
 1028+ * Selects the the specified fields of the first record matching the provided
 1029+ * conditions and returns it as an associative array, or false when nothing matches.
 1030+ * This method makes use of selectFields and expects the same parameters and
 1031+ * returns the same results (if there are any, if there are none, this method returns false).
 1032+ * @see DBDataObject::selectFields
 1033+ *
 1034+ * @since 0.1
 1035+ *
 1036+ * @param array|string|null $fields
 1037+ * @param array $conditions
 1038+ * @param array $options
 1039+ * @param array $joinConds
 1040+ * @param boolean $collapse Set to false to always return each result row as associative array.
 1041+ *
 1042+ * @return mixed|array|false
 1043+ */
 1044+ public static function selectFieldsRow( $fields = null, array $conditions = array(), array $options = array(), array $joinConds = array(), $collapse = true ) {
 1045+ $options['LIMIT'] = 1;
 1046+
 1047+ $objects = static::selectFields( $fields, $conditions, $options, $joinConds, $collapse );
 1048+
 1049+ return count( $objects ) > 0 ? $objects[0] : false;
 1050+ }
 1051+
 1052+ /**
 1053+ * Returns if there is at least one record matching the provided conditions.
 1054+ * Condition field names get prefixed.
 1055+ *
 1056+ * @since 0.1
 1057+ *
 1058+ * @param array $conditions
 1059+ *
 1060+ * @return boolean
 1061+ */
 1062+ public static function has( array $conditions = array() ) {
 1063+ return static::selectRow( array( 'id' ), $conditions ) !== false;
 1064+ }
 1065+
 1066+ /**
 1067+ * Returns the amount of matching records.
 1068+ * Condition field names get prefixed.
 1069+ *
 1070+ * @since 0.1
 1071+ *
 1072+ * @param array $conditions
 1073+ * @param array $options
 1074+ *
 1075+ * @return integer
 1076+ */
 1077+ public static function count( array $conditions = array(), array $options = array() ) {
 1078+ $res = static::rawSelect(
 1079+ array( 'COUNT(*) AS rowcount' ),
 1080+ static::getPrefixedValues( $conditions ),
 1081+ $options
 1082+ )->fetchObject();
 1083+
 1084+ return $res->rowcount;
 1085+ }
 1086+
 1087+ /**
 1088+ * Selects the the specified fields of the records matching the provided
 1089+ * conditions. Field names do NOT get prefixed.
 1090+ *
 1091+ * @since 0.1
 1092+ *
 1093+ * @param array $fields
 1094+ * @param array $conditions
 1095+ * @param array $options
 1096+ * @param array $joinConds
 1097+ * @param array $tables
 1098+ *
 1099+ * @return ResultWrapper
 1100+ */
 1101+ public static function rawSelect( array $fields, array $conditions = array(), array $options = array(), array $joinConds = array(), array $tables = null ) {
 1102+ if ( is_null( $tables ) ) {
 1103+ $tables = static::getDBTable();
 1104+ }
 1105+
 1106+ $dbr = wfGetDB( static::getReadDb() );
 1107+
 1108+ return $dbr->select(
 1109+ $tables,
 1110+ $fields,
 1111+ count( $conditions ) == 0 ? '' : $conditions,
 1112+ __METHOD__,
 1113+ $options,
 1114+ $joinConds
 1115+ );
 1116+ }
 1117+
 1118+ /**
 1119+ * Update the records matching the provided conditions by
 1120+ * setting the fields that are keys in the $values param to
 1121+ * their corresponding values.
 1122+ *
 1123+ * @since 0.1
 1124+ *
 1125+ * @param array $values
 1126+ * @param array $conditions
 1127+ *
 1128+ * @return boolean Success indicator
 1129+ */
 1130+ public static function update( array $values, array $conditions = array() ) {
 1131+ $dbw = wfGetDB( DB_MASTER );
 1132+
 1133+ return $dbw->update(
 1134+ static::getDBTable(),
 1135+ static::getPrefixedValues( $values ),
 1136+ static::getPrefixedValues( $conditions ),
 1137+ __METHOD__
 1138+ );
 1139+ }
 1140+
 1141+ /**
 1142+ * Return the names of the fields.
 1143+ *
 1144+ * @since 0.1
 1145+ *
 1146+ * @return array
 1147+ */
 1148+ public static function getFieldNames() {
 1149+ return array_keys( static::getFieldTypes() );
 1150+ }
 1151+
 1152+ /**
 1153+ * Returns an array with the fields and their descriptions.
 1154+ *
 1155+ * field name => field description
 1156+ *
 1157+ * @since 0.1
 1158+ *
 1159+ * @return array
 1160+ */
 1161+ public static function getFieldDescriptions() {
 1162+ return array();
 1163+ }
 1164+
 1165+ /**
 1166+ * Get API parameters for the fields supported by this object.
 1167+ *
 1168+ * @since 0.1
 1169+ *
 1170+ * @param boolean $requireParams
 1171+ * @param boolean $setDefaults
 1172+ *
 1173+ * @return array
 1174+ */
 1175+ public static function getAPIParams( $requireParams = false, $setDefaults = false ) {
 1176+ $typeMap = array(
 1177+ 'id' => 'integer',
 1178+ 'int' => 'integer',
 1179+ 'float' => 'NULL',
 1180+ 'str' => 'string',
 1181+ 'bool' => 'integer',
 1182+ 'array' => 'string',
 1183+ 'blob' => 'string',
 1184+ );
 1185+
 1186+ $params = array();
 1187+ $defaults = static::getDefaults();
 1188+
 1189+ foreach ( static::getFieldTypes() as $field => $type ) {
 1190+ if ( $field == 'id' ) {
 1191+ continue;
 1192+ }
 1193+
 1194+ $hasDefault = array_key_exists( $field, $defaults );
 1195+
 1196+ $params[$field] = array(
 1197+ ApiBase::PARAM_TYPE => $typeMap[$type],
 1198+ ApiBase::PARAM_REQUIRED => $requireParams && !$hasDefault
 1199+ );
 1200+
 1201+ if ( $type == 'array' ) {
 1202+ $params[$field][ApiBase::PARAM_ISMULTI] = true;
 1203+ }
 1204+
 1205+ if ( $setDefaults && $hasDefault ) {
 1206+ $default = is_array( $defaults[$field] ) ? implode( '|', $defaults[$field] ) : $defaults[$field];
 1207+ $params[$field][ApiBase::PARAM_DFLT] = $default;
 1208+ }
 1209+ }
 1210+
 1211+ return $params;
 1212+ }
 1213+
 1214+ /**
 1215+ * Computes and updates the values of the summary fields.
 1216+ *
 1217+ * @since 0.1
 1218+ *
 1219+ * @param array|string|null $summaryFields
 1220+ */
 1221+ public function loadSummaryFields( $summaryFields = null ) {
 1222+
 1223+ }
 1224+
 1225+ /**
 1226+ * Computes the values of the summary fields of the objects matching the provided conditions.
 1227+ *
 1228+ * @since 0.1
 1229+ *
 1230+ * @param array|string|null $summaryFields
 1231+ * @param array $conditions
 1232+ */
 1233+ public static function updateSummaryFields( $summaryFields = null, array $conditions = array() ) {
 1234+ self::setReadDb( DB_MASTER );
 1235+
 1236+ foreach ( self::select( null, $conditions ) as /* DBDataObject */ $item ) {
 1237+ $item->loadSummaryFields( $summaryFields );
 1238+ $item->setSummaryMode( true );
 1239+ $item->saveExisting();
 1240+ }
 1241+
 1242+ self::setReadDb( DB_SLAVE );
 1243+ }
 1244+
 1245+ /**
 1246+ * Sets the value for the @see $updateSummaries field.
 1247+ *
 1248+ * @since 0.1
 1249+ *
 1250+ * @param boolean $update
 1251+ */
 1252+ public function setUpdateSummaries( $update ) {
 1253+ $this->updateSummaries = $update;
 1254+ }
 1255+
 1256+ /**
 1257+ * Sets the value for the @see $inSummaryMode field.
 1258+ *
 1259+ * @since 0.1
 1260+ *
 1261+ * @param boolean $update
 1262+ */
 1263+ public function setSummaryMode( $summaryMode ) {
 1264+ $this->inSummaryMode = $summaryMode;
 1265+ }
 1266+
 1267+ /**
 1268+ * Return if any fields got changed.
 1269+ *
 1270+ * @since 0.1
 1271+ *
 1272+ * @param DBDataObject $object
 1273+ * @param boolean $excludeSummaryFields When set to true, summary field changes are ignored.
 1274+ *
 1275+ * @return boolean
 1276+ */
 1277+ protected function fieldsChanged( DBDataObject $object, $excludeSummaryFields = false ) {
 1278+ foreach ( $this->fields as $name => $value ) {
 1279+ $excluded = $excludeSummaryFields && in_array( $name, $this->getSummaryFields() );
 1280+
 1281+ if ( !$excluded && $object->getField( $name ) !== $value ) {
 1282+ return true;
 1283+ }
 1284+ }
 1285+
 1286+ return false;
 1287+ }
 1288+
 1289+}
Property changes on: trunk/extensions/EducationProgram/includes/DBDataObject.php
___________________________________________________________________
Added: svn:eol-style
11290 + native
Index: trunk/extensions/EducationProgram/includes/EPArticle.php
@@ -12,7 +12,7 @@
1313 * @licence GNU GPL v3 or later
1414 * @author Jeroen De Dauw < jeroendedauw@gmail.com >
1515 */
16 -class EPArticle extends EPDBObject {
 16+class EPArticle extends DBDataObject {
1717
1818 /**
1919 * Cached user object for this revision.
@@ -42,7 +42,7 @@
4343
4444 /**
4545 * (non-PHPdoc)
46 - * @see EPDBObject::getDefaults()
 46+ * @see DBDataObject::getDefaults()
4747 */
4848 public static function getDefaults() {
4949 return array(
Index: trunk/extensions/EducationProgram/includes/EPCA.php
@@ -32,7 +32,7 @@
3333
3434 /**
3535 * (non-PHPdoc)
36 - * @see EPDBObject::getDefaults()
 36+ * @see DBDataObject::getDefaults()
3737 */
3838 public static function getDefaults() {
3939 return array(
Index: trunk/extensions/EducationProgram/includes/EPOrg.php
@@ -47,7 +47,7 @@
4848
4949 /**
5050 * (non-PHPdoc)
51 - * @see EPDBObject::getDefaults()
 51+ * @see DBDataObject::getDefaults()
5252 */
5353 public static function getDefaults() {
5454 return array(
@@ -66,7 +66,7 @@
6767
6868 /**
6969 * (non-PHPdoc)
70 - * @see EPDBObject::getSummaryFields()
 70+ * @see DBDataObject::getSummaryFields()
7171 */
7272 public static function getSummaryFields() {
7373 return array(
@@ -81,7 +81,7 @@
8282
8383 /**
8484 * (non-PHPdoc)
85 - * @see EPDBObject::loadSummaryFields()
 85+ * @see DBDataObject::loadSummaryFields()
8686 */
8787 public function loadSummaryFields( $summaryFields = null ) {
8888 if ( is_null( $summaryFields ) ) {
@@ -153,7 +153,7 @@
154154
155155 /**
156156 * (non-PHPdoc)
157 - * @see EPDBObject::save()
 157+ * @see DBDataObject::save()
158158 */
159159 public function save() {
160160 if ( $this->hasField( 'name' ) ) {
Index: trunk/extensions/EducationProgram/includes/EPRoleObject.php
@@ -11,7 +11,7 @@
1212 * @licence GNU GPL v3 or later
1313 * @author Jeroen De Dauw < jeroendedauw@gmail.com >
1414 */
15 -abstract class EPRoleObject extends EPDBObject implements EPIRole {
 15+abstract class EPRoleObject extends DBDataObject implements EPIRole {
1616
1717 /**
1818 * Field for caching the linked user.
Index: trunk/extensions/EducationProgram/includes/EPPager.php
@@ -2,7 +2,7 @@
33
44 /**
55 * Abstract class extending the TablePager with common functions
6 - * for pagers listing EPDBObject deriving classes and some compatibility helpers.
 6+ * for pagers listing DBDataObject deriving classes and some compatibility helpers.
77 *
88 * @since 0.1
99 *
@@ -22,16 +22,16 @@
2323 protected $conds;
2424
2525 /**
26 - * Name of the class deriving from EPDBObject.
 26+ * Name of the class deriving from DBDataObject.
2727 * @since 0.1
2828 * @var string
2929 */
3030 protected $className;
3131
3232 /**
33 - * EPDBObject object constructed from $this->currentRow.
 33+ * DBDataObject object constructed from $this->currentRow.
3434 * @since 0.1
35 - * @var EPDBObject
 35+ * @var DBDataObject
3636 */
3737 protected $currentObject;
3838
@@ -455,11 +455,11 @@
456456 *
457457 * @since 0.1
458458 *
459 - * @param EPDBObject $item
 459+ * @param DBDataObject $item
460460 *
461461 * @return array
462462 */
463 - protected function getControlLinks( EPDBObject $item ) {
 463+ protected function getControlLinks( DBDataObject $item ) {
464464 return array();
465465 }
466466
Index: trunk/extensions/EducationProgram/includes/EPRevision.php
@@ -11,7 +11,7 @@
1212 * @licence GNU GPL v3 or later
1313 * @author Jeroen De Dauw < jeroendedauw@gmail.com >
1414 */
15 -class EPRevision extends EPDBObject {
 15+class EPRevision extends DBDataObject {
1616
1717 /**
1818 * Cached user object for this revision.
@@ -64,7 +64,7 @@
6565 *
6666 * @since 0.1
6767 *
68 - * @param EPDBObject $object
 68+ * @param DBDataObject $object
6969 * @param EPRevisionAction $revAction
7070 *
7171 * @return EPRevision
Index: trunk/extensions/EducationProgram/includes/EPRevisionedObject.php
@@ -1,7 +1,7 @@
22 <?php
33
44 /**
5 - * Abstract base class for EPDBObjects with revision history and logging support.
 5+ * Abstract base class for DBDataObjects with revision history and logging support.
66 *
77 * @since 0.1
88 *
@@ -11,7 +11,7 @@
1212 * @licence GNU GPL v3 or later
1313 * @author Jeroen De Dauw < jeroendedauw@gmail.com >
1414 */
15 -abstract class EPRevisionedObject extends EPDBObject {
 15+abstract class EPRevisionedObject extends DBDataObject {
1616
1717 /**
1818 * If the object should log changes.
@@ -132,7 +132,7 @@
133133
134134 /**
135135 * (non-PHPdoc)
136 - * @see EPDBObject::saveExisting()
 136+ * @see DBDataObject::saveExisting()
137137 */
138138 protected function saveExisting() {
139139 if ( !$this->inSummaryMode ) {
@@ -173,7 +173,7 @@
174174
175175 /**
176176 * (non-PHPdoc)
177 - * @see EPDBObject::insert()
 177+ * @see DBDataObject::insert()
178178 */
179179 protected function insert() {
180180 $result = parent::insert();
@@ -188,7 +188,7 @@
189189
190190 /**
191191 * Do logging and revision storage after a removal.
192 - * @see EPDBObject::onRemoved()
 192+ * @see DBDataObject::onRemoved()
193193 *
194194 * @since 0.1
195195 */
@@ -238,7 +238,7 @@
239239
240240 /**
241241 * (non-PHPdoc)
242 - * @see EPDBObject::getBeforeRemoveFields()
 242+ * @see DBDataObject::getBeforeRemoveFields()
243243 */
244244 protected function getBeforeRemoveFields() {
245245 return null;
Index: trunk/extensions/EducationProgram/includes/EPOA.php
@@ -32,7 +32,7 @@
3333
3434 /**
3535 * (non-PHPdoc)
36 - * @see EPDBObject::getDefaults()
 36+ * @see DBDataObject::getDefaults()
3737 */
3838 public static function getDefaults() {
3939 return array(
Index: trunk/extensions/EducationProgram/includes/EPCourse.php
@@ -124,7 +124,7 @@
125125
126126 /**
127127 * (non-PHPdoc)
128 - * @see EPDBObject::getDefaults()
 128+ * @see DBDataObject::getDefaults()
129129 */
130130 public static function getDefaults() {
131131 return array(
@@ -152,7 +152,7 @@
153153
154154 /**
155155 * (non-PHPdoc)
156 - * @see EPDBObject::getSummaryFields()
 156+ * @see DBDataObject::getSummaryFields()
157157 */
158158 public static function getSummaryFields() {
159159 return array(
@@ -172,7 +172,7 @@
173173
174174 /**
175175 * (non-PHPdoc)
176 - * @see EPDBObject::loadSummaryFields()
 176+ * @see DBDataObject::loadSummaryFields()
177177 */
178178 public function loadSummaryFields( $summaryFields = null ) {
179179 if ( is_null( $summaryFields ) ) {
@@ -193,7 +193,7 @@
194194
195195 /**
196196 * (non-PHPdoc)
197 - * @see EPDBObject::insert()
 197+ * @see DBDataObject::insert()
198198 */
199199 protected function insert() {
200200 $success = parent::insert();
@@ -290,7 +290,7 @@
291291
292292 /**
293293 * (non-PHPdoc)
294 - * @see EPDBObject::save()
 294+ * @see DBDataObject::save()
295295 */
296296 public function save() {
297297 if ( $this->hasField( 'name' ) ) {
@@ -604,7 +604,7 @@
605605
606606 /**
607607 * (non-PHPdoc)
608 - * @see EPDBObject::setField()
 608+ * @see DBDataObject::setField()
609609 */
610610 public function setField( $name, $value ) {
611611 if ( $name === 'instructors' ) {

Status & tagging log