From: mjollnir_ Date: Wed, 10 Sep 2008 16:34:08 +0000 (+0000) Subject: MDL-16423 - refactor of portfolio_add_button into class for much better usability X-Git-Url: http://git.mjollnir.org/gw?a=commitdiff_plain;h=ce09fecc99da1bb95177ede4aa267c6be6ac641b;p=moodle.git MDL-16423 - refactor of portfolio_add_button into class for much better usability currently portfolio_add_button still exists and just acts as a wrapper around the class so i have not changed any calling code to use the new objects yet. --- diff --git a/lang/en_utf8/portfolio.php b/lang/en_utf8/portfolio.php index cc327a6702..f3040f4e7f 100644 --- a/lang/en_utf8/portfolio.php +++ b/lang/en_utf8/portfolio.php @@ -56,6 +56,7 @@ $string['invalidproperty'] = 'Could not find that property ($a->property of $a-> $string['invalidexportproperty'] = 'Could not find that export config property ($a->property of $a->class)'; $string['invaliduserproperty'] = 'Could not find that user config property ($a->property of $a->class)'; $string['invalidconfigproperty'] = 'Could not find that config property ($a->property of $a->class)'; +$string['invalidbuttonproperty'] = 'Could not find that property ($a) of portfolio_button'; $string['manageportfolios'] = 'Manage portfolios'; $string['manageyourportfolios'] = 'Manage your portfolios'; $string['moderatefilesizethreshold'] = 'Moderate transfer filesize'; @@ -63,8 +64,10 @@ $string['moderatefilesizethresholddesc'] = 'Filesizes over this threshold will b $string['moderatedbsizethreshold'] = 'Moderate transfer dbsize'; $string['moderatedbsizethresholddesc'] = 'Number of db records over which will be considered to take a moderate amount of time to transfer'; $string['multipledisallowed'] = 'Trying to create another instance of a plugin that has disallowed multiple instances ($a)'; +$string['mustsetcallbackoptions'] = 'You must set the callback options either in the portfolio_add_button constructor or using the set_callback_options method'; $string['noavailableplugins'] = 'Sorry, but there are no available portfolios for you to export to'; $string['nocallbackfile'] = 'Something in the module you\'re trying to export from is broken - couldn\'t find a required file ($a)'; +$string['nocallbackclass'] = 'Could not find the callback class to use ($a)'; $string['nocommonformats'] = 'No common formats between any available portfolio plugin and the calling location $a'; $string['nopermissions'] = 'Sorry but you do not have the required permissions to export files from this area'; $string['nonprimative'] = 'A non primative value was passed as a callback argument to portfolio_add_button. Refusing to continue. The key was $a->key and the value was $a->value'; diff --git a/lib/portfolio/exceptions.php b/lib/portfolio/exceptions.php index aad25ac3b8..52476b25d7 100644 --- a/lib/portfolio/exceptions.php +++ b/lib/portfolio/exceptions.php @@ -78,4 +78,8 @@ class portfolio_caller_exception extends portfolio_exception {} */ class portfolio_plugin_exception extends portfolio_exception {} +/** +* exception for interacting with the button class +*/ +class portfolio_button_exception extends portfolio_exception {} ?> diff --git a/lib/portfoliolib.php b/lib/portfoliolib.php index 1850b8a0cc..c39b7700ac 100644 --- a/lib/portfoliolib.php +++ b/lib/portfoliolib.php @@ -38,150 +38,248 @@ require_once($CFG->libdir . '/portfolio/plugin.php'); // the base classes f require_once($CFG->libdir . '/portfolio/caller.php'); // the base classes for calling code /** -* Entry point to add an 'add to portfolio' button to a page somewhere in moodle +* use this to add a portfolio button or icon or form to a page * -* This function does not check permissions. the caller must check permissions first. +* These class methods do not check permissions. the caller must check permissions first. * Later, during the export process, the caller class is instantiated and the check_permissions method is called -* This does not happen in this function - you are responsible for it. -* -* @param string $callbackclass name of the class containing the callback functions -* activity modules should ALWAYS use their name_portfolio_caller -* other locations must use something unique -* @param mixed $callbackargs this can be an array or hash of arguments to pass -* back to the callback functions (passed by reference) -* these MUST be primatives to be added as hidden form fields. -* and the values get cleaned to PARAM_ALPHAEXT or PARAM_NUMBER or PARAM_PATH -* @param string $callbackfile this can be autodetected if it's in the same file as your caller, -* but more often, the caller is a script.php and the class in a lib.php -* so you can pass it here if necessary. -* this path should be relative (ie, not include) dirroot, eg '/mod/forum/lib.php' -* @param int $format format to display the button or form or icon or link. -* See constants PORTFOLIO_ADD_XXX for more info. -* optional, defaults to PORTFOLI_ADD_FULL_FORM -* @param str $addstr string to use for the button or icon alt text or link text. -* this is whole string, not key. optional, defaults to 'Add to portfolio'; -* @param boolean $return whether to echo or return content (optional defaults to false (echo) -* @param array $callersupports if the calling code knows better than the static method on the calling class (supported_formats) -* eg, if there's a file that might be an image, you can pass it here instead -* {@see portfolio_format_from_file} for how to get the appropriate formats to pass here. +* +* This class can be used like this: +* $button = new portfolio_add_button(); +* $button->set_callback_options('name_of_caller_class', array('id' => 6), '/your/mod/lib.php'); +* $button->render(PORTFOLIO_ADD_FULL_FORM, get_string('addeverythingtoportfolio', 'yourmodule')); +* +* or like this: +* $button = new portfolio_add_button(array('callbackclass' => 'name_of_caller_class', 'callbackargs' => array('id' => 6), 'callbackfile' => '/your/mod/lib.php')); +* $somehtml .= $button->to_html(PORTFOLIO_ADD_TEXT_LINK); +* +* See http://docs.moodle.org/en/Development:Adding_a_Portfolio_Button_to_a_page for more information */ -function portfolio_add_button($callbackclass, $callbackargs, $callbackfile=null, $format=PORTFOLIO_ADD_FULL_FORM, $addstr=null, $return=false, $callersupports=null) { - - global $SESSION, $CFG, $COURSE, $USER; - - if (empty($CFG->enableportfolios)) { - return; - } - - if (!$instances = portfolio_instances()) { - return; - } - - if (defined('PORTFOLIO_INTERNAL')) { - // something somewhere has detected a risk of this being called during inside the preparation - // eg forum_print_attachments - return; - } - - if (isset($SESSION->portfolioexport)) { - $a = new StdClass; - $a->cancel = $CFG->wwwroot . '/portfolio/add.php?cancel=1'; - $a->finish = $CFG->wwwroot . '/portfolio/add.php?id=' . $SESSION->portfolioexport; - throw new portfolio_exception('alreadyexporting', 'portfolio', null, $a); - } - - if (empty($callbackfile)) { - $backtrace = debug_backtrace(); - if (!array_key_exists(0, $backtrace) || !array_key_exists('file', $backtrace[0]) || !is_readable($backtrace[0]['file'])) { - debugging(get_string('nocallbackfile', 'portfolio')); - return; +class portfolio_add_button { + + private $callbackclass; + private $callbackargs; + private $callbackfile; + private $formats; + private $instances; + + /** + * constructor. either pass the options here or set them using the helper methods. + * generally the code will be clearer if you use the helper methods. + * + * @param array $options keyed array of options: + * key 'callbackclass': name of the caller class (eg forum_portfolio_caller') + * key 'callbackargs': the array of callback arguments your caller class wants passed to it in the constructor + * key 'callbackfile': the file containing the class definition of your caller class. + * See set_callback_options for more information on these three. + * key 'formats': an array of PORTFOLIO_FORMATS this caller will support + * See set_formats for more information on this. + */ + public function __construct($options=null) { + global $SESSION; + if (isset($SESSION->portfolioexport)) { + $a = new StdClass; + $a->cancel = $CFG->wwwroot . '/portfolio/add.php?cancel=1'; + $a->finish = $CFG->wwwroot . '/portfolio/add.php?id=' . $SESSION->portfolioexport; + throw new portfolio_button_exception('alreadyexporting', 'portfolio', null, $a); + } + if (empty($options)) { + return true; + } + foreach ((array)$options as $key => $value) { + if (!in_array($key, $constructoroptions)) { + throw new portfolio_button_exception('invalidbuttonproperty', 'portfolio', $key); + } + $this->{$key} = $value; } + $this->instances = portfolio_instances(); + } + + /* + * @param string $class name of the class containing the callback functions + * activity modules should ALWAYS use their name_portfolio_caller + * other locations must use something unique + * @param mixed $argarray this can be an array or hash of arguments to pass + * back to the callback functions (passed by reference) + * these MUST be primatives to be added as hidden form fields. + * and the values get cleaned to PARAM_ALPHAEXT or PARAM_NUMBER or PARAM_PATH + * @param string $file this can be autodetected if it's in the same file as your caller, + * but often, the caller is a script.php and the class in a lib.php + * so you can pass it here if necessary. + * this path should be relative (ie, not include) dirroot, eg '/mod/forum/lib.php' + */ + public function set_callback_options($class, array $argarray, $file=null) { + global $CFG; + if (empty($file)) { + $backtrace = debug_backtrace(); + if (!array_key_exists(0, $backtrace) || !array_key_exists('file', $backtrace[0]) || !is_readable($backtrace[0]['file'])) { + throw new portfolio_button_exception('nocallbackfile', 'portfolio'); + } - $callbackfile = substr($backtrace[0]['file'], strlen($CFG->dirroot)); - } else { - if (!is_readable($CFG->dirroot . $callbackfile)) { - debugging(get_string('nocallbackfile', 'portfolio')); + $file = substr($backtrace[0]['file'], strlen($CFG->dirroot)); + } else if (!is_readable($CFG->dirroot . $file)) { + throw new portfolio_button_exception('nocallbackfile', 'portfolio', $file); + } + $this->callbackfile = $file; + require_once($CFG->dirroot . $file); + if (!class_exists($class)) { + throw new portfolio_button_exception('nocallbackclass', 'portfolio', $class); + } + $this->callbackclass = $class; + $this->callbackargs = $argarray; + } + + /* + * @param array $formats if the calling code knows better than the static method on the calling class (supported_formats) + * eg, if it's going to be a single file, or if you know it's HTML, you can pass it here instead + * this is almost always the case so you should always use this. + * {@see portfolio_format_from_file} for how to get the appropriate formats to pass here for uploaded files. + */ + public function set_formats($formats=null) { + if (is_string($formats)) { + $formats = array($formats); + } + if (empty($formats)) { + if (empty($this->callbackclass)) { + throw new portfolio_button_exception('noformatsorclass', 'portfolio'); + } + $formats = call_user_func(array($this->callbackclass, 'supported_formats')); + } + $this->formats = $formats; + } + + /* + * echo the form/button/icon/text link to the page + * + * @param int $format format to display the button or form or icon or link. + * See constants PORTFOLIO_ADD_XXX for more info. + * optional, defaults to PORTFOLI_ADD_FULL_FORM + * @param str $addstr string to use for the button or icon alt text or link text. + * this is whole string, not key. optional, defaults to 'Add to portfolio'; + */ + public function render($format=null, $addstr=null) { + echo $this->tohtml($format, $addstr); + } + + /* + * returns the form/button/icon/text link as html + * + * @param int $format format to display the button or form or icon or link. + * See constants PORTFOLIO_ADD_XXX for more info. + * optional, defaults to PORTFOLI_ADD_FULL_FORM + * @param str $addstr string to use for the button or icon alt text or link text. + * this is whole string, not key. optional, defaults to 'Add to portfolio'; + */ + public function to_html($format=null, $addstr=null) { + global $CFG, $COURSE; + if (!$this->is_renderable()) { return; } - } - - require_once($CFG->dirroot . $callbackfile); + if (empty($this->callbackclass) || $this->callbackfile) { + throw new portfolio_button_exception('mustcallsetcallbackoptions', 'portfolio'); + } + if (empty($this->formats)) { + // use the caller defaults + $this->set_formats(); + } + $formoutput = '
' . "\n"; + $linkoutput = ''; + } + $formoutput .= "\n" . ''; + $formoutput .= "\n" . ''; + $formoutput .= "\n" . ''; + $linkoutput .= 'callbackfile=' . $this->callbackfile . '&callbackclass=' + . $this->callbackclass . '&course=' . (!empty($COURSE) ? $COURSE->id : 0); + $selectoutput = ''; + if (count($this->instances) == 1) { + $instance = array_shift($this->instances); + $formats = portfolio_supported_formats_intersect($this->formats, $instance->supported_formats()); + if (count($formats) == 0) { + // bail. no common formats. + debugging(get_string('nocommonformats', 'portfolio', $this->callbackclass)); + return; + } + if ($error = portfolio_instance_sanity_check($instance)) { + // bail, plugin is misconfigured + debugging(get_string('instancemisconfigured', 'portfolio', get_string($error[$instance->get('id')], 'portfolio_' . $instance->get('plugin')))); + return; + } + $formoutput .= "\n" . ''; + $linkoutput .= '&instance=' . $instance->get('id'); + } + else { + $selectoutput = portfolio_instance_select($this->instances, $this->formats, $this->callbackclass, 'instance', true); + } - if (empty($callersupports)) { - $callersupports = call_user_func(array($callbackclass, 'supported_formats')); + if (empty($addstr)) { + $addstr = get_string('addtoportfolio', 'portfolio'); + } + if (empty($format)) { + $format = PORTFOLIO_ADD_FULL_FORM; + } + switch ($format) { + case PORTFOLIO_ADD_FULL_FORM: + $formoutput .= $selectoutput; + $formoutput .= "\n" . ''; + $formoutput .= "\n" . ''; + break; + case PORTFOLIO_ADD_ICON_FORM: + $formoutput .= $selectoutput; + $formoutput .= "\n" . ''; + $formoutput .= "\n" . ''; + break; + case PORTFOLIO_ADD_ICON_LINK: + $linkoutput .= '"> . $addstr .
'; + break; + case PORTFOLIO_ADD_TEXT_LINK: + $linkoutput .= '">' . $addstr .''; + break; + default: + debugging(get_string('invalidaddformat', 'portfolio', $format)); + } + $output = (in_array($format, array(PORTFOLIO_ADD_FULL_FORM, PORTFOLIO_ADD_ICON_FORM)) ? $formoutput : $linkoutput); + return $output; } - $formoutput = '
' . "\n"; - $linkoutput = ''; - } - $formoutput .= "\n" . ''; - $formoutput .= "\n" . ''; - $formoutput .= "\n" . ''; - $linkoutput .= 'callbackfile=' . $callbackfile . '&callbackclass=' - . $callbackclass . '&course=' . (!empty($COURSE) ? $COURSE->id : 0); - $selectoutput = ''; - if (count($instances) == 1) { - $instance = array_shift($instances); - $formats = portfolio_supported_formats_intersect($callersupports, $instance->supported_formats()); - if (count($formats) == 0) { - // bail. no common formats. - debugging(get_string('nocommonformats', 'portfolio', $callbackclass)); - return; + if (defined('PORTFOLIO_INTERNAL')) { + // something somewhere has detected a risk of this being called during inside the preparation + // eg forum_print_attachments + return false; } - if ($error = portfolio_instance_sanity_check($instance)) { - // bail, plugin is misconfigured - debugging(get_string('instancemisconfigured', 'portfolio', get_string($error[$instance->get('id')], 'portfolio_' . $instance->get('plugin')))); - return; + if (!$this->instances) { + return false; } - $formoutput .= "\n" . ''; - $linkoutput .= '&instance=' . $instance->get('id'); + return true; } - else { - $selectoutput = portfolio_instance_select($instances, $callersupports, $callbackclass, 'instance', true); - } - - if (empty($addstr)) { - $addstr = get_string('addtoportfolio', 'portfolio'); - } - if (empty($format)) { - $format = PORTFOLIO_ADD_FULL_FORM; - } - switch ($format) { - case PORTFOLIO_ADD_FULL_FORM: - $formoutput .= $selectoutput; - $formoutput .= "\n" . ''; - $formoutput .= "\n" . ''; - break; - case PORTFOLIO_ADD_ICON_FORM: - $formoutput .= $selectoutput; - $formoutput .= "\n" . ''; - $formoutput .= "\n" . ''; - break; - case PORTFOLIO_ADD_ICON_LINK: - $linkoutput .= '"> . $addstr .
'; - break; - case PORTFOLIO_ADD_TEXT_LINK: - $linkoutput .= '">' . $addstr .''; - break; - default: - debugging(get_string('invalidaddformat', 'portfolio', $format)); - } - $output = (in_array($format, array(PORTFOLIO_ADD_FULL_FORM, PORTFOLIO_ADD_ICON_FORM)) ? $formoutput : $linkoutput); +} + + +function portfolio_add_button($callbackclass, $callbackargs, $callbackfile=null, $format=PORTFOLIO_ADD_FULL_FORM, $addstr=null, $return=false, $callersupports=null) { + $button = new portfolio_add_button(); + $button->set_callback_options($callbackclass, $callbackargs, $callbackfile); + $button->set_formats($callersupports); if ($return) { - return $output; - } else { - echo $output; + return $button->to_html($format, $addstr); } - return true; + $button->render(); } /**