Actions

Database Storage Engine Project M2 API: Difference between revisions

From LimeSurvey Manual

No edit summary
No edit summary
Line 337: Line 337:
This controller provides methodes to store and retrieve survey answers.
This controller provides methodes to store and retrieve survey answers.


=== void addResponse(participantID, questionID, value, starttime, endtime, iteration=0)===
=== void addResponse(surveyID, participantID, questionID, value, starttime, endtime, iteration=0)===


Adds the given answer and metadata for the given question to the answers of the given participant. If there already was an answer to the given question for the given participant, the answer will be overridden. The iteration parameter is used to express this is the answer for the i'th loop. If the given answer value is invalid for the given question, an exception will be thrown.
Adds the given answer and metadata for the given question to the answers of the given participant. If there already was an answer to the given question for the given participant, the answer will be overridden. The iteration parameter is used to express this is the answer for the i'th loop. If the given answer value is invalid for the given question, an exception will be thrown.


=== Response getResponse(participantID, questionID)===
=== Response getResponse(surveyID, participantID, questionID)===


Returns the response of the given participant to the given question and its metadata.
Returns the response of the given participant to the given question and its metadata.


=== Response[] getResponsesToQuestion(questionID)===
=== Response[] getResponsesToQuestion(surveyID, questionID)===


Returns all responses to the given question and their metadata.
Returns all responses to the given question and their metadata.
Line 357: Line 357:
Returns a double array containing all response information from the survey.
Returns a double array containing all response information from the survey.


=== boolean hasFinished(surveyID,participantID)===
=== boolean hasFinished(surveyID, participantID)===


Returns true if the given participant already finished the survey. Returns false if the participant did not complete the survey.
Returns true if the given participant already finished the survey. Returns false if the participant did not complete the survey.


=== date getSurveyStart(surveyID,participantID)===
=== date getSurveyStart(surveyID, participantID)===


Returns the start time of this participant.
Returns the start time of this participant.


=== date getSurveyEnd(surveyID,participantID)===
=== date getSurveyEnd(surveyID, participantID)===


Returns the end time of this participant.
Returns the end time of this participant.


=== assoc(section_id => date) getSectionStart(surveyID,participantID)===
=== assoc(section_id => date) getSectionStart(surveyID, participantID)===


Returns the start times of this participant for each section.
Returns the start times of this participant for each section.


=== assoc(section_id => date) getSectionEnd(surveyID,participantID)===
=== assoc(section_id => date) getSectionEnd(surveyID, participantID)===


Returns the end times of this participant for each section.
Returns the end times of this participant for each section.

Revision as of 12:01, 10 July 2010

About the milestone

This milestone includes building the API for the database system.

We will release a preview of the API before the 1st of June in order to have plenty of time for the community to comment.

Todo

  • Develop basic API and post it on the forums (done)
  • Explore comments on the basic API (done)
  • Complete the API (done)
  • Make sure it is possible to add/have support for current en future metadata related to single questions & whole surveys. (done)
  • Add methods to add and remove observers (done)

Basic API version (06-25)

Below you find the API.

Survey

A survey is a collection of sections. Surveys can have various metadata like a respondent e-mail adres, a name, ...

mixed get()

Getter method for all properties.

void set()

Setter method for the properties.

assoc(key => value) listMetaData()

Lists all metadata belonging to the survey.

void addMetaData(key, value)

Adds the given metadata to the survey.

void updateMetaData(key, newValue)

Updates the given metadata with the new value.

void removeMetaData(key)

Removes the given metadata from the survey.

Section

A section is a part of a survey, grouping questions together. Using conditions it is possible to loop or branch over sections.

mixed get()

Getter method for all properties.

void set()

Setter method for the properties.

assoc(key => value) listMetaData()

Lists all metadata belonging to the section.

void addMetaData(key, value)

Adds the given metadata to the section.

void updateMetaDate(key, newValue)

Updates the given metadata with the new value.

void removeMetaData(key)

Removes the given metadata from the section.

QuestionType

A survey can have various types of questions, ranging from string & integers up to fileinput and matrix types. QuestionType will have subclasses: basic question types like IntegerQuestionType, StringQuestionType, DateQuestionType ... and structures like MatrixQuestionType, ArrayQuestionType, ...

string render(Question)

Returns a template for this questiontype.

mixed getFields(Question)

Returns a list of all fields required by this questiontype and their types.

bool checkResponse(Question, value)

Returns true if the given value is a valid response to the question.

Question

A question is a combination of a string (the question) a QuestionType and possible various options - depending on the type.

mixed get()

Getter method for all properties.

void set()

Setter method for the properties.

assoc(key => value) listMetaData()

Lists all metadata belonging to the question.

void addMetaData(key, value)

Adds the given metadata to the question.

void updateMetaDate(key, newValue)

Updates the given metadata with the new value.

void removeMetaData(key)

Removes the given metadata from the question.

string render(Question)

Returns a template for this question.

mixed getFields(Question)

Returns a list of all fields required by this question and their types.

bool checkResponse(value)

Returns true if the given value is a valid response to the question.

ModelAnswer

A model answer for a closed question.

mixed getValue()

Returns the value of this model answer.

Response

A response is a combination of a token, questionID, answervalue and metadata.

mixed get()

Getter method for all properties.

date getStartTime()

Returns the time this response was started. This means when the question was displayed.

date getEndTime()

Returns the time this response was ended. This means when the question was filled in.

int getIteration()

Returns the iteration of this response (used for loops).

ModelAnswerManagementController

This controller will handle the management of model answers.

void storeModelAnswer(questionID, ModelAnswer)

Stores the given model answer to the database. If the model answer has no ID, it will be considered a new model answer. In this case ModelAnswer->id will be set to the ID appointed to this model answer. The model answer must have a valid question id.

ModelAnswer[] listModelAnswers(questionID)

Returns all model answers of the given question.

void moveUp(modelAnswerID, places)

Moves the model answer one place to the front of the question.

void moveDown(modelAnswerID, places)

Moves the model answer one place to the end of the question.

void reorder(assoc(modelAnswerId => orderNumber))

Changes the order of the given model answers to the given order numbers. O6rders must be unique. When there are clashes, an exception will be thrown (defined later).

ModelAnswer getModelAnswer(modelAnswerID)

Returns the model answer belonging to the given model answer ID.

void removeModelAnswer(modelAnswerID)

Removes the model answer with the given model answer ID.

SurveyManagementController

This controller will handle the management of surveys.

Survey[] listSurveys()

Lists all surveys.

void storeSurvey(Survey)

Stores the given survey to the database. If the survey has no ID, it will be considered a new survey. In this case Survey->id will be set to the ID appointed to this survey.

Survey getSurvey(surveyID)

Returns the wanted survey.

void removeSurvey(surveyID)

Removes survey data and all answers.

void openSurvey(surveyID)

Changes the state of the survey to open.

void closeSurvey(surveyID)

Changes the state of the survey to closed.

void setDatabaseEngine(surveyID, engineID)

Enables the chosen database engine for the given survey. Can only be called the first time before the survey is opened.

string[] getPossibleDatabaseEngines(surveyID)

Returns the possible engineID's of the database engines which are possible for this survey.

SectionManagementController

This controller will handle the management of sections.

Section[] listSections(surveyID)

Lists all sections in the given survey.

void storeSection(Section)

Stores the given section to the database. If the section has no ID, it will be considered a new section. In this case Section->id will be set to the ID appointed to this section. The section must have a valid survey id.

Section getSection(sectionID)

Returns the wanted section.

void removeSection(sectionID)

Removes section data and all answers.

void moveUp(sectionId, places)

Moves the section one place to the front of the survey.

void moveDown(sectionId, places)

Moves the section one place to the end of the survey.

void reorder(assoc(sectionId => orderNumber))

Changes the order of the given sections to the given order numbers. Orders must be unique. When there are clashes, an exception will be thrown (defined later).

interface DBSEObserver

void notifySurveyCreated(Survey survey)

Called on creation of survey.

void notifySurveyRemoved(int id)

Called on removal of survey.

void notifySurveyChanged(Survey survey)

Called on update of survey.

void notifySectionCreated(Section section)

Called on creation of section.

void notifySectionRemoved(int id)

Called on removal of section.

void notifySectionChanged(Section section)

Called on update of section.

void notifyQuestionCreated(Question question)

Called on creation of question.

void notifyQuestionRemoved(int id)

Called on removal of question.

void notifyQuestionChanged(Question question)

Called on update of question.

void notifyResponse(Response response)

Called on submission of a response.

QuestionManagementController

This controller will handle the management of questions.

Question[] listQuestions(sectionID)

Lists all questions in the given section.

void storeQuestion(Question)

Stores the given question to the database. If the question has no ID, it will be considered a new question. In this case Question->id will be set to the ID appointed to this question. The question must have a valid section id.

Question getQuestion(questionID)

Returns the wanted question.

void removeQuestion(questionID)

Removes question data and all answers.

void moveUp(questionID, places)

Moves the question one place to the front of the section.

void moveDown(questionID, places)

Moves the question one place to the end of the section.

void reorder(assoc(questionID => orderNumber))

Changes the order of the given questions to the given order numbers. Orders must be unique. When there are clashes, an exception will be thrown (defined later).

AnswerAccessController

This controller provides methodes to store and retrieve survey answers.

void addResponse(surveyID, participantID, questionID, value, starttime, endtime, iteration=0)

Adds the given answer and metadata for the given question to the answers of the given participant. If there already was an answer to the given question for the given participant, the answer will be overridden. The iteration parameter is used to express this is the answer for the i'th loop. If the given answer value is invalid for the given question, an exception will be thrown.

Response getResponse(surveyID, participantID, questionID)

Returns the response of the given participant to the given question and its metadata.

Response[] getResponsesToQuestion(surveyID, questionID)

Returns all responses to the given question and their metadata.

Response[] getResponses(surveyID)

Returns all responses to the survey.

mixed exportResponses(surveyID)

Returns a double array containing all response information from the survey.

boolean hasFinished(surveyID, participantID)

Returns true if the given participant already finished the survey. Returns false if the participant did not complete the survey.

date getSurveyStart(surveyID, participantID)

Returns the start time of this participant.

date getSurveyEnd(surveyID, participantID)

Returns the end time of this participant.

assoc(section_id => date) getSectionStart(surveyID, participantID)

Returns the start times of this participant for each section.

assoc(section_id => date) getSectionEnd(surveyID, participantID)

Returns the end times of this participant for each section.

ObserverController

static ObserverController getInstance()

Returns a statical instance to the ObserverController.

void addObserver(DBSEObserver observer)

Adds an observer to the ObserverController.

void removeObserver(DBSEObserver observer)

Removes an observer from the ObserverController.

=== void notifyObservers(callback $function  ~091~,  mixed $parameter  ~091~,  mixed $...  ~093 array(color => array(red => ...)). When you use a subkey, you cannot use the key itself anymore.

  • Exceptions will be used for reporting errors. The exceptions thrown by each method will be added later in the development process.

Discussions

Comments and ideas here please:

Comments from Machaven:

 1. All the functions that do not return anything (void)

  • Should functions not return true/false (bool) depending on success or failure?

 2. void updateMetaDate(key, value, newValue)

  • Should this be spelled: updateMetaData?
  • Why is the original value required to change the metadata? Are the keys not unique?

 3. How are errors handled?

  • Can we trigger some action on error, set logging or retrieve error information?

Comments from Jason:

From May

 1. There has been some discussion about the use of the word token to represent each unique participant

  • this may be better expressed using a different word internally. Since survey participants/token recipients will be represented as "users" maybe "userID" would be a better label than tokens - ie instead of "Answer getAnswer(token, questionID)", "Answer getAnswer(userID, questionID)"

 2. The AnswerAccess controller, should it also be storing responses?

  • So, there should be an equivalent of "getAnswer", being "putAnswer" (or "saveAnswer")

 3. Once answers are being stored, either in a flatfile table, or a normalised one, there will be some kind of unique id for the "collection" of answers, so they can be grouped together.

  • A collection of survey responses, with their unique identifier, become the "sheet of answers" to a particular survey. In the case of a controlled survey - where the user has been specifically invited, so we know who they are, they'll have a unique userID from the users table. In the case of open/anonymous or general public surveys, this unique identifier will have to be something else - where is that reflected in the getAnswers, and where will it be reflected in the putAnswer(s) call?

New June Comments

I've had a thought that the moveUp and moveDown methods should take an option of how many positions to move them. When you have 20 questions in a section, and you want to move your question to the top, moving it up one at a time can be really annoying. Can we have void moveUp(sectionId,positions) so if we want to move something 5 places up in the order, it could have a 5 for the positions? Default, of course, would be 1.

Comments from Hai:

  • Add functions for reordering questions (something that would take an array and/or an assoc. map)
  • Make sure you handle scalability for conditions well. This includes:
    • ability to link survey elements to multiple conditions, each condition linkable to multiple actions.
    • providing functions for various condition actions, such as question hiding, branching etc. (sorry, I know this is extremely vague, I'll try to specify later on)