Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
1682 lines (1531 sloc) 63.8 KB
<?php
/**
* LimeSurvey
* Copyright (C) 2007-2016 The LimeSurvey Project Team / Carsten Schmitz
* All rights reserved.
* License: GNU/GPL License v3 or later, see LICENSE.php
* LimeSurvey is free software. This version may have been modified pursuant
* to the GNU General Public License, and as distributed it includes or
* is derivative of works licensed under the GNU General Public License or
* other free or open source software licenses.
* See COPYRIGHT.php for copyright notices and details.
*
*/
namespace LimeSurvey\Helpers;
use QuestionAttribute;
use Yii;
/**
* General helper class for question + question setting system
*/
class questionHelper
{
/* @var array[]|null The question attribute definition for this LimeSurvey installation */
protected static $attributes;
/* @var array[] The question attribute (settings) by question type*/
protected static $questionAttributesSettings = array();
/**
* Return all the definitions of Question attributes core+extended value
* @return array[]
*/
public static function getAttributesDefinitions()
{
if (self::$attributes) {
return self::$attributes;
}
self::$attributes = array();
//For each question attribute include a key:
// name - the display name
// types - a string with one character representing each question typy to which the attribute applies
// help - a short explanation
// If you insert a new attribute please do it in correct alphabetical order!
// Please also list the new attribute in the function &TSVSurveyExport($sid) in em_manager_helper.php,
// so your new attribute will not be "forgotten" when the survey is exported to Excel/CSV-format!
// If you need to create a new attribute selector rendering for question advanced attribute
// Just add it to application/views/admin/survey/Question/advanced_settings_view
self::$attributes["alphasort"] = array(
"types"=>"!LOWZ",
'category'=>gT('Display'),
'sortorder'=>100,
'inputtype'=>'switch',
'options'=>array(
0=>gT('No'),
1=>gT('Yes')
),
'default'=>0,
"help"=>gT("Sort the answer options alphabetically"),
"caption"=>gT('Sort answers alphabetically'));
self::$attributes["answer_width"] = array(
"types"=>"ABCEF1:;",
'category'=>gT('Display'),
'sortorder'=>100,
'inputtype'=>'integer',
'min'=>'0',
'max'=>'100',
"help"=>gT('Set the percentage width of the (sub-)question column (1-100)'),
"caption"=>gT('(Sub-)question width')
);
self::$attributes["answer_width_bycolumn"] = array(
"types"=>"H",
'category'=>gT('Display'),
'sortorder'=>100,
'inputtype'=>'integer',
'min'=>'0',
'max'=>'100',
"help"=>gT('Set the percentage width of the answers column (1-100)'),
"caption"=>gT('Answers column width')
);
self::$attributes["repeat_headings"] = array(
"types"=>"F:1;",
'category'=>gT('Display'),
'sortorder'=>100,
'inputtype'=>'integer',
'default'=>'',
"help"=>gT('Repeat answer options every X subquestions (Set to 0 to deactivate answer options repeat, deactivate minimum answer options repeat from config).'),
"caption"=>gT('Repeat answer options')
);
self::$attributes["array_filter"] = array(
"types"=>"1ABCEF:;MPLKQR",
'category'=>gT('Logic'),
'sortorder'=>100,
'inputtype'=>'text',
"help"=>gT("Enter the code(s) of Multiple choice question(s) (separated by semicolons) to only show the matching answer options in this question."),
"caption"=>gT('Array filter')
);
self::$attributes["array_filter_exclude"] = array(
"types"=>"1ABCEF:;MPLKQR",
'category'=>gT('Logic'),
'sortorder'=>100,
'inputtype'=>'text',
"help"=>gT("Enter the code(s) of Multiple choice question(s) (separated by semicolons) to exclude the matching answer options in this question."),
"caption"=>gT('Array filter exclusion')
);
self::$attributes["array_filter_style"] = array(
"types"=>"1ABCEF:;MPLKQR",
'category'=>gT('Logic'),
'sortorder'=>100,
'inputtype'=>'buttongroup',
'options'=>array(0=>gT('Hidden', 'unescaped'),
1=>gT('Disabled', 'unescaped')),
'default'=>0,
"help"=>gT("Specify how array-filtered subquestions should be displayed"),
"caption"=>gT('Array filter style')
);
self::$attributes["assessment_value"] = array(
"types"=>"MP",
'category'=>gT('Logic'),
'sortorder'=>100,
'default'=>'1',
'inputtype'=>'integer',
"help"=>gT("If one of the subquestions is marked then for each marked subquestion this value is added as assessment."),
"caption"=>gT('Assessment value')
);
self::$attributes["category_separator"] = array(
"types"=>"!",
'category'=>gT('Display'),
'sortorder'=>100,
'inputtype'=>'text',
"help"=>gT('Category separator'),
"caption"=>gT('Category separator')
);
self::$attributes["code_filter"] = array(
"types"=>"WZ",
'category'=>gT('Logic'),
'sortorder'=>100,
'inputtype'=>'text',
"help"=>gT('Filter the available answers by this value'),
"caption"=>gT('Code filter')
);
self::$attributes["commented_checkbox"] = array(
"types"=>"P",
'category'=>gT('Logic'),
'sortorder'=>110,
'inputtype'=>'singleselect',
'options'=>array(
"allways"=>gT('No control on checkbox'),
"checked"=>gT('Checkbox is checked'),
"unchecked"=>gT('Checkbox is unchecked'),
),
'default' => "checked",
'help'=>gT('Choose when user can add a comment'),
'caption'=>gT('Comment only when')
);
self::$attributes["commented_checkbox_auto"] = array(
"types"=>"P",
'category'=>gT('Logic'),
'sortorder'=>111,
'inputtype'=>'switch',
'options'=>array(
"0"=>gT('No'),
"1"=>gT('Yes'),
),
'default' => "1",
'help'=>gT('Use javascript function to remove text and uncheck checkbox (or use Expression Manager only).'),
'caption'=>gT('Remove text or uncheck checkbox automatically')
);
self::$attributes["display_columns"] = array(
"types"=>"LM",
'category'=>gT('Display'),
'sortorder'=>100,
'inputtype'=>'columns',
'default'=>'',
"help"=>gT('The answer options will be distributed across the number of columns set here'),
"caption"=>gT('Display columns')
);
self::$attributes["display_rows"] = array(
"types"=>"QSTU",
'category'=>gT('Display'),
'sortorder'=>100,
'inputtype'=>'integer',
"help"=>gT('How many rows to display'),
"caption"=>gT('Display rows')
);
self::$attributes["dropdown_dates"] = array(
"types"=>"D",
'category'=>gT('Display'),
'sortorder'=>100,
'inputtype'=>'switch',
'options'=>array(0=>gT('No'),
1=>gT('Yes')),
'default'=>0,
"help"=>gT('Use accessible dropdown boxes instead of calendar popup'),
"caption"=>gT('Display dropdown boxes')
);
self::$attributes["date_min"] = array(
"types"=>"D",
'category'=>gT('Display'),
'sortorder'=>110,
'inputtype'=>'text',
'expression'=>2, /* What for "tomorrow" etc ....*/
"help"=>gT('Minimum date, valide date in YYYY-MM-DD format or any English textual datetime description. Expression Managed can be used (only with YYYY-MM-DD format). For dropdown : only the year is restricted if date use variable not in same page.'),
"caption"=>gT('Minimum date')
);
self::$attributes["date_max"] = array(
"types"=>"D",
'category'=>gT('Display'),
'sortorder'=>111,
'inputtype'=>'text',
'expression'=>2,
"help"=>gT('Maximum date, valide date in any English textual datetime description (YYYY-MM-DD for example). Expression Managed can be used (only with YYYY-MM-DD format) value. For dropdown : only the year is restricted if date use variable not in same page.'),
"caption"=>gT('Maximum date')
);
self::$attributes["dropdown_prepostfix"] = array(
"types"=>"1",
'category'=>gT('Display'),
'sortorder'=>112,
'inputtype'=>'text',
'i18n'=>true,
"help"=>gT('Prefix|Suffix for dropdown lists'),
"caption"=>gT('Dropdown prefix/suffix')
);
self::$attributes["dropdown_separators"] = array(
"types"=>"1",
'category'=>gT('Display'),
'sortorder'=>120,
'inputtype'=>'text',
"help"=>gT('Text shown on each subquestion row between both scales in dropdown mode'),
"caption"=>gT('Dropdown separator')
);
self::$attributes["dualscale_headerA"] = array(
"types"=>"1",
'category'=>gT('Display'),
'sortorder'=>110,
'inputtype'=>'text',
'expression'=>1,
'i18n'=>true,
"help"=>gT('Enter a header text for the first scale'),
"caption"=>gT('Header for first scale')
);
self::$attributes["dualscale_headerB"] = array(
"types"=>"1",
'category'=>gT('Display'),
'sortorder'=>111,
'inputtype'=>'text',
'expression'=>1,
'i18n'=>true,
"help"=>gT('Enter a header text for the second scale'),
"caption"=>gT('Header for second scale')
);
self::$attributes["equation"] = array(
"types"=>"*",
'category'=>gT('Logic'),
'sortorder'=>100,
'inputtype'=>'textarea',
'expression'=>1,
"help"=>gT('Final equation to set in database, defaults to question text.'),
"caption"=>gT('Equation'),
"default"=>""
);
self::$attributes["equals_num_value"] = array(
"types"=>"K",
'category'=>gT('Input'),
'sortorder'=>100,
'inputtype'=>'text',
'expression'=>2,
"help"=>gT('Multiple numeric inputs sum must equal this value'),
"caption"=>gT('Equals sum value')
);
self::$attributes["em_validation_q"] = array(
"types"=>":;ABCDEFHKMNOPQRSTU"."L!", // separate question with REAL subqs (in EM) and with FALSE subsq (where subqs are answer …)
'category'=>gT('Logic'),
'sortorder'=>200,
'inputtype'=>'textarea',
'expression'=>2,
"help"=>gT('Enter a boolean equation to validate the whole question.'),
"caption"=>gT('Question validation equation')
);
self::$attributes["em_validation_q_tip"] = array(
"types"=>":;ABCDEFHKMNOPQRSTU"."L!", // separate question with subqs (in EM) and without
'category'=>gT('Logic'),
'sortorder'=>210,
'inputtype'=>'textarea',
'expression'=>1,
'i18n'=>true,
"help"=>gT('This is a hint text that will be shown to the participant describing the question validation equation.'),
"caption"=>gT('Question validation tip')
);
self::$attributes["em_validation_sq"] = array(
"types"=>";:KQSTUN",
'category'=>gT('Logic'),
'sortorder'=>220,
'inputtype'=>'textarea',
'expression'=>2,
"help"=>gT('Enter a boolean equation to validate each subquestion.'),
"caption"=>gT('Subquestion validation equation')
);
self::$attributes["em_validation_sq_tip"] = array(
"types"=>";:KQSTUN",
'category'=>gT('Logic'),
'sortorder'=>230,
'inputtype'=>'textarea',
'expression'=>1,
'i18n'=>true,
"help"=>gT('This is a tip shown to the participant describing the subquestion validation equation.'),
"caption"=>gT('Subquestion validation tip')
);
self::$attributes["exclude_all_others"] = array(
"types"=>"ABCEFMPKQ",
'category'=>gT('Logic'),
'sortorder'=>130,
'inputtype'=>'text',
"help"=>gT('Excludes all other options if a certain answer is selected - just enter the answer code(s) separated with a semicolon.'),
"caption"=>gT('Exclusive option')
);
self::$attributes["exclude_all_others_auto"] = array(
"types"=>"MP",
'category'=>gT('Logic'),
'sortorder'=>131,
'inputtype'=>'switch',
'options'=>array(1=>gT('Yes'), 0=>gT('No')),
'default'=>0,
"help"=>gT('If the participant marks all options, uncheck all and check the option set in the "Exclusive option" setting'),
"caption"=>gT('Auto-check exclusive option if all others are checked')
);
// Map Options
self::$attributes["location_city"] = array(
"types"=>"S",
'readonly_when_active'=>true,
'category'=>gT('Location'),
'sortorder'=>100,
'inputtype'=>'singleselect',
'default'=>0,
'options'=>array(1=>gT('Yes'), 0=>gT('No')),
"help"=>gT("Store the city?"),
"caption"=>gT("Save city")
);
self::$attributes["location_state"] = array(
"types"=>"S",
'readonly_when_active'=>true,
'category'=>gT('Location'),
'sortorder'=>100,
'default'=>0,
'inputtype'=>'singleselect',
'options'=>array(1=>gT('Yes'), 0=>gT('No')),
"help"=>gT("Store the state?"),
"caption"=>gT("Save state")
);
self::$attributes["location_postal"] = array(
"types"=>"S",
'readonly_when_active'=>true,
'category'=>gT('Location'),
'sortorder'=>100,
'inputtype'=>'singleselect',
'default'=>0,
'options'=>array(1=>gT('Yes'), 0=>gT('No')),
"help"=>gT("Store the postal code?"),
"caption"=>gT("Save postal code")
);
self::$attributes["location_country"] = array(
"types"=>"S",
'readonly_when_active'=>true,
'category'=>gT('Location'),
'sortorder'=>100,
'inputtype'=>'singleselect',
'default'=>0,
'options'=>array(1=>gT('Yes'), 0=>gT('No')),
"help"=>gT("Store the country?"),
"caption"=>gT("Save country")
);
self::$attributes["statistics_showmap"] = array(
"types"=>"S",
'category'=>gT('Statistics'),
'inputtype'=>'switch',
'sortorder'=>100,
'options'=>array(1=>gT('Yes'), 0=>gT('No')),
'help'=>gT("Show a map in the statistics?"),
'caption'=>gT("Display map"),
'default'=>1
);
self::$attributes["statistics_showgraph"] = array(
'types'=>'15ABCDEFGHIKLMNOPQRSTUWXYZ!:;|*',
'category'=>gT('Statistics'),
'inputtype'=>'switch',
'sortorder'=>101,
'options'=>array(1=>gT('Yes'), 0=>gT('No')),
'help'=>gT("Display a chart in the statistics?"),
'caption'=>gT("Display chart"),
'default'=>1
);
self::$attributes["statistics_graphtype"] = array(
"types"=>'15ABCDEFGHIKLMNOQRSTUWXYZ!:;|*',
'category'=>gT('Statistics'),
'inputtype'=>'singleselect',
'sortorder'=>102,
'options'=>array(
0=>gT('Bar chart'),
1=>gT('Pie chart'),
2=>gT('Radar'),
3=>gT('Line'),
4=>gT('PolarArea'),
5=>gT('Doughnut'),
),
'help'=>gT("Select the type of chart to be displayed"),
'caption'=>gT("Chart type"),
'default'=>0
);
self::$attributes["location_mapservice"] = array(
"types"=>"S",
'category'=>gT('Location'),
'sortorder'=>90,
'inputtype'=>'buttongroup',
'options'=>array(
0=>gT('Off'),
100=>gT('OpenStreetMap via MapQuest', 'unescaped'),
1=>gT('Google Maps', 'unescaped')
),
'default' => 0,
"help"=>gT("Activate this to show a map above the input field where the user can select a location"),
"caption"=>gT("Use mapping service")
);
self::$attributes["location_mapwidth"] = array(
"types"=>"S",
'category'=>gT('Location'),
'sortorder'=>102,
'inputtype'=>'text',
'default'=>'500',
"help"=>gT("Map width in pixel"),
"caption"=>gT("Map width")
);
self::$attributes["location_mapheight"] = array(
"types"=>"S",
'category'=>gT('Location'),
'sortorder'=>103,
'inputtype'=>'text',
'default'=>'300',
"help"=>gT("Map height in pixel"),
"caption"=>gT("Map height")
);
self::$attributes["location_nodefaultfromip"] = array(
"types"=>"S",
'category'=>gT('Location'),
'sortorder'=>91,
'inputtype'=>'singleselect',
'options'=>array(0=>gT('Yes'), 1=>gT('No')),
'default' => 0,
"help"=>gT("Get the default location using the user's IP address?"),
"caption"=>gT("IP as default location")
);
self::$attributes["location_defaultcoordinates"] = array(
"types"=>"S",
'category'=>gT('Location'),
'sortorder'=>101,
'inputtype'=>'text',
'expression'=>1,/* As static */
"help"=>gT('Default coordinates of the map when the page first loads. Format: latitude [space] longtitude'),
"caption"=>gT('Default position')
);
self::$attributes["location_mapzoom"] = array(
"types"=>"S",
'category'=>gT('Location'),
'sortorder'=>101,
'inputtype'=>'text',
'default'=>'11',
"help"=>gT("Map zoom level"),
"caption"=>gT("Zoom level")
);
// End Map Options
self::$attributes["hide_tip"] = array(
"types"=>"15ABCDEFGHIKLMNOPQRSTUXY!:;|",
'category'=>gT('Display'),
'sortorder'=>100,
'inputtype'=>'switch',
'options'=>array(0=>gT('No'), 1=>gT('Yes')),
'default'=>0,
"help"=>gT('Hide the tip that is normally shown with a question'),
"caption"=>gT('Hide tip')
);
self::$attributes['hidden'] = array(
'types'=>'15ABCDEFGHIKLMNOPQRSTUWXYZ!:;|*',
'category'=>gT('Display'),
'sortorder'=>101,
'inputtype'=>'switch',
'options'=>array(0=>gT('No'), 1=>gT('Yes')),
'default'=>0,
'help'=>gT('Hide this question at any time. This is useful for including data using answer prefilling.'),
'caption'=>gT('Always hide this question')
);
self::$attributes['cssclass'] = array(
'types'=>'15ABCDEFGHIKLMNOPQRSTUWXYZ!:;|*',
'category'=>gT('Display'),
'sortorder'=>102,
'inputtype'=>'text',
'expression'=>1, /* As static */
'help'=>gT('Add additional CSS class(es) for this question. Use a space between multiple CSS class names. You may use expressions - remember this part is static.'),
'caption'=>gT('CSS class(es)')
);
self::$attributes["max_answers"] = array(
"types"=>"MPR1:;ABCEFKQ",
'category'=>gT('Logic'),
'sortorder'=>11,
'inputtype'=>'text',
'expression'=>2,
"help"=>gT('Limit the number of possible answers'),
"caption"=>gT('Maximum answers')
);
self::$attributes["max_num_value"] = array(
"types"=>"K",
'category'=>gT('Input'),
'sortorder'=>100,
'inputtype'=>'text',
'expression'=>2,
"help"=>gT('Maximum sum value of multiple numeric input'),
"caption"=>gT('Maximum sum value')
);
self::$attributes["max_num_value_n"] = array(
"types"=>"NK",
'category'=>gT('Input'),
'sortorder'=>110,
'inputtype'=>'text',
'expression'=>2,
"help"=>gT('Maximum value of the numeric input'),
"caption"=>gT('Maximum value')
);
/* Ranking specific : max DB answer */
self::$attributes["max_subquestions"] = array(
"types"=>"R",
'readonly_when_active'=>true,
'category'=>gT('Logic'),
'sortorder'=>12,
'inputtype'=>'integer',
'default'=>'',
"help"=>gT('Limit the number of possible answers fixed by number of columns in database'),
"caption"=>gT('Maximum columns for answers')
);
self::$attributes["maximum_chars"] = array(
"types"=>"STUNQK:;",
'category'=>gT('Input'),
'sortorder'=>100,
'inputtype'=>'integer',
'default'=>'',
"help"=>gT('Maximum characters allowed'),
"caption"=>gT('Maximum characters')
);
self::$attributes["min_answers"] = array(
"types"=>"MPR1:;ABCEFKQ",
'category'=>gT('Logic'),
'sortorder'=>10,
'inputtype'=>'text',
'expression'=>2,
"help"=>gT('Ensure a minimum number of possible answers (0=No limit)'),
"caption"=>gT('Minimum answers')
);
self::$attributes["min_num_value"] = array(
"types"=>"K",
'category'=>gT('Input'),
'sortorder'=>100,
'inputtype'=>'text',
'expression'=>2,
"help"=>gT('The sum of the multiple numeric inputs must be greater than this value'),
"caption"=>gT('Minimum sum value')
);
self::$attributes["min_num_value_n"] = array(
"types"=>"NK",
'category'=>gT('Input'),
'sortorder'=>100,
'inputtype'=>'text',
'expression'=>2,
"help"=>gT('Minimum value of the numeric input'),
"caption"=>gT('Minimum value')
);
self::$attributes["multiflexible_max"] = array(
"types"=>":",
'category'=>gT('Display'),
'sortorder'=>112,
'inputtype'=>'text',
'expression'=>2, // Really ? Only if shown as text then
"help"=>gT('Maximum value for array(mult-flexible) question type'),
"caption"=>gT('Maximum value')
);
self::$attributes["multiflexible_min"] = array(
"types"=>":",
'category'=>gT('Display'),
'sortorder'=>110,
'inputtype'=>'text',
'expression'=>2, // Really ? Only if shown as text then
"help"=>gT('Minimum value for array(multi-flexible) question type'),
"caption"=>gT('Minimum value')
);
self::$attributes["multiflexible_step"] = array(
"types"=>":",
'category'=>gT('Display'),
'sortorder'=>111,
'inputtype'=>'float',
'default'=>'',
"help"=>gT('Step value'),
"caption"=>gT('Step value')
);
self::$attributes["multiflexible_checkbox"] = array(
"types"=>":",
'category'=>gT('Display'),
'sortorder'=>100,
'inputtype'=>'switch',
'options'=>array(0=>gT('No'), 1=>gT('Yes')),
'default'=>0,
"help"=>gT('Use checkbox layout'),
"caption"=>gT('Checkbox layout')
);
self::$attributes["reverse"] = array(
"types"=>"D:",
'category'=>gT('Display'),
'sortorder'=>100,
'inputtype'=>'switch',
'options'=>array(0=>gT('No'), 1=>gT('Yes')),
'default'=>0,
"help"=>gT('Present answer options in reverse order'),
"caption"=>gT('Reverse answer order')
);
self::$attributes["num_value_int_only"] = array(
"types"=>"NK",
'category'=>gT('Input'),
'sortorder'=>100,
'inputtype'=>'switch',
'options'=>array(0=>gT('No'), 1=>gT('Yes')),
'default'=>0,
"help"=>gT('Restrict input to integer values'),
"caption"=>gT('Integer only')
);
self::$attributes["numbers_only"] = array(
"types"=>"Q;S*",
'category'=>gT('Other'),
'sortorder'=>150,
'inputtype'=>'switch',
'options'=>array(0=>gT('No'), 1=>gT('Yes')),
'default'=>0,
"help"=>gT('Allow only numerical input'),
"caption"=>gT('Numbers only')
);
self::$attributes['show_totals'] = array(
'types' => ';',
'category' => gT('Other'),
'sortorder' => 151,
'inputtype' => 'buttongroup',
'options' => array(
'X' => gT('Off', 'unescaped'),
'R' => gT('Rows', 'unescaped'),
'C' => gT('Columns', 'unescaped'),
'B' => gT('Rows & columns', 'unescaped')
),
'default' => 'X',
'help' => gT('Show totals for either rows, columns or both rows and columns'),
'caption' => gT('Show totals for')
);
self::$attributes['show_grand_total'] = array(
'types' => ';',
'category' => gT('Other'),
'sortorder' => 152,
'inputtype' => 'switch',
'options' =>array(0=>gT('No'), 1=>gT('Yes')),
'default' => 0,
'help' => gT('Show grand total for either columns or rows'),
'caption' => gT('Show grand total')
);
self::$attributes["input_size"] = array(
"types"=>"STUQNMK:;",
'category'=>gT('Display'),
'sortorder'=>100,
'inputtype'=>'integer',
'default'=>'',
"help"=>gT("Set the size to the input or textarea, the input will be displayed with approximately this size in width."),
"caption"=>gT("Text input size")
);
self::$attributes["input_boxes"] = array(
"types"=>":",
'category'=>gT('Display'),
'sortorder'=>110,
'inputtype'=>'switch',
'options'=>array(0=>gT('No'), 1=>gT('Yes')),
'default'=>0,
"help"=>gT("Present as text input boxes instead of dropdown lists"),
"caption"=>gT("Text inputs")
);
self::$attributes["other_comment_mandatory"] = array(
"types"=>"PLW!Z",
'category'=>gT('Logic'),
'sortorder'=>100,
'inputtype'=>'switch',
'options'=>array(0=>gT('No'), 1=>gT('Yes')),
'default'=>0,
"help"=>gT("Make the 'Other:' comment field mandatory when the 'Other:' option is active"),
"caption"=>gT("'Other:' comment mandatory")
);
self::$attributes["other_numbers_only"] = array(
"types"=>"LMP",
'category'=>gT('Logic'),
'sortorder'=>100,
'inputtype'=>'switch',
'options'=>array(0=>gT('No'), 1=>gT('Yes')),
'default'=>0,
"help"=>gT("Allow only numerical input for 'Other' text"),
"caption"=>gT("Numbers only for 'Other'")
);
self::$attributes["other_replace_text"] = array(
"types"=>"LMPWZ!",
'category'=>gT('Display'),
'sortorder'=>100,
'inputtype'=>'text',
'expression'=>1,
'i18n'=>true,
"help"=>gT("Replaces the label of the 'Other:' answer option with a custom text"),
"caption"=>gT("Label for 'Other:' option")
);
self::$attributes["page_break"] = array(
"types"=>"15ABCDEFGHKLMNOPQRSTUWXYZ!:;|*",
'category'=>gT('Other'),
'sortorder'=>100,
'inputtype'=>'switch',
'options'=>array(0=>gT('No'), 1=>gT('Yes')),
'default'=>0,
"help"=>gT('Insert a page break before this question in printable view by setting this to Yes.'),
"caption"=>gT('Insert page break in printable view')
);
self::$attributes["prefix"] = array(
"types"=>"KNQS",
'category'=>gT('Display'),
'sortorder'=>10,
'inputtype'=>'text',
'expression'=>1,
'i18n'=>true,
"help"=>gT('Add a prefix to the answer field'),
"caption"=>gT('Answer prefix')
);
self::$attributes["printable_help"] = array(
"types"=>"15ABCDEFGHKLMNOPRWYZ!:*",
'category'=>gT('Display'),
'sortorder'=>201,
"inputtype"=>"text",
'expression'=>1, // Must control if yes
'i18n'=>true,
'default'=>"",
"help"=>gT('In the printable version replace the relevance equation with this explanation text.'),
"caption"=>gT("Relevance help for printable survey")
);
self::$attributes["public_statistics"] = array(
"types"=>"15ABCEFGHKLMNOPRWYZ!:*",
'category'=>gT('Statistics'),
'sortorder'=>80,
'inputtype'=>'switch',
'options'=>array(0=>gT('No'), 1=>gT('Yes')),
'default'=>0,
"help"=>gT('Show statistics of this question in the public statistics page'),
"caption"=>gT('Show in public statistics')
);
self::$attributes["random_order"] = array(
"types"=>"!ABCEFHKLMOPQRWZ1:;",
'category'=>gT('Display'),
'sortorder'=>100,
'inputtype'=>'singleselect',
'options'=>array(0=>gT('No'), 1=>gT("Yes")),
//1=>gT('Randomize on each page load') // Shnoulle : replace by yes till we have only one solution
//2=>gT('Randomize once on survey start') //Mdekker: commented out as code to handle this was removed in refactoring
'default'=>0,
"help"=>gT('Present subquestions/answer options in random order'),
"caption"=>gT('Random order')
);
self::$attributes["showpopups"] = array(
"types"=>"R",
'category'=>gT('Display'),
'sortorder'=>110,
'inputtype'=>'switch',
'options'=>array(0=>gT('No'), 1=>gT('Yes')),
'default'=>1,
"caption"=>gT('Show javascript alert'),
"help"=>gT('Show an alert if answers exceeds the number of max answers')
);
self::$attributes["samechoiceheight"] = array(
"types"=>"R",
'category'=>gT('Display'),
'sortorder'=>120,
'inputtype'=>'switch',
'options'=>array(0=>gT('No'), 1=>gT('Yes')),
'default'=>1,
"caption"=>gT('Same height for all answer options'),
"help"=>gT('Force each answer option to have the same height.').' '.gT('If you have a lot of items and use a filter you can disable this to improve browser speed.')
);
self::$attributes["samelistheight"] = array(
"types"=>"R",
'category'=>gT('Display'),
'sortorder'=>121,
'inputtype'=>'switch',
'options'=>array(0=>gT('No'), 1=>gT('Yes')),
'default'=>1,
"caption"=>gT('Same height for lists'),
"help"=>gT('Force the choice list and the rank list to have the same height.').' '.gT('If you have a lot of items and use a filter you can disable this to improve browser speed.')
);
self::$attributes["parent_order"] = array(
"types"=>":",
'category'=>gT('Display'),
'sortorder'=>100,
'inputtype'=>'text',
"caption"=>gT('Get order from previous question'),
"help"=>gT('Enter question ID to get subquestion order from a previous question')
);
self::$attributes["slider_layout"] = array(
"types"=>"K",
'category'=>gT('Slider'),
'sortorder'=>100,
'inputtype'=>'switch',
'options'=>array(0=>gT('No'), 1=>gT('Yes')),
'default'=>0,
"help"=>gT('Use slider layout'),
"caption"=>gT('Use slider layout')
);
self::$attributes["slider_min"] = array(
"types"=>"K",
'category'=>gT('Slider'),
'sortorder'=>110,
'inputtype'=>'text',
'expression'=>2,
"help"=>gT('You can use Expression manager, but this must be a number before showing the page else set to 0. If minimum value is not set, this value is used.'),
"caption"=>gT('Slider minimum value')
);
self::$attributes["slider_max"] = array(
"types"=>"K",
'category'=>gT('Slider'),
'sortorder'=>120,
'inputtype'=>'text',
'expression'=>2,
"help"=>gT('You can use Expression manager, but this must be a number before showing the page else set to 100. If maximum value is not set, this value is used.'),
"caption"=>gT('Slider maximum value')
);
self::$attributes["slider_accuracy"] = array(
"types"=>"K",
'category'=>gT('Slider'),
'sortorder'=>130,
'inputtype'=>'text',
'expression'=>2,
"help"=>gT('You can use Expression manager, but this must be a number before showing the page else set to 1.'),
"caption"=>gT('Slider accuracy')
);
self::$attributes["slider_middlestart"] = array(
"types"=>"K",
'category'=>gT('Slider'),
'sortorder'=>200,
'inputtype'=>'switch',
'options'=>array(0=>gT('No'), 1=>gT('Yes')),
'default'=>0,
"help"=>gT('The handle is displayed at the middle of the slider except if Slider initial value is set (this will not set the initial value).'),
"caption"=>gT('Slider starts at the middle position')
);
self::$attributes["slider_default"] = array(
"types"=>"K",
'category'=>gT('Slider'),
'sortorder'=>210,
'inputtype'=>'text',
'expression'=>2, // must be controlled : unsure
'default'=>"",
"help"=>gT('Slider start as this value. You can use Expression manager, but this must be a number before showing the page. This setting has priority over slider starts at the middle position.'),
"caption"=>gT('Slider initial value')
);
self::$attributes["slider_default_set"] = array(
"types"=>"K",
'category'=>gT('Slider'),
'sortorder'=>220,
'inputtype'=>'switch',
'options'=>array(0=>gT('No'), 1=>gT('Yes')),
'default'=>1, /* before 3.0 : this is the default behaviour */
"help"=>gT('When using slider initial value set this value at survey start.'),
"caption"=>gT('Slider initial value set at start')
);
self::$attributes["slider_orientation"] = array(
"types"=>"K",
'category'=>gT('Slider'),
'sortorder'=>300,
'inputtype'=>'buttongroup',
'options'=>array(
0=>gT('Horizontal', 'unescaped'),
1=>gT('Vertical', 'unescaped')
),
'default'=>0,
"help"=>gT('Set the orientation.'),
"caption"=>gT('Orientation')
);
self::$attributes["slider_handle"] = array(
"types"=>"K",
'category'=>gT('Slider'),
'sortorder'=>320,
'inputtype'=>'singleselect',
'options'=>array(
0=>gT('Circle'),
1=>gT('Square'),
2=>gT('Triangle'),
3=>gT('Custom')
),
'default'=>0,
"help"=>gT("Set the handle shape. 'Custom' is defined in CSS using the Font Awesome font."),
"caption"=>gT('Handle shape')
);
self::$attributes["slider_custom_handle"] = array(
"types"=>"K",
'category'=>gT('Slider'),
'sortorder'=>321,
'inputtype'=>'text',
'default'=>'f1ae',
"help"=>gT('Accepts Font Awesome Unicode characters.'),
"caption"=>gT('Custom handle Unicode code')
);
self::$attributes["slider_rating"] = array(
"types"=>"5",
'category'=>gT('Display'),
'sortorder'=>90,
'inputtype'=>'buttongroup',
'options'=>array(
0=>gT('Off', 'unescaped'),
1=>gT('Stars', 'unescaped'),
2=>gT('Slider with emoticon', 'unescaped'),
),
'default'=>0,
"help"=>gT('Use slider layout'),
"caption"=>gT('Use slider layout')
);
self::$attributes["slider_reversed"] = array(
"types"=>"K",
'category'=>gT('Slider'),
'sortorder'=>310,
'inputtype'=>'switch',
'options'=>array(0=>gT('No'), 1=>gT('Yes')),
'default'=>0,
"help"=>gT('Reverses the slider direction and repositions the min/max text accordingly.'),
"caption"=>gT('Reverse the slider direction')
);
self::$attributes["slider_reset"] = array(
"types"=>"K",
'category'=>gT('Slider'),
'sortorder'=>230,
'inputtype'=>'switch',
'options'=>array(0=>gT('No'), 1=>gT('Yes')),
'default'=>0,
"help"=>gT('Add a button to reset the slider. If you choose an start value, it reset at start value, else empty the answer.'),
"caption"=>gT('Allow reset the slider')
);
self::$attributes["slider_showminmax"] = array(
"types"=>"K",
'category'=>gT('Slider'),
'sortorder'=>150,
'inputtype'=>'switch',
'options'=>array(0=>gT('No'), 1=>gT('Yes')),
'default'=>0,
"help"=>gT('Display min and max value under the slider'),
"caption"=>gT('Display slider min and max value')
);
self::$attributes["slider_separator"] = array(
"types"=>"K",
'category'=>gT('Slider'),
'sortorder'=>160,
'inputtype'=>'text',
"help"=>gT('Answer|Left-slider-text|Right-slider-text separator character'),
'default'=>'|',
"caption"=>gT('Slider left/right text separator')
);
self::$attributes["suffix"] = array(
"types"=>"KNQS",
'category'=>gT('Display'),
'sortorder'=>11,
'inputtype'=>'text',
'expression'=>1,
'i18n'=>true,
"help"=>gT('Add a suffix to the answer field'),
"caption"=>gT('Answer suffix')
);
self::$attributes["text_input_width"] = array(
"types"=>"KNSTU",
'category'=>gT('Display'),
'sortorder'=>100,
'inputtype'=>'singleselect',
'default'=>'',
'options'=>array(
''=>gT("Default"),
1=>'8%',
2=>'17%',
3=>'25%',
4=>'33%',
5=>'41%',
6=>'50%',
7=>'58%',
8=>'67%',
9=>'75%',
10=>'83%',
11=>'92%',
12=>'100%'
),
"help"=>gT('Relative width of the text input wrapper element'),
"caption"=>gT('Text input box width'));
/* Do EXACTLY the same than text_input_width for K(multinum): must move K here and rename in a DB update and remove it + fix when import*/
self::$attributes["text_input_columns"] = array(
"types"=>"QP",
'category'=>gT('Display'),
'sortorder'=>90,
'inputtype'=>'singleselect',
'default'=>'',
'options'=>array(
''=>gT("Default"),
1=>'8%',
2=>'17%',
3=>'25%',
4=>'33%',
5=>'41%',
6=>'50%',
7=>'58%',
8=>'67%',
9=>'75%',
10=>'83%',
11=>'92%',
12=>'100%'
),
"help"=>gT('Relative width of the text input wrapper element'),
"caption"=>gT('Text input box width'));
self::$attributes["label_input_columns"] = array(
"types"=>"KQ",
'category'=>gT('Display'),
'sortorder'=>91,
'inputtype'=>'singleselect',
'default'=>'',
'options'=>array(
''=>gT("Default"),
'hidden'=>gT("Hidden"), /* can not use 0, sometimes we don't test with === */
1=>'8%',
2=>'17%',
3=>'25%',
4=>'33%',
5=>'41%',
6=>'50%',
7=>'58%',
8=>'67%',
9=>'75%',
10=>'83%',
11=>'92%',
12=>'100%'
),
"help"=>gT('Relative width of the labels'),
"caption"=>gT('Label column width'));
/* Same than label_input_columns for multiple choice*/
self::$attributes["choice_input_columns"] = array(
"types"=>"P",
'category'=>gT('Display'),
'sortorder'=>90,
'inputtype'=>'singleselect',
'default'=>'',
'options'=>array(
''=>gT("Default"),
1=>'8%',
2=>'17%',
3=>'25%',
4=>'33%',
5=>'41%',
6=>'50%',
7=>'58%',
8=>'67%',
9=>'75%',
10=>'83%',
11=>'92%',
12=>'100%'
),
"help"=>gT('Relative width of checkbox wrapper element'),
"caption"=>gT('Choice column width'));
self::$attributes["use_dropdown"] = array(
"types"=>"1FO",
'category'=>gT('Display'),
'sortorder'=>112,
'inputtype'=>'switch',
'options'=>array(0=>gT('No'), 1=>gT('Yes')),
'default'=>0,
"help"=>gT('Present dropdown control(s) instead of list of radio buttons'),
"caption"=>gT('Use dropdown presentation')
);
self::$attributes["dropdown_size"] = array(
"types"=>"!", // TODO add these later? "1F",
'category'=>gT('Display'),
'sortorder'=>200,
'inputtype'=>'text',
'default'=>'',
"help"=>gT('For list dropdown boxes, show up to this many rows'),
"caption"=>gT('Height of dropdown')
);
self::$attributes["dropdown_prefix"] = array(
"types"=>"!", // TODO add these later? "1F",
'category'=>gT('Display'),
'sortorder'=>201,
'inputtype'=>'buttongroup',
'options'=>array(
0=>gT('None', 'unescaped'),
1=>gT('Order - like 3)', 'unescaped'),
// 2=>gT('Code - like A1','unescaped'), // Just an idea ;)
),
'default'=>0,
"help"=>gT('Accelerator keys for list items'),
"caption"=>gT('Prefix for list items')
);
self::$attributes["scale_export"] = array(
"types"=>"CEFGHLMOPWYZ1!:*",
'category'=>gT('Other'),
'sortorder'=>100,
'inputtype'=>'singleselect',
'options'=>array(0=>gT('Default'),
1=>gT('Nominal'),
2=>gT('Ordinal'),
3=>gT('Scale')),
'default'=>0,
"help"=>gT("Set a specific SPSS export scale type for this question"),
"caption"=>gT('SPSS export scale type')
);
self::$attributes["choice_title"] = array(
"types"=>"R",
'category'=>gT('Other'),
'sortorder'=>200,
"inputtype"=>"text",
'expression'=>1,
'i18n'=>true,
'default'=>"",
"help"=>sprintf(gT("Replace choice header (default: \"%s\")"), gT("Your choices")),
"caption"=>gT("Choice header")
);
self::$attributes["rank_title"] = array(
"types"=>"R",
'category'=>gT('Other'),
'sortorder'=>201,
"inputtype"=>"text",
'expression'=>1,
'i18n'=>true,
'default'=>"",
"help"=>sprintf(gT("Replace rank header (default: \"%s\")"), gT("Your ranking")),
"caption"=>gT("Rank header")
);
//Timer attributes
self::$attributes["time_limit"] = array(
"types"=>"STUXL!",
'category'=>gT('Timer'),
'sortorder'=>90,
"inputtype"=>"integer",
"help"=>gT("Limit time to answer question (in seconds)"),
"caption"=>gT("Time limit")
);
self::$attributes["time_limit_action"] = array(
"types"=>"STUXL!",
'category'=>gT('Timer'),
'sortorder'=>92,
'inputtype'=>'singleselect',
'options'=>array(
1=>gT('Warn and move on'),
2=>gT('Move on without warning'),
3=>gT('Disable only')
),
"default" => 1,
"help"=>gT("Action to perform when time limit is up"),
"caption"=>gT("Time limit action")
);
self::$attributes["time_limit_disable_next"] = array(
"types"=>"STUXL!",
'category'=>gT('Timer'),
'sortorder'=>94,
"inputtype"=>"switch",
'default'=>0,
'options'=>array(0=>gT('No'), 1=>gT('Yes')),
"help"=>gT("Disable the next button until time limit expires"),
"caption"=>gT("Time limit disable next")
);
self::$attributes["time_limit_disable_prev"] = array(
"types"=>"STUXL!",
'category'=>gT('Timer'),
'sortorder'=>96,
"inputtype"=>"switch",
'options'=>array(0=>gT('No'), 1=>gT('Yes')),
'default'=>0,
"help"=>gT("Disable the prev button until the time limit expires"),
"caption"=>gT("Time limit disable prev")
);
self::$attributes["time_limit_countdown_message"] = array(
"types"=>"STUXL!",
'category'=>gT('Timer'),
'sortorder'=>98,
"inputtype"=>"textarea",
'expression'=>1,
'i18n'=>true,
"help"=>gT("The text message that displays in the countdown timer during the countdown"),
"caption"=>gT("Time limit countdown message")
);
self::$attributes["time_limit_timer_style"] = array(
"types"=>"STUXL!",
'category'=>gT('Timer'),
'sortorder'=>100,
"inputtype"=>"textarea",
"help"=>gT("CSS Style for the message that displays in the countdown timer during the countdown"),
"caption"=>gT("Time limit timer CSS style")
);
self::$attributes["time_limit_message_delay"] = array(
"types"=>"STUXL!",
'category'=>gT('Timer'),
'sortorder'=>102,
"inputtype"=>"integer",
"help"=>gT("Display the 'time limit expiry message' for this many seconds before performing the 'time limit action' (defaults to 1 second if left blank)"),
"caption"=>gT("Time limit expiry message display time")
);
self::$attributes["time_limit_message"] = array(
"types"=>"STUXL!",
'category'=>gT('Timer'),
'sortorder'=>104,
"inputtype"=>"textarea",
'expression'=>1,
'i18n'=>true,
"help"=>gT("The message to display when the time limit has expired (a default message will display if this setting is left blank)"),
"caption"=>gT("Time limit expiry message")
);
self::$attributes["time_limit_message_style"] = array(
"types"=>"STUXL!",
'category'=>gT('Timer'),
'sortorder'=>106,
"inputtype"=>"textarea",
"help"=>gT("CSS style for the 'time limit expiry message'"),
"caption"=>gT("Time limit message CSS style")
);
self::$attributes["time_limit_warning"] = array(
"types"=>"STUXL!",
'category'=>gT('Timer'),
'sortorder'=>108,
"inputtype"=>"integer",
"help"=>gT("Display a 'time limit warning' when there are this many seconds remaining in the countdown (warning will not display if left blank)"),
"caption"=>gT("1st time limit warning message timer")
);
self::$attributes["time_limit_warning_display_time"] = array(
"types"=>"STUXL!",
'category'=>gT('Timer'),
'sortorder'=>110,
"inputtype"=>"integer",
"help"=>gT("The 'time limit warning' will stay visible for this many seconds (will not turn off if this setting is left blank)"),
"caption"=>gT("1st time limit warning message display time")
);
self::$attributes["time_limit_warning_message"] = array(
"types"=>"STUXL!",
'category'=>gT('Timer'),
'sortorder'=>112,
"inputtype"=>"textarea",
'expression'=>1,
'i18n'=>true,
"help"=>gT("The message to display as a 'time limit warning' (a default warning will display if this is left blank)"),
"caption"=>gT("1st time limit warning message")
);
self::$attributes["time_limit_warning_style"] = array(
"types"=>"STUXL!",
'category'=>gT('Timer'),
'sortorder'=>114,
"inputtype"=>"textarea",
"help"=>gT("CSS style used when the 'time limit warning' message is displayed"),
"caption"=>gT("1st time limit warning CSS style")
);
self::$attributes["time_limit_warning_2"] = array(
"types"=>"STUXL!",
'category'=>gT('Timer'),
'sortorder'=>116,
"inputtype"=>"integer",
"help"=>gT("Display the 2nd 'time limit warning' when there are this many seconds remaining in the countdown (warning will not display if left blank)"),
"caption"=>gT("2nd time limit warning message timer")
);
self::$attributes["time_limit_warning_2_display_time"] = array(
"types"=>"STUXL!",
'category'=>gT('Timer'),
'sortorder'=>118,
"inputtype"=>"integer",
"help"=>gT("The 2nd 'time limit warning' will stay visible for this many seconds (will not turn off if this setting is left blank)"),
"caption"=>gT("2nd time limit warning message display time")
);
self::$attributes["time_limit_warning_2_message"] = array(
"types"=>"STUXL!",
'category'=>gT('Timer'),
'sortorder'=>120,
"inputtype"=>"textarea",
'expression'=>1,
'i18n'=>true,
"help"=>gT("The 2nd message to display as a 'time limit warning' (a default warning will display if this is left blank)"),
"caption"=>gT("2nd time limit warning message")
);
self::$attributes["time_limit_warning_2_style"] = array(
"types"=>"STUXL!",
'category'=>gT('Timer'),
'sortorder'=>122,
"inputtype"=>"textarea",
"help"=>gT("CSS style used when the 2nd 'time limit warning' message is displayed"),
"caption"=>gT("2nd time limit warning CSS style")
);
self::$attributes["date_format"] = array(
"types"=>"D",
'category'=>gT('Input'),
'sortorder'=>100,
"inputtype"=>"text",
"help"=>gT("Specify a custom date/time format (the <i>d/dd m/mm yy/yyyy H/HH M/MM</i> formats and \"-./: \" characters are allowed for day/month/year/hour/minutes without or with leading zero respectively. Defaults to survey's date format"),
"caption"=>gT("Date/Time format")
);
self::$attributes["dropdown_dates_minute_step"] = array(
"types"=>"D",
'category'=>gT('Input'),
'sortorder'=>100,
"inputtype"=>"integer",
'default'=>1,
"help"=>gT("Visual minute step interval"),
"caption"=>gT("Minute step interval")
);
self::$attributes["dropdown_dates_month_style"] = array(
"types"=>"D",
'category'=>gT('Display'),
'sortorder'=>100,
"inputtype"=>"buttongroup",
'options'=>array(
0=>gT('Short names', 'unescaped'),
1=>gT('Full names', 'unescaped'),
2=>gT('Numbers', 'unescaped')
),
'default'=>0,
"help"=>gT("Change the display style of the month when using select boxes"),
"caption"=>gT("Month display style")
);
self::$attributes["show_title"] = array(
"types"=>"|",
'category'=>gT('File metadata'),
'sortorder'=>124,
"inputtype"=>"switch",
'options'=>array(0=>gT('No'), 1=>gT('Yes')),
'default'=>1,
"help"=>gT("Is the participant required to give a title to the uploaded file?"),
"caption"=>gT("Show title")
);
self::$attributes["show_comment"] = array(
"types"=>"|",
'category'=>gT('File metadata'),
'sortorder'=>126,
"inputtype"=>"switch",
'options'=>array(0=>gT('No'), 1=>gT('Yes')),
'default'=>1,
"help"=>gT("Is the participant required to give a comment to the uploaded file?"),
"caption"=>gT("Show comment")
);
self::$attributes["max_filesize"] = array(
"types"=>"|",
'category'=>gT('Other'),
'sortorder'=>128,
"inputtype"=>"integer",
'default'=>10240,
"help"=>sprintf(gT("The participant cannot upload a single file larger than this size. Server configuration allow a maximum file size of %s KB."),getMaximumFileUploadSize()/1024),
"caption"=>gT("Maximum file size allowed (in KB)")
);
self::$attributes["max_num_of_files"] = array(
"types"=>"|",
'category'=>gT('Other'),
'sortorder'=>130,
"inputtype"=>"integer",
'min'=>1,
'default'=>'1',
"help"=>gT("Maximum number of files that the participant can upload for this question"),
"caption"=>gT("Max number of files")
);
self::$attributes["min_num_of_files"] = array(
"types"=>"|",
'category'=>gT('Other'),
'sortorder'=>132,
"inputtype"=>"integer",
'default'=>'0',
'min'=>0,
"help"=>gT("Minimum number of files that the participant must upload for this question"),
"caption"=>gT("Min number of files")
);
self::$attributes["allowed_filetypes"] = array(
"types"=>"|",
'category'=>gT('Other'),
'sortorder'=>134,
"inputtype"=>"text",
'default'=>"png, gif, doc, odt, jpg, pdf, png",
"help"=>gT("Allowed file types in comma separated format. e.g. pdf,doc,odt"),
"caption"=>gT("Allowed file types")
);
self::$attributes["random_group"] = array(
"types"=>"15ABCDEFGHIKLMNOPQRSTUWXYZ!:;|",
'category'=>gT('Logic'),
'sortorder'=>180,
'inputtype'=>'text',
"help"=>gT("Place questions into a specified randomization group, all questions included in the specified group will appear in a random order"),
"caption"=>gT("Randomization group name")
);
// This is added to support historical behavior. Early versions of 1.92 used a value of "No", so if there was a min_sum_value or equals_sum_value, the question was not valid
// unless those criteria were met. In later releases of 1.92, the default was changed so that missing values were allowed even if those attributes were set
// This attribute lets authors control whether missing values should be allowed in those cases without needing to set min_answers
// Existing surveys will use the old behavior, but if the author edits the question, the default will be the new behavior.
self::$attributes["value_range_allows_missing"] = array(
"types"=>"K",
'category'=>gT('Input'),
'sortorder'=>100,
"inputtype"=>"switch",
'options'=>array(0=>gT('No'), 1=>gT('Yes')),
'default'=>1,
"help"=>gT("Is no answer (missing) allowed when either 'Equals sum value' or 'Minimum sum value' are set?"),
"caption"=>gT("Value range allows missing")
);
/*
Deactivated because it does not work properly
self::$attributes["thousands_separator"] = array(
'types' => 'NK',
"help" => gT("Show a thousands separator when the user enters a value"),
"caption" => gT("Thousands separator"),
'category' => gT('Display'),
'inputtype' => 'singleselect',
'sortorder' => 100,
'options' => array(
0 => gT('No'),
1 => gT('Yes')
),
'default'=>0,
);
*/
self::$attributes["display_type"] = array(
"types"=>"YG",
'category'=>gT('Display'),
'sortorder'=>90,
'inputtype'=>'buttongroup',
'options'=>array(
0=>gT('Button group', 'unescaped'),
1=>gT('Radio list', 'unescaped')
),
'default'=>0,
"help"=>gT('Use button group or radio list'),
"caption"=>gT('Display type')
);
self::$attributes["question_template"] = array(
"types"=>"15ABCDEFGHIKLMNOPQRSTUWXYZ!:;|",
'category'=>gT('Display'),
'sortorder'=>100,
'inputtype'=>'question_template',
'options'=>array(),
'default' => "core",
"help"=>gT('Use a customized question theme for this question'),
"caption"=>gT('Question theme')
);
/**
* New event to allow plugin to add own question attribute (settings)
* Using $event->append('questionAttributes', $questionAttributes);
* $questionAttributes=[
* attributeName=>[
* 'types' : Aply to this question type
* 'category' : Where to put it
* 'sortorder' : Qort order in this category
* 'inputtype' : type of input
* 'expression' : 2 to force Exprerssion Manager when see the survey logic file (add { } and validate, 1 : allow it : validate in survey logic file
* 'options' : optionnal options if input type need it
* 'default' : the default value
* 'caption' : the label
* 'help' : an help
* ]
*/
$event = new \LimeSurvey\PluginManager\PluginEvent('newQuestionAttributes');
$result = App()->getPluginManager()->dispatchEvent($event);
/* Cast as array , or test if exist , or set to an empty array at start (or to self::$attributes : and do self::$attributes=$result->get('questionAttributes') directly ) ? */
$questionAttributes = (array) $result->get('questionAttributes');
self::$attributes = array_merge(self::$attributes, $questionAttributes);
return self::$attributes;
}
/**
* Return the question attributes definition by question type
* @param $sType: type pof question
* @return array : the attribute settings for this question type
*/
public static function getQuestionAttributesSettings($sType)
{
if (!isset(self::$questionAttributesSettings[$sType])) {
self::$questionAttributesSettings[$sType] = array();
self::getAttributesDefinitions(); /* we need to have self::$attributes */
/* Filter to get this question type setting */
$aQuestionTypeAttributes = array_filter(self::$attributes, function($attribute) use ($sType) {
return stripos($attribute['types'], $sType) !== false;
});
foreach ($aQuestionTypeAttributes as $attribute=>$settings) {
self::$questionAttributesSettings[$sType][$attribute] = array_merge(
QuestionAttribute::getDefaultSettings(),
array("category"=>gT("Plugins")),
$settings,
array("name"=>$attribute)
);
}
}
return self::$questionAttributesSettings[$sType];
}
/**
* Return the question Theme custom attributes values
* @param $sQuestionThemeName: question theme name
* @return array : the attribute settings for this question type
*/
public static function getQuestionThemeAttributeValues($sQuestionThemeName = null, $question_template = null)
{
libxml_disable_entity_loader(false);
$sCoreThemeXmlPath = Yii::app()->getConfig('corequestionthemerootdir').'/'.$sQuestionThemeName.'/survey/questions/answer/'.$question_template.'/config.xml';
$sUserThemeXmlPath = Yii::app()->getConfig("userquestionthemerootdir").'/'.$sQuestionThemeName.'/survey/questions/answer/'.$question_template.'/config.xml';
$xml_config = is_file($sCoreThemeXmlPath) ? simplexml_load_file($sCoreThemeXmlPath) : simplexml_load_file($sUserThemeXmlPath);
$custom_attributes = json_decode(json_encode((array)$xml_config->custom_attributes), TRUE);
libxml_disable_entity_loader(true);
if(!empty($custom_attributes['attribute']['name'])) {
// Only one attribute set in config : need an array of attributes
$custom_attributes['attribute'] = array($custom_attributes['attribute']);
}
$defaultQuestionAttributeValues = QuestionAttribute::getDefaultSettings();
$additionalAttributes = array();
// Create array of attribute with name as key
foreach($custom_attributes['attribute'] as $customAttribute) {
if(!empty($customAttribute['name'])) {
$additionalAttributes[$customAttribute['name']] = array_merge($defaultQuestionAttributeValues,$customAttribute);
}
}
return $additionalAttributes;
}
/**
* Return the question Theme preview URL
* @param $sType: type pof question
* @return string : question theme preview URL
*/
public static function getQuestionThemePreviewUrl($sType = null)
{
if ($sType == '*'){
$preview_filename = 'EQUATION.png';
} elseif ($sType == ':'){
$preview_filename = 'COLON.png';
} elseif ($sType == '|'){
$preview_filename = 'PIPE.png';
} elseif (!empty($sType)) {
$preview_filename = $sType.'.png';
} else {
$preview_filename = '.png';
}
return Yii::app()->getConfig("imageurl").'/screenshots/'.$preview_filename;
}
}
You can’t perform that action at this time.