upsc_quiz-1.0.x-dev/upsc_quiz.install
upsc_quiz.install
<?php
/**
* @file
* Install, update and uninstall functions for the UPSC Quiz module.
*/
/**
* Implements hook_schema().
*/
function upsc_quiz_schema() {
$schema = [];
// Table for storing quiz questions
$schema['upsc_quiz_questions'] = [
'description' => 'Stores quiz questions with their options and correct answers.',
'fields' => [
'id' => [
'type' => 'serial',
'not null' => TRUE,
'description' => 'Primary Key: Unique question ID.',
],
'section' => [
'type' => 'varchar',
'length' => 100,
'not null' => TRUE,
'description' => 'The quiz section (Polity, History, etc.).',
],
'question' => [
'type' => 'text',
'not null' => TRUE,
'description' => 'The question text.',
],
'options' => [
'type' => 'text',
'size' => 'medium',
'not null' => TRUE,
'description' => 'JSON encoded options array.',
'serialize' => TRUE,
],
'correct_answer' => [
'type' => 'varchar',
'length' => 1,
'not null' => TRUE,
'description' => 'The correct answer (A, B, C, or D).',
],
'explanation' => [
'type' => 'text',
'not null' => FALSE,
'description' => 'Optional explanation for the answer.',
],
'difficulty' => [
'type' => 'int',
'size' => 'tiny',
'not null' => TRUE,
'default' => 1,
'description' => 'Question difficulty level (1-5).',
],
'weight' => [
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'Weight for ordering questions.',
],
'status' => [
'type' => 'int',
'size' => 'tiny',
'not null' => TRUE,
'default' => 1,
'description' => 'Published status (0 = unpublished, 1 = published).',
],
'created' => [
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'The Unix timestamp when the question was created.',
],
'changed' => [
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'The Unix timestamp when the question was most recently saved.',
],
],
'primary key' => ['id'],
'indexes' => [
'section' => ['section'],
'status' => ['status'],
'difficulty' => ['difficulty'],
'weight' => ['weight'],
],
];
// Table for storing quiz attempts
$schema['upsc_quiz_attempts'] = [
'description' => 'Stores user quiz attempts and their results.',
'fields' => [
'id' => [
'type' => 'serial',
'not null' => TRUE,
'description' => 'Primary Key: Unique attempt ID.',
],
'uid' => [
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'The user ID who took the quiz.',
],
'session_id' => [
'type' => 'varchar',
'length' => 128,
'not null' => TRUE,
'description' => 'Session ID for anonymous users.',
],
'section' => [
'type' => 'varchar',
'length' => 100,
'not null' => TRUE,
'description' => 'The quiz section attempted.',
],
'score' => [
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'Final score achieved.',
],
'total_questions' => [
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'Total number of questions in the attempt.',
],
'correct_answers' => [
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'Number of correct answers.',
],
'time_taken' => [
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'Time taken to complete the quiz in seconds.',
],
'answers' => [
'type' => 'text',
'size' => 'medium',
'not null' => FALSE,
'description' => 'JSON encoded user answers.',
],
'results' => [
'type' => 'text',
'size' => 'medium',
'not null' => FALSE,
'description' => 'JSON encoded quiz results.',
],
'quiz_mode' => [
'type' => 'varchar',
'length' => 50,
'not null' => TRUE,
'default' => 'practice',
'description' => 'Quiz mode (practice, exam, section).',
],
'completed' => [
'type' => 'int',
'size' => 'tiny',
'not null' => TRUE,
'default' => 0,
'description' => 'Whether the quiz was completed (0 = incomplete, 1 = completed).',
],
'created' => [
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'The Unix timestamp when the quiz was started.',
],
'finished' => [
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'The Unix timestamp when the quiz was finished.',
],
],
'primary key' => ['id'],
'indexes' => [
'uid' => ['uid'],
'section' => ['section'],
'completed' => ['completed'],
'created' => ['created'],
'quiz_mode' => ['quiz_mode'],
],
];
// Table for storing individual question responses
$schema['upsc_quiz_responses'] = [
'description' => 'Stores individual question responses for each quiz attempt.',
'fields' => [
'id' => [
'type' => 'serial',
'not null' => TRUE,
'description' => 'Primary Key: Unique response ID.',
],
'attempt_id' => [
'type' => 'int',
'not null' => TRUE,
'description' => 'Reference to the quiz attempt.',
],
'question_id' => [
'type' => 'int',
'not null' => TRUE,
'description' => 'Reference to the question.',
],
'user_answer' => [
'type' => 'varchar',
'length' => 1,
'not null' => FALSE,
'description' => 'The answer selected by the user (A, B, C, or D).',
],
'is_correct' => [
'type' => 'int',
'size' => 'tiny',
'not null' => TRUE,
'default' => 0,
'description' => 'Whether the answer was correct (0 = incorrect, 1 = correct).',
],
'time_spent' => [
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'Time spent on this question in seconds.',
],
'answered_at' => [
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'The Unix timestamp when the question was answered.',
],
],
'primary key' => ['id'],
'indexes' => [
'attempt_id' => ['attempt_id'],
'question_id' => ['question_id'],
'is_correct' => ['is_correct'],
],
'foreign keys' => [
'attempt' => [
'table' => 'upsc_quiz_attempts',
'columns' => ['attempt_id' => 'id'],
],
'question' => [
'table' => 'upsc_quiz_questions',
'columns' => ['question_id' => 'id'],
],
],
];
// Table for storing analytics data
$schema['upsc_quiz_analytics'] = [
'description' => 'Stores analytics data for quiz performance tracking.',
'fields' => [
'id' => [
'type' => 'serial',
'not null' => TRUE,
'description' => 'Primary Key: Unique analytics ID.',
],
'section' => [
'type' => 'varchar',
'length' => 100,
'not null' => TRUE,
'description' => 'The quiz section.',
],
'question_id' => [
'type' => 'int',
'not null' => TRUE,
'description' => 'Reference to the question.',
],
'total_attempts' => [
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'Total number of times this question was attempted.',
],
'correct_attempts' => [
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'Number of times this question was answered correctly.',
],
'avg_time_spent' => [
'type' => 'float',
'not null' => TRUE,
'default' => 0,
'description' => 'Average time spent on this question.',
],
'difficulty_rating' => [
'type' => 'float',
'not null' => TRUE,
'default' => 0,
'description' => 'Calculated difficulty based on performance.',
],
'last_updated' => [
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'The Unix timestamp when analytics were last updated.',
],
],
'primary key' => ['id'],
'unique keys' => [
'section_question' => ['section', 'question_id'],
],
'indexes' => [
'section' => ['section'],
'question_id' => ['question_id'],
'difficulty_rating' => ['difficulty_rating'],
],
'foreign keys' => [
'question' => [
'table' => 'upsc_quiz_questions',
'columns' => ['question_id' => 'id'],
],
],
];
return $schema;
}
/**
* Implements hook_install().
*/
function upsc_quiz_install() {
// Set default configuration values
\Drupal::configFactory()->getEditable('upsc_quiz.settings')
->set('time_limit', 30)
->set('enable_analytics', TRUE)
->set('allow_retake', TRUE)
->set('show_correct_answers', TRUE)
->set('randomize_questions', FALSE)
->set('randomize_options', FALSE)
->set('questions_per_section', 10)
->set('notify_admin', FALSE)
->set('admin_email', '')
->set('cache_questions', TRUE)
->set('debug_mode', FALSE)
->save();
// Insert sample questions for each section
_upsc_quiz_insert_sample_questions();
\Drupal::messenger()->addMessage(t('UPSC Quiz module has been installed successfully. Sample questions have been added to get you started.'));
}
/**
* Implements hook_uninstall().
*/
function upsc_quiz_uninstall() {
// Delete configuration
\Drupal::configFactory()->getEditable('upsc_quiz.settings')->delete();
\Drupal::messenger()->addMessage(t('UPSC Quiz module has been uninstalled. All quiz data has been removed.'));
}
/**
* Helper function to insert sample questions.
*/
function _upsc_quiz_insert_sample_questions() {
$database = \Drupal::database();
$current_time = \Drupal::time()->getCurrentTime();
// Sample questions for each section
$sample_questions = [
// Polity questions
[
'section' => 'Polity',
'question' => 'Which article of the Indian Constitution deals with the Right to Education?',
'option_a' => 'Article 19',
'option_b' => 'Article 21A',
'option_c' => 'Article 25',
'option_d' => 'Article 29',
'correct_answer' => 'B',
'explanation' => 'Article 21A was inserted by the 86th Constitutional Amendment Act, 2002, which makes education a fundamental right for children aged 6-14 years.',
'difficulty' => 2,
],
[
'section' => 'Polity',
'question' => 'The President of India is elected by which method?',
'option_a' => 'Direct election by people',
'option_b' => 'Electoral College system',
'option_c' => 'Parliament members only',
'option_d' => 'Prime Minister nomination',
'correct_answer' => 'B',
'explanation' => 'The President is elected by an Electoral College consisting of elected members of both Houses of Parliament and Legislative Assemblies of states.',
'difficulty' => 1,
],
// History questions
[
'section' => 'History',
'question' => 'The Quit India Movement was launched in which year?',
'option_a' => '1940',
'option_b' => '1942',
'option_c' => '1944',
'option_d' => '1946',
'correct_answer' => 'B',
'explanation' => 'The Quit India Movement was launched by Mahatma Gandhi on August 8, 1942, during World War II.',
'difficulty' => 1,
],
[
'section' => 'History',
'question' => 'Who was the founder of the Mauryan Empire?',
'option_a' => 'Ashoka',
'option_b' => 'Chandragupta Maurya',
'option_c' => 'Bindusara',
'option_d' => 'Samudragupta',
'correct_answer' => 'B',
'explanation' => 'Chandragupta Maurya founded the Mauryan Empire around 321 BCE with the help of Chanakya.',
'difficulty' => 1,
],
// Geography questions
[
'section' => 'Geography',
'question' => 'Which is the longest river in India?',
'option_a' => 'Yamuna',
'option_b' => 'Godavari',
'option_c' => 'Ganga',
'option_d' => 'Narmada',
'correct_answer' => 'C',
'explanation' => 'The Ganga river is the longest river in India, flowing for about 2,525 kilometers.',
'difficulty' => 1,
],
[
'section' => 'Geography',
'question' => 'The Tropic of Cancer passes through how many Indian states?',
'option_a' => '6',
'option_b' => '7',
'option_c' => '8',
'option_d' => '9',
'correct_answer' => 'C',
'explanation' => 'The Tropic of Cancer passes through 8 Indian states: Gujarat, Rajasthan, Madhya Pradesh, Chhattisgarh, Jharkhand, West Bengal, Tripura, and Mizoram.',
'difficulty' => 2,
],
// Economics questions
[
'section' => 'Economics',
'question' => 'What does GDP stand for?',
'option_a' => 'Gross Domestic Product',
'option_b' => 'General Domestic Product',
'option_c' => 'Gross Development Product',
'option_d' => 'General Development Product',
'correct_answer' => 'A',
'explanation' => 'GDP stands for Gross Domestic Product, which measures the total economic output of a country.',
'difficulty' => 1,
],
[
'section' => 'Economics',
'question' => 'The Reserve Bank of India was established in which year?',
'option_a' => '1934',
'option_b' => '1935',
'option_c' => '1936',
'option_d' => '1937',
'correct_answer' => 'B',
'explanation' => 'The Reserve Bank of India was established on April 1, 1935, under the Reserve Bank of India Act, 1934.',
'difficulty' => 2,
],
// General Science questions
[
'section' => 'General Science',
'question' => 'What is the chemical symbol for Gold?',
'option_a' => 'Go',
'option_b' => 'Gd',
'option_c' => 'Au',
'option_d' => 'Ag',
'correct_answer' => 'C',
'explanation' => 'The chemical symbol for Gold is Au, derived from the Latin word "aurum".',
'difficulty' => 1,
],
[
'section' => 'General Science',
'question' => 'Which planet is known as the Red Planet?',
'option_a' => 'Venus',
'option_b' => 'Mars',
'option_c' => 'Jupiter',
'option_d' => 'Saturn',
'correct_answer' => 'B',
'explanation' => 'Mars is known as the Red Planet due to iron oxide (rust) on its surface.',
'difficulty' => 1,
],
// Current Affairs questions
[
'section' => 'Current Affairs',
'question' => 'Who is the current Chief Justice of India (as of 2024)?',
'option_a' => 'N.V. Ramana',
'option_b' => 'U.U. Lalit',
'option_c' => 'D.Y. Chandrachud',
'option_d' => 'Ranjan Gogoi',
'correct_answer' => 'C',
'explanation' => 'Justice D.Y. Chandrachud is the current Chief Justice of India, appointed in November 2022.',
'difficulty' => 2,
],
[
'section' => 'Current Affairs',
'question' => 'Which country hosted the G20 summit in 2023?',
'option_a' => 'Indonesia',
'option_b' => 'India',
'option_c' => 'Brazil',
'option_d' => 'South Africa',
'correct_answer' => 'B',
'explanation' => 'India hosted the G20 summit in New Delhi in September 2023 under its G20 presidency.',
'difficulty' => 1,
],
];
// Insert sample questions
foreach ($sample_questions as $weight => $question) {
$question['weight'] = $weight;
$question['status'] = 1;
$question['created'] = $current_time;
$question['changed'] = $current_time;
$database->insert('upsc_quiz_questions')->fields($question)->execute();
}
}
/**
* Update 11001: Migrate schema to Drupal 11 standards.
*
* Updates database schema to be compliant with Drupal 11 coding standards
* and removes deprecated accessCheck(false) usage from queries.
*/
function upsc_quiz_update_11001() {
$database = \Drupal::database();
$schema = $database->schema();
// Update upsc_quiz_questions table
if ($schema->tableExists('upsc_quiz_questions')) {
// Check if we need to migrate from individual option fields to JSON options field
if ($schema->fieldExists('upsc_quiz_questions', 'option_a')) {
// Add the new options field
$options_field = [
'type' => 'text',
'size' => 'medium',
'not null' => TRUE,
'description' => 'JSON encoded options array.',
];
$schema->addField('upsc_quiz_questions', 'options', $options_field);
// Migrate data from individual option fields to JSON format
$questions = $database->select('upsc_quiz_questions', 'q')
->fields('q', ['id', 'option_a', 'option_b', 'option_c', 'option_d'])
->execute();
foreach ($questions as $question) {
$options = [
'A' => $question->option_a,
'B' => $question->option_b,
'C' => $question->option_c,
'D' => $question->option_d,
];
$database->update('upsc_quiz_questions')
->fields(['options' => json_encode($options)])
->condition('id', $question->id)
->execute();
}
// Drop old option fields
$schema->dropField('upsc_quiz_questions', 'option_a');
$schema->dropField('upsc_quiz_questions', 'option_b');
$schema->dropField('upsc_quiz_questions', 'option_c');
$schema->dropField('upsc_quiz_questions', 'option_d');
}
}
// Update upsc_quiz_attempts table
if ($schema->tableExists('upsc_quiz_attempts')) {
// Add missing fields if they don't exist
if (!$schema->fieldExists('upsc_quiz_attempts', 'answers')) {
$answers_field = [
'type' => 'text',
'size' => 'medium',
'not null' => FALSE,
'description' => 'JSON encoded user answers.',
];
$schema->addField('upsc_quiz_attempts', 'answers', $answers_field);
}
if (!$schema->fieldExists('upsc_quiz_attempts', 'results')) {
$results_field = [
'type' => 'text',
'size' => 'medium',
'not null' => FALSE,
'description' => 'JSON encoded quiz results.',
];
$schema->addField('upsc_quiz_attempts', 'results', $results_field);
}
if (!$schema->fieldExists('upsc_quiz_attempts', 'quiz_mode')) {
$quiz_mode_field = [
'type' => 'varchar',
'length' => 50,
'not null' => TRUE,
'default' => 'practice',
'description' => 'Quiz mode (practice, exam, section).',
];
$schema->addField('upsc_quiz_attempts', 'quiz_mode', $quiz_mode_field);
}
// Rename 'started' to 'created' for consistency
if ($schema->fieldExists('upsc_quiz_attempts', 'started') &&
!$schema->fieldExists('upsc_quiz_attempts', 'created')) {
$schema->changeField('upsc_quiz_attempts', 'started', 'created', [
'type' => 'int',
'not null' => TRUE,
'default' => 0,
'description' => 'The Unix timestamp when the quiz was started.',
]);
}
// Drop session_id field if it exists (not used in current implementation)
if ($schema->fieldExists('upsc_quiz_attempts', 'session_id')) {
$schema->dropField('upsc_quiz_attempts', 'session_id');
}
}
return t('Successfully updated UPSC Quiz schema for Drupal 11 compliance.');
}
/**
* Update hook to add new fields or modify existing schema.
*/
function upsc_quiz_update_8001() {
// Example update hook for future schema changes
// This would be used when updating the module to add new features
}