2008-07-25 08:14:11 +00:00
< ? php
2012-01-30 15:37:46 +08:00
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
2009-05-02 13:23:22 +00:00
/**
* This file is the main controller to do with the portfolio export wizard .
2012-01-30 15:37:46 +08:00
*
* @ package core_portfolio
* @ copyright 2008 Penny Leach < penny @ catalyst . net . nz > ,
* Martin Dougiamas < http :// dougiamas . com >
* @ license http :// www . gnu . org / copyleft / gpl . html GNU GPL
2009-05-02 13:23:22 +00:00
*/
2016-02-26 17:47:58 +11:00
require_once ( __DIR__ . '/../config.php' );
2008-07-29 11:27:16 +00:00
2008-08-26 05:45:07 +00:00
if ( empty ( $CFG -> enableportfolios )) {
2022-04-12 09:38:41 +05:30
throw new \moodle_exception ( 'disabled' , 'portfolio' );
2008-07-29 11:27:16 +00:00
}
2008-07-25 08:14:11 +00:00
require_once ( $CFG -> libdir . '/portfoliolib.php' );
2009-12-12 11:27:07 +00:00
require_once ( $CFG -> libdir . '/portfolio/exporter.php' );
require_once ( $CFG -> libdir . '/portfolio/caller.php' );
require_once ( $CFG -> libdir . '/portfolio/plugin.php' );
2008-08-22 13:25:53 +00:00
2012-11-07 14:49:52 +08:00
$dataid = optional_param ( 'id' , 0 , PARAM_INT ); // The ID of partially completed export, corresponds to a record in portfolio_tempdata.
$type = optional_param ( 'type' , null , PARAM_SAFEDIR ); // If we're returning from an external system (postcontrol) for a single-export only plugin.
$cancel = optional_param ( 'cancel' , 0 , PARAM_RAW ); // User has cancelled the request.
$cancelsure = optional_param ( 'cancelsure' , 0 , PARAM_BOOL ); // Make sure they confirm first.
$logreturn = optional_param ( 'logreturn' , 0 , PARAM_BOOL ); // When cancelling, we can also come from the log page, rather than the caller.
$instanceid = optional_param ( 'instance' , 0 , PARAM_INT ); // The instance of configured portfolio plugin.
$courseid = optional_param ( 'course' , 0 , PARAM_INT ); // The courseid the data being exported belongs to (caller object should provide this later).
$stage = optional_param ( 'stage' , PORTFOLIO_STAGE_CONFIG , PARAM_INT ); // Stage of the export we're at (stored in the exporter).
$postcontrol = optional_param ( 'postcontrol' , 0 , PARAM_INT ); // When returning from some bounce to an external system, this gets passed.
$callbackcomponent = optional_param ( 'callbackcomponent' , null , PARAM_PATH ); // Callback component eg mod_forum - the component of the exporting content.
$callbackclass = optional_param ( 'callbackclass' , null , PARAM_ALPHAEXT ); // Callback class eg forum_portfolio_caller - the class to handle the exporting content.
$callerformats = optional_param ( 'callerformats' , null , PARAM_TAGLIST ); // Comma separated list of formats the specific place exporting content supports.
2008-08-22 13:25:53 +00:00
2009-05-02 13:23:22 +00:00
require_login (); // this is selectively called again with $course later when we know for sure which one we're in.
2013-07-03 14:39:10 +08:00
$PAGE -> set_context ( context_system :: instance ());
2009-11-17 14:01:25 +00:00
$PAGE -> set_url ( '/portfolio/add.php' , array ( 'id' => $dataid , 'sesskey' => sesskey ()));
2014-04-06 15:57:32 +12:00
$PAGE -> set_pagelayout ( 'admin' );
2008-07-25 08:14:11 +00:00
$exporter = null ;
2008-08-06 15:27:42 +00:00
2009-11-17 14:01:25 +00:00
if ( $postcontrol && $type && ! $dataid ) {
// we're returning from an external system that can't construct dynamic return urls
// this is a special "one export of this type only per session" case
if ( portfolio_static_function ( $type , 'allows_multiple_exports' )) {
throw new portfolio_exception ( 'multiplesingleresume' , 'portfolio' );
2008-07-25 08:14:11 +00:00
}
2009-11-17 14:01:25 +00:00
2009-11-19 07:03:53 +00:00
if ( ! $dataid = portfolio_export_type_to_id ( $type , $USER -> id )) {
2009-11-17 14:01:25 +00:00
throw new portfolio_exception ( 'invalidtempid' , 'portfolio' );
}
} else {
// we can't do this in the above case, because we're redirecting straight back from an external system
// this is not really ideal, but since we're in a "staged" wizard, the session key is checked in other stages.
require_sesskey (); // pretty much everything in this page is a write that could be hijacked, so just do this at the top here
2008-08-06 15:27:42 +00:00
}
2008-09-04 10:32:17 +00:00
2009-05-02 13:23:22 +00:00
// if we have a dataid, it means we're in the middle of an export,
// so rewaken it and continue.
if ( ! empty ( $dataid )) {
2008-08-22 13:25:53 +00:00
try {
$exporter = portfolio_exporter :: rewaken_object ( $dataid );
} catch ( portfolio_exception $e ) {
2008-09-04 10:32:17 +00:00
// this can happen in some cases, a cancel request is sent when something is already broken
// so process it elegantly and move on.
2008-08-22 13:25:53 +00:00
if ( $cancel ) {
2009-11-17 14:01:25 +00:00
if ( $logreturn ) {
redirect ( $CFG -> wwwroot . '/user/portfoliologs.php' );
}
2008-08-22 13:25:53 +00:00
redirect ( $CFG -> wwwroot );
} else {
2009-11-17 14:01:25 +00:00
throw $e ;
2008-08-22 13:25:53 +00:00
}
}
2009-05-02 13:23:22 +00:00
// we have to wake it up first before we can cancel it
// so temporary directories etc get cleaned up.
2008-08-22 13:25:53 +00:00
if ( $cancel ) {
2009-11-17 14:01:25 +00:00
if ( $cancelsure ) {
$exporter -> cancel_request ( $logreturn );
} else {
2011-03-18 16:19:59 +08:00
portfolio_export_pagesetup ( $PAGE , $exporter -> get ( 'caller' ));
2010-05-02 18:01:05 +00:00
$exporter -> print_header ( get_string ( 'confirmcancel' , 'portfolio' ));
2009-11-17 14:01:25 +00:00
echo $OUTPUT -> box_start ();
2010-02-26 15:30:59 +00:00
$yesbutton = new single_button ( new moodle_url ( '/portfolio/add.php' , array ( 'id' => $dataid , 'cancel' => 1 , 'cancelsure' => 1 , 'logreturn' => $logreturn )), get_string ( 'yes' ));
2009-12-03 14:26:37 +00:00
if ( $logreturn ) {
2010-07-21 20:16:49 +00:00
$nobutton = new single_button ( new moodle_url ( '/user/portfoliologs.php' ), get_string ( 'no' ));
2010-01-14 19:18:04 +00:00
} else {
2010-01-16 15:39:56 +00:00
$nobutton = new single_button ( new moodle_url ( '/portfolio/add.php' , array ( 'id' => $dataid )), get_string ( 'no' ));
2009-12-03 14:26:37 +00:00
}
echo $OUTPUT -> confirm ( get_string ( 'confirmcancel' , 'portfolio' ), $yesbutton , $nobutton );
2009-11-17 14:01:25 +00:00
echo $OUTPUT -> box_end ();
echo $OUTPUT -> footer ();
exit ;
}
2008-07-25 08:14:11 +00:00
}
2009-11-17 14:01:25 +00:00
// verify we still belong to the correct user and permissions are still ok
2008-08-22 13:25:53 +00:00
$exporter -> verify_rewaken ();
2009-05-02 13:23:22 +00:00
// if we don't have an instanceid in the exporter
// it means we've just posted from the 'choose portfolio instance' page
// so process that and start up the portfolio plugin
2008-08-04 16:07:37 +00:00
if ( ! $exporter -> get ( 'instance' )) {
2009-05-02 13:23:22 +00:00
if ( $instanceid ) {
2008-08-19 14:20:32 +00:00
try {
2009-05-02 13:23:22 +00:00
$instance = portfolio_instance ( $instanceid );
2008-08-19 14:20:32 +00:00
} catch ( portfolio_exception $e ) {
portfolio_export_rethrow_exception ( $exporter , $e );
2008-08-04 16:07:37 +00:00
}
2009-05-02 13:23:22 +00:00
// this technically shouldn't happen but make sure anyway
2008-08-04 16:07:37 +00:00
if ( $broken = portfolio_instance_sanity_check ( $instance )) {
2008-09-04 10:32:17 +00:00
throw new portfolio_export_exception ( $exporter , $broken [ $instance -> get ( 'id' )], 'portfolio_' . $instance -> get ( 'plugin' ));
2008-08-04 16:07:37 +00:00
}
2009-05-02 13:23:22 +00:00
// now we're all set up, ready to go
2008-08-04 16:07:37 +00:00
$instance -> set ( 'user' , $USER );
$exporter -> set ( 'instance' , $instance );
2008-08-09 14:24:58 +00:00
$exporter -> save ();
2008-08-04 16:07:37 +00:00
}
}
2009-11-17 14:01:06 +00:00
portfolio_export_pagesetup ( $PAGE , $exporter -> get ( 'caller' )); // this calls require_login($course) if it can..
2009-05-02 13:23:22 +00:00
// completely new request, look to see what information we've been passed and set up the exporter object.
2008-07-25 08:14:11 +00:00
} else {
2009-05-02 13:23:22 +00:00
// you cannot get here with no information for us, we must at least have the caller.
2008-09-16 17:50:55 +00:00
if ( empty ( $_GET ) && empty ( $_POST )) {
portfolio_exporter :: print_expired_export ();
}
2008-07-25 08:14:11 +00:00
// we'e just posted here for the first time and have might the instance already
2009-05-02 13:23:22 +00:00
if ( $instanceid ) {
2008-09-04 10:32:17 +00:00
// this can throw exceptions but there's no point catching and rethrowing here
// as the exporter isn't created yet.
2009-05-02 13:23:22 +00:00
$instance = portfolio_instance ( $instanceid );
2008-07-25 08:14:11 +00:00
if ( $broken = portfolio_instance_sanity_check ( $instance )) {
2008-08-19 14:20:32 +00:00
throw new portfolio_exception ( $broken [ $instance -> get ( 'id' )], 'portfolio_' . $instance -> get ( 'plugin' ));
2008-07-25 08:14:11 +00:00
}
$instance -> set ( 'user' , $USER );
} else {
$instance = null ;
}
2009-05-02 13:23:22 +00:00
// we must be passed this from the caller, we cannot start a new export
// without knowing information about what part of moodle we come from.
2012-11-07 14:49:52 +08:00
if ( empty ( $callbackcomponent ) || empty ( $callbackclass )) {
2009-12-03 14:26:37 +00:00
debugging ( 'no callback file or class' );
2008-09-16 17:50:55 +00:00
portfolio_exporter :: print_expired_export ();
}
2008-07-25 08:14:11 +00:00
2009-05-02 13:23:22 +00:00
// so each place in moodle can pass callback args here
// process the entire request looking for ca_*
// be as lenient as possible while still being secure
// so only accept certain parameter types.
2008-07-25 08:14:11 +00:00
$callbackargs = array ();
2008-08-01 12:23:32 +00:00
foreach ( array_keys ( array_merge ( $_GET , $_POST )) as $key ) {
2008-07-25 08:14:11 +00:00
if ( strpos ( $key , 'ca_' ) === 0 ) {
if ( ! $value = optional_param ( $key , false , PARAM_ALPHAEXT )) {
2012-05-11 11:34:34 +08:00
if ( ! $value = optional_param ( $key , false , PARAM_FLOAT )) {
2008-07-25 08:14:11 +00:00
$value = optional_param ( $key , false , PARAM_PATH );
}
}
2009-05-02 13:23:22 +00:00
// strip off ca_ for niceness
2008-07-25 08:14:11 +00:00
$callbackargs [ substr ( $key , 3 )] = $value ;
}
}
2012-11-07 14:49:52 +08:00
// Ensure that we found a file we can use, if not throw an exception.
portfolio_include_callback_file ( $callbackcomponent , $callbackclass );
2008-07-25 08:14:11 +00:00
$caller = new $callbackclass ( $callbackargs );
2008-08-22 16:35:26 +00:00
$caller -> set ( 'user' , $USER );
2009-12-03 14:26:37 +00:00
if ( $formats = explode ( ',' , $callerformats )) {
$caller -> set_formats_from_button ( $formats );
}
2008-09-11 13:42:58 +00:00
$caller -> load_data ();
2009-05-02 13:23:22 +00:00
// this must check capabilities and either throw an exception or return false.
2008-07-25 08:14:11 +00:00
if ( ! $caller -> check_permissions ()) {
2008-09-04 10:32:17 +00:00
throw new portfolio_caller_exception ( 'nopermissions' , 'portfolio' , $caller -> get_return_url ());
2008-07-25 08:14:11 +00:00
}
2009-11-17 14:01:06 +00:00
portfolio_export_pagesetup ( $PAGE , $caller ); // this calls require_login($course) if it can..
2008-07-25 08:14:11 +00:00
2009-09-03 06:59:25 +00:00
// finally! set up the exporter object with the portfolio instance, and caller information elements
2012-11-07 14:49:52 +08:00
$exporter = new portfolio_exporter ( $instance , $caller , $callbackcomponent );
2009-05-02 13:23:22 +00:00
// set the export-specific variables, and save.
2008-07-25 08:14:11 +00:00
$exporter -> set ( 'user' , $USER );
2008-08-06 15:27:42 +00:00
$exporter -> save ();
2008-07-25 08:14:11 +00:00
}
if ( ! $exporter -> get ( 'instance' )) {
// we've just arrived but have no instance
2009-05-02 13:23:22 +00:00
// in this case the exporter object and the caller object have been set up above
// so just make a little form to select the portfolio plugin instance,
// which is the last thing to do before starting the export.
2009-12-03 14:26:37 +00:00
//
// first check to make sure there is actually a point
$options = portfolio_instance_select (
portfolio_instances (),
$exporter -> get ( 'caller' ) -> supported_formats (),
get_class ( $exporter -> get ( 'caller' )),
2009-12-15 12:36:49 +00:00
$exporter -> get ( 'caller' ) -> get_mimetype (),
2009-12-03 14:26:37 +00:00
'instance' ,
true ,
true
);
if ( empty ( $options )) {
throw new portfolio_export_exception ( $exporter , 'noavailableplugins' , 'portfolio' );
} else if ( count ( $options ) == 1 ) {
// no point displaying a form, just redirect.
2012-05-13 15:33:02 +08:00
$optionskeys = array_keys ( $options );
$instance = array_shift ( $optionskeys );
2009-12-03 14:26:37 +00:00
redirect ( $CFG -> wwwroot . '/portfolio/add.php?id= ' . $exporter -> get ( 'id' ) . '&instance=' . $instance . '&sesskey=' . sesskey ());
}
2009-12-12 11:27:07 +00:00
// be very selective about not including this unless we really need to
require_once ( $CFG -> libdir . '/portfolio/forms.php' );
2009-12-03 14:26:37 +00:00
$mform = new portfolio_instance_select ( '' , array ( 'id' => $exporter -> get ( 'id' ), 'caller' => $exporter -> get ( 'caller' ), 'options' => $options ));
2008-08-04 16:07:37 +00:00
if ( $mform -> is_cancelled ()) {
2008-08-06 15:27:42 +00:00
$exporter -> cancel_request ();
2008-08-04 16:07:37 +00:00
} else if ( $fromform = $mform -> get_data ()){
2008-08-06 15:27:42 +00:00
redirect ( $CFG -> wwwroot . '/portfolio/add.php?instance=' . $fromform -> instance . '&id=' . $exporter -> get ( 'id' ));
2008-08-04 16:07:37 +00:00
exit ;
}
else {
2010-05-02 18:01:05 +00:00
$exporter -> print_header ( get_string ( 'selectplugin' , 'portfolio' ));
2009-08-18 05:18:28 +00:00
echo $OUTPUT -> box_start ();
2008-08-04 16:07:37 +00:00
$mform -> display ();
2009-08-18 05:18:28 +00:00
echo $OUTPUT -> box_end ();
2009-08-06 14:09:50 +00:00
echo $OUTPUT -> footer ();
2008-08-04 16:07:37 +00:00
exit ;
2008-07-25 08:14:11 +00:00
}
}
2009-05-02 13:23:22 +00:00
// if we haven't been passed &stage= grab it from the exporter.
if ( ! $stage ) {
2008-08-19 10:17:39 +00:00
$stage = $exporter -> get ( 'stage' );
}
2008-08-09 14:24:58 +00:00
// for places returning control to pass (rather than PORTFOLIO_STAGE_PACKAGE
// which is unstable if they can't get to the constant (eg external system)
2009-05-02 13:23:22 +00:00
$alreadystolen = false ;
if ( $postcontrol ) { // the magic request variable plugins must pass on returning here
2008-08-19 14:20:32 +00:00
try {
2009-05-02 13:23:22 +00:00
// allow it to read whatever gets sent back in the request
// this is useful for plugins that redirect away and back again
// adding a token to the end of the url, for example box.net
2008-08-19 14:20:32 +00:00
$exporter -> instance () -> post_control ( $stage , array_merge ( $_GET , $_POST ));
} catch ( portfolio_plugin_exception $e ) {
portfolio_export_rethrow_exception ( $exporter , $e );
}
2009-05-02 13:23:22 +00:00
$alreadystolen = true ; // remember this so we don't get caught in a steal control loop!
2008-08-09 14:24:58 +00:00
}
2008-08-19 10:17:39 +00:00
2008-09-04 10:32:17 +00:00
// actually do the work now..
2008-07-25 08:14:11 +00:00
$exporter -> process_stage ( $stage , $alreadystolen );
2009-11-01 12:51:40 +00:00