cm = get_coursemodule_from_id('sloodle', $id))) {
sloodle_debug("Failed to load course module instance #$id.
");
return false;
}
// Make sure the module is visible
if ($this->cm->visible == 0) {
sloodle_debug("Error: course module instance #$id not visible.
");
return false;
}
// Load from the primary table: sloodle instance
if (!($this->sloodle_instance = sloodle_get_record('sloodle', 'id', $this->cm->instance))) {
sloodle_debug("Failed to load Sloodle module with instance ID #{$cm->instance}.
");
return false;
}
// Load from the secondary table: sloodle_presenter
if (!($this->presenter = sloodle_get_record('sloodle_presenter', 'sloodleid', $this->cm->instance))) {
sloodle_debug("Failed to load secondary module table with instance ID #{$this->cm->instance}.
");
return false;
}
return true;
}
/**
* Gets an array of absolute URLs to images in this slideshow, all correctly ordered.
* @return 2d numeric array, each element associates an entry ID to a numeric array of URL string, the name of the source type, and the name of the slide.
*/
function get_entry_urls()
{
// Search the database for entries
$recs = sloodle_get_records_select_params('sloodle_presenter_entry', "sloodleid = ? ", array($this->sloodle_instance->id), 'ordering');
if (!$recs) return array();
// Format it all nicely into a simple array
$output = array();
foreach ($recs as $r) {
// Substitute the source data for the name if no name is given.
$name = '';
if (isset($r->name)){
$name = $r->name;
}
if (empty($name)) $name = $r->source;
$output[$r->id] = array($r->source, $r->type, $name);
}
return $output;
}
/**
* Gets a specific slide from the presentation, identified by its database ID.
* Note that the slide position is NOT determined by this function so it will be given as -1.
* Use "get_slides()" to fetch an array with valid slide positions.
* @param int $id The record ID of the sldie in the database.
* @return SloodlePresenterSlide|bool A slide object if successful, or false if it could not be found.
*/
function get_slide($id)
{
// Sanitize the data
$id = (int)$id;
// Fetch the requested slide
$rec = sloodle_get_record('sloodle_presenter_entry', 'id', $id);
if (!$rec) return false;
// Substitute the source data for the name if no name is given.
$name = '';
if (isset($rec->name)){
$name = $rec->name;
}
if (empty($name)) $name = $rec->source;
// Convert plugin class names back to legacy slide types.
// (The class names were used temporarily, but deemed unnecessary.)
$type = strtolower($rec->type);
switch ($type)
{
case 'sloodlepluginpresenterslideimage': case 'presenterslideimage': $type = 'image'; break;
case 'sloodlepluginpresenterslideweb': case 'presenterslideweb': $type = 'web'; break;
case 'sloodlepluginpresenterslidevideo': case 'presenterslidevideo': $type = 'video'; break;
}
return new SloodlePresenterSlide($rec->id, $this, $name, $rec->source, $type, $rec->ordering, -1);
}
/**
* Gets an ordered associative array of slides in presentation order.
* @return Array associating slide IDs to SloodlePresenterSlide objects if successful, or false if not.
*/
function get_slides()
{
// Make sure we have valid ordering
$this->validate_ordering();
// Fetch the database records
$recs = sloodle_get_records_select_params('sloodle_presenter_entry', "sloodleid = ? ", array($this->sloodle_instance->id), 'ordering');
if (!$recs) return array();
// Construct the array of objects
$output = array();
$slideposition = 1;
foreach ($recs as $r) {
// Substitute the source data for the name if no name is given.
$name = '';
if (isset($r->name)){
$name = $r->name;
}
if (empty($name)) $name = $r->source;
// Convert plugin class names back to legacy slide types.
// (The class names were used temporarily, but deemed unnecessary.)
$type = strtolower($r->type);
switch ($r->type)
{
case 'sloodlepluginpresenterslideimage': case 'presenterslideimage': $type = 'image'; break;
case 'sloodlepluginpresenterslideweb': case 'presenterslideweb': $type = 'web'; break;
case 'sloodlepluginpresenterslidevideo': case 'presenterslidevideo': $type = 'video'; break;
}
// Add the slide to our list
$output[$r->id] = new SloodlePresenterSlide($r->id, $this, $name, $r->source, $type, $r->ordering, $slideposition);
$slideposition++;
}
return $output;
}
/**
* Adds a new entry to the presentation.
* @param string $source A string containing the source address -- must start with http for absolute URLs
* @param string $type Name of the type of source, e.g. "web", "image", or "video"
* @param string $name Name of the slide
* @param integer $position Integer indicating the position of the new entry. If negative, then it is placed last in the presentation.
* @return True if successful, or false on failure.
*/
function add_entry($source, $type, $name, $position = -1)
{
// Make sure our entry ordering is valid before we start
$this->validate_ordering();
// Construct and attempt to insert the new record
$rec = new stdClass();
$rec->sloodleid = $this->sloodle_instance->id;
$rec->source = $source;
$rec->name = $name;
$rec->type = $type;
if ($position < 0) {
$num = sloodle_count_records('sloodle_presenter_entry', 'sloodleid', $this->sloodle_instance->id);
$rec->ordering = ((int)$num + 1) * 10;
} else {
$rec->ordering = ($position * 10) - 1; // Ordering works in multiples of 10, starting at 10.
}
$result = (bool)sloodle_insert_record('sloodle_presenter_entry', $rec, false);
// Make sure our entry ordering is valid again now
$this->validate_ordering();
return $result;
}
/**
* Edits an existing entry in the presentation.
* @param int $id The ID of the entry in the database.
* @param string $source A string containing the source address -- must start with http for absolute URLs
* @param string $type Name of the type of source, e.g. "web", "image", or "video"
* @param string $name Name of the slide
* @param integer $position Integer indicating the desired position of the entry. If negative, then its position is left unchanged.
* @return True if successful, or false on failure.
*/
function edit_entry($id, $source, $type, $name, $position = -1)
{
// Ensure we have valid ordering to begin with
$this->validate_ordering();
// Attempt to fetch the existing entry from the database
$id = (int)$id;
$rec = sloodle_get_record('sloodle_presenter_entry', 'id', $id, 'sloodleid', $this->sloodle_instance->id);
if (!$rec) return false;
// Apply the changes to the record
$rec->source = $source;
$rec->name = $name;
$rec->type = $type;
if ($position > 0) {
$rec->ordering = ($position * 10) - 1; // Ordering works in multiples of 10, starting at 10.
}
// Update the database
$result = (bool)sloodle_update_record('sloodle_presenter_entry', $rec);
// Make sure our entry ordering is valid
$this->validate_ordering();
return $result;
}
/**
* Deletes the identified entry by ID.
* Only works if the entry is part of this presentation.
* @param int $id The ID of an entry record to delete
* @return bool True if successful or false otherwise.
*/
function delete_entry($id)
{
$result = sloodle_delete_records('sloodle_presenter_entry', 'sloodleid', $this->sloodle_instance->id, 'id', $id);
// Fix the ordering
$this->validate_ordering();
if ($result === false) return false;
return true;
}
/**
* Moves the ID'd entry forward or back in the presentation ordering.
* Only works if the entry is part of this presentation.
* @param int $id The ID of the entry to move.
* @param bool $forward TRUE to move the entry forward (closer to the beginning) or FALSE to push it back (closer to the end)
* @return void
*/
function move_entry($id, $forward)
{
// Start by ensuring uniform ordering, starting at 10.
$this->validate_ordering();
// Attempt to move the specified entry in the appropriate direction
$entry = sloodle_get_record('sloodle_presenter_entry', 'sloodleid', $this->sloodle_instance->id, 'id', $id);
if (!$entry) return;
if ($forward) {
// Avoid a negative ordering value.
if ($entry->ordering >= 20) $entry->ordering -= 15;
} else {
$entry->ordering += 15;
}
sloodle_update_record('sloodle_presenter_entry', $entry);
// Re-validate the entry ordering
$this->validate_ordering();
}
/**
* Relocates the identified entry to the specified position in the presentation.
* Positions count from 1 upwards. If an entry already exists in that location, then the existing entry is pushed to the next position.
* @param int $id The ID of the entry to relocate
* @param int $pos The position in the presentation to move the slide to
* @return void
*/
function relocate_entry($id, $pos)
{
// Start by ensuring uniform ordering, starting at 10.
$this->validate_ordering();
// Calculate the ordering value for our entry.
// The first entry in a presentation has ordering 10, and subsequent entries increment by 10.
// Therefore, we can insert an entry before an existing slot by moving it to one BEFORE the appropriate multiple of 10.
$newordering = ($pos * 10) - 1;
// Write the new ordering to the database, and re-validate the order
$entry = sloodle_get_record('sloodle_presenter_entry', 'sloodleid', $this->sloodle_instance->id, 'id', $id);
if (!$entry) return;
$entry->ordering = $newordering;
sloodle_update_record('sloodle_presenter_entry', $entry);
$this->validate_ordering();
}
/**
* Validates the ordering value of all entries in the presenter.
* Gives each record an ordering value from 10 upwards, incrementing by 10 each time.
* @return void
*/
function validate_ordering()
{
// Get all entries in this presentation
$entries = sloodle_get_records('sloodle_presenter_entry', 'sloodleid', $this->sloodle_instance->id, 'ordering');
if (!$entries || count($entries) <= 1) return;
// Go through each entry in our array, and give it a valid ordering value.
$ordering = 10;
foreach ($entries as $entry) {
$entry->ordering = $ordering;
sloodle_update_record('sloodle_presenter_entry', $entry);
$ordering += 10;
}
}
// BACKUP AND RESTORE //
/**
* Backs-up secondary data regarding this module.
* That includes everything except the main 'sloodle' database table for this instance.
* @param $bf Handle to the file which backup data should be written to.
* @param bool $includeuserdata Indicates whether or not to backup 'user' data, i.e. any content. Most SLOODLE tools don't have any user data.
* @return bool True if successful, or false on failure.
*/
function backup($bf, $includeuserdata)
{
// Data about the Presenter itself
fwrite($bf, full_tag('ID', 5, false, $this->presenter->id));
fwrite($bf, full_tag('FRAMEWIDTH', 5, false, $this->presenter->framewidth));
fwrite($bf, full_tag('FRAMEHEIGHT', 5, false, $this->presenter->frameheight));
// Attempt to fetch all the slides in the presentation
$slides = $this->get_slides();
if (!$slides) return false;
// Data about the slides in the presenter.
// Currently this will only backup the raw URLs, and won't transfer any files.
// In future, it should backup any files which are on the same server.
fwrite($bf, start_tag('SLIDES', 5, true));
foreach ($slides as $slide) {
fwrite($bf, start_tag('SLIDE', 6, true));
// Convert plugin class names back to simple slide types
switch ($slide->type) {
case 'SloodlePluginPresenterSlideImage': case 'PresenterSlideImage': $slide->type = 'image'; break;
case 'SloodlePluginPresenterSlideVideo': case 'PresenterSlideVideo': $slide->type = 'video'; break;
case 'SloodlePluginPresenterSlideWeb': case 'PresenterSlideWeb': $slide->type = 'web'; break;
}
fwrite($bf, full_tag('ID', 7, false, $slide->id));
fwrite($bf, full_tag('NAME', 7, false, $slide->name));
fwrite($bf, full_tag('SOURCE', 7, false, $slide->source));
fwrite($bf, full_tag('TYPE', 7, false, $slide->type));
fwrite($bf, full_tag('ORDERING', 7, false, $slide->ordering));
fwrite($bf, end_tag('SLIDE', 6, true));
}
fwrite($bf, end_tag('SLIDES', 5, true));
return true;
}
/**
* Restore this module's secondary data into the database.
* This ignores any member data, so can be called statically.
* @param int $sloodleid The ID of the primary SLOODLE entry this restore belongs to (i.e. the ID of the record in the "sloodle" table)
* @param array $info An associative array representing the XML backup information for the secondary module data
* @param bool $includeuserdata Indicates whether or not to restore user data
* @return bool True if successful, or false on failure.
*/
function restore($sloodleid, $info, $includeuserdata)
{
// Construct the database record for the Presenter itself
$presenter = new object();
$presenter->sloodleid = $sloodleid;
$presenter->framewidth = $info['FRAMEWIDTH']['0']['#'];
$presenter->frameheight = $info['FRAMEHEIGHT']['0']['#'];
$presenter->id = sloodle_insert_record('sloodle_presenter', $presenter);
// Go through each slide in the presenter backup
$numslides = count($info['SLIDES']['0']['#']['SLIDE']);
$curslide = null;
for ($slidenum = 0; $slidenum < $numslides; $slidenum++) {
// Get the current slide data
$curslide = $info['SLIDES']['0']['#']['SLIDE'][$slidenum]['#'];
// Construct a new Presenter slide database object
$slide = new object();
$slide->sloodleid = $sloodleid;
$slide->name = $curslide['NAME']['0']['#'];
$slide->source = $curslide['SOURCE']['0']['#'];
$slide->type = $curslide['TYPE']['0']['#'];
$slide->ordering = $curslide['ORDERING']['0']['#'];
$slide->id = sloodle_insert_record('sloodle_presenter_entry', $slide);
}
return true;
}
/**
* Gets the name of the user data required by this type, or an empty string if none is required.
* For example, a chatroom would use the name "Messages" for user data.
* Note that this should respect current language settings in Moodle.
* @return string Localised name of the user data.
*/
function get_user_data_name()
{
return '';
}
/**
* Gets the number of user data records to be backed-up.
* @return int A count of the number of user data records which can be backed-up.
*/
function get_user_data_count()
{
return 0;
}
// ACCESSORS //
/**
* Gets the width of the Presenter frame (for viewing in Moodle).
* @return int Width of the Presenter frame.
*/
function get_frame_width()
{
return (int)$this->presenter->framewidth;
}
/**
* Gets the height of the Presenter frame (for viewing in Moodle).
* @return int Height of the Presenter frame.
*/
function get_frame_height()
{
return (int)$this->presenter->frameheight;
}
/**
* Gets the name of this module instance.
* @return string The name of this module
*/
function get_name()
{
return $this->sloodle_instance->name;
}
/**
* Gets the intro description of this module instance, if available.
* @return string The intro description of this controller
*/
function get_intro()
{
return $this->sloodle_instance->intro;
}
/**
* Gets the identifier of the course this controller belongs to.
* @return mixed Course identifier. Type depends on VLE. (In Moodle, it will be an integer).
*/
function get_course_id()
{
return (int)$this->sloodle_instance->course;
}
/**
* Gets the time at which this instance was created, or 0 if unknown.
* @return int Timestamp
*/
function get_creation_time()
{
return (int)$this->sloodle_instance->timecreated;
}
/**
* Gets the time at which this instance was last modified, or 0 if unknown.
* @return int Timestamp
*/
function get_modification_time()
{
return (int)$this->sloodle_instance->timemodified;
}
/**
* Gets the short type name of this instance.
* @return string
*/
function get_type()
{
return SLOODLE_TYPE_PRESENTER;
}
/**
* Gets the full type name of this instance, according to the current language pack, if available.
* Note: should be overridden by sub-classes.
* @return string Full type name if possible, or the short name otherwise.
*/
function get_type_full()
{
return get_string('moduletype:'.SLOODLE_TYPE_PRESENTER, 'sloodle');
}
}
/**
* Defines a single slide from a presentation, containing raw data.
* The data will usually need to interpreted by a slide plugin.
* @package sloodle
*/
class SloodlePresenterSlide
{
// FUNCTIONS //
// Constructor
function SloodlePresenterSlide($id=0, $presenter=null, $name='', $source='', $type='', $ordering=0, $slideposition=0)
{
$this->id = $id;
$this->presenter = $presenter;
$this->name = $name;
$this->source = $source;
$this->type = $type;
$this->ordering = $ordering;
$this->slideposition = $slideposition;
}
// DATA //
/**
* The ID of this slide in the DB table of slides.
* @access public
* @var int
*/
var $id = 0;
/**
* The SloodleModulePresenter object relating the presentation this slide is in
* @access public
* @var SloodleModulePresenter
*/
var $presenter = null;
/**
* The name of this slide
* @access public
* @var string
*/
var $name = '';
/**
* The source data for this slide. Normally this would be an absolute url (starting with a protocol specifier like HTTP),
* or a relative path, in which case it is treated as an internal Moodle file.
* Plugins may alternatively use this to store data which is to be rendered.
* @access public
* @var string
*/
var $source = '';
/**
* The type of this slide. This will be the ID of a plugin in the "presenter-slide" category, such as "web", "image", or "video".
* @access public
* @var string
*/
var $type = '';
/**
* The ordering value for this slide. This should not generally be used. Refer to 'slideposition' instead.
* @access public
* @var integer
*/
var $ordering = 0;
/**
* The position of this slide in the presentation. This is a 1-based count.
* @access public
* @var integer
*/
var $slideposition = 0;
}
?>