Question object types: Difference between revisions
From LimeSurvey Manual
Line 39: | Line 39: | ||
| renderFrontend || Former qanda code; render question for survey taker | | renderFrontend || Former qanda code; render question for survey taker | ||
|- | |- | ||
| getSettings | | getSettings || Return settings (array) that can be used by a settings widget for edit form in backend | ||
|- | |||
| renderCustomSettings || Possibly custom HTML settings? | |||
|- | |- | ||
| renderPDFStatistics || Render question statistics for PDF format | | renderPDFStatistics || Render question statistics for PDF format |
Revision as of 12:10, 21 April 2016
Question object types is about making questions in LS more object-oriented and modular, and letting users create and upload their own object types.
Basically, every place in the code which is doing a switch on question type should be replaced by a polymorphic call to an object, e.g. $object->renderFrontend();
Use-cases
- Colour picker - user click on a picture with colours, and the position in the picture defines the colour.
- "... the surgeon would indicate the location of a fracture by drawing on a diagram of the knee."
Features
TODO
Open issues
- Is array it's own object type, or is it a property of a question? Could we have an array of any question typ, e.g. yes/no questions?
- Cross-cutting concerns: What if the user wants to add a comment field to all questions in the survey? Or timing?
- Composability: Should it be possible to combine two questions into one, or pick-and-choose among "question elements"?
- Should we also change the way we save answer data? If yes, in which step - first or last? Which database design should we use instead?
- Can we inherit views?
- Interaction with plugins, e.g. Stata XML export? No other way around it than using switch in plugin, or each question type should itself supply a method the plugin can use?
Implementation
Object hierarchy.
Minimum requirements
This is a list of functions that all question types must implement. They should be included in a "base interface" or base class.
If not implemented they could throw an NotImplementedException
(must be catched higher up).
Function name | Meaning |
---|---|
renderFrontend | Former qanda code; render question for survey taker |
getSettings | Return settings (array) that can be used by a settings widget for edit form in backend |
renderCustomSettings | Possibly custom HTML settings? |
renderPDFStatistics | Render question statistics for PDF format |
renderHTMLStatistics | Render question statistics for HTML (back-end statistics view) |
renderXLSStatistics | Render question statistics for XLS |
Implemented as Yii module, with views, models and controllers (http://www.yiiframework.com/doc/guide/1.1/en/basics.module#creating-module).
Replace switch-cases in:
- Frontend render (render answers, qanda)
- Backend render (edit question, file
questions.php
) - Statistics
- SQL and database queries, included extra field the question might define
- Expression manager
Ideally, each switch case in the code should have a unit test or functional test to test it with.
Current question types
From statistics.php:
- 1 - Array Dual Scale
- 5 - 5 Point Choice
- A - Array (5 Point Choice)
- B - Array (10 Point Choice)
- C - Array (Yes/No/Uncertain)
- D - Date
- E - Array (Increase, Same, Decrease)
- F - Array (Flexible Labels)
- G - Gender
- H - Array (Flexible Labels) by Column
- I - Language Switch
- K - Multiple Numerical Input
- L - List (Radio)
- M - Multiple choice
- N - Numerical Input
- O - List With Comment
- P - Multiple choice with comments
- Q - Multiple Short Text
- R - Ranking
- S - Short Free Text
- T - Long Free Text
- U - Huge Free Text
- X - Boilerplate Question
- Y - Yes/No
- ! - List (Dropdown)
- : - Array (Flexible Labels) multiple drop down
- ; - Array (Flexible Labels) multiple texts
- | - File Upload
Categories:
- Single-choice questions
- Arrays
- Mask questions
- Text questions
- Multiple-choice questions
Prototype/proof-of-concept
As a first cycle of development (iteration), one could implement a completely new question type (say, drawing board) with the new system on top of the old one. The purpose would be to get a better feeling of the problem domain, what changes are needed, if the current approach is possible, and so on.
After the prototype is done, the existent questions can be exported to the new system one by one. This represents a "horizontal" development style, where the complete problem is solved for _one_ case in the first cycle, in contrast to exporting the entire qanda to the new system, then the entire statistics module, etc. A horizontal style would give faster results and introduce lesser mechanical work, focusing on design and creativity which is needed in the beginning.
Example from qanda:
if (is_object($ia))
{
$ia->renderFrontend();
}
else
{
switch ($ia[4]) // $ia[4] is question type
{
case 'X': //BOILERPLATE QUESTION
$values = do_boilerplate($ia);
break;
// and so on for all question types
}
}
When all questions have been exported to the new system, this snippet will just be:
$ia->renderFrontend();
Current LS3 implementation
Note, this is the current state and some of these are mostly because it is a refactoring from LS2.
1. Uses an interface.
2. Defines what columns it needs via a fieldname => column type map.
3. Defines what EM expressions apply to it.
4. Defines a render functionality that renders the content.
5. Defines a list of classes that should be in the wrapping div.