r91863 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r91862‎ | r91863 | r91864 >
Date:08:43, 11 July 2011
Author:salvatoreingala
Status:deferred
Tags:
Comment:
Changed preference descriptions format. 'fields' is now an array of preference descriptions instead of a map with the prefName => prefDescription (and preference name is now a field in description).
This is cleaner and more flexible (for example, fields that don't describe a gadget preference may now be added).
Modified paths:
  • /branches/salvatoreingala/Gadgets/Gadgets_tests.php (modified) (history)
  • /branches/salvatoreingala/Gadgets/api/ApiGetGadgetPrefs.php (modified) (history)
  • /branches/salvatoreingala/Gadgets/backend/GadgetPrefs.php (modified) (history)
  • /branches/salvatoreingala/Gadgets/ui/resources/jquery.formBuilder.js (modified) (history)

Diff [purge]

Index: branches/salvatoreingala/Gadgets/Gadgets_tests.php
@@ -89,7 +89,8 @@
9090 //Test with stdClass instead if array
9191 $this->assertFalse( GadgetPrefs::isPrefsDescriptionValid( (object)array(
9292 'fields' => array(
93 - 'testBoolean' => array(
 93+ array(
 94+ 'name' => 'testBoolean',
9495 'type' => 'boolean',
9596 'label' => 'foo',
9697 'default' => 'bar'
@@ -100,7 +101,8 @@
101102 //Test with wrong type
102103 $this->assertFalse( GadgetPrefs::isPrefsDescriptionValid( array(
103104 'fields' => array(
104 - 'testUnexisting' => array(
 105+ array(
 106+ 'name' => 'testUnexisting',
105107 'type' => 'unexistingtype',
106108 'label' => 'foo',
107109 'default' => 'bar'
@@ -108,10 +110,22 @@
109111 )
110112 ) ) );
111113
 114+ //Test with missing name
 115+ $this->assertFalse( GadgetPrefs::isPrefsDescriptionValid( array(
 116+ 'fields' => array(
 117+ array(
 118+ 'type' => 'boolean',
 119+ 'label' => 'foo',
 120+ 'default' => true
 121+ )
 122+ )
 123+ ) ) );
 124+
112125 //Test with wrong preference name
113126 $this->assertFalse( GadgetPrefs::isPrefsDescriptionValid( array(
114127 'fields' => array(
115 - 'testWrongN@me' => array(
 128+ array(
 129+ 'name' => 'testWrongN@me',
116130 'type' => 'boolean',
117131 'label' => 'foo',
118132 'default' => true
@@ -119,10 +133,41 @@
120134 )
121135 ) ) );
122136
 137+ //Test with two fields with the same name
 138+ $this->assertFalse( GadgetPrefs::isPrefsDescriptionValid( array(
 139+ 'fields' => array(
 140+ array(
 141+ 'name' => 'testBoolean',
 142+ 'type' => 'boolean',
 143+ 'label' => 'foo',
 144+ 'default' => true
 145+ ),
 146+ array(
 147+ 'name' => 'testBoolean',
 148+ 'type' => 'string',
 149+ 'label' => 'foo',
 150+ 'default' => 'bar'
 151+ )
 152+ )
 153+ ) ) );
 154+
 155+ //Test with fields encoded as associative array instead of regular array
 156+ $this->assertFalse( GadgetPrefs::isPrefsDescriptionValid( array(
 157+ 'fields' => array(
 158+ 'testBoolean' => array(
 159+ 'name' => 'testBoolean',
 160+ 'type' => 'string',
 161+ 'label' => 'foo',
 162+ 'default' => 'bar'
 163+ )
 164+ )
 165+ ) ) );
 166+
123167 //Test with too long preference name (41 characters)
124168 $this->assertFalse( GadgetPrefs::isPrefsDescriptionValid( array(
125169 'fields' => array(
126 - 'aPreferenceNameExceedingTheLimitOf40Chars' => array(
 170+ array(
 171+ 'name' => 'aPreferenceNameExceedingTheLimitOf40Chars',
127172 'type' => 'boolean',
128173 'label' => 'foo',
129174 'default' => true
@@ -133,7 +178,8 @@
134179 //This must pass, instead (40 characters is fine)
135180 $this->assertTrue( GadgetPrefs::isPrefsDescriptionValid( array(
136181 'fields' => array(
137 - 'otherPreferenceNameThatS40CharactersLong' => array(
 182+ array(
 183+ 'name' => 'otherPreferenceNameThatS40CharactersLong',
138184 'type' => 'boolean',
139185 'label' => 'foo',
140186 'default' => true
@@ -145,7 +191,8 @@
146192 //Test with an unexisting field parameter
147193 $this->assertFalse( GadgetPrefs::isPrefsDescriptionValid( array(
148194 'fields' => array(
149 - 'testBoolean' => array(
 195+ array(
 196+ 'name' => 'testBoolean',
150197 'type' => 'boolean',
151198 'label' => 'foo',
152199 'default' => true,
@@ -159,7 +206,8 @@
160207 function testPrefsDescriptionsBoolean() {
161208 $correct = array(
162209 'fields' => array(
163 - 'testBoolean' => array(
 210+ array(
 211+ 'name' => 'testBoolean',
164212 'type' => 'boolean',
165213 'label' => 'some label',
166214 'default' => true
@@ -171,7 +219,8 @@
172220
173221 $correct2 = array(
174222 'fields' => array(
175 - 'testBoolean' => array(
 223+ array(
 224+ 'name' => 'testBoolean',
176225 'type' => 'boolean',
177226 'label' => 'some label',
178227 'default' => false
@@ -184,7 +233,7 @@
185234 //Tests with wrong default values
186235 $wrong = $correct;
187236 foreach ( array( 0, 1, '', 'false', 'true', null, array() ) as $def ) {
188 - $wrong['fields']['testBoolean']['default'] = $def;
 237+ $wrong['fields'][0]['default'] = $def;
189238 $this->assertFalse( GadgetPrefs::isPrefsDescriptionValid( $wrong ) );
190239 }
191240 }
@@ -193,7 +242,8 @@
194243 function testPrefsDescriptionsString() {
195244 $correct = array(
196245 'fields' => array(
197 - 'testString' => array(
 246+ array(
 247+ 'name' => 'testString',
198248 'type' => 'string',
199249 'label' => 'some label',
200250 'minlength' => 6,
@@ -209,14 +259,14 @@
210260 //Tests with wrong default values
211261 $wrong = $correct;
212262 foreach ( array( null, true, false, 0, 1, array(), 'short', 'veryverylongstring' ) as $def ) {
213 - $wrong['fields']['testString']['default'] = $def;
 263+ $wrong['fields'][0]['default'] = $def;
214264 $this->assertFalse( GadgetPrefs::isPrefsDescriptionValid( $wrong ) );
215265 }
216266
217267 //Tests with correct default values (when required is false)
218268 $correct2 = $correct;
219269 foreach ( array( '', '6chars', '1234567890' ) as $def ) {
220 - $correct2['fields']['testString']['default'] = $def;
 270+ $correct2['fields'][0]['default'] = $def;
221271 $this->assertTrue( GadgetPrefs::isPrefsDescriptionValid( $correct2 ) );
222272 }
223273
@@ -231,7 +281,8 @@
232282 function testPrefsDescriptionsNumber() {
233283 $correctFloat = array(
234284 'fields' => array(
235 - 'testNumber' => array(
 285+ array(
 286+ 'name' => 'testNumber',
236287 'type' => 'number',
237288 'label' => 'some label',
238289 'min' => -15,
@@ -244,7 +295,8 @@
245296
246297 $correctInt = array(
247298 'fields' => array(
248 - 'testNumber' => array(
 299+ array(
 300+ 'name' => 'testNumber',
249301 'type' => 'number',
250302 'label' => 'some label',
251303 'min' => -15,
@@ -262,20 +314,20 @@
263315 //Tests with wrong default values (with 'required' = true)
264316 $wrongFloat = $correctFloat;
265317 foreach ( array( '', false, true, null, array(), -100, +100 ) as $def ) {
266 - $wrongFloat['fields']['testNumber']['default'] = $def;
 318+ $wrongFloat['fields'][0]['default'] = $def;
267319 $this->assertFalse( GadgetPrefs::isPrefsDescriptionValid( $wrongFloat ) );
268320 }
269321
270322 $wrongInt = $correctInt;
271323 foreach ( array( '', false, true, null, array(), -100, +100, 2.7182818 ) as $def ) {
272 - $wrongInt['fields']['testNumber']['default'] = $def;
 324+ $wrongInt['fields'][0]['default'] = $def;
273325 $this->assertFalse( GadgetPrefs::isPrefsDescriptionValid( $wrongInt ) );
274326 }
275327
276328 //If required=false, default=null must be accepted, too
277329 foreach ( array( $correctFloat, $correctInt ) as $correct ) {
278 - $correct['fields']['testNumber']['required'] = false;
279 - $correct['fields']['testNumber']['default'] = null;
 330+ $correct['fields'][0]['required'] = false;
 331+ $correct['fields'][0]['default'] = null;
280332 $this->assertTrue( GadgetPrefs::isPrefsDescriptionValid( $correct ) );
281333 }
282334 }
@@ -284,7 +336,8 @@
285337 function testPrefsDescriptionsSelect() {
286338 $correct = array(
287339 'fields' => array(
288 - 'testSelect' => array(
 340+ array(
 341+ 'name' => 'testSelect',
289342 'type' => 'select',
290343 'label' => 'some label',
291344 'default' => 3,
@@ -302,14 +355,14 @@
303356 //Tests with correct default values
304357 $correct2 = $correct;
305358 foreach ( array( null, true, 3, 'test' ) as $def ) {
306 - $correct2['fields']['testSelect']['default'] = $def;
 359+ $correct2['fields'][0]['default'] = $def;
307360 $this->assertTrue( GadgetPrefs::isPrefsDescriptionValid( $correct2 ) );
308361 }
309362
310363 //Tests with wrong default values
311364 $wrong = $correct;
312365 foreach ( array( '', 'true', 'null', false, array(), 0, 1, 3.0001 ) as $def ) {
313 - $wrong['fields']['testSelect']['default'] = $def;
 366+ $wrong['fields'][0]['default'] = $def;
314367 $this->assertFalse( GadgetPrefs::isPrefsDescriptionValid( $wrong ) );
315368 }
316369 }
@@ -318,7 +371,8 @@
319372 function testPrefsDescriptionsRange() {
320373 $correct = array(
321374 'fields' => array(
322 - 'testRange' => array(
 375+ array(
 376+ 'name' => 'testRange',
323377 'type' => 'range',
324378 'label' => 'some label',
325379 'default' => 35,
@@ -331,27 +385,28 @@
332386 //Tests with correct default values
333387 $correct2 = $correct;
334388 foreach ( array( 15, 33, 45 ) as $def ) {
335 - $correct2['fields']['testRange']['default'] = $def;
 389+ $correct2['fields'][0]['default'] = $def;
336390 $this->assertTrue( GadgetPrefs::isPrefsDescriptionValid( $correct2 ) );
337391 }
338392
339393 //Tests with wrong default values
340394 $wrong = $correct;
341395 foreach ( array( '', true, false, null, array(), '35', 14, 46, 30.2 ) as $def ) {
342 - $wrong['fields']['testRange']['default'] = $def;
 396+ $wrong['fields'][0]['default'] = $def;
343397 $this->assertFalse( GadgetPrefs::isPrefsDescriptionValid( $wrong ) );
344398 }
345399
346400 //Test with max not in the set min + k*step (step not given, so it's 1)
347401 $wrong = $correct;
348 - $wrong['fields']['testRange']['max'] = 45.5;
 402+ $wrong['fields'][0]['max'] = 45.5;
349403 $this->assertFalse( GadgetPrefs::isPrefsDescriptionValid( $wrong ) );
350404
351405
352406 //Tests with floating point min, max and step
353407 $correct = array(
354408 'fields' => array(
355 - 'testRange' => array(
 409+ array(
 410+ 'name' => 'testRange',
356411 'type' => 'range',
357412 'label' => 'some label',
358413 'default' => 0.20,
@@ -367,14 +422,14 @@
368423 //Tests with correct default values
369424 $correct2 = $correct;
370425 foreach ( array( -2.8, -2.55, 0.20, 4.2 ) as $def ) {
371 - $correct2['fields']['testRange']['default'] = $def;
 426+ $correct2['fields'][0]['default'] = $def;
372427 $this->assertTrue( GadgetPrefs::isPrefsDescriptionValid( $correct2 ) );
373428 }
374429
375430 //Tests with wrong default values
376431 $wrong = $correct;
377432 foreach ( array( '', true, false, null, array(), '0.20', -2.7, 0, 4.199999 ) as $def ) {
378 - $wrong['fields']['testRange']['default'] = $def;
 433+ $wrong['fields'][0]['default'] = $def;
379434 $this->assertFalse( GadgetPrefs::isPrefsDescriptionValid( $wrong ) );
380435 }
381436 }
@@ -383,7 +438,8 @@
384439 function testPrefsDescriptionsDate() {
385440 $correct = array(
386441 'fields' => array(
387 - 'testDate' => array(
 442+ array(
 443+ 'name' => 'testDate',
388444 'type' => 'date',
389445 'label' => 'some label',
390446 'default' => null
@@ -400,7 +456,7 @@
401457 '2011-12-31T23:59:59Z',
402458 ) as $def )
403459 {
404 - $correct2['fields']['testDate']['default'] = $def;
 460+ $correct2['fields'][0]['default'] = $def;
405461 $this->assertTrue( GadgetPrefs::isPrefsDescriptionValid( $correct2 ) );
406462 }
407463
@@ -423,7 +479,7 @@
424480 '2011:07-05T15:00:00Z'
425481 ) as $def )
426482 {
427 - $wrong['fields']['testDate']['default'] = $def;
 483+ $wrong['fields'][0]['default'] = $def;
428484 $this->assertFalse( GadgetPrefs::isPrefsDescriptionValid( $wrong ) );
429485 }
430486 }
@@ -432,7 +488,8 @@
433489 function testPrefsDescriptionsColor() {
434490 $correct = array(
435491 'fields' => array(
436 - 'testColor' => array(
 492+ array(
 493+ 'name' => 'testColor',
437494 'type' => 'color',
438495 'label' => 'some label',
439496 'default' => '#123456'
@@ -448,7 +505,7 @@
449506 '#8ed36e',
450507 ) as $def )
451508 {
452 - $correct2['fields']['testColor']['default'] = $def;
 509+ $correct2['fields'][0]['default'] = $def;
453510 $this->assertTrue( GadgetPrefs::isPrefsDescriptionValid( $correct2 ) );
454511 }
455512
@@ -465,7 +522,7 @@
466523 'red', //syntax not allowed
467524 ) as $def )
468525 {
469 - $wrong['fields']['testColor']['default'] = $def;
 526+ $wrong['fields'][0]['default'] = $def;
470527 $this->assertFalse( GadgetPrefs::isPrefsDescriptionValid( $wrong ) );
471528 }
472529 }
@@ -476,31 +533,36 @@
477534 return array( array(
478535 array(
479536 'fields' => array(
480 - 'testBoolean' => array(
 537+ array(
 538+ 'name' => 'testBoolean',
481539 'type' => 'boolean',
482540 'label' => '@foo',
483541 'default' => true
484542 ),
485 - 'testBoolean2' => array(
 543+ array(
 544+ 'name' => 'testBoolean2',
486545 'type' => 'boolean',
487546 'label' => '@@foo2',
488547 'default' => true
489548 ),
490 - 'testNumber' => array(
 549+ array(
 550+ 'name' => 'testNumber',
491551 'type' => 'number',
492552 'label' => '@foo3',
493553 'min' => 2.3,
494554 'max' => 13.94,
495555 'default' => 7
496556 ),
497 - 'testNumber2' => array(
 557+ array(
 558+ 'name' => 'testNumber2',
498559 'type' => 'number',
499560 'label' => 'foo4',
500561 'min' => 2.3,
501562 'max' => 13.94,
502563 'default' => 7
503564 ),
504 - 'testSelect' => array(
 565+ array(
 566+ 'name' => 'testSelect',
505567 'type' => 'select',
506568 'label' => 'foo',
507569 'default' => 3,
@@ -511,7 +573,8 @@
512574 '@opt4' => 'opt4value'
513575 )
514576 ),
515 - 'testSelect2' => array(
 577+ array(
 578+ 'name' => 'testSelect2',
516579 'type' => 'select',
517580 'label' => 'foo',
518581 'default' => 3,
@@ -557,9 +620,9 @@
558621 $this->assertEquals( $prefs2['testNumber'], $prefs['testNumber'] );
559622 $this->assertEquals( $prefs2['testSelect'], $prefs['testSelect'] );
560623
561 - $this->assertEquals( $prefs2['testBoolean2'], $prefsDescription['fields']['testBoolean2']['default'] );
562 - $this->assertEquals( $prefs2['testNumber2'], $prefsDescription['fields']['testNumber2']['default'] );
563 - $this->assertEquals( $prefs2['testSelect2'], $prefsDescription['fields']['testSelect2']['default'] );
 624+ $this->assertEquals( $prefs2['testBoolean2'], $prefsDescription['fields'][1]['default'] );
 625+ $this->assertEquals( $prefs2['testNumber2'], $prefsDescription['fields'][3]['default'] );
 626+ $this->assertEquals( $prefs2['testSelect2'], $prefsDescription['fields'][5]['default'] );
564627
565628 $g = $this->create( '*foo[ResourceLoader]| foo.css|foo.js|foo.bar' );
566629 $g->setPrefsDescription( $prefsDescription );
Index: branches/salvatoreingala/Gadgets/backend/GadgetPrefs.php
@@ -238,12 +238,17 @@
239239 public static function isPrefsDescriptionValid( $prefsDescription ) {
240240 if ( !is_array( $prefsDescription )
241241 || !isset( $prefsDescription['fields'] )
242 - || !is_array( $prefsDescription['fields'] )
243 - || count( $prefsDescription['fields'] ) == 0 )
 242+ || !is_array( $prefsDescription['fields'] ) )
244243 {
245244 return false;
246245 }
247 -
 246+
 247+ //Check if 'fields' is a regular (not-associative) array, and that it is not empty
 248+ $count = count( $prefsDescription['fields'] );
 249+ if ( $count == 0 || array_keys( $prefsDescription['fields'] ) !== range( 0, $count - 1 ) ) {
 250+ return false;
 251+ }
 252+
248253 //Count of mandatory members for each type
249254 $mandatoryCount = array();
250255 foreach ( self::$prefsDescriptionSpecifications as $type => $typeSpec ) {
@@ -256,22 +261,35 @@
257262 }
258263
259264 //TODO: validation of members other than $prefs['fields']
 265+
 266+ //Map of encountered names
 267+ $names = array();
260268
261 - foreach ( $prefsDescription['fields'] as $option => $optionDefinition ) {
 269+ foreach ( $prefsDescription['fields'] as $optionDefinition ) {
262270
263 - //Check if 'type' is set and valid
264 - if ( !isset( $optionDefinition['type'] ) ) {
 271+ //Check if 'name' and 'type' are set
 272+ if ( !isset( $optionDefinition['type'] ) || !isset( $optionDefinition['name'] ) ) {
265273 return false;
266274 }
267275
268276 $type = $optionDefinition['type'];
269277
 278+ //check if 'type' is valid
270279 if ( !isset( self::$prefsDescriptionSpecifications[$type] ) ) {
271280 return false;
272281 }
273282
274 - //check $option name compliance
275 - if ( strlen( $option ) > 40
 283+ $option = $optionDefinition['name'];
 284+
 285+ //check that it's different from previous names
 286+ if ( isset( $names[$option] ) ) {
 287+ return false;
 288+ }
 289+
 290+ $names[$option] = true;
 291+
 292+ //check option name compliance
 293+ if ( strlen( $option ) > 40
276294 || !preg_match( '/^[a-zA-Z_][a-zA-Z0-9_]*$/', $option ) )
277295 {
278296 return false;
@@ -283,8 +301,8 @@
284302 $count = 0; //count of present mandatory members
285303 foreach ( $optionDefinition as $fieldName => $fieldValue ) {
286304
287 - if ( $fieldName == 'type' ) {
288 - continue; //'type' must not be checked
 305+ if ( $fieldName == 'type' || $fieldName == 'name' ) {
 306+ continue; //'type' and 'name' must not be checked
289307 }
290308
291309 if ( !isset( $typeDescription[$fieldName] ) ) {
@@ -468,16 +486,19 @@
469487 * @return boolean true if $prefs passes validation against $prefsDescription, false otherwise.
470488 */
471489 public static function checkPrefsAgainstDescription( $prefsDescription, $prefs ) {
 490+ $validPrefs = array();
472491 //Check that all the given preferences pass validation
473 - foreach ( $prefsDescription['fields'] as $prefName => $prefDescription ) {
 492+ foreach ( $prefsDescription['fields'] as $prefDescription ) {
 493+ $prefName = $prefDescription['name'];
474494 if ( !self::checkSinglePref( $prefDescription, $prefs, $prefName ) ) {
475495 return false;
476496 }
 497+ $validPrefs[$prefName] = true;
477498 }
478499
479500 //Check that $prefs contains no preferences that are not described in $prefsDescription
480501 foreach ( $prefs as $prefName => $value ) {
481 - if ( !isset( $prefsDescription['fields'][$prefName] ) ) {
 502+ if ( !isset( $validPrefs[$prefName] ) ) {
482503 return false;
483504 }
484505 }
@@ -493,19 +514,23 @@
494515 * @param &$prefs Array: reference of the array of preferences to match.
495516 */
496517 public static function matchPrefsWithDescription( $prefsDescription, &$prefs ) {
 518+ $validPrefs = array();
 519+
 520+ //Fix preferences that fail validation, by replacing their value with default
 521+ foreach ( $prefsDescription['fields'] as $prefDescription ) {
 522+ $prefName = $prefDescription['name'];
 523+ if ( !self::checkSinglePref( $prefDescription, $prefs, $prefName ) ) {
 524+ $prefs[$prefName] = $prefDescription['default'];
 525+ }
 526+ $validPrefs[$prefName] = true;
 527+ }
 528+
497529 //Remove unexisting preferences from $prefs
498530 foreach ( $prefs as $prefName => $value ) {
499 - if ( !isset( $prefsDescription['fields'][$prefName] ) ) {
 531+ if ( !isset( $validPrefs[$prefName] ) ) {
500532 unset( $prefs[$prefName] );
501533 }
502534 }
503 -
504 - //Fix preferences that fail validation
505 - foreach ( $prefsDescription['fields'] as $prefName => $prefDescription ) {
506 - if ( !self::checkSinglePref( $prefDescription, $prefs, $prefName ) ) {
507 - $prefs[$prefName] = $prefDescription['default'];
508 - }
509 - }
510535 }
511536
512537 /**
Index: branches/salvatoreingala/Gadgets/api/ApiGetGadgetPrefs.php
@@ -53,8 +53,9 @@
5454 }
5555
5656 //Add user preferences to preference description
57 - foreach ( $userPrefs as $pref => $value ) {
58 - $prefsDescription['fields'][$pref]['value'] = $value;
 57+ foreach ( $prefsDescription['fields'] as $prefIdx => $prefDescription ) {
 58+ $prefName = $prefDescription['name'];
 59+ $prefsDescription['fields'][$prefIdx]['value'] = $userPrefs[$prefName];
5960 }
6061
6162 $this->getResult()->addValue( null, $this->getModuleName(), $prefsDescription );
Index: branches/salvatoreingala/Gadgets/ui/resources/jquery.formBuilder.js
@@ -556,37 +556,35 @@
557557
558558 var settings = {}; //validator settings
559559
560 - for ( var fieldName in description.fields ) {
561 - if ( description.fields.hasOwnProperty( fieldName )) {
562 - //TODO: validate fieldName
563 - var field = description.fields[fieldName];
 560+ for ( var i = 0; i < description.fields.length; i++ ) {
 561+ //TODO: validate fieldName
 562+ var field = description.fields[i],
 563+ fieldName = field.name,
 564+ FieldConstructor = validFieldTypes[field.type];
564565
565 - var FieldConstructor = validFieldTypes[field.type];
 566+ if ( typeof FieldConstructor != 'function' ) {
 567+ mw.log( "field with invalid type: " + field.type );
 568+ return null;
 569+ }
566570
567 - if ( typeof FieldConstructor != 'function' ) {
568 - mw.log( "field with invalid type: " + field.type );
569 - return null;
570 - }
571 -
572 - var f;
573 - try {
574 - f = new FieldConstructor( $form, fieldName, field );
575 - } catch ( e ) {
576 - mw.log( e );
577 - return null; //constructor failed, wrong syntax in field description
578 - }
579 -
580 - $form.append( f.getElement() );
581 -
582 - //If this field has validation rules, add them to settings
583 - var fieldSettings = f.getValidationSettings();
584 -
585 - if ( fieldSettings ) {
586 - $.extend( true, settings, fieldSettings );
587 - }
588 -
589 - fields.push( f );
 571+ var f;
 572+ try {
 573+ f = new FieldConstructor( $form, fieldName, field );
 574+ } catch ( e ) {
 575+ mw.log( e );
 576+ return null; //constructor failed, wrong syntax in field description
590577 }
 578+
 579+ $form.append( f.getElement() );
 580+
 581+ //If this field has validation rules, add them to settings
 582+ var fieldSettings = f.getValidationSettings();
 583+
 584+ if ( fieldSettings ) {
 585+ $.extend( true, settings, fieldSettings );
 586+ }
 587+
 588+ fields.push( f );
591589 }
592590
593591 var validator = $form.validate( settings );

Status & tagging log