From 17127a5157631e85311904b6bb39bdae72aa43e5 Mon Sep 17 00:00:00 2001 From: Guillaume Lajarige Date: Fri, 19 Feb 2016 16:43:28 +0000 Subject: [PATCH] Prerequisites to the custom fields (and space tabs to regular tabs conversion on some files) SVN:trunk[3919] --- js/field_set.js | 562 +++++++++--------- js/form_field.js | 394 ++++++------ js/form_handler.js | 283 ++++----- js/subform_field.js | 78 +-- .../form/field/checkboxfield.class.inc.php | 2 +- sources/form/field/field.class.inc.php | 516 +++++++++------- .../field/multiplechoicesfield.class.inc.php | 246 ++++---- sources/form/field/radiofield.class.inc.php | 2 +- sources/form/field/selectfield.class.inc.php | 86 +-- sources/form/field/subformfield.class.inc.php | 33 +- .../form/field/textareafield.class.inc.php | 2 +- sources/form/field/textfield.class.inc.php | 40 +- sources/form/form.class.inc.php | 551 +++++++++-------- sources/form/formmanager.class.inc.php | 155 +++-- .../validator/integervalidator.class.inc.php | 6 +- .../mandatoryvalidator.class.inc.php | 6 +- .../notemptyextkeyvalidator.class.inc.php | 6 +- .../validator/notemptyvalidator.class.inc.php | 6 +- .../form/validator/validator.class.inc.php | 136 ++--- .../bootstrap/bsformrenderer.class.inc.php | 28 +- .../bssimplefieldrenderer.class.inc.php | 360 +++++------ sources/renderer/fieldrenderer.class.inc.php | 58 +- sources/renderer/formrenderer.class.inc.php | 442 +++++++------- .../renderer/renderingoutput.class.inc.php | 270 ++++----- 24 files changed, 2278 insertions(+), 1990 deletions(-) diff --git a/js/field_set.js b/js/field_set.js index 69409f077..e3d808d7f 100644 --- a/js/field_set.js +++ b/js/field_set.js @@ -1,305 +1,307 @@ -//iTop Form handler +//iTop Field set +//Used by itop.form_handler and itop.subform_field to list their fields ; $(function() { - // the widget definition, where 'itop' is the namespace, - // 'form_handler' the widget name - $.widget( 'itop.field_set', - { - // default options - options: - { - field_identifier_attr: 'data-field-id', // convention: fields are rendered into a div and are identified by this attribute - fields_list: null, - fields_impacts: {}, - touched_fields: [], - is_valid: true, - form_path: '', - script_element: null, - style_element: null - }, + // the widget definition, where 'itop' is the namespace, + // 'field_set' the widget name + $.widget( 'itop.field_set', + { + // default options + options: + { + field_identifier_attr: 'data-field-id', // convention: fields are rendered into a div and are identified by this attribute + fields_list: null, + fields_impacts: {}, + touched_fields: [], + is_valid: true, + form_path: '', + script_element: null, + style_element: null + }, - buildData: - { - script_code: '', - style_code: '' - }, + buildData: + { + script_code: '', + style_code: '' + }, - // the constructor - _create: function() - { - var me = this; - - this.element - .addClass('field_set'); - - this.element - .bind('field_change', function(event, data){ - console.log('field_set: field_change'); - me._onFieldChange(event, data); - }) - .bind('update_form', function(event, data){ - console.log('field_set: update_form'); - me._onUpdateForm(event, data); - }) - .bind('get_current_values', function(event, data){ - console.log('field_set: get_current_values'); - return me._onGetCurrentValues(event, data); - }) - .bind('validate', function(event, data){ - if (data === undefined) - { - data = {}; - } - console.log('field_set: validate'); - return me._onValidate(event, data); - }); + // the constructor + _create: function() + { + var me = this; + + this.element + .addClass('field_set'); + + this.element + .bind('field_change', function(oEvent, oData){ + console.log('field_set: field_change'); + me._onFieldChange(oEvent, oData); + }) + .bind('update_form', function(oEvent, oData){ + console.log('field_set: update_form'); + me._onUpdateForm(oEvent, oData); + }) + .bind('get_current_values', function(oEvent, oData){ + console.log('field_set: get_current_values'); + return me._onGetCurrentValues(oEvent, oData); + }) + .bind('validate', function(oEvent, oData){ + if (oData === undefined) + { + oData = {}; + } + console.log('field_set: validate'); + return me._onValidate(oEvent, oData); + }); - // Creating DOM elements if not using user's specifics - if(this.options.script_element === null) - { - this.options.script_element = $(''); - this.element.after(this.options.script_element); - } - if(this.options.style_element === null) - { - this.options.style_element = $(''); - this.element.before(this.options.style_element); - } + // Creating DOM elements if not using user's specifics + if(this.options.script_element === null) + { + this.options.script_element = $(''); + this.element.after(this.options.script_element); + } + if(this.options.style_element === null) + { + this.options.style_element = $(''); + this.element.before(this.options.style_element); + } - // Building the form - if(this.options.fields_list !== null) - { - this.buildForm(); - } - }, + // Building the form + if(this.options.fields_list !== null) + { + this.buildForm(); + } + }, - // called when created, and later when changing options - _refresh: function() - { - - }, - // events bound via _bind are removed automatically - // revert other modifications here - _destroy: function() - { - this.element - .removeClass('field_set'); - }, - // _setOptions is called with a hash of all options that are changing - // always refresh when changing options - _setOptions: function() - { - this._superApply(arguments); - }, - // _setOption is called for each individual option that is changing - _setOption: function( key, value ) - { - this._super( key, value ); - }, - _getField: function (sFieldId) - { - return this.element.find('[' + this.options.field_identifier_attr + '="'+sFieldId+'"][data-form-path="'+this.options.form_path+'"]'); - }, - _onGetCurrentValues: function(event, data) - { - event.stopPropagation(); + // called when created, and later when changing options + _refresh: function() + { + + }, + // events bound via _bind are removed automatically + // revert other modifications here + _destroy: function() + { + this.element + .removeClass('field_set'); + }, + // _setOptions is called with a hash of all options that are changing + // always refresh when changing options + _setOptions: function() + { + this._superApply(arguments); + }, + // _setOption is called for each individual option that is changing + _setOption: function( key, value ) + { + this._super( key, value ); + }, + getField: function (sFieldId) + { + return this.element.find('[' + this.options.field_identifier_attr + '="' + sFieldId + '"][data-form-path="' + this.options.form_path + '"]'); + }, + _onGetCurrentValues: function(oEvent, oData) + { + oEvent.stopPropagation(); - var result = {}; - - for(var i in this.options.fields_list) - { - var field = this.options.fields_list[i]; - if(this._getField(field.id).hasClass('form_field')) - { - result[field.id] = this._getField(field.id).triggerHandler('get_current_value'); - } - else - { - console.log('Field set : Cannot retrieve current value from field [' + this.options.field_identifier_attr + '="'+field.id+'"] as it seems to have no itop.form_field widget attached.'); - } - } - - return result; - }, - _getRequestedFields: function(sourceFieldName) - { - var fieldsName = []; - - if(this.options.fields_impacts[sourceFieldName] !== undefined) - { - for(var i in this.options.fields_impacts[sourceFieldName]) - { - fieldsName.push(this.options.fields_impacts[sourceFieldName][i]); - } - } - - return fieldsName; - }, - _onFieldChange: function(event, data) - { - event.stopPropagation(); + var oResult = {}; + + for(var i in this.options.fields_list) + { + var oField = this.options.fields_list[i]; + if(this.getField(oField.id).hasClass('form_field')) + { + oResult[oField.id] = this.getField(oField.id).triggerHandler('get_current_value'); + } + else + { + console.log('Field set : Cannot retrieve current value from field [' + this.options.field_identifier_attr + '="' + oField.id + '"][data-form-path="' + this.options.form_path + '"] as it seems to have no itop.form_field widget attached.'); + } + } + + return oResult; + }, + _getRequestedFields: function(sSourceFieldName) + { + var aFieldsName = []; + + if(this.options.fields_impacts[sSourceFieldName] !== undefined) + { + for(var i in this.options.fields_impacts[sSourceFieldName]) + { + aFieldsName.push(this.options.fields_impacts[sSourceFieldName][i]); + } + } + + return aFieldsName; + }, + _onFieldChange: function(oEvent, oData) + { + oEvent.stopPropagation(); - // Set field as touched so we know that we have to do checks on it later - if(this.options.touched_fields.indexOf(data.name) < 0) - { - this.options.touched_fields.push(data.name); - } + // Set field as touched so we know that we have to do checks on it later + if(this.options.touched_fields.indexOf(oData.name) < 0) + { + this.options.touched_fields.push(oData.name); + } - // Validate the field - var oRes = this._getField(data.name).triggerHandler('validate', {touched_fields_only: true}); - if (!oRes.is_valid) - { - this.options.is_valid = false; - } + // Validate the field + var oResult = this.getField(oData.name).triggerHandler('validate', {touched_fields_only: true}); + if (!oResult.is_valid) + { + this.options.is_valid = false; + } - var requestedFields = this._getRequestedFields(data.name); - if(requestedFields.length > 0) - { - this.element.trigger('update_fields', {form_path: this.options.form_path, requested_fields: requestedFields}); - } - }, - _onUpdateForm: function(event, data) - { - event.stopPropagation(); + var oRequestedFields = this._getRequestedFields(oData.name); + if(oRequestedFields.length > 0) + { + this.element.trigger('update_fields', {form_path: this.options.form_path, requested_fields: oRequestedFields}); + } + }, + _onUpdateForm: function(oEvent, oData) + { + oEvent.stopPropagation(); - this.buildData.script_code = ''; - this.buildData.style_code = ''; + this.buildData.script_code = ''; + this.buildData.style_code = ''; - for (var i in data.updated_fields) - { - var updated_field = data.updated_fields[i]; - this.options.fields_list[updated_field.id] = updated_field; - this._prepareField(updated_field.id); - } + for (var i in oData.updated_fields) + { + var oUpdatedField = oData.updated_fields[i]; + this.options.fields_list[oUpdatedField.id] = oUpdatedField; + this._prepareField(oUpdatedField.id); + } - // Adding code to the dom - this.options.script_element.append('\n\n// Appended by update at ' + Date() + '\n' + this.buildData.script_code); - this.options.style_element.append('\n\n// Appended by update at ' + Date() + '\n' + this.buildData.style_code); + // Adding code to the dom + this.options.script_element.append('\n\n// Appended by update on ' + Date() + '\n' + this.buildData.script_code); + this.options.style_element.append('\n\n// Appended by update on ' + Date() + '\n' + this.buildData.style_code); - // Evaluating script code as adding it to dom did not executed it (only script from update !) - eval(this.buildData.script_code); - }, - _onValidate: function(event, data) - { - event.stopPropagation(); + // Evaluating script code as adding it to dom did not executed it (only script from update !) + eval(this.buildData.script_code); + }, + _onValidate: function(oEvent, oData) + { + oEvent.stopPropagation(); - this.options.is_valid = true; + this.options.is_valid = true; + var aFieldsToValidate = []; + if ((oData.touched_fields_only !== undefined) && (oData.touched_fields_only === true)) + { + aFieldsToValidate = this.options.touched_fields; + } + else + { + // TODO : Requires IE9+ Object.keys(this.options.fields_list); + for (var sFieldId in this.options.fields_list) + { + aFieldsToValidate.push(sFieldId); + } + } - var aFieldsToValidate = []; - if ((data.touched_fields_only !== undefined) && (data.touched_fields_only === true)) - { - aFieldsToValidate = this.options.touched_fields; - } - else - { - // Requires IE9+ Object.keys(this.options.fields_list); - for (var sFieldId in this.options.fields_list) - { - aFieldsToValidate.push(sFieldId); - } - } + for(var i in aFieldsToValidate) + { + var oRes = this.getField(aFieldsToValidate[i]).triggerHandler('validate', oData); + if (!oRes.is_valid) + { + this.options.is_valid = false; + } + } + return this.options.is_valid; + }, + // Debug helper + showOptions: function() + { + return this.options; + }, + _loadCssFile: function(url) + { + if (!$('link[href="' + url + '"]').length) + $('').appendTo('head'); + }, + _loadJsFile: function(url) + { + if (!$('script[src="' + url + '"]').length) + $.getScript(url); + }, + // Place a field for which no container exists + _addField: function(sFieldId) + { + $('
').appendTo(this.element); + }, + _prepareField: function(sFieldId) + { + var oField = this.options.fields_list[sFieldId]; - for(var i in aFieldsToValidate) - { - var oRes = this._getField(aFieldsToValidate[i]).triggerHandler('validate', data); - if (!oRes.is_valid) - { - this.options.is_valid = false; - } - } - return this.options.is_valid; - }, - showOptions: function() // Debug helper - { - console.log(this.options); - return this.options; - }, - _loadCssFile: function(url) - { - if (!$('link[href="'+url+'"]').length) - $('').appendTo('head'); - }, - _loadJsFile: function(url) - { - if (!$('script[src="'+url+'"]').length) - $.getScript(url); - }, - // Place a field for which no container exists - _addField: function(field_id) - { - $('
').appendTo(this.element); - }, - _prepareField: function(field_id) - { - var field = this.options.fields_list[field_id]; + if(this.getField(oField.id).length === 1) + { + // We replace the node instead of just replacing the inner html so the previous widget is automatically destroyed. + this.getField(oField.id).replaceWith( + $('
') + ); + } + else + { + this._addField(oField.id); + } - if(this._getField(field.id).length === 1) - { - // We replace the node instead of just replacing the inner html so the previous widget is automatically destroyed. - this._getField(field.id).replaceWith( $('
') ); - } - else - { - this._addField(field.id); - } + var oFieldContainer = this.getField(oField.id); + // HTML + if( (oField.html !== undefined) && (oField.html !== '') ) + { + oFieldContainer.html(oField.html); + } + // JS files + if( (oField.js_files !== undefined) && (oField.js_files.length > 0) ) + { + for(var j in oField.js_files) + { + this._loadJsFile(oField.js_files[i]); + } + } + // CSS files + if( (oField.css_files !== undefined) && (oField.css_files.length > 0) ) + { + for(var j in oField.css_files) + { + this._loadCssFile(oField.css_files[i]); + } + } + // JS inline + if( (oField.js_inline !== undefined) && (oField.js_inline !== '') ) + { + this.buildData.script_code += '; '+ oField.js_inline; + } + // CSS inline + if( (oField.css_inline !== undefined) && (oField.css_inline !== '') ) + { + this.buildData.style_code += ' '+ oField.css_inline; + } + + }, + buildForm: function() + { + this.buildData.script_code = ''; + this.buildData.style_code = ''; - var field_container = this._getField(field.id); - // HTML - if( (field.html !== undefined) && (field.html !== '') ) - { - field_container.html(field.html); - } - // JS files - if( (field.js_files !== undefined) && (field.js_files.length > 0) ) - { - for(var j in field.js_files) - { - this._loadJsFile(field.js_files[i]); - } - } - // CSS files - if( (field.css_files !== undefined) && (field.css_files.length > 0) ) - { - for(var j in field.css_files) - { - this._loadCssFile(field.css_files[i]); - } - } - // JS inline - if( (field.js_inline !== undefined) && (field.js_inline !== '') ) - { - this.buildData.script_code += '; '+ field.js_inline; - } - // CSS inline - if( (field.css_inline !== undefined) && (field.css_inline !== '') ) - { - this.buildData.style_code += ' '+ field.css_inline; - } - - }, - buildForm: function() - { - this.buildData.script_code = ''; - this.buildData.style_code = ''; + for(var i in this.options.fields_list) + { + var oField = this.options.fields_list[i]; + if(oField.id === undefined) + { + console.log('Field set : An field must have at least an id property.'); + return false; + } - for(var i in this.options.fields_list) - { - var field = this.options.fields_list[i]; - if(field.id === undefined) - { - console.log('Field set : An field must have at least an id property.'); - return false; - } + this._prepareField(oField.id); + } - this._prepareField(field.id); - } - - this.options.script_element.text('$(document).ready(function(){ '+this.buildData.script_code+' });'); - this.options.style_element.text(this.buildData.style_code); - - eval(this.options.script_element.text()); - } - }); + this.options.script_element.text('$(document).ready(function(){ ' + this.buildData.script_code + ' });'); + this.options.style_element.text(this.buildData.style_code); + + eval(this.options.script_element.text()); + } + }); }); diff --git a/js/form_field.js b/js/form_field.js index 9a616a726..8eb68ab10 100644 --- a/js/form_field.js +++ b/js/form_field.js @@ -2,203 +2,205 @@ ; $(function() { - // the widget definition, where 'itop' is the namespace, - // 'form_field' the widget name - $.widget( 'itop.form_field', - { - // default options - options: - { - validators: null, - validate_callback: 'validate', // When using an anonymous function, use the 'me' parameter to acces the current widget : function(me){ return me.validate(); }, - on_validation_callback: function(data){ }, - get_current_value_callback: 'getCurrentValue', - - }, + // the widget definition, where 'itop' is the namespace, + // 'form_field' the widget name + $.widget( 'itop.form_field', + { + // default options + options: + { + validators: null, + validate_callback: 'validate', // When using an anonymous function, use the 'me' parameter to acces the current widget : function(me){ return me.validate(); }, + on_validation_callback: function(data){ }, + get_current_value_callback: 'getCurrentValue', + + }, - // the constructor - _create: function() - { - var me = this; - - this.element - .addClass('form_field'); - - this.element - .bind('set_validators', function(event, data){ - event.stopPropagation(); - me.options.validators = data; - }); - this.element - .bind('validate get_current_value', function(event, data){ - event.stopPropagation(); - var callback = me.options[event.type+'_callback']; - - if(typeof callback === 'string') - { - return me[callback](event, data); - } - else if(typeof callback === 'function') - { - return callback(me, event, data); - } - else - { - console.log('Form field : callback type must be a function or a existing function name of the widget'); - return false; - } - }); - }, - // called when created, and later when changing options - _refresh: function() - { + // the constructor + _create: function() + { + var me = this; + + this.element + .addClass('form_field'); + + this.element + .bind('set_validators', function(oEvent, oData){ + oEvent.stopPropagation(); + me.options.validators = oData; + }); + this.element + .bind('validate get_current_value', function(oEvent, oData){ + oEvent.stopPropagation(); + + var callback = me.options[oEvent.type+'_callback']; + + if(typeof callback === 'string') + { + return me[callback](oEvent, oData); + } + else if(typeof callback === 'function') + { + return callback(me, oEvent, oData); + } + else + { + console.log('Form field : callback type must be a function or a existing function name of the widget'); + return false; + } + }); + }, + // called when created, and later when changing options + _refresh: function() + { - }, - // events bound via _bind are removed automatically - // revert other modifications here - _destroy: function() - { - this.element - .removeClass('form_field'); - }, - // _setOptions is called with a hash of all options that are changing - // always refresh when changing options - _setOptions: function() - { - this._superApply(arguments); - }, - // _setOption is called for each individual option that is changing - _setOption: function( key, value ) - { - this._super( key, value ); - }, - getCurrentValue: function() - { - var value = null; - - this.element.find(':input').each(function(index, elem){ - if($(elem).is(':hidden') || $(elem).is(':text') || $(elem).is('textarea')) - { - value = $(elem).val(); - } - else if($(elem).is('select')) - { - value = []; - $(elem).find('option:selected').each(function(){ - value.push($(this).val()); - }); - } - else if($(elem).is(':checkbox') || $(elem).is(':radio')) - { - if(value === null) - { - value = []; - } - if($(elem).is(':checked')) - { - value.push($(elem).val()); - } - } - else - { - console.log('Form field : Input type not handle yet.'); - } - }); - - return value; - }, - validate: function(event, data) - { - var oResult = { is_valid: true, error_messages: [] }; + }, + // events bound via _bind are removed automatically + // revert other modifications here + _destroy: function() + { + this.element + .removeClass('form_field'); + }, + // _setOptions is called with a hash of all options that are changing + // always refresh when changing options + _setOptions: function() + { + this._superApply(arguments); + }, + // _setOption is called for each individual option that is changing + _setOption: function( key, value ) + { + this._super( key, value ); + }, + getCurrentValue: function() + { + var value = null; + + this.element.find(':input').each(function(iIndex, oElem){ + if($(oElem).is(':hidden') || $(oElem).is(':text') || $(oElem).is('textarea')) + { + value = $(oElem).val(); + } + else if($(oElem).is('select')) + { + value = []; + $(oElem).find('option:selected').each(function(){ + value.push($(this).val()); + }); + } + else if($(oElem).is(':checkbox') || $(oElem).is(':radio')) + { + if(value === null) + { + value = []; + } + if($(oElem).is(':checked')) + { + value.push($(oElem).val()); + } + } + else + { + console.log('Form field : Input type not handle yet.'); + } + }); + + return value; + }, + validate: function(oEvent, oData) + { + var oResult = { is_valid: true, error_messages: [] }; - // Doing data validation - if(this.options.validators !== null) - { - var bMandatory = (this.options.validators.mandatory !== undefined); - // Extracting value for the field - var oValue = this.getCurrentValue(); - var aValueKeys = Object.keys(oValue); - - // This is just a safety check in case a field doesn't always return an object when no value assigned, so we have to check the mandatory validator here... - // ... But this should never happen. - if( (aValueKeys.length === 0) && bMandatory ) - { - oResult.is_valid = false; - oResult.error_messages.push(this.options.validators.mandatory.message); - } - // ... Otherwise, we check every validators - else if(aValueKeys.length > 0) - { - var value = oValue[aValueKeys[0]]; - for(var sValidatorType in this.options.validators) - { - var oValidator = this.options.validators[sValidatorType]; - if(sValidatorType === 'mandatory') - { - // Works for string, array, object - if($.isEmptyObject(value)) - { - oResult.is_valid = false; - oResult.error_messages.push(oValidator.message); - } - // ... In case of non empty array, we have to check if the value is not null - else if($.isArray(value)) - { - for(var i in value) - { - if(typeof value[i] === 'string') - { - if($.isEmptyObject(value[i])) - { - oResult.is_valid = false; - oResult.error_messages.push(oValidator.message); - } - } - else - { - console.log('Form field: mandatory validation not supported yet for the type "' + (typeof value[i]) +'"'); - } - } - } - } - else - { - var oRegExp = new RegExp(oValidator.reg_exp, "g"); - if(typeof value === 'string') - { - if(!oRegExp.test(value)) - { - oResult.is_valid = false; - oResult.error_messages.push(oValidator.message); - } - } - else if($.isArray(value)) - { - for(var i in value) - { - if(value[i] === 'string' && !oRegExp.test(value)) - { - oResult.is_valid = false; - oResult.error_messages.push(oValidator.message); - } - } - } - else - { - console.log('Form field: validation not supported yet for the type "' + (typeof value) +'"'); - } - } - } - } - } - - this.options.on_validation_callback(this, oResult); - - return oResult; - }, - showOptions: function() - { - return this.options; - } - }); + // Doing data validation + if(this.options.validators !== null) + { + var bMandatory = (this.options.validators.mandatory !== undefined); + // Extracting value for the field + var oValue = this.getCurrentValue(); + var aValueKeys = Object.keys(oValue); + + // This is just a safety check in case a field doesn't always return an object when no value assigned, so we have to check the mandatory validator here... + // ... But this should never happen. + if( (aValueKeys.length === 0) && bMandatory ) + { + oResult.is_valid = false; + oResult.error_messages.push(this.options.validators.mandatory.message); + } + // ... Otherwise, we check every validators + else if(aValueKeys.length > 0) + { + var value = oValue[aValueKeys[0]]; + for(var sValidatorType in this.options.validators) + { + var oValidator = this.options.validators[sValidatorType]; + if(sValidatorType === 'mandatory') + { + // Works for string, array, object + if($.isEmptyObject(value)) + { + oResult.is_valid = false; + oResult.error_messages.push(oValidator.message); + } + // ... In case of non empty array, we have to check if the value is not null + else if($.isArray(value)) + { + for(var i in value) + { + if(typeof value[i] === 'string') + { + if($.isEmptyObject(value[i])) + { + oResult.is_valid = false; + oResult.error_messages.push(oValidator.message); + } + } + else + { + console.log('Form field: mandatory validation not supported yet for the type "' + (typeof value[i]) +'"'); + } + } + } + } + else + { + var oRegExp = new RegExp(oValidator.reg_exp, "g"); + if(typeof value === 'string') + { + if(!oRegExp.test(value)) + { + oResult.is_valid = false; + oResult.error_messages.push(oValidator.message); + } + } + else if($.isArray(value)) + { + for(var i in value) + { + if(value[i] === 'string' && !oRegExp.test(value)) + { + oResult.is_valid = false; + oResult.error_messages.push(oValidator.message); + } + } + } + else + { + console.log('Form field: validation not supported yet for the type "' + (typeof value) +'"'); + } + } + } + } + } + + this.options.on_validation_callback(this, oResult); + + return oResult; + }, + // Debug helper + showOptions: function() + { + return this.options; + } + }); }); diff --git a/js/form_handler.js b/js/form_handler.js index d2947139f..868e98694 100644 --- a/js/form_handler.js +++ b/js/form_handler.js @@ -2,150 +2,151 @@ ; $(function() { - // the widget definition, where 'itop' is the namespace, - // 'form_handler' the widget name - $.widget( 'itop.form_handler', - { - // default options - options: - { - formmanager_class: null, - formmanager_data: null, - submit_btn_selector: null, - cancel_btn_selector: null, - endpoint: null, - is_modal: false, - field_set: null - }, + // the widget definition, where 'itop' is the namespace, + // 'form_handler' the widget name + $.widget( 'itop.form_handler', + { + // default options + options: + { + formmanager_class: null, + formmanager_data: null, + submit_btn_selector: null, + cancel_btn_selector: null, + endpoint: null, + is_modal: false, + field_set: null + }, - // the constructor - _create: function() - { - var me = this; - - this.element - .addClass('form_handler'); + // the constructor + _create: function() + { + var me = this; + + this.element + .addClass('form_handler'); - this.element.bind('update_fields', function(event, data){ - this._onUpdateFields(event, data); - }); + // Binding events + this.element.bind('update_fields', function(oEvent, oData){ + me._onUpdateFields(oEvent, oData); + }); - // Binding buttons - if(this.options.submit_btn_selector !== null) - { - this.options.submit_btn_selector.off('click').on('click', function(event){ me._onSubmitClick(event); }); - } - if(this.options.cancel_btn_selector !== null) - { - this.options.cancel_btn_selector.off('click').on('click', function(event){ me._onCancelClick(event); }); - } - }, + // Binding buttons + if(this.options.submit_btn_selector !== null) + { + this.options.submit_btn_selector.off('click').on('click', function(oEvent){ me._onSubmitClick(oEvent); }); + } + if(this.options.cancel_btn_selector !== null) + { + this.options.cancel_btn_selector.off('click').on('click', function(oEvent){ me._onCancelClick(oEvent); }); + } + }, - // called when created, and later when changing options - _refresh: function() - { - - }, - // events bound via _bind are removed automatically - // revert other modifications here - _destroy: function() - { - this.element - .removeClass('form_handler'); - }, - // _setOptions is called with a hash of all options that are changing - // always refresh when changing options - _setOptions: function() - { - this._superApply(arguments); - }, - // _setOption is called for each individual option that is changing - _setOption: function( key, value ) - { - this._super( key, value ); - }, - getCurrentValues: function() - { - return this.options.field_set.triggerHandler('get_current_values'); - }, - _onUpdateFields: function(event, data) - { - var me = this; - var sFormPath = data.form_path; + // called when created, and later when changing options + _refresh: function() + { + + }, + // events bound via _bind are removed automatically + // revert other modifications here + _destroy: function() + { + this.element + .removeClass('form_handler'); + }, + // _setOptions is called with a hash of all options that are changing + // always refresh when changing options + _setOptions: function() + { + this._superApply(arguments); + }, + // _setOption is called for each individual option that is changing + _setOption: function( key, value ) + { + this._super( key, value ); + }, + getCurrentValues: function() + { + return this.options.field_set.triggerHandler('get_current_values'); + }, + _onUpdateFields: function(oEvent, oData) + { + var me = this; + var sFormPath = oData.form_path; - // Data checks - if(this.options.endpoint === null) - { - console.log('Form handler : An endpoint must be defined.'); - return false; - } - if(this.options.formmanager_class === null) - { - console.log('Form handler : Form manager class must be defined.'); - return false; - } - if(this.options.formmanager_data === null) - { - console.log('Form handler : Form manager data must be defined.'); - return false; - } - - this._disableFormBeforeLoading(); - $.post( - this.options.endpoint, - { - operation: 'update', - formmanager_class: this.options.formmanager_class, - formmanager_data: JSON.stringify(this.options.formmanager_data), - current_values: this.getCurrentValues(), - requested_fields: data.requested_fields, - form_path: sFormPath - }, - function(data){ - me._onUpdateSuccess(data, sFormPath); - } - ) - .fail(function(data){ me._onUpdateFailure(data, sFormPath); }) - .always(function(data){ me._onUpdateAlways(data, sFormPath); }); - }, - // Intended for overloading in derived classes - _onSubmitClick: function(event) - { - }, - // Intended for overloading in derived classes - _onCancelClick: function(event) - { - }, - // Intended for overloading in derived classes - _onUpdateSuccess: function(data, sFormPath) - { - if(data.form.updated_fields !== undefined) - { - this.element.find('[data-form-path="'+sFormPath+'"]').trigger('update_form', {updated_fields: data.form.updated_fields}); - } - }, - // Intended for overloading in derived classes - _onUpdateFailure: function(data, sFormPath) - { - }, - // Intended for overloading in derived classes - _onUpdateAlways: function(data, sFormPath) - { - // Check all touched AFTER ajax is complete, otherwise the renderer will redraw the field in the mean time. - this.element.find('[data-form-path="'+sFormPath+'"]').trigger('validate'); - this._enableFormAfterLoading(); - }, - // Intended for overloading in derived classes - _disableFormBeforeLoading: function() - { - }, - // Intended for overloading in derived classes - _enableFormAfterLoading: function() - { - }, - showOptions: function() // Debug helper - { - console.log(this.options); - } - }); + // Data checks + if(this.options.endpoint === null) + { + console.log('Form handler : An endpoint must be defined.'); + return false; + } + if(this.options.formmanager_class === null) + { + console.log('Form handler : Form manager class must be defined.'); + return false; + } + if(this.options.formmanager_data === null) + { + console.log('Form handler : Form manager data must be defined.'); + return false; + } + + this._disableFormBeforeLoading(); + $.post( + this.options.endpoint, + { + operation: 'update', + formmanager_class: this.options.formmanager_class, + formmanager_data: JSON.stringify(this.options.formmanager_data), + current_values: this.getCurrentValues(), + requested_fields: oData.requested_fields, + form_path: sFormPath + }, + function(oData){ + me._onUpdateSuccess(oData, sFormPath); + } + ) + .fail(function(oData){ me._onUpdateFailure(oData, sFormPath); }) + .always(function(oData){ me._onUpdateAlways(oData, sFormPath); }); + }, + // Intended for overloading in derived classes + _onSubmitClick: function(oEvent) + { + }, + // Intended for overloading in derived classes + _onCancelClick: function(oEvent) + { + }, + // Intended for overloading in derived classes + _onUpdateSuccess: function(oData, sFormPath) + { + if(oData.form.updated_fields !== undefined) + { + this.element.find('[data-form-path="' + sFormPath + '"]').trigger('update_form', {updated_fields: oData.form.updated_fields}); + } + }, + // Intended for overloading in derived classes + _onUpdateFailure: function(oData, sFormPath) + { + }, + // Intended for overloading in derived classes + _onUpdateAlways: function(oData, sFormPath) + { + // Check all touched AFTER ajax is complete, otherwise the renderer will redraw the field in the mean time. + this.element.find('[data-form-path="' + sFormPath + '"]').trigger('validate'); + this._enableFormAfterLoading(); + }, + // Intended for overloading in derived classes + _disableFormBeforeLoading: function() + { + }, + // Intended for overloading in derived classes + _enableFormAfterLoading: function() + { + }, + showOptions: function() // Debug helper + { + console.log(this.options); + } + }); }); diff --git a/js/subform_field.js b/js/subform_field.js index 1d185b7ac..b50e7d720 100644 --- a/js/subform_field.js +++ b/js/subform_field.js @@ -1,46 +1,46 @@ -//iTop Form field +//iTop Subform field ; $(function() { - // the widget definition, where 'itop' is the namespace, - // 'subform_field' the widget name - $.widget( 'itop.subform_field', $.itop.form_field, - { - // default options - options: - { - field_set: null - }, + // the widget definition, where 'itop' is the namespace, + // 'subform_field' the widget name + $.widget( 'itop.subform_field', $.itop.form_field, + { + // default options + options: + { + field_set: null + }, - // the constructor - _create: function() - { - var me = this; - - this.element - .addClass('subform_field'); + // the constructor + _create: function() + { + var me = this; + + this.element + .addClass('subform_field'); - this._super(); - }, - // events bound via _bind are removed automatically - // revert other modifications here - _destroy: function() - { - this.element - .removeClass('subform_field'); + this._super(); + }, + // events bound via _bind are removed automatically + // revert other modifications here + _destroy: function() + { + this.element + .removeClass('subform_field'); - this._super(); - }, - getCurrentValue: function() - { - return this.options.field_set.triggerHandler('get_current_values'); - }, - validate: function(event, data) - { - return { - is_valid: this.options.field_set.triggerHandler('validate', data), - error_messages: [] - } - }, - }); + this._super(); + }, + getCurrentValue: function() + { + return this.options.field_set.triggerHandler('get_current_values'); + }, + validate: function(oEvent, oData) + { + return { + is_valid: this.options.field_set.triggerHandler('validate', oData), + error_messages: [] + } + }, + }); }); diff --git a/sources/form/field/checkboxfield.class.inc.php b/sources/form/field/checkboxfield.class.inc.php index 2747ccdbb..026ee4590 100644 --- a/sources/form/field/checkboxfield.class.inc.php +++ b/sources/form/field/checkboxfield.class.inc.php @@ -28,6 +28,6 @@ use \Combodo\iTop\Form\Field\MultipleChoicesField; */ class CheckboxField extends MultipleChoicesField { - const DEFAULT_MULTIPLE_VALUES_ENABLED = true; + const DEFAULT_MULTIPLE_VALUES_ENABLED = true; } diff --git a/sources/form/field/field.class.inc.php b/sources/form/field/field.class.inc.php index 67390c5aa..91f46427e 100644 --- a/sources/form/field/field.class.inc.php +++ b/sources/form/field/field.class.inc.php @@ -30,254 +30,330 @@ use \Combodo\iTop\Form\Validator\MandatoryValidator; */ abstract class Field { - const DEFAULT_LABEL = ''; - const DEFAULT_READ_ONLY = false; - const DEFAULT_MANDATORY = false; - const DEFAULT_VALID = true; + const DEFAULT_LABEL = ''; + const DEFAULT_READ_ONLY = false; + const DEFAULT_MANDATORY = false; + const DEFAULT_VALID = true; - protected $sId; - protected $sGlobalId; - protected $sFormPath; - protected $sLabel; - protected $bReadOnly; - protected $bMandatory; - protected $aValidators; - protected $bValid; - protected $aErrorMessages; - protected $currentValue; - protected $onFinalizeCallback; - - /** - * - * @param Closure $callback (Used in the $oForm->AddField($sId, ..., function() use ($oManager, $oForm, '...') { ... } ); ) - */ - public function __construct($sId, Closure $onFinalizeCallback = null) - { - $this->sId = $sId; - $this->sGlobalId = 'field_'.$sId.uniqid(); - $this->sLabel = static::DEFAULT_LABEL; - $this->bReadOnly = static::DEFAULT_READ_ONLY; - $this->bMandatory = static::DEFAULT_MANDATORY; - $this->aValidators = array(); - $this->bValid = static::DEFAULT_VALID; - $this->aErrorMessages = array(); - $this->onFinalizeCallback = $onFinalizeCallback; - } + protected $sId; + protected $sGlobalId; + protected $sFormPath; + protected $sLabel; + protected $bReadOnly; + protected $bMandatory; + protected $aValidators; + protected $bValid; + protected $aErrorMessages; + protected $currentValue; + protected $onFinalizeCallback; /** - * Get the field id within its container form - * @return string - */ - public function GetId() - { - return $this->sId; - } + * Default constructor + * + * @param string $sId + * @param Closure $onFinalizeCallback (Used in the $oForm->AddField($sId, ..., function() use ($oManager, $oForm, '...') { ... } ); ) + */ + public function __construct($sId, Closure $onFinalizeCallback = null) + { + $this->sId = $sId; + $this->sGlobalId = 'field_' . $sId . '_' . uniqid(); + $this->sLabel = static::DEFAULT_LABEL; + $this->bReadOnly = static::DEFAULT_READ_ONLY; + $this->bMandatory = static::DEFAULT_MANDATORY; + $this->aValidators = array(); + $this->bValid = static::DEFAULT_VALID; + $this->aErrorMessages = array(); + $this->onFinalizeCallback = $onFinalizeCallback; + } - /** - * Get a unique field id within the top level form - * @return string - */ - public function GetGlobalId() - { - return $this->sGlobalId; - } + /** + * Returns the field id within its container form + * + * @return string + */ + public function GetId() + { + return $this->sId; + } - /** - * Get the id of the container form - * @return string - */ - public function GetFormPath() - { - return $this->sFormPath; - } + /** + * Returns a unique field id within the top level form + * + * @return string + */ + public function GetGlobalId() + { + return $this->sGlobalId; + } - public function GetLabel() - { - return $this->sLabel; - } + /** + * Returns the id of the container form + * + * @return string + */ + public function GetFormPath() + { + return $this->sFormPath; + } - public function GetReadOnly() - { - return $this->bReadOnly; - } + /** + * + * @return string + */ + public function GetLabel() + { + return $this->sLabel; + } - public function GetMandatory() - { - return $this->bMandatory; - } + /** + * + * @return boolean + */ + public function GetReadOnly() + { + return $this->bReadOnly; + } - public function GetValidators() - { - return $this->aValidators; - } + /** + * + * @return boolean + */ + public function GetMandatory() + { + return $this->bMandatory; + } - /** - * Returns the current validation state of the field (true|false). - * It DOESN'T make the validation, see Validate() instead. - * - * @return boolean - */ - public function GetValid() - { - return $this->bValid; - } + /** + * + * @return array + */ + public function GetValidators() + { + return $this->aValidators; + } - public function GetErrorMessages() - { - return $this->aErrorMessages; - } + /** + * Returns the current validation state of the field (true|false). + * It DOESN'T make the validation, see Validate() instead. + * + * @return boolean + */ + public function GetValid() + { + return $this->bValid; + } - public function GetCurrentValue() - { - return $this->currentValue; - } + /** + * + * @return array + */ + public function GetErrorMessages() + { + return $this->aErrorMessages; + } - public function SetLabel($sLabel) - { - $this->sLabel = $sLabel; - return $this; - } + /** + * + * @return array + */ + public function GetCurrentValue() + { + return $this->currentValue; + } - public function SetReadOnly($bReadOnly) - { - $this->bReadOnly = $bReadOnly; - return $this; - } + /** + * Sets the field formpath + * Usually Called by the form when adding the field + * + * @param string $sFormPath + * @return \Combodo\iTop\Form\Field\Field + */ + public function SetFormPath($sFormPath) + { + $this->sFormPath = $sFormPath; + return $this; + } - public function SetMandatory($bMandatory) - { - // Before changing the property, we check if it was already mandatory. If not, we had the mandatory validator - if ($bMandatory && !$this->bMandatory) - { - $this->AddValidator(new MandatoryValidator()); - } + /** + * + * @param type $sLabel + * @return \Combodo\iTop\Form\Field\Field + */ + public function SetLabel($sLabel) + { + $this->sLabel = $sLabel; + return $this; + } - if (!$bMandatory) - { - foreach ($this->aValidators as $iKey => $oValue) - { - if ($oValue::Getname() === MandatoryValidator::GetName()) - { - unset($this->aValidators[$iKey]); - } - } - } + /** + * + * @param boolean $bReadOnly + * @return \Combodo\iTop\Form\Field\Field + */ + public function SetReadOnly($bReadOnly) + { + $this->bReadOnly = $bReadOnly; + return $this; + } - $this->bMandatory = $bMandatory; - return $this; - } + /** + * Sets if the field is mandatory or not. + * Setting the value will automatically add/remove a MandatoryValidator to the Field + * + * @param boolean $bMandatory + * @return \Combodo\iTop\Form\Field\Field + */ + public function SetMandatory($bMandatory) + { + // Before changing the property, we check if it was already mandatory. If not, we had the mandatory validator + if ($bMandatory && !$this->bMandatory) + { + $this->AddValidator(new MandatoryValidator()); + } - public function SetValidators($aValidators) - { - $this->aValidators = $aValidators; - return $this; - } + if (!$bMandatory) + { + foreach ($this->aValidators as $iKey => $oValue) + { + if ($oValue::Getname() === MandatoryValidator::GetName()) + { + unset($this->aValidators[$iKey]); + } + } + } - /** - * Note : Function is protected as bValid should not be set from outside - * - * @param boolean $bValid - * @return \Combodo\iTop\Form\Field\Field - */ - protected function SetValid($bValid) - { - $this->bValid = $bValid; - return $this; - } + $this->bMandatory = $bMandatory; + return $this; + } - /** - * Note : Function is protected as aErrorMessages should not be set from outside - * - * @param array $aErrorMessages - * @return \Combodo\iTop\Form\Field\Field - */ - protected function SetErrorMessages($aErrorMessages) - { - $this->aErrorMessages = $aErrorMessages; - return $this; - } + /** + * + * @param array $aValidators + * @return \Combodo\iTop\Form\Field\Field + */ + public function SetValidators($aValidators) + { + $this->aValidators = $aValidators; + return $this; + } - public function SetCurrentValue($currentValue) - { - $this->currentValue = $currentValue; - return $this; - } + /** + * Note : Function is protected as bValid should not be set from outside + * + * @param boolean $bValid + * @return \Combodo\iTop\Form\Field\Field + */ + protected function SetValid($bValid) + { + $this->bValid = $bValid; + return $this; + } - public function SetOnFinalizeCallback(Closure $onFinalizeCallback) - { - $this->onFinalizeCallback = $onFinalizeCallback; - return $this; - } + /** + * Note : Function is protected as aErrorMessages should not be set from outside + * + * @param array $aErrorMessages + * @return \Combodo\iTop\Form\Field\Field + */ + protected function SetErrorMessages($aErrorMessages) + { + $this->aErrorMessages = $aErrorMessages; + return $this; + } - /** - * Called by the form when adding the field - */ - public function SetFormPath($sFormPath) - { - $this->sFormPath = $sFormPath; - } + /** + * + * @param mixed $currentValue + * @return \Combodo\iTop\Form\Field\Field + */ + public function SetCurrentValue($currentValue) + { + $this->currentValue = $currentValue; + return $this; + } - public function AddValidator(Validator $oValidator) - { - $this->aValidators[] = $oValidator; - return $this; - } + /** + * + * @param Closure $onFinalizeCallback + * @return \Combodo\iTop\Form\Field\Field + */ + public function SetOnFinalizeCallback(Closure $onFinalizeCallback) + { + $this->onFinalizeCallback = $onFinalizeCallback; + return $this; + } - public function RemoveValidator(Validator $oValidator) - { - foreach ($this->aValidators as $iKey => $oValue) - { - if ($oValue === $oValidator) - { - unset($this->aValidators[$iKey]); - } - } - return $this; - } + /** + * + * @param Validator $oValidator + * @return \Combodo\iTop\Form\Field\Field + */ + public function AddValidator(Validator $oValidator) + { + $this->aValidators[] = $oValidator; + return $this; + } - /** - * Note : Function is protected as aErrorMessages should not be add from outside - * - * @param string $sErrorMessage - * @return \Combodo\iTop\Form\Field\Field - */ - protected function AddErrorMessage($sErrorMessage) - { - $this->aErrorMessages[] = $sErrorMessage; - return $this; - } + /** + * + * @param Validator $oValidator + * @return \Combodo\iTop\Form\Field\Field + */ + public function RemoveValidator(Validator $oValidator) + { + foreach ($this->aValidators as $iKey => $oValue) + { + if ($oValue === $oValidator) + { + unset($this->aValidators[$iKey]); + } + } + return $this; + } - /** - * Note : Function is protected as aErrorMessages should not be set from outside - * - * @return \Combodo\iTop\Form\Field\Field - */ - protected function EmptyErrorMessages() - { - $this->aErrorMessages = array(); - return $this; - } + /** + * Note : Function is protected as aErrorMessages should not be add from outside + * + * @param string $sErrorMessage + * @return \Combodo\iTop\Form\Field\Field + */ + protected function AddErrorMessage($sErrorMessage) + { + $this->aErrorMessages[] = $sErrorMessage; + return $this; + } - public function OnCancel() - { - // Overload when needed - } + /** + * Note : Function is protected as aErrorMessages should not be set from outside + * + * @return \Combodo\iTop\Form\Field\Field + */ + protected function EmptyErrorMessages() + { + $this->aErrorMessages = array(); + return $this; + } - public function OnFinalize() - { - if ($this->onFinalizeCallback !== null) - { - // Note : We MUST have a temp variable to call the Closure. otherwise it won't work when the Closure is a class member - $callback = $this->onFinalizeCallback; - $callback($this); - } - } + public function OnCancel() + { + // Overload when needed + } - /** - * Checks the validators to see if the field's current value is valid. - * Then sets $bValid and $aErrorMessages. - * - * @return boolean - */ - abstract public function Validate(); + public function OnFinalize() + { + if ($this->onFinalizeCallback !== null) + { + // Note : We MUST have a temp variable to call the Closure. otherwise it won't work when the Closure is a class member + $callback = $this->onFinalizeCallback; + $callback($this); + } + } + + /** + * Checks the validators to see if the field's current value is valid. + * Then sets $bValid and $aErrorMessages. + * + * @return boolean + */ + abstract public function Validate(); } diff --git a/sources/form/field/multiplechoicesfield.class.inc.php b/sources/form/field/multiplechoicesfield.class.inc.php index ec14ff2ba..ecad13ece 100644 --- a/sources/form/field/multiplechoicesfield.class.inc.php +++ b/sources/form/field/multiplechoicesfield.class.inc.php @@ -32,146 +32,146 @@ use \Combodo\iTop\Form\Field\Field; */ abstract class MultipleChoicesField extends Field { - const DEFAULT_MULTIPLE_VALUES_ENABLED = false; + const DEFAULT_MULTIPLE_VALUES_ENABLED = false; - protected $bMultipleValuesEnabled; - protected $aChoices; + protected $bMultipleValuesEnabled; + protected $aChoices; - public function __construct($sId, Closure $onFinalizeCallback = null) - { - parent::__construct($sId, $onFinalizeCallback); - $this->bMultipleValuesEnabled = static::DEFAULT_MULTIPLE_VALUES_ENABLED; - $this->aChoices = array(); - $this->currentValue = array(); - } + public function __construct($sId, Closure $onFinalizeCallback = null) + { + parent::__construct($sId, $onFinalizeCallback); + $this->bMultipleValuesEnabled = static::DEFAULT_MULTIPLE_VALUES_ENABLED; + $this->aChoices = array(); + $this->currentValue = array(); + } - public function GetCurrentValue() - { - $value = null; - if (!empty($this->currentValue)) - { - if ($this->bMultipleValuesEnabled) - { - $value = $this->currentValue; - } - else - { - reset($this->currentValue); - $value = current($this->currentValue); - } - } + public function GetCurrentValue() + { + $value = null; + if (!empty($this->currentValue)) + { + if ($this->bMultipleValuesEnabled) + { + $value = $this->currentValue; + } + else + { + reset($this->currentValue); + $value = current($this->currentValue); + } + } - return $value; - } + return $value; + } - /** - * Sets the current value for the MultipleChoicesField. - * - * @param mixed $currentValue Can be either an array of values (in case of multiple values) or just a simple value - * @return \Combodo\iTop\Form\Field\MultipleChoicesField - */ - public function SetCurrentValue($currentValue) - { - if (is_array($currentValue)) - { - $this->currentValue = $currentValue; - } - elseif (is_null($currentValue)) - { - $this->currentValue = array(); - } - else - { - $this->currentValue = array($currentValue); - } - return $this; - } + /** + * Sets the current value for the MultipleChoicesField. + * + * @param mixed $currentValue Can be either an array of values (in case of multiple values) or just a simple value + * @return \Combodo\iTop\Form\Field\MultipleChoicesField + */ + public function SetCurrentValue($currentValue) + { + if (is_array($currentValue)) + { + $this->currentValue = $currentValue; + } + elseif (is_null($currentValue)) + { + $this->currentValue = array(); + } + else + { + $this->currentValue = array($currentValue); + } + return $this; + } - public function GetMultipleValuesEnabled() - { - return $this->bMultipleValuesEnabled; - } + public function GetMultipleValuesEnabled() + { + return $this->bMultipleValuesEnabled; + } - public function SetMultipleValuesEnabled($bMultipleValuesEnabled) - { - $this->bMultipleValuesEnabled = $bMultipleValuesEnabled; - return $this; - } + public function SetMultipleValuesEnabled($bMultipleValuesEnabled) + { + $this->bMultipleValuesEnabled = $bMultipleValuesEnabled; + return $this; + } - public function SetValues($aValues) - { - $this->currentValue = $aValues; - return $this; - } + public function SetValues($aValues) + { + $this->currentValue = $aValues; + return $this; + } - public function AddValue($value) - { - $this->currentValue = $value; - return $this; - } + public function AddValue($value) + { + $this->currentValue = $value; + return $this; + } - public function RemoveValue($value) - { - if (array_key_exists($value, $this->currentValue)) - { - unset($this->currentValue[$sId]); - } - return $this; - } + public function RemoveValue($value) + { + if (array_key_exists($value, $this->currentValue)) + { + unset($this->currentValue[$sId]); + } + return $this; + } - public function IsAmongValues($value) - { - return in_array($value, $this->currentValue); - } + public function IsAmongValues($value) + { + return in_array($value, $this->currentValue); + } - public function GetChoices() - { - return $this->aChoices; - } + public function GetChoices() + { + return $this->aChoices; + } - public function SetChoices($aChoices) - { - $this->aChoices = $aChoices; - return $this; - } + public function SetChoices($aChoices) + { + $this->aChoices = $aChoices; + return $this; + } - public function AddChoice($sId, $choice = null) - { - if ($choice === null) - { - $choice = $sId; - } - $this->aChoices[$sId] = $choice; - return $this; - } + public function AddChoice($sId, $choice = null) + { + if ($choice === null) + { + $choice = $sId; + } + $this->aChoices[$sId] = $choice; + return $this; + } - public function RemoveChoice($sId) - { - if (in_array($sId, $this->aChoices)) - { - unset($this->aChoices[$sId]); - } - return $this; - } + public function RemoveChoice($sId) + { + if (in_array($sId, $this->aChoices)) + { + unset($this->aChoices[$sId]); + } + return $this; + } - public function Validate() - { - $this->SetValid(true); - $this->EmptyErrorMessages(); + public function Validate() + { + $this->SetValid(true); + $this->EmptyErrorMessages(); - foreach ($this->GetValidators() as $oValidator) - { - foreach ($this->currentValue as $value) - { - if (!preg_match($oValidator->GetRegExp(true), $value)) - { - $this->SetValid(false); - $this->AddErrorMessage($oValidator->GetErrorMessage()); - } - } - } + foreach ($this->GetValidators() as $oValidator) + { + foreach ($this->currentValue as $value) + { + if (!preg_match($oValidator->GetRegExp(true), $value)) + { + $this->SetValid(false); + $this->AddErrorMessage($oValidator->GetErrorMessage()); + } + } + } - return $this->GetValid(); - } + return $this->GetValid(); + } } diff --git a/sources/form/field/radiofield.class.inc.php b/sources/form/field/radiofield.class.inc.php index df7ca6068..f356a4127 100644 --- a/sources/form/field/radiofield.class.inc.php +++ b/sources/form/field/radiofield.class.inc.php @@ -28,6 +28,6 @@ use \Combodo\iTop\Form\Field\MultipleChoicesField; */ class RadioField extends MultipleChoicesField { - const DEFAULT_MULTIPLE_VALUES_ENABLED = false; + const DEFAULT_MULTIPLE_VALUES_ENABLED = false; } diff --git a/sources/form/field/selectfield.class.inc.php b/sources/form/field/selectfield.class.inc.php index d2c24160b..c7b9a0a4f 100644 --- a/sources/form/field/selectfield.class.inc.php +++ b/sources/form/field/selectfield.class.inc.php @@ -29,56 +29,56 @@ use \Combodo\iTop\Form\Field\MultipleChoicesField; */ class SelectField extends MultipleChoicesField { - const DEFAULT_NULL_CHOICE_LABEL = 'TOTR: - Choisir une valeur -'; - const DEFAULT_STARTS_WITH_NULL_CHOICE = true; + const DEFAULT_NULL_CHOICE_LABEL = 'TOTR: - Choisir une valeur -'; + const DEFAULT_STARTS_WITH_NULL_CHOICE = true; - protected $bStartsWithNullChoice; + protected $bStartsWithNullChoice; - public function __construct($sId, Closure $onFinalizeCallback = null) - { - parent::__construct($sId, $onFinalizeCallback); - $this->bStartsWithNullChoice = static::DEFAULT_STARTS_WITH_NULL_CHOICE; - } + public function __construct($sId, Closure $onFinalizeCallback = null) + { + parent::__construct($sId, $onFinalizeCallback); + $this->bStartsWithNullChoice = static::DEFAULT_STARTS_WITH_NULL_CHOICE; + } - /** - * Returns if the select starts with a dummy choice before its choices. - * This can be useful when you want to force the user to explicitly select a choice. - * - * @return boolean - */ - public function GetStartsWithNullChoice() - { - return $this->bStartsWithNullChoice; - } + /** + * Returns if the select starts with a dummy choice before its choices. + * This can be useful when you want to force the user to explicitly select a choice. + * + * @return boolean + */ + public function GetStartsWithNullChoice() + { + return $this->bStartsWithNullChoice; + } - public function SetStartsWithNullChoice($bStartsWithNullChoice) - { - $this->bStartsWithNullChoice = $bStartsWithNullChoice; + public function SetStartsWithNullChoice($bStartsWithNullChoice) + { + $this->bStartsWithNullChoice = $bStartsWithNullChoice; - if (!array_key_exists(null, $this->aChoices)) - { - $this->aChoices = array(null => static::DEFAULT_NULL_CHOICE_LABEL) + $this->aChoices; - } + if (!array_key_exists(null, $this->aChoices)) + { + $this->aChoices = array(null => static::DEFAULT_NULL_CHOICE_LABEL) + $this->aChoices; + } - return $this; - } + return $this; + } - /** - * Sets the choices for the fields - * Overloads the methods for the super class in order to put a dummy choice first if necessary. - * - * @param array $aChoices - * @return \Combodo\iTop\Form\Field\SelectField - */ - public function SetChoices($aChoices) - { - if ($this->bStartsWithNullChoice && !array_key_exists(null, $aChoices)) - { - $aChoices = array(null => static::DEFAULT_NULL_CHOICE_LABEL) + $aChoices; - } + /** + * Sets the choices for the fields + * Overloads the methods for the super class in order to put a dummy choice first if necessary. + * + * @param array $aChoices + * @return \Combodo\iTop\Form\Field\SelectField + */ + public function SetChoices($aChoices) + { + if ($this->bStartsWithNullChoice && !array_key_exists(null, $aChoices)) + { + $aChoices = array(null => static::DEFAULT_NULL_CHOICE_LABEL) + $aChoices; + } - parent::SetChoices($aChoices); - return $this; - } + parent::SetChoices($aChoices); + return $this; + } } diff --git a/sources/form/field/subformfield.class.inc.php b/sources/form/field/subformfield.class.inc.php index 5f18979b9..9f313fd3c 100644 --- a/sources/form/field/subformfield.class.inc.php +++ b/sources/form/field/subformfield.class.inc.php @@ -23,7 +23,7 @@ use \Closure; use \Combodo\iTop\Form\Form; /** - * Description of StringField + * Description of SubFormField * * @author Guillaume Lajarige */ @@ -31,12 +31,23 @@ class SubFormField extends Field { protected $oForm; + /** + * Default constructor + * + * @param string $sId + * @param string $sParentFormId + * @param Closure $onFinalizeCallback + */ public function __construct($sId, $sParentFormId, Closure $onFinalizeCallback = null) { $this->oForm = new Form($sParentFormId.'-subform_'.$sId); parent::__construct($sId, $onFinalizeCallback); } + /** + * + * @return \Combodo\iTop\Form\Form + */ public function GetForm() { return $this->oForm; @@ -53,11 +64,19 @@ class SubFormField extends Field $this->oForm->Validate(); } + /** + * + * @return boolean + */ public function GetValid() { return $this->oForm->GetValid(); } + /** + * + * @return array + */ public function GetErrorMessages() { $aRet = array(); @@ -68,13 +87,23 @@ class SubFormField extends Field return $aRet; } + /** + * + * @return array + */ public function GetCurrentValue() { return $this->oForm->GetCurrentValues(); } + /** + * + * @param array $value + * @return \Combodo\iTop\Form\Field\SubFormField + */ public function SetCurrentValue($value) { - return $this->oForm->SetCurrentValues($value); + $this->oForm->SetCurrentValues($value); + return $this; } } diff --git a/sources/form/field/textareafield.class.inc.php b/sources/form/field/textareafield.class.inc.php index e22d56594..cabf91240 100644 --- a/sources/form/field/textareafield.class.inc.php +++ b/sources/form/field/textareafield.class.inc.php @@ -28,5 +28,5 @@ use \Combodo\iTop\Form\Field\TextField; */ class TextAreaField extends TextField { - + } diff --git a/sources/form/field/textfield.class.inc.php b/sources/form/field/textfield.class.inc.php index 4919b4080..bd9b36b1b 100644 --- a/sources/form/field/textfield.class.inc.php +++ b/sources/form/field/textfield.class.inc.php @@ -29,26 +29,26 @@ use \Combodo\iTop\Form\Field\Field; abstract class TextField extends Field { - /** - * Checks the validators to see if the field's current value is valid. - * Then sets $bValid and $aErrorMessages. - * - * @return boolean - */ - public function Validate() - { - $this->SetValid(true); - $this->EmptyErrorMessages(); - foreach ($this->GetValidators() as $oValidator) - { - if (!preg_match($oValidator->GetRegExp(true), $this->GetCurrentValue())) - { - $this->SetValid(false); - $this->AddErrorMessage($oValidator->GetErrorMessage()); - } - } + /** + * Checks the validators to see if the field's current value is valid. + * Then sets $bValid and $aErrorMessages. + * + * @return boolean + */ + public function Validate() + { + $this->SetValid(true); + $this->EmptyErrorMessages(); + foreach ($this->GetValidators() as $oValidator) + { + if (!preg_match($oValidator->GetRegExp(true), $this->GetCurrentValue())) + { + $this->SetValid(false); + $this->AddErrorMessage($oValidator->GetErrorMessage()); + } + } - return $this->GetValid(); - } + return $this->GetValid(); + } } diff --git a/sources/form/form.class.inc.php b/sources/form/form.class.inc.php index 587b7eae0..f197d7623 100644 --- a/sources/form/form.class.inc.php +++ b/sources/form/form.class.inc.php @@ -30,268 +30,343 @@ use \Combodo\iTop\Form\Field\Field; */ class Form { - protected $sId; - protected $aFields; - protected $aDependencies; - protected $bValid; - protected $aErrorMessages; + protected $sId; + protected $aFields; + protected $aDependencies; + protected $bValid; + protected $aErrorMessages; - public function __construct($sId) - { - $this->sId = $sId; - $this->aFields = array(); - $this->aDependencies = array(); - $this->bValid = true; - $this->aErrorMessages = array(); - } + /** + * Default constructor + * + * @param string $sId + */ + public function __construct($sId) + { + $this->sId = $sId; + $this->aFields = array(); + $this->aDependencies = array(); + $this->bValid = true; + $this->aErrorMessages = array(); + } - public function GetId() - { - return $this->sId; - } + /** + * + * @return string + */ + public function GetId() + { + return $this->sId; + } - public function GetFields() - { - return $this->aFields; - } + /** + * + * @return array + */ + public function GetFields() + { + return $this->aFields; + } - public function GetDependencies() - { - return $this->aDependencies; - } + /** + * + * @return array + */ + public function GetDependencies() + { + return $this->aDependencies; + } - public function GetCurrentValues() - { - $aValues = array(); - foreach ($this->aFields as $sId => $oField) - { - $aValues[$sId] = $oField->GetCurrentValue(); - } - return $aValues; - } + /** + * Returns a hash array of "Field id" => "Field value" + * + * @return array + */ + public function GetCurrentValues() + { + $aValues = array(); + foreach ($this->aFields as $sId => $oField) + { + $aValues[$sId] = $oField->GetCurrentValue(); + } + return $aValues; + } - public function SetCurrentValues($aValues) - { - foreach ($aValues as $sId => $value) - { - $oField = $this->GetField($sId); - $oField->SetCurrentValue($value); - } - } + /** + * + * @param array $aValues Must be a hash array of "Field id" => "Field value" + * @return \Combodo\iTop\Form\Form + */ + public function SetCurrentValues($aValues) + { + foreach ($aValues as $sId => $value) + { + $oField = $this->GetField($sId); + $oField->SetCurrentValue($value); + } - /** - * Returns the current validation state of the form (true|false). - * It DOESN'T make the validation, see Validate() instead. - * - * @return boolean - */ - public function GetValid() - { - return $this->bValid; - } + return $this; + } - /** - * Note : Function is protected as bValid should not be set from outside - * - * @param boolean $bValid - * @return \Combodo\iTop\Form\Form - */ - protected function SetValid($bValid) - { - $this->bValid = $bValid; - return $this; - } + /** + * Returns the current validation state of the form (true|false). + * It DOESN'T make the validation, see Validate() instead. + * + * @return boolean + */ + public function GetValid() + { + return $this->bValid; + } - public function GetErrorMessages() - { - return $this->aErrorMessages; - } + /** + * Note : Function is protected as bValid should not be set from outside + * + * @param boolean $bValid + * @return \Combodo\iTop\Form\Form + */ + protected function SetValid($bValid) + { + $this->bValid = $bValid; + return $this; + } - /** - * Note : Function is protected as aErrorMessages should not be set from outside - * - * @param array $aErrorMessages - * @param string $sFieldId - * @return \Combodo\iTop\Form\Form - */ - protected function SetErrorMessages($aErrorMessages, $sFieldId = null) - { - if ($sFieldId === null) - { - $this->aErrorMessages = $aErrorMessages; - } - else - { - $this->aErrorMessages[$sFieldId] = $aErrorMessages; - } - return $this; - } + /** + * + * @return array + */ + public function GetErrorMessages() + { + return $this->aErrorMessages; + } - /** - * If $sFieldId is not set, the $sErrorMessage will be added to the general form messages - * - * Note : Function is protected as aErrorMessages should not be add from outside - * - * @param string $sErrorMessage - * @param string $sFieldId - * @return \Combodo\iTop\Form\Form - */ - protected function AddErrorMessage($sErrorMessage, $sFieldId = '_main') - { - if (!isset($this->aErrorMessages[$sFieldId])) - { - $this->aErrorMessages[$sFieldId] = array(); - } - $this->aErrorMessages[$sFieldId][] = $sErrorMessage; - return $this; - } + /** + * Note : Function is protected as aErrorMessages should not be set from outside + * + * @param array $aErrorMessages + * @param string $sFieldId + * @return \Combodo\iTop\Form\Form + */ + protected function SetErrorMessages($aErrorMessages, $sFieldId = null) + { + if ($sFieldId === null) + { + $this->aErrorMessages = $aErrorMessages; + } + else + { + $this->aErrorMessages[$sFieldId] = $aErrorMessages; + } + return $this; + } - /** - * Note : Function is protected as aErrorMessages should not be set from outside - * - * @return \Combodo\iTop\Form\Form - */ - protected function EmptyErrorMessages() - { - $this->aErrorMessages = array(); - return $this; - } + /** + * If $sFieldId is not set, the $sErrorMessage will be added to the general form messages + * + * Note : Function is protected as aErrorMessages should not be add from outside + * + * @param string $sErrorMessage + * @param string $sFieldId + * @return \Combodo\iTop\Form\Form + */ + protected function AddErrorMessage($sErrorMessage, $sFieldId = '_main') + { + if (!isset($this->aErrorMessages[$sFieldId])) + { + $this->aErrorMessages[$sFieldId] = array(); + } + $this->aErrorMessages[$sFieldId][] = $sErrorMessage; + return $this; + } - public function GetField($sId) - { - if (!array_key_exists($sId, $this->aFields)) - { - throw new Exception('Field with ID "' . $sId . '" was not found in the Form.'); - } - return $this->aFields[$sId]; - } + /** + * Note : Function is protected as aErrorMessages should not be set from outside + * + * @return \Combodo\iTop\Form\Form + */ + protected function EmptyErrorMessages() + { + $this->aErrorMessages = array(); + return $this; + } - public function HasField($sId) - { - return array_key_exists($sId, $this->aFields); - } + /** + * + * @param string $sId + * @return \Combodo\iTop\Form\Field\Field + * @throws Exception + */ + public function GetField($sId) + { + if (!array_key_exists($sId, $this->aFields)) + { + throw new Exception('Field with ID "' . $sId . '" was not found in the Form.'); + } + return $this->aFields[$sId]; + } - public function AddField(Field $oField, $aDependsOnIds = array()) - { - $oField->SetFormPath($this->sId); - $this->aFields[$oField->GetId()] = $oField; - return $this; - } + /** + * + * @param string $sId + * @return boolean + */ + public function HasField($sId) + { + return array_key_exists($sId, $this->aFields); + } - public function RemoveField($sId) - { - if (array_key_exists($sId, $this->aFields)) - { - unset($this->aFields[$sId]); - } - return $this; - } + /** + * + * @param \Combodo\iTop\Form\Field\Field $oField + * @param array $aDependsOnIds + * @return \Combodo\iTop\Form\Form + */ + public function AddField(Field $oField, $aDependsOnIds = array()) + { + $oField->SetFormPath($this->sId); + $this->aFields[$oField->GetId()] = $oField; + return $this; + } - /** - * Returns a array (list) of the fields ordered by their dependencies. - * - * @return array - */ - public function GetOrderedFields() - { - // TODO : Do this so it flatten the array - return $this->aFields; - } + /** + * + * @param string $sId + * @return \Combodo\iTop\Form\Form + */ + public function RemoveField($sId) + { + if (array_key_exists($sId, $this->aFields)) + { + unset($this->aFields[$sId]); + } + return $this; + } - /** - * Returns an array of field ids the $sFieldId depends on. - * - * @param string $sFieldId - * @return array - * @throws Exception - */ - public function GetFieldDependencies($sFieldId) - { - if (!array_key_exists($sFieldId, $this->aDependencies)) - { - throw new Exception('Field with ID "' . $sFieldId . '" had no dependancies declared in the Form.'); - } - return $this->aDependencies[$sFieldId]; - } + /** + * Returns a array (list) of the fields ordered by their dependencies. + * + * @return array + */ + public function GetOrderedFields() + { + // TODO : Do this so it flatten the array + return $this->aFields; + } - public function AddFieldDependencies($sFieldId, array $aDependsOnIds) - { - foreach ($aDependsOnIds as $sDependsOnId) - { - $this->AddFieldDependency($sFieldId, $sDependsOnId); - } - return $this; - } + /** + * Returns an array of field ids the $sFieldId depends on. + * + * @param string $sFieldId + * @return array + * @throws Exception + */ + public function GetFieldDependencies($sFieldId) + { + if (!array_key_exists($sFieldId, $this->aDependencies)) + { + throw new Exception('Field with ID "' . $sFieldId . '" had no dependancies declared in the Form.'); + } + return $this->aDependencies[$sFieldId]; + } - public function AddFieldDependency($sFieldId, $sDependsOnId) - { - if (!array_key_exists($sFieldId, $this->aDependencies)) - { - $this->aDependencies[$sFieldId] = array(); - } - $this->aDependencies[$sFieldId][] = $sDependsOnId; - return $this; - } + /** + * + * @param string $sFieldId + * @param array $aDependsOnIds + * @return \Combodo\iTop\Form\Form + */ + public function AddFieldDependencies($sFieldId, array $aDependsOnIds) + { + foreach ($aDependsOnIds as $sDependsOnId) + { + $this->AddFieldDependency($sFieldId, $sDependsOnId); + } + return $this; + } - /** - * Returns a hash array of the fields impacts on other fields. Key being the field that impacts the fields stored in the value as a regular array - * (It kind of reversed the dependencies array) - * - * eg : - * - 'service' => array('subservice', 'template') - * - 'subservice' => array() - * - ... - * - * @return array - */ - public function GetFieldsImpacts() - { - $aRes = array(); + /** + * + * @param string $sFieldId + * @param string $sDependsOnId + * @return \Combodo\iTop\Form\Form + */ + public function AddFieldDependency($sFieldId, $sDependsOnId) + { + if (!array_key_exists($sFieldId, $this->aDependencies)) + { + $this->aDependencies[$sFieldId] = array(); + } + $this->aDependencies[$sFieldId][] = $sDependsOnId; + return $this; + } - foreach ($this->aDependencies as $sImpactedFieldId => $aDependentFieldsIds) - { - foreach ($aDependentFieldsIds as $sDependentFieldId) - { - if (!array_key_exists($sDependentFieldId, $aRes)) - { - $aRes[$sDependentFieldId] = array(); - } - $aRes[$sDependentFieldId][] = $sImpactedFieldId; - } - } + /** + * Returns a hash array of the fields impacts on other fields. Key being the field that impacts the fields stored in the value as a regular array + * (It kind of reversed the dependencies array) + * + * eg : + * - 'service' => array('subservice', 'template') + * - 'subservice' => array() + * - ... + * + * @return array + */ + public function GetFieldsImpacts() + { + $aRes = array(); - return $aRes; - } + foreach ($this->aDependencies as $sImpactedFieldId => $aDependentFieldsIds) + { + foreach ($aDependentFieldsIds as $sDependentFieldId) + { + if (!array_key_exists($sDependentFieldId, $aRes)) + { + $aRes[$sDependentFieldId] = array(); + } + $aRes[$sDependentFieldId][] = $sImpactedFieldId; + } + } - public function Finalize() - { - //TODO : Call GetOrderedFields - // Must call OnFinalize on each fields, regarding the dependencies order - // On a SubFormField, will call its own Finalize - foreach ($this->aFields as $sId => $oField) - { - $oField->OnFinalize(); - } - } + return $aRes; + } - public function Validate() - { - $this->SetValid(true); - $this->EmptyErrorMessages(); - - foreach ($this->aFields as $oField) - { - if (!$oField->Validate()) - { - $this->SetValid(false); - foreach ($oField->GetErrorMessages() as $sErrorMessage) - { - $this->AddErrorMessage(Dict::S($sErrorMessage), $oField->Getid()); - } - } - } - - return $this->GetValid(); - } + /** + * + */ + public function Finalize() + { + //TODO : Call GetOrderedFields + // Must call OnFinalize on each fields, regarding the dependencies order + // On a SubFormField, will call its own Finalize + foreach ($this->aFields as $sId => $oField) + { + $oField->OnFinalize(); + } + } + + /** + * Validate the form and return if it's valid or not + * + * @return boolean + */ + public function Validate() + { + $this->SetValid(true); + $this->EmptyErrorMessages(); + + foreach ($this->aFields as $oField) + { + if (!$oField->Validate()) + { + $this->SetValid(false); + foreach ($oField->GetErrorMessages() as $sErrorMessage) + { + $this->AddErrorMessage(Dict::S($sErrorMessage), $oField->Getid()); + } + } + } + + return $this->GetValid(); + } } diff --git a/sources/form/formmanager.class.inc.php b/sources/form/formmanager.class.inc.php index 26c23795a..8777f207a 100644 --- a/sources/form/formmanager.class.inc.php +++ b/sources/form/formmanager.class.inc.php @@ -29,72 +29,111 @@ use \Combodo\iTop\Renderer\FormRenderer; */ abstract class FormManager { - protected $oForm; - protected $oRenderer; - - static function FromJSON($sJson) - { - // Overload in child class when needed - $aJson = json_decode($sJson, true); - - $oFormManager = new static(); - - $sFormRendererClass = $aJson['formrenderer_class']; - $oFormRenderer = new $sFormRendererClass(); - $oFormRenderer->SetEndpoint($aJson['formrenderer_endpoint']); - $oFormManager->SetRenderer($oFormRenderer); - - return $oFormManager; - } - - public function __construct() - { - // Overload in child class when needed - } + protected $oForm; + protected $oRenderer; /** - * @return Form - */ - public function GetForm() - { - return $this->oForm; - } + * Creates an instance of \Combodo\iTop\Form\FormManager from JSON data that must contain at least : + * - formrenderer_class : The class of the FormRenderer to use in the FormManager + * - formrenderer_endpoint : The endpoint of the renderer + * + * @param string $sJson + * @return \Combodo\iTop\Form\FormManager + */ + static function FromJSON($sJson) + { + // Overload in child class when needed + $aJson = json_decode($sJson, true); - /** - * @return FormRenderer - */ - public function GetRenderer() - { - return $this->oRenderer; - } + $oFormManager = new static(); - public function SetRenderer(FormRenderer $oRenderer) - { - $this->oRenderer = $oRenderer; - return $this; - } + $sFormRendererClass = $aJson['formrenderer_class']; + $oFormRenderer = new $sFormRendererClass(); + $oFormRenderer->SetEndpoint($aJson['formrenderer_endpoint']); + $oFormManager->SetRenderer($oFormRenderer); - public function GetClass() - { - return get_class($this); - } + return $oFormManager; + } - public function ToJSON() - { - // Overload in child class when needed - return array( - 'id' => $this->oForm->GetId(), - 'formmanager_class' => $this->GetClass(), - 'formrenderer_class' => get_class($this->GetRenderer()), - 'formrenderer_endpoint' => $this->GetRenderer()->GetEndpoint() - ); - } + public function __construct() + { + // Overload in child class when needed + } - abstract public function Build(); + /** + * + * @return \Combodo\iTop\Form\Form + */ + public function GetForm() + { + return $this->oForm; + } - abstract public function OnUpdate($aArgs = null); + /** + * + * @param \Combodo\iTop\Form\Form $oForm + * @return \Combodo\iTop\Form\FormManager + */ + public function SetForm(Form $oForm) + { + $this->oForm = $oForm; + return $this; + } - abstract public function OnSubmit($aArgs = null); + /** + * + * @return \Combodo\iTop\Renderer\FormRenderer + */ + public function GetRenderer() + { + return $this->oRenderer; + } - abstract public function OnCancel($aArgs = null); + /** + * + * @param \Combodo\iTop\Renderer\FormRenderer $oRenderer + * @return \Combodo\iTop\Form\FormManager + */ + public function SetRenderer(FormRenderer $oRenderer) + { + $this->oRenderer = $oRenderer; + return $this; + } + + /** + * + * @return string + */ + public function GetClass() + { + return get_class($this); + } + + /** + * Creates a JSON string from the current object including : + * - id : Id of the current Form + * - formmanager_class + * - formrenderer_class + * - formrenderer_endpoint + * + * @return string + */ + public function ToJSON() + { + // Overload in child class when needed + return array( + 'id' => $this->oForm->GetId(), + 'formmanager_class' => $this->GetClass(), + 'formrenderer_class' => get_class($this->GetRenderer()), + 'formrenderer_endpoint' => $this->GetRenderer()->GetEndpoint() + ); + } + + abstract public function Build(); + + abstract public function OnUpdate($aArgs = null); + + abstract public function OnSubmit($aArgs = null); + + abstract public function OnCancel($aArgs = null); } diff --git a/sources/form/validator/integervalidator.class.inc.php b/sources/form/validator/integervalidator.class.inc.php index 23c8f7811..3effa2522 100644 --- a/sources/form/validator/integervalidator.class.inc.php +++ b/sources/form/validator/integervalidator.class.inc.php @@ -28,8 +28,8 @@ use \Combodo\iTop\Form\Validator\Validator; */ class IntegerValidator extends Validator { - const VALIDATOR_NAME = 'integer'; - const DEFAULT_REGEXP = '^[0-9]+$'; - const DEFAULT_ERROR_MESSAGE = 'TOTR: MUST NOT BE AN INTEGER MESSAGE'; + const VALIDATOR_NAME = 'integer'; + const DEFAULT_REGEXP = '^[0-9]+$'; + const DEFAULT_ERROR_MESSAGE = 'TOTR: MUST NOT BE AN INTEGER MESSAGE'; } diff --git a/sources/form/validator/mandatoryvalidator.class.inc.php b/sources/form/validator/mandatoryvalidator.class.inc.php index 0279aef65..91c9a4af6 100644 --- a/sources/form/validator/mandatoryvalidator.class.inc.php +++ b/sources/form/validator/mandatoryvalidator.class.inc.php @@ -30,8 +30,8 @@ use \Combodo\iTop\Form\Validator\Validator; */ class MandatoryValidator extends Validator { - const VALIDATOR_NAME = 'mandatory'; - const DEFAULT_REGEXP = '.*\S.*'; - const DEFAULT_ERROR_MESSAGE = 'TOTR: MANDATORY MESSAGE'; + const VALIDATOR_NAME = 'mandatory'; + const DEFAULT_REGEXP = '.*\S.*'; + const DEFAULT_ERROR_MESSAGE = 'TOTR: MANDATORY MESSAGE'; } diff --git a/sources/form/validator/notemptyextkeyvalidator.class.inc.php b/sources/form/validator/notemptyextkeyvalidator.class.inc.php index 8a268f4ad..569b1abad 100644 --- a/sources/form/validator/notemptyextkeyvalidator.class.inc.php +++ b/sources/form/validator/notemptyextkeyvalidator.class.inc.php @@ -28,8 +28,8 @@ use \Combodo\iTop\Form\Validator\Validator; */ class NotEmptyExtKeyValidator extends Validator { - const VALIDATOR_NAME = 'notemptyextkey'; - const DEFAULT_REGEXP = '^[1-9]+$'; - const DEFAULT_ERROR_MESSAGE = 'TOTR: MUST SELECT ONE'; + const VALIDATOR_NAME = 'notemptyextkey'; + const DEFAULT_REGEXP = '^[1-9]+$'; + const DEFAULT_ERROR_MESSAGE = 'TOTR: MUST SELECT ONE'; } diff --git a/sources/form/validator/notemptyvalidator.class.inc.php b/sources/form/validator/notemptyvalidator.class.inc.php index edf36faef..dabb32d2b 100644 --- a/sources/form/validator/notemptyvalidator.class.inc.php +++ b/sources/form/validator/notemptyvalidator.class.inc.php @@ -28,8 +28,8 @@ use \Combodo\iTop\Form\Validator\Validator; */ class NotEmptyValidator extends Validator { - const VALIDATOR_NAME = 'notempty'; - const DEFAULT_REGEXP = '.*\S.*'; - const DEFAULT_ERROR_MESSAGE = 'TOTR: MUST NOT BE EMPTY MESSAGE'; + const VALIDATOR_NAME = 'notempty'; + const DEFAULT_REGEXP = '.*\S.*'; + const DEFAULT_ERROR_MESSAGE = 'TOTR: MUST NOT BE EMPTY MESSAGE'; } diff --git a/sources/form/validator/validator.class.inc.php b/sources/form/validator/validator.class.inc.php index 9a8fa7bdf..a4414db44 100644 --- a/sources/form/validator/validator.class.inc.php +++ b/sources/form/validator/validator.class.inc.php @@ -26,83 +26,83 @@ namespace Combodo\iTop\Form\Validator; */ class Validator { - const VALIDATOR_NAME = 'expression'; - const DEFAULT_REGEXP = ''; - const DEFAULT_ERROR_MESSAGE = 'TOTR: Core:Validator:Default'; + const VALIDATOR_NAME = 'expression'; + const DEFAULT_REGEXP = ''; + const DEFAULT_ERROR_MESSAGE = 'TOTR: Core:Validator:Default'; - protected $sRegExp; - protected $sErrorMessage; + protected $sRegExp; + protected $sErrorMessage; - public static function GetName() - { - return static::VALIDATOR_NAME; - } + public static function GetName() + { + return static::VALIDATOR_NAME; + } - /** - * - * @param Closure $callback (Used in the $oForm->AddField($sId, ..., function() use ($oManager, $oForm, '...') { ... } ); ) - */ - public function __construct($sRegExp = null, $sErrorMessage = null) - { - $this->sRegExp = ($sRegExp === null) ? static::DEFAULT_REGEXP : $sRegExp; - $this->sErrorMessage = ($sErrorMessage === null) ? static::DEFAULT_ERROR_MESSAGE : $sErrorMessage; - $this->ComputeConstraints(); - } + /** + * + * @param Closure $callback (Used in the $oForm->AddField($sId, ..., function() use ($oManager, $oForm, '...') { ... } ); ) + */ + public function __construct($sRegExp = null, $sErrorMessage = null) + { + $this->sRegExp = ($sRegExp === null) ? static::DEFAULT_REGEXP : $sRegExp; + $this->sErrorMessage = ($sErrorMessage === null) ? static::DEFAULT_ERROR_MESSAGE : $sErrorMessage; + $this->ComputeConstraints(); + } - /** - * Returns the regular expression of the validator. - * - * @param boolean $bWithSlashes If true, surrounds $sRegExp with '/'. Used with preg_match & co - * @return string - */ - public function GetRegExp($bWithSlashes = false) - { - return ($bWithSlashes) ? '/' . $this->sRegExp . '/' : $this->sRegExp; - } + /** + * Returns the regular expression of the validator. + * + * @param boolean $bWithSlashes If true, surrounds $sRegExp with '/'. Used with preg_match & co + * @return string + */ + public function GetRegExp($bWithSlashes = false) + { + return ($bWithSlashes) ? '/' . $this->sRegExp . '/' : $this->sRegExp; + } - public function GetErrorMessage() - { - return $this->sErrorMessage; - } + public function GetErrorMessage() + { + return $this->sErrorMessage; + } - public function SetRegExp($sRegExp) - { - $this->sRegExp = $sRegExp; - $this->ComputeConstraints(); - return $this; - } + public function SetRegExp($sRegExp) + { + $this->sRegExp = $sRegExp; + $this->ComputeConstraints(); + return $this; + } - public function SetErrorMessage($sErrorMessage) - { - $this->sErrorMessage = $sErrorMessage; - $this->ComputeConstraints(); - return $this; - } + public function SetErrorMessage($sErrorMessage) + { + $this->sErrorMessage = $sErrorMessage; + $this->ComputeConstraints(); + return $this; + } - /** - * Computes the regular expression and error message when changing constraints on the validator. - * Should be called in the validator's setters. - */ - public function ComputeConstraints() - { - $this->ComputeRegularExpression(); - $this->ComputeErrorMessage(); - } + /** + * Computes the regular expression and error message when changing constraints on the validator. + * Should be called in the validator's setters. + */ + public function ComputeConstraints() + { + $this->ComputeRegularExpression(); + $this->ComputeErrorMessage(); + } - /** - * Computes the regular expression when changing constraints on the validator. - */ - public function ComputeRegularExpression() - { - // Overload when necessary - } + /** + * Computes the regular expression when changing constraints on the validator. + */ + public function ComputeRegularExpression() + { + // Overload when necessary + } - /** - * Computes the error message when changing constraints on the validator. - */ - public function ComputeErrorMessage() - { - // Overload when necessary - } + /** + * Computes the error message when changing constraints on the validator. + */ + public function ComputeErrorMessage() + { + // Overload when necessary + } } diff --git a/sources/renderer/bootstrap/bsformrenderer.class.inc.php b/sources/renderer/bootstrap/bsformrenderer.class.inc.php index 633059788..f0005d413 100644 --- a/sources/renderer/bootstrap/bsformrenderer.class.inc.php +++ b/sources/renderer/bootstrap/bsformrenderer.class.inc.php @@ -29,16 +29,22 @@ use \Combodo\iTop\Form\Form; */ class BsFormRenderer extends FormRenderer { - const DEFAULT_RENDERER_NAMESPACE = 'Combodo\\iTop\\Renderer\\Bootstrap\\FieldRenderer\\'; + const DEFAULT_RENDERER_NAMESPACE = 'Combodo\\iTop\\Renderer\\Bootstrap\\FieldRenderer\\'; + + /** + * Default constructor + * + * @param \Combodo\iTop\Form\Form $oForm + */ + public function __construct(Form $oForm = null) + { + parent::__construct($oForm); + $this->AddSupportedField('HiddenField', 'BsSimpleFieldRenderer'); + $this->AddSupportedField('StringField', 'BsSimpleFieldRenderer'); + $this->AddSupportedField('TextAreaField', 'BsSimpleFieldRenderer'); + $this->AddSupportedField('SelectField', 'BsSimpleFieldRenderer'); + $this->AddSupportedField('RadioField', 'BsSimpleFieldRenderer'); + $this->AddSupportedField('CheckboxField', 'BsSimpleFieldRenderer'); + } - public function __construct(Form $oForm = null) - { - parent::__construct($oForm); - $this->AddSupportedField('HiddenField', 'BsSimpleFieldRenderer'); - $this->AddSupportedField('StringField', 'BsSimpleFieldRenderer'); - $this->AddSupportedField('TextAreaField', 'BsSimpleFieldRenderer'); - $this->AddSupportedField('SelectField', 'BsSimpleFieldRenderer'); - $this->AddSupportedField('RadioField', 'BsSimpleFieldRenderer'); - $this->AddSupportedField('CheckboxField', 'BsSimpleFieldRenderer'); - } } diff --git a/sources/renderer/bootstrap/fieldrenderer/bssimplefieldrenderer.class.inc.php b/sources/renderer/bootstrap/fieldrenderer/bssimplefieldrenderer.class.inc.php index 1ca50a41d..c8bbfbf1b 100644 --- a/sources/renderer/bootstrap/fieldrenderer/bssimplefieldrenderer.class.inc.php +++ b/sources/renderer/bootstrap/fieldrenderer/bssimplefieldrenderer.class.inc.php @@ -31,201 +31,209 @@ use \Combodo\iTop\Renderer\RenderingOutput; class BsSimpleFieldRenderer extends FieldRenderer { - public function Render() - { - $oOutput = new RenderingOutput(); - $sFieldClass = get_class($this->oField); - $sFieldId = 'field_' . spl_object_hash($this->oField); - $sFieldMandatoryClass = ($this->oField->GetMandatory()) ? 'form_mandatory' : ''; + /** + * Returns a RenderingOutput for the FieldRenderer's Field + * + * @return \Combodo\iTop\Renderer\RenderingOutput + */ + public function Render() + { + $oOutput = new RenderingOutput(); + $sFieldClass = get_class($this->oField); + $sFieldMandatoryClass = ($this->oField->GetMandatory()) ? 'form_mandatory' : ''; - // TODO : Shouldn't we have a field type so we don't have to maintain FQN classname ? - // Rendering field in edition mode - if (!$this->oField->GetReadOnly()) - { - switch ($sFieldClass) - { - case 'Combodo\\iTop\\Form\\Field\\StringField': - $oOutput->AddHtml('
'); - if ($this->oField->GetLabel() !== '') - { - $oOutput->AddHtml(''); - } - $oOutput->AddHtml('
'); - $oOutput->AddHtml(''); - $oOutput->AddHtml('
'); - break; + // TODO : Shouldn't we have a field type so we don't have to maintain FQN classname ? + // Rendering field in edition mode + if (!$this->oField->GetReadOnly()) + { + switch ($sFieldClass) + { + case 'Combodo\\iTop\\Form\\Field\\StringField': + $oOutput->AddHtml('
'); + if ($this->oField->GetLabel() !== '') + { + $oOutput->AddHtml(''); + } + $oOutput->AddHtml('
'); + $oOutput->AddHtml(''); + $oOutput->AddHtml('
'); + break; - case 'Combodo\\iTop\\Form\\Field\\TextAreaField': - $oOutput->AddHtml('
'); - if ($this->oField->GetLabel() !== '') - { - $oOutput->AddHtml(''); - } - $oOutput->AddHtml('
'); - $oOutput->AddHtml(''); - $oOutput->AddHtml('
'); - break; + case 'Combodo\\iTop\\Form\\Field\\TextAreaField': + $oOutput->AddHtml('
'); + if ($this->oField->GetLabel() !== '') + { + $oOutput->AddHtml(''); + } + $oOutput->AddHtml('
'); + $oOutput->AddHtml(''); + $oOutput->AddHtml('
'); + break; - case 'Combodo\\iTop\\Form\\Field\\SelectField': - $oOutput->AddHtml('
'); - if ($this->oField->GetLabel() !== '') - { - $oOutput->AddHtml(''); - } - $oOutput->AddHtml('
'); - $oOutput->AddHtml(''); - $oOutput->AddHtml('
'); - break; + case 'Combodo\\iTop\\Form\\Field\\SelectField': + $oOutput->AddHtml('
'); + if ($this->oField->GetLabel() !== '') + { + $oOutput->AddHtml(''); + } + $oOutput->AddHtml('
'); + $oOutput->AddHtml(''); + $oOutput->AddHtml('
'); + break; - case 'Combodo\\iTop\\Form\\Field\\RadioField': - case 'Combodo\\iTop\\Form\\Field\\CheckboxField': - $sFieldType = ($sFieldClass === 'Combodo\\iTop\\Form\\Field\\RadioField') ? 'radio' : 'checkbox'; + case 'Combodo\\iTop\\Form\\Field\\RadioField': + case 'Combodo\\iTop\\Form\\Field\\CheckboxField': + $sFieldType = ($sFieldClass === 'Combodo\\iTop\\Form\\Field\\RadioField') ? 'radio' : 'checkbox'; - $oOutput->AddHtml('
'); + $oOutput->AddHtml('
'); - if ($this->oField->GetLabel() !== '') - { - $oOutput->AddHtml('
'); - } + if ($this->oField->GetLabel() !== '') + { + $oOutput->AddHtml('
'); + } - $oOutput->AddHtml('
'); - $oOutput->AddHtml('
'); - $i = 0; - foreach ($this->oField->GetChoices() as $sChoice => $sLabel) - { - // Note : The test is a double equal on purpose as the type of the value received from the XHR is not always the same as the type of the allowed values. (eg : string vs int) - $sCheckedAtt = ($this->oField->IsAmongValues($sChoice)) ? 'checked' : ''; - $sCheckedClass = ($this->oField->IsAmongValues($sChoice)) ? 'active' : ''; - $oOutput->AddHtml(''); - $i++; - } - $oOutput->AddHtml('
'); + $oOutput->AddHtml('
'); + $oOutput->AddHtml('
'); + $i = 0; + foreach ($this->oField->GetChoices() as $sChoice => $sLabel) + { + // Note : The test is a double equal on purpose as the type of the value received from the XHR is not always the same as the type of the allowed values. (eg : string vs int) + $sCheckedAtt = ($this->oField->IsAmongValues($sChoice)) ? 'checked' : ''; + $sCheckedClass = ($this->oField->IsAmongValues($sChoice)) ? 'active' : ''; + $oOutput->AddHtml(''); + $i++; + } + $oOutput->AddHtml('
'); - $oOutput->AddHtml('
'); - break; + $oOutput->AddHtml('
'); + break; - case 'Combodo\\iTop\\Form\\Field\\HiddenField': - $oOutput->AddHtml(''); - break; - } - } - // ... and in read-only mode - else - { - // ... specific rendering for fields with mulltiple values - if (($this->oField instanceof Combodo\iTop\Form\Field\MultipleChoicesField) && ($this->oField->GetMultipleValuesEnabled())) - { - // TODO - } - // ... clasic rendering for fields with only one value - else - { - switch ($sFieldClass) - { - case 'Combodo\\iTop\\Form\\Field\\StringField': - case 'Combodo\\iTop\\Form\\Field\\TextAreaField': - $oOutput->AddHtml('
'); - if ($this->oField->GetLabel() !== '') - { - $oOutput->AddHtml(''); - } - $oOutput->AddHtml('
' . $this->oField->GetCurrentValue() . '
'); - $oOutput->AddHtml(''); - $oOutput->AddHtml('
'); - break; + case 'Combodo\\iTop\\Form\\Field\\HiddenField': + $oOutput->AddHtml(''); + break; + } + } + // ... and in read-only mode + else + { + // ... specific rendering for fields with mulltiple values + if (($this->oField instanceof Combodo\iTop\Form\Field\MultipleChoicesField) && ($this->oField->GetMultipleValuesEnabled())) + { + // TODO + } + // ... clasic rendering for fields with only one value + else + { + switch ($sFieldClass) + { + case 'Combodo\\iTop\\Form\\Field\\StringField': + case 'Combodo\\iTop\\Form\\Field\\TextAreaField': + $oOutput->AddHtml('
'); + if ($this->oField->GetLabel() !== '') + { + $oOutput->AddHtml(''); + } + $oOutput->AddHtml('
' . $this->oField->GetCurrentValue() . '
'); + $oOutput->AddHtml(''); + $oOutput->AddHtml('
'); + break; - case 'Combodo\\iTop\\Form\\Field\\RadioField': - case 'Combodo\\iTop\\Form\\Field\\SelectField': // TODO : This should be check for external key, as we would display it differently - $aFieldChoices = $this->oField->GetChoices(); - $sFieldValue = (isset($aFieldChoices[$this->oField->GetCurrentValue()])) ? $aFieldChoices[$this->oField->GetCurrentValue()] : Dict::S('UI:UndefinedObject'); + case 'Combodo\\iTop\\Form\\Field\\RadioField': + case 'Combodo\\iTop\\Form\\Field\\SelectField': // TODO : This should be check for external key, as we would display it differently + $aFieldChoices = $this->oField->GetChoices(); + $sFieldValue = (isset($aFieldChoices[$this->oField->GetCurrentValue()])) ? $aFieldChoices[$this->oField->GetCurrentValue()] : Dict::S('UI:UndefinedObject'); - $oOutput->AddHtml('
'); - if ($this->oField->GetLabel() !== '') - { - $oOutput->AddHtml(''); - } - $oOutput->AddHtml('
' . $sFieldValue . '
'); - $oOutput->AddHtml(''); - $oOutput->AddHtml('
'); - break; - } - } - } + $oOutput->AddHtml('
'); + if ($this->oField->GetLabel() !== '') + { + $oOutput->AddHtml(''); + } + $oOutput->AddHtml('
' . $sFieldValue . '
'); + $oOutput->AddHtml(''); + $oOutput->AddHtml('
'); + break; + } + } + } - // JS FieldChange trigger (:input are not always at the same depth) - switch ($sFieldClass) - { - case 'Combodo\\iTop\\Form\\Field\\StringField': - case 'Combodo\\iTop\\Form\\Field\\TextAreaField': - case 'Combodo\\iTop\\Form\\Field\\SelectField': - case 'Combodo\\iTop\\Form\\Field\\HiddenField': - $oOutput->AddJs( -<<AddJs( + <<oField->GetGlobalId()}").off("change keyup").on("change keyup", function(){ + var me = this; + + $(this).closest(".field_set").trigger("field_change", { + id: $(me).attr("id"), + name: $(me).closest(".form_field").attr("data-field-id"), + value: $(me).val() + }); + }); EOF - ); - break; + ); + break; - case 'Combodo\\iTop\\Form\\Field\\RadioField': - case 'Combodo\\iTop\\Form\\Field\\CheckboxField': - $oOutput->AddJs( -<<AddJs( + <<oField->GetGlobalId()} input").off("change").on("change", function(){ + var me = this; + + $(this).closest(".field_set").trigger("field_change", { + id: $(me).closest("#{$this->oField->GetGlobalId()}").attr("id"), + name: $(me).attr("name"), + value: $(me).val() + }); + }); EOF - ); - break; - } + ); + break; + } - // JS Form field widget construct - $aValidators = array(); - foreach ($this->oField->GetValidators() as $oValidator) - { - $aValidators[$oValidator::GetName()] = array( - 'reg_exp' => $oValidator->GetRegExp(), - 'message' => Dict::S($oValidator->GetErrorMessage()) - ); - } + // JS Form field widget construct + $aValidators = array(); + foreach ($this->oField->GetValidators() as $oValidator) + { + $aValidators[$oValidator::GetName()] = array( + 'reg_exp' => $oValidator->GetRegExp(), + 'message' => Dict::S($oValidator->GetErrorMessage()) + ); + } - $sFormFieldOptions = json_encode(array( - 'validators' => $aValidators - )); + $sFormFieldOptions = json_encode(array( + 'validators' => $aValidators + )); - switch ($sFieldClass) - { - case 'Combodo\\iTop\\Form\\Field\\StringField': - case 'Combodo\\iTop\\Form\\Field\\TextAreaField': - case 'Combodo\\iTop\\Form\\Field\\SelectField': - case 'Combodo\\iTop\\Form\\Field\\HiddenField': - case 'Combodo\\iTop\\Form\\Field\\RadioField': - case 'Combodo\\iTop\\Form\\Field\\CheckboxField': - $oOutput->AddJs( - <<AddJs( + <<oField = $oField; - } + /** + * Default constructor + * + * @param \Combodo\iTop\Form\Field\Field $oField + */ + public function __construct(Field $oField) + { + $this->oField = $oField; + } - public function GetEndpoint() - { - return $this->sEndpoint; - } + /** + * + * @return string + */ + public function GetEndpoint() + { + return $this->sEndpoint; + } - public function SetEndpoint($sEndpoint) - { - $this->sEndpoint = $sEndpoint; - } + /** + * + * @param string $sEndpoint + */ + public function SetEndpoint($sEndpoint) + { + $this->sEndpoint = $sEndpoint; + } - /** - * Renders a Field as a RenderingOutput - * - * @return \Combodo\iTop\Renderer\RenderingOutput - */ - abstract public function Render(); + /** + * Renders a Field as a RenderingOutput + * + * @return \Combodo\iTop\Renderer\RenderingOutput + */ + abstract public function Render(); } diff --git a/sources/renderer/formrenderer.class.inc.php b/sources/renderer/formrenderer.class.inc.php index 2481ba23b..640a5442c 100644 --- a/sources/renderer/formrenderer.class.inc.php +++ b/sources/renderer/formrenderer.class.inc.php @@ -22,6 +22,7 @@ namespace Combodo\iTop\Renderer; use \Exception; use \Dict; use \Combodo\iTop\Form\Form; +use \Combodo\iTop\Form\Field\Field; /** * Description of FormRenderer @@ -30,231 +31,272 @@ use \Combodo\iTop\Form\Form; */ abstract class FormRenderer { - const ENUM_RENDER_MODE_EXPLODED = 'exploded'; - const ENUM_RENDER_MODE_JOINED = 'joined'; - const DEFAULT_RENDERER_NAMESPACE = ''; + const ENUM_RENDER_MODE_EXPLODED = 'exploded'; + const ENUM_RENDER_MODE_JOINED = 'joined'; + const DEFAULT_RENDERER_NAMESPACE = ''; - protected $oForm; - protected $sEndpoint; - protected $aSupportedFields; - protected $sBaseLayout; - protected $aOutputs; + protected $oForm; + protected $sEndpoint; + protected $aSupportedFields; + protected $sBaseLayout; + protected $aOutputs; - /** - * Default constructor - * - * @param \Combodo\iTop\Form\Form $oForm - */ - public function __construct(Form $oForm = null) - { - if ($oForm !== null) - { - $this->oForm = $oForm; - } - $this->sBaseLayout = ''; - $this->InitOutputs(); - } + /** + * Default constructor + * + * @param \Combodo\iTop\Form\Form $oForm + */ + public function __construct(Form $oForm = null) + { + if ($oForm !== null) + { + $this->oForm = $oForm; + } + $this->sBaseLayout = ''; + $this->InitOutputs(); + } - public function GetForm() - { - return $this->oForm; - } + /** + * + * @return \Combodo\iTop\Form\Form + */ + public function GetForm() + { + return $this->oForm; + } - public function SetForm($oForm) - { - $this->oForm = $oForm; - return $this; - } + /** + * + * @param \Combodo\iTop\Form\Form $oForm + * @return \Combodo\iTop\Renderer\FormRenderer + */ + public function SetForm(Form $oForm) + { + $this->oForm = $oForm; + return $this; + } - public function GetEndpoint() - { - return $this->sEndpoint; - } + /** + * + * @return string + */ + public function GetEndpoint() + { + return $this->sEndpoint; + } - public function SetEndpoint($sEndpoint) - { - $this->sEndpoint = $sEndpoint; - return $this; - } + /** + * + * @param string $sEndpoint + * @return \Combodo\iTop\Renderer\FormRenderer + */ + public function SetEndpoint($sEndpoint) + { + $this->sEndpoint = $sEndpoint; + return $this; + } - public function GetBaseLayout() - { - return $this->sBaseLayout; - } + /** + * + * @return string + */ + public function GetBaseLayout() + { + return $this->sBaseLayout; + } - public function SetBaseLayout($sBaseLayout) - { - $this->sBaseLayout = $sBaseLayout; - return $this; - } + /** + * + * @param string $sBaseLayout + * @return \Combodo\iTop\Renderer\FormRenderer + */ + public function SetBaseLayout($sBaseLayout) + { + $this->sBaseLayout = $sBaseLayout; + return $this; + } - public function GetFieldRendererClass($oField) - { - if (array_key_exists(get_class($oField), $this->aSupportedFields)) - { - return $this->aSupportedFields[get_class($oField)]; - } - else - { - throw new Exception('Field type not supported by the renderer: '.get_class($oField)); - } - } + /** + * + * @param \Combodo\iTop\Form\Field\Field $oField + * @return string + * @throws Exception + */ + public function GetFieldRendererClass(Field $oField) + { + if (array_key_exists(get_class($oField), $this->aSupportedFields)) + { + return $this->aSupportedFields[get_class($oField)]; + } + else + { + throw new Exception('Field type not supported by the renderer: ' . get_class($oField)); + } + } - /** - * Returns the field identified by the id $sId in $this->oForm. - * - * @param string $sId - * @return \Combodo\iTop\Renderer\FieldRenderer - */ - public function GetFieldRendererClassFromId($sId) - { - return $this->GetFieldRendererClass($this->oForm->GetField($sId)); - } + /** + * Returns the field identified by the id $sId in $this->oForm. + * + * @param string $sId + * @return \Combodo\iTop\Renderer\FieldRenderer + */ + public function GetFieldRendererClassFromId($sId) + { + return $this->GetFieldRendererClass($this->oForm->GetField($sId)); + } - /** - * - * @return array - */ - public function GetOutputs() - { - return $this->aOutputs; - } + /** + * + * @return array + */ + public function GetOutputs() + { + return $this->aOutputs; + } + /** + * Registers a Renderer class for the specified Field class. + * + * If the Field class is not fully qualified, the default "Combodo\iTop\Form\Field" will be prepend. + * If the Field class already had a registered Renderer, it is replaced. + * + * @param string $sFieldClass + * @param string $sRendererClass + */ + public function AddSupportedField($sFieldClass, $sRendererClass) + { + $sFieldClass = (strpos($sFieldClass, '\\') !== false) ? $sFieldClass : 'Combodo\\iTop\\Form\\Field\\' . $sFieldClass; + $sRendererClass = (strpos($sRendererClass, '\\') !== false) ? $sRendererClass : static::DEFAULT_RENDERER_NAMESPACE . $sRendererClass; - /** - * Registers a Renderer class for the specified Field class. - * - * If the Field class is not fully qualified, the default "Combodo\iTop\Form\Field" will be prepend. - * If the Field class already had a registered Renderer, it is replaced. - * - * @param string $sFieldClass - * @param string $sRendererClass - */ - public function AddSupportedField($sFieldClass, $sRendererClass) - { - $sFieldClass = (strpos($sFieldClass, '\\') !== false) ? $sFieldClass : 'Combodo\\iTop\\Form\\Field\\' . $sFieldClass; - $sRendererClass = (strpos($sRendererClass, '\\') !== false) ? $sRendererClass : static::DEFAULT_RENDERER_NAMESPACE . $sRendererClass; + $this->aSupportedFields[$sFieldClass] = $sRendererClass; - $this->aSupportedFields[$sFieldClass] = $sRendererClass; + return $this; + } - return $this; - } + /** + * + * @return \Combodo\iTop\Renderer\FormRenderer + */ + public function InitOutputs() + { + $this->aOutputs = array(); + return $this; + } - public function InitOutputs() - { - $this->aOutputs = array(); - return $this; - } + /** + * + * @return array + */ + public function Render() + { + $this->InitOutputs(); - public function Render() - { - $this->InitOutputs(); + foreach ($this->oForm->GetFields() as $oField) + { + $this->aOutputs[$oField->GetId()] = $this->PrepareOutputForField($oField); + } - foreach ($this->oForm->GetFields() as $oField) - { - $this->aOutputs[$oField->GetId()] = $this->PrepareOutputForField($oField); - } + return $this->aOutputs; + } - return $this->aOutputs; - } + /** + * Returns the output for the $oField. Output format depends on the $sMode. + * + * If $sMode = 'exploded', output is an has array with id / html / js_inline / js_files / css_inline / css_files / validators + * Else if $sMode = 'joined', output is a string with everything in it + * + * @param \Combodo\iTop\Form\Field\Field $oField + * @param string $sMode 'exploded'|'joined' + * @return mixed + */ + protected function PrepareOutputForField($oField, $sMode = 'exploded') + { + $output = array( + 'id' => $oField->GetId(), + 'html' => '', + 'js_inline' => '', + 'css_inline' => '', + 'js_files' => array(), + 'css_files' => array() + ); - /** - * Returns the output for the $oField. Output format depends on the $sMode. - * - * If $sMode = 'exploded', output is an has array with id / html / js_inline / js_files / css_inline / css_files / validators - * Else if $sMode = 'joined', output is a string with everything in it - * - * @param \Combodo\iTop\Form\Field\Field $oField - * @param string $sMode 'exploded'|'joined' - * @return mixed - */ - protected function PrepareOutputForField($oField, $sMode = 'exploded') - { - $output = array( - 'id' => $oField->GetId(), - 'html' => '', - 'js_inline' => '', - 'css_inline' => '', - 'js_files' => array(), - 'css_files' => array() - ); + $sFieldRendererClass = $this->GetFieldRendererClass($oField); - $sFieldRendererClass = $this->GetFieldRendererClass($oField); + $oFieldRenderer = new $sFieldRendererClass($oField); + $oFieldRenderer->SetEndpoint($this->GetEndpoint()); - $oFieldRenderer = new $sFieldRendererClass($oField); - $oFieldRenderer->SetEndpoint($this->GetEndpoint()); + $oRenderingOutput = $oFieldRenderer->Render(); - $oRenderingOutput = $oFieldRenderer->Render(); + // HTML + if ($oRenderingOutput->GetHtml() !== '') + { + if ($sMode === static::ENUM_RENDER_MODE_EXPLODED) + { + $output['html'] = $oRenderingOutput->GetHtml(); + } + else + { + $output['html'] .= $oRenderingOutput->GetHtml(); + } + } - // HTML - if ($oRenderingOutput->GetHtml() !== '') - { - if ($sMode === static::ENUM_RENDER_MODE_EXPLODED) - { - $output['html'] = $oRenderingOutput->GetHtml(); - } - else - { - $output['html'] .= $oRenderingOutput->GetHtml(); - } - } + // JS files + foreach ($oRenderingOutput->GetJsFiles() as $sJsFile) + { + if ($sMode === static::ENUM_RENDER_MODE_EXPLODED) + { + if (!in_array($sJsFile, $output['js_files'])) + { + $output['js_files'][] = $sJsFile; + } + } + else + { + $output['html'] .= ''; + } + } + // JS inline + if ($oRenderingOutput->GetJs() !== '') + { + if ($sMode === static::ENUM_RENDER_MODE_EXPLODED) + { + $output['js_inline'] .= ' ' . $oRenderingOutput->GetJs(); + } + else + { + $output['html'] .= ''; + } + } - // JS files - foreach ($oRenderingOutput->GetJsFiles() as $sJsFile) - { - if ($sMode === static::ENUM_RENDER_MODE_EXPLODED) - { - if (!in_array($sJsFile, $output['js_files'])) - { - $output['js_files'][] = $sJsFile; - } - } - else - { - $output['html'] .= ''; - } - } - // JS inline - if ($oRenderingOutput->GetJs() !== '') - { - if ($sMode === static::ENUM_RENDER_MODE_EXPLODED) - { - $output['js_inline'] .= ' ' . $oRenderingOutput->GetJs(); - } - else - { - $output['html'] .= ''; - } - } + // CSS files + foreach ($oRenderingOutput->GetCssFiles() as $sCssFile) + { + if ($sMode === static::ENUM_RENDER_MODE_EXPLODED) + { + if (!in_array($sCssFile, $output['css_files'])) + { + $output['css_files'][] = $sCssFile; + } + } + else + { + $output['html'] .= ''; + } + } + // CSS inline + if ($oRenderingOutput->GetCss() !== '') + { + if ($sMode === static::ENUM_RENDER_MODE_EXPLODED) + { + $output['css_inline'] .= ' ' . $oRenderingOutput->GetCss(); + } + else + { + $output['html'] .= ''; + } + } - // CSS files - foreach ($oRenderingOutput->GetCssFiles() as $sCssFile) - { - if ($sMode === static::ENUM_RENDER_MODE_EXPLODED) - { - if (!in_array($sCssFile, $output['css_files'])) - { - $output['css_files'][] = $sCssFile; - } - } - else - { - $output['html'] .= ''; - } - } - // CSS inline - if ($oRenderingOutput->GetCss() !== '') - { - if ($sMode === static::ENUM_RENDER_MODE_EXPLODED) - { - $output['css_inline'] .= ' ' . $oRenderingOutput->GetCss(); - } - else - { - $output['html'] .= ''; - } - } + return $output; + } - return $output; - } } diff --git a/sources/renderer/renderingoutput.class.inc.php b/sources/renderer/renderingoutput.class.inc.php index 8f816d101..2e002d497 100644 --- a/sources/renderer/renderingoutput.class.inc.php +++ b/sources/renderer/renderingoutput.class.inc.php @@ -26,153 +26,153 @@ namespace Combodo\iTop\Renderer; */ class RenderingOutput { - protected $sHtml; - protected $sJsInline; - protected $aJsFiles; - protected $sCssInline; - protected $aCssFiles; + protected $sHtml; + protected $sJsInline; + protected $aJsFiles; + protected $sCssInline; + protected $aCssFiles; - public function __construct() - { - $this->sHtml = ''; - $this->sJsInline = ''; - $this->aJsFiles = array(); - $this->sCssInline = ''; - $this->aCssFiles = array(); - } + public function __construct() + { + $this->sHtml = ''; + $this->sJsInline = ''; + $this->aJsFiles = array(); + $this->sCssInline = ''; + $this->aCssFiles = array(); + } - /** - * - * @return string - */ - public function GetHtml() - { - return $this->sHtml; - } + /** + * + * @return string + */ + public function GetHtml() + { + return $this->sHtml; + } - /** - * - * @return string - */ - public function GetJs() - { - return $this->sJsInline; - } + /** + * + * @return string + */ + public function GetJs() + { + return $this->sJsInline; + } - /** - * - * @return array - */ - public function GetJsFiles() - { - return $this->aJsFiles; - } + /** + * + * @return array + */ + public function GetJsFiles() + { + return $this->aJsFiles; + } - /** - * - * @return string - */ - public function GetCss() - { - return $this->sCssInline; - } + /** + * + * @return string + */ + public function GetCss() + { + return $this->sCssInline; + } - /** - * - * @return array - */ - public function GetCssFiles() - { - return $this->aCssFiles; - } + /** + * + * @return array + */ + public function GetCssFiles() + { + return $this->aCssFiles; + } - /** - * - * @param string $sHtml - * @return \Combodo\iTop\Renderer\RenderingOutput - */ - public function AddHtml($sHtml) - { - $this->sHtml .= $sHtml; - return $this; - } + /** + * + * @param string $sHtml + * @return \Combodo\iTop\Renderer\RenderingOutput + */ + public function AddHtml($sHtml) + { + $this->sHtml .= $sHtml; + return $this; + } - /** - * - * @param string $sJs - * @return \Combodo\iTop\Renderer\RenderingOutput - */ - public function AddJs($sJs) - { - $this->sJsInline .= $sJs . "\n"; - return $this; - } + /** + * + * @param string $sJs + * @return \Combodo\iTop\Renderer\RenderingOutput + */ + public function AddJs($sJs) + { + $this->sJsInline .= $sJs . "\n"; + return $this; + } - /** - * - * @param string $sFile - * @return \Combodo\iTop\Renderer\RenderingOutput - */ - public function AddJsFile($sFile) - { - if (!in_array($sFile, $this->aJsFiles)) - { - $this->aJsFiles[] = $sFile; - } - return $this; - } + /** + * + * @param string $sFile + * @return \Combodo\iTop\Renderer\RenderingOutput + */ + public function AddJsFile($sFile) + { + if (!in_array($sFile, $this->aJsFiles)) + { + $this->aJsFiles[] = $sFile; + } + return $this; + } - /** - * - * @param string $sFile - * @return \Combodo\iTop\Renderer\RenderingOutput - */ - public function RemoveJsFile($sFile) - { - if (in_array($sFile, $this->aJsFiles)) - { - unset($this->aJsFiles[$sFile]); - } - return $this; - } + /** + * + * @param string $sFile + * @return \Combodo\iTop\Renderer\RenderingOutput + */ + public function RemoveJsFile($sFile) + { + if (in_array($sFile, $this->aJsFiles)) + { + unset($this->aJsFiles[$sFile]); + } + return $this; + } - /** - * - * @param string $sCss - * @return \Combodo\iTop\Renderer\RenderingOutput - */ - public function AddCss($sCss) - { - $this->sCssInline .= $sCss . "\n"; - return $this; - } + /** + * + * @param string $sCss + * @return \Combodo\iTop\Renderer\RenderingOutput + */ + public function AddCss($sCss) + { + $this->sCssInline .= $sCss . "\n"; + return $this; + } - /** - * - * @param string $sFile - * @return \Combodo\iTop\Renderer\RenderingOutput - */ - public function AddCssFile($sFile) - { - if (!in_array($sFile, $this->aCssFiles)) - { - $this->aCssFiles[] = $sFile; - } - return $this; - } + /** + * + * @param string $sFile + * @return \Combodo\iTop\Renderer\RenderingOutput + */ + public function AddCssFile($sFile) + { + if (!in_array($sFile, $this->aCssFiles)) + { + $this->aCssFiles[] = $sFile; + } + return $this; + } - /** - * - * @param string $sFile - * @return \Combodo\iTop\Renderer\RenderingOutput - */ - public function RemoveCssFile($sFile) - { - if (in_array($sFile, $this->aCssFiles)) - { - unset($this->aCssFiles[$sFile]); - } - return $this; - } + /** + * + * @param string $sFile + * @return \Combodo\iTop\Renderer\RenderingOutput + */ + public function RemoveCssFile($sFile) + { + if (in_array($sFile, $this->aCssFiles)) + { + unset($this->aCssFiles[$sFile]); + } + return $this; + } }