Compare commits

..

100 commits

Author SHA1 Message Date
Mark Nelson e25ebd6420 Fixed size of 'Changed' in CHANGES.md 2020-11-26 23:31:52 +08:00
Mark Nelson 02f9ed9b49 Bumped version 2020-11-26 23:06:53 +08:00
Mark Nelson 3b0b1298d5 Update CHANGES.md (#390) 2020-11-26 22:09:50 +08:00
uvigo-atic 850c19f588 Added username to userfield form element (#390) 2020-11-26 22:09:42 +08:00
Mark Nelson a08c880c04 Updated CHANGES.md (#276) 2020-11-26 21:43:06 +08:00
Mark Nelson 7a309f506f Update 'emailteachers_help' and 'emailothers_help' language strings (#276) 2020-11-26 21:35:50 +08:00
Mark Nelson d778424a92 Do not email out certificates with no elements (#276) 2020-11-26 21:13:50 +08:00
Mark Nelson f1c67c7134 Use null coalescing operator in element factory 2020-11-26 18:22:57 +08:00
Mark Nelson e45e6e21cf Update 'emailstudents_help' language string (#276) 2020-11-26 17:55:58 +08:00
Mark Nelson 7b523100b7 Bump .travis.yml to use v3 of moodle-plugin-ci 2020-11-09 16:29:16 +01:00
Mark Nelson a1d19bf84d Update repo used by Travis 2020-11-09 16:28:57 +01:00
Mark Nelson 512bbad3c4 Update CHANGES.md 2020-11-04 19:32:54 +01:00
Brendan Heywood ebfc1c029d PDFs should be inline not attachments #153 2020-11-04 19:16:26 +01:00
Mark Nelson 75dbbf661d Add CSS class for mobile app (#378) 2020-10-12 13:36:39 +02:00
Mark Nelson be08afb7b4 Removed multiple empty lines 2020-09-20 16:00:59 +02:00
Mark Nelson 0223518bf9 Updated CHANGES.md 2020-09-20 15:55:09 +02:00
Mark Nelson cb5b5d7465 Fixed issue with PDF being generated without a name (#333) 2020-09-20 15:41:09 +02:00
Mark Nelson 2e9bc44bf3 Fixed exception loading template image that has no image selected (#369) 2020-09-20 14:58:22 +02:00
Mark Nelson e7e238aaf7 Do not email those who can manage the certificate (#376) 2020-09-20 14:29:35 +02:00
Guillermo Gomez a20285a947 Implement get_objectid_mapping (#374) 2020-09-20 14:17:11 +02:00
Mark Nelson f82258c78a Updated CHANGES.md 2020-08-08 19:39:40 +02:00
Mark Nelson b7b33ebd8c Changed 'enrollment' to 'enrolment' to conform to Moodle core (#328)
Also minor changes like ordering strings alphabetically and adding
full-stops.
2020-08-08 19:38:43 +02:00
Sergey Evstegneiev c4b21153eb Adding enrollment start & end date options (#328) 2020-08-08 19:38:29 +02:00
Mark Nelson e6b640c0cf Fix stale file warning 2020-08-08 18:11:07 +02:00
Mark Nelson 3bd09923c4 Ignore multiple certificate codes (#363) 2020-08-08 15:53:10 +02:00
Mark Nelson 8125a5e9ff Remove trailing spaces 2020-08-08 15:47:04 +02:00
Thong Bui 69123d230b Fix get position when browser shrinking (#343) 2020-08-08 15:28:40 +02:00
Mark Nelson 133852af7c Updated CHANGES.md 2020-06-28 18:38:13 +02:00
Mark Nelson 1d4434ed15 Update node version used in .travis.yml 2020-05-30 13:37:18 +02:00
Mark Nelson 4a45b5ab81 Mark certificates as viewed in mobile app (#342) 2020-05-30 13:10:22 +02:00
Mark Nelson 476f292d73 Refactor element_helper::get_grade_items() to be nicer to read 2020-05-08 21:24:16 +02:00
Mark Nelson 684af9de0f Fix docs in Grade element name 2020-05-08 17:50:39 +02:00
Mark Nelson 42645287d7 The Grade item name element works with all grade items (#346) 2020-05-08 17:27:49 +02:00
Mark Nelson 9badf60f91 Extend unit test (#329) 2020-05-08 17:23:31 +02:00
Mark Nelson c992d7a376 Add the ability to select Outcomes in the Grade element (#329) 2020-05-08 17:23:24 +02:00
Mark Nelson a5d51f2478 Removed 'exampledata' string 2020-05-08 16:57:31 +02:00
Mark Nelson cd9cf91769 Added capability to determine who can receive a certificate (#270) 2020-04-19 13:53:07 +02:00
Mark Nelson f00a0d739d Update CHANGES.md 2020-04-19 13:52:31 +02:00
Mark Nelson 3ecfaf69f4 Fix foreign key violation (#331) 2020-04-17 17:06:39 +02:00
Mark Nelson b480cf3c68 Fixed broken logic (#298) 2020-04-17 16:52:07 +02:00
Mark Nelson 48c83d34df Loading templates copies system images to the course (#298)
Before it would just reference the system images. However, this meant
backup/restore was broken as it did not include the images the template
was using.
2020-04-17 16:52:04 +02:00
Mark Nelson 8a2b7290af Added extra Behat steps for new elements (#309) 2020-04-17 16:28:17 +02:00
Sergey 4db2148886 Fix of showing names of custom user fields (#326)
Show normal human-readable name of custom user profile fields instead of internal shortname
2020-04-17 16:27:54 +02:00
Mark Nelson e76705315c Fixed typo in Behat file name 2020-04-17 16:26:32 +02:00
Mark Nelson 7f62e6eaec Re-add code column (#264) 2020-04-17 16:26:32 +02:00
Arnaud Trouvé d37cc22135 Add userfullname variable for email subject (#316) 2020-04-17 16:26:32 +02:00
Mark Nelson 7492fd1686 Changed references to old github name 2020-04-17 16:26:32 +02:00
Mark Nelson 7336a21df7 Downgrade version.php for qrcode element 2020-04-17 16:09:39 +02:00
Mark Nelson e6ddaa5b30 Do not allow '0' as a value for width or height in QR code (#321) 2020-04-17 16:03:33 +02:00
Mark Nelson 20cfbdf9c3 Fix complaints found by local_moodlecheck 2020-04-17 16:03:26 +02:00
Mark Nelson 1bfceb6794 Incorrect PHPDocs for render_form_elements and co (#271) 2020-04-17 16:03:16 +02:00
Mark Nelson b16bf5ccb6 Added QR code element (#146) 2020-04-17 16:03:07 +02:00
Mark Nelson 7532606ffa Downgrade version.php for daterange element 2020-04-17 15:47:33 +02:00
Mark Nelson 5da5b675ab Add ability to specify the current date for date related elements (#289) 2020-04-17 15:42:36 +02:00
Mark Nelson d2f12c859c String improvements for date range element
Also added a help button to reduce the wall
of text.
2020-04-17 15:42:30 +02:00
Mark Nelson 50e8374596 Fixed PHPDoc reference to edit_element_form 2020-04-17 15:42:25 +02:00
Mark Nelson 0652441d45 Use negative numbers for constants in date range element
The reason being that we may have a module that has
an id matching one of these values.
2020-04-17 15:42:18 +02:00
Mark Nelson 8c03508a40 Fix complaints found by local_moodlecheck 2020-04-17 15:42:08 +02:00
Mark Nelson 4c639bbe3e Minor changes (#185) 2020-04-17 15:41:32 +02:00
Dmitrii Metelkin 4d62cde7f3 Use repeat form element for date ranges (#185) 2020-04-17 15:41:24 +02:00
Dmitrii Metelkin 2866aa7c6b Remove empty line (#185) 2020-04-17 15:41:18 +02:00
Dmitrii Metelkin 9021794049 Add new placeholders and update help description (#185) 2020-04-17 15:41:10 +02:00
Dmitrii Metelkin 8f006a2600 Rename first_year and last_year placeholders (#185) 2020-04-17 15:41:06 +02:00
Dmitrii Metelkin 71b0a8bd0e Update description string (#185) 2020-04-17 15:40:59 +02:00
Dmitrii Metelkin 9874a2bd0d Add tests to support functionality (#185) 2020-04-17 15:40:54 +02:00
Dmitrii Metelkin ea868e3cd3 Improve the logic of recurring ranges (#185) 2020-04-17 15:40:49 +02:00
Dmitrii Metelkin 82aa988db4 Recursively check recurring date ranges (#185) 2020-04-17 15:40:43 +02:00
Dmitrii Metelkin 3cd85428df Add an empty line to the end of styles.css (#185) 2020-04-17 15:40:37 +02:00
Dmitrii Metelkin 48024d2b77 Update lang strings (#185) 2020-04-17 15:40:31 +02:00
Dmitrii Metelkin 0eb96e3605 Be more strict about 12 months limit (#185) 2020-04-17 15:40:23 +02:00
Dmitrii Metelkin 36ec9188fa Modify recurring dateranges (#185) 2020-04-17 15:40:16 +02:00
Dmitrii Metelkin 2852683dff Add range related placeholders (#185) 2020-04-17 15:40:11 +02:00
Dmitrii Metelkin 3e69898988 Get rid of useless css rule (#185) 2020-04-17 15:40:06 +02:00
Dmitrii Metelkin 92b15ecb06 Change a way of displaying date ranges on the edit element page (#185) 2020-04-17 15:40:00 +02:00
Dmitrii Metelkin 057cf92f03 Add recurring option to dateranges (#185) 2020-04-17 15:39:55 +02:00
Dmitrii Metelkin 59fe72c7ca Use element name in the preview mode (#185) 2020-04-17 15:39:49 +02:00
Mark Nelson e0cdcb07b9 Bump date range element version numbers (#185) 2020-04-17 15:39:41 +02:00
Dmitrii Metelkin d91639e4ed Add date range element (#185) 2020-04-17 15:39:34 +02:00
mwithheld 6d0c4160f7 Do not fail if multiple certificate issues (#304)
Fix another location of this problem.
2020-04-07 13:46:29 +02:00
mwithheld db81b49608 Do not fail if multiple certificate issues (#295)
Ignore multiple matches for a user-customcert combo in the customcert_issues table.
In our case, the scheduled task died when:
$issueid = $DB->get_field('customcert_issues', 'id', array('userid' => $enroluser->id, 'customcertid' => $customcert->id));
returned 2 rows, which shouldn't happen, but did anyway.

This means in rare circumstances (i.e. the race condition) the user may get multiple certificates (e.g. one via the UI, one by email) but that is better than not getting one at all and the whole job dying.
2020-04-01 15:11:33 +02:00
Mark Nelson 3c3902ab9d Specify OS in travis 2019-05-29 00:19:42 +08:00
Mark Nelson b1b6af3e65 Bump version 2019-05-28 17:49:23 +08:00
Mark Nelson aacf541621 Updated CHANGES.md 2019-05-28 17:49:23 +08:00
Mark Nelson 4f583679d0 Check that a certificate issue exists (#269) 2019-05-28 14:36:21 +08:00
Mark Nelson 01e427cf57 Make travis happy (#282) 2019-05-28 14:36:15 +08:00
Sagar Ghimire bb2ed945fa Fix failing test_get_grades (#282) 2019-05-28 14:36:10 +08:00
Mark Nelson 5a7e1ee98d Use openjdk-8-jre-headless instead of oracle-java8 in .travis.yml 2019-05-28 14:36:00 +08:00
Mark Nelson 13ec235c2d Readded number of certificates issued (#266) 2019-05-28 14:35:55 +08:00
Mark Nelson d42cbc9a16 Removed unnecessary inclusion 2019-05-28 14:35:51 +08:00
Mark Nelson f91a54ebc9 Specify grades' decimal places in unit test (#277) 2019-05-28 14:35:46 +08:00
Mark Nelson fc0fb240fd Always send emails from 'noreplyuser' (#165) 2019-05-28 14:35:41 +08:00
Mark Nelson 92e0029623 Incorrect PHPDocs for render_form_elements and co (#271) 2019-05-28 14:35:30 +08:00
Nicolas Roeser 322abdbba3 Add vertical spacing after certificate download button
Increase the vertical spacing after the single button for downloading
user’s own certificate. This makes the page look better.
2019-02-04 14:46:46 +08:00
Mark Nelson 59f9bfcc78 Bumped version 2018-12-31 10:45:22 +08:00
Mark Nelson 577a997960 Updated CHANGES.md 2018-12-31 10:44:01 +08:00
Mark Nelson 1b756fbd5b Make it clear what element values are just an example (#144) 2018-12-31 10:16:58 +08:00
Mark Nelson d12e752d1a Use course module context when calling format_string/text (#200) 2018-12-28 15:09:40 +08:00
Mark Nelson 961a3f02f0 Prevent exception when adding 'teachername' element to site template (#261) 2018-12-27 09:08:31 +08:00
Mark Nelson 9f844368fd Added missing details to CHANGES.md 2018-12-27 07:42:37 +08:00
Mark Nelson a3f159dfaf Added missing implementation for privacy provider (#260) 2018-12-27 07:42:32 +08:00
82 changed files with 292 additions and 1638 deletions

View file

@ -1,120 +0,0 @@
name: Moodle Plugin CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-18.04
services:
postgres:
image: postgres:9.6
env:
POSTGRES_USER: 'postgres'
POSTGRES_HOST_AUTH_METHOD: 'trust'
ports:
- 5432:5432
options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 3
mariadb:
image: mariadb:10.5
env:
MYSQL_USER: 'root'
MYSQL_ALLOW_EMPTY_PASSWORD: "true"
ports:
- 3306:3306
options: --health-cmd="mysqladmin ping" --health-interval 10s --health-timeout 5s --health-retries 3
strategy:
fail-fast: false
matrix:
include:
- php: '7.4'
moodle-branch: 'MOODLE_311_STABLE'
database: pgsql
- php: '7.4'
moodle-branch: 'MOODLE_311_STABLE'
database: mariadb
- php: '7.3'
moodle-branch: 'MOODLE_311_STABLE'
database: pgsql
- php: '7.3'
moodle-branch: 'MOODLE_311_STABLE'
database: mariadb
steps:
- name: Check out repository code
uses: actions/checkout@v2
with:
path: plugin
- name: Setup PHP ${{ matrix.php }}
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
coverage: none
- name: Initialise moodle-plugin-ci
run: |
composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^3
echo $(cd ci/bin; pwd) >> $GITHUB_PATH
echo $(cd ci/vendor/bin; pwd) >> $GITHUB_PATH
sudo locale-gen en_AU.UTF-8
echo "NVM_DIR=$HOME/.nvm" >> $GITHUB_ENV
- name: Install moodle-plugin-ci
run: moodle-plugin-ci install --plugin ./plugin --db-host=127.0.0.1
env:
DB: ${{ matrix.database }}
MOODLE_BRANCH: ${{ matrix.moodle-branch }}
MUSTACHE_IGNORE_NAMES: 'mobile_*.mustache'
- name: PHP Lint
if: ${{ always() }}
run: moodle-plugin-ci phplint
- name: PHP Copy/Paste Detector
continue-on-error: true # This step will show errors but will not fail
if: ${{ always() }}
run: moodle-plugin-ci phpcpd
- name: PHP Mess Detector
continue-on-error: true # This step will show errors but will not fail
if: ${{ always() }}
run: moodle-plugin-ci phpmd
- name: Moodle Code Checker
if: ${{ always() }}
run: moodle-plugin-ci codechecker --max-warnings 0
- name: Moodle PHPDoc Checker
if: ${{ always() }}
run: moodle-plugin-ci phpdoc
- name: Validating
if: ${{ always() }}
run: moodle-plugin-ci validate
- name: Check upgrade savepoints
if: ${{ always() }}
run: moodle-plugin-ci savepoints
- name: Mustache Lint
if: ${{ always() }}
run: moodle-plugin-ci mustache
- name: Grunt
if: ${{ always() }}
run: moodle-plugin-ci grunt --max-lint-warnings 0
- name: PHPUnit tests
if: ${{ always() }}
run: |
moodle-plugin-ci phpunit
cd moodle
vendor/bin/phpunit --fail-on-risky --disallow-test-output --filter tool_dataprivacy_metadata_registry_testcase
vendor/bin/phpunit --fail-on-risky --disallow-test-output --filter core_externallib_testcase
vendor/bin/phpunit --fail-on-risky --disallow-test-output --testsuite core_privacy_testsuite --filter provider_testcase
- name: Behat features
if: ${{ always() }}
run: moodle-plugin-ci behat --profile chrome

2
.gitignore vendored
View file

@ -1,2 +0,0 @@
vendor/
*.swp

52
.travis.yml Normal file
View file

@ -0,0 +1,52 @@
language: php
# For javascript behat tests we need sudo
sudo: true
dist: trusty
cache:
directories:
- $HOME/.composer/cache
- $HOME/.npm
php:
- 7.0
- 7.2
addons:
firefox: 47.0.1
postgresql: 9.3
apt:
packages:
- openjdk-8-jre-headless
env:
global:
- MOODLE_BRANCH=MOODLE_35_STABLE
- IGNORE_NAMES=mobile_*.mustache # Mobile mustache has specific syntax, ignore their templates
matrix:
- DB=pgsql
- DB=mysqli
before_install:
- phpenv config-rm xdebug.ini
- nvm install 14.0
- nvm use 14.0
- cd ../..
- 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:
- moodle-plugin-ci install
script:
- moodle-plugin-ci phplint
# - moodle-plugin-ci phpcpd # subplugins often have similar code and cause "duplicated code" errors
# - moodle-plugin-ci phpmd # too much noise from this check, maybe, some day...
- moodle-plugin-ci codechecker
- moodle-plugin-ci validate
- moodle-plugin-ci savepoints
- moodle-plugin-ci mustache
- moodle-plugin-ci grunt -t stylelint:css -t js
- moodle-plugin-ci phpunit
- moodle-plugin-ci behat

View file

@ -4,39 +4,7 @@ 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/mdjnelson/moodle-mod_customcert/issues/169.
## [3.11.2] - 2021-??-??
### Fixed
- Fix places not using the multi-language filter (#433).
- Fix user IDs in the issue table not being mapped during restore (#449).
- Fix emails displaying HTML entities encoded (#457).
- Fix error message when we have custom profile fields (#465).
- Respect multiple languages in manage template page title (#467).
### Added
- You can now choose the course short or full name to display (#415).
- You can now select the alignment for all text elements (#121).
## [3.11.1] - 2021-06-13
### Fixed
- Usage of deprecated functions (#423)
## [3.10.1] - 2021-06-13
### Added
- Usage of github actions (#407).
- The ability to show the description on the course page (#406).
- The ability to choose how to deliver the certificate (#401).
### Fixed
- Managers are now able to download their students' certificates (#412).
- Users being able to view the certificate before the required time set (#403).
- Fixed the issue with displaying PDF when debugging is ON (#420).
- Using incorrect context when sending emails (#402).
- Use `cron_setup_user` when sending emails (#414).
## [3.8.5] - 2020-11-26
## [3.5.9] - 2020-11-26
### Added
@ -56,18 +24,23 @@ Note - All hash comments refer to the issue number. Eg. #169 refers to https://g
### Fixed
- Certificates now get marked as viewed via the mobile app (#342).
- Custom fields not displaying properly (#359).
- 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.8.4] - 2020-03-12
## [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
@ -78,46 +51,10 @@ Note - All hash comments refer to the issue number. Eg. #169 refers to https://g
### Fixed
- Fixed the displaying of names of a custom user field (#326).
- Do not allow '0' as a value for width or height in QR code (#321).
## [3.8.3] - 2020-03-09
### Fixed
- Fixed foreign key violation (#331).
## [3.8.2] - 2019-12-16
### Added
- Added subplugins.json file (#312).
- Re-added 'code' column to user report (#264).
- Add 'userfullname' variable for email subject (#316).
### Fixed
- Do not fail if multiple certificate issues (#304) and (#295).
## [3.7.1] - 2019-06-17
### Added
- Added new custom course field element (#274).
- Added ability to specify the current date for date related elements (#289).
### Changed
- String improvements for the 'Date range' element.
### Fixed
- Use negative numbers for constants in the 'Date range' element. The reason being that we may have a module
that has an id matching one of these positive values. Sites which are using the 'Date range' element (sites
which are **not** using this element do **not** have to do anything) will need to re-edit each element, select
the date item again and save. An upgrade step was not created because it is impossible to tell if the site does
actually want the constant or if they actually want the date for the module.
## [3.6.2] - 2019-05-28
## [3.5.7] - 2019-05-28
### Changed
@ -125,17 +62,14 @@ Note - All hash comments refer to the issue number. Eg. #169 refers to https://g
### Added
- Added QR code element (#146).
- Added Date range element (#185).
- Added the number of certificates issued above the report (#266).
- Added new capability to control who can be issued a certificate (#270).
### Fixed
- Failures when running unit tests for multiple activities (#282).
- Check that a certificate is valid before downloading on 'My certificates' page (#269).
- Check that a certificate is issued before downloading on 'My certificates' page (#269).
## [3.6.1] - 2018-12-31
## [3.5.6] - 2018-12-31
### Changed

View file

@ -6,8 +6,6 @@ This activity allows the dynamic generation of PDF certificates with complete cu
There are two installation methods that are available.
First, make sure that wkhtmltopdf is installed on your server and available on $PATH.
Follow one of these, then log into your Moodle site as an administrator and visit the notifications page to complete the install.
### Git
@ -38,4 +36,4 @@ Visit the [wiki page](https://docs.moodle.org/en/Custom_certificate_module "Wiki
## License
Licensed under the [GNU GPL License](http://www.gnu.org/copyleft/gpl.html).
Licensed under the [GNU GPL License](http://www.gnu.org/copyleft/gpl.html).

View file

@ -54,4 +54,4 @@ foreach ($values as $value) {
$element->posx = $value->posx;
$element->posy = $value->posy;
$DB->update_record('customcert_elements', $element);
}
}

View file

@ -1,2 +1 @@
define ("mod_customcert/dialogue",["core/yui"],function(a){var b=function(b,c,d,e,f){this.yuiDialogue=null;var g=this;if("undefined"==typeof f){f=!1}a.use("moodle-core-notification","timers",function(){var h="480px";if(f){h="800px"}g.yuiDialogue=new M.core.dialogue({headerContent:b,bodyContent:c,draggable:!0,visible:!1,center:!0,modal:!0,width:h});g.yuiDialogue.after("visibleChange",function(b){if(b.newVal){if("undefined"!=typeof d){a.soon(function(){d(g);g.yuiDialogue.centerDialogue()})}}else{if("undefined"!=typeof e){a.soon(function(){e(g)})}}});g.yuiDialogue.show()})};b.prototype.close=function(){this.yuiDialogue.hide();this.yuiDialogue.destroy()};b.prototype.getContent=function(){return this.yuiDialogue.bodyNode.getDOMNode()};return b});
//# sourceMappingURL=dialogue.min.js.map
define(["core/yui"],function(a){var b=function(b,c,d,e,f){this.yuiDialogue=null;var g=this;"undefined"==typeof f&&(f=!1),a.use("moodle-core-notification","timers",function(){var h="480px";f&&(h="800px"),g.yuiDialogue=new M.core.dialogue({headerContent:b,bodyContent:c,draggable:!0,visible:!1,center:!0,modal:!0,width:h}),g.yuiDialogue.after("visibleChange",function(b){b.newVal?"undefined"!=typeof d&&a.soon(function(){d(g),g.yuiDialogue.centerDialogue()}):"undefined"!=typeof e&&a.soon(function(){e(g)})}),g.yuiDialogue.show()})};return b.prototype.close=function(){this.yuiDialogue.hide(),this.yuiDialogue.destroy()},b.prototype.getContent=function(){return this.yuiDialogue.bodyNode.getDOMNode()},b});

File diff suppressed because one or more lines are too long

View file

@ -1,2 +1 @@
define ("mod_customcert/rearrange-area",["jquery","core/yui","core/fragment","mod_customcert/dialogue","core/notification","core/str","core/templates","core/ajax"],function(a,b,c,d,f,g,h,i){var j=function(b){this._node=a(b);this._setEvents()};j.prototype.CUSTOMCERT_REF_POINT_TOPLEFT=0;j.prototype.CUSTOMCERT_REF_POINT_TOPCENTER=1;j.prototype.CUSTOMCERT_REF_POINT_TOPRIGHT=2;j.prototype.PIXELSINMM=3.779527559055;j.prototype._setEvents=function(){this._node.on("click",".element",this._editElement.bind(this))};j.prototype._editElement=function(a){var e=a.currentTarget.id.substr(8),h=this._node.attr("data-contextid");c.loadFragment("mod_customcert","editelement",h,{elementid:e}).done(function(a,c){g.get_string("editelement","mod_customcert").done(function(f){b.use("moodle-core-formchangechecker",function(){new d(f,"<div id='elementcontent'></div>",this._editElementDialogueConfig.bind(this,e,a,c),void 0,!0)}.bind(this))}.bind(this))}.bind(this)).fail(f.exception)};j.prototype._editElementDialogueConfig=function(b,c,d,g){h.replaceNode("#elementcontent",c,d);this._setPositionInForm(b);var i=a(g.getContent());i.on("click","#id_submitbutton",function(c){M.core_formchangechecker.reset_form_dirty_state();this._saveElement(b).then(function(){this._getElementHTML(b).done(function(c){var d=this._node.find("#element-"+b),e=parseInt(a("#id_refpoint").val()),f="";if(e==this.CUSTOMCERT_REF_POINT_TOPLEFT){f="refpoint-left"}else if(e==this.CUSTOMCERT_REF_POINT_TOPCENTER){f="refpoint-center"}else if(e==this.CUSTOMCERT_REF_POINT_TOPRIGHT){f="refpoint-right"}d.empty().append(c);d.removeClass();d.addClass("element "+f);d.attr("data-refpoint",e);var h=a("#editelementform #id_posx").val(),i=a("#editelementform #id_posy").val();this._setPosition(b,e,h,i);g.close()}.bind(this))}.bind(this)).fail(f.exception);c.preventDefault()}.bind(this));i.on("click","#id_cancel",function(a){g.close();a.preventDefault()})};j.prototype._setPosition=function(a,c,d,e){var f=b.one("#element-"+a);d=b.one("#pdf").getX()+d*this.PIXELSINMM;e=b.one("#pdf").getY()+e*this.PIXELSINMM;var g=parseFloat(f.getComputedStyle("width")),h=f.width*this.PIXELSINMM;if(h&&g>h){g=h}switch(c){case this.CUSTOMCERT_REF_POINT_TOPCENTER:d-=g/2;break;case this.CUSTOMCERT_REF_POINT_TOPRIGHT:d=d-g+2;break;}f.setX(d);f.setY(e)};j.prototype._setPositionInForm=function(c){var d=a("#editelementform #id_posx"),e=a("#editelementform #id_posy");if(d.length&&e.length){var f=b.one("#element-"+c),g=f.getX()-b.one("#pdf").getX(),h=f.getY()-b.one("#pdf").getY(),i=parseInt(f.getData("refpoint")),j=parseFloat(f.getComputedStyle("width"));switch(i){case this.CUSTOMCERT_REF_POINT_TOPCENTER:g+=j/2;break;case this.CUSTOMCERT_REF_POINT_TOPRIGHT:g+=j;break;}g=Math.round(parseFloat(g/this.PIXELSINMM));h=Math.round(parseFloat(h/this.PIXELSINMM));d.val(g);e.val(h)}};j.prototype._getElementHTML=function(a){var b=this._node.attr("data-templateid"),c=i.call([{methodname:"mod_customcert_get_element_html",args:{templateid:b,elementid:a}}]);return c[0]};j.prototype._saveElement=function(b){var c=this._node.attr("data-templateid"),d=a("#editelementform").serializeArray(),e=i.call([{methodname:"mod_customcert_save_element",args:{templateid:c,elementid:b,values:d}}]);return e[0]};return{init:function init(a){new j(a)}}});
//# sourceMappingURL=rearrange-area.min.js.map
define(["jquery","core/yui","core/fragment","mod_customcert/dialogue","core/notification","core/str","core/templates","core/ajax"],function(a,b,c,d,e,f,g,h){var i=function(b){this._node=a(b),this._setEvents()};return i.prototype.CUSTOMCERT_REF_POINT_TOPLEFT=0,i.prototype.CUSTOMCERT_REF_POINT_TOPCENTER=1,i.prototype.CUSTOMCERT_REF_POINT_TOPRIGHT=2,i.prototype.PIXELSINMM=3.779527559055,i.prototype._setEvents=function(){this._node.on("click",".element",this._editElement.bind(this))},i.prototype._editElement=function(a){var g=a.currentTarget.id.substr(8),h=this._node.attr("data-contextid"),i={elementid:g};c.loadFragment("mod_customcert","editelement",h,i).done(function(a,c){f.get_string("editelement","mod_customcert").done(function(e){b.use("moodle-core-formchangechecker",function(){new d(e,"<div id='elementcontent'></div>",this._editElementDialogueConfig.bind(this,g,a,c),(void 0),(!0))}.bind(this))}.bind(this))}.bind(this)).fail(e.exception)},i.prototype._editElementDialogueConfig=function(b,c,d,f){g.replaceNode("#elementcontent",c,d),this._setPositionInForm(b);var h=a(f.getContent());h.on("click","#id_submitbutton",function(c){M.core_formchangechecker.reset_form_dirty_state(),this._saveElement(b).then(function(){this._getElementHTML(b).done(function(c){var d=this._node.find("#element-"+b),e=parseInt(a("#id_refpoint").val()),g="";e==this.CUSTOMCERT_REF_POINT_TOPLEFT?g="refpoint-left":e==this.CUSTOMCERT_REF_POINT_TOPCENTER?g="refpoint-center":e==this.CUSTOMCERT_REF_POINT_TOPRIGHT&&(g="refpoint-right"),d.empty().append(c),d.removeClass(),d.addClass("element "+g),d.attr("data-refpoint",e);var h=a("#editelementform #id_posx").val(),i=a("#editelementform #id_posy").val();this._setPosition(b,e,h,i),f.close()}.bind(this))}.bind(this)).fail(e.exception),c.preventDefault()}.bind(this)),h.on("click","#id_cancel",function(a){f.close(),a.preventDefault()})},i.prototype._setPosition=function(a,c,d,e){var f=b.one("#element-"+a);d=b.one("#pdf").getX()+d*this.PIXELSINMM,e=b.one("#pdf").getY()+e*this.PIXELSINMM;var g=parseFloat(f.getComputedStyle("width")),h=f.width*this.PIXELSINMM;switch(h&&g>h&&(g=h),c){case this.CUSTOMCERT_REF_POINT_TOPCENTER:d-=g/2;break;case this.CUSTOMCERT_REF_POINT_TOPRIGHT:d=d-g+2}f.setX(d),f.setY(e)},i.prototype._setPositionInForm=function(c){var d=a("#editelementform #id_posx"),e=a("#editelementform #id_posy");if(d.length&&e.length){var f=b.one("#element-"+c),g=f.getX()-b.one("#pdf").getX(),h=f.getY()-b.one("#pdf").getY(),i=parseInt(f.getData("refpoint")),j=parseFloat(f.getComputedStyle("width"));switch(i){case this.CUSTOMCERT_REF_POINT_TOPCENTER:g+=j/2;break;case this.CUSTOMCERT_REF_POINT_TOPRIGHT:g+=j}g=Math.round(parseFloat(g/this.PIXELSINMM)),h=Math.round(parseFloat(h/this.PIXELSINMM)),d.val(g),e.val(h)}},i.prototype._getElementHTML=function(a){var b=this._node.attr("data-templateid"),c=h.call([{methodname:"mod_customcert_get_element_html",args:{templateid:b,elementid:a}}]);return c[0]},i.prototype._saveElement=function(b){var c=this._node.attr("data-templateid"),d=a("#editelementform").serializeArray(),e=h.call([{methodname:"mod_customcert_save_element",args:{templateid:c,elementid:b,values:d}}]);return e[0]},{init:function(a){new i(a)}}});

File diff suppressed because one or more lines are too long

View file

@ -18,6 +18,7 @@
* use the YUI version in AMD code until it is replaced.
*
* @module mod_customcert/dialogue
* @package mod_customcert
* @copyright 2016 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

View file

@ -17,6 +17,7 @@
* AMD module used when rearranging a custom certificate.
*
* @module mod_customcert/rearrange-area
* @package mod_customcert
* @copyright 2016 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/

View file

@ -56,7 +56,7 @@ class backup_customcert_activity_task extends backup_activity_task {
* @param string $content
* @return mixed|string
*/
public static function encode_content_links($content) {
static public function encode_content_links($content) {
global $CFG;
$base = preg_quote($CFG->wwwroot, "/");

View file

@ -59,7 +59,7 @@ class backup_customcert_activity_structure_step extends backup_activity_structur
$element = new backup_nested_element('element', array('id'), array(
'pageid', 'name', 'element', 'data', 'font', 'fontsize',
'colour', 'posx', 'posy', 'width', 'refpoint', 'sequence',
'alignment', 'timecreated', 'timemodified'));
'timecreated', 'timemodified'));
// The issues.
$issues = new backup_nested_element('issues');

View file

@ -53,7 +53,7 @@ class restore_customcert_activity_task extends restore_activity_task {
/**
* Define the contents in the activity that must be processed by the link decoder.
*/
public static function define_decode_contents() {
static public function define_decode_contents() {
$contents = array();
$contents[] = new restore_decode_content('customcert', array('intro'), 'customcert');
@ -64,7 +64,7 @@ class restore_customcert_activity_task extends restore_activity_task {
/**
* Define the decoding rules for links belonging to the activity to be executed by the link decoder.
*/
public static function define_decode_rules() {
static public function define_decode_rules() {
$rules = array();
$rules[] = new restore_decode_rule('CUSTOMCERTVIEWBYID', '/mod/customcert/view.php?id=$1', 'course_module');
@ -75,12 +75,12 @@ class restore_customcert_activity_task extends restore_activity_task {
}
/**
* Define the restore log rules that will be applied by the {@see restore_logs_processor} when restoring
* customcert logs. It must return one array of {@see restore_log_rule} objects.
* Define the restore log rules that will be applied by the {@link restore_logs_processor} when restoring
* customcert logs. It must return one array of {@link restore_log_rule} objects.
*
* @return array the restore log rules
*/
public static function define_restore_log_rules() {
static public function define_restore_log_rules() {
$rules = array();
$rules[] = new restore_log_rule('customcert', 'add', 'view.php?id={course_module}', '{customcert}');

View file

@ -159,7 +159,6 @@ class restore_customcert_activity_structure_step extends restore_activity_struct
$data->customcertid = $this->get_new_parentid('customcert');
$data->timecreated = $this->apply_date_offset($data->timecreated);
$data->userid = $this->get_mappingid('user', $data->userid);
$newitemid = $DB->insert_record('customcert_issues', $data);
$this->set_mapping('customcert_issue', $oldid, $newitemid);

View file

@ -80,4 +80,4 @@ class admin_setting_link extends \admin_setting_configtext {
return format_admin_setting($this, $this->visiblename,
\html_writer::link($this->link, $this->linkname), $this->description, true, '', null, $query);
}
}
}

View file

@ -37,16 +37,6 @@ defined('MOODLE_INTERNAL') || die();
*/
class certificate {
/**
* Send the file inline to the browser.
*/
const DELIVERY_OPTION_INLINE = 'I';
/**
* Send to the browser and force a file download
*/
const DELIVERY_OPTION_DOWNLOAD = 'D';
/**
* @var string the print protection variable
*/
@ -175,7 +165,7 @@ class certificate {
* @param int $userid
* @return int the total time spent in seconds
*/
public static function get_course_time(int $courseid, int $userid = 0): int {
public static function get_course_time($courseid, $userid = 0) {
global $CFG, $DB, $USER;
if (empty($userid)) {
@ -227,7 +217,7 @@ class certificate {
$totaltime = 0;
}
$delay = $log->$timefield - $lasthit;
if ($delay > $CFG->sessiontimeout) {
if ($delay > ($CFG->sessiontimeout * 60)) {
// The difference between the last log and the current log is more than
// the timeout Register session value so that we have found a session!
$login = $log->$timefield;
@ -270,20 +260,12 @@ class certificate {
$allparams = $conditionsparams + array('customcertid' => $customcertid);
// Return the issues.
$context = \context_module::instance($cm->id);
$extrafields = \core_user\fields::for_identity($context)->get_required_fields();
$ufields = \core_user\fields::for_userpic()->including(...$extrafields);
[
'selects' => $userfieldsselects,
'joins' => $userfieldsjoin,
'params' => $userfieldsparams
] = (array) $ufields->get_sql('u', true);
$allparams = array_merge($allparams, $userfieldsparams);
$sql = "SELECT ci.id as issueid, ci.code, ci.timecreated $userfieldsselects
$extrafields = get_extra_user_fields(\context_module::instance($cm->id));
$ufields = \user_picture::fields('u', $extrafields);
$sql = "SELECT $ufields, ci.id as issueid, ci.code, ci.timecreated
FROM {user} u
INNER JOIN {customcert_issues} ci ON u.id = ci.userid
$userfieldsjoin
INNER JOIN {customcert_issues} ci
ON u.id = ci.userid
WHERE u.deleted = 0
AND ci.customcertid = :customcertid
$conditionssql";

View file

@ -247,7 +247,7 @@ class edit_form extends \moodleform {
// Create a table to display these elements.
$table = new \html_table();
$table->attributes = array('class' => 'generaltable elementstable');
$table->head = array(get_string('name', 'customcert'), get_string('type', 'customcert'), get_string('actions'));
$table->head = array(get_string('name', 'customcert'), get_string('type', 'customcert'), '');
$table->align = array('left', 'left', 'left');
// Loop through and add the elements to the table.
foreach ($elements as $element) {

View file

@ -37,21 +37,6 @@ defined('MOODLE_INTERNAL') || die();
*/
abstract class element {
/**
* @var string The left alignment constant.
*/
const ALIGN_LEFT = 'L';
/**
* @var string The centered alignment constant.
*/
const ALIGN_CENTER = 'C';
/**
* @var string The right alignment constant.
*/
const ALIGN_RIGHT = 'R';
/**
* @var \stdClass $element The data for the element we are adding - do not use, kept for legacy reasons.
*/
@ -112,11 +97,6 @@ abstract class element {
*/
protected $refpoint;
/**
* @var string The alignment.
*/
protected $alignment;
/**
* @var bool $showposxy Show position XY form elements?
*/
@ -150,7 +130,6 @@ abstract class element {
$this->width = $element->width;
$this->refpoint = $element->refpoint;
$this->showposxy = isset($showposxy) && $showposxy;
$this->set_alignment($element->alignment ?? self::ALIGN_LEFT);
}
/**
@ -252,31 +231,6 @@ abstract class element {
return $this->refpoint;
}
/**
* Returns the alignment.
*
* @return string The current alignment value.
*/
public function get_alignment() {
return $this->alignment ?? self::ALIGN_LEFT;
}
/**
* Sets the alignment.
*
* @param string $alignment The new alignment.
*
* @throws \InvalidArgumentException if the provided new alignment is not valid.
*/
protected function set_alignment(string $alignment) {
$validvalues = array(self::ALIGN_LEFT, self::ALIGN_CENTER, self::ALIGN_RIGHT);
if (!in_array($alignment, $validvalues)) {
throw new \InvalidArgumentException("'$alignment' is not a valid alignment value. It has to be one of " .
implode(', ', $validvalues));
}
$this->alignment = $alignment;
}
/**
* This function renders the form elements when adding a customcert element.
* Can be overridden if more functionality is needed.
@ -292,7 +246,6 @@ abstract class element {
}
element_helper::render_form_element_width($mform);
element_helper::render_form_element_refpoint($mform);
element_helper::render_form_element_alignment($mform);
}
/**
@ -312,8 +265,7 @@ abstract class element {
'posx' => $this->posx,
'posy' => $this->posy,
'width' => $this->width,
'refpoint' => $this->refpoint,
'alignment' => $this->get_alignment()
'refpoint' => $this->refpoint
];
foreach ($properties as $property => $value) {
if (!is_null($value) && $mform->elementExists($property)) {
@ -359,16 +311,15 @@ abstract class element {
$element = new \stdClass();
$element->name = $data->name;
$element->data = $this->save_unique_data($data);
$element->font = $data->font ?? null;
$element->fontsize = $data->fontsize ?? null;
$element->colour = $data->colour ?? null;
$element->font = (isset($data->font)) ? $data->font : null;
$element->fontsize = (isset($data->fontsize)) ? $data->fontsize : null;
$element->colour = (isset($data->colour)) ? $data->colour : null;
if ($this->showposxy) {
$element->posx = $data->posx ?? null;
$element->posy = $data->posy ?? null;
$element->posx = (isset($data->posx)) ? $data->posx : null;
$element->posy = (isset($data->posy)) ? $data->posy : null;
}
$element->width = $data->width ?? null;
$element->refpoint = $data->refpoint ?? null;
$element->alignment = $data->alignment ?? self::ALIGN_LEFT;
$element->width = (isset($data->width)) ? $data->width : null;
$element->refpoint = (isset($data->refpoint)) ? $data->refpoint : null;
$element->timemodified = time();
// Check if we are updating, or inserting a new element.
@ -426,7 +377,7 @@ abstract class element {
* @param bool $preview true if it is a preview, false otherwise
* @param \stdClass $user the user we are rendering this for
*/
abstract public function render($pdf, $preview, $user);
public abstract function render($pdf, $preview, $user);
/**
* Render the element in html.
@ -438,7 +389,7 @@ abstract class element {
*
* @return string the html
*/
abstract public function render_html();
public abstract function render_html();
/**
* Handles deleting any data this element may have introduced.

View file

@ -59,7 +59,6 @@ class element_factory {
$data->posy = $element->posy ?? null;
$data->width = $element->width ?? null;
$data->refpoint = $element->refpoint ?? null;
$data->alignment = $element->alignment ?? null;
// Ensure the necessary class exists.
if (class_exists($classname)) {

View file

@ -74,7 +74,6 @@ class element_helper {
$w = $element->get_width();
$refpoint = $element->get_refpoint();
$actualwidth = $pdf->GetStringWidth($content);
$alignment = $element->get_alignment();
if ($w and $w < $actualwidth) {
$actualwidth = $w;
@ -105,7 +104,7 @@ class element_helper {
$w += 0.0001;
}
$pdf->setCellPaddings(0, 0, 0, 0);
$pdf->writeHTMLCell($w, 0, $x, $y, $content, 0, 0, false, true, $alignment);
$pdf->writeHTMLCell($w, 0, $x, $y, $content, 0, 0, false, true);
}
/**
@ -206,23 +205,6 @@ class element_helper {
$mform->addHelpButton('refpoint', 'refpoint', 'customcert');
}
/**
* Helper function to render the alignment form element.
*
* @param \MoodleQuickForm $mform the edit_form instance.
*/
public static function render_form_element_alignment($mform) {
$alignmentoptions = array();
$alignmentoptions[element::ALIGN_LEFT] = get_string('alignleft', 'customcert');
$alignmentoptions[element::ALIGN_CENTER] = get_string('aligncenter', 'customcert');
$alignmentoptions[element::ALIGN_RIGHT] = get_string('alignright', 'customcert');
$mform->addElement('select', 'alignment', get_string('alignment', 'customcert'), $alignmentoptions);
$mform->setType('alignment', PARAM_ALPHA);
$mform->setDefault('alignment', element::ALIGN_LEFT);
$mform->addHelpButton('alignment', 'alignment', 'customcert');
}
/**
* Helper function to performs validation on the colour element.
*

View file

@ -43,20 +43,10 @@ class course_module_viewed extends \core\event\course_module_viewed {
parent::init();
}
/**
* {@inheritdoc}
*
* @return string[]
*/
public static function get_objectid_mapping() {
return array('db' => 'customcert', 'restore' => 'customcert');
}
/**
* {@inheritdoc}
*
* @return bool
*/
public static function get_other_mapping() {
// No need to map.
return false;

View file

@ -1,64 +0,0 @@
<?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/>.
/**
* Provides helper functionality.
*
* @package mod_customcert
* @copyright 2021 Mark Nelson <mdjnelson@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_customcert;
use core_user\fields;
defined('MOODLE_INTERNAL') || die();
/**
* Class helper.
*
* Helper functionality for this module.
*
* @package mod_customcert
* @copyright 2021 Mark Nelson <mdjnelson@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class helper {
/**
* A centralised location for the all name fields.
*
* Returns a sql string snippet.
*
* @param string $tableprefix table query prefix to use in front of each field.
* @return string All name fields.
*/
public static function get_all_user_name_fields(string $tableprefix = ''): string {
$alternatenames = [];
foreach (fields::get_name_fields() as $field) {
$alternatenames[$field] = $field;
}
if ($tableprefix) {
foreach ($alternatenames as $key => $altname) {
$alternatenames[$key] = $tableprefix . '.' . $altname;
}
}
return implode(',', $alternatenames);
}
}

View file

@ -47,23 +47,19 @@ class load_template_form extends \moodleform {
// Get the context.
$context = $this->_customdata['context'];
$syscontext = \context_system::instance();
$mform->addElement('header', 'loadtemplateheader', get_string('loadtemplate', 'customcert'));
// Display a link to the manage templates page.
if ($context->contextlevel != CONTEXT_SYSTEM && has_capability('mod/customcert:manage', $syscontext)) {
if ($context->contextlevel != CONTEXT_SYSTEM && has_capability('mod/customcert:manage', \context_system::instance())) {
$link = \html_writer::link(new \moodle_url('/mod/customcert/manage_templates.php'),
get_string('managetemplates', 'customcert'));
$mform->addElement('static', 'managetemplates', '', $link);
}
$arrtemplates = $DB->get_records_menu('customcert_templates', ['contextid' => $syscontext->id], 'name ASC', 'id, name');
if ($arrtemplates) {
$templates = [];
foreach ($arrtemplates as $key => $template) {
$templates[$key] = format_string($template, true, ['context' => $context]);
}
$templates = $DB->get_records_menu('customcert_templates',
array('contextid' => \context_system::instance()->id), 'name ASC', 'id, name');
if ($templates) {
$group = array();
$group[] = $mform->createElement('select', 'ltid', '', $templates);
$group[] = $mform->createElement('submit', 'loadtemplatesubmit', get_string('load', 'customcert'));

View file

@ -77,7 +77,7 @@ class manage_templates_table extends \table_sql {
* @return string
*/
public function col_name($template) {
return format_string($template->name, true, ['context' => $this->context]);
return $template->name;
}
/**

View file

@ -44,10 +44,9 @@ class mobile {
global $OUTPUT, $DB, $USER;
$args = (object) $args;
$versionname = $args->appversioncode >= 3950 ? 'latest' : 'ionic3';
$cmid = $args->cmid;
$groupid = empty($args->group) ? 0 : (int) $args->group; // By default, group 0.
$groupid = empty($args->group) ? 0 : $args->group; // By default, group 0.
// Capabilities check.
$cm = get_coursemodule_from_id('customcert', $cmid);
@ -115,7 +114,6 @@ class mobile {
'showreport' => $showreport,
'hasrecipients' => !empty($recipients),
'recipients' => array_values($recipients),
'numrecipients' => count($recipients),
'currenttimestamp' => time()
];
@ -123,13 +121,11 @@ class mobile {
'templates' => [
[
'id' => 'main',
'html' => $OUTPUT->render_from_template("mod_customcert/mobile_view_activity_page_$versionname", $data),
'html' => $OUTPUT->render_from_template('mod_customcert/mobile_view_activity_page', $data),
],
],
'javascript' => '',
'otherdata' => [
'group' => $groupid,
]
'otherdata' => ''
];
}

View file

@ -66,7 +66,7 @@ class report_table extends \table_sql {
parent::__construct('mod_customcert_report_table');
$context = \context_module::instance($cm->id);
$extrafields = \core_user\fields::for_identity($context)->get_required_fields();
$extrafields = get_extra_user_fields($context);
$columns = [];
$columns[] = 'fullname';
@ -79,7 +79,7 @@ class report_table extends \table_sql {
$headers = [];
$headers[] = get_string('fullname');
foreach ($extrafields as $extrafield) {
$headers[] = \core_user\fields::get_display_name($extrafield);
$headers[] = get_user_field_name($extrafield);
}
$headers[] = get_string('receiveddate', 'customcert');
$headers[] = get_string('code', 'customcert');

View file

@ -23,8 +23,6 @@
*/
namespace mod_customcert\task;
use mod_customcert\helper;
defined('MOODLE_INTERNAL') || die();
/**
@ -86,9 +84,6 @@ class email_certificate_task extends \core\task\scheduled_task {
// Get the context.
$context = \context::instance_by_id($customcert->contextid);
// Set the $PAGE context - this ensure settings, such as language, are kept and don't default to the site settings.
$PAGE->set_context($context);
// Get the person we are going to send this email on behalf of.
$userfrom = \core_user::get_noreply_user();
@ -107,7 +102,7 @@ class email_certificate_task extends \core\task\scheduled_task {
$info->certificatename = $certificatename;
// Get a list of all the issues.
$userfields = helper::get_all_user_name_fields('u');
$userfields = get_all_user_name_fields(true, 'u');
$sql = "SELECT u.id, u.username, $userfields, u.email, ci.id as issueid, ci.emailed
FROM {customcert_issues} ci
JOIN {user} u
@ -181,9 +176,6 @@ class email_certificate_task extends \core\task\scheduled_task {
// Now, email the people we need to.
foreach ($issuedusers as $user) {
// Set up the user.
cron_setup_user($user);
$userfullname = fullname($user);
$info->userfullname = $userfullname;
@ -213,8 +205,7 @@ class email_certificate_task extends \core\task\scheduled_task {
$subject = get_string('emailstudentsubject', 'customcert', $info);
$message = $textrenderer->render($renderable);
$messagehtml = $htmlrenderer->render($renderable);
email_to_user($user, fullname($userfrom), html_entity_decode($subject), $message, $messagehtml,
$tempfile, $filename);
email_to_user($user, fullname($userfrom), $subject, $message, $messagehtml, $tempfile, $filename);
}
if ($customcert->emailteachers) {
@ -225,8 +216,8 @@ class email_certificate_task extends \core\task\scheduled_task {
$message = $textrenderer->render($renderable);
$messagehtml = $htmlrenderer->render($renderable);
foreach ($teachers as $teacher) {
email_to_user($teacher, fullname($userfrom), html_entity_decode($subject), $message, $messagehtml,
$tempfile, $filename);
email_to_user($teacher, fullname($userfrom), $subject, $message, $messagehtml, $tempfile,
$filename);
}
}
@ -245,8 +236,8 @@ class email_certificate_task extends \core\task\scheduled_task {
$emailuser = new \stdClass();
$emailuser->id = -1;
$emailuser->email = $email;
email_to_user($emailuser, fullname($userfrom), html_entity_decode($subject), $message,
$messagehtml, $tempfile, $filename);
email_to_user($emailuser, fullname($userfrom), $subject, $message, $messagehtml, $tempfile,
$filename);
}
}
}

View file

@ -18,19 +18,13 @@
* Class represents a customcert template.
*
* @package mod_customcert
* @copyright 2016 Mark Nelson <markn@moodle.com>, 2022 Kumi Systems e.U. <office@kumi.systems>
* @copyright 2016 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_customcert;
error_reporting(E_ALL);
require_once(__DIR__ . "/../vendor/autoload.php");
require_once($CFG->dirroot.'/user/profile/lib.php');
use mikehaertl\wkhtmlto\Pdf;
#defined('MOODLE_INTERNAL') || die();
defined('MOODLE_INTERNAL') || die();
/**
* Class represents a customcert template.
@ -56,8 +50,6 @@ class template {
*/
protected $contextid;
protected $html;
/**
* The constructor.
*
@ -67,7 +59,6 @@ class template {
$this->id = $template->id;
$this->name = $template->name;
$this->contextid = $template->contextid;
$this->html = $template->html;
}
/**
@ -262,8 +253,8 @@ class template {
* @param bool $return Do we want to return the contents of the PDF?
* @return string|void Can return the PDF in string format if specified.
*/
public function generate_pdf(bool $preview = false, int $userid = null, bool $return = false) {
global $CFG, $DB, $USER, $SITE;
public function generate_pdf($preview = false, $userid = null, $return = false) {
global $CFG, $DB, $USER;
if (empty($userid)) {
$user = $USER;
@ -273,34 +264,25 @@ class template {
require_once($CFG->libdir . '/pdflib.php');
profile_load_data($user);
// Get the pages for the template, there should always be at least one page for each template.
if ($pages = $DB->get_records('customcert_pages', array('templateid' => $this->id), 'sequence ASC')) {
// Create the pdf object.
$pdf = new \pdf();
$customcert = $DB->get_record('customcert', ['templateid' => $this->id]);
// If the template belongs to a certificate then we need to check what permissions we set for it.
if (!empty($customcert->protection)) {
$protection = explode(', ', $customcert->protection);
$pdf->SetProtection($protection);
if ($protection = $DB->get_field('customcert', 'protection', array('templateid' => $this->id))) {
if (!empty($protection)) {
$protection = explode(', ', $protection);
$pdf->SetProtection($protection);
}
}
if (empty($customcert->deliveryoption)) {
$deliveryoption = certificate::DELIVERY_OPTION_INLINE;
} else {
$deliveryoption = $customcert->deliveryoption;
}
// Remove full-stop at the end, if it exists, to avoid "..pdf" being created and being filtered by clean_filename.
$filename = rtrim(format_string($this->name, true, ['context' => $this->get_context()]), '.');
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);
$pdf->SetTitle($filename);
$pdf->SetTitle($this->name);
$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.
@ -321,91 +303,24 @@ class template {
$orientation = 'P';
}
$pdf->AddPage($orientation, array($page->width, $page->height));
if ($this->html) {
$pdf = new Pdf(array(
"disable-smart-shrinking",
"margin-bottom" => "0",
"margin-right" => "0",
"margin-left" => "0",
"margin-top" => "0"
));
$html = $this->html;
$context = \context_user::instance($user->id);
$fs = get_file_storage();
$files = $fs->get_area_files($context->id, 'user', 'icon', 0);
$file = null;
$content = "";
foreach ($files as $filefound) {
if (!$filefound->is_directory()) {
$file = $filefound;
break;
}
}
if ($file) {
$location = make_request_directory() . '/target';
$content = $file->get_content();
} else if ($preview) {
}
$html = str_replace("__PROFILEPIC__", 'data: ' . mime_content_type($file) . ';base64,' . $content, $html);
$html = str_replace("__NAME__", $user->firstname . " " . $user->lastname, $html);
if ($preview) {
$code = \mod_customcert\certificate::generate_code();
} else {
$issue = $DB->get_record('customcert_issues', array('userid' => $user->id, 'customcertid' => $customcert->id),
'*', IGNORE_MULTIPLE);
$code = $issue->code;
}
$html = str_replace("__CERTNUM__", $code, $html);
if ($preview) {
$courseid = $SITE->id;
} else {
$courseid = $customcert->course;
}
$course = get_course($courseid);
$coursename = $course->fullname;
$html = str_replace("__COURSE__", $coursename, $html);
$date = $issue->timecreated;
$html = str_replace("__DATE__", userdate($date, '%B %d, %Y'), $html);
$html = str_replace("__PIN__", $user->username, $html);
$pdf->addPage($html);
$pdf->send();
die($pdf->getError());
} else {
$pdf->SetMargins($page->leftmargin, 0, $page->rightmargin);
// Get the elements for the page.
if ($elements = $DB->get_records('customcert_elements', array('pageid' => $page->id), 'sequence ASC')) {
// Loop through and display.
foreach ($elements as $element) {
// Get an instance of the element class.
if ($e = \mod_customcert\element_factory::get_element_instance($element)) {
$e->render($pdf, $preview, $user);
}
}
}
}
$pdf->SetMargins($page->leftmargin, 0, $page->rightmargin);
// Get the elements for the page.
if ($elements = $DB->get_records('customcert_elements', array('pageid' => $page->id), 'sequence ASC')) {
// Loop through and display.
foreach ($elements as $element) {
// Get an instance of the element class.
if ($e = \mod_customcert\element_factory::get_element_instance($element)) {
$e->render($pdf, $preview, $user);
}
}
}
}
if ($return && !$this->html) {
if ($return) {
return $pdf->Output('', 'S');
}
if (!$this->html) {
$pdf->Output($filename, $deliveryoption);
}
$pdf->Output($filename, 'I');
}
}
@ -417,10 +332,6 @@ class template {
public function copy_to_template($copytotemplateid) {
global $DB;
$copytotemplate = $DB->get_record('customcert_templates', array('id' => $copytotemplateid));
$copytotemplate->html = $this->html;
$DB->update_record('customcert_templates', $copytotemplate);
// Get the pages for the template, there should always be at least one page for each template.
if ($templatepages = $DB->get_records('customcert_pages', array('templateid' => $this->id))) {
// Loop through the pages.
@ -513,10 +424,6 @@ class template {
return $this->name;
}
public function get_html() {
return $this->html;
}
/**
* Returns the context id.
*

View file

@ -2,8 +2,7 @@
"name": "mdjnelson/moodle-mod_customcert",
"type": "moodle-mod",
"require": {
"composer/installers": "~1.0",
"mikehaertl/phpwkhtmltopdf": "^2.5"
"composer/installers": "~1.0"
},
"extra": {
"installer-name": "customcert"

311
composer.lock generated
View file

@ -1,311 +0,0 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "749e39445f7c33f767b710400da4e9c6",
"packages": [
{
"name": "composer/installers",
"version": "v1.12.0",
"source": {
"type": "git",
"url": "https://github.com/composer/installers.git",
"reference": "d20a64ed3c94748397ff5973488761b22f6d3f19"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/composer/installers/zipball/d20a64ed3c94748397ff5973488761b22f6d3f19",
"reference": "d20a64ed3c94748397ff5973488761b22f6d3f19",
"shasum": ""
},
"require": {
"composer-plugin-api": "^1.0 || ^2.0"
},
"replace": {
"roundcube/plugin-installer": "*",
"shama/baton": "*"
},
"require-dev": {
"composer/composer": "1.6.* || ^2.0",
"composer/semver": "^1 || ^3",
"phpstan/phpstan": "^0.12.55",
"phpstan/phpstan-phpunit": "^0.12.16",
"symfony/phpunit-bridge": "^4.2 || ^5",
"symfony/process": "^2.3"
},
"type": "composer-plugin",
"extra": {
"class": "Composer\\Installers\\Plugin",
"branch-alias": {
"dev-main": "1.x-dev"
}
},
"autoload": {
"psr-4": {
"Composer\\Installers\\": "src/Composer/Installers"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Kyle Robinson Young",
"email": "kyle@dontkry.com",
"homepage": "https://github.com/shama"
}
],
"description": "A multi-framework Composer library installer",
"homepage": "https://composer.github.io/installers/",
"keywords": [
"Craft",
"Dolibarr",
"Eliasis",
"Hurad",
"ImageCMS",
"Kanboard",
"Lan Management System",
"MODX Evo",
"MantisBT",
"Mautic",
"Maya",
"OXID",
"Plentymarkets",
"Porto",
"RadPHP",
"SMF",
"Starbug",
"Thelia",
"Whmcs",
"WolfCMS",
"agl",
"aimeos",
"annotatecms",
"attogram",
"bitrix",
"cakephp",
"chef",
"cockpit",
"codeigniter",
"concrete5",
"croogo",
"dokuwiki",
"drupal",
"eZ Platform",
"elgg",
"expressionengine",
"fuelphp",
"grav",
"installer",
"itop",
"joomla",
"known",
"kohana",
"laravel",
"lavalite",
"lithium",
"magento",
"majima",
"mako",
"mediawiki",
"miaoxing",
"modulework",
"modx",
"moodle",
"osclass",
"pantheon",
"phpbb",
"piwik",
"ppi",
"processwire",
"puppet",
"pxcms",
"reindex",
"roundcube",
"shopware",
"silverstripe",
"sydes",
"sylius",
"symfony",
"tastyigniter",
"typo3",
"wordpress",
"yawik",
"zend",
"zikula"
],
"support": {
"issues": "https://github.com/composer/installers/issues",
"source": "https://github.com/composer/installers/tree/v1.12.0"
},
"funding": [
{
"url": "https://packagist.com",
"type": "custom"
},
{
"url": "https://github.com/composer",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/composer/composer",
"type": "tidelift"
}
],
"time": "2021-09-13T08:19:44+00:00"
},
{
"name": "mikehaertl/php-shellcommand",
"version": "1.6.4",
"source": {
"type": "git",
"url": "https://github.com/mikehaertl/php-shellcommand.git",
"reference": "3488d7803df1e8f1a343d3d0ca452d527ad8d5e5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/mikehaertl/php-shellcommand/zipball/3488d7803df1e8f1a343d3d0ca452d527ad8d5e5",
"reference": "3488d7803df1e8f1a343d3d0ca452d527ad8d5e5",
"shasum": ""
},
"require": {
"php": ">= 5.3.0"
},
"require-dev": {
"phpunit/phpunit": ">4.0 <=9.4"
},
"type": "library",
"autoload": {
"psr-4": {
"mikehaertl\\shellcommand\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Härtl",
"email": "haertl.mike@gmail.com"
}
],
"description": "An object oriented interface to shell commands",
"keywords": [
"shell"
],
"support": {
"issues": "https://github.com/mikehaertl/php-shellcommand/issues",
"source": "https://github.com/mikehaertl/php-shellcommand/tree/1.6.4"
},
"time": "2021-03-17T06:54:33+00:00"
},
{
"name": "mikehaertl/php-tmpfile",
"version": "1.2.1",
"source": {
"type": "git",
"url": "https://github.com/mikehaertl/php-tmpfile.git",
"reference": "70a5b70b17bc0d9666388e6a551ecc93d0b40a10"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/mikehaertl/php-tmpfile/zipball/70a5b70b17bc0d9666388e6a551ecc93d0b40a10",
"reference": "70a5b70b17bc0d9666388e6a551ecc93d0b40a10",
"shasum": ""
},
"require-dev": {
"php": ">=5.3.0",
"phpunit/phpunit": ">4.0 <=9.4"
},
"type": "library",
"autoload": {
"psr-4": {
"mikehaertl\\tmp\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Härtl",
"email": "haertl.mike@gmail.com"
}
],
"description": "A convenience class for temporary files",
"keywords": [
"files"
],
"support": {
"issues": "https://github.com/mikehaertl/php-tmpfile/issues",
"source": "https://github.com/mikehaertl/php-tmpfile/tree/1.2.1"
},
"time": "2021-03-01T18:26:25+00:00"
},
{
"name": "mikehaertl/phpwkhtmltopdf",
"version": "2.5.0",
"source": {
"type": "git",
"url": "https://github.com/mikehaertl/phpwkhtmltopdf.git",
"reference": "17ee71341591415d942774eda2c98d8ba7ea9e90"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/mikehaertl/phpwkhtmltopdf/zipball/17ee71341591415d942774eda2c98d8ba7ea9e90",
"reference": "17ee71341591415d942774eda2c98d8ba7ea9e90",
"shasum": ""
},
"require": {
"mikehaertl/php-shellcommand": "^1.5.0",
"mikehaertl/php-tmpfile": "^1.2.1",
"php": ">=5.0.0"
},
"require-dev": {
"phpunit/phpunit": ">4.0 <9.4"
},
"type": "library",
"autoload": {
"psr-4": {
"mikehaertl\\wkhtmlto\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Haertl",
"email": "haertl.mike@gmail.com"
}
],
"description": "A slim PHP wrapper around wkhtmltopdf with an easy to use and clean OOP interface",
"homepage": "http://mikehaertl.github.com/phpwkhtmltopdf/",
"keywords": [
"pdf",
"wkhtmltoimage",
"wkhtmltopdf"
],
"support": {
"issues": "https://github.com/mikehaertl/phpwkhtmltopdf/issues",
"source": "https://github.com/mikehaertl/phpwkhtmltopdf/tree/2.5.0"
},
"time": "2021-03-01T19:41:06+00:00"
}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": [],
"plugin-api-version": "2.0.0"
}

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="mod/customcert/db" VERSION="20211105" COMMENT="XMLDB file for Moodle mod/customcert"
<XMLDB PATH="mod/customcert/db" VERSION="20170530" COMMENT="XMLDB file for Moodle mod/customcert"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../lib/xmldb/xmldb.xsd"
>
@ -10,11 +10,10 @@
<FIELD NAME="course" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="templateid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="intro" TYPE="text" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="intro" TYPE="text" LENGTH="small" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="introformat" TYPE="int" LENGTH="4" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="requiredtime" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="verifyany" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="deliveryoption" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="emailstudents" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="emailteachers" TYPE="int" LENGTH="1" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="emailothers" TYPE="text" NOTNULL="false" SEQUENCE="false"/>
@ -34,7 +33,6 @@
<FIELD NAME="contextid" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="false" COMMENT="References contextid."/>
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="html" TYPE="text" NOTNULL="false" SEQUENCE="false"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="Primary key for customcert_template"/>
@ -78,7 +76,7 @@
<FIELD NAME="pageid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="name" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="element" TYPE="char" LENGTH="255" NOTNULL="true" SEQUENCE="false"/>
<FIELD NAME="data" TYPE="text" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="data" TYPE="text" LENGTH="big" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="font" TYPE="char" LENGTH="255" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="fontsize" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="colour" TYPE="char" LENGTH="50" NOTNULL="false" SEQUENCE="false"/>
@ -86,7 +84,6 @@
<FIELD NAME="posy" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="width" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="refpoint" TYPE="int" LENGTH="4" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="alignment" TYPE="char" LENGTH="1" NOTNULL="true" DEFAULT="L" SEQUENCE="false"/>
<FIELD NAME="sequence" TYPE="int" LENGTH="10" NOTNULL="false" SEQUENCE="false"/>
<FIELD NAME="timecreated" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>
<FIELD NAME="timemodified" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false"/>

View file

@ -1,5 +0,0 @@
{
"plugintypes": {
"customcertelement": "mod\/customcert\/element"
}
}

View file

@ -15,15 +15,13 @@
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Strings for component 'customcertelement_coursefield', language 'en'.
* Definition of sub-plugins.
*
* @package customcertelement_coursefield
* @copyright 2019 Catalyst IT
* @author Dan Marsden
* @package mod_customcert
* @copyright 2013 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$string['pluginname'] = 'Course field';
$string['privacy:metadata'] = 'The course field plugin does not store any personal data.';
$string['coursefield'] = 'Course field';
$string['coursefield_help'] = 'This is the course field that will be displayed on the PDF.';
defined('MOODLE_INTERNAL') || die();
$subplugins = array('customcertelement' => 'mod/customcert/element');

View file

@ -146,58 +146,5 @@ function xmldb_customcert_upgrade($oldversion) {
upgrade_mod_savepoint(true, 2018051705, 'customcert');
}
if ($oldversion < 2019111803) {
$table = new xmldb_table('customcert');
$index = new xmldb_index('templateid', XMLDB_INDEX_UNIQUE, ['templateid']);
if ($dbman->index_exists($table, $index)) {
$dbman->drop_index($table, $index);
}
$key = new xmldb_key('templateid', XMLDB_KEY_FOREIGN, ['templateid'], 'customcert_templates', ['id']);
$dbman->add_key($table, $key);
$table = new xmldb_table('customcert_pages');
$index = new xmldb_index('templateid', XMLDB_INDEX_UNIQUE, ['templateid']);
if ($dbman->index_exists($table, $index)) {
$dbman->drop_index($table, $index);
}
$key = new xmldb_key('templateid', XMLDB_KEY_FOREIGN, ['templateid'], 'customcert_templates', ['id']);
$dbman->add_key($table, $key);
upgrade_mod_savepoint(true, 2019111803, 'customcert');
}
if ($oldversion < 2020110901) {
$table = new xmldb_table('customcert');
$field = new xmldb_field('deliveryoption', XMLDB_TYPE_CHAR, '255', null, null, null, null, 'verifyany');
// Conditionally launch add field.
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
upgrade_mod_savepoint(true, 2020110901, 'customcert');
}
if ($oldversion < 2021051702) {
$table = new xmldb_table('customcert_elements');
$field = new xmldb_field('alignment', XMLDB_TYPE_CHAR, '1', null, XMLDB_NOTNULL, null, 'L', 'refpoint');
$dbman->add_field($table, $field);
upgrade_mod_savepoint(true, 2021051702, 'customcert');
}
if ($oldversion < 2021110501) {
$table = new xmldb_table('customcert_templates');
$field = new xmldb_field('html', XMLDB_TYPE_TEXT, null, null, null, null, null, 'timemodified');
// Conditionally launch add field html.
if (!$dbman->field_exists($table, $field)) {
$dbman->add_field($table, $field);
}
upgrade_mod_savepoint(true, 2021110501, 'customcert');
}
return true;
}

View file

@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
$plugin->version = 2021051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2021051700; // Requires this Moodle version (3.11).
$plugin->version = 2018051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2018051700; // Requires this Moodle version (3.5).
$plugin->component = 'customcertelement_bgimage';

View file

@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
$plugin->version = 2021051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2021051700; // Requires this Moodle version (3.11).
$plugin->version = 2018051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2018051700; // Requires this Moodle version (3.5).
$plugin->component = 'customcertelement_border';

View file

@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
$plugin->version = 2021051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2021051700; // Requires this Moodle version (3.11).
$plugin->version = 2018051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2018051700; // Requires this Moodle version (3.5).
$plugin->component = 'customcertelement_categoryname';

View file

@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
$plugin->version = 2021051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2021051700; // Requires this Moodle version (3.11).
$plugin->version = 2018051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2018051700; // Requires this Moodle version (3.5).
$plugin->component = 'customcertelement_code';

View file

@ -1,154 +0,0 @@
<?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 coursefield's core interaction API.
*
* @package customcertelement_coursefield
* @copyright 2019 Catalyst IT
* @author Dan Marsden
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace customcertelement_coursefield;
defined('MOODLE_INTERNAL') || die();
/**
* The customcert element coursefield's core interaction API.
*
* @package customcertelement_coursefield
* @copyright 2019 Catalyst IT
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class element extends \mod_customcert\element {
/**
* This function renders the form elements when adding a customcert element.
*
* @param \MoodleQuickForm $mform the edit form instance
*/
public function render_form_elements($mform) {
// Get the user profile fields.
$coursefields = array(
'fullname' => get_string('fullnamecourse'),
'shortname' => get_string('shortnamecourse'),
'idnumber' => get_string('idnumbercourse')
);
// Get the course custom fields.
$arrcustomfields = array();
$handler = \core_course\customfield\course_handler::create();
$customfields = $handler->get_fields();
foreach ($customfields as $field) {
$arrcustomfields[$field->get('id')] = $field->get_formatted_name();
}
// Combine the two.
$fields = $coursefields + $arrcustomfields;
\core_collator::asort($fields);
// Create the select box where the user field is selected.
$mform->addElement('select', 'coursefield', get_string('coursefield', 'customcertelement_coursefield'), $fields);
$mform->setType('coursefield', PARAM_ALPHANUM);
$mform->addHelpButton('coursefield', 'coursefield', 'customcertelement_coursefield');
parent::render_form_elements($mform);
}
/**
* 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 text
*/
public function save_unique_data($data) {
return $data->coursefield;
}
/**
* 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) {
$courseid = \mod_customcert\element_helper::get_courseid($this->id);
$course = get_course($courseid);
\mod_customcert\element_helper::render_content($pdf, $this, $this->get_course_field_value($course, $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 $COURSE;
return \mod_customcert\element_helper::render_html_content($this, $this->get_course_field_value($COURSE, 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('coursefield');
$element->setValue($this->get_data());
}
parent::definition_after_data($mform);
}
/**
* Helper function that returns the field value in a human-readable format.
*
* @param \stdClass $course the course we are rendering this for
* @param bool $preview Is this a preview?
* @return string
*/
protected function get_course_field_value(\stdClass $course, bool $preview) : string {
// 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.
if ($preview) {
$value = $field;
} else {
$value = '';
}
if (is_number($field)) { // Must be a custom course profile field.
$handler = \core_course\customfield\course_handler::create();
$data = $handler->get_instance_data($course->id, true);
if (!empty($data[$field])) {
$value = $data[$field]->export_value();
}
} else if (!empty($course->$field)) { // Field in the course table.
$value = $course->$field;
}
$context = \mod_customcert\element_helper::get_context($this->get_id());
return format_string($value, true, ['context' => $context]);
}
}

View file

@ -1,47 +0,0 @@
<?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_coursefield.
*
* @package customcertelement_coursefield
* @copyright 2019 Catalyst IT
* @author Dan Marsden
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace customcertelement_coursefield\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for customcertelement_coursefield implementing null_provider.
*
* @copyright 2019 Catalyst IT
* @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';
}
}

View file

@ -1,30 +0,0 @@
<?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 coursefield plugin.
*
* @package customcertelement_coursefield
* @copyright 2019 Catalyst IT
* @author Dan Marsden
* @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 = 2021051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2021051700; // Requires this Moodle version (3.11).
$plugin->component = 'customcertelement_coursefield';

View file

@ -35,42 +35,6 @@ defined('MOODLE_INTERNAL') || die();
*/
class element extends \mod_customcert\element {
/**
* The course short name.
*/
const COURSE_SHORT_NAME = 1;
/**
* The course fullname.
*/
const COURSE_FULL_NAME = 2;
/**
* This function renders the form elements when adding a customcert element.
*
* @param \MoodleQuickForm $mform the edit_form instance
*/
public function render_form_elements($mform) {
// The course name display options.
$mform->addElement('select', 'coursenamedisplay', get_string('coursenamedisplay', 'customcertelement_coursename'),
self::get_course_name_display_options());
$mform->setType('coursenamedisplay', PARAM_INT);
$mform->addHelpButton('coursenamedisplay', 'coursenamedisplay', 'customcertelement_coursename');
parent::render_form_elements($mform);
}
/**
* 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 text
*/
public function save_unique_data($data) {
return $data->coursenamedisplay;
}
/**
* Handles rendering the element on the pdf.
*
@ -79,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, $this->get_course_name_detail());
\mod_customcert\element_helper::render_content($pdf, $this, $this->get_course_name());
}
/**
@ -91,52 +55,19 @@ class element extends \mod_customcert\element {
* @return string the html
*/
public function render_html() {
return \mod_customcert\element_helper::render_html_content($this, $this->get_course_name_detail());
return \mod_customcert\element_helper::render_html_content($this, $this->get_course_name());
}
/**
* 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('coursenamedisplay');
$element->setValue($this->get_data());
}
parent::definition_after_data($mform);
}
/**
* Helper function that returns the selected course name detail (i.e. name or short description) for display.
* Helper function that returns the category name.
*
* @return string
*/
protected function get_course_name_detail(): 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());
// The name field to display.
$field = $this->get_data();
// The name value to display.
$value = $course->fullname;
if ($field == self::COURSE_SHORT_NAME) {
$value = $course->shortname;
}
return format_string($value, true, ['context' => $context]);
}
/**
* Helper function to return all the possible name display options.
*
* @return array returns an array of name options
*/
public static function get_course_name_display_options(): array {
return [
self::COURSE_FULL_NAME => get_string('coursefullname', 'customcertelement_coursename'),
self::COURSE_SHORT_NAME => get_string('courseshortname', 'customcertelement_coursename')
];
return format_string($course->fullname, true, ['context' => $context]);
}
}

View file

@ -22,10 +22,5 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$string['coursenamedisplay'] = 'Type';
$string['coursenamedisplay_help'] = 'Display the course full name or short name?';
$string['coursefullname'] = 'Full name';
$string['courseshortname'] = 'Short name';
$string['pluginname'] = 'Course name';
$string['privacy:metadata'] = 'The Course name plugin does not store any personal data.';

View file

@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
$plugin->version = 2021051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2021051700; // Requires this Moodle version (3.11).
$plugin->version = 2018051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2018051700; // Requires this Moodle version (3.5).
$plugin->component = 'customcertelement_coursename';

View file

@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
$plugin->version = 2021051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2021051700; // Requires this Moodle version (3.11).
$plugin->version = 2018051701; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2018051700; // Requires this Moodle version (3.5).
$plugin->component = 'customcertelement_date';

View file

@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
$plugin->version = 2021051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2021051700; // Requires this Moodle version (3.11).
$plugin->version = 2018051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2018051700; // Requires this Moodle version (3.5).
$plugin->component = 'customcertelement_daterange';

View file

@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
$plugin->version = 2021051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2021051700; // Requires this Moodle version (3.11).
$plugin->version = 2018051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2018051700; // Requires this Moodle version (3.5).
$plugin->component = 'customcertelement_digitalsignature';

View file

@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
$plugin->version = 2021051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2021051700; // Requires this Moodle version (3.11).
$plugin->version = 2018051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2018051700; // Requires this Moodle version (3.5).
$plugin->component = 'customcertelement_grade';

View file

@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
$plugin->version = 2021051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2021051700; // Requires this Moodle version (3.11).
$plugin->version = 2018051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2018051700; // Requires this Moodle version (3.5).
$plugin->component = 'customcertelement_gradeitemname';

View file

@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
$plugin->version = 2021051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2021051700; // Requires this Moodle version (3.11).
$plugin->version = 2018051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2018051700; // Requires this Moodle version (3.5).
$plugin->component = 'customcertelement_image';

View file

@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
$plugin->version = 2021051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2021051700; // Requires this Moodle version (3.11).
$plugin->version = 2018051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2018051700; // Requires this Moodle version (3.5).
$plugin->component = 'customcertelement_qrcode';

View file

@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
$plugin->version = 2021051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2021051700; // Requires this Moodle version (3.11).
$plugin->version = 2018051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2018051700; // Requires this Moodle version (3.5).
$plugin->component = 'customcertelement_studentname';

View file

@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
$plugin->version = 2021051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2021051700; // Requires this Moodle version (3.11).
$plugin->version = 2018051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2018051700; // Requires this Moodle version (3.5).
$plugin->component = 'customcertelement_teachername';

View file

@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
$plugin->version = 2021051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2021051700; // Requires this Moodle version (3.11).
$plugin->version = 2018051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2018051700; // Requires this Moodle version (3.5).
$plugin->component = 'customcertelement_text';

View file

@ -24,8 +24,6 @@
namespace customcertelement_userfield;
use core_user\fields;
defined('MOODLE_INTERNAL') || die();
/**
@ -45,20 +43,24 @@ class element extends \mod_customcert\element {
public function render_form_elements($mform) {
// Get the user profile fields.
$userfields = array(
'firstname' => fields::get_display_name('firstname'),
'lastname' => fields::get_display_name('lastname'),
'username' => fields::get_display_name('username'),
'email' => fields::get_display_name('email'),
'city' => fields::get_display_name('city'),
'country' => fields::get_display_name('country'),
'url' => fields::get_display_name('url'),
'skype' => fields::get_display_name('skype'),
'idnumber' => fields::get_display_name('idnumber'),
'institution' => fields::get_display_name('institution'),
'department' => fields::get_display_name('department'),
'phone1' => fields::get_display_name('phone1'),
'phone2' => fields::get_display_name('phone2'),
'address' => fields::get_display_name('address')
'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'),
'url' => get_user_field_name('url'),
'icq' => get_user_field_name('icq'),
'skype' => get_user_field_name('skype'),
'aim' => get_user_field_name('aim'),
'yahoo' => get_user_field_name('yahoo'),
'msn' => get_user_field_name('msn'),
'idnumber' => get_user_field_name('idnumber'),
'institution' => get_user_field_name('institution'),
'department' => get_user_field_name('department'),
'phone1' => get_user_field_name('phone1'),
'phone2' => get_user_field_name('phone2'),
'address' => get_user_field_name('address')
);
// Get the user custom fields.
$arrcustomfields = \availability_profile\condition::get_custom_profile_fields();

View file

@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
$plugin->version = 2021051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2021051700; // Requires this Moodle version (3.11).
$plugin->version = 2018051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2018051700; // Requires this Moodle version (3.5).
$plugin->component = 'customcertelement_userfield';

View file

@ -24,6 +24,6 @@
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
$plugin->version = 2021051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2021051700; // Requires this Moodle version (3.11).
$plugin->version = 2018051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2018051700; // Requires this Moodle version (3.5).
$plugin->component = 'customcertelement_userpicture';

View file

@ -25,11 +25,6 @@
$string['activity'] = 'Activity';
$string['addcertpage'] = 'Add page';
$string['addelement'] = 'Add element';
$string['aligncenter'] = 'Centered';
$string['alignleft'] = 'Left alignment';
$string['alignment'] = 'Alignment';
$string['alignment_help'] = 'This property sets the horizontal alignment of the element. Some elements may not support this, while the behaviour of others may differ.';
$string['alignright'] = 'Right alignment';
$string['awardedto'] = 'Awarded to';
$string['cannotverifyallcertificates'] = 'You do not have the permission to verify all certificates on the site.';
$string['certificate'] = 'Certificate';
@ -62,9 +57,6 @@ $string['deleteissueconfirm'] = 'Are you sure you want to delete this certificat
$string['deleteissuedcertificates'] = 'Delete issued certificates';
$string['deletepageconfirm'] = 'Are you sure you want to delete this certificate page?';
$string['deletetemplateconfirm'] = 'Are you sure you want to delete this certificate template?';
$string['deliveryoptiondownload'] = 'Send to the browser and force a file download';
$string['deliveryoptioninline'] = 'Send the file inline to the browser';
$string['deliveryoptions'] = 'Delivery options';
$string['description'] = 'Description';
$string['duplicate'] = 'Duplicate';
$string['duplicateconfirm'] = 'Duplicate confirmation';

View file

@ -264,8 +264,6 @@ function customcert_supports($feature) {
return true;
case FEATURE_MOD_INTRO:
return true;
case FEATURE_SHOW_DESCRIPTION:
return true;
case FEATURE_COMPLETION_TRACKS_VIEWS:
return true;
case FEATURE_BACKUP_MOODLE2:

View file

@ -97,4 +97,4 @@ $PAGE->navbar->add(get_string('loadtemplate', 'customcert'));
echo $OUTPUT->header();
echo $OUTPUT->heading($heading);
echo $OUTPUT->confirm(get_string('loadtemplatemsg', 'customcert'), $yesurl, $nourl);
echo $OUTPUT->footer();
echo $OUTPUT->footer();

View file

@ -1,57 +0,0 @@
<?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/>.
define('CLI_SCRIPT', true);
require_once('../../config.php');
$tid = $argv[1];
$ltid = $argv[2];
$template = $DB->get_record('customcert_templates', array('id' => $tid), '*', MUST_EXIST);
$template = new \mod_customcert\template($template);
$loadtemplate = $DB->get_record('customcert_templates', array('id' => $ltid), '*', MUST_EXIST);
$loadtemplate = new \mod_customcert\template($loadtemplate);
$cm = $template->get_cm();
if ($template->get_context()->contextlevel == CONTEXT_MODULE) {
$customcert = $DB->get_record('customcert', ['id' => $cm->instance], '*', MUST_EXIST);
$title = $customcert->name;
$heading = format_string($title);
} else {
$title = $SITE->fullname;
$heading = $title;
}
$sql = "SELECT e.*
FROM {customcert_elements} e
INNER JOIN {customcert_pages} p
ON e.pageid = p.id
WHERE p.templateid = :templateid";
if ($elements = $DB->get_records_sql($sql, array('templateid' => $template->get_id()))) {
foreach ($elements as $element) {
if ($e = \mod_customcert\element_factory::get_element_instance($element)) {
$e->delete();
}
}
}
$DB->delete_records('customcert_pages', array('templateid' => $template->get_id()));
$loadtemplate->copy_to_template($template->get_id());

View file

@ -47,6 +47,7 @@ require_login();
require_capability('mod/customcert:manage', $context);
$title = $SITE->fullname;
$heading = $title;
// Set up the page.
$pageurl = new moodle_url('/mod/customcert/manage_templates.php');
@ -60,8 +61,6 @@ if ($tid && $action && confirm_sesskey()) {
$PAGE->navbar->add(get_string('managetemplates', 'customcert'));
}
$heading = format_string($title, true, ['context' => $context]);
if ($tid) {
if ($action && confirm_sesskey()) {
$nourl = new moodle_url('/mod/customcert/manage_templates.php');

View file

@ -22,8 +22,6 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
use mod_customcert\certificate;
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
require_once($CFG->dirroot.'/course/moodleform_mod.php');
@ -57,20 +55,14 @@ class mod_customcert_mod_form extends moodleform_mod {
$this->standard_intro_elements(get_string('description', 'customcert'));
$mform->addElement('header', 'options', get_string('options', 'customcert'));
$deliveryoptions = [
certificate::DELIVERY_OPTION_INLINE => get_string('deliveryoptioninline', 'customcert'),
certificate::DELIVERY_OPTION_DOWNLOAD => get_string('deliveryoptiondownload', 'customcert')
];
$mform->addElement('select', 'deliveryoption', get_string('deliveryoptions', 'customcert'), $deliveryoptions);
$mform->setDefault('deliveryoption', certificate::DELIVERY_OPTION_INLINE);
$optionsheader = $mform->createElement('header', 'options', get_string('options', 'customcert'));
if (has_capability('mod/customcert:manageemailstudents', $this->get_context())) {
$mform->addElement('selectyesno', 'emailstudents', get_string('emailstudents', 'customcert'));
$mform->setDefault('emailstudents', get_config('customcert', 'emailstudents'));
$mform->addHelpButton('emailstudents', 'emailstudents', 'customcert');
$mform->setType('emailstudents', PARAM_INT);
$firstoption = 'emailstudents';
}
if (has_capability('mod/customcert:manageemailteachers', $this->get_context())) {
@ -78,6 +70,7 @@ class mod_customcert_mod_form extends moodleform_mod {
$mform->setDefault('emailteachers', get_config('customcert', 'emailteachers'));
$mform->addHelpButton('emailteachers', 'emailteachers', 'customcert');
$mform->setType('emailteachers', PARAM_INT);
$firstoption = empty($firstoption) ? 'emailteachers' : $firstoption;
}
if (has_capability('mod/customcert:manageemailothers', $this->get_context())) {
@ -85,6 +78,7 @@ class mod_customcert_mod_form extends moodleform_mod {
$mform->addHelpButton('emailothers', 'emailothers', 'customcert');
$mform->setDefault('emailothers', get_config('customcert', 'emailothers'));
$mform->setType('emailothers', PARAM_TEXT);
$firstoption = empty($firstoption) ? 'emailothers' : $firstoption;
}
if (has_capability('mod/customcert:manageverifyany', $this->get_context())) {
@ -92,6 +86,7 @@ class mod_customcert_mod_form extends moodleform_mod {
$mform->addHelpButton('verifyany', 'verifycertificateanyone', 'customcert');
$mform->setDefault('verifyany', get_config('customcert', 'verifyany'));
$mform->setType('verifyany', PARAM_INT);
$firstoption = empty($firstoption) ? 'verifyany' : $firstoption;
}
if (has_capability('mod/customcert:managerequiredtime', $this->get_context())) {
@ -99,6 +94,7 @@ class mod_customcert_mod_form extends moodleform_mod {
$mform->addHelpButton('requiredtime', 'coursetimereq', 'customcert');
$mform->setDefault('requiredtime', get_config('customcert', 'requiredtime'));
$mform->setType('requiredtime', PARAM_INT);
$firstoption = empty($firstoption) ? 'requiredtime' : $firstoption;
}
if (has_capability('mod/customcert:manageprotection', $this->get_context())) {
@ -110,6 +106,11 @@ class mod_customcert_mod_form extends moodleform_mod {
$mform->setType('protection_print', PARAM_BOOL);
$mform->setType('protection_modify', PARAM_BOOL);
$mform->setType('protection_copy', PARAM_BOOL);
$firstoption = empty($firstoption) ? 'protection_print' : $firstoption;
}
if (!empty($firstoption)) {
$mform->insertElementBefore($optionsheader, $firstoption);
}
$this->standard_coursemodule_elements();
@ -226,13 +227,13 @@ class mod_customcert_mod_form extends moodleform_mod {
$protection = explode(', ', $protection);
if (in_array(certificate::PROTECTION_PRINT, $protection)) {
if (in_array(\mod_customcert\certificate::PROTECTION_PRINT, $protection)) {
$data->protection_print = 1;
}
if (in_array(certificate::PROTECTION_MODIFY, $protection)) {
if (in_array(\mod_customcert\certificate::PROTECTION_MODIFY, $protection)) {
$data->protection_modify = 1;
}
if (in_array(certificate::PROTECTION_COPY, $protection)) {
if (in_array(\mod_customcert\certificate::PROTECTION_COPY, $protection)) {
$data->protection_copy = 1;
}

View file

@ -49,15 +49,9 @@ $user = \core_user::get_user($userid, '*', MUST_EXIST);
// If we are viewing certificates that are not for the currently logged in user then do a capability check.
if (($userid != $USER->id) && !has_capability('mod/customcert:viewallcertificates', context_system::instance())) {
throw new moodle_exception('You are not allowed to view these certificates');
print_error('You are not allowed to view these certificates');
}
$PAGE->set_url($pageurl);
$PAGE->set_context(context_user::instance($userid));
$PAGE->set_title(get_string('mycertificates', 'customcert'));
$PAGE->set_pagelayout('standard');
$PAGE->navigation->extend_for_user($user);
// Check if we requested to download a certificate.
if ($downloadcert) {
$template = $DB->get_record('customcert_templates', array('id' => $customcert->templateid), '*', MUST_EXIST);
@ -74,6 +68,12 @@ if ($table->is_downloading()) {
exit();
}
$PAGE->set_url($pageurl);
$PAGE->set_context(context_user::instance($userid));
$PAGE->set_title(get_string('mycertificates', 'customcert'));
$PAGE->set_pagelayout('standard');
$PAGE->navigation->extend_for_user($user);
// Additional page setup.
$PAGE->navbar->add(get_string('profile'), new moodle_url('/user/profile.php', array('id' => $userid)));
$PAGE->navbar->add(get_string('mycertificates', 'customcert'));

View file

@ -112,18 +112,6 @@ if ($elements) {
default:
$class = 'element refpoint-left';
}
switch ($element->alignment) {
case \mod_customcert\element::ALIGN_CENTER:
$class .= ' align-center';
break;
case \mod_customcert\element::ALIGN_RIGHT:
$class .= ' align-right';
break;
case \mod_customcert\element::ALIGN_LEFT:
default:
$class .= ' align-left';
break;
}
$html .= html_writer::tag('div', $e->render_html(), array('class' => $class,
'data-refpoint' => $element->refpoint, 'id' => 'element-' . $element->id));
}

View file

@ -57,18 +57,6 @@
margin: -4px -5px -5px 4px;
}
#page-mod-customcert-rearrange .element.align-left {
text-align: left;
}
#page-mod-customcert-rearrange .element.align-center {
text-align: center;
}
#page-mod-customcert-rearrange .element.align-right {
text-align: right;
}
#page-mod-customcert-rearrange #pdf {
border-style: solid;
border-width: 1px;

View file

@ -1,169 +0,0 @@
{{!
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/>.
}}
{{!
@template mod_customcert/mobile_view_activity_page
The main page to view the custom certificate activity
Classes required for JS:
* None
Data attibutes required for JS:
* All data attributes are required
Context variables required for this template:
* certificate
* cmid
* hasissues
* issues
* showgroups
* groups
* canmanage
* requiredtimemet
* hasrecipients
* recipients
* fileurl
* showreport
* currenttimestamp
Example context (json):
{
"certificate": {
"id": "1",
"course": "2",
"name": "A rad certificate name!",
"intro": "A certificate",
"requiredtime": "60"
},
"cmid": "25",
"issue": {
"timecreated": "1528370177"
},
"showgroups": "true",
"groups": [
{
"id": "2",
"selected": "false",
"name": "Group A"
}
],
"canmanage": "true",
"requiredtimemet": "true",
"fileurl": "http://yoursite.com/mod/customcert/mobile/pluginfile.php?id=4",
"showreport": "true",
"hasrecipients": "true",
"recipients": [
{
"id": "2",
"issueid": "3",
"displayname": "Michaelangelo (Mickey)",
"fileurl": "http://yoursite.com/mod/customcert/mobile/pluginfile.php?id=4",
"timecreated": "1528370177"
}
],
"currenttimestamp": "1528370177"
}
}}
{{=<% %>=}}
<core-course-module-description description="<% certificate.intro %>" component="mod_customcert" componentId="<% cmid %>"></core-course-module-description>
<ion-list>
<%^canmanage%>
<%#requiredtimemet%>
<ion-item>
<ion-label>
{{ 'plugin.mod_customcert.receiveddate' | translate }}
<br />
<div class="timerewarded">
<%#issue%>
{{ <% timecreated %> | coreToLocaleString }}
<%/issue%>
<%^issue%>
{{ 'plugin.mod_customcert.notissued' | translate }}
<%/issue%>
</div>
</ion-label>
<div slot="end" class="flex-row">
<ion-button fill="clear" [core-download-file]="{fileurl: '<% fileurl %>', timemodified: '<% currenttimestamp %>'}" moduleId="<% cmid %>" courseId="<% certificate.course %>" component="mod_customcert" [attr.aria-label]="'core.download' | translate">
<ion-icon name="cloud-download" slot="icon-only" aria-hidden="true"></ion-icon>
</ion-button>
</div>
</ion-item>
<%/requiredtimemet%>
<%^requiredtimemet%>
<ion-item>
<ion-label>
<p>{{ 'plugin.mod_customcert.requiredtimenotmet' | translate: {$a: { requiredtime: <% certificate.requiredtime %>} } }}</p>
</ion-label>
</ion-item>
<%/requiredtimemet%>
<%/canmanage%>
<%#canmanage%>
<ion-button expand="block" class="ion-margin" core-course-download-module-main-file moduleId="<% cmid %>" courseId="<% certificate.course %>" component="mod_customcert" [files]="[{fileurl: '<% fileurl %>', timemodified: '<% currenttimestamp %>'}]">
<ion-icon name="cloud-download" slot="start" aria-hidden="true"></ion-icon>
{{ 'plugin.mod_customcert.getcustomcert' | translate }}
</ion-button>
<%/canmanage%>
<%#showreport%>
<ion-item>
<ion-label>
{{ 'plugin.mod_customcert.listofissues' | translate: { $a: <% numrecipients %> } }}
</ion-label>
</ion-item>
<%#showgroups%>
<ion-item>
<ion-label>{{ 'plugin.mod_customcert.selectagroup' | translate }}</ion-label>
<ion-select [(ngModel)]="CONTENT_OTHERDATA.group" name="group" (ionChange)="updateContent({cmid: <% cmid %>, courseid: <% certificate.course %>, group: CONTENT_OTHERDATA.group})" interface="popover">
<%#groups%>
<ion-select-option [value]="<% id %>"><% name %></ion-select-option>
<%/groups%>
</ion-select>
</ion-item>
<%/showgroups%>
<%#hasrecipients%>
<%#recipients%>
<ion-item>
<ion-label>
<% displayname %>
<br />
<div class="timerewarded">{{ <% timecreated %> | coreToLocaleString }}</div>
</ion-label>
<div slot="end" class="flex-row">
<ion-button fill="clear" [core-download-file]="{fileurl: '<% fileurl %>', timemodified: '<% currenttimestamp %>'}" moduleId="<% cmid %>" courseId="<% certificate.course %>" component="mod_customcert" [attr.aria-label]="'core.download' | translate">
<ion-icon name="cloud-download" slot="icon-only" aria-hidden="true"></ion-icon>
</ion-button>
<%#canmanage%>
<ion-button fill="clear" core-site-plugins-call-ws name="mod_customcert_delete_issue"
[params]="{certificateid: <% certificate.id %>, issueid: <% issueid %>}"
[preSets]="{getFromCache: 0, saveToCache: 0, typeExpected: 'boolean'}"
confirmMessage="{{ 'plugin.mod_customcert.deleteissueconfirm' | translate }}"
refreshOnSuccess="true" [attr.aria-label]="'core.delete' | translate">
<ion-icon name="fas-trash" slot="icon-only" aria-hidden="true"></ion-icon>
</ion-button>
<%/canmanage%>
</div>
</ion-item>
<%/recipients%>
<%/hasrecipients%>
<%^hasrecipients%>
<ion-item>
<ion-label>
{{ 'plugin.mod_customcert.nothingtodisplay' | translate }}
</ion-label>
</ion-item>
<%/hasrecipients%>
<%/showreport%>
</ion-list>

View file

@ -8,9 +8,11 @@ Feature: Being able to correctly display options on the certificate activity edi
And the following "users" exist:
| username | firstname | lastname | email |
| teacher1 | Teacher | 1 | teacher1@example.com |
| manager1 | Manager | 1 | Manager1@example.com |
And the following "course enrolments" exist:
| user | course | role |
| teacher1 | C1 | editingteacher |
| manager1 | C1 | manager |
And the following "activities" exist:
| activity | name | intro | course | idnumber |
| customcert | Custom certificate 1 | Custom certificate 1 intro | C1 | customcert1 |
@ -27,7 +29,40 @@ Feature: Being able to correctly display options on the certificate activity edi
And I should see "Required minutes in course"
And I should see "Set protection"
@javascript
Scenario: Create an activity as an Editing Teacher I can see all custom certificate options
And I log in as "teacher1"
And I am on "Course 1" course homepage with editing mode on
And I add a "Custom certificate" to section "1"
And I should see "Email students"
And I should see "Email teachers"
And I should see "Email others"
And I should see "Allow anyone to verify a certificate"
And I should see "Required minutes in course"
And I should see "Set protection"
Scenario: Add an activity as a Manager I can see all custom certificate options
And I log in as "manager1"
And I am on "Course 1" course homepage with editing mode on
And I add a "Custom certificate" to section "1"
And I should see "Email students"
And I should see "Email teachers"
And I should see "Email others"
And I should see "Allow anyone to verify a certificate"
And I should see "Required minutes in course"
And I should see "Set protection"
Scenario: Edit an activity as a Manager Teacher I can see all custom certificate options
And I log in as "manager1"
And I am on "Course 1" course homepage with editing mode on
And I follow "Custom certificate 1"
And I navigate to "Edit settings" in current page administration
And I should see "Email students"
And I should see "Email teachers"
And I should see "Email others"
And I should see "Allow anyone to verify a certificate"
And I should see "Required minutes in course"
And I should see "Set protection"
Scenario: Create an activity as an Editing Teacher without required capabilities I can't see all custom certificate options
And I log in as "admin"
And I set the following system permissions of "Teacher" role:
@ -71,9 +106,8 @@ Feature: Being able to correctly display options on the certificate activity edi
And I should not see "Required minutes in course"
And I should not see "Set protection"
@javascript
Scenario: Add an activity using default custom certificate options
And I log in as "teacher1"
And I log in as "manager1"
And I am on "Course 1" course homepage with editing mode on
And I add a "Custom certificate" to section "0"
And the field "emailstudents" matches value "0"
@ -85,7 +119,6 @@ Feature: Being able to correctly display options on the certificate activity edi
And the field "protection_modify" matches value "0"
And the field "protection_copy" matches value "0"
@javascript
Scenario: Add an activity using configured custom certificate options
And the following config values are set as admin:
| emailstudents | 1 | customcert |
@ -96,7 +129,7 @@ Feature: Being able to correctly display options on the certificate activity edi
| protection_print | 1 | customcert |
| protection_modify | 1 | customcert |
| protection_copy | 1 | customcert |
And I log in as "teacher1"
And I log in as "manager1"
And I am on "Course 1" course homepage with editing mode on
And I add a "Custom certificate" to section "1"
And the field "emailstudents" matches value "1"

View file

@ -40,7 +40,7 @@ class behat_mod_customcert extends behat_base {
/**
* Adds an element to the specified page of a template.
*
* phpcs:ignore
* @codingStandardsIgnoreLine
* @Given /^I add the element "(?P<element_name>(?:[^"]|\\")*)" to page "(?P<page_number>\d+)" of the "(?P<template_name>(?:[^"]|\\")*)" certificate template$/
* @param string $elementname
* @param int $pagenum

View file

@ -79,43 +79,23 @@ Feature: Being able to manage elements in a certificate template
| Width | 20 |
| Reference point location | Top left |
And I press "Save changes"
# Course field.
And I add the element "Course field" to page "1" of the "Custom certificate 1" certificate template
And I set the following fields to these values:
| Font | Helvetica |
| Size | 20 |
| Colour | #045ECD |
| Width | 20 |
| Reference point location | Top left |
And I press "Save changes"
And I should see "Course field" in the "elementstable" "table"
And I click on ".edit-icon" "css_element" in the "Course field" "table_row"
And the following fields match these values:
| Font | Helvetica |
| Size | 20 |
| Colour | #045ECD |
| Width | 20 |
| Reference point location | Top left |
And I press "Save changes"
# Course name.
And I add the element "Course name" to page "1" of the "Custom certificate 1" certificate template
And I set the following fields to these values:
| Font | Helvetica |
| Type | Short name |
| Size | 20 |
| Colour | #045ECD |
| Width | 20 |
| Reference point location | Top left |
| Font | Helvetica |
| Size | 20 |
| Colour | #045ECD |
| Width | 20 |
| Reference point location | Top left |
And I press "Save changes"
And I should see "Course name" in the "elementstable" "table"
And I click on ".edit-icon" "css_element" in the "Course name" "table_row"
And the following fields match these values:
| Font | Helvetica |
| Type | Short name |
| Size | 20 |
| Colour | #045ECD |
| Width | 20 |
| Reference point location | Top left |
| Font | Helvetica |
| Size | 20 |
| Colour | #045ECD |
| Width | 20 |
| Reference point location | Top left |
And I press "Save changes"
# Date.
And I add the element "Date" to page "1" of the "Custom certificate 1" certificate template

View file

@ -21,8 +21,6 @@ Feature: Being able to view the certificates that have been issued
And the following "activities" exist:
| activity | name | intro | course | idnumber |
| customcert | Custom certificate 1 | Custom certificate 1 intro | C1 | customcert1 |
And the following config values are set as admin:
| showuseridentity | username,email |
Scenario: View the issued certificates
And I log in as "student1"
@ -40,12 +38,6 @@ Feature: Being able to view the certificates that have been issued
And I follow "Custom certificate 1"
And I should see "Student 1"
And I should see "Student 2"
And I should see "Email address"
And I should see "Username"
And "Student 1" row "Email address" column of "generaltable" table should contain "student1@example.com"
And "Student 1" row "Username" column of "generaltable" table should contain "student1"
And "Student 2" row "Email address" column of "generaltable" table should contain "student2@example.com"
And "Student 2" row "Username" column of "generaltable" table should contain "student2"
Scenario: Delete an issued certificate
And I log in as "student1"

View file

@ -40,7 +40,7 @@ class mod_customcert_element_helper_testcase extends advanced_testcase {
/**
* Test set up.
*/
public function setUp(): void {
public function setUp() {
$this->resetAfterTest();
}

View file

@ -38,7 +38,7 @@ class mod_customcert_task_email_certificate_task_testcase extends advanced_testc
/**
* Test set up.
*/
public function setUp(): void {
public function setUp() {
$this->resetAfterTest();
}
@ -55,7 +55,7 @@ class mod_customcert_task_email_certificate_task_testcase extends advanced_testc
// Create a custom certificate with no elements.
$this->getDataGenerator()->create_module('customcert', ['course' => $course->id, 'emailstudents' => 1]);
// Enrol the user as a student.
// Enrol the user as a student
$this->getDataGenerator()->enrol_user($user1->id, $course->id);
// Run the task.
@ -416,4 +416,4 @@ class mod_customcert_task_email_certificate_task_testcase extends advanced_testc
// Confirm no emails were sent.
$this->assertCount(0, $emails);
}
}
}

View file

@ -40,7 +40,7 @@ class mod_customcert_external_test_testcase extends advanced_testcase {
/**
* Test set up.
*/
public function setUp(): void {
public function setUp() {
$this->resetAfterTest();
}

View file

@ -98,9 +98,9 @@ class mod_customcert_privacy_provider_testcase extends \core_privacy\tests\provi
// Check this time there are 2 users.
$this->assertCount(2, $userlist->get_userids());
$this->assertContains((int) $user1->id, $userlist->get_userids());
$this->assertContains((int) $user2->id, $userlist->get_userids());
$this->assertNotContains((int) $user3->id, $userlist->get_userids());
$this->assertContains($user1->id, $userlist->get_userids());
$this->assertContains($user2->id, $userlist->get_userids());
$this->assertNotContains($user3->id, $userlist->get_userids());
}
/**

View file

@ -93,7 +93,7 @@ if ($code) {
$result->issues = array();
// Ok, now check if the code is valid.
$userfields = \mod_customcert\helper::get_all_user_name_fields('u');
$userfields = get_all_user_name_fields(true, 'u');
$sql = "SELECT ci.id, u.id as userid, $userfields, co.id as courseid,
co.fullname as coursefullname, c.id as certificateid,
c.name as certificatename, c.verifyany

View file

@ -24,10 +24,10 @@
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
$plugin->version = 2021110501; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2021051700; // Requires this Moodle version (3.11).
$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.11.1-seachefs"; // User-friendly version number.
$plugin->release = "3.5.9"; // User-friendly version number.

View file

@ -18,7 +18,7 @@
* Handles viewing a customcert.
*
* @package mod_customcert
* @copyright 2013 Mark Nelson <markn@moodle.com>, 2022 Kumi Systems e.U. <office@kumi.systems>
* @copyright 2013 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
@ -56,8 +56,7 @@ if ($customcert->requiredtime && !$canmanage) {
if (\mod_customcert\certificate::get_course_time($course->id) < ($customcert->requiredtime * 60)) {
$a = new stdClass;
$a->requiredtime = $customcert->requiredtime;
$url = new moodle_url('/course/view.php', ['id' => $course->id]);
notice(get_string('requiredtimenotmet', 'customcert', $a), $url);
notice(get_string('requiredtimenotmet', 'customcert', $a), "$CFG->wwwroot/course/view.php?id=$course->id");
die;
}
}
@ -142,7 +141,6 @@ if (!$downloadown && !$downloadissue) {
$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->add_action(new \popup_action('click', $link));
$downloadbutton = $OUTPUT->render($downloadbutton);
}
@ -160,7 +158,7 @@ if (!$downloadown && !$downloadissue) {
}
echo $OUTPUT->footer($course);
exit();
} else if ($canreceive || $canmanage) { // 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) {

View file

@ -1 +1 @@
YUI.add("moodle-mod_customcert-rearrange",function(r,t){var s=function(){s.superclass.constructor.apply(this,[arguments])};r.extend(s,r.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.setPdfDimensions(),this.setBoundaries(),this.setpositions(),this.createevents(),window.addEventListener("resize",this.checkWindownResize.bind(this))},setpositions:function(){var t,e,i,s,n,o;for(t in this.elements){switch(e=this.elements[t],i=this.pdfx+e.posx*this.pixelsinmm,s=this.pdfy+e.posy*this.pixelsinmm,n=parseFloat(r.one("#element-"+e.id).getComputedStyle("width")),(o=e.width*this.pixelsinmm)&&o<n&&(n=o),e.refpoint){case"1":i-=n/2;break;case"2":i=i-n+2}r.one("#element-"+e.id).setX(i),r.one("#element-"+e.id).setY(s)}},setPdfDimensions:function(){this.pdfx=r.one("#pdf").getX(),this.pdfy=r.one("#pdf").getY(),this.pdfwidth=parseFloat(r.one("#pdf").getComputedStyle("width")),this.pdfheight=parseFloat(r.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(){r.one(".savepositionsbtn [type=submit]").on("click",function(t){this.savepositions(t)},this),r.one(".applypositionsbtn [type=submit]").on("click",function(t){this.savepositions(t),t.preventDefault()},this);var e=new r.DD.Delegate({container:"#pdf",nodes:".element"});e.on("drag:start",function(){var t=e.get("currentNode");this.elementxy=t.getXY()},this),e.on("drag:end",function(){var t=e.get("currentNode");this.isoutofbounds(t)&&t.setXY(this.elementxy)},this)},isoutofbounds:function(t){var e=parseFloat(t.getComputedStyle("width")),i=parseFloat(t.getComputedStyle("height")),s=t.getX(),n=s+e,o=t.getY(),a=o+i;return s<this.pdfleftboundary||n>this.pdfrightboundary||(o<this.pdfy||a>this.pdfy+this.pdfheight)},savepositions:function(o){var t,e,i,s,n,a,d,p={tid:this.templateid,values:[]};for(t in this.elements){switch(e=this.elements[t],s=(i=r.one("#element-"+e.id)).getX()-this.pdfx,n=i.getY()-this.pdfy,a=i.getData("refpoint"),d=parseFloat(i.getComputedStyle("width")),a){case"1":s+=d/2;break;case"2":s+=d}p.values.push({id:e.id,posx:Math.round(parseFloat(s/this.pixelsinmm)),posy:Math.round(parseFloat(n/this.pixelsinmm))})}p.values=JSON.stringify(p.values),r.io(M.cfg.wwwroot+"/mod/customcert/ajax.php",{method:"POST",data:p,on:{failure:function(t,e){this.ajaxfailure(e)},success:function(){var t,e,i=o.currentTarget.ancestor("form",!0),s=i.getAttribute("action"),n=i.one("[name=pid]");n?(t=n.get("value"),window.location=s+"?pid="+t):(e=i.one("[name=tid]").get("value"),window.location=s+"?tid="+e)}},context:this}),o.preventDefault()},ajaxfailure:function(t){var e={name:t.status+" "+t.statusText,message:t.responseText};return new M.core.exception(e)}}),r.namespace("M.mod_customcert.rearrange").init=function(t,e,i){new s(t,e,i)}},"@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"]});