Plugin Development

Interview Questions: Plugin Types, Versioning, and Upgrades

Q1: What are the essential files for a Moodle plugin?

  • version.php: Metadata (version, requires, component name).
  • lang/en/pluginname.php: Language strings.
  • db/install.xml: Database schema (optional).
  • lib.php: Core functions (optional, but common).

Q2: How do you perform a database upgrade in a plugin?

1. Update the version number in version.php.

2. Add the upgrade logic in db/upgrade.php inside the xmldb_pluginname_upgrade($oldversion) function.

3. Use the XMLDB manager to add/modify tables or fields.

if ($oldversion < 2023101001) {
    // Define field
    $table = new xmldb_table('my_table');
    $field = new xmldb_field('new_col', XMLDB_TYPE_INTEGER, '10', null, null, null, null);
    
    // Add field
    if (!$dbman->field_exists($table, $field)) {
        $dbman->add_field($table, $field);
    }
    
    upgrade_plugin_savepoint(true, 2023101001, 'local_myplugin');
}

Q3: What is the difference between a 'Block' and a 'Module'?

Modules (Activities/Resources): Located in /mod. They are the main content of a course (e.g., Quiz, Assignment, Page). They have grades, completion tracking, and occupy the central column.

Blocks: Located in /blocks. They are small widgets that sit on the side (left/right) or dashboard (e.g., Calendar, Online Users). They provide auxiliary information or tools.

Q4: How do you declare a new capability for your plugin?

Capabilities are declared in db/access.php. You define the capability name (e.g., local/myplugin:view), the risk bitmask, the context level (e.g., CONTEXT_SYSTEM), and default permissions for archetypes (e.g., 'manager' => CAP_ALLOW).

Q5: What is the purpose of 'db/services.php'?

db/services.php is used to register external web services functions. It defines the function name, class path, method name, description, and required capabilities. It allows your plugin to expose an API to external applications.

Q6: How do you add a scheduled task to a plugin?

1. Create a class in classes/task/my_task.php extending \core\task\scheduled_task.

2. Implement get_name() and execute().

3. Register the task in db/tasks.php with its schedule (minute, hour, day, etc.).

Q7: What is the 'local' plugin type used for?

The local plugin type (/local) is a catch-all for site-wide customizations that don't fit into other standard plugin types. It's ideal for background tasks, event observers, web services, or extending navigation globally.

Q8: How do you include JavaScript in a plugin?

The modern way is to create an AMD module in amd/src/script.js. Moodle compiles this to amd/build/script.min.js. In PHP, you load it using $PAGE->requires->js_call_amd('pluginname/script', 'init', [$params]);.

Q9: How do you handle plugin dependencies?

Dependencies are defined in version.php using the $plugin->dependencies array. You specify the component name and the minimum required version. Moodle checks these during installation and prevents the plugin from being installed if dependencies are missing.

Q10: What is the String API and `get_string()`?

The String API manages internationalization (i18n). get_string('identifier', 'component', $a) retrieves a localized string. The $a parameter is used to pass variables into the string placeholders (e.g., {$a->name}).

Q11: How do you run unit tests for a plugin?

Moodle uses PHPUnit for backend testing. You must initialize the test environment (php admin/tool/phpunit/cli/init.php) and then run tests using the vendor binary, filtering by your plugin path: vendor/bin/phpunit --group=local_myplugin or pointing to the specific test file.

Q12: How do you handle language strings in a plugin?

Strings are stored in lang/en/pluginname.php as $string['key'] = 'Value';. In code, retrieve them using get_string('key', 'pluginname'). This supports internationalization (i18n).

Q13: What is 'db/events.php'?

db/events.php is used to register event observers. It maps an event class name (e.g., \core\event\user_created) to a callback function or method in your plugin that should execute when that event is triggered.

Q14: How do you create a custom database table for a plugin?

Use the XMLDB editor (in Site Admin > Development) to define the table structure. Save the XML to db/install.xml. Moodle will automatically create the table when the plugin is installed.

Q15: What is the 'settings.php' file?

settings.php defines the configuration options for the plugin that appear in the Site Administration tree. You use $settings->add() to add fields like text boxes, checkboxes, or selects.

Q16: How do you use the Moodle Form API?

Create a class extending moodleform (usually in classes/form/my_form.php or locallib.php). Define the form fields in the definition() method using $mform->addElement(). Instantiate and display it in your script.

Q17: What is the 'classes' directory for?

The classes directory is for autoloaded PHP classes. Moodle uses a namespace mapping: a class \plugintype_pluginname\output\renderer maps to plugintype/pluginname/classes/output/renderer.php.

Q18: How do you add a new page to Moodle via a plugin?

Create a PHP script (e.g., index.php) in your plugin folder. Setup the page using $PAGE->set_url(), $PAGE->set_context(), check permissions, and output content using $OUTPUT.

Q19: What is 'db/messages.php'?

db/messages.php defines message providers for the plugin. This allows the plugin to send notifications (email, popup, mobile) through Moodle's messaging system, which users can configure in their preferences.

Q20: How do you uninstall a plugin properly?

Usually, deleting the folder and letting Moodle detect it is enough. However, for cleanup, you can include a db/uninstall.php file to perform custom cleanup tasks (like removing external files) before the database tables are dropped.

Q21: What is the 'auth' plugin type?

Authentication plugins (/auth) handle user login and account creation. Examples include Manual, LDAP, SAML, and OAuth2. They implement methods to validate credentials and sync user data.

Q22: What is the 'enrol' plugin type?

Enrollment plugins (/enrol) handle how users are added to courses. Examples include Manual, Self, PayPal, and Cohort sync. They manage role assignments within the course context.

Q23: What is the 'theme' plugin type?

Theme plugins (/theme) control the visual appearance of the site. They use CSS (SCSS), Mustache templates, and renderers to override the default look and feel.

Q24: How do you use 'Unit Tests' in a plugin?

Unit tests are placed in tests/ directory. They extend advanced_testcase. You run them using PHPUnit. They are essential for verifying the logic of your plugin functions and classes.

Q25: What is 'db/mobile.php'?

db/mobile.php is used to configure support for the Moodle Mobile App. It can define handlers to display plugin content natively within the app or delegate to the browser.

Q26: How do you restrict access to a plugin script?

Use require_login() to ensure the user is authenticated. Then use require_capability('plugintype/pluginname:capability', $context) to ensure they have the specific permission needed.

Q27: What is the 'repository' plugin type?

Repository plugins (/repository) allow users to bring content into Moodle from external sources (e.g., Google Drive, Dropbox, Wikimedia) via the File Picker.

Q28: What is the 'portfolio' plugin type?

Portfolio plugins (/portfolio) allow users to export content (like forum posts or assignment submissions) from Moodle to external systems (e.g., Mahara, Google Docs).

Q29: How do you handle file uploads in a plugin form?

Use the filemanager element in your form definition. In the processing logic, use file_save_draft_area_files() to move files from the draft area to permanent storage associated with the plugin record.

Q30: What is 'db/renamedclasses.php'?

This file is used when you refactor and rename classes. It maps old class names to new ones, allowing Moodle's class loader to find them and maintain backward compatibility during upgrades.

Q31: How do you add a navigation node to the course menu?

In your plugin's lib.php, implement the _extend_navigation_course() callback function. Use the passed navigation object to add a new node with a label and URL.

Q32: What is the 'availability' plugin type?

Availability plugins (/availability/condition) define conditions for restricting access to activities or sections (e.g., "Grade must be > 80%", "Date must be after X").

Q33: How do you validate form data?

In your form class, override the validation($data, $files) method. Check the $data array for errors. Return an array of errors where keys are field names and values are error messages. If the array is empty, validation passes.