Index: branches/license-work/phase3/includes/ImagePage.php |
— | — | @@ -596,8 +596,8 @@ |
597 | 597 | */ |
598 | 598 | protected function showFileProperties() { |
599 | 599 | $props = $this->img->properties(); |
600 | | - $authors = $props->getAuthors(); |
601 | | - $licenses = $props->getLicenses(); |
| 600 | + $authors = $props->get( 'author' ); |
| 601 | + $licenses = $props->get( 'license' ); |
602 | 602 | if ( $authors || $licenses ) { |
603 | 603 | global $wgOut; |
604 | 604 | |
Index: branches/license-work/phase3/includes/filerepo/FileProperties.php |
— | — | @@ -1,6 +1,11 @@ |
2 | 2 | <?php |
3 | 3 | |
4 | 4 | class FileProperties { |
| 5 | + public static $propertyClasses = array( |
| 6 | + 'license' => 'FileLicense', |
| 7 | + 'author' => 'FileAuthor', |
| 8 | + ); |
| 9 | + |
5 | 10 | /** |
6 | 11 | * Constructor for the FileProperties class that represents proeprties |
7 | 12 | * associated with a file. |
— | — | @@ -12,8 +17,8 @@ |
13 | 18 | $this->file = $file; |
14 | 19 | $this->revId = $revision; |
15 | 20 | |
16 | | - $this->authors = array(); |
17 | | - $this->licenses = array(); |
| 21 | + $this->props = array(); |
| 22 | + $this->propsByType = array(); |
18 | 23 | |
19 | 24 | $this->load(); |
20 | 25 | } |
— | — | @@ -23,6 +28,7 @@ |
24 | 29 | */ |
25 | 30 | public function load() { |
26 | 31 | if ( !$this->revId ) { |
| 32 | + // Load from the latest revision by default |
27 | 33 | $this->revId = $this->file->getTitle()->getLatestRevID(); |
28 | 34 | } |
29 | 35 | |
— | — | @@ -38,40 +44,72 @@ |
39 | 45 | * Construct FileAuthor and FileProperties objects from a database result |
40 | 46 | */ |
41 | 47 | protected function loadFromResult( $res ) { |
42 | | - $repo = $this->file->getRepo(); |
43 | | - $result = array(); |
44 | | - |
45 | 48 | foreach ( $res as $row ) { |
46 | | - switch ( $row->fp_key ) { |
47 | | - case 'author': |
48 | | - $this->authors[] = FileAuthor::newFromRow( $row ); |
49 | | - break; |
50 | | - case 'license': |
51 | | - $this->licenses[] = FileLicense::newFromRow( $repo, $row ); |
52 | | - break; |
| 49 | + if ( isset( self::$propertyClasses[$row->fp_key] ) ) { |
| 50 | + // Call the constructor |
| 51 | + $prop = call_user_func( self::$propertyClasses[$row->fp_key] . |
| 52 | + '::newFromRow', $this->file, $row ); |
| 53 | + |
| 54 | + $this->props[] = $prop; |
| 55 | + if ( !isset( $this->propsByType[$row->fp_key] ) ) { |
| 56 | + $this->propsByType[$row->fp_key] = array(); |
| 57 | + } |
| 58 | + $this->propsByType[$row->fp_key][] = $prop; |
53 | 59 | } |
54 | 60 | } |
55 | 61 | |
56 | | - if ( $this->licenses ) { |
57 | | - FileLicense::loadArray( $this->licenses ); |
| 62 | + foreach ( self::$propertyClasses as $key => $class ) { |
| 63 | + // Batch load properties |
| 64 | + if ( !empty( $this->propsByType[$key] ) ) { |
| 65 | + call_user_func( "$class::loadArray", $this->propsByType[$key] ); |
| 66 | + } |
58 | 67 | } |
59 | 68 | } |
60 | 69 | |
61 | 70 | /** |
62 | | - * Get all licenses associated with this file |
| 71 | + * Get all properties of $type, or all if null or omitted |
| 72 | + * |
| 73 | + * @param $type mixed |
| 74 | + * @return array |
63 | 75 | */ |
64 | | - public function getLicenses() { |
65 | | - return $this->licenses; |
| 76 | + public function get( $type = null ) { |
| 77 | + if ( is_null( $type ) ) { |
| 78 | + return $this->props; |
| 79 | + } |
| 80 | + return isset( $this->propsByType[$type] ) ? |
| 81 | + $this->propsByType[$type] : array(); |
66 | 82 | } |
| 83 | + |
67 | 84 | /** |
68 | | - * Get all authors associated with this file |
| 85 | + * Deleted all properties and sets them to the passed array |
| 86 | + * |
| 87 | + * @param $props array |
69 | 88 | */ |
70 | | - public function getAuthors() { |
71 | | - return $this->authors; |
| 89 | + public function set( $props ) { |
| 90 | + $this->props = array(); |
| 91 | + $this->propsByType = array(); |
| 92 | + |
| 93 | + $this->append( $props ); |
72 | 94 | } |
| 95 | + /** |
| 96 | + * Appends an array of properties to the current properties |
| 97 | + * |
| 98 | + * @param $props array |
| 99 | + */ |
| 100 | + public function append( $props ) { |
| 101 | + foreach ( $props as $prop ) { |
| 102 | + $this->props[] = $prop; |
| 103 | + |
| 104 | + $key = $prop->getKey(); |
| 105 | + if ( !isset( $this->propsByType[$key] ) ) { |
| 106 | + $this->propsByType = array(); |
| 107 | + } |
| 108 | + $this->propsByType[$key] = $prop; |
| 109 | + } |
| 110 | + } |
73 | 111 | |
74 | 112 | /** |
75 | | - * Save the licenses and authors to the database and create a new revision |
| 113 | + * Save the properties to the database and create a new revision |
76 | 114 | * |
77 | 115 | * @param $comment string Edit summary |
78 | 116 | * @param $minor bool Minor edit |
— | — | @@ -97,42 +135,82 @@ |
98 | 136 | $dbw = $this->file->getRepo()->getMasterDB(); |
99 | 137 | |
100 | 138 | $insert = array(); |
101 | | - foreach ( $this->authors as $author ) { |
102 | | - $a = array( |
| 139 | + foreach ( $this->props as $prop ) { |
| 140 | + $insert[] = array( |
103 | 141 | 'fp_rev_id' => $revId, |
104 | | - 'fp_key' => 'author', |
105 | | - 'fp_value_int' => $author->getId() |
| 142 | + 'fp_key' => $prop->getKey(), |
| 143 | + 'fp_value_int' => $prop->getIntValue(), |
| 144 | + 'fp_value_string' => $prop->getStringValue(), |
106 | 145 | ); |
107 | | - |
108 | | - $text = $author->getText(); |
109 | | - if ( $text ) { |
110 | | - $a['fp_value_text'] = $text; |
111 | | - } |
112 | | - $insert[] = $a; |
113 | 146 | } |
114 | | - foreach ( $this->licenses as $license ) { |
115 | | - $insert[] = array( |
116 | | - 'fp_rev_id' => $revId, |
117 | | - 'fp_key' => 'license', |
118 | | - 'fp_value_int' => $license->getId(), |
119 | | - ); |
120 | | - } |
121 | 147 | |
122 | | - |
123 | 148 | $dbw->insert( 'file_props', $insert, __METHOD__ ); |
124 | 149 | |
125 | 150 | $this->revId = $revId; |
126 | 151 | } |
127 | 152 | } |
128 | 153 | |
129 | | -class FileAuthor { |
| 154 | +/** |
| 155 | + * Base class for file properties |
| 156 | + */ |
| 157 | +abstract class FileProperty { |
130 | 158 | /** |
| 159 | + * Create a new property object from a row |
| 160 | + * |
| 161 | + * @param $file File |
| 162 | + * @param $row Stdclass |
| 163 | + */ |
| 164 | + public static function newFromRow( $file, $row ) { |
| 165 | + throw new MWException( __CLASS__ . ' does not implement newFromRow' ); |
| 166 | + } |
| 167 | + /** |
| 168 | + * Load any other information for an array of properties |
| 169 | + * |
| 170 | + * @param &$array array |
| 171 | + */ |
| 172 | + public static function loadArray( &$array ) {} |
| 173 | + /** |
| 174 | + * Get the key name |
| 175 | + * |
| 176 | + * @return string |
| 177 | + */ |
| 178 | + abstract public function getKey(); |
| 179 | + /** |
| 180 | + * Get the string value; null by default |
| 181 | + * |
| 182 | + * @return string|null |
| 183 | + */ |
| 184 | + public function getStringValue() { |
| 185 | + return null; |
| 186 | + } |
| 187 | + /** |
| 188 | + * Get the int value; null by default |
| 189 | + * |
| 190 | + * @return int|null |
| 191 | + */ |
| 192 | + public function getIntValue() { |
| 193 | + return null; |
| 194 | + } |
| 195 | + /** |
| 196 | + * Sets the value |
| 197 | + * |
| 198 | + * @param $value int|string |
| 199 | + */ |
| 200 | + abstract public function setValue( $value ); |
| 201 | +} |
| 202 | + |
| 203 | +/** |
| 204 | + * FileAuthor class that represents the author of a file; possibly a wiki user |
| 205 | + */ |
| 206 | +class FileAuthor extends FileProperty { |
| 207 | + /** |
131 | 208 | * Construct a FileAuthor object from a database row |
132 | 209 | * |
| 210 | + * @param $file File |
133 | 211 | * @param $row Stdclass |
134 | 212 | * @return FileAuthor |
135 | 213 | */ |
136 | | - public static function newFromRow( $row ) { |
| 214 | + public static function newFromRow( $file, $row ) { |
137 | 215 | return new self( $row->fp_value_int, $row->fp_value_text ); |
138 | 216 | } |
139 | 217 | /** |
— | — | @@ -150,7 +228,7 @@ |
151 | 229 | * |
152 | 230 | * @return int |
153 | 231 | */ |
154 | | - public function getUserId() { |
| 232 | + public function getIntValue() { |
155 | 233 | return $this->id; |
156 | 234 | } |
157 | 235 | /** |
— | — | @@ -158,21 +236,43 @@ |
159 | 237 | * |
160 | 238 | * @return string |
161 | 239 | */ |
162 | | - public function getText() { |
| 240 | + public function getStringValue() { |
163 | 241 | return $this->text; |
164 | 242 | } |
| 243 | + |
| 244 | + public function getKey() { |
| 245 | + return 'author'; |
| 246 | + } |
| 247 | + |
| 248 | + /** |
| 249 | + * Sets the name or user id of the author. Changing either the id or the name |
| 250 | + * does not change the other property |
| 251 | + * |
| 252 | + * @param $value string |
| 253 | + */ |
| 254 | + public function setValue( $value ) { |
| 255 | + if ( is_string( $value ) ) { |
| 256 | + $this->name = $value; |
| 257 | + } elseif ( is_int( $value ) ) { |
| 258 | + $this->id = $value; |
| 259 | + } |
| 260 | + } |
165 | 261 | } |
166 | 262 | |
167 | | -class FileLicense { |
| 263 | +/** |
| 264 | + * FileLicense class that represents the license of a file and provides access |
| 265 | + * to the extended license attributes |
| 266 | + */ |
| 267 | +class FileLicense extends FileProperty { |
168 | 268 | /** |
169 | 269 | * Initialize a license object from a row |
170 | 270 | * |
171 | | - * @param $repo FileRepo |
| 271 | + * @param $file File |
172 | 272 | * @param $row Stdclass |
173 | 273 | * @return FileLicense |
174 | 274 | */ |
175 | | - public static function newFromRow( $repo, $row ) { |
176 | | - $license = new self( $repo ); |
| 275 | + public static function newFromRow( $file, $row ) { |
| 276 | + $license = new self( $file->getRepo() ); |
177 | 277 | $license->id = $row->fp_value_int; |
178 | 278 | return $license; |
179 | 279 | } |
— | — | @@ -200,15 +300,45 @@ |
201 | 301 | $this->name = null; |
202 | 302 | $this->url = null; |
203 | 303 | $this->count = 0; |
| 304 | + $this->exists = null; |
204 | 305 | } |
205 | | - public function getId() { |
| 306 | + public function getKey() { |
| 307 | + return 'license'; |
| 308 | + } |
| 309 | + /** |
| 310 | + * Tries to load the license id and returns it |
| 311 | + * |
| 312 | + * @return int|null |
| 313 | + */ |
| 314 | + public function getIntValue() { |
| 315 | + if ( is_null( $this->id ) ) { |
| 316 | + $this->load(); |
| 317 | + } |
206 | 318 | return $this->id; |
207 | 319 | } |
208 | | - public function getName() { |
| 320 | + /** |
| 321 | + * Tries to load the license name and returns it |
| 322 | + * |
| 323 | + * @return string|null |
| 324 | + */ |
| 325 | + public function getStringValue() { |
| 326 | + if ( is_null( $this->name ) ) { |
| 327 | + $this->load(); |
| 328 | + } |
209 | 329 | return $this->name; |
210 | 330 | } |
211 | | - public function setName( $name ) { |
212 | | - $this->name = $name; |
| 331 | + /** |
| 332 | + * Sets the license name or id and sets the other property to null |
| 333 | + */ |
| 334 | + public function setValue( $value ) { |
| 335 | + $this->exists = null; |
| 336 | + if ( is_string( $value ) ) { |
| 337 | + $this->id = null; |
| 338 | + $this->name = $value; |
| 339 | + } elseif ( is_int( $value ) ) { |
| 340 | + $this->id = $value; |
| 341 | + $this->name = null; |
| 342 | + } |
213 | 343 | } |
214 | 344 | public function getUrl() { |
215 | 345 | return $this->url; |
— | — | @@ -219,7 +349,36 @@ |
220 | 350 | public function getCount() { |
221 | 351 | return $this->count; |
222 | 352 | } |
| 353 | + public function incrementCount( $inc ) { |
| 354 | + $this->count += $inc; |
| 355 | + } |
| 356 | + public function exists() { |
| 357 | + return $this->exists; |
| 358 | + } |
223 | 359 | |
| 360 | + public function load() { |
| 361 | + if ( !is_null( $this->exists ) ) { |
| 362 | + // Already loaded |
| 363 | + return; |
| 364 | + } |
| 365 | + |
| 366 | + $a = array( $this ); |
| 367 | + if ( !is_null( $this->id ) ) { |
| 368 | + $from = 'id'; |
| 369 | + } elseif ( !is_null( $this->name ) ) { |
| 370 | + $from = 'name'; |
| 371 | + } else { |
| 372 | + throw new MWException( 'Trying to load bogus license' ); |
| 373 | + } |
| 374 | + self::loadArrayFrom( $a, $from ); |
| 375 | + |
| 376 | + $this->exists = (bool)count( $a ); |
| 377 | + } |
| 378 | + |
| 379 | + public static function loadArray( &$licenses ) { |
| 380 | + self::loadArrayFrom( $licenses, 'id' ); |
| 381 | + } |
| 382 | + |
224 | 383 | /** |
225 | 384 | * Initializes an uninitialized array of FileLicense objects from the db. |
226 | 385 | * Removes non-existent licenses from the array. Allows loading from id or |
— | — | @@ -228,15 +387,15 @@ |
229 | 388 | * @param &$licenses array Array of FileLicense objects |
230 | 389 | * @param $loadFrom string id|name depending on from which field to load |
231 | 390 | */ |
232 | | - public static function loadArray( &$licenses, $loadFrom = 'id' ) { |
| 391 | + public static function loadArrayFrom( &$licenses, $loadFrom ) { |
233 | 392 | $licenseIds = array(); |
234 | 393 | foreach ( $licenses as $license ) { |
235 | 394 | switch ( $loadFrom ) { |
236 | 395 | case 'id': |
237 | | - $licenseIds[] = $license->getId(); |
| 396 | + $licenseIds[] = $license->getIntValue(); |
238 | 397 | break; |
239 | 398 | case 'name': |
240 | | - $licenseIds[] = $license->getName(); |
| 399 | + $licenseIds[] = $license->getStringValue(); |
241 | 400 | break; |
242 | 401 | } |
243 | 402 | |
— | — | @@ -276,6 +435,7 @@ |
277 | 436 | $this->name = $row->lic_name; |
278 | 437 | $this->url = $row->lic_url; |
279 | 438 | $this->count = $row->lic_count; |
| 439 | + $this->exists = true; |
280 | 440 | } |
281 | 441 | |
282 | 442 | /** |
— | — | @@ -284,7 +444,7 @@ |
285 | 445 | public function insert() { |
286 | 446 | $dbw = $this->repo->getMasterDb(); |
287 | 447 | $dbw->insert( 'licenses', array( |
288 | | - 'lic_name' => $this->getName(), |
| 448 | + 'lic_name' => $this->getStringValue(), |
289 | 449 | 'lic_url' => $this->getUrl(), |
290 | 450 | 'lic_count' => 0 ), |
291 | 451 | __METHOD__ ); |
— | — | @@ -296,15 +456,17 @@ |
297 | 457 | public function update() { |
298 | 458 | $dbw = $this->repo->getMasterDb(); |
299 | 459 | $dbw->update( 'licenses', array( |
300 | | - 'lic_name' => $this->getName(), |
| 460 | + 'lic_name' => $this->getStringValue(), |
301 | 461 | 'lic_url' => $this->getUrl(), |
302 | | - 'lic_count' => $this->count + 1 ), |
| 462 | + 'lic_count' => $this->count ), |
303 | 463 | array( 'lic_id' => $this->id ), |
304 | 464 | __METHOD__ ); |
305 | 465 | } |
306 | 466 | /** |
307 | 467 | * Inserts a new license into the database if this license does not have |
308 | | - * an id, updates it otherwise |
| 468 | + * an id, updates it otherwise. This updates the properties of this |
| 469 | + * license, as opposed to changing the license for this file. If you want |
| 470 | + * to change the license of this file, you need to use FileProperties::save |
309 | 471 | */ |
310 | 472 | public function save() { |
311 | 473 | if ( $this->id ) { |