Note:

If you want to create a new page for developers, you should create it on the Moodle Developer Resource site.

Adding a Portfolio Button to a page: Difference between revisions

From MoodleDocs
Line 118: Line 118:
===reliance on large data and atomicity===
===reliance on large data and atomicity===
For more information on this see MDL-15934 - if you need to work with large amounts of data for the export (eg, whole database module instance, or whole glossary) you don't want to store it in the session in between calculating the sha1 (during the user interactive bit) and actually sending the data (can be in cron). Use set_export_data and get_export_data instead (provided by the parent class).
For more information on this see MDL-15934 - if you need to work with large amounts of data for the export (eg, whole database module instance, or whole glossary) you don't want to store it in the session in between calculating the sha1 (during the user interactive bit) and actually sending the data (can be in cron). Use set_export_data and get_export_data instead (provided by the parent class).
===complicated printing stuff===
Sometimes during prepare_package, you need to call functions in the libraries to render content as HTML that would normally also call portfolio_add_button.  This will result in 'you already have an export active in this session' error - to get around this, do something like
    $SESSION->portfoliointernal = true;
    modulename_print_some_htmlcontent();
    $SESSION->portfoliointernal = false;

Revision as of 15:23, 5 August 2008

Introduction

Adding an 'Add to Portfolio' button to any page is relatively trivial, there are just two things that you need to do:

Write a subclass

You can either subclass portfolio_caller_base for the general case, or portfolio_module_caller_base if you're somewhere inside mod/

This sounds scary, but really it's not! It's a very small class. portfolio_caller_base has abstract functions that you must override, and some functions that you can override if you want to do something special. You should call it something like $module_portfolio_caller, or in a more complicated case (say assignment/type/upload, assignment_upload_portfolio_caller)

If you're adding the portfolio button somewhere in a module, it's better to subclass portfolio_module_caller_base, which implements 2 of the below abstract methods for you.

Methods you must override

__construct

When your object is constructed, the contents of whatever callback arguments you passed to portfolio_add_button are passed back to you here in an array, so your chance to set member variables or do whatever you need is in the constructor.

get_navigation

During the export screens, it's desirable to still have some sensible navigation that logically follows from the place the user was before they started the export process. This function should return components to pass to build_nagivation (extralinks and cm). portfolio_module_caller_base implements this for you

prepare_package

prepares the package up before control is passed to the portfolio plugin. You should copy any files (or write out any files) into the temporary directory provided, where they'll be found by the portfolio plugin.

expected_time

You should return a constant here to indicate how long the transfer is expected to take. This should be based on the size of the file. There are three options, PORTFOLIO_TIME_LOW, PORTFOLIO_TIME_MODERATE, and PORTFOLIO_TIME_HIGH. The first means the user will not be asked if they want to wait for the transfer or not, they will just wait. The second and third mean they'll be given the option (and in the case of the third, advised not to). The portfolio plugin can override this if it wants (eg in the case of download, they always want to wait for the transfer)

check_permissions

portfolio/add.php will expect the caller to verify the user is allowed to export the given content. This function should perform any has_capability checks it needs to and return a booelan.

get_return_url

This is used for redirecting the user on the case of a cancelled export, or at the end of their export, they are offered the option of continuing back to where they were (what this function returns) or on to their portfolio. portfolio_module_caller_base implements this for you (but will use mod/modname/view.php)

display_name (static)

A nice language string for displaying the location of this export to the user (this is used to notify the user in case of duplicate exports that originated from different places in moodle (Eg exporting an assignment upload and a forum post attachment that are the same file)

get_sha1

Return a sha1 of the content being exported - used to detect duplicate exports later.

Methods you can override

supported_formats (static)

The formats this caller can support. At export time, both the plugin and the caller are polled for which formats they can support, and then the intersection is used to determine the export format. In the case that the intersection is greater than 1, the user is asked for their selection.

The available formats you can choose from are in portfolio_supported_formats and are constants PORTFOLIO_FORMAT_XXX. By default, the subclass defines PORTFOLIO_FORMAT_FILE.

has_export_config

If there's any addition config during the export process (for example, extra metadata), you can override this function to return true. If you do this, you must also override export_config_form and get_export_summary.

export_config_form

This function is called, and passed a moodle form object by reference to add elements to it. TODO: it would be nice to able to add validation at this point too.

export_config_validation

This follows the exact same format as the validation() function in the moodleform object.

get_allowed_export_config

If at any point, your caller is going to use set_export_config, you must implement this function to return an array of allowed config fields. (Note that you can set export time config even if you're not using interactive user config)

get_export_summary

If your plugin has overridden has_export_config, you must implement this to display nicely to the user on the confirmation screen. It should return a named array (keys are nice strings to describe the config, values are the config options)

Call portfolio_add_button in the appropriate place

Now that you've implemented this class, you just need to add the button. To do this, you require_once("$CFG->libdir/portfoliolib.php"); and call portfolio_add_button. It takes the following parameters:

$callbackclass

The name of the class you've made that subclassed portfolio_caller_base.

$callbackargs

An associative array of key=>value pairs you want passed to the constructor of your class. These must be primitives, as they are added as hidden form fields and cleaned to either PARAM_ALPHAEXT, PARAM_NUMERIC or PARAM_PATH. Weird stuff will happen if they're not compliant.

$callbackfile

This can be autodetected from the backtrace of where this function was called, but if your class definition isn't in the same file as the caller (eg if your caller is some .php script, but the class is in a lib.php file), you can pass it explicitly here.

$fullform

whether you want the full form with the dropmenu of available plugins or just a little icon. defaults to true. (using the icon will force a whole screen on the wizard)

$return

Whether you want the output returned or echoed. Defaults to false (echo)

A few extra notes on the caller base class

protected $course

There is a protected member variable, $course, that subclasses can set (with $this->set('course', $course); ).

portfolio_add_button tries to look for a course object at the point that it's called, by doing a global $COURSE which is hackish but mostly works. This is also used to build the navigation during the export process. If for some reason, your navigation doesn't include the current course, you can set it like this. You shouldn't need to in the majority of cases.

serialization

The caller object is stored in the user's session during the export process. In Moodle, session_start is called very early on, before the class definition is loaded. The portfolio/add.php and associated libraries work around this by loading the class definitions and then serializing and unserializing the objects again. However, if you're storing any real objects in your caller class, you will need to do this as well. See the assignment implementation for how this done (using php5's __wakeup function):


   public function __wakeup() {
       require_once($this->assignmentfile);
       $this->assignment = unserialize(serialize($this->assignment));
   }

reliance on large data and atomicity

For more information on this see MDL-15934 - if you need to work with large amounts of data for the export (eg, whole database module instance, or whole glossary) you don't want to store it in the session in between calculating the sha1 (during the user interactive bit) and actually sending the data (can be in cron). Use set_export_data and get_export_data instead (provided by the parent class).

complicated printing stuff

Sometimes during prepare_package, you need to call functions in the libraries to render content as HTML that would normally also call portfolio_add_button. This will result in 'you already have an export active in this session' error - to get around this, do something like


   $SESSION->portfoliointernal = true;
   modulename_print_some_htmlcontent();
   $SESSION->portfoliointernal = false;