Compare commits
100 commits
main
...
MOODLE_35_
Author | SHA1 | Date | |
---|---|---|---|
|
e25ebd6420 | ||
|
02f9ed9b49 | ||
|
3b0b1298d5 | ||
|
850c19f588 | ||
|
a08c880c04 | ||
|
7a309f506f | ||
|
d778424a92 | ||
|
f1c67c7134 | ||
|
e45e6e21cf | ||
|
7b523100b7 | ||
|
a1d19bf84d | ||
|
512bbad3c4 | ||
|
ebfc1c029d | ||
|
75dbbf661d | ||
|
be08afb7b4 | ||
|
0223518bf9 | ||
|
cb5b5d7465 | ||
|
2e9bc44bf3 | ||
|
e7e238aaf7 | ||
|
a20285a947 | ||
|
f82258c78a | ||
|
b7b33ebd8c | ||
|
c4b21153eb | ||
|
e6b640c0cf | ||
|
3bd09923c4 | ||
|
8125a5e9ff | ||
|
69123d230b | ||
|
133852af7c | ||
|
1d4434ed15 | ||
|
4a45b5ab81 | ||
|
476f292d73 | ||
|
684af9de0f | ||
|
42645287d7 | ||
|
9badf60f91 | ||
|
c992d7a376 | ||
|
a5d51f2478 | ||
|
cd9cf91769 | ||
|
f00a0d739d | ||
|
3ecfaf69f4 | ||
|
b480cf3c68 | ||
|
48c83d34df | ||
|
8a2b7290af | ||
|
4db2148886 | ||
|
e76705315c | ||
|
7f62e6eaec | ||
|
d37cc22135 | ||
|
7492fd1686 | ||
|
7336a21df7 | ||
|
e6ddaa5b30 | ||
|
20cfbdf9c3 | ||
|
1bfceb6794 | ||
|
b16bf5ccb6 | ||
|
7532606ffa | ||
|
5da5b675ab | ||
|
d2f12c859c | ||
|
50e8374596 | ||
|
0652441d45 | ||
|
8c03508a40 | ||
|
4c639bbe3e | ||
|
4d62cde7f3 | ||
|
2866aa7c6b | ||
|
9021794049 | ||
|
8f006a2600 | ||
|
71b0a8bd0e | ||
|
9874a2bd0d | ||
|
ea868e3cd3 | ||
|
82aa988db4 | ||
|
3cd85428df | ||
|
48024d2b77 | ||
|
0eb96e3605 | ||
|
36ec9188fa | ||
|
2852683dff | ||
|
3e69898988 | ||
|
92b15ecb06 | ||
|
057cf92f03 | ||
|
59fe72c7ca | ||
|
e0cdcb07b9 | ||
|
d91639e4ed | ||
|
6d0c4160f7 | ||
|
db81b49608 | ||
|
3c3902ab9d | ||
|
b1b6af3e65 | ||
|
aacf541621 | ||
|
4f583679d0 | ||
|
01e427cf57 | ||
|
bb2ed945fa | ||
|
5a7e1ee98d | ||
|
13ec235c2d | ||
|
d42cbc9a16 | ||
|
f91a54ebc9 | ||
|
fc0fb240fd | ||
|
92e0029623 | ||
|
322abdbba3 | ||
|
59f9bfcc78 | ||
|
577a997960 | ||
|
1b756fbd5b | ||
|
d12e752d1a | ||
|
961a3f02f0 | ||
|
9f844368fd | ||
|
a3f159dfaf |
58 changed files with 2453 additions and 334 deletions
10
.travis.yml
10
.travis.yml
|
@ -2,6 +2,7 @@ language: php
|
|||
|
||||
# For javascript behat tests we need sudo
|
||||
sudo: true
|
||||
dist: trusty
|
||||
|
||||
cache:
|
||||
directories:
|
||||
|
@ -17,8 +18,7 @@ addons:
|
|||
postgresql: 9.3
|
||||
apt:
|
||||
packages:
|
||||
- oracle-java8-installer
|
||||
- oracle-java8-set-default
|
||||
- openjdk-8-jre-headless
|
||||
|
||||
env:
|
||||
global:
|
||||
|
@ -30,10 +30,10 @@ env:
|
|||
|
||||
before_install:
|
||||
- phpenv config-rm xdebug.ini
|
||||
- nvm install 8.9
|
||||
- nvm use 8.9
|
||||
- nvm install 14.0
|
||||
- nvm use 14.0
|
||||
- cd ../..
|
||||
- composer create-project -n --no-dev --prefer-dist blackboard-open-source/moodle-plugin-ci ci ^2
|
||||
- composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^3
|
||||
- export PATH="$(cd ci/bin; pwd):$(cd ci/vendor/bin; pwd):$PATH"
|
||||
|
||||
install:
|
||||
|
|
82
CHANGES.md
82
CHANGES.md
|
@ -2,7 +2,84 @@
|
|||
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
Note - All hash comments refer to the issue number. Eg. #169 refers to https://github.com/markn86/moodle-mod_customcert/issues/169.
|
||||
Note - All hash comments refer to the issue number. Eg. #169 refers to https://github.com/mdjnelson/moodle-mod_customcert/issues/169.
|
||||
|
||||
## [3.5.9] - 2020-11-26
|
||||
|
||||
### Added
|
||||
|
||||
- Added ability to select outcomes in the Grade element (#329).
|
||||
- The Grade Item Name element now works with all grade items, whereas before it was just activities (#346).
|
||||
- Added enrolment start and end dates to the date element (#328).
|
||||
- Added username to userfield form element (#390).
|
||||
|
||||
### Changed
|
||||
|
||||
- Removed unnecessary and confusing 'exampledata' string.
|
||||
- Do not email those who can manage the certificate (#376).
|
||||
- Do not force the PDF to be downloaded, instead send the file inline to the browser (#153).
|
||||
- Updated the 'emailstudents_help', 'emailteachers_help' and 'emailothers_help' strings to warn users about prematurely emailing the certificate (#276).
|
||||
- Do not email out certificates that contain no elements (#276).
|
||||
|
||||
### Fixed
|
||||
|
||||
- Certificates now get marked as viewed via the mobile app (#342).
|
||||
- Fix repositioning elements page when resizing the browser (#343).
|
||||
- Prevent error when duplicate issues exist when using the code element (#363).
|
||||
- Implemented get_objectid_mapping for the course_module_viewed.php event to avoid warning (#374).
|
||||
- Fixed exception being thrown when loading a template that has an image element but no image selected (#369).
|
||||
- Fixed issue with PDF being generated without a name (#333).
|
||||
|
||||
## [3.5.8] - 2020-04-19
|
||||
|
||||
### Added
|
||||
|
||||
- Added extra Behat steps for new elements (#309).
|
||||
- Re-added 'code' column to user report (#264).
|
||||
- Add 'userfullname' variable for email subject (#316).
|
||||
- Added ability to specify the current date for date related elements (#289).
|
||||
- Added QR code element (#146).
|
||||
- Added Date range element (#185).
|
||||
- Added new capability to control who can be issued a certificate (#270).
|
||||
|
||||
### Changed
|
||||
|
||||
- When copying a site template the site images are also copied to the course context and then those copied images are used.
|
||||
Before, the elements would simply point to the site images. However, this meant when performing a backup/restore the
|
||||
images were not stored in the backup file (#298).
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fixed the displaying of names of a custom user field (#326).
|
||||
- Fixed foreign key violation (#331).
|
||||
- Do not fail if multiple certificate issues (#304) and (#295).
|
||||
|
||||
## [3.5.7] - 2019-05-28
|
||||
|
||||
### Changed
|
||||
|
||||
- Always send emails from the 'noreplyuser' (#165).
|
||||
|
||||
### Added
|
||||
|
||||
- Added the number of certificates issued above the report (#266).
|
||||
|
||||
### Fixed
|
||||
|
||||
- Failures when running unit tests for multiple activities (#282).
|
||||
- Check that a certificate is issued before downloading on 'My certificates' page (#269).
|
||||
|
||||
## [3.5.6] - 2018-12-31
|
||||
|
||||
### Changed
|
||||
|
||||
- Make it clear what element values are just an example when previewing the PDF (#144).
|
||||
|
||||
### Fixed
|
||||
|
||||
- Missing implementation for privacy provider (#260).
|
||||
- Use course module context when calling format_string/text (#200).
|
||||
- Exception being thrown when adding the 'teachername' element to site template (#261).
|
||||
|
||||
## [3.5.5] - 2018-12-20
|
||||
### Added
|
||||
|
@ -20,12 +97,15 @@ Note - All hash comments refer to the issue number. Eg. #169 refers to https://g
|
|||
- Allow verification of deleted users (#159).
|
||||
- The 'element' field in the 'customcert_elements' table has been changed from a Text field to varchar(255) (#241).
|
||||
- The 'Completion date' option in the 'date' element is only displayed when completion is enabled (#160).
|
||||
- Instead of assuming 2 decimal points for percentages, we now make use of the decimal value setting, which the
|
||||
function `grade_format_gradevalue` does by default if no decimal value is passed.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Issue with scales not displaying correctly (#242).
|
||||
- The report now respects the setting 'Show user identity' (#224).
|
||||
- Removed incorrect course reset logic (#223).
|
||||
- Description strings referring to the wrong setting (#254).
|
||||
|
||||
## [3.5.4] - 2018-07-13
|
||||
### Fixed
|
||||
|
|
|
@ -15,7 +15,7 @@ This requires Git being installed. If you do not have Git installed, please visi
|
|||
Once you have Git installed, simply visit your Moodle mod directory and clone the repository using the following command.
|
||||
|
||||
```
|
||||
git clone https://github.com/markn86/moodle-mod_customcert.git customcert
|
||||
git clone https://github.com/mdjnelson/moodle-mod_customcert.git customcert
|
||||
```
|
||||
|
||||
Then checkout the branch corresponding to the version of Moodle you are using with the following command. Make sure to replace MOODLE_32_STABLE with the version of Moodle you are using.
|
||||
|
|
|
@ -64,6 +64,7 @@ class edit_element_form extends \moodleform {
|
|||
$mform->addHelpButton('name', 'elementname', 'customcert');
|
||||
|
||||
$this->element = \mod_customcert\element_factory::get_element_instance($element);
|
||||
$this->element->set_edit_element_form($this);
|
||||
$this->element->render_form_elements($mform);
|
||||
|
||||
$this->add_action_buttons(true);
|
||||
|
|
|
@ -102,6 +102,11 @@ abstract class element {
|
|||
*/
|
||||
protected $showposxy;
|
||||
|
||||
/**
|
||||
* @var edit_element_form Element edit form instance.
|
||||
*/
|
||||
private $editelementform;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
|
@ -230,7 +235,7 @@ abstract class element {
|
|||
* This function renders the form elements when adding a customcert element.
|
||||
* Can be overridden if more functionality is needed.
|
||||
*
|
||||
* @param edit_element_form $mform the edit_form instance.
|
||||
* @param \MoodleQuickForm $mform the edit_form instance.
|
||||
*/
|
||||
public function render_form_elements($mform) {
|
||||
// Render the common elements.
|
||||
|
@ -240,6 +245,7 @@ abstract class element {
|
|||
element_helper::render_form_element_position($mform);
|
||||
}
|
||||
element_helper::render_form_element_width($mform);
|
||||
element_helper::render_form_element_refpoint($mform);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -421,4 +427,27 @@ abstract class element {
|
|||
return $this->element->$name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set edit form instance for the custom cert element.
|
||||
*
|
||||
* @param \mod_customcert\edit_element_form $editelementform
|
||||
*/
|
||||
public function set_edit_element_form(edit_element_form $editelementform) {
|
||||
$this->editelementform = $editelementform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get edit form instance for the custom cert element.
|
||||
*
|
||||
* @return \mod_customcert\edit_element_form
|
||||
*/
|
||||
public function get_edit_element_form() {
|
||||
if (empty($this->editelementform)) {
|
||||
throw new \coding_exception('Edit element form instance is not set.');
|
||||
}
|
||||
|
||||
return $this->editelementform;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -47,18 +47,18 @@ class element_factory {
|
|||
$classname = '\\customcertelement_' . $element->element . '\\element';
|
||||
|
||||
$data = new \stdClass();
|
||||
$data->id = isset($element->id) ? $element->id : null;
|
||||
$data->pageid = isset($element->pageid) ? $element->pageid : null;
|
||||
$data->name = isset($element->name) ? $element->name : get_string('pluginname', 'customcertelement_' . $element->element);
|
||||
$data->id = $element->id ?? null;
|
||||
$data->pageid = $element->pageid ?? null;
|
||||
$data->name = $element->name ?? get_string('pluginname', 'customcertelement_' . $element->element);
|
||||
$data->element = $element->element;
|
||||
$data->data = isset($element->data) ? $element->data : null;
|
||||
$data->font = isset($element->font) ? $element->font : null;
|
||||
$data->fontsize = isset($element->fontsize) ? $element->fontsize : null;
|
||||
$data->colour = isset($element->colour) ? $element->colour : null;
|
||||
$data->posx = isset($element->posx) ? $element->posx : null;
|
||||
$data->posy = isset($element->posy) ? $element->posy : null;
|
||||
$data->width = isset($element->width) ? $element->width : null;
|
||||
$data->refpoint = isset($element->refpoint) ? $element->refpoint : null;
|
||||
$data->data = $element->data ?? null;
|
||||
$data->font = $element->font ?? null;
|
||||
$data->fontsize = $element->fontsize ?? null;
|
||||
$data->colour = $element->colour ?? null;
|
||||
$data->posx = $element->posx ?? null;
|
||||
$data->posy = $element->posy ?? null;
|
||||
$data->width = $element->width ?? null;
|
||||
$data->refpoint = $element->refpoint ?? null;
|
||||
|
||||
// Ensure the necessary class exists.
|
||||
if (class_exists($classname)) {
|
||||
|
|
|
@ -134,7 +134,7 @@ class element_helper {
|
|||
/**
|
||||
* Helper function to render the font elements.
|
||||
*
|
||||
* @param \mod_customcert\edit_element_form $mform the edit_form instance.
|
||||
* @param \MoodleQuickForm $mform the edit_form instance.
|
||||
*/
|
||||
public static function render_form_element_font($mform) {
|
||||
$mform->addElement('select', 'font', get_string('font', 'customcert'), \mod_customcert\certificate::get_fonts());
|
||||
|
@ -151,7 +151,7 @@ class element_helper {
|
|||
/**
|
||||
* Helper function to render the colour elements.
|
||||
*
|
||||
* @param \mod_customcert\edit_element_form $mform the edit_form instance.
|
||||
* @param \MoodleQuickForm $mform the edit_form instance.
|
||||
*/
|
||||
public static function render_form_element_colour($mform) {
|
||||
$mform->addElement('customcert_colourpicker', 'colour', get_string('fontcolour', 'customcert'));
|
||||
|
@ -163,7 +163,7 @@ class element_helper {
|
|||
/**
|
||||
* Helper function to render the position elements.
|
||||
*
|
||||
* @param \mod_customcert\edit_element_form $mform the edit_form instance.
|
||||
* @param \MoodleQuickForm $mform the edit_form instance.
|
||||
*/
|
||||
public static function render_form_element_position($mform) {
|
||||
$mform->addElement('text', 'posx', get_string('posx', 'customcert'), array('size' => 10));
|
||||
|
@ -179,17 +179,26 @@ class element_helper {
|
|||
/**
|
||||
* Helper function to render the width element.
|
||||
*
|
||||
* @param \mod_customcert\edit_element_form $mform the edit_form instance.
|
||||
* @param \MoodleQuickForm $mform the edit_form instance.
|
||||
*/
|
||||
public static function render_form_element_width($mform) {
|
||||
$mform->addElement('text', 'width', get_string('elementwidth', 'customcert'), array('size' => 10));
|
||||
$mform->setType('width', PARAM_INT);
|
||||
$mform->setDefault('width', 0);
|
||||
$mform->addHelpButton('width', 'elementwidth', 'customcert');
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to render the refpoint element.
|
||||
*
|
||||
* @param \MoodleQuickForm $mform the edit_form instance.
|
||||
*/
|
||||
public static function render_form_element_refpoint($mform) {
|
||||
$refpointoptions = array();
|
||||
$refpointoptions[self::CUSTOMCERT_REF_POINT_TOPLEFT] = get_string('topleft', 'customcert');
|
||||
$refpointoptions[self::CUSTOMCERT_REF_POINT_TOPCENTER] = get_string('topcenter', 'customcert');
|
||||
$refpointoptions[self::CUSTOMCERT_REF_POINT_TOPRIGHT] = get_string('topright', 'customcert');
|
||||
|
||||
$mform->addElement('select', 'refpoint', get_string('refpoint', 'customcert'), $refpointoptions);
|
||||
$mform->setType('refpoint', PARAM_INT);
|
||||
$mform->setDefault('refpoint', self::CUSTOMCERT_REF_POINT_TOPCENTER);
|
||||
|
@ -383,6 +392,27 @@ class element_helper {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that returns the context for this element.
|
||||
*
|
||||
* @param int $elementid The element id
|
||||
* @return \context The context
|
||||
*/
|
||||
public static function get_context(int $elementid) : \context {
|
||||
global $DB;
|
||||
|
||||
$sql = "SELECT ct.contextid
|
||||
FROM {customcert_templates} ct
|
||||
INNER JOIN {customcert_pages} cp
|
||||
ON ct.id = cp.templateid
|
||||
INNER JOIN {customcert_elements} ce
|
||||
ON cp.id = ce.pageid
|
||||
WHERE ce.id = :elementid";
|
||||
$contextid = $DB->get_field_sql($sql, array('elementid' => $elementid), MUST_EXIST);
|
||||
|
||||
return \context::instance_by_id($contextid);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the list of possible elements to add.
|
||||
*
|
||||
|
@ -432,70 +462,40 @@ class element_helper {
|
|||
* @return array the array of gradeable items in the course
|
||||
*/
|
||||
public static function get_grade_items($course) {
|
||||
global $DB;
|
||||
|
||||
// Array to store the grade items.
|
||||
$modules = array();
|
||||
|
||||
// Collect course modules data.
|
||||
$modinfo = get_fast_modinfo($course);
|
||||
$mods = $modinfo->get_cms();
|
||||
$sections = $modinfo->get_section_info_all();
|
||||
|
||||
// Create the section label depending on course format.
|
||||
$sectionlabel = get_string('section');
|
||||
if ($course->format == 'topics') {
|
||||
$sectionlabel = get_string('topic');
|
||||
} else if ($course->format == 'weeks') {
|
||||
$sectionlabel = get_string('week');
|
||||
}
|
||||
|
||||
// Loop through each course section.
|
||||
for ($i = 0; $i <= count($sections) - 1; $i++) {
|
||||
// Confirm the index exists, should always be true.
|
||||
if (isset($sections[$i])) {
|
||||
// Get the individual section.
|
||||
$section = $sections[$i];
|
||||
// Get the mods for this section.
|
||||
$sectionmods = explode(",", $section->sequence);
|
||||
// Loop through the section mods.
|
||||
foreach ($sectionmods as $sectionmod) {
|
||||
// Should never happen unless DB is borked.
|
||||
if (empty($mods[$sectionmod])) {
|
||||
continue;
|
||||
}
|
||||
$mod = $mods[$sectionmod];
|
||||
$instance = $DB->get_record($mod->modname, array('id' => $mod->instance));
|
||||
// Get the grade items for this activity.
|
||||
if ($gradeitems = grade_get_grade_items_for_activity($mod)) {
|
||||
$moditem = grade_get_grades($course->id, 'mod', $mod->modname, $mod->instance);
|
||||
$gradeitem = reset($moditem->items);
|
||||
if (isset($gradeitem->grademax)) {
|
||||
$modules[$mod->id] = $sectionlabel . ' ' . $section->section . ' : ' . $instance->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$arrgradeitems = array();
|
||||
|
||||
// Get other non-module related grade items.
|
||||
if ($gradeitems = \grade_item::fetch_all(['courseid' => $course->id])) {
|
||||
$arrgradeitems = [];
|
||||
foreach ($gradeitems as $gi) {
|
||||
// Skip the course and mod items since we already have them.
|
||||
if ($gi->itemtype == 'mod' || $gi->itemtype == 'course') {
|
||||
continue;
|
||||
if ($gi->is_course_item()) {
|
||||
continue; // Skipping for legacy reasons - this was added to individual elements.
|
||||
}
|
||||
|
||||
if ($gi->is_external_item()) {
|
||||
$cm = get_coursemodule_from_instance($gi->itemmodule, $gi->iteminstance, $course->id);
|
||||
$modcontext = \context_module::instance($cm->id);
|
||||
$modname = format_string($cm->name, true, array('context' => $modcontext));
|
||||
}
|
||||
|
||||
if ($gi->is_external_item() && !$gi->is_outcome_item()) {
|
||||
// Due to legacy reasons we are storing the course module ID here rather than the grade item id.
|
||||
// If we were to change we would need to provide upgrade steps to convert cm->id to gi->id.
|
||||
$arrgradeitems[$cm->id] = get_string('activity', 'mod_customcert') . ' : ' . $gi->get_name();
|
||||
} else if ($gi->is_external_item() && $gi->is_outcome_item()) {
|
||||
// Get the name of the activity.
|
||||
$optionname = get_string('gradeoutcome', 'mod_customcert') . ' : ' . $modname . " - " . $gi->get_name();
|
||||
$arrgradeitems['gradeitem:' . $gi->id] = $optionname;
|
||||
} else {
|
||||
$arrgradeitems['gradeitem:' . $gi->id] = get_string('gradeitem', 'grades') . ' : ' . $gi->get_name(true);
|
||||
}
|
||||
$arrgradeitems['gradeitem:' . $gi->id] = get_string('gradeitem', 'grades') . ' : ' . $gi->get_name(true);
|
||||
}
|
||||
|
||||
// Alphabetise this.
|
||||
asort($arrgradeitems);
|
||||
|
||||
// Merge results.
|
||||
$modules = $modules + $arrgradeitems;
|
||||
}
|
||||
|
||||
return $modules;
|
||||
return $arrgradeitems;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -42,4 +42,13 @@ class course_module_viewed extends \core\event\course_module_viewed {
|
|||
$this->data['objecttable'] = 'customcert';
|
||||
parent::init();
|
||||
}
|
||||
|
||||
public static function get_objectid_mapping() {
|
||||
return array('db' => 'customcert', 'restore' => 'customcert');
|
||||
}
|
||||
|
||||
public static function get_other_mapping() {
|
||||
// No need to map.
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,8 @@ defined('MOODLE_INTERNAL') || die();
|
|||
*/
|
||||
class provider implements
|
||||
\core_privacy\local\metadata\provider,
|
||||
\core_privacy\local\request\plugin\provider {
|
||||
\core_privacy\local\request\plugin\provider,
|
||||
\core_privacy\local\request\core_userlist_provider {
|
||||
|
||||
/**
|
||||
* Return the fields which contain personal data.
|
||||
|
|
|
@ -74,6 +74,7 @@ class report_table extends \table_sql {
|
|||
$columns[] = $extrafield;
|
||||
}
|
||||
$columns[] = 'timecreated';
|
||||
$columns[] = 'code';
|
||||
|
||||
$headers = [];
|
||||
$headers[] = get_string('fullname');
|
||||
|
@ -81,6 +82,7 @@ class report_table extends \table_sql {
|
|||
$headers[] = get_user_field_name($extrafield);
|
||||
}
|
||||
$headers[] = get_string('receiveddate', 'customcert');
|
||||
$headers[] = get_string('code', 'customcert');
|
||||
|
||||
// Check if we were passed a filename, which means we want to download it.
|
||||
if ($download) {
|
||||
|
@ -101,6 +103,7 @@ class report_table extends \table_sql {
|
|||
$this->define_headers($headers);
|
||||
$this->collapsible(false);
|
||||
$this->sortable(true);
|
||||
$this->no_sorting('code');
|
||||
$this->no_sorting('download');
|
||||
$this->is_downloadable(true);
|
||||
|
||||
|
@ -135,6 +138,16 @@ class report_table extends \table_sql {
|
|||
return userdate($user->timecreated);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the code column.
|
||||
*
|
||||
* @param \stdClass $user
|
||||
* @return string
|
||||
*/
|
||||
public function col_code($user) {
|
||||
return $user->code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the download column.
|
||||
*
|
||||
|
|
|
@ -69,17 +69,26 @@ class email_certificate_task extends \core\task\scheduled_task {
|
|||
$htmlrenderer = $PAGE->get_renderer('mod_customcert', 'email', 'htmlemail');
|
||||
$textrenderer = $PAGE->get_renderer('mod_customcert', 'email', 'textemail');
|
||||
foreach ($customcerts as $customcert) {
|
||||
// Do not process an empty certificate.
|
||||
$sql = "SELECT ce.*
|
||||
FROM {customcert_elements} ce
|
||||
JOIN {customcert_pages} cp
|
||||
ON cp.id = ce.pageid
|
||||
JOIN {customcert_templates} ct
|
||||
ON ct.id = cp.templateid
|
||||
WHERE ct.contextid = :contextid";
|
||||
if (!$DB->record_exists_sql($sql, ['contextid' => $customcert->contextid])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get the context.
|
||||
$context = \context::instance_by_id($customcert->contextid);
|
||||
|
||||
// Get the person we are going to send this email on behalf of.
|
||||
// Look through the teachers.
|
||||
if ($teachers = get_enrolled_users($context, 'moodle/course:update')) {
|
||||
$teachers = sort_by_roleassignment_authority($teachers, $context);
|
||||
$userfrom = reset($teachers);
|
||||
} else { // Ok, no teachers, use administrator name.
|
||||
$userfrom = get_admin();
|
||||
}
|
||||
$userfrom = \core_user::get_noreply_user();
|
||||
|
||||
// Store teachers for later.
|
||||
$teachers = get_enrolled_users($context, 'moodle/course:update');
|
||||
|
||||
$courseshortname = format_string($customcert->courseshortname, true, array('context' => $context));
|
||||
$coursefullname = format_string($customcert->coursefullname, true, array('context' => $context));
|
||||
|
@ -120,6 +129,11 @@ class email_certificate_task extends \core\task\scheduled_task {
|
|||
continue;
|
||||
}
|
||||
|
||||
// Only email those with the capability to receive the certificate.
|
||||
if (!has_capability('mod/customcert:receiveissue', $context, $enroluser->id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check that they have passed the required time.
|
||||
if (!empty($customcert->requiredtime)) {
|
||||
if (\mod_customcert\certificate::get_course_time($customcert->courseid,
|
||||
|
@ -130,7 +144,7 @@ class email_certificate_task extends \core\task\scheduled_task {
|
|||
|
||||
// Ensure the cert hasn't already been issued, e.g via the UI (view.php) - a race condition.
|
||||
$issueid = $DB->get_field('customcert_issues', 'id',
|
||||
array('userid' => $enroluser->id, 'customcertid' => $customcert->id));
|
||||
array('userid' => $enroluser->id, 'customcertid' => $customcert->id), IGNORE_MULTIPLE);
|
||||
if (empty($issueid)) {
|
||||
// Ok, issue them the certificate.
|
||||
$issueid = \mod_customcert\certificate::issue_certificate($customcert->id, $enroluser->id);
|
||||
|
@ -163,6 +177,7 @@ class email_certificate_task extends \core\task\scheduled_task {
|
|||
// Now, email the people we need to.
|
||||
foreach ($issuedusers as $user) {
|
||||
$userfullname = fullname($user);
|
||||
$info->userfullname = $userfullname;
|
||||
|
||||
// Now, get the PDF.
|
||||
$template = new \stdClass();
|
||||
|
|
|
@ -283,6 +283,16 @@ class template {
|
|||
$pdf->SetAutoPageBreak(true, 0);
|
||||
// Remove full-stop at the end, if it exists, to avoid "..pdf" being created and being filtered by clean_filename.
|
||||
$filename = rtrim($this->name, '.');
|
||||
|
||||
// This is the logic the TCPDF library uses when processing the name. This makes names
|
||||
// such as 'الشهادة' become empty, so set a default name in these cases.
|
||||
$filename = preg_replace('/[\s]+/', '_', $filename);
|
||||
$filename = preg_replace('/[^a-zA-Z0-9_\.-]/', '', $filename);
|
||||
|
||||
if (empty($filename)) {
|
||||
$filename = get_string('certificate', 'customcert');
|
||||
}
|
||||
|
||||
$filename = clean_filename($filename . '.pdf');
|
||||
// Loop through the pages and display their content.
|
||||
foreach ($pages as $page) {
|
||||
|
@ -305,10 +315,12 @@ class template {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($return) {
|
||||
return $pdf->Output('', 'S');
|
||||
}
|
||||
$pdf->Output($filename, 'D');
|
||||
|
||||
$pdf->Output($filename, 'I');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "markn86/moodle-mod_customcert",
|
||||
"name": "mdjnelson/moodle-mod_customcert",
|
||||
"type": "moodle-mod",
|
||||
"require": {
|
||||
"composer/installers": "~1.0"
|
||||
|
|
|
@ -60,6 +60,14 @@ $capabilities = array(
|
|||
)
|
||||
),
|
||||
|
||||
'mod/customcert:receiveissue' => array(
|
||||
'captype' => 'read',
|
||||
'contextlevel' => CONTEXT_MODULE,
|
||||
'archetypes' => array(
|
||||
'student' => CAP_ALLOW
|
||||
)
|
||||
),
|
||||
|
||||
'mod/customcert:viewreport' => array(
|
||||
|
||||
'captype' => 'read',
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="Primary key for customcert"/>
|
||||
<KEY NAME="template" TYPE="foreign" FIELDS="templateid" REFTABLE="customcert_template" REFFIELDS="id"/>
|
||||
<KEY NAME="template" TYPE="foreign" FIELDS="templateid" REFTABLE="customcert_templates" REFFIELDS="id"/>
|
||||
</KEYS>
|
||||
</TABLE>
|
||||
<TABLE NAME="customcert_templates" COMMENT="Stores each customcert template">
|
||||
|
@ -67,7 +67,7 @@
|
|||
</FIELDS>
|
||||
<KEYS>
|
||||
<KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="Primary key for customcert_pages"/>
|
||||
<KEY NAME="template" TYPE="foreign" FIELDS="templateid" REFTABLE="customcert_template" REFFIELDS="id"/>
|
||||
<KEY NAME="template" TYPE="foreign" FIELDS="templateid" REFTABLE="customcert_templates" REFFIELDS="id"/>
|
||||
</KEYS>
|
||||
</TABLE>
|
||||
<TABLE NAME="customcert_elements" COMMENT="Stores the elements for a given page">
|
||||
|
|
|
@ -30,7 +30,7 @@ $addons = [
|
|||
'issueview' => [ // Handler unique name.
|
||||
'displaydata' => [
|
||||
'icon' => $CFG->wwwroot . '/mod/customcert/pix/icon.png',
|
||||
'class' => '',
|
||||
'class' => 'core-course-module-customcert-handler',
|
||||
],
|
||||
'delegate' => 'CoreCourseModuleDelegate', // Delegate (where to display the link to the plugin).
|
||||
'method' => 'mobile_view_activity', // Main function in \mod_customcert\output\mobile.
|
||||
|
|
|
@ -38,7 +38,7 @@ class element extends \customcertelement_image\element {
|
|||
/**
|
||||
* This function renders the form elements when adding a customcert element.
|
||||
*
|
||||
* @param \mod_customcert\edit_element_form $mform the edit_form instance
|
||||
* @param \MoodleQuickForm $mform the edit_form instance
|
||||
*/
|
||||
public function render_form_elements($mform) {
|
||||
$mform->addElement('select', 'fileid', get_string('image', 'customcertelement_image'), self::get_images());
|
||||
|
|
|
@ -38,7 +38,7 @@ class element extends \mod_customcert\element {
|
|||
/**
|
||||
* This function renders the form elements when adding a customcert element.
|
||||
*
|
||||
* @param \mod_customcert\edit_element_form $mform the edit_form instance
|
||||
* @param \MoodleQuickForm $mform the edit_form instance
|
||||
*/
|
||||
public function render_form_elements($mform) {
|
||||
// We want to define the width of the border.
|
||||
|
@ -103,7 +103,7 @@ class element extends \mod_customcert\element {
|
|||
/**
|
||||
* Sets the data on the form when editing an element.
|
||||
*
|
||||
* @param \mod_customcert\edit_element_form $mform the edit_form instance
|
||||
* @param \MoodleQuickForm $mform the edit_form instance
|
||||
*/
|
||||
public function definition_after_data($mform) {
|
||||
if (!empty($this->get_data())) {
|
||||
|
|
|
@ -43,7 +43,7 @@ class element extends \mod_customcert\element {
|
|||
* @param \stdClass $user the user we are rendering this for
|
||||
*/
|
||||
public function render($pdf, $preview, $user) {
|
||||
\mod_customcert\element_helper::render_content($pdf, $this, self::get_category_name($this->get_id()));
|
||||
\mod_customcert\element_helper::render_content($pdf, $this, $this->get_category_name());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -55,30 +55,28 @@ class element extends \mod_customcert\element {
|
|||
* @return string the html
|
||||
*/
|
||||
public function render_html() {
|
||||
global $COURSE;
|
||||
|
||||
$categoryname = format_string($COURSE->fullname, true, ['context' => \context_course::instance($COURSE->id)]);
|
||||
return \mod_customcert\element_helper::render_html_content($this, $categoryname);
|
||||
return \mod_customcert\element_helper::render_html_content($this, $this->get_category_name());
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that returns the category name.
|
||||
*
|
||||
* @param int $elementid
|
||||
* @return string
|
||||
*/
|
||||
protected static function get_category_name($elementid) {
|
||||
protected function get_category_name() : string {
|
||||
global $DB, $SITE;
|
||||
|
||||
$courseid = \mod_customcert\element_helper::get_courseid($elementid);
|
||||
$courseid = \mod_customcert\element_helper::get_courseid($this->get_id());
|
||||
$course = get_course($courseid);
|
||||
$context = \mod_customcert\element_helper::get_context($this->get_id());
|
||||
|
||||
// Check that there is a course category available.
|
||||
if (!empty($course->category)) {
|
||||
$categoryname = $DB->get_field('course_categories', 'name', array('id' => $course->category), MUST_EXIST);
|
||||
return format_string($categoryname, true, ['context' => \context_course::instance($courseid)]);
|
||||
} else { // Must be in a site template.
|
||||
return format_string($SITE->fullname, true, ['context' => \context_system::instance()]);
|
||||
$categoryname = $SITE->fullname;
|
||||
}
|
||||
|
||||
return format_string($categoryname, true, ['context' => $context]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ class element extends \mod_customcert\element {
|
|||
$customcert = $DB->get_record('customcert', array('templateid' => $page->templateid), '*', MUST_EXIST);
|
||||
// Now we can get the issue for this user.
|
||||
$issue = $DB->get_record('customcert_issues', array('userid' => $user->id, 'customcertid' => $customcert->id),
|
||||
'*', MUST_EXIST);
|
||||
'*', IGNORE_MULTIPLE);
|
||||
$code = $issue->code;
|
||||
}
|
||||
|
||||
|
|
|
@ -43,11 +43,7 @@ class element extends \mod_customcert\element {
|
|||
* @param \stdClass $user the user we are rendering this for
|
||||
*/
|
||||
public function render($pdf, $preview, $user) {
|
||||
$courseid = \mod_customcert\element_helper::get_courseid($this->get_id());
|
||||
$course = get_course($courseid);
|
||||
|
||||
$coursename = format_string($course->fullname, true, ['context' => \context_course::instance($courseid)]);
|
||||
\mod_customcert\element_helper::render_content($pdf, $this, $coursename);
|
||||
\mod_customcert\element_helper::render_content($pdf, $this, $this->get_course_name());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -59,9 +55,19 @@ class element extends \mod_customcert\element {
|
|||
* @return string the html
|
||||
*/
|
||||
public function render_html() {
|
||||
global $COURSE;
|
||||
return \mod_customcert\element_helper::render_html_content($this, $this->get_course_name());
|
||||
}
|
||||
|
||||
$coursename = format_string($COURSE->fullname, true, ['context' => \context_course::instance($COURSE->id)]);
|
||||
return \mod_customcert\element_helper::render_html_content($this, $coursename);
|
||||
/**
|
||||
* Helper function that returns the category name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_course_name() : string {
|
||||
$courseid = \mod_customcert\element_helper::get_courseid($this->get_id());
|
||||
$course = get_course($courseid);
|
||||
$context = \mod_customcert\element_helper::get_context($this->get_id());
|
||||
|
||||
return format_string($course->fullname, true, ['context' => $context]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -51,6 +51,21 @@ define('CUSTOMCERT_DATE_COURSE_START', '-3');
|
|||
*/
|
||||
define('CUSTOMCERT_DATE_COURSE_END', '-4');
|
||||
|
||||
/**
|
||||
* Date - Current date
|
||||
*/
|
||||
define('CUSTOMCERT_DATE_CURRENT_DATE', '-5');
|
||||
|
||||
/**
|
||||
* Date - Enrollment start
|
||||
*/
|
||||
define('CUSTOMCERT_DATE_ENROLMENT_START', '-6');
|
||||
|
||||
/**
|
||||
* Date - Entrollment end
|
||||
*/
|
||||
define('CUSTOMCERT_DATE_ENROLMENT_END', '-7');
|
||||
|
||||
require_once($CFG->dirroot . '/lib/grade/constants.php');
|
||||
|
||||
/**
|
||||
|
@ -65,7 +80,7 @@ class element extends \mod_customcert\element {
|
|||
/**
|
||||
* This function renders the form elements when adding a customcert element.
|
||||
*
|
||||
* @param \mod_customcert\edit_element_form $mform the edit_form instance
|
||||
* @param \MoodleQuickForm $mform the edit_form instance
|
||||
*/
|
||||
public function render_form_elements($mform) {
|
||||
global $CFG, $COURSE;
|
||||
|
@ -73,10 +88,14 @@ class element extends \mod_customcert\element {
|
|||
// Get the possible date options.
|
||||
$dateoptions = array();
|
||||
$dateoptions[CUSTOMCERT_DATE_ISSUE] = get_string('issueddate', 'customcertelement_date');
|
||||
$dateoptions[CUSTOMCERT_DATE_CURRENT_DATE] = get_string('currentdate', 'customcertelement_date');
|
||||
$completionenabled = $CFG->enablecompletion && ($COURSE->id == SITEID || $COURSE->enablecompletion);
|
||||
if ($completionenabled) {
|
||||
$dateoptions[CUSTOMCERT_DATE_COMPLETION] = get_string('completiondate', 'customcertelement_date');
|
||||
}
|
||||
$dateoptions[CUSTOMCERT_DATE_ENROLMENT_START] = get_string('enrolmentstartdate', 'customcertelement_date');
|
||||
$dateoptions[CUSTOMCERT_DATE_ENROLMENT_END] = get_string('enrolmentenddate', 'customcertelement_date');
|
||||
|
||||
$dateoptions[CUSTOMCERT_DATE_COURSE_START] = get_string('coursestartdate', 'customcertelement_date');
|
||||
$dateoptions[CUSTOMCERT_DATE_COURSE_END] = get_string('courseenddate', 'customcertelement_date');
|
||||
$dateoptions[CUSTOMCERT_DATE_COURSE_GRADE] = get_string('coursegradedate', 'customcertelement_date');
|
||||
|
@ -141,10 +160,12 @@ class element extends \mod_customcert\element {
|
|||
$customcert = $DB->get_record('customcert', array('templateid' => $page->templateid), '*', MUST_EXIST);
|
||||
// Now we can get the issue for this user.
|
||||
$issue = $DB->get_record('customcert_issues', array('userid' => $user->id, 'customcertid' => $customcert->id),
|
||||
'*', MUST_EXIST);
|
||||
'*', IGNORE_MULTIPLE);
|
||||
|
||||
if ($dateitem == CUSTOMCERT_DATE_ISSUE) {
|
||||
$date = $issue->timecreated;
|
||||
} else if ($dateitem == CUSTOMCERT_DATE_CURRENT_DATE) {
|
||||
$date = time();
|
||||
} else if ($dateitem == CUSTOMCERT_DATE_COMPLETION) {
|
||||
// Get the last completion date.
|
||||
$sql = "SELECT MAX(c.timecompleted) as timecompleted
|
||||
|
@ -156,6 +177,26 @@ class element extends \mod_customcert\element {
|
|||
$date = $timecompleted->timecompleted;
|
||||
}
|
||||
}
|
||||
} else if ($dateitem == CUSTOMCERT_DATE_ENROLMENT_START) {
|
||||
// Get the enrolment start date.
|
||||
$sql = "SELECT ue.timestart FROM {enrol} e JOIN {user_enrolments} ue ON ue.enrolid = e.id
|
||||
WHERE e.courseid = :courseid
|
||||
AND ue.userid = :userid";
|
||||
if ($timestart = $DB->get_record_sql($sql, array('userid' => $issue->userid, 'courseid' => $courseid))) {
|
||||
if (!empty($timestart->timestart)) {
|
||||
$date = $timestart->timestart;
|
||||
}
|
||||
}
|
||||
} else if ($dateitem == CUSTOMCERT_DATE_ENROLMENT_END) {
|
||||
// Get the enrolment end date.
|
||||
$sql = "SELECT ue.timeend FROM {enrol} e JOIN {user_enrolments} ue ON ue.enrolid = e.id
|
||||
WHERE e.courseid = :courseid
|
||||
AND ue.userid = :userid";
|
||||
if ($timeend = $DB->get_record_sql($sql, array('userid' => $issue->userid, 'courseid' => $courseid))) {
|
||||
if (!empty($timeend->timeend)) {
|
||||
$date = $timeend->timeend;
|
||||
}
|
||||
}
|
||||
} else if ($dateitem == CUSTOMCERT_DATE_COURSE_START) {
|
||||
$date = $DB->get_field('course', 'startdate', array('id' => $courseid));
|
||||
} else if ($dateitem == CUSTOMCERT_DATE_COURSE_END) {
|
||||
|
@ -218,7 +259,7 @@ class element extends \mod_customcert\element {
|
|||
/**
|
||||
* Sets the data on the form when editing an element.
|
||||
*
|
||||
* @param \mod_customcert\edit_element_form $mform the edit_form instance
|
||||
* @param \MoodleQuickForm $mform the edit_form instance
|
||||
*/
|
||||
public function definition_after_data($mform) {
|
||||
// Set the item and format for this element.
|
||||
|
|
|
@ -26,6 +26,9 @@ $string['completiondate'] = 'Completion date';
|
|||
$string['courseenddate'] = 'Course end date';
|
||||
$string['coursegradedate'] = 'Course grade date';
|
||||
$string['coursestartdate'] = 'Course start date';
|
||||
$string['enrolmentenddate'] = 'Enrolment end date';
|
||||
$string['enrolmentstartdate'] = 'Enrolment start date';
|
||||
$string['currentdate'] = 'Current date';
|
||||
$string['dateformat'] = 'Date format';
|
||||
$string['dateformat_help'] = 'This is the format of the date that will be displayed';
|
||||
$string['dateitem'] = 'Date item';
|
||||
|
|
|
@ -24,6 +24,6 @@
|
|||
|
||||
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
|
||||
|
||||
$plugin->version = 2018051700; // The current module version (Date: YYYYMMDDXX).
|
||||
$plugin->version = 2018051701; // The current module version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2018051700; // Requires this Moodle version (3.5).
|
||||
$plugin->component = 'customcertelement_date';
|
||||
|
|
731
element/daterange/classes/element.php
Normal file
731
element/daterange/classes/element.php
Normal file
|
@ -0,0 +1,731 @@
|
|||
<?php
|
||||
// This file is part of the customcert module for 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/>.
|
||||
|
||||
/**
|
||||
* This file contains the customcert date range element.
|
||||
*
|
||||
* @package customcertelement_daterange
|
||||
* @copyright 2018 Dmitrii Metelkin <dmitriim@catalyst-au.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace customcertelement_daterange;
|
||||
|
||||
use \mod_customcert\element_helper;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
|
||||
|
||||
require_once($CFG->dirroot . '/lib/grade/constants.php');
|
||||
|
||||
/**
|
||||
* The customcert date range element.
|
||||
*
|
||||
* @package customcertelement_daterange
|
||||
* @copyright 2018 Dmitrii Metelkin <dmitriim@catalyst-au.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class element extends \mod_customcert\element {
|
||||
|
||||
/**
|
||||
* Max recurring period in seconds.
|
||||
*/
|
||||
const MAX_RECURRING_PERIOD = 31556926; // 12 months.
|
||||
|
||||
/**
|
||||
* Current year placeholder string.
|
||||
*/
|
||||
const CURRENT_YEAR_PLACEHOLDER = '{{current_year}}';
|
||||
|
||||
/**
|
||||
* First year in a date range placeholder string.
|
||||
*/
|
||||
const RANGE_FIRST_YEAR_PLACEHOLDER = '{{range_first_year}}';
|
||||
|
||||
/**
|
||||
* Last year in a date range placeholder string.
|
||||
*/
|
||||
const RANGE_LAST_YEAR_PLACEHOLDER = '{{range_last_year}}';
|
||||
|
||||
/**
|
||||
* First year in a date range placeholder string.
|
||||
*/
|
||||
const RECUR_RANGE_FIRST_YEAR_PLACEHOLDER = '{{recurring_range_first_year}}';
|
||||
|
||||
/**
|
||||
* Last year in a date range placeholder string.
|
||||
*/
|
||||
const RECUR_RANGE_LAST_YEAR_PLACEHOLDER = '{{recurring_range_last_year}}';
|
||||
|
||||
/**
|
||||
* A year in the user's date.
|
||||
*/
|
||||
const DATE_YEAR_PLACEHOLDER = '{{date_year}}';
|
||||
|
||||
/**
|
||||
* Date - Issue
|
||||
*/
|
||||
const DATE_ISSUE = -1;
|
||||
|
||||
/**
|
||||
* Date - Completion
|
||||
*/
|
||||
const DATE_COMPLETION = -2;
|
||||
|
||||
/**
|
||||
* Date - Course start
|
||||
*/
|
||||
const DATE_COURSE_START = -3;
|
||||
|
||||
/**
|
||||
* Date - Course end
|
||||
*/
|
||||
const DATE_COURSE_END = -4;
|
||||
|
||||
/**
|
||||
* Date - Course grade date
|
||||
*/
|
||||
const DATE_COURSE_GRADE = -5;
|
||||
|
||||
/**
|
||||
* Date - Course current date
|
||||
*/
|
||||
const DATE_CURRENT_DATE = -6;
|
||||
|
||||
/**
|
||||
* This function renders the form elements when adding a customcert element.
|
||||
*
|
||||
* @param \MoodleQuickForm $mform the edit form instance
|
||||
*/
|
||||
public function render_form_elements($mform) {
|
||||
global $COURSE;
|
||||
|
||||
// Get the possible date options.
|
||||
$dateoptions = array();
|
||||
$dateoptions[self::DATE_ISSUE] = get_string('issueddate', 'customcertelement_daterange');
|
||||
$dateoptions[self::DATE_CURRENT_DATE] = get_string('currentdate', 'customcertelement_daterange');
|
||||
$dateoptions[self::DATE_COMPLETION] = get_string('completiondate', 'customcertelement_daterange');
|
||||
$dateoptions[self::DATE_COURSE_START] = get_string('coursestartdate', 'customcertelement_daterange');
|
||||
$dateoptions[self::DATE_COURSE_END] = get_string('courseenddate', 'customcertelement_daterange');
|
||||
$dateoptions[self::DATE_COURSE_GRADE] = get_string('coursegradedate', 'customcertelement_daterange');
|
||||
|
||||
$dateoptions = $dateoptions + element_helper::get_grade_items($COURSE);
|
||||
|
||||
$mform->addElement('select', 'dateitem', get_string('dateitem', 'customcertelement_daterange'), $dateoptions);
|
||||
$mform->addHelpButton('dateitem', 'dateitem', 'customcertelement_daterange');
|
||||
|
||||
parent::render_form_elements($mform);
|
||||
|
||||
$mform->addElement('header', 'dateranges', get_string('dateranges', 'customcertelement_daterange'));
|
||||
$mform->addElement('static', 'help', '', get_string('help', 'customcertelement_daterange'));
|
||||
$mform->addElement('static', 'placeholders', '', get_string('placeholders', 'customcertelement_daterange'));
|
||||
|
||||
$mform->addElement('text', 'fallbackstring', get_string('fallbackstring', 'customcertelement_daterange'));
|
||||
$mform->addHelpButton('fallbackstring', 'fallbackstring', 'customcertelement_daterange');
|
||||
$mform->setType('fallbackstring', PARAM_NOTAGS);
|
||||
|
||||
if (empty($this->get_decoded_data()->dateranges)) {
|
||||
$repeats = 1;
|
||||
} else {
|
||||
$repeats = count($this->get_decoded_data()->dateranges);
|
||||
}
|
||||
|
||||
$ranges = [];
|
||||
|
||||
$ranges[] = $mform->createElement('html', '<hr>');
|
||||
|
||||
$ranges[] = $mform->createElement(
|
||||
'date_selector',
|
||||
'startdate',
|
||||
get_string('start', 'customcertelement_daterange')
|
||||
);
|
||||
|
||||
$ranges[] = $mform->createElement(
|
||||
'date_selector',
|
||||
'enddate',
|
||||
get_string('end', 'customcertelement_daterange')
|
||||
);
|
||||
|
||||
$ranges[] = $mform->createElement(
|
||||
'checkbox',
|
||||
'recurring',
|
||||
get_string('recurring', 'customcertelement_daterange')
|
||||
);
|
||||
|
||||
$ranges[] = $mform->createElement(
|
||||
'text',
|
||||
'datestring',
|
||||
get_string('datestring', 'customcertelement_daterange'),
|
||||
['class' => 'datestring']
|
||||
);
|
||||
|
||||
$ranges[] = $mform->createElement(
|
||||
'advcheckbox',
|
||||
'rangedelete',
|
||||
get_string('setdeleted', 'customcertelement_daterange'),
|
||||
'',
|
||||
[],
|
||||
[0, 1]
|
||||
);
|
||||
|
||||
$rangeoptions = array();
|
||||
$rangeoptions['startdate']['type'] = PARAM_INT;
|
||||
$rangeoptions['enddate']['type'] = PARAM_INT;
|
||||
$rangeoptions['recurring']['type'] = PARAM_INT;
|
||||
$rangeoptions['recurring']['helpbutton'] = ['recurring', 'customcertelement_daterange'];
|
||||
$rangeoptions['datestring']['type'] = PARAM_NOTAGS;
|
||||
$rangeoptions['rangedelete']['type'] = PARAM_BOOL;
|
||||
|
||||
$addstring = get_string('addrange', 'customcertelement_daterange');
|
||||
$this->get_edit_element_form()->repeat_elements($ranges, $repeats, $rangeoptions, 'repeats', 'add', 1, $addstring, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function to build consistent form element name.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $num
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function build_element_name($name, $num) {
|
||||
return $name . '[' . $num . ']';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get decoded data stored in DB.
|
||||
*
|
||||
* @return \stdClass
|
||||
*/
|
||||
protected function get_decoded_data() {
|
||||
return json_decode($this->get_data());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the data on the form when editing an element.
|
||||
*
|
||||
* @param \MoodleQuickForm $mform the edit form instance
|
||||
*/
|
||||
public function definition_after_data($mform) {
|
||||
if (!empty($this->get_data()) && !$mform->isSubmitted()) {
|
||||
$element = $mform->getElement('dateitem');
|
||||
$element->setValue($this->get_decoded_data()->dateitem);
|
||||
|
||||
$element = $mform->getElement('fallbackstring');
|
||||
$element->setValue($this->get_decoded_data()->fallbackstring);
|
||||
|
||||
foreach ($this->get_decoded_data()->dateranges as $key => $range) {
|
||||
$mform->setDefault($this->build_element_name('startdate', $key), $range->startdate);
|
||||
$mform->setDefault($this->build_element_name('enddate', $key), $range->enddate);
|
||||
$mform->setDefault($this->build_element_name('datestring', $key), $range->datestring);
|
||||
$mform->setDefault($this->build_element_name('recurring', $key), $range->recurring);
|
||||
}
|
||||
}
|
||||
|
||||
parent::definition_after_data($mform);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs validation on the element values.
|
||||
*
|
||||
* @param array $data the submitted data
|
||||
* @param array $files the submitted files
|
||||
* @return array the validation errors
|
||||
*/
|
||||
public function validate_form_elements($data, $files) {
|
||||
$errors = parent::validate_form_elements($data, $files);
|
||||
|
||||
// Check if at least one range is set.
|
||||
$error = get_string('error:atleastone', 'customcertelement_daterange');
|
||||
|
||||
for ($i = 0; $i < $data['repeats']; $i++) {
|
||||
if (empty($data['rangedelete'][$i])) {
|
||||
$error = '';
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($error)) {
|
||||
$errors['help'] = $error;
|
||||
}
|
||||
|
||||
// Check that datestring is set dataranges what aren't need to be deleted.
|
||||
for ($i = 0; $i < $data['repeats']; $i++) {
|
||||
// Skip elements that needs to be deleted.
|
||||
if (!empty($data['rangedelete'][$i])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (empty($data['datestring'][$i])) {
|
||||
$name = $this->build_element_name('datestring', $i);
|
||||
$errors[$name] = get_string('error:datestring', 'customcertelement_daterange');
|
||||
}
|
||||
|
||||
// Check that end date is correctly set.
|
||||
if ( $data['startdate'][$i] >= $data['enddate'][$i] ) {
|
||||
$errors[$this->build_element_name('enddate', $i)] = get_string('error:enddate', 'customcertelement_daterange');
|
||||
}
|
||||
|
||||
$rangeperiod = $data['enddate'][$i] - $data['startdate'][$i];
|
||||
|
||||
// Check that recurring dateranges are not longer than 12 months.
|
||||
if (!empty($data['recurring'][$i]) && $rangeperiod >= self::MAX_RECURRING_PERIOD ) {
|
||||
$errors[$this->build_element_name('enddate', $i)] = get_string('error:recurring', 'customcertelement_daterange');
|
||||
}
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* This will handle how form data will be saved into the data column in the
|
||||
* customcert_elements table.
|
||||
*
|
||||
* @param \stdClass $data the form data
|
||||
* @return string the json encoded array
|
||||
*/
|
||||
public function save_unique_data($data) {
|
||||
$arrtostore = array(
|
||||
'dateitem' => $data->dateitem,
|
||||
'fallbackstring' => $data->fallbackstring,
|
||||
'dateranges' => [],
|
||||
);
|
||||
|
||||
for ($i = 0; $i < $data->repeats; $i++) {
|
||||
if (empty($data->rangedelete[$i])) {
|
||||
$arrtostore['dateranges'][] = [
|
||||
'startdate' => $data->startdate[$i],
|
||||
'enddate' => $data->enddate[$i],
|
||||
'datestring' => $data->datestring[$i],
|
||||
'recurring' => !empty($data->recurring[$i]),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
// Encode these variables before saving into the DB.
|
||||
return json_encode($arrtostore);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles rendering the element on the pdf.
|
||||
*
|
||||
* @param \pdf $pdf the pdf object
|
||||
* @param bool $preview true if it is a preview, false otherwise
|
||||
* @param \stdClass $user the user we are rendering this for
|
||||
*/
|
||||
public function render($pdf, $preview, $user) {
|
||||
global $DB;
|
||||
|
||||
// If there is no element data, we have nothing to display.
|
||||
if (empty($this->get_data())) {
|
||||
return;
|
||||
}
|
||||
|
||||
$courseid = element_helper::get_courseid($this->id);
|
||||
$dateitem = $this->get_decoded_data()->dateitem;
|
||||
|
||||
// If we are previewing this certificate then just show a demonstration date.
|
||||
if ($preview) {
|
||||
$date = time();
|
||||
} else {
|
||||
// Get the page.
|
||||
$page = $DB->get_record('customcert_pages', array('id' => $this->get_pageid()), '*', MUST_EXIST);
|
||||
// Get the customcert this page belongs to.
|
||||
$customcert = $DB->get_record('customcert', array('templateid' => $page->templateid), '*', MUST_EXIST);
|
||||
// Now we can get the issue for this user.
|
||||
$issue = $DB->get_record('customcert_issues', array('userid' => $user->id, 'customcertid' => $customcert->id),
|
||||
'*', MUST_EXIST);
|
||||
|
||||
switch ($dateitem) {
|
||||
case self::DATE_ISSUE:
|
||||
$date = $issue->timecreated;
|
||||
break;
|
||||
|
||||
case self::DATE_CURRENT_DATE:
|
||||
$date = time();
|
||||
break;
|
||||
|
||||
case self::DATE_COMPLETION:
|
||||
// Get the last completion date.
|
||||
$sql = "SELECT MAX(c.timecompleted) as timecompleted
|
||||
FROM {course_completions} c
|
||||
WHERE c.userid = :userid
|
||||
AND c.course = :courseid";
|
||||
if ($timecompleted = $DB->get_record_sql($sql, array('userid' => $issue->userid, 'courseid' => $courseid))) {
|
||||
if (!empty($timecompleted->timecompleted)) {
|
||||
$date = $timecompleted->timecompleted;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case self::DATE_COURSE_START:
|
||||
$date = $DB->get_field('course', 'startdate', array('id' => $courseid));
|
||||
break;
|
||||
|
||||
case self::DATE_COURSE_END:
|
||||
$date = $DB->get_field('course', 'enddate', array('id' => $courseid));
|
||||
break;
|
||||
|
||||
case self::DATE_COURSE_GRADE:
|
||||
$grade = element_helper::get_course_grade_info(
|
||||
$courseid,
|
||||
GRADE_DISPLAY_TYPE_DEFAULT, $user->id
|
||||
);
|
||||
if ($grade && !empty($grade->get_dategraded())) {
|
||||
$date = $grade->get_dategraded();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (strpos($dateitem, 'gradeitem:') === 0) {
|
||||
$gradeitemid = substr($dateitem, 10);
|
||||
$grade = element_helper::get_grade_item_info(
|
||||
$gradeitemid,
|
||||
$dateitem,
|
||||
$user->id
|
||||
);
|
||||
} else {
|
||||
$grade = element_helper::get_mod_grade_info(
|
||||
$dateitem,
|
||||
GRADE_DISPLAY_TYPE_DEFAULT,
|
||||
$user->id
|
||||
);
|
||||
}
|
||||
if ($grade && !empty($grade->get_dategraded())) {
|
||||
$date = $grade->get_dategraded();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that a date has been set.
|
||||
if (!empty($date)) {
|
||||
element_helper::render_content($pdf, $this, $this->get_daterange_string($date));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get daterange string.
|
||||
*
|
||||
* @param int $date Unix stamp date.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_daterange_string($date) {
|
||||
$matchedrange = null;
|
||||
$outputstring = '';
|
||||
$formatdata = [];
|
||||
$formatdata['date'] = $date;
|
||||
|
||||
foreach ($this->get_decoded_data()->dateranges as $key => $range) {
|
||||
if ($this->is_recurring_range($range)) {
|
||||
if ($matchedrange = $this->get_matched_recurring_range($date, $range)) {
|
||||
$outputstring = $matchedrange->datestring;
|
||||
$formatdata['range'] = $range;
|
||||
$formatdata['recurringrange'] = $matchedrange;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if ($this->is_date_in_range($date, $range)) {
|
||||
$outputstring = $range->datestring;
|
||||
$formatdata['range'] = $range;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($outputstring) && !empty($this->get_decoded_data()->fallbackstring)) {
|
||||
$outputstring = $this->get_decoded_data()->fallbackstring;
|
||||
}
|
||||
|
||||
return $this->format_date_string($outputstring, $formatdata);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not a range is recurring.
|
||||
*
|
||||
* @param \stdClass $range Range object.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function is_recurring_range(\stdClass $range) {
|
||||
return !empty($range->recurring);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the provided date is in the date range.
|
||||
*
|
||||
* @param int $date Unix timestamp date to check.
|
||||
* @param \stdClass $range Range object.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function is_date_in_range($date, \stdClass $range) {
|
||||
return ($date >= $range->startdate && $date <= $range->enddate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if provided date is in the recurring date range.
|
||||
*
|
||||
* @param int $date Unix timestamp date to check.
|
||||
* @param \stdClass $range Range object.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function is_date_in_recurring_range($date, \stdClass $range) {
|
||||
$intdate = $this->build_number_from_date($date);
|
||||
$intstart = $this->build_number_from_date($range->startdate);
|
||||
$intend = $this->build_number_from_date($range->enddate);
|
||||
|
||||
if (!$this->has_turn_of_the_year($range)) {
|
||||
if ($intdate >= $intstart && $intdate <= $intend) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if ($intdate >= $intstart && $intdate >= $intend) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($intdate <= $intstart && $intdate <= $intend) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if provided recurring range has a turn of the year.
|
||||
*
|
||||
* @param \stdClass $reccurringrange Range object.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function has_turn_of_the_year(\stdClass $reccurringrange) {
|
||||
return date('Y', $reccurringrange->startdate) != date('Y', $reccurringrange->enddate);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if provided date is in the start year of the recurring range with a turn of the year.
|
||||
*
|
||||
* @param int $date Unix timestamp date to check.
|
||||
* @param \stdClass $range Range object.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function in_start_year($date, \stdClass $range) {
|
||||
$intdate = $this->build_number_from_date($date);
|
||||
$intstart = $this->build_number_from_date($range->startdate);
|
||||
$intend = $this->build_number_from_date($range->enddate);
|
||||
|
||||
return $intdate >= $intstart && $intdate >= $intend;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if provided date is in the end year of the recurring range with a turn of the year.
|
||||
*
|
||||
* @param int $date Unix timestamp date to check.
|
||||
* @param \stdClass $range Range object.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function in_end_year($date, \stdClass $range) {
|
||||
$intdate = $this->build_number_from_date($date);
|
||||
$intstart = $this->build_number_from_date($range->startdate);
|
||||
$intend = $this->build_number_from_date($range->enddate);
|
||||
|
||||
return $intdate <= $intstart && $intdate <= $intend;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return matched recurring date range.
|
||||
*
|
||||
* As recurring date ranges do not depend on the year,
|
||||
* we will use a date's year to build a new matched recurring date range with
|
||||
* start year and end year. This is required to replace placeholders like range_first_year and range_last_year.
|
||||
*
|
||||
* @param int $date Unix timestamp date to check.
|
||||
* @param \stdClass $range Range object.
|
||||
*
|
||||
* @return \stdClass || null
|
||||
*/
|
||||
protected function get_matched_recurring_range($date, \stdClass $range) {
|
||||
if (!$this->is_date_in_recurring_range($date, $range)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$matchedrage = clone $range;
|
||||
|
||||
if ($this->has_turn_of_the_year($matchedrage)) {
|
||||
|
||||
if ($this->in_start_year($date, $matchedrage)) {
|
||||
$startyear = date('Y', $date);
|
||||
$endyear = $startyear + 1;
|
||||
$matchedrage->startdate = strtotime(date('d.m.', $matchedrage->startdate) . $startyear);
|
||||
$matchedrage->enddate = strtotime(date('d.m.', $matchedrage->enddate) . $endyear);
|
||||
|
||||
return $matchedrage;
|
||||
}
|
||||
|
||||
if ($this->in_end_year($date, $matchedrage)) {
|
||||
$endyear = date('Y', $date);
|
||||
$startyear = $endyear - 1;
|
||||
$matchedrage->startdate = strtotime(date('d.m.', $matchedrage->startdate) . $startyear);
|
||||
$matchedrage->enddate = strtotime(date('d.m.', $matchedrage->enddate) . $endyear);
|
||||
|
||||
return $matchedrage;
|
||||
}
|
||||
} else {
|
||||
$matchedrage->startdate = strtotime(date('d.m.', $matchedrage->startdate) . date('Y', $date));
|
||||
$matchedrage->enddate = strtotime(date('d.m.', $matchedrage->enddate) . date('Y', $date));
|
||||
|
||||
return $matchedrage;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build number representation of the provided date.
|
||||
*
|
||||
* @param int $date Unix timestamp date to check.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function build_number_from_date($date) {
|
||||
return (int)date('md', $date);
|
||||
}
|
||||
|
||||
/**
|
||||
* Format date string based on different types of placeholders.
|
||||
*
|
||||
* @param string $datestring The date string
|
||||
* @param array $formatdata A list of format data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function format_date_string($datestring, array $formatdata) {
|
||||
foreach ($this->get_placeholders() as $search => $replace) {
|
||||
$datestring = str_replace($search, $replace, $datestring);
|
||||
}
|
||||
|
||||
if (!empty($formatdata['date'])) {
|
||||
foreach ($this->get_date_placeholders($formatdata['date']) as $search => $replace) {
|
||||
$datestring = str_replace($search, $replace, $datestring);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($formatdata['range'])) {
|
||||
foreach ($this->get_range_placeholders($formatdata['range']) as $search => $replace) {
|
||||
$datestring = str_replace($search, $replace, $datestring);
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($formatdata['recurringrange'])) {
|
||||
foreach ($this->get_recurring_range_placeholders($formatdata['recurringrange']) as $search => $replace) {
|
||||
$datestring = str_replace($search, $replace, $datestring);
|
||||
}
|
||||
}
|
||||
|
||||
return $datestring;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of placeholders to replace in date string as search => $replace pairs.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_placeholders() {
|
||||
return [
|
||||
self::CURRENT_YEAR_PLACEHOLDER => date('Y', time()),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of user's date related placeholders to replace in date string as search => $replace pairs.
|
||||
|
||||
* @param int $date Unix timestamp date to check.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_date_placeholders($date) {
|
||||
return [
|
||||
self::DATE_YEAR_PLACEHOLDER => date('Y', $date),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of range related placeholders to replace in date string as search => $replace pairs.
|
||||
*
|
||||
* @param \stdClass $range
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_range_placeholders(\stdClass $range) {
|
||||
return [
|
||||
self::RANGE_FIRST_YEAR_PLACEHOLDER => date('Y', $range->startdate),
|
||||
self::RANGE_LAST_YEAR_PLACEHOLDER => date('Y', $range->enddate),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of recurring range s placeholders to replace in date string as search => $replace pairs.
|
||||
*
|
||||
* @param \stdClass $range
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_recurring_range_placeholders(\stdClass $range) {
|
||||
return [
|
||||
self::RECUR_RANGE_FIRST_YEAR_PLACEHOLDER => date('Y', $range->startdate),
|
||||
self::RECUR_RANGE_LAST_YEAR_PLACEHOLDER => date('Y', $range->enddate),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the element in html.
|
||||
*
|
||||
* This function is used to render the element when we are using the
|
||||
* drag and drop interface to position it.
|
||||
*
|
||||
* @return string the html
|
||||
*/
|
||||
public function render_html() {
|
||||
// If there is no element data, we have nothing to display.
|
||||
if (empty($this->get_data())) {
|
||||
return;
|
||||
}
|
||||
|
||||
return element_helper::render_html_content($this, get_string('preview', 'customcertelement_daterange', $this->get_name()));
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is responsible for handling the restoration process of the element.
|
||||
*
|
||||
* We will want to update the course module the date element is pointing to as it will
|
||||
* have changed in the course restore.
|
||||
*
|
||||
* @param \restore_customcert_activity_task $restore
|
||||
*/
|
||||
public function after_restore($restore) {
|
||||
global $DB;
|
||||
|
||||
$data = $this->get_decoded_data();
|
||||
if ($newitem = \restore_dbops::get_backup_ids_record($restore->get_restoreid(), 'course_module', $data->dateitem)) {
|
||||
$data->dateitem = $newitem->newitemid;
|
||||
$DB->set_field('customcert_elements', 'data', $this->save_unique_data($data), array('id' => $this->get_id()));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
46
element/daterange/classes/privacy/provider.php
Normal file
46
element/daterange/classes/privacy/provider.php
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* Privacy Subsystem implementation for customcertelement_daterange.
|
||||
*
|
||||
* @package customcertelement_daterange
|
||||
* @copyright 2018 Dmitrii Metelkin <dmitriim@catalyst-au.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace customcertelement_daterange\privacy;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Privacy Subsystem for customcertelement_daterange implementing null_provider.
|
||||
*
|
||||
* @copyright 2018 Dmitrii Metelkin <dmitriim@catalyst-au.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class provider implements \core_privacy\local\metadata\null_provider {
|
||||
|
||||
/**
|
||||
* Get the language string identifier with the component's language
|
||||
* file to explain why this plugin stores no data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_reason() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
}
|
53
element/daterange/lang/en/customcertelement_daterange.php
Normal file
53
element/daterange/lang/en/customcertelement_daterange.php
Normal file
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
// This file is part of the customcert module for 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/>.
|
||||
|
||||
/**
|
||||
* Strings for component 'customcertelement_daterange', language 'en'.
|
||||
*
|
||||
* @package customcertelement_daterange
|
||||
* @copyright 2018 Dmitrii Metelkin <dmitriim@catalyst-au.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
|
||||
|
||||
$string['addrange'] = 'Add another range';
|
||||
$string['completiondate'] = 'Completion date';
|
||||
$string['courseenddate'] = 'Course end date';
|
||||
$string['coursegradedate'] = 'Course grade date';
|
||||
$string['coursestartdate'] = 'Course start date';
|
||||
$string['currentdate'] = 'Current date';
|
||||
$string['dateitem'] = 'Date item';
|
||||
$string['dateitem_help'] = 'This will be the date that is printed on the certificate';
|
||||
$string['dateranges'] = 'Date ranges';
|
||||
$string['datestring'] = 'String';
|
||||
$string['end'] = 'End';
|
||||
$string['error:atleastone'] = 'You must have at least one date range configured';
|
||||
$string['error:datestring'] = 'You must provide string representation for the date range';
|
||||
$string['error:enddate'] = 'End date must occur after the start date';
|
||||
$string['error:recurring'] = 'Recurring range must not be longer than 12 months';
|
||||
$string['fallbackstring'] = 'Fallback string';
|
||||
$string['fallbackstring_help'] = 'This string will be displayed if no date range applies to a date. If the fallback string is not set, then there will be no output at all.';
|
||||
$string['help'] = 'Configure a string representation for your date ranges.<br /><br />If your ranges overlap the first matched date range will be applied.';
|
||||
$string['issueddate'] = 'Issued date';
|
||||
$string['placeholders'] = 'The following placeholders can be used in the string representation or fallback string. <br/><br /> {{range_first_year}} - first year of the matched range,<br/> {{range_last_year}} - last year of the matched range,<br/> {{recurring_range_first_year}} - first year of the matched recurring period,<br/> {{recurring_range_last_year}} - last year of the matched recurring period,<br/> {{current_year}} - the current year,<br/> {{date_year}} - a year of the users\'s date.';
|
||||
$string['pluginname'] = 'Date range';
|
||||
$string['preview'] = 'Preview {$a}';
|
||||
$string['privacy:metadata'] = 'The Date range plugin does not store any personal data.';
|
||||
$string['recurring'] = 'Recurring';
|
||||
$string['recurring_help'] = 'If you mark a date range as recurring then the configured year will not be considered.';
|
||||
$string['setdeleted'] = 'Delete';
|
||||
$string['start'] = 'Start';
|
248
element/daterange/tests/element_test.php
Normal file
248
element/daterange/tests/element_test.php
Normal file
|
@ -0,0 +1,248 @@
|
|||
<?php
|
||||
// This file is part of the customcert module for 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/>.
|
||||
|
||||
/**
|
||||
* Test datarange element.
|
||||
*
|
||||
* @package customcertelement_daterange
|
||||
* @copyright 2018 Dmitrii Metelkin <dmitriim@catalyst-au.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
|
||||
require_once($CFG->dirroot . '/mod/customcert/element/daterange/tests/fixtures/fake_datarange_element.php');
|
||||
|
||||
/**
|
||||
* Test datarange element.
|
||||
*
|
||||
* @package customcertelement_daterange
|
||||
* @copyright 2018 Dmitrii Metelkin <dmitriim@catalyst-au.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class customcertelement_daterange_element_test extends advanced_testcase {
|
||||
|
||||
/**
|
||||
* Helper function to build element data.
|
||||
*
|
||||
* @param stdClass $data Element data.
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
protected function build_element_data(stdClass $data) {
|
||||
return (object) [
|
||||
'id' => 1,
|
||||
'pageid' => 1,
|
||||
'name' => 'Test',
|
||||
'data' => json_encode($data),
|
||||
'font' => 'Font',
|
||||
'fontsize' => 1,
|
||||
'colour' => '#EEE',
|
||||
'posx' => 0,
|
||||
'posy' => 0,
|
||||
'width' => 100,
|
||||
'refpoint' => 1
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to build datarange data.
|
||||
*
|
||||
* @param array $dataranges A list of dataranges.
|
||||
* @param string $fallbackstring Fall back string.
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
protected function build_datarange_data(array $dataranges, $fallbackstring = '') {
|
||||
return (object) [
|
||||
'dateitem' => 1,
|
||||
'fallbackstring' => $fallbackstring,
|
||||
'numranges' => count($dataranges),
|
||||
'dateranges' => $dataranges,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function to get datarange element for testing.
|
||||
*
|
||||
* @param array $dataranges A list of dataranges.
|
||||
* @param string $fallbackstring Fall back strin
|
||||
*
|
||||
* @return \fake_datarange_element
|
||||
*/
|
||||
protected function get_datarange_element(array $dataranges, $fallbackstring = '') {
|
||||
$datarangedata = $this->build_datarange_data($dataranges, $fallbackstring);
|
||||
$elementdata = $this->build_element_data($datarangedata);
|
||||
|
||||
return new fake_datarange_element($elementdata);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for test_get_daterange_string_for_recurring_ranges.
|
||||
* @return array
|
||||
*/
|
||||
public function get_test_get_daterange_string_for_recurring_ranges_data_provider() {
|
||||
return [
|
||||
['1.11.2016', 'WS 2016/2017'],
|
||||
['1.11.2017', 'WS 2017/2018'],
|
||||
['1.11.2018', 'WS 2018/2019'],
|
||||
['1.11.2019', 'WS 2019/2020'],
|
||||
['1.02.2017', 'WS 2016/2017'],
|
||||
['1.02.2018', 'WS 2017/2018'],
|
||||
['1.02.2019', 'WS 2018/2019'],
|
||||
['1.02.2020', 'WS 2019/2020'],
|
||||
['1.05.2016', 'SS 2016'],
|
||||
['1.05.2017', 'SS 2017'],
|
||||
['1.05.2018', 'SS 2018'],
|
||||
['1.05.2019', 'SS 2019'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get correct strings for recurring ranges.
|
||||
*
|
||||
* @dataProvider get_test_get_daterange_string_for_recurring_ranges_data_provider
|
||||
*
|
||||
* @param string $date Date to test.
|
||||
* @param string $expected Expected result.
|
||||
*/
|
||||
public function test_get_daterange_string_for_recurring_ranges($date, $expected) {
|
||||
$dateranges = [
|
||||
(object)[
|
||||
'startdate' => strtotime('01.04.2017'),
|
||||
'enddate' => strtotime('30.09.2017'),
|
||||
'datestring' => 'SS {{date_year}}',
|
||||
'recurring' => true,
|
||||
],
|
||||
(object)[
|
||||
'startdate' => strtotime('01.10.2017'),
|
||||
'enddate' => strtotime('31.03.2018'),
|
||||
'datestring' => 'WS {{recurring_range_first_year}}/{{recurring_range_last_year}}',
|
||||
'recurring' => true,
|
||||
],
|
||||
];
|
||||
|
||||
$element = $this->get_datarange_element($dateranges);
|
||||
$date = strtotime($date);
|
||||
$this->assertEquals($expected, $element->get_daterange_string($date));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that first found element matched.
|
||||
*/
|
||||
public function test_that_first_matched_range_applied_first() {
|
||||
$dateranges = [
|
||||
(object)[
|
||||
'startdate' => strtotime('01.04.2017'),
|
||||
'enddate' => strtotime('30.09.2017'),
|
||||
'datestring' => 'First range',
|
||||
'recurring' => false,
|
||||
],
|
||||
(object)[
|
||||
'startdate' => strtotime('01.05.2017'),
|
||||
'enddate' => strtotime('01.07.2018'),
|
||||
'datestring' => 'Second range',
|
||||
'recurring' => false,
|
||||
],
|
||||
];
|
||||
|
||||
$element = $this->get_datarange_element($dateranges);
|
||||
$date = strtotime('1.06.2017');
|
||||
$this->assertEquals('First range', $element->get_daterange_string($date));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that placeholders correctly applied to matched range and fall back string.
|
||||
*/
|
||||
public function test_placeholders_and_fall_back_string() {
|
||||
$dateranges = [
|
||||
(object)[
|
||||
'startdate' => strtotime('01.04.2017'),
|
||||
'enddate' => strtotime('30.09.2018'),
|
||||
'datestring' => '{{current_year}} - {{range_first_year}} - {{range_last_year}} - {{date_year}}',
|
||||
'recurring' => false,
|
||||
],
|
||||
];
|
||||
|
||||
$fallbackstring = '{{current_year}} - {{range_first_year}} - {{range_last_year}} - {{date_year}}';
|
||||
$element = $this->get_datarange_element($dateranges, $fallbackstring);
|
||||
|
||||
$date = strtotime('1.01.2000');
|
||||
$expected = date('Y', time()) . ' - {{range_first_year}} - {{range_last_year}} - 2000';
|
||||
$this->assertEquals($expected, $element->get_daterange_string($date));
|
||||
|
||||
$date = strtotime('1.07.2017');
|
||||
$expected = date('Y', time()) . ' - 2017 - 2018 - 2017';
|
||||
$this->assertEquals($expected, $element->get_daterange_string($date));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that nothing will be displayed if not matched and empty fall back string.
|
||||
*/
|
||||
public function test_nothing_will_be_displayed_if_empty_fallback_string() {
|
||||
$dateranges = [
|
||||
(object)[
|
||||
'startdate' => strtotime('01.04.2017'),
|
||||
'enddate' => strtotime('30.09.2018'),
|
||||
'datestring' => '{{current_year}} - {{range_first_year}} - {{range_last_year}} - {{date_year}}',
|
||||
'recurring' => false,
|
||||
],
|
||||
];
|
||||
|
||||
$fallbackstring = '';
|
||||
$element = $this->get_datarange_element($dateranges, $fallbackstring);
|
||||
|
||||
$date = strtotime('1.07.2011');
|
||||
$this->assertEquals($fallbackstring, $element->get_daterange_string($date));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that display recurring_range_first_year and recurring_range_last_year placeholders.
|
||||
*/
|
||||
public function test_recurring_range_first_year_and_recurring_range_last_year_placeholders() {
|
||||
$datestring = '{{range_first_year}}-{{range_last_year}}-{{recurring_range_first_year}}-{{recurring_range_last_year}}';
|
||||
$dateranges = [
|
||||
(object) [
|
||||
'startdate' => strtotime('01.04.2017'),
|
||||
'enddate' => strtotime('30.09.2017'),
|
||||
'datestring' => $datestring,
|
||||
'recurring' => true,
|
||||
],
|
||||
(object)[
|
||||
'startdate' => strtotime('01.10.2017'),
|
||||
'enddate' => strtotime('31.03.2018'),
|
||||
'datestring' => $datestring,
|
||||
'recurring' => true,
|
||||
],
|
||||
];
|
||||
|
||||
$element = $this->get_datarange_element($dateranges);
|
||||
|
||||
$date = strtotime('1.05.2020');
|
||||
$this->assertEquals('2017-2017-2020-2020', $element->get_daterange_string($date));
|
||||
|
||||
$date = strtotime('1.05.2024');
|
||||
$this->assertEquals('2017-2017-2024-2024', $element->get_daterange_string($date));
|
||||
|
||||
$date = strtotime('1.02.2020');
|
||||
$this->assertEquals('2017-2018-2019-2020', $element->get_daterange_string($date));
|
||||
|
||||
$date = strtotime('1.02.2024');
|
||||
$this->assertEquals('2017-2018-2023-2024', $element->get_daterange_string($date));
|
||||
}
|
||||
|
||||
}
|
47
element/daterange/tests/fixtures/fake_datarange_element.php
vendored
Normal file
47
element/daterange/tests/fixtures/fake_datarange_element.php
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
<?php
|
||||
// This file is part of the customcert module for 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/>.
|
||||
|
||||
/**
|
||||
* Fake datarange element for testing.
|
||||
*
|
||||
* @package customcertelement_daterange
|
||||
* @copyright 2018 Dmitrii Metelkin <dmitriim@catalyst-au.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Fake datarange element for testing.
|
||||
*
|
||||
* @package customcertelement_daterange
|
||||
* @copyright 2018 Dmitrii Metelkin <dmitriim@catalyst-au.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class fake_datarange_element extends \customcertelement_daterange\element {
|
||||
|
||||
/**
|
||||
* Override protected method for testing.
|
||||
*
|
||||
* @param int $date
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_daterange_string($date) {
|
||||
$result = parent::get_daterange_string($date);
|
||||
return $result;
|
||||
}
|
||||
}
|
29
element/daterange/version.php
Normal file
29
element/daterange/version.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
// This file is part of the customcert module for 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/>.
|
||||
|
||||
/**
|
||||
* This file contains the version information for the date plugin.
|
||||
*
|
||||
* @package customcertelement_daterange
|
||||
* @copyright 2018 Dmitrii Metelkin <dmitriim@catalyst-au.net>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
|
||||
|
||||
$plugin->version = 2018051700; // The current module version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2018051700; // Requires this Moodle version (3.5).
|
||||
$plugin->component = 'customcertelement_daterange';
|
|
@ -60,7 +60,7 @@ class element extends \customcertelement_image\element {
|
|||
/**
|
||||
* This function renders the form elements when adding a customcert element.
|
||||
*
|
||||
* @param \mod_customcert\edit_element_form $mform the edit_form instance
|
||||
* @param \MoodleQuickForm $mform the edit_form instance
|
||||
*/
|
||||
public function render_form_elements($mform) {
|
||||
$mform->addElement('select', 'fileid', get_string('image', 'customcertelement_image'), self::get_images());
|
||||
|
@ -240,7 +240,7 @@ class element extends \customcertelement_image\element {
|
|||
/**
|
||||
* Sets the data on the form when editing an element.
|
||||
*
|
||||
* @param \mod_customcert\edit_element_form $mform the edit_form instance
|
||||
* @param \MoodleQuickForm $mform the edit_form instance
|
||||
*/
|
||||
public function definition_after_data($mform) {
|
||||
global $COURSE, $SITE;
|
||||
|
|
|
@ -43,7 +43,7 @@ class element extends \mod_customcert\element {
|
|||
/**
|
||||
* This function renders the form elements when adding a customcert element.
|
||||
*
|
||||
* @param \mod_customcert\edit_element_form $mform the edit_form instance
|
||||
* @param \MoodleQuickForm $mform the edit_form instance
|
||||
*/
|
||||
public function render_form_elements($mform) {
|
||||
global $COURSE;
|
||||
|
@ -107,7 +107,7 @@ class element extends \mod_customcert\element {
|
|||
// If we are previewing this certificate then just show a demonstration grade.
|
||||
if ($preview) {
|
||||
$courseitem = \grade_item::fetch_course_item($courseid);
|
||||
$grade = grade_format_gradevalue('100', $courseitem, true, $gradeinfo->gradeformat);
|
||||
$grade = grade_format_gradevalue('100', $courseitem, true, $gradeinfo->gradeformat);;
|
||||
} else {
|
||||
if ($gradeitem == CUSTOMCERT_GRADE_COURSE) {
|
||||
$grade = \mod_customcert\element_helper::get_course_grade_info(
|
||||
|
@ -167,7 +167,7 @@ class element extends \mod_customcert\element {
|
|||
/**
|
||||
* Sets the data on the form when editing an element.
|
||||
*
|
||||
* @param \mod_customcert\edit_element_form $mform the edit_form instance
|
||||
* @param \MoodleQuickForm $mform the edit_form instance
|
||||
*/
|
||||
public function definition_after_data($mform) {
|
||||
// Set the item and format for this element.
|
||||
|
|
|
@ -38,7 +38,7 @@ class element extends \mod_customcert\element {
|
|||
/**
|
||||
* This function renders the form elements when adding a customcert element.
|
||||
*
|
||||
* @param \mod_customcert\edit_element_form $mform the edit_form instance
|
||||
* @param \MoodleQuickForm $mform the edit_form instance
|
||||
*/
|
||||
public function render_form_elements($mform) {
|
||||
global $COURSE;
|
||||
|
@ -73,20 +73,9 @@ class element extends \mod_customcert\element {
|
|||
* @param \stdClass $user the user we are rendering this for
|
||||
*/
|
||||
public function render($pdf, $preview, $user) {
|
||||
global $DB;
|
||||
|
||||
// Check that the grade item is not empty.
|
||||
if (!empty($this->get_data())) {
|
||||
// Get the course module information.
|
||||
$cm = $DB->get_record('course_modules', array('id' => $this->get_data()), '*', MUST_EXIST);
|
||||
$module = $DB->get_record('modules', array('id' => $cm->module), '*', MUST_EXIST);
|
||||
|
||||
// Get the name of the item.
|
||||
$courseid = \mod_customcert\element_helper::get_courseid($this->get_data());
|
||||
$itemname = $DB->get_field($module->name, 'name', array('id' => $cm->instance), MUST_EXIST);
|
||||
$itemname = format_string($itemname, true, ['context' => \context_course::instance($courseid)]);
|
||||
|
||||
\mod_customcert\element_helper::render_content($pdf, $this, $itemname);
|
||||
\mod_customcert\element_helper::render_content($pdf, $this, $this->get_grade_item_name());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,20 +88,9 @@ class element extends \mod_customcert\element {
|
|||
* @return string the html
|
||||
*/
|
||||
public function render_html() {
|
||||
global $DB;
|
||||
|
||||
// Check that the grade item is not empty.
|
||||
if (!empty($this->get_data())) {
|
||||
// Get the course module information.
|
||||
$cm = $DB->get_record('course_modules', array('id' => $this->get_data()), '*', MUST_EXIST);
|
||||
$module = $DB->get_record('modules', array('id' => $cm->module), '*', MUST_EXIST);
|
||||
|
||||
// Get the name of the item.
|
||||
$courseid = \mod_customcert\element_helper::get_courseid($this->get_data());
|
||||
$itemname = $DB->get_field($module->name, 'name', array('id' => $cm->instance), MUST_EXIST);
|
||||
$itemname = format_string($itemname, true, ['context' => \context_course::instance($courseid)]);
|
||||
|
||||
return \mod_customcert\element_helper::render_html_content($this, $itemname);
|
||||
return \mod_customcert\element_helper::render_html_content($this, $this->get_grade_item_name());
|
||||
}
|
||||
|
||||
return '';
|
||||
|
@ -121,7 +99,7 @@ class element extends \mod_customcert\element {
|
|||
/**
|
||||
* Sets the data on the form when editing an element.
|
||||
*
|
||||
* @param \mod_customcert\edit_element_form $mform the edit_form instance
|
||||
* @param \MoodleQuickForm $mform the edit_form instance
|
||||
*/
|
||||
public function definition_after_data($mform) {
|
||||
if (!empty($this->get_data())) {
|
||||
|
@ -130,4 +108,42 @@ class element extends \mod_customcert\element {
|
|||
}
|
||||
parent::definition_after_data($mform);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that returns the grade item name.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_grade_item_name() : string {
|
||||
global $DB;
|
||||
|
||||
$gradeitem = $this->get_data();
|
||||
|
||||
if (strpos($gradeitem, 'gradeitem:') === 0) {
|
||||
$gradeitemid = substr($gradeitem, 10);
|
||||
$gradeitem = \grade_item::fetch(['id' => $gradeitemid]);
|
||||
|
||||
return $gradeitem->get_name();
|
||||
} else {
|
||||
if (!$cm = $DB->get_record('course_modules', array('id' => $gradeitem))) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (!$module = $DB->get_record('modules', array('id' => $cm->module))) {
|
||||
return '';
|
||||
}
|
||||
|
||||
$params = [
|
||||
'itemtype' => 'mod',
|
||||
'itemmodule' => $module->name,
|
||||
'iteminstance' => $cm->instance,
|
||||
'courseid' => $cm->course,
|
||||
'itemnumber' => 0
|
||||
];
|
||||
|
||||
$gradeitem = \grade_item::fetch($params);
|
||||
|
||||
return $gradeitem->get_name();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ class element extends \mod_customcert\element {
|
|||
/**
|
||||
* This function renders the form elements when adding a customcert element.
|
||||
*
|
||||
* @param \mod_customcert\edit_element_form $mform the edit_form instance
|
||||
* @param \MoodleQuickForm $mform the edit_form instance
|
||||
*/
|
||||
public function render_form_elements($mform) {
|
||||
$mform->addElement('select', 'fileid', get_string('image', 'customcertelement_image'), self::get_images());
|
||||
|
@ -282,7 +282,7 @@ class element extends \mod_customcert\element {
|
|||
/**
|
||||
* Sets the data on the form when editing an element.
|
||||
*
|
||||
* @param \mod_customcert\edit_element_form $mform the edit_form instance
|
||||
* @param \MoodleQuickForm $mform the edit_form instance
|
||||
*/
|
||||
public function definition_after_data($mform) {
|
||||
global $COURSE, $SITE;
|
||||
|
@ -382,14 +382,14 @@ class element extends \mod_customcert\element {
|
|||
// Loop through the files uploaded in the system context.
|
||||
if ($files = $fs->get_area_files(\context_system::instance()->id, 'mod_customcert', 'image', false, 'filename', false)) {
|
||||
foreach ($files as $hash => $file) {
|
||||
$arrfiles[$file->get_id()] = $file->get_filename();
|
||||
$arrfiles[$file->get_id()] = get_string('systemimage', 'customcertelement_image', $file->get_filename());
|
||||
}
|
||||
}
|
||||
// Loop through the files uploaded in the course context.
|
||||
if ($files = $fs->get_area_files(\context_course::instance($COURSE->id)->id, 'mod_customcert', 'image', false,
|
||||
'filename', false)) {
|
||||
foreach ($files as $hash => $file) {
|
||||
$arrfiles[$file->get_id()] = $file->get_filename();
|
||||
$arrfiles[$file->get_id()] = get_string('courseimage', 'customcertelement_image', $file->get_filename());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -398,4 +398,60 @@ class element extends \mod_customcert\element {
|
|||
|
||||
return $arrfiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* This handles copying data from another element of the same type.
|
||||
*
|
||||
* @param \stdClass $data the form data
|
||||
* @return bool returns true if the data was copied successfully, false otherwise
|
||||
*/
|
||||
public function copy_element($data) {
|
||||
global $COURSE, $DB, $SITE;
|
||||
|
||||
$imagedata = json_decode($data->data);
|
||||
|
||||
// If we are in the site context we don't have to do anything, the image is already there.
|
||||
if ($COURSE->id == $SITE->id) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$coursecontext = \context_course::instance($COURSE->id);
|
||||
$systemcontext = \context_system::instance();
|
||||
|
||||
$fs = get_file_storage();
|
||||
|
||||
// Check that a file has been selected.
|
||||
if (isset($imagedata->filearea)) {
|
||||
// If the course file doesn't exist, copy the system file to the course context.
|
||||
if (!$coursefile = $fs->get_file(
|
||||
$coursecontext->id,
|
||||
'mod_customcert',
|
||||
$imagedata->filearea,
|
||||
$imagedata->itemid,
|
||||
$imagedata->filepath,
|
||||
$imagedata->filename
|
||||
)) {
|
||||
$systemfile = $fs->get_file(
|
||||
$systemcontext->id,
|
||||
'mod_customcert',
|
||||
$imagedata->filearea,
|
||||
$imagedata->itemid,
|
||||
$imagedata->filepath,
|
||||
$imagedata->filename
|
||||
);
|
||||
|
||||
// We want to update the context of the file if it doesn't exist in the course context.
|
||||
$fieldupdates = [
|
||||
'contextid' => $coursecontext->id
|
||||
];
|
||||
$coursefile = $fs->create_file_from_storedfile($fieldupdates, $systemfile);
|
||||
}
|
||||
|
||||
// Set the image to the copied file in the course.
|
||||
$imagedata->fileid = $coursefile->get_id();
|
||||
$DB->set_field('customcert_elements', 'data', $this->save_unique_data($imagedata), ['id' => $this->get_id()]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
|
||||
$string['alphachannel'] = 'Alpha channel';
|
||||
$string['alphachannel_help'] = 'This value determines how transparent the image is. You can set the alpha channel from 0 (fully transparent) to 1 (fully opaque).';
|
||||
$string['courseimage'] = 'Course image: {$a}';
|
||||
$string['height'] = 'Height';
|
||||
$string['height_help'] = 'Height of the image in mm. If equal to zero, it is automatically calculated.';
|
||||
$string['image'] = 'Image';
|
||||
|
@ -31,5 +32,6 @@ $string['invalidheight'] = 'The height has to be a valid number greater than or
|
|||
$string['invalidwidth'] = 'The width has to be a valid number greater than or equal to 0.';
|
||||
$string['pluginname'] = 'Image';
|
||||
$string['privacy:metadata'] = 'The Image plugin does not store any personal data.';
|
||||
$string['systemimage'] = 'Site image: {$a}';
|
||||
$string['width'] = 'Width';
|
||||
$string['width_help'] = 'Width of the image in mm. If equal to zero, it is automatically calculated.';
|
||||
|
|
208
element/qrcode/classes/element.php
Normal file
208
element/qrcode/classes/element.php
Normal file
|
@ -0,0 +1,208 @@
|
|||
<?php
|
||||
// This file is part of the customcert module for 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/>.
|
||||
|
||||
/**
|
||||
* This file contains the customcert element QR code's core interaction API.
|
||||
*
|
||||
* @package customcertelement_qrcode
|
||||
* @copyright 2019 Mark Nelson <markn@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace customcertelement_qrcode;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->libdir . '/tcpdf/tcpdf_barcodes_2d.php');
|
||||
|
||||
/**
|
||||
* The customcert element QR code's core interaction API.
|
||||
*
|
||||
* @package customcertelement_qrcode
|
||||
* @copyright 2019 Mark Nelson <markn@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class element extends \mod_customcert\element {
|
||||
|
||||
/**
|
||||
* @var string The barcode type.
|
||||
*/
|
||||
const BARCODETYPE = 'QRCODE';
|
||||
|
||||
/**
|
||||
* This function renders the form elements when adding a customcert element.
|
||||
*
|
||||
* @param \MoodleQuickForm $mform the edit_form instance
|
||||
*/
|
||||
public function render_form_elements($mform) {
|
||||
\mod_customcert\element_helper::render_form_element_width($mform);
|
||||
|
||||
$mform->addElement('text', 'height', get_string('height', 'customcertelement_qrcode'), array('size' => 10));
|
||||
$mform->setType('height', PARAM_INT);
|
||||
$mform->setDefault('height', 0);
|
||||
$mform->addHelpButton('height', 'height', 'customcertelement_qrcode');
|
||||
|
||||
if ($this->showposxy) {
|
||||
\mod_customcert\element_helper::render_form_element_position($mform);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs validation on the element values.
|
||||
*
|
||||
* @param array $data the submitted data
|
||||
* @param array $files the submitted files
|
||||
* @return array the validation errors
|
||||
*/
|
||||
public function validate_form_elements($data, $files) {
|
||||
// Array to return the errors.
|
||||
$errors = [];
|
||||
|
||||
// Check if height is not set, or not numeric or less than 0.
|
||||
if ((!isset($data['height'])) || (!is_numeric($data['height'])) || ($data['height'] <= 0)) {
|
||||
$errors['height'] = get_string('invalidheight', 'mod_customcert');
|
||||
}
|
||||
|
||||
if ((!isset($data['width'])) || (!is_numeric($data['width'])) || ($data['width'] <= 0)) {
|
||||
$errors['width'] = get_string('invalidwidth', 'mod_customcert');
|
||||
}
|
||||
|
||||
if ($this->showposxy) {
|
||||
$errors += \mod_customcert\element_helper::validate_form_element_position($data);
|
||||
}
|
||||
|
||||
$errors += \mod_customcert\element_helper::validate_form_element_width($data);
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
/**
|
||||
* This will handle how form data will be saved into the data column in the
|
||||
* customcert_elements table.
|
||||
*
|
||||
* @param \stdClass $data the form data
|
||||
* @return string the json encoded array
|
||||
*/
|
||||
public function save_unique_data($data) {
|
||||
$arrtostore = [
|
||||
'width' => !empty($data->width) ? (int)$data->width : 0,
|
||||
'height' => !empty($data->height) ? (int)$data->height : 0
|
||||
];
|
||||
|
||||
return json_encode($arrtostore);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the data on the form when editing an element.
|
||||
*
|
||||
* @param \MoodleQuickForm $mform the edit_form instance
|
||||
*/
|
||||
public function definition_after_data($mform) {
|
||||
parent::definition_after_data($mform);
|
||||
|
||||
// Set the image, width, height and alpha channel for this element.
|
||||
if (!empty($this->get_data())) {
|
||||
$imageinfo = json_decode($this->get_data());
|
||||
|
||||
if (!empty($imageinfo->height)) {
|
||||
$element = $mform->getElement('height');
|
||||
$element->setValue($imageinfo->height);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles rendering the element on the pdf.
|
||||
*
|
||||
* @param \pdf $pdf the pdf object
|
||||
* @param bool $preview true if it is a preview, false otherwise
|
||||
* @param \stdClass $user the user we are rendering this for
|
||||
*/
|
||||
public function render($pdf, $preview, $user) {
|
||||
global $DB;
|
||||
|
||||
// If there is no element data, we have nothing to display.
|
||||
if (empty($this->get_data())) {
|
||||
return;
|
||||
}
|
||||
|
||||
$imageinfo = json_decode($this->get_data());
|
||||
|
||||
if ($preview) {
|
||||
// Generate the URL to verify this.
|
||||
$qrcodeurl = new \moodle_url('/');
|
||||
$qrcodeurl = $qrcodeurl->out(false);
|
||||
} else {
|
||||
// Get the information we need.
|
||||
$sql = "SELECT c.id, ct.contextid, ci.code
|
||||
FROM {customcert_issues} ci
|
||||
JOIN {customcert} c
|
||||
ON ci.customcertid = c.id
|
||||
JOIN {customcert_templates} ct
|
||||
ON c.templateid = ct.id
|
||||
JOIN {customcert_pages} cp
|
||||
ON cp.templateid = ct.id
|
||||
WHERE ci.userid = :userid
|
||||
AND cp.id = :pageid";
|
||||
|
||||
// Now we can get the issue for this user.
|
||||
$issue = $DB->get_record_sql($sql, array('userid' => $user->id, 'pageid' => $this->get_pageid()),
|
||||
'*', MUST_EXIST);
|
||||
$code = $issue->code;
|
||||
|
||||
// Generate the URL to verify this.
|
||||
$qrcodeurl = new \moodle_url('/mod/customcert/verify_certificate.php',
|
||||
[
|
||||
'contextid' => $issue->contextid,
|
||||
'code' => $code,
|
||||
'qrcode' => 1
|
||||
]
|
||||
);
|
||||
$qrcodeurl = $qrcodeurl->out(false);
|
||||
}
|
||||
|
||||
$barcode = new \TCPDF2DBarcode($qrcodeurl, self::BARCODETYPE);
|
||||
$image = $barcode->getBarcodePngData($imageinfo->width, $imageinfo->height);
|
||||
|
||||
$location = make_request_directory() . '/target';
|
||||
file_put_contents($location, $image);
|
||||
|
||||
$pdf->Image($location, $this->get_posx(), $this->get_posy(), $imageinfo->width, $imageinfo->height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the element in html.
|
||||
*
|
||||
* This function is used to render the element when we are using the
|
||||
* drag and drop interface to position it.
|
||||
*
|
||||
* @return string the html
|
||||
*/
|
||||
public function render_html() {
|
||||
// If there is no element data, we have nothing to display.
|
||||
if (empty($this->get_data())) {
|
||||
return;
|
||||
}
|
||||
|
||||
$imageinfo = json_decode($this->get_data());
|
||||
|
||||
$qrcodeurl = new \moodle_url('/');
|
||||
$qrcodeurl = $qrcodeurl->out(false);
|
||||
|
||||
$barcode = new \TCPDF2DBarcode($qrcodeurl, self::BARCODETYPE);
|
||||
return $barcode->getBarcodeHTML($imageinfo->width / 10, $imageinfo->height / 10);
|
||||
}
|
||||
}
|
46
element/qrcode/classes/privacy/provider.php
Normal file
46
element/qrcode/classes/privacy/provider.php
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?php
|
||||
// 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/>.
|
||||
|
||||
/**
|
||||
* Privacy Subsystem implementation for customcertelement_qrcode.
|
||||
*
|
||||
* @package customcertelement_qrcode
|
||||
* @copyright 2019 Mark Nelson <markn@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
namespace customcertelement_qrcode\privacy;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
/**
|
||||
* Privacy Subsystem for customcertelement_qrcode implementing null_provider.
|
||||
*
|
||||
* @copyright 2019 Mark Nelson <markn@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class provider implements \core_privacy\local\metadata\null_provider {
|
||||
|
||||
/**
|
||||
* Get the language string identifier with the component's language
|
||||
* file to explain why this plugin stores no data.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function get_reason() : string {
|
||||
return 'privacy:metadata';
|
||||
}
|
||||
}
|
30
element/qrcode/lang/en/customcertelement_qrcode.php
Normal file
30
element/qrcode/lang/en/customcertelement_qrcode.php
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
// This file is part of the customcert module for 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/>.
|
||||
|
||||
/**
|
||||
* Strings for component 'customcertelement_qrcode', language 'en'.
|
||||
*
|
||||
* @package customcertelement_qrcode
|
||||
* @copyright 2019 Mark Nelson <markn@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
$string['height'] = 'Height';
|
||||
$string['height_help'] = 'Height help';
|
||||
$string['pluginname'] = 'QR code';
|
||||
$string['privacy:metadata'] = 'The QR code plugin does not store any personal data.';
|
||||
$string['width'] = 'Width';
|
||||
$string['width_help'] = 'width help';
|
29
element/qrcode/version.php
Normal file
29
element/qrcode/version.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?php
|
||||
// This file is part of the customcert module for 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/>.
|
||||
|
||||
/**
|
||||
* This file contains the version information for the QR code plugin.
|
||||
*
|
||||
* @package customcertelement_qrcode
|
||||
* @copyright 2019 Mark Nelson <markn@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
|
||||
|
||||
$plugin->version = 2018051700; // The current module version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2018051700; // Requires this Moodle version (3.5).
|
||||
$plugin->component = 'customcertelement_qrcode';
|
|
@ -38,7 +38,7 @@ class element extends \mod_customcert\element {
|
|||
/**
|
||||
* This function renders the form elements when adding a customcert element.
|
||||
*
|
||||
* @param \mod_customcert\edit_element_form $mform the edit_form instance
|
||||
* @param \MoodleQuickForm $mform the edit_form instance
|
||||
*/
|
||||
public function render_form_elements($mform) {
|
||||
$mform->addElement('select', 'teacher', get_string('teacher', 'customcertelement_teachername'),
|
||||
|
@ -102,6 +102,11 @@ class element extends \mod_customcert\element {
|
|||
protected function get_list_of_teachers() {
|
||||
global $PAGE;
|
||||
|
||||
// Return early if we are in a site template.
|
||||
if ($PAGE->context->id == \context_system::instance()->id) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// The list of teachers to return.
|
||||
$teachers = array();
|
||||
|
||||
|
@ -118,7 +123,7 @@ class element extends \mod_customcert\element {
|
|||
/**
|
||||
* Sets the data on the form when editing an element.
|
||||
*
|
||||
* @param \mod_customcert\edit_element_form $mform the edit_form instance
|
||||
* @param \MoodleQuickForm $mform the edit_form instance
|
||||
*/
|
||||
public function definition_after_data($mform) {
|
||||
if (!empty($this->get_data())) {
|
||||
|
|
|
@ -38,7 +38,7 @@ class element extends \mod_customcert\element {
|
|||
/**
|
||||
* This function renders the form elements when adding a customcert element.
|
||||
*
|
||||
* @param \mod_customcert\edit_element_form $mform the edit_form instance
|
||||
* @param \MoodleQuickForm $mform the edit_form instance
|
||||
*/
|
||||
public function render_form_elements($mform) {
|
||||
$mform->addElement('textarea', 'text', get_string('text', 'customcertelement_text'));
|
||||
|
@ -67,9 +67,7 @@ class element extends \mod_customcert\element {
|
|||
* @param \stdClass $user the user we are rendering this for
|
||||
*/
|
||||
public function render($pdf, $preview, $user) {
|
||||
$courseid = \mod_customcert\element_helper::get_courseid($this->get_id());
|
||||
$text = format_text($this->get_data(), FORMAT_HTML, ['context' => \context_course::instance($courseid)]);
|
||||
\mod_customcert\element_helper::render_content($pdf, $this, $text);
|
||||
\mod_customcert\element_helper::render_content($pdf, $this, $this->get_text());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -81,15 +79,13 @@ class element extends \mod_customcert\element {
|
|||
* @return string the html
|
||||
*/
|
||||
public function render_html() {
|
||||
$courseid = \mod_customcert\element_helper::get_courseid($this->get_id());
|
||||
$text = format_text($this->get_data(), FORMAT_HTML, ['context' => \context_course::instance($courseid)]);
|
||||
return \mod_customcert\element_helper::render_html_content($this, $text);
|
||||
return \mod_customcert\element_helper::render_html_content($this, $this->get_text());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the data on the form when editing an element.
|
||||
*
|
||||
* @param \mod_customcert\edit_element_form $mform the edit_form instance
|
||||
* @param \MoodleQuickForm $mform the edit_form instance
|
||||
*/
|
||||
public function definition_after_data($mform) {
|
||||
if (!empty($this->get_data())) {
|
||||
|
@ -98,4 +94,14 @@ class element extends \mod_customcert\element {
|
|||
}
|
||||
parent::definition_after_data($mform);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that returns the text.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function get_text() : string {
|
||||
$context = \mod_customcert\element_helper::get_context($this->get_id());
|
||||
return format_text($this->get_data(), FORMAT_HTML, ['context' => $context]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,13 +38,14 @@ class element extends \mod_customcert\element {
|
|||
/**
|
||||
* This function renders the form elements when adding a customcert element.
|
||||
*
|
||||
* @param \mod_customcert\edit_element_form $mform the edit_form instance
|
||||
* @param \MoodleQuickForm $mform the edit_form instance
|
||||
*/
|
||||
public function render_form_elements($mform) {
|
||||
// Get the user profile fields.
|
||||
$userfields = array(
|
||||
'firstname' => get_user_field_name('firstname'),
|
||||
'lastname' => get_user_field_name('lastname'),
|
||||
'username' => get_user_field_name('username'),
|
||||
'email' => get_user_field_name('email'),
|
||||
'city' => get_user_field_name('city'),
|
||||
'country' => get_user_field_name('country'),
|
||||
|
@ -65,7 +66,7 @@ class element extends \mod_customcert\element {
|
|||
$arrcustomfields = \availability_profile\condition::get_custom_profile_fields();
|
||||
$customfields = array();
|
||||
foreach ($arrcustomfields as $key => $customfield) {
|
||||
$customfields[$customfield->id] = $key;
|
||||
$customfields[$customfield->id] = $customfield->name;
|
||||
}
|
||||
// Combine the two.
|
||||
$fields = $userfields + $customfields;
|
||||
|
@ -98,14 +99,56 @@ class element extends \mod_customcert\element {
|
|||
* @param \stdClass $user the user we are rendering this for
|
||||
*/
|
||||
public function render($pdf, $preview, $user) {
|
||||
\mod_customcert\element_helper::render_content($pdf, $this, $this->get_user_field_value($user, $preview));
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the element in html.
|
||||
*
|
||||
* This function is used to render the element when we are using the
|
||||
* drag and drop interface to position it.
|
||||
*/
|
||||
public function render_html() {
|
||||
global $USER;
|
||||
|
||||
return \mod_customcert\element_helper::render_html_content($this, $this->get_user_field_value($USER, true));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the data on the form when editing an element.
|
||||
*
|
||||
* @param \MoodleQuickForm $mform the edit_form instance
|
||||
*/
|
||||
public function definition_after_data($mform) {
|
||||
if (!empty($this->get_data())) {
|
||||
$element = $mform->getElement('userfield');
|
||||
$element->setValue($this->get_data());
|
||||
}
|
||||
parent::definition_after_data($mform);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function that returns the text.
|
||||
*
|
||||
* @param \stdClass $user the user we are rendering this for
|
||||
* @param bool $preview Is this a preview?
|
||||
* @return string
|
||||
*/
|
||||
protected function get_user_field_value(\stdClass $user, bool $preview) : string {
|
||||
global $CFG, $DB;
|
||||
|
||||
// The user field to display.
|
||||
$field = $this->get_data();
|
||||
// The value to display on the PDF.
|
||||
$value = '';
|
||||
// The value to display - we always want to show a value here so it can be repositioned.
|
||||
if ($preview) {
|
||||
$value = $field;
|
||||
} else {
|
||||
$value = '';
|
||||
}
|
||||
if (is_number($field)) { // Must be a custom user profile field.
|
||||
if ($field = $DB->get_record('user_info_field', array('id' => $field))) {
|
||||
// Found the field name, let's update the value to display.
|
||||
$value = $field->name;
|
||||
$file = $CFG->dirroot . '/user/profile/field/' . $field->datatype . '/field.class.php';
|
||||
if (file_exists($file)) {
|
||||
require_once($CFG->dirroot . '/user/profile/lib.php');
|
||||
|
@ -119,59 +162,7 @@ class element extends \mod_customcert\element {
|
|||
$value = $user->$field;
|
||||
}
|
||||
|
||||
$courseid = \mod_customcert\element_helper::get_courseid($this->get_id());
|
||||
$value = format_string($value, true, ['context' => \context_course::instance($courseid)]);
|
||||
\mod_customcert\element_helper::render_content($pdf, $this, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the element in html.
|
||||
*
|
||||
* This function is used to render the element when we are using the
|
||||
* drag and drop interface to position it.
|
||||
*/
|
||||
public function render_html() {
|
||||
global $CFG, $DB, $USER;
|
||||
|
||||
// The user field to display.
|
||||
$field = $this->get_data();
|
||||
// The value to display - we always want to show a value here so it can be repositioned.
|
||||
$value = $field;
|
||||
if (is_number($field)) { // Must be a custom user profile field.
|
||||
if ($field = $DB->get_record('user_info_field', array('id' => $field))) {
|
||||
// Found the field name, let's update the value to display.
|
||||
$value = $field->name;
|
||||
$file = $CFG->dirroot . '/user/profile/field/' . $field->datatype . '/field.class.php';
|
||||
if (file_exists($file)) {
|
||||
require_once($CFG->dirroot . '/user/profile/lib.php');
|
||||
require_once($file);
|
||||
$class = "profile_field_{$field->datatype}";
|
||||
$field = new $class($field->id, $USER->id);
|
||||
if ($fieldvalue = $field->display_data()) {
|
||||
// Ok, found a value for the user, let's show that instead.
|
||||
$value = $fieldvalue;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (!empty($USER->$field)) { // Field in the user table.
|
||||
$value = $USER->$field;
|
||||
}
|
||||
|
||||
$courseid = \mod_customcert\element_helper::get_courseid($this->get_id());
|
||||
$value = format_string($value, true, ['context' => \context_course::instance($courseid)]);
|
||||
return \mod_customcert\element_helper::render_html_content($this, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the data on the form when editing an element.
|
||||
*
|
||||
* @param \mod_customcert\edit_element_form $mform the edit_form instance
|
||||
*/
|
||||
public function definition_after_data($mform) {
|
||||
if (!empty($this->get_data())) {
|
||||
$element = $mform->getElement('userfield');
|
||||
$element->setValue($this->get_data());
|
||||
}
|
||||
parent::definition_after_data($mform);
|
||||
$context = \mod_customcert\element_helper::get_context($this->get_id());
|
||||
return format_string($value, true, ['context' => $context]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ class element extends \mod_customcert\element {
|
|||
/**
|
||||
* This function renders the form elements when adding a customcert element.
|
||||
*
|
||||
* @param \mod_customcert\edit_element_form $mform the edit_form instance
|
||||
* @param \MoodleQuickForm $mform the edit_form instance
|
||||
*/
|
||||
public function render_form_elements($mform) {
|
||||
$mform->addElement('text', 'width', get_string('width', 'customcertelement_userpicture'), array('size' => 10));
|
||||
|
@ -190,7 +190,7 @@ class element extends \mod_customcert\element {
|
|||
/**
|
||||
* Sets the data on the form when editing an element.
|
||||
*
|
||||
* @param \mod_customcert\edit_element_form $mform the edit_form instance
|
||||
* @param \MoodleQuickForm $mform the edit_form instance
|
||||
*/
|
||||
public function definition_after_data($mform) {
|
||||
// Set the image, width and height for this element.
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
$string['activity'] = 'Activity';
|
||||
$string['addcertpage'] = 'Add page';
|
||||
$string['addelement'] = 'Add element';
|
||||
$string['awardedto'] = 'Awarded to';
|
||||
|
@ -41,6 +42,7 @@ $string['customcert:manageemailothers'] = 'Manage email others setting';
|
|||
$string['customcert:manageverifyany'] = 'Manage verification setting';
|
||||
$string['customcert:managerequiredtime'] = 'Manage time required setting';
|
||||
$string['customcert:manageprotection'] = 'Manage protection setting';
|
||||
$string['customcert:receiveissue'] = 'Receive a certificate';
|
||||
$string['customcert:view'] = 'View a custom certificate';
|
||||
$string['customcert:viewreport'] = 'View course report';
|
||||
$string['customcert:viewallcertificates'] = 'View all certificates';
|
||||
|
@ -82,11 +84,12 @@ $string['emailstudentcertificatelinktext'] = 'View certificate';
|
|||
$string['emailstudentgreeting'] = 'Dear {$a}';
|
||||
$string['emailstudentsubject'] = '{$a->coursefullname}: {$a->certificatename}';
|
||||
$string['emailstudents'] = 'Email students';
|
||||
$string['emailstudents_help'] = 'If set this will email the students a copy of the certificate when it becomes available.';
|
||||
$string['emailstudents_help'] = 'If set this will email the students a copy of the certificate when it becomes available. <strong>Warning:</strong> Setting this to \'Yes\' before you have finished creating the certificate will email the student an incomplete certificate.';
|
||||
$string['emailteachers'] = 'Email teachers';
|
||||
$string['emailteachers_help'] = 'If set this will email the teachers a copy of the certificate when it becomes available.';
|
||||
$string['emailteachers_help'] = 'If set this will email the teachers a copy of the certificate when it becomes available. <strong>Warning:</strong> Setting this to \'Yes\' before you have finished creating the certificate will email the teacher an incomplete certificate.';
|
||||
$string['emailothers'] = 'Email others';
|
||||
$string['emailothers_help'] = 'If set this will email the email addresses listed here (separated by a comma) with a copy of the certificate when it becomes available.';
|
||||
$string['emailothers_help'] = 'If set this will email the email addresses listed here (separated by a comma) with a copy of the certificate when it becomes available. <strong>Warning:</strong> Setting this field before you have finished creating the certificate will email the addresses an incomplete certificate.';
|
||||
$string['exampledatawarning'] = 'Some of these values may just be an example to ensure positioning of the elements is possible.';
|
||||
$string['font'] = 'Font';
|
||||
$string['font_help'] = 'The font used when generating this element.';
|
||||
$string['fontcolour'] = 'Colour';
|
||||
|
@ -94,6 +97,7 @@ $string['fontcolour_help'] = 'The colour of the font.';
|
|||
$string['fontsize'] = 'Size';
|
||||
$string['fontsize_help'] = 'The size of the font in points.';
|
||||
$string['getcustomcert'] = 'View certificate';
|
||||
$string['gradeoutcome'] = 'Outcome';
|
||||
$string['height'] = 'Height';
|
||||
$string['height_help'] = 'This is the height of the certificate PDF in mm. For reference an A4 piece of paper is 297mm high and a letter is 279mm high.';
|
||||
$string['invalidcode'] = 'Invalid code supplied.';
|
||||
|
@ -106,7 +110,7 @@ $string['invalidwidth'] = 'The width has to be a valid number greater than 0.';
|
|||
$string['landscape'] = 'Landscape';
|
||||
$string['leftmargin'] = 'Left margin';
|
||||
$string['leftmargin_help'] = 'This is the left margin of the certificate PDF in mm.';
|
||||
$string['listofissues'] = 'Recipients';
|
||||
$string['listofissues'] = 'Recipients: {$a}';
|
||||
$string['load'] = 'Load';
|
||||
$string['loadtemplate'] = 'Load template';
|
||||
$string['loadtemplatemsg'] = 'Are you sure you wish to load this template? This will remove any existing pages and elements for this certificate.';
|
||||
|
|
|
@ -34,6 +34,7 @@ define('NO_MOODLE_COOKIES', true);
|
|||
|
||||
require_once('../../../config.php');
|
||||
require_once($CFG->libdir . '/filelib.php');
|
||||
require_once($CFG->libdir . '/completionlib.php');
|
||||
require_once($CFG->dirroot . '/webservice/lib.php');
|
||||
|
||||
// Allow CORS requests.
|
||||
|
@ -54,6 +55,7 @@ if (empty($enabledfiledownload)) {
|
|||
}
|
||||
|
||||
$cm = get_coursemodule_from_instance('customcert', $certificateid, 0, false, MUST_EXIST);
|
||||
$course = $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST);
|
||||
$certificate = $DB->get_record('customcert', ['id' => $certificateid], '*', MUST_EXIST);
|
||||
$template = $DB->get_record('customcert_templates', ['id' => $certificate->templateid], '*', MUST_EXIST);
|
||||
|
||||
|
@ -80,6 +82,10 @@ if (!$issue) {
|
|||
}
|
||||
|
||||
\mod_customcert\certificate::issue_certificate($certificate->id, $USER->id);
|
||||
|
||||
// Set the custom certificate as viewed.
|
||||
$completion = new completion_info($course);
|
||||
$completion->set_module_viewed($cm);
|
||||
}
|
||||
|
||||
// Now we want to generate the PDF.
|
||||
|
|
|
@ -30,6 +30,11 @@ $downloadcert = optional_param('downloadcert', '', PARAM_BOOL);
|
|||
if ($downloadcert) {
|
||||
$certificateid = required_param('certificateid', PARAM_INT);
|
||||
$customcert = $DB->get_record('customcert', array('id' => $certificateid), '*', MUST_EXIST);
|
||||
|
||||
// Check there exists an issued certificate for this user.
|
||||
if (!$issue = $DB->get_record('customcert_issues', ['userid' => $userid, 'customcertid' => $customcert->id])) {
|
||||
throw new moodle_exception('You have not been issued a certificate');
|
||||
}
|
||||
}
|
||||
$page = optional_param('page', 0, PARAM_INT);
|
||||
$perpage = optional_param('perpage', \mod_customcert\certificate::CUSTOMCERT_PER_PAGE, PARAM_INT);
|
||||
|
|
|
@ -125,7 +125,8 @@ $html .= html_writer::end_tag('div');
|
|||
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading($heading);
|
||||
echo $OUTPUT->heading(get_string('rearrangeelementsheading', 'customcert'), 4);
|
||||
echo $OUTPUT->heading(get_string('rearrangeelementsheading', 'customcert'), 3);
|
||||
echo $OUTPUT->notification(get_string('exampledatawarning', 'customcert'), \core\output\notification::NOTIFY_WARNING);
|
||||
echo $html;
|
||||
$PAGE->requires->js_call_amd('mod_customcert/rearrange-area', 'init', array('#pdf'));
|
||||
echo $OUTPUT->footer();
|
||||
|
|
|
@ -119,6 +119,42 @@ Feature: Being able to manage elements in a certificate template
|
|||
| Width | 20 |
|
||||
| Reference point location | Top left |
|
||||
And I press "Save changes"
|
||||
# Date range.
|
||||
And I add the element "Date range" to page "1" of the "Custom certificate 1" certificate template
|
||||
And I set the following fields to these values:
|
||||
| Date item | Course start date |
|
||||
| Font | Helvetica |
|
||||
| Size | 20 |
|
||||
| Colour | #045ECD |
|
||||
| Width | 20 |
|
||||
| Reference point location | Top left |
|
||||
| Fallback string | {{range_first_year}} |
|
||||
| id_startdate_0_day | 24 |
|
||||
| id_startdate_0_month | October |
|
||||
| id_startdate_0_year | 2015 |
|
||||
| id_enddate_0_day | 21 |
|
||||
| id_enddate_0_month | March |
|
||||
| id_enddate_0_year | 2016 |
|
||||
| String | Oct to March |
|
||||
And I press "Save changes"
|
||||
And I should see "Date range" in the "elementstable" "table"
|
||||
And I click on ".edit-icon" "css_element" in the "Date range" "table_row"
|
||||
And the following fields match these values:
|
||||
| Date item | Course start date |
|
||||
| Font | Helvetica |
|
||||
| Size | 20 |
|
||||
| Colour | #045ECD |
|
||||
| Width | 20 |
|
||||
| Reference point location | Top left |
|
||||
| Fallback string | {{range_first_year}} |
|
||||
| id_startdate_0_day | 24 |
|
||||
| id_startdate_0_month | October |
|
||||
| id_startdate_0_year | 2015 |
|
||||
| id_enddate_0_day | 21 |
|
||||
| id_enddate_0_month | March |
|
||||
| id_enddate_0_year | 2016 |
|
||||
| String | Oct to March |
|
||||
And I press "Save changes"
|
||||
# Digital signature.
|
||||
And I add the element "Digital signature" to page "1" of the "Custom certificate 1" certificate template
|
||||
And I set the following fields to these values:
|
||||
|
@ -144,44 +180,44 @@ Feature: Being able to manage elements in a certificate template
|
|||
# Grade.
|
||||
And I add the element "Grade" to page "1" of the "Custom certificate 1" certificate template
|
||||
And I set the following fields to these values:
|
||||
| Grade item | Topic 0 : Assignment 1 |
|
||||
| Grade format | Percentage |
|
||||
| Font | Helvetica |
|
||||
| Size | 20 |
|
||||
| Colour | #045ECD |
|
||||
| Width | 20 |
|
||||
| Reference point location | Top left |
|
||||
| Grade item | Activity : Assignment 1 |
|
||||
| Grade format | Percentage |
|
||||
| Font | Helvetica |
|
||||
| Size | 20 |
|
||||
| Colour | #045ECD |
|
||||
| Width | 20 |
|
||||
| Reference point location | Top left |
|
||||
And I press "Save changes"
|
||||
And I should see "Grade" in the "elementstable" "table"
|
||||
And I click on ".edit-icon" "css_element" in the "Grade" "table_row"
|
||||
And the following fields match these values:
|
||||
| Grade item | Topic 0 : Assignment 1 |
|
||||
| Grade format | Percentage |
|
||||
| Font | Helvetica |
|
||||
| Size | 20 |
|
||||
| Colour | #045ECD |
|
||||
| Width | 20 |
|
||||
| Reference point location | Top left |
|
||||
| Grade item | Activity : Assignment 1 |
|
||||
| Grade format | Percentage |
|
||||
| Font | Helvetica |
|
||||
| Size | 20 |
|
||||
| Colour | #045ECD |
|
||||
| Width | 20 |
|
||||
| Reference point location | Top left |
|
||||
And I press "Save changes"
|
||||
# Grade item name.
|
||||
And I add the element "Grade item name" to page "1" of the "Custom certificate 1" certificate template
|
||||
And I set the following fields to these values:
|
||||
| Grade item | Topic 0 : Assignment 2 |
|
||||
| Font | Helvetica |
|
||||
| Size | 20 |
|
||||
| Colour | #045ECD |
|
||||
| Width | 20 |
|
||||
| Reference point location | Top left |
|
||||
| Grade item | Activity : Assignment 2 |
|
||||
| Font | Helvetica |
|
||||
| Size | 20 |
|
||||
| Colour | #045ECD |
|
||||
| Width | 20 |
|
||||
| Reference point location | Top left |
|
||||
And I press "Save changes"
|
||||
And I should see "Grade item name" in the "elementstable" "table"
|
||||
And I click on ".edit-icon" "css_element" in the "Grade item name" "table_row"
|
||||
And the following fields match these values:
|
||||
| Grade item | Topic 0 : Assignment 2 |
|
||||
| Font | Helvetica |
|
||||
| Size | 20 |
|
||||
| Colour | #045ECD |
|
||||
| Width | 20 |
|
||||
| Reference point location | Top left |
|
||||
| Grade item | Activity : Assignment 2 |
|
||||
| Font | Helvetica |
|
||||
| Size | 20 |
|
||||
| Colour | #045ECD |
|
||||
| Width | 20 |
|
||||
| Reference point location | Top left |
|
||||
And I press "Save changes"
|
||||
# Image.
|
||||
And I add the element "Image" to page "1" of the "Custom certificate 1" certificate template
|
||||
|
@ -287,6 +323,18 @@ Feature: Being able to manage elements in a certificate template
|
|||
| Width | 10 |
|
||||
| Height | 10 |
|
||||
And I press "Save changes"
|
||||
# QR Code.
|
||||
And I add the element "QR code" to page "1" of the "Custom certificate 1" certificate template
|
||||
And I set the following fields to these values:
|
||||
| Width | 25 |
|
||||
| Height | 15 |
|
||||
And I press "Save changes"
|
||||
And I should see "QR code" in the "elementstable" "table"
|
||||
And I click on ".edit-icon" "css_element" in the "QR code" "table_row"
|
||||
And the following fields match these values:
|
||||
| Width | 25 |
|
||||
| Height | 15 |
|
||||
And I press "Save changes"
|
||||
# Just to test there are no exceptions being thrown.
|
||||
And I follow "Reposition elements"
|
||||
And I press "Save and close"
|
||||
|
|
|
@ -101,6 +101,64 @@ class mod_customcert_element_helper_testcase extends advanced_testcase {
|
|||
$this->assertEquals($SITE->id, \mod_customcert\element_helper::get_courseid($element->id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests we are returning the correct course module id for an element in a course customcert activity.
|
||||
*/
|
||||
public function test_get_context_element_in_course_certificate() {
|
||||
global $DB;
|
||||
|
||||
// Create a course.
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
|
||||
// Create a custom certificate in the course.
|
||||
$customcert = $this->getDataGenerator()->create_module('customcert', array('course' => $course->id));
|
||||
|
||||
// Get the template to add elements to.
|
||||
$template = $DB->get_record('customcert_templates', array('contextid' => context_module::instance($customcert->cmid)->id));
|
||||
$template = new \mod_customcert\template($template);
|
||||
|
||||
// Add a page to the template.
|
||||
$pageid = $template->add_page();
|
||||
|
||||
// Add an element to this page.
|
||||
$element = new \stdClass();
|
||||
$element->name = 'Test element';
|
||||
$element->element = 'testelement';
|
||||
$element->pageid = $pageid;
|
||||
$element->sequence = \mod_customcert\element_helper::get_element_sequence($element->pageid);
|
||||
$element->timecreated = time();
|
||||
$element->id = $DB->insert_record('customcert_elements', $element);
|
||||
|
||||
// Confirm the correct course module id is returned.
|
||||
$this->assertEquals(context_module::instance($customcert->cmid),
|
||||
\mod_customcert\element_helper::get_context($element->id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests we are returning the correct course module id for an element in a site template.
|
||||
*/
|
||||
public function test_get_context_element_in_site_template() {
|
||||
global $DB;
|
||||
|
||||
// Add a template to the site.
|
||||
$template = \mod_customcert\template::create('Site template', context_system::instance()->id);
|
||||
|
||||
// Add a page to the template.
|
||||
$pageid = $template->add_page();
|
||||
|
||||
// Add an element to this page.
|
||||
$element = new \stdClass();
|
||||
$element->name = 'Test element';
|
||||
$element->element = 'testelement';
|
||||
$element->pageid = $pageid;
|
||||
$element->sequence = \mod_customcert\element_helper::get_element_sequence($element->pageid);
|
||||
$element->timecreated = time();
|
||||
$element->id = $DB->insert_record('customcert_elements', $element);
|
||||
|
||||
// Confirm the correct course module id is returned.
|
||||
$this->assertEquals(context_system::instance(), \mod_customcert\element_helper::get_context($element->id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test we return the correct grade items in a course.
|
||||
*/
|
||||
|
@ -122,28 +180,36 @@ class mod_customcert_element_helper_testcase extends advanced_testcase {
|
|||
$gc = $this->getDataGenerator()->create_grade_category(['courseid' => $course->id]);
|
||||
$gc = $DB->get_record('grade_items', ['itemtype' => 'category', 'iteminstance' => $gc->id]);
|
||||
|
||||
// Create an item attached to an outcome.
|
||||
$outcome = $this->getDataGenerator()->create_grade_outcome(['courseid' => $course->id, 'shortname' => 'outcome']);
|
||||
$go = $this->getDataGenerator()->create_grade_item(
|
||||
[
|
||||
'courseid' => $course->id,
|
||||
'outcomeid' => $outcome->id
|
||||
]
|
||||
);
|
||||
|
||||
// Confirm the function returns the correct number of grade items.
|
||||
$gradeitems = \mod_customcert\element_helper::get_grade_items($course);
|
||||
$this->assertCount(5, $gradeitems);
|
||||
$this->assertCount(6, $gradeitems);
|
||||
$this->assertArrayHasKey($assign1->cmid, $gradeitems);
|
||||
$this->assertArrayHasKey($assign2->cmid, $gradeitems);
|
||||
$this->assertArrayHasKey($assign3->cmid, $gradeitems);
|
||||
$this->assertArrayHasKey('gradeitem:' . $gi->id, $gradeitems);
|
||||
$this->assertArrayHasKey('gradeitem:' . $gc->id, $gradeitems);
|
||||
$this->assertArrayHasKey('gradeitem:' . $go->id, $gradeitems);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test we return the correct grade information for an activity.
|
||||
*/
|
||||
public function test_get_mod_grade_info() {
|
||||
global $CFG;
|
||||
|
||||
// Set that we want 3 decimals to display.
|
||||
$CFG->grade_decimalpoints = 3;
|
||||
|
||||
// Create a course.
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
|
||||
// Set that we want 3 decimals to display.
|
||||
grade_set_setting($course->id, 'decimalpoints', 3);
|
||||
|
||||
// Create two users.
|
||||
$student1 = $this->getDataGenerator()->create_user();
|
||||
$student2 = $this->getDataGenerator()->create_user();
|
||||
|
@ -199,23 +265,20 @@ class mod_customcert_element_helper_testcase extends advanced_testcase {
|
|||
$this->assertEquals(null, $grade->get_grade());
|
||||
$this->assertEquals('-', $grade->get_displaygrade());
|
||||
$this->assertEquals(null, $grade->get_dategraded());
|
||||
|
||||
grade_get_setting($course->id, null, null, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test we return the correct grade information for a course.
|
||||
*/
|
||||
public function test_get_course_grade_info() {
|
||||
global $CFG;
|
||||
|
||||
// Including to use constant.
|
||||
require_once($CFG->dirroot . '/mod/customcert/element/grade/classes/element.php');
|
||||
|
||||
// Set that we want 3 decimals to display.
|
||||
$CFG->grade_decimalpoints = 3;
|
||||
|
||||
// Create a course.
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
|
||||
// Set that we want 3 decimals to display.
|
||||
grade_set_setting($course->id, 'decimalpoints', 3);
|
||||
|
||||
// Create two users.
|
||||
$student1 = $this->getDataGenerator()->create_user();
|
||||
$student2 = $this->getDataGenerator()->create_user();
|
||||
|
@ -262,20 +325,20 @@ class mod_customcert_element_helper_testcase extends advanced_testcase {
|
|||
$this->assertEquals(null, $grade->get_grade());
|
||||
$this->assertEquals('-', $grade->get_displaygrade());
|
||||
$this->assertEquals(null, $grade->get_dategraded());
|
||||
|
||||
grade_get_setting($course->id, null, null, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test we return the correct grade information for a grade item.
|
||||
*/
|
||||
public function test_get_grade_item_info() {
|
||||
global $CFG;
|
||||
|
||||
// Set that we want 3 decimals to display.
|
||||
$CFG->grade_decimalpoints = 3;
|
||||
|
||||
// Create a course.
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
|
||||
// Set that we want 3 decimals to display.
|
||||
grade_set_setting($course->id, 'decimalpoints', 3);
|
||||
|
||||
// Create two users.
|
||||
$student1 = $this->getDataGenerator()->create_user();
|
||||
$student2 = $this->getDataGenerator()->create_user();
|
||||
|
@ -324,5 +387,7 @@ class mod_customcert_element_helper_testcase extends advanced_testcase {
|
|||
$this->assertEquals(null, $grade->get_grade());
|
||||
$this->assertEquals('-', $grade->get_displaygrade());
|
||||
$this->assertEquals(null, $grade->get_dategraded());
|
||||
|
||||
grade_get_setting($course->id, null, null, true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,8 +25,6 @@
|
|||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
global $CFG;
|
||||
|
||||
/**
|
||||
* Unit tests for the email certificate task.
|
||||
*
|
||||
|
@ -44,6 +42,81 @@ class mod_customcert_task_email_certificate_task_testcase extends advanced_testc
|
|||
$this->resetAfterTest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the email certificate task when there are no elements.
|
||||
*/
|
||||
public function test_email_certificates_no_elements() {
|
||||
// Create a course.
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
|
||||
// Create a user.
|
||||
$user1 = $this->getDataGenerator()->create_user();
|
||||
|
||||
// Create a custom certificate with no elements.
|
||||
$this->getDataGenerator()->create_module('customcert', ['course' => $course->id, 'emailstudents' => 1]);
|
||||
|
||||
// Enrol the user as a student
|
||||
$this->getDataGenerator()->enrol_user($user1->id, $course->id);
|
||||
|
||||
// Run the task.
|
||||
$sink = $this->redirectEmails();
|
||||
$task = new \mod_customcert\task\email_certificate_task();
|
||||
$task->execute();
|
||||
$emails = $sink->get_messages();
|
||||
|
||||
// Confirm that we did not send any emails because the certificate has no elements.
|
||||
$this->assertCount(0, $emails);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the email certificate task for users without a capability to receive a certificate.
|
||||
*/
|
||||
public function test_email_certificates_no_cap() {
|
||||
global $DB;
|
||||
|
||||
// Create a course.
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
|
||||
// Create some users.
|
||||
$user1 = $this->getDataGenerator()->create_user();
|
||||
$user2 = $this->getDataGenerator()->create_user();
|
||||
|
||||
// Enrol two of them in the course as students but revoke their right to receive a certificate issue.
|
||||
$roleids = $DB->get_records_menu('role', null, '', 'shortname, id');
|
||||
$this->getDataGenerator()->enrol_user($user1->id, $course->id);
|
||||
$this->getDataGenerator()->enrol_user($user2->id, $course->id);
|
||||
|
||||
unassign_capability('mod/customcert:receiveissue', $roleids['student']);
|
||||
|
||||
// Create a custom certificate.
|
||||
$customcert = $this->getDataGenerator()->create_module('customcert', ['course' => $course->id, 'emailstudents' => 1]);
|
||||
|
||||
// Create template object.
|
||||
$template = new stdClass();
|
||||
$template->id = $customcert->templateid;
|
||||
$template->name = 'A template';
|
||||
$template->contextid = context_course::instance($course->id)->id;
|
||||
$template = new \mod_customcert\template($template);
|
||||
|
||||
// Add a page to this template.
|
||||
$pageid = $template->add_page();
|
||||
|
||||
// Add an element to the page.
|
||||
$element = new stdClass();
|
||||
$element->pageid = $pageid;
|
||||
$element->name = 'Image';
|
||||
$DB->insert_record('customcert_elements', $element);
|
||||
|
||||
// Run the task.
|
||||
$sink = $this->redirectEmails();
|
||||
$task = new \mod_customcert\task\email_certificate_task();
|
||||
$task->execute();
|
||||
$emails = $sink->get_messages();
|
||||
|
||||
// Confirm that we did not send any emails.
|
||||
$this->assertCount(0, $emails);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the email certificate task for students.
|
||||
*/
|
||||
|
@ -70,6 +143,22 @@ class mod_customcert_task_email_certificate_task_testcase extends advanced_testc
|
|||
$customcert = $this->getDataGenerator()->create_module('customcert', array('course' => $course->id,
|
||||
'emailstudents' => 1));
|
||||
|
||||
// Create template object.
|
||||
$template = new stdClass();
|
||||
$template->id = $customcert->templateid;
|
||||
$template->name = 'A template';
|
||||
$template->contextid = context_course::instance($course->id)->id;
|
||||
$template = new \mod_customcert\template($template);
|
||||
|
||||
// Add a page to this template.
|
||||
$pageid = $template->add_page();
|
||||
|
||||
// Add an element to the page.
|
||||
$element = new stdClass();
|
||||
$element->pageid = $pageid;
|
||||
$element->name = 'Image';
|
||||
$DB->insert_record('customcert_elements', $element);
|
||||
|
||||
// Ok, now issue this to one user.
|
||||
\mod_customcert\certificate::issue_certificate($customcert->id, $user1->id);
|
||||
|
||||
|
@ -95,11 +184,9 @@ class mod_customcert_task_email_certificate_task_testcase extends advanced_testc
|
|||
// Confirm that we sent out emails to the two users.
|
||||
$this->assertCount(2, $emails);
|
||||
|
||||
$this->assertContains(fullname($user3), $emails[0]->header);
|
||||
$this->assertEquals($CFG->noreplyaddress, $emails[0]->from);
|
||||
$this->assertEquals($user1->email, $emails[0]->to);
|
||||
|
||||
$this->assertContains(fullname($user3), $emails[1]->header);
|
||||
$this->assertEquals($CFG->noreplyaddress, $emails[1]->from);
|
||||
$this->assertEquals($user2->email, $emails[1]->to);
|
||||
|
||||
|
@ -138,9 +225,25 @@ class mod_customcert_task_email_certificate_task_testcase extends advanced_testc
|
|||
$this->getDataGenerator()->enrol_user($user3->id, $course->id, $roleids['editingteacher']);
|
||||
|
||||
// Create a custom certificate.
|
||||
$this->getDataGenerator()->create_module('customcert', array('course' => $course->id,
|
||||
$customcert = $this->getDataGenerator()->create_module('customcert', array('course' => $course->id,
|
||||
'emailteachers' => 1));
|
||||
|
||||
// Create template object.
|
||||
$template = new stdClass();
|
||||
$template->id = $customcert->templateid;
|
||||
$template->name = 'A template';
|
||||
$template->contextid = context_course::instance($course->id)->id;
|
||||
$template = new \mod_customcert\template($template);
|
||||
|
||||
// Add a page to this template.
|
||||
$pageid = $template->add_page();
|
||||
|
||||
// Add an element to the page.
|
||||
$element = new stdClass();
|
||||
$element->pageid = $pageid;
|
||||
$element->name = 'Image';
|
||||
$DB->insert_record('customcert_elements', $element);
|
||||
|
||||
// Run the task.
|
||||
$sink = $this->redirectEmails();
|
||||
$task = new \mod_customcert\task\email_certificate_task();
|
||||
|
@ -150,11 +253,9 @@ class mod_customcert_task_email_certificate_task_testcase extends advanced_testc
|
|||
// Confirm that we only sent out 2 emails, both emails to the teacher for the two students.
|
||||
$this->assertCount(2, $emails);
|
||||
|
||||
$this->assertContains(fullname($user3), utf8_encode($emails[0]->header));
|
||||
$this->assertEquals($CFG->noreplyaddress, $emails[0]->from);
|
||||
$this->assertEquals($user3->email, $emails[0]->to);
|
||||
|
||||
$this->assertContains(fullname($user3), utf8_encode($emails[1]->header));
|
||||
$this->assertEquals($CFG->noreplyaddress, $emails[1]->from);
|
||||
$this->assertEquals($user3->email, $emails[1]->to);
|
||||
}
|
||||
|
@ -163,7 +264,7 @@ class mod_customcert_task_email_certificate_task_testcase extends advanced_testc
|
|||
* Tests the email certificate task for others.
|
||||
*/
|
||||
public function test_email_certificates_others() {
|
||||
global $CFG;
|
||||
global $CFG, $DB;
|
||||
|
||||
// Create a course.
|
||||
$course = $this->getDataGenerator()->create_course();
|
||||
|
@ -177,9 +278,25 @@ class mod_customcert_task_email_certificate_task_testcase extends advanced_testc
|
|||
$this->getDataGenerator()->enrol_user($user2->id, $course->id);
|
||||
|
||||
// Create a custom certificate.
|
||||
$this->getDataGenerator()->create_module('customcert', array('course' => $course->id,
|
||||
$customcert = $this->getDataGenerator()->create_module('customcert', array('course' => $course->id,
|
||||
'emailothers' => 'testcustomcert@example.com, doo@dah'));
|
||||
|
||||
// Create template object.
|
||||
$template = new stdClass();
|
||||
$template->id = $customcert->templateid;
|
||||
$template->name = 'A template';
|
||||
$template->contextid = context_course::instance($course->id)->id;
|
||||
$template = new \mod_customcert\template($template);
|
||||
|
||||
// Add a page to this template.
|
||||
$pageid = $template->add_page();
|
||||
|
||||
// Add an element to the page.
|
||||
$element = new stdClass();
|
||||
$element->pageid = $pageid;
|
||||
$element->name = 'Image';
|
||||
$DB->insert_record('customcert_elements', $element);
|
||||
|
||||
// Run the task.
|
||||
$sink = $this->redirectEmails();
|
||||
$task = new \mod_customcert\task\email_certificate_task();
|
||||
|
@ -189,11 +306,9 @@ class mod_customcert_task_email_certificate_task_testcase extends advanced_testc
|
|||
// Confirm that we only sent out 2 emails, both emails to the other address that was valid for the two students.
|
||||
$this->assertCount(2, $emails);
|
||||
|
||||
$this->assertContains(fullname(get_admin()), utf8_encode($emails[0]->header));
|
||||
$this->assertEquals($CFG->noreplyaddress, $emails[0]->from);
|
||||
$this->assertEquals('testcustomcert@example.com', $emails[0]->to);
|
||||
|
||||
$this->assertContains(fullname(get_admin()), utf8_encode($emails[1]->header));
|
||||
$this->assertEquals($CFG->noreplyaddress, $emails[1]->from);
|
||||
$this->assertEquals('testcustomcert@example.com', $emails[1]->to);
|
||||
}
|
||||
|
@ -215,7 +330,23 @@ class mod_customcert_task_email_certificate_task_testcase extends advanced_testc
|
|||
$this->getDataGenerator()->enrol_user($user1->id, $course->id);
|
||||
|
||||
// Create a custom certificate.
|
||||
$this->getDataGenerator()->create_module('customcert', array('course' => $course->id, 'emailstudents' => 1));
|
||||
$customcert = $this->getDataGenerator()->create_module('customcert', ['course' => $course->id, 'emailstudents' => 1]);
|
||||
|
||||
// Create template object.
|
||||
$template = new stdClass();
|
||||
$template->id = $customcert->templateid;
|
||||
$template->name = 'A template';
|
||||
$template->contextid = context_course::instance($course->id)->id;
|
||||
$template = new \mod_customcert\template($template);
|
||||
|
||||
// Add a page to this template.
|
||||
$pageid = $template->add_page();
|
||||
|
||||
// Add an element to the page.
|
||||
$element = new stdClass();
|
||||
$element->pageid = $pageid;
|
||||
$element->name = 'Image';
|
||||
$DB->insert_record('customcert_elements', $element);
|
||||
|
||||
// Remove the permission for the user to view the certificate.
|
||||
assign_capability('mod/customcert:view', CAP_PROHIBIT, $roleids['student'], \context_course::instance($course->id));
|
||||
|
@ -253,9 +384,25 @@ class mod_customcert_task_email_certificate_task_testcase extends advanced_testc
|
|||
$this->getDataGenerator()->enrol_user($user1->id, $course->id);
|
||||
|
||||
// Create a custom certificate.
|
||||
$this->getDataGenerator()->create_module('customcert', array('course' => $course->id, 'emailstudents' => 1,
|
||||
$customcert = $this->getDataGenerator()->create_module('customcert', array('course' => $course->id, 'emailstudents' => 1,
|
||||
'requiredtime' => '60'));
|
||||
|
||||
// Create template object.
|
||||
$template = new stdClass();
|
||||
$template->id = $customcert->templateid;
|
||||
$template->name = 'A template';
|
||||
$template->contextid = context_course::instance($course->id)->id;
|
||||
$template = new \mod_customcert\template($template);
|
||||
|
||||
// Add a page to this template.
|
||||
$pageid = $template->add_page();
|
||||
|
||||
// Add an element to the page.
|
||||
$element = new stdClass();
|
||||
$element->pageid = $pageid;
|
||||
$element->name = 'Image';
|
||||
$DB->insert_record('customcert_elements', $element);
|
||||
|
||||
// Run the task.
|
||||
$sink = $this->redirectEmails();
|
||||
$task = new \mod_customcert\task\email_certificate_task();
|
||||
|
|
|
@ -28,6 +28,7 @@ require_once('../../config.php');
|
|||
|
||||
$contextid = optional_param('contextid', context_system::instance()->id, PARAM_INT);
|
||||
$code = optional_param('code', '', PARAM_ALPHANUM); // The code for the certificate we are verifying.
|
||||
$qrcode = optional_param('qrcode', false, PARAM_BOOL);
|
||||
|
||||
$context = context::instance_by_id($contextid);
|
||||
|
||||
|
@ -87,7 +88,7 @@ if ($checkallofsite) {
|
|||
// The form we are using to verify these codes.
|
||||
$form = new \mod_customcert\verify_certificate_form($pageurl);
|
||||
|
||||
if ($form->get_data()) {
|
||||
if ($code) {
|
||||
$result = new stdClass();
|
||||
$result->issues = array();
|
||||
|
||||
|
@ -128,7 +129,10 @@ if ($form->get_data()) {
|
|||
|
||||
echo $OUTPUT->header();
|
||||
echo $OUTPUT->heading($heading);
|
||||
echo $form->display();
|
||||
// Don't show the form if we are coming from a QR code.
|
||||
if (!$qrcode) {
|
||||
echo $form->display();
|
||||
}
|
||||
if (isset($result)) {
|
||||
$renderer = $PAGE->get_renderer('mod_customcert');
|
||||
$result = new \mod_customcert\output\verify_certificate_results($result);
|
||||
|
|
|
@ -24,10 +24,10 @@
|
|||
|
||||
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
|
||||
|
||||
$plugin->version = 2018051706; // The current module version (Date: YYYYMMDDXX).
|
||||
$plugin->version = 2018051710; // The current module version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2018051700; // Requires this Moodle version (3.5).
|
||||
$plugin->cron = 0; // Period for cron to check this module (secs).
|
||||
$plugin->component = 'mod_customcert';
|
||||
|
||||
$plugin->maturity = MATURITY_STABLE;
|
||||
$plugin->release = "3.5.5"; // User-friendly version number.
|
||||
$plugin->release = "3.5.9"; // User-friendly version number.
|
||||
|
|
20
view.php
20
view.php
|
@ -43,6 +43,7 @@ require_login($course, false, $cm);
|
|||
$context = context_module::instance($cm->id);
|
||||
require_capability('mod/customcert:view', $context);
|
||||
|
||||
$canreceive = has_capability('mod/customcert:receiveissue', $context);
|
||||
$canmanage = has_capability('mod/customcert:manage', $context);
|
||||
$canviewreport = has_capability('mod/customcert:viewreport', $context);
|
||||
|
||||
|
@ -134,10 +135,14 @@ if (!$downloadown && !$downloadissue) {
|
|||
}
|
||||
|
||||
// Create the button to download the customcert.
|
||||
$linkname = get_string('getcustomcert', 'customcert');
|
||||
$link = new moodle_url('/mod/customcert/view.php', array('id' => $cm->id, 'downloadown' => true));
|
||||
$downloadbutton = new single_button($link, $linkname, 'post', true);
|
||||
$downloadbutton = $OUTPUT->render($downloadbutton);
|
||||
$downloadbutton = '';
|
||||
if ($canreceive) {
|
||||
$linkname = get_string('getcustomcert', 'customcert');
|
||||
$link = new moodle_url('/mod/customcert/view.php', array('id' => $cm->id, 'downloadown' => true));
|
||||
$downloadbutton = new single_button($link, $linkname, 'get', true);
|
||||
$downloadbutton->class .= ' m-b-1'; // Seems a bit hackish, ahem.
|
||||
$downloadbutton = $OUTPUT->render($downloadbutton);
|
||||
}
|
||||
|
||||
// Output all the page data.
|
||||
echo $OUTPUT->header();
|
||||
|
@ -146,13 +151,14 @@ if (!$downloadown && !$downloadissue) {
|
|||
echo $issuehtml;
|
||||
echo $downloadbutton;
|
||||
if (isset($reporttable)) {
|
||||
echo $OUTPUT->heading(get_string('listofissues', 'customcert'), 3);
|
||||
$numissues = \mod_customcert\certificate::get_number_of_issues($customcert->id, $cm, $groupmode);
|
||||
echo $OUTPUT->heading(get_string('listofissues', 'customcert', $numissues), 3);
|
||||
groups_print_activity_menu($cm, $pageurl);
|
||||
echo $reporttable->out($perpage, false);
|
||||
}
|
||||
echo $OUTPUT->footer($course);
|
||||
exit();
|
||||
} else { // Output to pdf.
|
||||
} else if ($canreceive) { // Output to pdf.
|
||||
// Set the userid value of who we are downloading the certificate for.
|
||||
$userid = $USER->id;
|
||||
if ($downloadown) {
|
||||
|
@ -173,6 +179,8 @@ if (!$downloadown && !$downloadissue) {
|
|||
redirect(new moodle_url('/mod/customcert/view.php', array('id' => $cm->id)));
|
||||
}
|
||||
|
||||
\core\session\manager::write_close();
|
||||
|
||||
// Now we want to generate the PDF.
|
||||
$template = new \mod_customcert\template($template);
|
||||
$template->generate_pdf(false, $userid);
|
||||
|
|
|
@ -80,24 +80,14 @@ Y.extend(Rearrange, Y.Base, {
|
|||
this.elements = params[2];
|
||||
|
||||
// Set the PDF dimensions.
|
||||
this.pdfx = Y.one('#pdf').getX();
|
||||
this.pdfy = Y.one('#pdf').getY();
|
||||
this.pdfwidth = parseFloat(Y.one('#pdf').getComputedStyle('width'));
|
||||
this.pdfheight = parseFloat(Y.one('#pdf').getComputedStyle('height'));
|
||||
this.setPdfDimensions();
|
||||
|
||||
// Set the boundaries.
|
||||
this.pdfleftboundary = this.pdfx;
|
||||
if (this.page.leftmargin) {
|
||||
this.pdfleftboundary += parseInt(this.page.leftmargin * this.pixelsinmm, 10);
|
||||
}
|
||||
|
||||
this.pdfrightboundary = this.pdfx + this.pdfwidth;
|
||||
if (this.page.rightmargin) {
|
||||
this.pdfrightboundary -= parseInt(this.page.rightmargin * this.pixelsinmm, 10);
|
||||
}
|
||||
this.setBoundaries();
|
||||
|
||||
this.setpositions();
|
||||
this.createevents();
|
||||
window.addEventListener("resize", this.checkWindownResize.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -130,6 +120,40 @@ Y.extend(Rearrange, Y.Base, {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the PDF dimensions.
|
||||
*/
|
||||
setPdfDimensions: function() {
|
||||
this.pdfx = Y.one('#pdf').getX();
|
||||
this.pdfy = Y.one('#pdf').getY();
|
||||
this.pdfwidth = parseFloat(Y.one('#pdf').getComputedStyle('width'));
|
||||
this.pdfheight = parseFloat(Y.one('#pdf').getComputedStyle('height'));
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the boundaries.
|
||||
*/
|
||||
setBoundaries: function() {
|
||||
this.pdfleftboundary = this.pdfx;
|
||||
if (this.page.leftmargin) {
|
||||
this.pdfleftboundary += parseInt(this.page.leftmargin * this.pixelsinmm, 10);
|
||||
}
|
||||
|
||||
this.pdfrightboundary = this.pdfx + this.pdfwidth;
|
||||
if (this.page.rightmargin) {
|
||||
this.pdfrightboundary -= parseInt(this.page.rightmargin * this.pixelsinmm, 10);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Check browser resize and reset position.
|
||||
*/
|
||||
checkWindownResize: function() {
|
||||
this.setPdfDimensions();
|
||||
this.setBoundaries();
|
||||
this.setpositions();
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates the JS events for changing element positions.
|
||||
*/
|
||||
|
|
|
@ -1 +1 @@
|
|||
YUI.add("moodle-mod_customcert-rearrange",function(e,t){var n=function(){n.superclass.constructor.apply(this,[arguments])};e.extend(n,e.Base,{templateid:0,page:[],elements:[],pdfx:0,pdfy:0,pdfwidth:0,pdfheight:0,elementxy:0,pdfleftboundary:0,pdfrightboundary:0,pixelsinmm:3.779527559055,initializer:function(t){this.templateid=t[0],this.page=t[1],this.elements=t[2],this.pdfx=e.one("#pdf").getX(),this.pdfy=e.one("#pdf").getY(),this.pdfwidth=parseFloat(e.one("#pdf").getComputedStyle("width")),this.pdfheight=parseFloat(e.one("#pdf").getComputedStyle("height")),this.pdfleftboundary=this.pdfx,this.page.leftmargin&&(this.pdfleftboundary+=parseInt(this.page.leftmargin*this.pixelsinmm,10)),this.pdfrightboundary=this.pdfx+this.pdfwidth,this.page.rightmargin&&(this.pdfrightboundary-=parseInt(this.page.rightmargin*this.pixelsinmm,10)),this.setpositions(),this.createevents()},setpositions:function(){for(var t in this.elements){var n=this.elements[t],r=this.pdfx+n.posx*this.pixelsinmm,i=this.pdfy+n.posy*this.pixelsinmm,s=parseFloat(e.one("#element-"+n.id).getComputedStyle("width")),o=n.width*this.pixelsinmm;o&&s>o&&(s=o);switch(n.refpoint){case"1":r-=s/2;break;case"2":r=r-s+2}e.one("#element-"+n.id).setX(r),e.one("#element-"+n.id).setY(i)}},createevents:function(){e.one(".savepositionsbtn [type=submit]").on("click",function(e){this.savepositions(e)},this),e.one(".applypositionsbtn [type=submit]").on("click",function(e){this.savepositions(e),e.preventDefault()},this);var t=new e.DD.Delegate({container:"#pdf",nodes:".element"});t.on("drag:start",function(){var e=t.get("currentNode");this.elementxy=e.getXY()},this),t.on("drag:end",function(){var e=t.get("currentNode");this.isoutofbounds(e)&&e.setXY(this.elementxy)},this)},isoutofbounds:function(e){var t=parseFloat(e.getComputedStyle("width")),n=parseFloat(e.getComputedStyle("height")),r=e.getX(),i=r+t,s=e.getY(),o=s+n;return r<this.pdfleftboundary||i>this.pdfrightboundary?!0:s<this.pdfy||o>this.pdfy+this.pdfheight?!0:!1},savepositions:function(t){var n={tid:this.templateid,values:[]};for(var r in this.elements){var i=this.elements[r],s=e.one("#element-"+i.id),o=s.getX()-this.pdfx,u=s.getY()-this.pdfy,a=s.getData("refpoint"),f=parseFloat(s.getComputedStyle("width"));switch(a){case"1":o+=f/2;break;case"2":o+=f}n.values.push({id:i.id,posx:Math.round(parseFloat(o/this.pixelsinmm)),posy:Math.round(parseFloat(u/this.pixelsinmm))})}n.values=JSON.stringify(n.values),e.io(M.cfg.wwwroot+"/mod/customcert/ajax.php",{method:"POST",data:n,on:{failure:function(e,t){this.ajaxfailure(t)},success:function(){var e=t.currentTarget.ancestor("form",!0),n=e.getAttribute("action"),r=e.one("[name=pid]");if(r){var i=r.get("value");window.location=n+"?pid="+i}else{var s=e.one("[name=tid]").get("value");window.location=n+"?tid="+s}}},context:this}),t.preventDefault()},ajaxfailure:function(e){var t={name:e.status+" "+e.statusText,message:e.responseText};return new M.core.exception(t)}}),e.namespace("M.mod_customcert.rearrange").init=function(e,t,r){new n(e,t,r)}},"@VERSION@",{requires:["dd-delegate","dd-drag"]});
|
||||
YUI.add("moodle-mod_customcert-rearrange",function(e,t){var n=function(){n.superclass.constructor.apply(this,[arguments])};e.extend(n,e.Base,{templateid:0,page:[],elements:[],pdfx:0,pdfy:0,pdfwidth:0,pdfheight:0,elementxy:0,pdfleftboundary:0,pdfrightboundary:0,pixelsinmm:3.779527559055,initializer:function(e){this.templateid=e[0],this.page=e[1],this.elements=e[2],this.setPdfDimensions(),this.setBoundaries(),this.setpositions(),this.createevents(),window.addEventListener("resize",this.checkWindownResize.bind(this))},setpositions:function(){for(var t in this.elements){var n=this.elements[t],r=this.pdfx+n.posx*this.pixelsinmm,i=this.pdfy+n.posy*this.pixelsinmm,s=parseFloat(e.one("#element-"+n.id).getComputedStyle("width")),o=n.width*this.pixelsinmm;o&&s>o&&(s=o);switch(n.refpoint){case"1":r-=s/2;break;case"2":r=r-s+2}e.one("#element-"+n.id).setX(r),e.one("#element-"+n.id).setY(i)}},setPdfDimensions:function(){this.pdfx=e.one("#pdf").getX(),this.pdfy=e.one("#pdf").getY(),this.pdfwidth=parseFloat(e.one("#pdf").getComputedStyle("width")),this.pdfheight=parseFloat(e.one("#pdf").getComputedStyle("height"))},setBoundaries:function(){this.pdfleftboundary=this.pdfx,this.page.leftmargin&&(this.pdfleftboundary+=parseInt(this.page.leftmargin*this.pixelsinmm,10)),this.pdfrightboundary=this.pdfx+this.pdfwidth,this.page.rightmargin&&(this.pdfrightboundary-=parseInt(this.page.rightmargin*this.pixelsinmm,10))},checkWindownResize:function(){this.setPdfDimensions(),this.setBoundaries(),this.setpositions()},createevents:function(){e.one(".savepositionsbtn [type=submit]").on("click",function(e){this.savepositions(e)},this),e.one(".applypositionsbtn [type=submit]").on("click",function(e){this.savepositions(e),e.preventDefault()},this);var t=new e.DD.Delegate({container:"#pdf",nodes:".element"});t.on("drag:start",function(){var e=t.get("currentNode");this.elementxy=e.getXY()},this),t.on("drag:end",function(){var e=t.get("currentNode");this.isoutofbounds(e)&&e.setXY(this.elementxy)},this)},isoutofbounds:function(e){var t=parseFloat(e.getComputedStyle("width")),n=parseFloat(e.getComputedStyle("height")),r=e.getX(),i=r+t,s=e.getY(),o=s+n;return r<this.pdfleftboundary||i>this.pdfrightboundary?!0:s<this.pdfy||o>this.pdfy+this.pdfheight?!0:!1},savepositions:function(t){var n={tid:this.templateid,values:[]};for(var r in this.elements){var i=this.elements[r],s=e.one("#element-"+i.id),o=s.getX()-this.pdfx,u=s.getY()-this.pdfy,a=s.getData("refpoint"),f=parseFloat(s.getComputedStyle("width"));switch(a){case"1":o+=f/2;break;case"2":o+=f}n.values.push({id:i.id,posx:Math.round(parseFloat(o/this.pixelsinmm)),posy:Math.round(parseFloat(u/this.pixelsinmm))})}n.values=JSON.stringify(n.values),e.io(M.cfg.wwwroot+"/mod/customcert/ajax.php",{method:"POST",data:n,on:{failure:function(e,t){this.ajaxfailure(t)},success:function(){var e=t.currentTarget.ancestor("form",!0),n=e.getAttribute("action"),r=e.one("[name=pid]");if(r){var i=r.get("value");window.location=n+"?pid="+i}else{var s=e.one("[name=tid]").get("value");window.location=n+"?tid="+s}}},context:this}),t.preventDefault()},ajaxfailure:function(e){var t={name:e.status+" "+e.statusText,message:e.responseText};return new M.core.exception(t)}}),e.namespace("M.mod_customcert.rearrange").init=function(e,t,r){new n(e,t,r)}},"@VERSION@",{requires:["dd-delegate","dd-drag"]});
|
||||
|
|
|
@ -80,24 +80,14 @@ Y.extend(Rearrange, Y.Base, {
|
|||
this.elements = params[2];
|
||||
|
||||
// Set the PDF dimensions.
|
||||
this.pdfx = Y.one('#pdf').getX();
|
||||
this.pdfy = Y.one('#pdf').getY();
|
||||
this.pdfwidth = parseFloat(Y.one('#pdf').getComputedStyle('width'));
|
||||
this.pdfheight = parseFloat(Y.one('#pdf').getComputedStyle('height'));
|
||||
this.setPdfDimensions();
|
||||
|
||||
// Set the boundaries.
|
||||
this.pdfleftboundary = this.pdfx;
|
||||
if (this.page.leftmargin) {
|
||||
this.pdfleftboundary += parseInt(this.page.leftmargin * this.pixelsinmm, 10);
|
||||
}
|
||||
|
||||
this.pdfrightboundary = this.pdfx + this.pdfwidth;
|
||||
if (this.page.rightmargin) {
|
||||
this.pdfrightboundary -= parseInt(this.page.rightmargin * this.pixelsinmm, 10);
|
||||
}
|
||||
this.setBoundaries();
|
||||
|
||||
this.setpositions();
|
||||
this.createevents();
|
||||
window.addEventListener("resize", this.checkWindownResize.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -130,6 +120,40 @@ Y.extend(Rearrange, Y.Base, {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the PDF dimensions.
|
||||
*/
|
||||
setPdfDimensions: function() {
|
||||
this.pdfx = Y.one('#pdf').getX();
|
||||
this.pdfy = Y.one('#pdf').getY();
|
||||
this.pdfwidth = parseFloat(Y.one('#pdf').getComputedStyle('width'));
|
||||
this.pdfheight = parseFloat(Y.one('#pdf').getComputedStyle('height'));
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the boundaries.
|
||||
*/
|
||||
setBoundaries: function() {
|
||||
this.pdfleftboundary = this.pdfx;
|
||||
if (this.page.leftmargin) {
|
||||
this.pdfleftboundary += parseInt(this.page.leftmargin * this.pixelsinmm, 10);
|
||||
}
|
||||
|
||||
this.pdfrightboundary = this.pdfx + this.pdfwidth;
|
||||
if (this.page.rightmargin) {
|
||||
this.pdfrightboundary -= parseInt(this.page.rightmargin * this.pixelsinmm, 10);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Check browser resize and reset position.
|
||||
*/
|
||||
checkWindownResize: function() {
|
||||
this.setPdfDimensions();
|
||||
this.setBoundaries();
|
||||
this.setpositions();
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates the JS events for changing element positions.
|
||||
*/
|
||||
|
|
50
yui/src/rearrange/js/rearrange.js
vendored
50
yui/src/rearrange/js/rearrange.js
vendored
|
@ -78,24 +78,14 @@ Y.extend(Rearrange, Y.Base, {
|
|||
this.elements = params[2];
|
||||
|
||||
// Set the PDF dimensions.
|
||||
this.pdfx = Y.one('#pdf').getX();
|
||||
this.pdfy = Y.one('#pdf').getY();
|
||||
this.pdfwidth = parseFloat(Y.one('#pdf').getComputedStyle('width'));
|
||||
this.pdfheight = parseFloat(Y.one('#pdf').getComputedStyle('height'));
|
||||
this.setPdfDimensions();
|
||||
|
||||
// Set the boundaries.
|
||||
this.pdfleftboundary = this.pdfx;
|
||||
if (this.page.leftmargin) {
|
||||
this.pdfleftboundary += parseInt(this.page.leftmargin * this.pixelsinmm, 10);
|
||||
}
|
||||
|
||||
this.pdfrightboundary = this.pdfx + this.pdfwidth;
|
||||
if (this.page.rightmargin) {
|
||||
this.pdfrightboundary -= parseInt(this.page.rightmargin * this.pixelsinmm, 10);
|
||||
}
|
||||
this.setBoundaries();
|
||||
|
||||
this.setpositions();
|
||||
this.createevents();
|
||||
window.addEventListener("resize", this.checkWindownResize.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -128,6 +118,40 @@ Y.extend(Rearrange, Y.Base, {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the PDF dimensions.
|
||||
*/
|
||||
setPdfDimensions: function() {
|
||||
this.pdfx = Y.one('#pdf').getX();
|
||||
this.pdfy = Y.one('#pdf').getY();
|
||||
this.pdfwidth = parseFloat(Y.one('#pdf').getComputedStyle('width'));
|
||||
this.pdfheight = parseFloat(Y.one('#pdf').getComputedStyle('height'));
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets the boundaries.
|
||||
*/
|
||||
setBoundaries: function() {
|
||||
this.pdfleftboundary = this.pdfx;
|
||||
if (this.page.leftmargin) {
|
||||
this.pdfleftboundary += parseInt(this.page.leftmargin * this.pixelsinmm, 10);
|
||||
}
|
||||
|
||||
this.pdfrightboundary = this.pdfx + this.pdfwidth;
|
||||
if (this.page.rightmargin) {
|
||||
this.pdfrightboundary -= parseInt(this.page.rightmargin * this.pixelsinmm, 10);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Check browser resize and reset position.
|
||||
*/
|
||||
checkWindownResize: function() {
|
||||
this.setPdfDimensions();
|
||||
this.setBoundaries();
|
||||
this.setpositions();
|
||||
},
|
||||
|
||||
/**
|
||||
* Creates the JS events for changing element positions.
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue