Compare commits

..

91 commits

Author SHA1 Message Date
Mark Nelson
8598927ccb Bumped version 2019-02-04 15:00:45 +08:00
Mark Nelson
efcf0c1487 Updated CHANGES.md 2019-02-04 15:00:25 +08:00
Mark Nelson
10630a6967 Fixed invalid syntax for PHP 5.6.x 2019-02-04 14:57:23 +08:00
Nicolas Roeser
cab793fb1d 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:47:02 +08:00
Mark Nelson
758b72bd85 Bumped version 2019-02-04 14:34:04 +08:00
Mark Nelson
2412cc4cb0 Updated CHANGES.md 2019-02-04 14:33:34 +08:00
Mark Nelson
d4af36c370 Make it clear what element values are just an example (#144) 2019-02-04 14:31:54 +08:00
Mark Nelson
aca9e1d09a Use course module context when calling format_string/text (#200) 2019-02-04 14:31:49 +08:00
Mark Nelson
454bd388c0 Prevent exception when adding 'teachername' element to site template (#261) 2019-02-04 14:31:43 +08:00
Mark Nelson
8daf8c5bb6 Added missing details to CHANGES.md 2019-02-04 14:30:35 +08:00
Mark Nelson
9c215d4982 Bumped version 2018-12-24 15:24:56 +08:00
Mark Nelson
9f643b21eb Updated CHANGES.md 2018-12-20 12:34:06 +08:00
Mark Nelson
6f6b6fb45e Add ability to set transparency on images (#186) 2018-12-20 09:35:28 +08:00
Mark Nelson
1b4de1c53a Fixed issue when scales are used (#242)
The grade item's type was being hard-coded to
GRADE_TYPE_VALUE when this isn't always the
case.
2018-12-20 07:10:03 +08:00
Mark Nelson
94c32de40f Make use of the decimal value setting
We should use this instead of our own logic.
2018-12-20 07:09:56 +08:00
Mark Nelson
6ddb6f4818 Allow verification of deleted users (#159) 2018-12-19 09:33:58 +08:00
Mark Nelson
b3be9d558a Report now respects the setting 'Show user identity' (#224) 2018-12-19 09:33:54 +08:00
Mark Nelson
b3bd669eac Fixed logic so site templates work as expected (#160) 2018-12-17 16:44:27 +08:00
Mark Nelson
31e5feeb1b Hide completion date option if not applicable (#160) 2018-12-17 16:44:22 +08:00
mwithheld
06a7595c85 Move creating the temp directory out of the emailing for loop (#238) 2018-12-17 15:44:36 +08:00
Mark Nelson
f1d6813889 Removed boolean return and added a comment (#237) 2018-12-17 15:16:09 +08:00
mwithheld
3e2e9c9c8b Reduce code nesting level in task (#237)
Make the code easier to read and understand
2018-12-17 15:16:03 +08:00
Mark Nelson
810bc2d3fd Change field 'element' to character rather than text (#241) 2018-12-17 12:52:34 +08:00
Aaron Parker
fe6e5210ab Added plaintext lang variants for email bodies and updated template (#230) 2018-12-17 11:02:40 +08:00
james-cnz
ded62a208c Matched up prevent x description strings (#254)
The description strings for the settings prevent copy, prevent print, and prevent modify were mixed up when added with:
#180 Add possibility to set default values of activity instance
2018-12-17 10:56:22 +08:00
Mark Nelson
e5598e30ea #225 Renamed static function 2018-12-17 10:04:26 +08:00
Alexander Bias
f16434575d #225 Allow element plugins to control if they can be added 2018-12-17 10:04:20 +08:00
Mark Nelson
97498b54a0 Changed reference to moodlerooms (#249) 2018-12-17 09:54:15 +08:00
Marina Glancy
ec822b7662 Update travis (#249)
Bring the travis.yml up to date with https://github.com/blackboard-open-source/moodle-plugin-ci/blob/master/.travis.dist.yml
use grunt to validate js and css
add validation of mustache, savepoints, allow javascript behat tests
2018-12-17 09:53:06 +08:00
Mark Nelson
8b1e414370 #223 Removed incorrect course reset logic 2018-08-07 12:16:51 +08:00
Dmitrii Metelkin
b74c95a474 Add tests to support new permissions and default activity options 2018-08-07 12:16:47 +08:00
Dmitrii Metelkin
6d28c1b3ed #179 Don't display form elements if a user doesn't have capabilities 2018-08-07 12:16:43 +08:00
Dmitrii Metelkin
6c07679c2c #180 Add possibility to set default values of activity instance 2018-08-07 12:16:38 +08:00
Dmitrii Metelkin
f42a0ac394 #179 Add possibility to selectively disable activity instance settings 2018-08-07 12:16:33 +08:00
Mark Nelson
e7e2106efb Added LICENSE.md 2018-08-04 13:53:44 +08:00
Dmitrii Metelkin
f0ab803912 #213 Allow element plugins to have admin settings 2018-08-04 13:53:13 +08:00
Mark Nelson
29d9b27a90 Bumped version 2018-07-13 22:41:21 +08:00
Mark Nelson
855845ccbf Updated CHANGES.md 2018-07-13 22:06:22 +08:00
Mark Nelson
9e24bd0446 #171 Only get teachers who are enrolled within the course 2018-07-13 20:55:56 +08:00
Tristan Mackay
f547e4b88c #176 Only get users details who are enrolled within the course 2018-07-13 20:55:52 +08:00
Mark Nelson
f76ec6e841 #210 Allow short dates with leading zeros 2018-07-13 20:55:44 +08:00
Mark Nelson
c66fb9703d #210 Improve code for adding date strings to select 2018-07-13 20:55:38 +08:00
Mark Nelson
6070185a61 #154 Don't display 'Add page' link for unsaved templates 2018-07-13 20:55:32 +08:00
Mark Nelson
7f592e332f #187 Fix broken SQL on Oracle 2018-07-13 20:55:24 +08:00
Mark Nelson
71ea74a0ae #211 Use custom fonts if present 2018-07-13 20:55:19 +08:00
Mark Nelson
70fc4f454d #207 Changed download button between managers and non-managers on mobile
Also minor changes to 'notissued' string and fixed reference to
non-existent string 'notissuedyet'.
2018-07-13 20:55:10 +08:00
Mark Nelson
622d670f47 #207 No need to use a table/list when displaying only one issue 2018-07-13 20:55:03 +08:00
Mark Nelson
e3675ff267 #207 Changed font-size for awarded time in the report in mobile view
Also made minor alignment changes.
2018-07-13 20:54:58 +08:00
Mark Nelson
7d2826654d #207 Follow-up UX improvements
The majority of this change involved moving
the report page logic into the view page for
both browser and mobile.
2018-07-13 20:54:53 +08:00
Mark Nelson
82018e7d67 Fixed reference to tool_mobile in CHANGES.md 2018-06-27 11:34:02 +08:00
Mark Nelson
a7f79b4602 Removed unnecessary new lines 2018-06-26 21:42:38 +08:00
Mark Nelson
91ae210c84 Bumped version 2018-06-26 21:42:03 +08:00
Mark Nelson
cad3ce43b0 #203 Added missing consistency changes for headings/titles 2018-06-26 20:11:43 +08:00
Mark Nelson
8f526a40c8 Updated CHANGES.md 2018-06-26 19:54:35 +08:00
Mark Nelson
d3b22a23b5 #203 Consistency among headings/titles on all pages 2018-06-26 19:53:43 +08:00
Mark Nelson
ab4f8e1fb3 #203 Removed 'code' column
Not all certificates contain a 'code' element,
making this column unnecessary. It may also
confuse users when it is not applicable. For
those who are interested they can always use
the 'verify' functionality to confirm
certificates, rather than using this page.
2018-06-26 19:53:33 +08:00
Mark Nelson
46a40ff51c #203 Improved 'listofissues' string 2018-06-26 17:02:27 +08:00
Mark Nelson
99213e81fd #203 Make report heading/title consistent with core activities 2018-06-26 17:02:27 +08:00
Mark Nelson
873528cd84 #203 Changed 'listofissues' string to avoid confusion 2018-06-26 17:02:27 +08:00
Mark Nelson
24e8dde0d4 #203 Added heading to activity view page in browser 2018-06-26 17:02:27 +08:00
Mark Nelson
8d810440ae #203 Added new string for list of awarded certificates 2018-06-26 17:02:27 +08:00
Mark Nelson
9a0decf45e #203 Don't display group select on activity view page 2018-06-26 17:02:27 +08:00
Mark Nelson
eee14ade58 #203 Don't show 'Awarded on' date to managers 2018-06-26 17:02:27 +08:00
Mark Nelson
f7587a5d22 Fixed reference to 'mod/certificate' capability 2018-06-26 17:02:27 +08:00
Mark Nelson
73e12cca4f #203 Make mobile layout friendly on small screens 2018-06-26 17:02:27 +08:00
Mark Nelson
a0546ea2d4 #203 Removed 'issued' string and replaced with 'receiveddate'
Also renamed 'Received date' to 'Awarded on'.
2018-06-26 17:02:27 +08:00
Mark Nelson
44e8d2ee81 #203 Removed confusing 'summaryofissue' string 2018-06-26 17:02:27 +08:00
Mark Nelson
05b23b5213 #197 Respect filters in 'My certificates' and 'Verify certificate' pages 2018-06-26 17:02:27 +08:00
Mark Nelson
1ecb528c11 #202 Make web service accessible by 'local_mobile' 2018-06-13 18:42:21 +08:00
Mark Nelson
fa89eb1a55 #196 Use FORMAT_HTML when calling format_text() (again)
This commit is not as vital as the previous one as it
does not affect the layout of the PDF.
2018-06-07 20:12:06 +08:00
Mark Nelson
5fe9057758 Bumped version 2018-06-07 19:56:56 +08:00
Mark Nelson
f296f07786 Updated CHANGES.md 2018-06-07 19:55:50 +08:00
Mark Nelson
f46b9ff229 Add example JSON context to templates 2018-06-07 19:55:21 +08:00
Mark Nelson
5ced9220a4 #196 Use FORMAT_HTML when calling format_text() 2018-06-07 19:55:15 +08:00
Mark Nelson
3c7a854544 Updated CHANGES.md 2018-06-07 12:42:27 +08:00
Mark Nelson
0404785271 #70 Added mobile app support
This allows students to view the activity and download
their certificate. It also allows teachers to view the
list of issued certificates, with the ability to revoke
any.

This is for Moodle Mobile v3.5.0 (not to be confused with
your Moodle site version) and will not work on Mobile
versions earlier than this.

If you are running a Moodle site on version 3.4 or below
you will need to install the local_mobile plugin in order
for this to work.

If you are running a Moodle site on version 3.0 or below
then you will need to upgrade.
2018-06-07 12:42:27 +08:00
Mark Nelson
808ac9bc3d #170 Elements now respect filters 2018-06-07 12:33:23 +08:00
Mark Nelson
9352c969ad Fixed typo in PHPDoc 2018-06-07 12:33:16 +08:00
Roberto Pinna
ccc7e9730e #192 Fixed report fields for download 2018-05-26 18:38:47 +08:00
Mark Nelson
237c21db4d Fixed PHPDoc 2018-05-26 18:38:42 +08:00
Mark Nelson
df058698b0 Added helper function to issue certificates 2018-05-26 18:38:32 +08:00
Mark Nelson
06cf83ffe9 Changed icon for downloading certificate from reports
This was done because the core 'import' icon was mapped
to the Font Awesome icon 'fa-level-up' which did not look
appropriate.
2018-05-26 18:38:05 +08:00
Mark Nelson
fa67a82dbc #148 Increase size limit on fonts 2018-05-17 19:49:21 +08:00
Mark Nelson
9cbc4a5add Bump version 2018-05-17 14:49:55 +08:00
Mark Nelson
061f3ff76d Updated CHANGES.md 2018-05-17 14:49:17 +08:00
Mark Nelson
2470709383 #189 Implemented privacy provider for GDPR compliance 2018-05-15 18:29:36 +08:00
Mark Nelson
a45906cfbf Bumped to PHP 7.1 in travis.yml 2018-05-15 12:33:49 +08:00
Eugene Venter
9f4e1f43b4 #173 Fix race condition on certificate issues in scheduled task 2018-05-14 19:32:06 +08:00
Mark Nelson
f55f3cf399 #169 Ensure we backup the 'verifyany' setting 2018-02-22 19:16:23 +08:00
Mark Nelson
8e11a0fe3a #166 Fixed encoding content links 2018-02-22 19:16:02 +08:00
Mark Nelson
b8e66d84d3 Coding style fixes 2017-12-04 21:26:30 +08:00
128 changed files with 544 additions and 4056 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
cache:
directories:
- $HOME/.composer/cache
- $HOME/.npm
php:
- 5.6
- 7.1
addons:
firefox: 47.0.1
postgresql: 9.3
apt:
packages:
- oracle-java8-installer
- oracle-java8-set-default
env:
global:
- MOODLE_BRANCH=MOODLE_33_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 8.9
- nvm use 8.9
- cd ../..
- composer create-project -n --no-dev --prefer-dist blackboard-open-source/moodle-plugin-ci ci ^2
- 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

@ -2,140 +2,15 @@
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.
Note - All hash comments refer to the issue number. Eg. #169 refers to https://github.com/markn86/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
### Added
- Added ability to select outcomes in the Grade element (#329).
- The Grade Item Name element now works with all grade items, whereas before it was just activities (#346).
- Added enrolment start and end dates to the date element (#328).
- Added username to userfield form element (#390).
### Changed
- Removed unnecessary and confusing 'exampledata' string.
- Do not email those who can manage the certificate (#376).
- Do not force the PDF to be downloaded, instead send the file inline to the browser (#153).
- Updated the 'emailstudents_help', 'emailteachers_help' and 'emailothers_help' strings to warn users about prematurely emailing the certificate (#276).
- Do not email out certificates that contain no elements (#276).
## [3.3.17] - 2019-02-04
### 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).
- Fixed invalid syntax for PHP 5.6 as it is still supported in 3.3.
## [3.8.4] - 2020-03-12
### Added
- Added extra Behat steps for new elements (#309).
### Changed
- When copying a site template the site images are also copied to the course context and then those copied images are used.
Before, the elements would simply point to the site images. However, this meant when performing a backup/restore the
images were not stored in the backup file (#298).
### Fixed
- Fixed the displaying of names of a custom user field (#326).
- 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
### Changed
- Always send emails from the 'noreplyuser' (#165).
### 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).
## [3.6.1] - 2018-12-31
## [3.3.16] - 2019-02-04
### Changed
@ -143,14 +18,12 @@ Note - All hash comments refer to the issue number. Eg. #169 refers to https://g
### Fixed
- Missing implementation for privacy provider (#260).
- Use course module context when calling format_string/text (#200).
- Exception being thrown when adding the 'teachername' element to site template (#261).
## [3.5.5] - 2018-12-20
## [3.3.15] - 2018-12-20
### Added
- GDPR: Add support for removal of users from a context (see MDL-62560) (#252).
- Images can be made transparent (#186).
- Set default values of activity instance settings (#180).
- Allow element plugins to control if they can be added to a certificate (#225).
@ -173,7 +46,7 @@ Note - All hash comments refer to the issue number. Eg. #169 refers to https://g
- Removed incorrect course reset logic (#223).
- Description strings referring to the wrong setting (#254).
## [3.5.4] - 2018-07-13
## [3.3.14] - 2018-07-13
### Fixed
- Use custom fonts if present (#211).
@ -188,22 +61,23 @@ Note - All hash comments refer to the issue number. Eg. #169 refers to https://g
- One big change here is combining the report and activity view page into one.
- Allow short dates with leading zeros (#210).
## [3.5.3] - 2018-06-26
## [3.3.13] - 2018-06-26
### Fixed
- Respect filters in the 'My certificates' and 'Verify certificate' pages (#197).
- Fixed reference to 'mod/certificate' capability.
- Provided access to necessary web services for mobile functionality to the local_mobile plugin (#202).
### Changed
- Multiple UX improvements to both the browser and mobile views (#203).
## [3.5.2] - 2018-06-07
## [3.3.12] - 2018-06-07
### Fixed
- Hotfix to prevent misalignment of 'text' elements after last release (#196).
## [3.5.1] - 2018-06-06
## [3.3.11] - 2018-06-06
### Added
- Mobile app support (#70).
```
@ -235,7 +109,7 @@ Note - All hash comments refer to the issue number. Eg. #169 refers to https://g
- No longer display the 'action' column and user picture URL when downloading the user report (#192).
- Elements no longer ignore filters (#170).
## [3.4.1] - 2018-05-17
## [3.3.10] - 2018-05-17
### Added
- GDPR Compliance (#189).

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
@ -17,7 +15,7 @@ This requires Git being installed. If you do not have Git installed, please visi
Once you have Git installed, simply visit your Moodle mod directory and clone the repository using the following command.
```
git clone https://github.com/mdjnelson/moodle-mod_customcert.git customcert
git clone https://github.com/markn86/moodle-mod_customcert.git customcert
```
Then checkout the branch corresponding to the version of Moodle you are using with the following command. Make sure to replace MOODLE_32_STABLE with the version of Moodle you are using.

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

@ -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

@ -64,7 +64,6 @@ class edit_element_form extends \moodleform {
$mform->addHelpButton('name', 'elementname', 'customcert');
$this->element = \mod_customcert\element_factory::get_element_instance($element);
$this->element->set_edit_element_form($this);
$this->element->render_form_elements($mform);
$this->add_action_buttons(true);

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,21 +97,11 @@ abstract class element {
*/
protected $refpoint;
/**
* @var string The alignment.
*/
protected $alignment;
/**
* @var bool $showposxy Show position XY form elements?
*/
protected $showposxy;
/**
* @var edit_element_form Element edit form instance.
*/
private $editelementform;
/**
* Constructor.
*
@ -150,7 +125,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,36 +226,11 @@ 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.
*
* @param \MoodleQuickForm $mform the edit_form instance.
* @param edit_element_form $mform the edit_form instance.
*/
public function render_form_elements($mform) {
// Render the common elements.
@ -291,8 +240,6 @@ abstract class element {
element_helper::render_form_element_position($mform);
}
element_helper::render_form_element_width($mform);
element_helper::render_form_element_refpoint($mform);
element_helper::render_form_element_alignment($mform);
}
/**
@ -312,8 +259,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 +305,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 +371,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 +383,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.
@ -476,27 +421,4 @@ abstract class element {
return $this->element->$name;
}
}
/**
* Set edit form instance for the custom cert element.
*
* @param \mod_customcert\edit_element_form $editelementform
*/
public function set_edit_element_form(edit_element_form $editelementform) {
$this->editelementform = $editelementform;
}
/**
* Get edit form instance for the custom cert element.
*
* @return \mod_customcert\edit_element_form
*/
public function get_edit_element_form() {
if (empty($this->editelementform)) {
throw new \coding_exception('Edit element form instance is not set.');
}
return $this->editelementform;
}
}

View file

@ -47,19 +47,18 @@ class element_factory {
$classname = '\\customcertelement_' . $element->element . '\\element';
$data = new \stdClass();
$data->id = $element->id ?? null;
$data->pageid = $element->pageid ?? null;
$data->name = $element->name ?? get_string('pluginname', 'customcertelement_' . $element->element);
$data->id = isset($element->id) ? $element->id : null;
$data->pageid = isset($element->pageid) ? $element->pageid : null;
$data->name = isset($element->name) ? $element->name : get_string('pluginname', 'customcertelement_' . $element->element);
$data->element = $element->element;
$data->data = $element->data ?? null;
$data->font = $element->font ?? null;
$data->fontsize = $element->fontsize ?? null;
$data->colour = $element->colour ?? null;
$data->posx = $element->posx ?? null;
$data->posy = $element->posy ?? null;
$data->width = $element->width ?? null;
$data->refpoint = $element->refpoint ?? null;
$data->alignment = $element->alignment ?? null;
$data->data = isset($element->data) ? $element->data : null;
$data->font = isset($element->font) ? $element->font : null;
$data->fontsize = isset($element->fontsize) ? $element->fontsize : null;
$data->colour = isset($element->colour) ? $element->colour : null;
$data->posx = isset($element->posx) ? $element->posx : null;
$data->posy = isset($element->posy) ? $element->posy : null;
$data->width = isset($element->width) ? $element->width : null;
$data->refpoint = isset($element->refpoint) ? $element->refpoint : null;
// 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);
}
/**
@ -135,7 +134,7 @@ class element_helper {
/**
* Helper function to render the font elements.
*
* @param \MoodleQuickForm $mform the edit_form instance.
* @param \mod_customcert\edit_element_form $mform the edit_form instance.
*/
public static function render_form_element_font($mform) {
$mform->addElement('select', 'font', get_string('font', 'customcert'), \mod_customcert\certificate::get_fonts());
@ -152,7 +151,7 @@ class element_helper {
/**
* Helper function to render the colour elements.
*
* @param \MoodleQuickForm $mform the edit_form instance.
* @param \mod_customcert\edit_element_form $mform the edit_form instance.
*/
public static function render_form_element_colour($mform) {
$mform->addElement('customcert_colourpicker', 'colour', get_string('fontcolour', 'customcert'));
@ -164,7 +163,7 @@ class element_helper {
/**
* Helper function to render the position elements.
*
* @param \MoodleQuickForm $mform the edit_form instance.
* @param \mod_customcert\edit_element_form $mform the edit_form instance.
*/
public static function render_form_element_position($mform) {
$mform->addElement('text', 'posx', get_string('posx', 'customcert'), array('size' => 10));
@ -180,49 +179,23 @@ class element_helper {
/**
* Helper function to render the width element.
*
* @param \MoodleQuickForm $mform the edit_form instance.
* @param \mod_customcert\edit_element_form $mform the edit_form instance.
*/
public static function render_form_element_width($mform) {
$mform->addElement('text', 'width', get_string('elementwidth', 'customcert'), array('size' => 10));
$mform->setType('width', PARAM_INT);
$mform->setDefault('width', 0);
$mform->addHelpButton('width', 'elementwidth', 'customcert');
}
/**
* Helper function to render the refpoint element.
*
* @param \MoodleQuickForm $mform the edit_form instance.
*/
public static function render_form_element_refpoint($mform) {
$refpointoptions = array();
$refpointoptions[self::CUSTOMCERT_REF_POINT_TOPLEFT] = get_string('topleft', 'customcert');
$refpointoptions[self::CUSTOMCERT_REF_POINT_TOPCENTER] = get_string('topcenter', 'customcert');
$refpointoptions[self::CUSTOMCERT_REF_POINT_TOPRIGHT] = get_string('topright', 'customcert');
$mform->addElement('select', 'refpoint', get_string('refpoint', 'customcert'), $refpointoptions);
$mform->setType('refpoint', PARAM_INT);
$mform->setDefault('refpoint', self::CUSTOMCERT_REF_POINT_TOPCENTER);
$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.
*
@ -416,7 +389,7 @@ class element_helper {
* @param int $elementid The element id
* @return \context The context
*/
public static function get_context(int $elementid) : \context {
public static function get_context($elementid) {
global $DB;
$sql = "SELECT ct.contextid
@ -480,40 +453,70 @@ class element_helper {
* @return array the array of gradeable items in the course
*/
public static function get_grade_items($course) {
global $DB;
// Array to store the grade items.
$arrgradeitems = array();
$modules = array();
// Collect course modules data.
$modinfo = get_fast_modinfo($course);
$mods = $modinfo->get_cms();
$sections = $modinfo->get_section_info_all();
// Create the section label depending on course format.
$sectionlabel = get_string('section');
if ($course->format == 'topics') {
$sectionlabel = get_string('topic');
} else if ($course->format == 'weeks') {
$sectionlabel = get_string('week');
}
// Loop through each course section.
for ($i = 0; $i <= count($sections) - 1; $i++) {
// Confirm the index exists, should always be true.
if (isset($sections[$i])) {
// Get the individual section.
$section = $sections[$i];
// Get the mods for this section.
$sectionmods = explode(",", $section->sequence);
// Loop through the section mods.
foreach ($sectionmods as $sectionmod) {
// Should never happen unless DB is borked.
if (empty($mods[$sectionmod])) {
continue;
}
$mod = $mods[$sectionmod];
$instance = $DB->get_record($mod->modname, array('id' => $mod->instance));
// Get the grade items for this activity.
if ($gradeitems = grade_get_grade_items_for_activity($mod)) {
$moditem = grade_get_grades($course->id, 'mod', $mod->modname, $mod->instance);
$gradeitem = reset($moditem->items);
if (isset($gradeitem->grademax)) {
$modules[$mod->id] = $sectionlabel . ' ' . $section->section . ' : ' . $instance->name;
}
}
}
}
}
// Get other non-module related grade items.
if ($gradeitems = \grade_item::fetch_all(['courseid' => $course->id])) {
$arrgradeitems = [];
foreach ($gradeitems as $gi) {
if ($gi->is_course_item()) {
continue; // Skipping for legacy reasons - this was added to individual elements.
}
if ($gi->is_external_item()) {
$cm = get_coursemodule_from_instance($gi->itemmodule, $gi->iteminstance, $course->id);
$modcontext = \context_module::instance($cm->id);
$modname = format_string($cm->name, true, array('context' => $modcontext));
}
if ($gi->is_external_item() && !$gi->is_outcome_item()) {
// Due to legacy reasons we are storing the course module ID here rather than the grade item id.
// If we were to change we would need to provide upgrade steps to convert cm->id to gi->id.
$arrgradeitems[$cm->id] = get_string('activity', 'mod_customcert') . ' : ' . $gi->get_name();
} else if ($gi->is_external_item() && $gi->is_outcome_item()) {
// Get the name of the activity.
$optionname = get_string('gradeoutcome', 'mod_customcert') . ' : ' . $modname . " - " . $gi->get_name();
$arrgradeitems['gradeitem:' . $gi->id] = $optionname;
} else {
$arrgradeitems['gradeitem:' . $gi->id] = get_string('gradeitem', 'grades') . ' : ' . $gi->get_name(true);
// Skip the course and mod items since we already have them.
if ($gi->itemtype == 'mod' || $gi->itemtype == 'course') {
continue;
}
$arrgradeitems['gradeitem:' . $gi->id] = get_string('gradeitem', 'grades') . ' : ' . $gi->get_name(true);
}
// Alphabetise this.
asort($arrgradeitems);
// Merge results.
$modules = $modules + $arrgradeitems;
}
return $arrgradeitems;
return $modules;
}
/**

View file

@ -42,23 +42,4 @@ class course_module_viewed extends \core\event\course_module_viewed {
$this->data['objecttable'] = 'customcert';
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' => ''
];
}
@ -206,7 +202,7 @@ class mobile {
* @param \context $context
* @param string $cap
*/
protected static function require_capability(\stdClass $cm, \context $context, string $cap) {
protected static function require_capability(\stdClass $cm, \context $context, $cap) {
require_login($cm->course, false, $cm, true, true);
require_capability($cap, $context);
}

View file

@ -25,11 +25,9 @@ namespace mod_customcert\privacy;
use core_privacy\local\metadata\collection;
use core_privacy\local\request\approved_contextlist;
use core_privacy\local\request\approved_userlist;
use core_privacy\local\request\contextlist;
use core_privacy\local\request\helper;
use core_privacy\local\request\transform;
use core_privacy\local\request\userlist;
use core_privacy\local\request\writer;
defined('MOODLE_INTERNAL') || die();
@ -42,8 +40,7 @@ defined('MOODLE_INTERNAL') || die();
*/
class provider implements
\core_privacy\local\metadata\provider,
\core_privacy\local\request\plugin\provider,
\core_privacy\local\request\core_userlist_provider {
\core_privacy\local\request\plugin\provider {
/**
* Return the fields which contain personal data.
@ -51,7 +48,7 @@ class provider implements
* @param collection $items a reference to the collection to use to store the metadata.
* @return collection the updated collection of metadata items.
*/
public static function get_metadata(collection $items) : collection {
public static function get_metadata(collection $items) {
$items->add_database_table(
'customcert_issues',
[
@ -73,7 +70,7 @@ class provider implements
* @param int $userid the userid.
* @return contextlist the list of contexts containing user info for the user.
*/
public static function get_contexts_for_userid(int $userid) : contextlist {
public static function get_contexts_for_userid($userid) {
$sql = "SELECT c.id
FROM {context} c
INNER JOIN {course_modules} cm
@ -99,37 +96,6 @@ class provider implements
return $contextlist;
}
/**
* Get the list of users who have data within a context.
*
* @param userlist $userlist The userlist containing the list of users who have data in this context/plugin combination.
*/
public static function get_users_in_context(userlist $userlist) {
$context = $userlist->get_context();
if (!$context instanceof \context_module) {
return;
}
// Fetch all users who have a custom certificate.
$sql = "SELECT customcertissues.userid
FROM {course_modules} cm
JOIN {modules} m
ON m.id = cm.module AND m.name = :modname
JOIN {customcert} customcert
ON customcert.id = cm.instance
JOIN {customcert_issues} customcertissues
ON customcertissues.customcertid = customcert.id
WHERE cm.id = :cmid";
$params = [
'cmid' => $context->instanceid,
'modname' => 'customcert',
];
$userlist->add_from_sql('userid', $sql, $params);
}
/**
* Export personal data for the given approved_contextlist. User and context information is contained within the contextlist.
*
@ -216,33 +182,6 @@ class provider implements
}
}
/**
* Delete multiple users within a single context.
*
* @param approved_userlist $userlist The approved context and user information to delete information for.
*/
public static function delete_data_for_users(approved_userlist $userlist) {
global $DB;
$context = $userlist->get_context();
if (!$context instanceof \context_module) {
return;
}
$cm = get_coursemodule_from_id('customcert', $context->instanceid);
if (!$cm) {
// Only customcert module will be handled.
return;
}
$userids = $userlist->get_userids();
list($usersql, $userparams) = $DB->get_in_or_equal($userids, SQL_PARAMS_NAMED);
$select = "customcertid = :customcertid AND userid $usersql";
$params = ['customcertid' => $cm->instance] + $userparams;
$DB->delete_records_select('customcert_issues', $select, $params);
}
/**
* Return a list of Customcert IDs mapped to their course module ID.
*

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';
@ -74,15 +74,13 @@ class report_table extends \table_sql {
$columns[] = $extrafield;
}
$columns[] = 'timecreated';
$columns[] = 'code';
$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');
// Check if we were passed a filename, which means we want to download it.
if ($download) {
@ -103,7 +101,6 @@ class report_table extends \table_sql {
$this->define_headers($headers);
$this->collapsible(false);
$this->sortable(true);
$this->no_sorting('code');
$this->no_sorting('download');
$this->is_downloadable(true);
@ -138,16 +135,6 @@ class report_table extends \table_sql {
return userdate($user->timecreated);
}
/**
* Generate the code column.
*
* @param \stdClass $user
* @return string
*/
public function col_code($user) {
return $user->code;
}
/**
* Generate the download column.
*

View file

@ -23,8 +23,6 @@
*/
namespace mod_customcert\task;
use mod_customcert\helper;
defined('MOODLE_INTERNAL') || die();
/**
@ -71,29 +69,17 @@ class email_certificate_task extends \core\task\scheduled_task {
$htmlrenderer = $PAGE->get_renderer('mod_customcert', 'email', 'htmlemail');
$textrenderer = $PAGE->get_renderer('mod_customcert', 'email', 'textemail');
foreach ($customcerts as $customcert) {
// Do not process an empty certificate.
$sql = "SELECT ce.*
FROM {customcert_elements} ce
JOIN {customcert_pages} cp
ON cp.id = ce.pageid
JOIN {customcert_templates} ct
ON ct.id = cp.templateid
WHERE ct.contextid = :contextid";
if (!$DB->record_exists_sql($sql, ['contextid' => $customcert->contextid])) {
continue;
}
// Get the context.
$context = \context::instance_by_id($customcert->contextid);
// 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();
// Store teachers for later.
$teachers = get_enrolled_users($context, 'moodle/course:update');
// Look through the teachers.
if ($teachers = get_enrolled_users($context, 'moodle/course:update')) {
$teachers = sort_by_roleassignment_authority($teachers, $context);
$userfrom = reset($teachers);
} else { // Ok, no teachers, use administrator name.
$userfrom = get_admin();
}
$courseshortname = format_string($customcert->courseshortname, true, array('context' => $context));
$coursefullname = format_string($customcert->coursefullname, true, array('context' => $context));
@ -107,7 +93,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
@ -134,11 +120,6 @@ class email_certificate_task extends \core\task\scheduled_task {
continue;
}
// Only email those with the capability to receive the certificate.
if (!has_capability('mod/customcert:receiveissue', $context, $enroluser->id)) {
continue;
}
// Check that they have passed the required time.
if (!empty($customcert->requiredtime)) {
if (\mod_customcert\certificate::get_course_time($customcert->courseid,
@ -149,7 +130,7 @@ class email_certificate_task extends \core\task\scheduled_task {
// Ensure the cert hasn't already been issued, e.g via the UI (view.php) - a race condition.
$issueid = $DB->get_field('customcert_issues', 'id',
array('userid' => $enroluser->id, 'customcertid' => $customcert->id), IGNORE_MULTIPLE);
array('userid' => $enroluser->id, 'customcertid' => $customcert->id));
if (empty($issueid)) {
// Ok, issue them the certificate.
$issueid = \mod_customcert\certificate::issue_certificate($customcert->id, $enroluser->id);
@ -181,11 +162,7 @@ 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;
// Now, get the PDF.
$template = new \stdClass();
@ -213,8 +190,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 +201,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 +221,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,44 +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);
// This is the logic the TCPDF library uses when processing the name. This makes names
// such as 'الشهادة' become empty, so set a default name in these cases.
$filename = preg_replace('/[\s]+/', '_', $filename);
$filename = preg_replace('/[^a-zA-Z0-9_\.-]/', '', $filename);
if (empty($filename)) {
$filename = get_string('certificate', 'customcert');
}
// Remove full-stop at the end, if it exists, to avoid "..pdf" being created and being filtered by clean_filename.
$filename = rtrim($this->name, '.');
$filename = clean_filename($filename . '.pdf');
// Loop through the pages and display their content.
foreach ($pages as $page) {
@ -321,91 +293,22 @@ 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, 'D');
}
}
@ -417,10 +320,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 +412,6 @@ class template {
return $this->name;
}
public function get_html() {
return $this->html;
}
/**
* Returns the context id.
*

View file

@ -1,9 +1,8 @@
{
"name": "mdjnelson/moodle-mod_customcert",
"name": "markn86/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

@ -60,14 +60,6 @@ $capabilities = array(
)
),
'mod/customcert:receiveissue' => array(
'captype' => 'read',
'contextlevel' => CONTEXT_MODULE,
'archetypes' => array(
'student' => CAP_ALLOW
)
),
'mod/customcert:viewreport' => array(
'captype' => 'read',

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"/>
@ -24,7 +23,7 @@
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="Primary key for customcert"/>
<KEY NAME="template" TYPE="foreign" FIELDS="templateid" REFTABLE="customcert_templates" REFFIELDS="id"/>
<KEY NAME="template" TYPE="foreign" FIELDS="templateid" REFTABLE="customcert_template" REFFIELDS="id"/>
</KEYS>
</TABLE>
<TABLE NAME="customcert_templates" COMMENT="Stores each customcert template">
@ -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"/>
@ -69,7 +67,7 @@
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id" COMMENT="Primary key for customcert_pages"/>
<KEY NAME="template" TYPE="foreign" FIELDS="templateid" REFTABLE="customcert_templates" REFFIELDS="id"/>
<KEY NAME="template" TYPE="foreign" FIELDS="templateid" REFTABLE="customcert_template" REFFIELDS="id"/>
</KEYS>
</TABLE>
<TABLE NAME="customcert_elements" COMMENT="Stores the elements for a given page">
@ -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

@ -30,7 +30,7 @@ $addons = [
'issueview' => [ // Handler unique name.
'displaydata' => [
'icon' => $CFG->wwwroot . '/mod/customcert/pix/icon.png',
'class' => 'core-course-module-customcert-handler',
'class' => '',
],
'delegate' => 'CoreCourseModuleDelegate', // Delegate (where to display the link to the plugin).
'method' => 'mobile_view_activity', // Main function in \mod_customcert\output\mobile.

View file

@ -32,7 +32,7 @@ $functions = array(
'description' => 'Delete an issue for a certificate',
'type' => 'write',
'ajax' => true,
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE)
'services' => array(MOODLE_OFFICIAL_MOBILE_SERVICE, 'local_mobile')
),
'mod_customcert_save_element' => array(
'classname' => 'mod_customcert\external',

View file

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

View file

@ -15,16 +15,13 @@
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Strings for component 'customcertelement_qrcode', language 'en'.
* Definition of sub-plugins.
*
* @package customcertelement_qrcode
* @copyright 2019 Mark Nelson <markn@moodle.com>
* @package mod_customcert
* @copyright 2013 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$string['height'] = 'Height';
$string['height_help'] = 'Height help';
$string['pluginname'] = 'QR code';
$string['privacy:metadata'] = 'The QR code plugin does not store any personal data.';
$string['width'] = 'Width';
$string['width_help'] = 'width help';
defined('MOODLE_INTERNAL') || die();
$subplugins = array('customcertelement' => 'mod/customcert/element');

View file

@ -135,7 +135,7 @@ function xmldb_customcert_upgrade($oldversion) {
upgrade_mod_savepoint(true, 2017050506, 'customcert');
}
if ($oldversion < 2018051705) {
if ($oldversion < 2017050515) {
$table = new xmldb_table('customcert_elements');
$field = new xmldb_field('element', XMLDB_TYPE_CHAR, '255', null, XMLDB_NOTNULL, null, null, 'name');
@ -143,60 +143,7 @@ function xmldb_customcert_upgrade($oldversion) {
$dbman->change_field_type($table, $field);
// Savepoint reached.
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');
upgrade_mod_savepoint(true, 2017050515, 'customcert');
}
return true;

View file

@ -38,7 +38,7 @@ class element extends \customcertelement_image\element {
/**
* This function renders the form elements when adding a customcert element.
*
* @param \MoodleQuickForm $mform the edit_form instance
* @param \mod_customcert\edit_element_form $mform the edit_form instance
*/
public function render_form_elements($mform) {
$mform->addElement('select', 'fileid', get_string('image', 'customcertelement_image'), self::get_images());

View file

@ -40,7 +40,7 @@ class provider implements \core_privacy\local\metadata\null_provider {
*
* @return string
*/
public static function get_reason() : string {
public static function get_reason() {
return 'privacy:metadata';
}
}

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 = 2017050500; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2017050500; // Requires this Moodle version (3.3).
$plugin->component = 'customcertelement_bgimage';

View file

@ -38,7 +38,7 @@ class element extends \mod_customcert\element {
/**
* This function renders the form elements when adding a customcert element.
*
* @param \MoodleQuickForm $mform the edit_form instance
* @param \mod_customcert\edit_element_form $mform the edit_form instance
*/
public function render_form_elements($mform) {
// We want to define the width of the border.
@ -103,7 +103,7 @@ class element extends \mod_customcert\element {
/**
* Sets the data on the form when editing an element.
*
* @param \MoodleQuickForm $mform the edit_form instance
* @param \mod_customcert\edit_element_form $mform the edit_form instance
*/
public function definition_after_data($mform) {
if (!empty($this->get_data())) {

View file

@ -40,7 +40,7 @@ class provider implements \core_privacy\local\metadata\null_provider {
*
* @return string
*/
public static function get_reason() : string {
public static function get_reason() {
return 'privacy:metadata';
}
}

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 = 2017050500; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2017050500; // Requires this Moodle version (3.3).
$plugin->component = 'customcertelement_border';

View file

@ -63,7 +63,7 @@ class element extends \mod_customcert\element {
*
* @return string
*/
protected function get_category_name() : string {
protected function get_category_name() {
global $DB, $SITE;
$courseid = \mod_customcert\element_helper::get_courseid($this->get_id());

View file

@ -40,7 +40,7 @@ class provider implements \core_privacy\local\metadata\null_provider {
*
* @return string
*/
public static function get_reason() : string {
public static function get_reason() {
return 'privacy:metadata';
}
}

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 = 2017050500; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2017050500; // Requires this Moodle version (3.3).
$plugin->component = 'customcertelement_categoryname';

View file

@ -54,7 +54,7 @@ class element extends \mod_customcert\element {
$customcert = $DB->get_record('customcert', array('templateid' => $page->templateid), '*', MUST_EXIST);
// Now we can get the issue for this user.
$issue = $DB->get_record('customcert_issues', array('userid' => $user->id, 'customcertid' => $customcert->id),
'*', IGNORE_MULTIPLE);
'*', MUST_EXIST);
$code = $issue->code;
}

View file

@ -40,7 +40,7 @@ class provider implements \core_privacy\local\metadata\null_provider {
*
* @return string
*/
public static function get_reason() : string {
public static function get_reason() {
return 'privacy:metadata';
}
}

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 = 2017050500; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2017050500; // Requires this Moodle version (3.3).
$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,29 +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/>.
/**
* Strings for component 'customcertelement_coursefield', language 'en'.
*
* @package customcertelement_coursefield
* @copyright 2019 Catalyst IT
* @author Dan Marsden
* @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.';

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() {
$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

@ -40,7 +40,7 @@ class provider implements \core_privacy\local\metadata\null_provider {
*
* @return string
*/
public static function get_reason() : string {
public static function get_reason() {
return 'privacy:metadata';
}
}

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 = 2017050500; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2017050500; // Requires this Moodle version (3.3).
$plugin->component = 'customcertelement_coursename';

View file

@ -51,21 +51,6 @@ define('CUSTOMCERT_DATE_COURSE_START', '-3');
*/
define('CUSTOMCERT_DATE_COURSE_END', '-4');
/**
* Date - Current date
*/
define('CUSTOMCERT_DATE_CURRENT_DATE', '-5');
/**
* Date - Enrollment start
*/
define('CUSTOMCERT_DATE_ENROLMENT_START', '-6');
/**
* Date - Entrollment end
*/
define('CUSTOMCERT_DATE_ENROLMENT_END', '-7');
require_once($CFG->dirroot . '/lib/grade/constants.php');
/**
@ -80,7 +65,7 @@ class element extends \mod_customcert\element {
/**
* This function renders the form elements when adding a customcert element.
*
* @param \MoodleQuickForm $mform the edit_form instance
* @param \mod_customcert\edit_element_form $mform the edit_form instance
*/
public function render_form_elements($mform) {
global $CFG, $COURSE;
@ -88,14 +73,10 @@ class element extends \mod_customcert\element {
// Get the possible date options.
$dateoptions = array();
$dateoptions[CUSTOMCERT_DATE_ISSUE] = get_string('issueddate', 'customcertelement_date');
$dateoptions[CUSTOMCERT_DATE_CURRENT_DATE] = get_string('currentdate', 'customcertelement_date');
$completionenabled = $CFG->enablecompletion && ($COURSE->id == SITEID || $COURSE->enablecompletion);
if ($completionenabled) {
$dateoptions[CUSTOMCERT_DATE_COMPLETION] = get_string('completiondate', 'customcertelement_date');
}
$dateoptions[CUSTOMCERT_DATE_ENROLMENT_START] = get_string('enrolmentstartdate', 'customcertelement_date');
$dateoptions[CUSTOMCERT_DATE_ENROLMENT_END] = get_string('enrolmentenddate', 'customcertelement_date');
$dateoptions[CUSTOMCERT_DATE_COURSE_START] = get_string('coursestartdate', 'customcertelement_date');
$dateoptions[CUSTOMCERT_DATE_COURSE_END] = get_string('courseenddate', 'customcertelement_date');
$dateoptions[CUSTOMCERT_DATE_COURSE_GRADE] = get_string('coursegradedate', 'customcertelement_date');
@ -160,12 +141,10 @@ class element extends \mod_customcert\element {
$customcert = $DB->get_record('customcert', array('templateid' => $page->templateid), '*', MUST_EXIST);
// Now we can get the issue for this user.
$issue = $DB->get_record('customcert_issues', array('userid' => $user->id, 'customcertid' => $customcert->id),
'*', IGNORE_MULTIPLE);
'*', MUST_EXIST);
if ($dateitem == CUSTOMCERT_DATE_ISSUE) {
$date = $issue->timecreated;
} else if ($dateitem == CUSTOMCERT_DATE_CURRENT_DATE) {
$date = time();
} else if ($dateitem == CUSTOMCERT_DATE_COMPLETION) {
// Get the last completion date.
$sql = "SELECT MAX(c.timecompleted) as timecompleted
@ -177,26 +156,6 @@ class element extends \mod_customcert\element {
$date = $timecompleted->timecompleted;
}
}
} else if ($dateitem == CUSTOMCERT_DATE_ENROLMENT_START) {
// Get the enrolment start date.
$sql = "SELECT ue.timestart FROM {enrol} e JOIN {user_enrolments} ue ON ue.enrolid = e.id
WHERE e.courseid = :courseid
AND ue.userid = :userid";
if ($timestart = $DB->get_record_sql($sql, array('userid' => $issue->userid, 'courseid' => $courseid))) {
if (!empty($timestart->timestart)) {
$date = $timestart->timestart;
}
}
} else if ($dateitem == CUSTOMCERT_DATE_ENROLMENT_END) {
// Get the enrolment end date.
$sql = "SELECT ue.timeend FROM {enrol} e JOIN {user_enrolments} ue ON ue.enrolid = e.id
WHERE e.courseid = :courseid
AND ue.userid = :userid";
if ($timeend = $DB->get_record_sql($sql, array('userid' => $issue->userid, 'courseid' => $courseid))) {
if (!empty($timeend->timeend)) {
$date = $timeend->timeend;
}
}
} else if ($dateitem == CUSTOMCERT_DATE_COURSE_START) {
$date = $DB->get_field('course', 'startdate', array('id' => $courseid));
} else if ($dateitem == CUSTOMCERT_DATE_COURSE_END) {
@ -231,7 +190,12 @@ class element extends \mod_customcert\element {
// Ensure that a date has been set.
if (!empty($date)) {
\mod_customcert\element_helper::render_content($pdf, $this, $this->get_date_format_string($date, $dateformat));
$date = $this->get_date_format_string($date, $dateformat);
// If we are previewing, we want to let the user know it's an example date so they don't get confused.
if ($preview) {
$date = get_string('exampledata', 'customcert', 'date') . ' ' . $date;
}
\mod_customcert\element_helper::render_content($pdf, $this, $date);
}
}
@ -259,7 +223,7 @@ class element extends \mod_customcert\element {
/**
* Sets the data on the form when editing an element.
*
* @param \MoodleQuickForm $mform the edit_form instance
* @param \mod_customcert\edit_element_form $mform the edit_form instance
*/
public function definition_after_data($mform) {
// Set the item and format for this element.

View file

@ -40,7 +40,7 @@ class provider implements \core_privacy\local\metadata\null_provider {
*
* @return string
*/
public static function get_reason() : string {
public static function get_reason() {
return 'privacy:metadata';
}
}

View file

@ -26,9 +26,6 @@ $string['completiondate'] = 'Completion date';
$string['courseenddate'] = 'Course end date';
$string['coursegradedate'] = 'Course grade date';
$string['coursestartdate'] = 'Course start date';
$string['enrolmentenddate'] = 'Enrolment end date';
$string['enrolmentstartdate'] = 'Enrolment start date';
$string['currentdate'] = 'Current date';
$string['dateformat'] = 'Date format';
$string['dateformat_help'] = 'This is the format of the date that will be displayed';
$string['dateitem'] = 'Date item';

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 = 2017050500; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2017050500; // Requires this Moodle version (3.3).
$plugin->component = 'customcertelement_date';

View file

@ -1,731 +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 date range element.
*
* @package customcertelement_daterange
* @copyright 2018 Dmitrii Metelkin <dmitriim@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace customcertelement_daterange;
use \mod_customcert\element_helper;
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
require_once($CFG->dirroot . '/lib/grade/constants.php');
/**
* The customcert date range element.
*
* @package customcertelement_daterange
* @copyright 2018 Dmitrii Metelkin <dmitriim@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class element extends \mod_customcert\element {
/**
* Max recurring period in seconds.
*/
const MAX_RECURRING_PERIOD = 31556926; // 12 months.
/**
* Current year placeholder string.
*/
const CURRENT_YEAR_PLACEHOLDER = '{{current_year}}';
/**
* First year in a date range placeholder string.
*/
const RANGE_FIRST_YEAR_PLACEHOLDER = '{{range_first_year}}';
/**
* Last year in a date range placeholder string.
*/
const RANGE_LAST_YEAR_PLACEHOLDER = '{{range_last_year}}';
/**
* First year in a date range placeholder string.
*/
const RECUR_RANGE_FIRST_YEAR_PLACEHOLDER = '{{recurring_range_first_year}}';
/**
* Last year in a date range placeholder string.
*/
const RECUR_RANGE_LAST_YEAR_PLACEHOLDER = '{{recurring_range_last_year}}';
/**
* A year in the user's date.
*/
const DATE_YEAR_PLACEHOLDER = '{{date_year}}';
/**
* Date - Issue
*/
const DATE_ISSUE = -1;
/**
* Date - Completion
*/
const DATE_COMPLETION = -2;
/**
* Date - Course start
*/
const DATE_COURSE_START = -3;
/**
* Date - Course end
*/
const DATE_COURSE_END = -4;
/**
* Date - Course grade date
*/
const DATE_COURSE_GRADE = -5;
/**
* Date - Course current date
*/
const DATE_CURRENT_DATE = -6;
/**
* This function renders the form elements when adding a customcert element.
*
* @param \MoodleQuickForm $mform the edit form instance
*/
public function render_form_elements($mform) {
global $COURSE;
// Get the possible date options.
$dateoptions = array();
$dateoptions[self::DATE_ISSUE] = get_string('issueddate', 'customcertelement_daterange');
$dateoptions[self::DATE_CURRENT_DATE] = get_string('currentdate', 'customcertelement_daterange');
$dateoptions[self::DATE_COMPLETION] = get_string('completiondate', 'customcertelement_daterange');
$dateoptions[self::DATE_COURSE_START] = get_string('coursestartdate', 'customcertelement_daterange');
$dateoptions[self::DATE_COURSE_END] = get_string('courseenddate', 'customcertelement_daterange');
$dateoptions[self::DATE_COURSE_GRADE] = get_string('coursegradedate', 'customcertelement_daterange');
$dateoptions = $dateoptions + element_helper::get_grade_items($COURSE);
$mform->addElement('select', 'dateitem', get_string('dateitem', 'customcertelement_daterange'), $dateoptions);
$mform->addHelpButton('dateitem', 'dateitem', 'customcertelement_daterange');
parent::render_form_elements($mform);
$mform->addElement('header', 'dateranges', get_string('dateranges', 'customcertelement_daterange'));
$mform->addElement('static', 'help', '', get_string('help', 'customcertelement_daterange'));
$mform->addElement('static', 'placeholders', '', get_string('placeholders', 'customcertelement_daterange'));
$mform->addElement('text', 'fallbackstring', get_string('fallbackstring', 'customcertelement_daterange'));
$mform->addHelpButton('fallbackstring', 'fallbackstring', 'customcertelement_daterange');
$mform->setType('fallbackstring', PARAM_NOTAGS);
if (empty($this->get_decoded_data()->dateranges)) {
$repeats = 1;
} else {
$repeats = count($this->get_decoded_data()->dateranges);
}
$ranges = [];
$ranges[] = $mform->createElement('html', '<hr>');
$ranges[] = $mform->createElement(
'date_selector',
'startdate',
get_string('start', 'customcertelement_daterange')
);
$ranges[] = $mform->createElement(
'date_selector',
'enddate',
get_string('end', 'customcertelement_daterange')
);
$ranges[] = $mform->createElement(
'checkbox',
'recurring',
get_string('recurring', 'customcertelement_daterange')
);
$ranges[] = $mform->createElement(
'text',
'datestring',
get_string('datestring', 'customcertelement_daterange'),
['class' => 'datestring']
);
$ranges[] = $mform->createElement(
'advcheckbox',
'rangedelete',
get_string('setdeleted', 'customcertelement_daterange'),
'',
[],
[0, 1]
);
$rangeoptions = array();
$rangeoptions['startdate']['type'] = PARAM_INT;
$rangeoptions['enddate']['type'] = PARAM_INT;
$rangeoptions['recurring']['type'] = PARAM_INT;
$rangeoptions['recurring']['helpbutton'] = ['recurring', 'customcertelement_daterange'];
$rangeoptions['datestring']['type'] = PARAM_NOTAGS;
$rangeoptions['rangedelete']['type'] = PARAM_BOOL;
$addstring = get_string('addrange', 'customcertelement_daterange');
$this->get_edit_element_form()->repeat_elements($ranges, $repeats, $rangeoptions, 'repeats', 'add', 1, $addstring, true);
}
/**
* A helper function to build consistent form element name.
*
* @param string $name
* @param string $num
*
* @return string
*/
protected function build_element_name($name, $num) {
return $name . '[' . $num . ']';
}
/**
* Get decoded data stored in DB.
*
* @return \stdClass
*/
protected function get_decoded_data() {
return json_decode($this->get_data());
}
/**
* Sets the data on the form when editing an element.
*
* @param \MoodleQuickForm $mform the edit form instance
*/
public function definition_after_data($mform) {
if (!empty($this->get_data()) && !$mform->isSubmitted()) {
$element = $mform->getElement('dateitem');
$element->setValue($this->get_decoded_data()->dateitem);
$element = $mform->getElement('fallbackstring');
$element->setValue($this->get_decoded_data()->fallbackstring);
foreach ($this->get_decoded_data()->dateranges as $key => $range) {
$mform->setDefault($this->build_element_name('startdate', $key), $range->startdate);
$mform->setDefault($this->build_element_name('enddate', $key), $range->enddate);
$mform->setDefault($this->build_element_name('datestring', $key), $range->datestring);
$mform->setDefault($this->build_element_name('recurring', $key), $range->recurring);
}
}
parent::definition_after_data($mform);
}
/**
* Performs validation on the element values.
*
* @param array $data the submitted data
* @param array $files the submitted files
* @return array the validation errors
*/
public function validate_form_elements($data, $files) {
$errors = parent::validate_form_elements($data, $files);
// Check if at least one range is set.
$error = get_string('error:atleastone', 'customcertelement_daterange');
for ($i = 0; $i < $data['repeats']; $i++) {
if (empty($data['rangedelete'][$i])) {
$error = '';
}
}
if (!empty($error)) {
$errors['help'] = $error;
}
// Check that datestring is set dataranges what aren't need to be deleted.
for ($i = 0; $i < $data['repeats']; $i++) {
// Skip elements that needs to be deleted.
if (!empty($data['rangedelete'][$i])) {
continue;
}
if (empty($data['datestring'][$i])) {
$name = $this->build_element_name('datestring', $i);
$errors[$name] = get_string('error:datestring', 'customcertelement_daterange');
}
// Check that end date is correctly set.
if ( $data['startdate'][$i] >= $data['enddate'][$i] ) {
$errors[$this->build_element_name('enddate', $i)] = get_string('error:enddate', 'customcertelement_daterange');
}
$rangeperiod = $data['enddate'][$i] - $data['startdate'][$i];
// Check that recurring dateranges are not longer than 12 months.
if (!empty($data['recurring'][$i]) && $rangeperiod >= self::MAX_RECURRING_PERIOD ) {
$errors[$this->build_element_name('enddate', $i)] = get_string('error:recurring', 'customcertelement_daterange');
}
}
return $errors;
}
/**
* This will handle how form data will be saved into the data column in the
* customcert_elements table.
*
* @param \stdClass $data the form data
* @return string the json encoded array
*/
public function save_unique_data($data) {
$arrtostore = array(
'dateitem' => $data->dateitem,
'fallbackstring' => $data->fallbackstring,
'dateranges' => [],
);
for ($i = 0; $i < $data->repeats; $i++) {
if (empty($data->rangedelete[$i])) {
$arrtostore['dateranges'][] = [
'startdate' => $data->startdate[$i],
'enddate' => $data->enddate[$i],
'datestring' => $data->datestring[$i],
'recurring' => !empty($data->recurring[$i]),
];
}
}
// Encode these variables before saving into the DB.
return json_encode($arrtostore);
}
/**
* Handles rendering the element on the pdf.
*
* @param \pdf $pdf the pdf object
* @param bool $preview true if it is a preview, false otherwise
* @param \stdClass $user the user we are rendering this for
*/
public function render($pdf, $preview, $user) {
global $DB;
// If there is no element data, we have nothing to display.
if (empty($this->get_data())) {
return;
}
$courseid = element_helper::get_courseid($this->id);
$dateitem = $this->get_decoded_data()->dateitem;
// If we are previewing this certificate then just show a demonstration date.
if ($preview) {
$date = time();
} else {
// Get the page.
$page = $DB->get_record('customcert_pages', array('id' => $this->get_pageid()), '*', MUST_EXIST);
// Get the customcert this page belongs to.
$customcert = $DB->get_record('customcert', array('templateid' => $page->templateid), '*', MUST_EXIST);
// Now we can get the issue for this user.
$issue = $DB->get_record('customcert_issues', array('userid' => $user->id, 'customcertid' => $customcert->id),
'*', MUST_EXIST);
switch ($dateitem) {
case self::DATE_ISSUE:
$date = $issue->timecreated;
break;
case self::DATE_CURRENT_DATE:
$date = time();
break;
case self::DATE_COMPLETION:
// Get the last completion date.
$sql = "SELECT MAX(c.timecompleted) as timecompleted
FROM {course_completions} c
WHERE c.userid = :userid
AND c.course = :courseid";
if ($timecompleted = $DB->get_record_sql($sql, array('userid' => $issue->userid, 'courseid' => $courseid))) {
if (!empty($timecompleted->timecompleted)) {
$date = $timecompleted->timecompleted;
}
}
break;
case self::DATE_COURSE_START:
$date = $DB->get_field('course', 'startdate', array('id' => $courseid));
break;
case self::DATE_COURSE_END:
$date = $DB->get_field('course', 'enddate', array('id' => $courseid));
break;
case self::DATE_COURSE_GRADE:
$grade = element_helper::get_course_grade_info(
$courseid,
GRADE_DISPLAY_TYPE_DEFAULT, $user->id
);
if ($grade && !empty($grade->get_dategraded())) {
$date = $grade->get_dategraded();
}
break;
default:
if (strpos($dateitem, 'gradeitem:') === 0) {
$gradeitemid = substr($dateitem, 10);
$grade = element_helper::get_grade_item_info(
$gradeitemid,
$dateitem,
$user->id
);
} else {
$grade = element_helper::get_mod_grade_info(
$dateitem,
GRADE_DISPLAY_TYPE_DEFAULT,
$user->id
);
}
if ($grade && !empty($grade->get_dategraded())) {
$date = $grade->get_dategraded();
}
break;
}
}
// Ensure that a date has been set.
if (!empty($date)) {
element_helper::render_content($pdf, $this, $this->get_daterange_string($date));
}
}
/**
* Get daterange string.
*
* @param int $date Unix stamp date.
*
* @return string
*/
protected function get_daterange_string($date) {
$matchedrange = null;
$outputstring = '';
$formatdata = [];
$formatdata['date'] = $date;
foreach ($this->get_decoded_data()->dateranges as $key => $range) {
if ($this->is_recurring_range($range)) {
if ($matchedrange = $this->get_matched_recurring_range($date, $range)) {
$outputstring = $matchedrange->datestring;
$formatdata['range'] = $range;
$formatdata['recurringrange'] = $matchedrange;
break;
}
} else {
if ($this->is_date_in_range($date, $range)) {
$outputstring = $range->datestring;
$formatdata['range'] = $range;
break;
}
}
}
if (empty($outputstring) && !empty($this->get_decoded_data()->fallbackstring)) {
$outputstring = $this->get_decoded_data()->fallbackstring;
}
return $this->format_date_string($outputstring, $formatdata);
}
/**
* Returns whether or not a range is recurring.
*
* @param \stdClass $range Range object.
*
* @return bool
*/
protected function is_recurring_range(\stdClass $range) {
return !empty($range->recurring);
}
/**
* Check if the provided date is in the date range.
*
* @param int $date Unix timestamp date to check.
* @param \stdClass $range Range object.
*
* @return bool
*/
protected function is_date_in_range($date, \stdClass $range) {
return ($date >= $range->startdate && $date <= $range->enddate);
}
/**
* Check if provided date is in the recurring date range.
*
* @param int $date Unix timestamp date to check.
* @param \stdClass $range Range object.
*
* @return bool
*/
protected function is_date_in_recurring_range($date, \stdClass $range) {
$intdate = $this->build_number_from_date($date);
$intstart = $this->build_number_from_date($range->startdate);
$intend = $this->build_number_from_date($range->enddate);
if (!$this->has_turn_of_the_year($range)) {
if ($intdate >= $intstart && $intdate <= $intend) {
return true;
}
} else {
if ($intdate >= $intstart && $intdate >= $intend) {
return true;
}
if ($intdate <= $intstart && $intdate <= $intend) {
return true;
}
}
return false;
}
/**
* Check if provided recurring range has a turn of the year.
*
* @param \stdClass $reccurringrange Range object.
*
* @return bool
*/
protected function has_turn_of_the_year(\stdClass $reccurringrange) {
return date('Y', $reccurringrange->startdate) != date('Y', $reccurringrange->enddate);
}
/**
* Check if provided date is in the start year of the recurring range with a turn of the year.
*
* @param int $date Unix timestamp date to check.
* @param \stdClass $range Range object.
*
* @return bool
*/
protected function in_start_year($date, \stdClass $range) {
$intdate = $this->build_number_from_date($date);
$intstart = $this->build_number_from_date($range->startdate);
$intend = $this->build_number_from_date($range->enddate);
return $intdate >= $intstart && $intdate >= $intend;
}
/**
* Check if provided date is in the end year of the recurring range with a turn of the year.
*
* @param int $date Unix timestamp date to check.
* @param \stdClass $range Range object.
*
* @return bool
*/
protected function in_end_year($date, \stdClass $range) {
$intdate = $this->build_number_from_date($date);
$intstart = $this->build_number_from_date($range->startdate);
$intend = $this->build_number_from_date($range->enddate);
return $intdate <= $intstart && $intdate <= $intend;
}
/**
* Return matched recurring date range.
*
* As recurring date ranges do not depend on the year,
* we will use a date's year to build a new matched recurring date range with
* start year and end year. This is required to replace placeholders like range_first_year and range_last_year.
*
* @param int $date Unix timestamp date to check.
* @param \stdClass $range Range object.
*
* @return \stdClass || null
*/
protected function get_matched_recurring_range($date, \stdClass $range) {
if (!$this->is_date_in_recurring_range($date, $range)) {
return null;
}
$matchedrage = clone $range;
if ($this->has_turn_of_the_year($matchedrage)) {
if ($this->in_start_year($date, $matchedrage)) {
$startyear = date('Y', $date);
$endyear = $startyear + 1;
$matchedrage->startdate = strtotime(date('d.m.', $matchedrage->startdate) . $startyear);
$matchedrage->enddate = strtotime(date('d.m.', $matchedrage->enddate) . $endyear);
return $matchedrage;
}
if ($this->in_end_year($date, $matchedrage)) {
$endyear = date('Y', $date);
$startyear = $endyear - 1;
$matchedrage->startdate = strtotime(date('d.m.', $matchedrage->startdate) . $startyear);
$matchedrage->enddate = strtotime(date('d.m.', $matchedrage->enddate) . $endyear);
return $matchedrage;
}
} else {
$matchedrage->startdate = strtotime(date('d.m.', $matchedrage->startdate) . date('Y', $date));
$matchedrage->enddate = strtotime(date('d.m.', $matchedrage->enddate) . date('Y', $date));
return $matchedrage;
}
return null;
}
/**
* Build number representation of the provided date.
*
* @param int $date Unix timestamp date to check.
*
* @return int
*/
protected function build_number_from_date($date) {
return (int)date('md', $date);
}
/**
* Format date string based on different types of placeholders.
*
* @param string $datestring The date string
* @param array $formatdata A list of format data.
*
* @return string
*/
protected function format_date_string($datestring, array $formatdata) {
foreach ($this->get_placeholders() as $search => $replace) {
$datestring = str_replace($search, $replace, $datestring);
}
if (!empty($formatdata['date'])) {
foreach ($this->get_date_placeholders($formatdata['date']) as $search => $replace) {
$datestring = str_replace($search, $replace, $datestring);
}
}
if (!empty($formatdata['range'])) {
foreach ($this->get_range_placeholders($formatdata['range']) as $search => $replace) {
$datestring = str_replace($search, $replace, $datestring);
}
}
if (!empty($formatdata['recurringrange'])) {
foreach ($this->get_recurring_range_placeholders($formatdata['recurringrange']) as $search => $replace) {
$datestring = str_replace($search, $replace, $datestring);
}
}
return $datestring;
}
/**
* Return a list of placeholders to replace in date string as search => $replace pairs.
*
* @return array
*/
protected function get_placeholders() {
return [
self::CURRENT_YEAR_PLACEHOLDER => date('Y', time()),
];
}
/**
* Return a list of user's date related placeholders to replace in date string as search => $replace pairs.
* @param int $date Unix timestamp date to check.
*
* @return array
*/
protected function get_date_placeholders($date) {
return [
self::DATE_YEAR_PLACEHOLDER => date('Y', $date),
];
}
/**
* Return a list of range related placeholders to replace in date string as search => $replace pairs.
*
* @param \stdClass $range
*
* @return array
*/
protected function get_range_placeholders(\stdClass $range) {
return [
self::RANGE_FIRST_YEAR_PLACEHOLDER => date('Y', $range->startdate),
self::RANGE_LAST_YEAR_PLACEHOLDER => date('Y', $range->enddate),
];
}
/**
* Return a list of recurring range s placeholders to replace in date string as search => $replace pairs.
*
* @param \stdClass $range
*
* @return array
*/
protected function get_recurring_range_placeholders(\stdClass $range) {
return [
self::RECUR_RANGE_FIRST_YEAR_PLACEHOLDER => date('Y', $range->startdate),
self::RECUR_RANGE_LAST_YEAR_PLACEHOLDER => date('Y', $range->enddate),
];
}
/**
* Render the element in html.
*
* This function is used to render the element when we are using the
* drag and drop interface to position it.
*
* @return string the html
*/
public function render_html() {
// If there is no element data, we have nothing to display.
if (empty($this->get_data())) {
return;
}
return element_helper::render_html_content($this, get_string('preview', 'customcertelement_daterange', $this->get_name()));
}
/**
* This function is responsible for handling the restoration process of the element.
*
* We will want to update the course module the date element is pointing to as it will
* have changed in the course restore.
*
* @param \restore_customcert_activity_task $restore
*/
public function after_restore($restore) {
global $DB;
$data = $this->get_decoded_data();
if ($newitem = \restore_dbops::get_backup_ids_record($restore->get_restoreid(), 'course_module', $data->dateitem)) {
$data->dateitem = $newitem->newitemid;
$DB->set_field('customcert_elements', 'data', $this->save_unique_data($data), array('id' => $this->get_id()));
}
}
}

View file

@ -1,46 +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_daterange.
*
* @package customcertelement_daterange
* @copyright 2018 Dmitrii Metelkin <dmitriim@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace customcertelement_daterange\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for customcertelement_daterange implementing null_provider.
*
* @copyright 2018 Dmitrii Metelkin <dmitriim@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason() : string {
return 'privacy:metadata';
}
}

View file

@ -1,53 +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/>.
/**
* Strings for component 'customcertelement_daterange', language 'en'.
*
* @package customcertelement_daterange
* @copyright 2018 Dmitrii Metelkin <dmitriim@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
$string['addrange'] = 'Add another range';
$string['completiondate'] = 'Completion date';
$string['courseenddate'] = 'Course end date';
$string['coursegradedate'] = 'Course grade date';
$string['coursestartdate'] = 'Course start date';
$string['currentdate'] = 'Current date';
$string['dateitem'] = 'Date item';
$string['dateitem_help'] = 'This will be the date that is printed on the certificate';
$string['dateranges'] = 'Date ranges';
$string['datestring'] = 'String';
$string['end'] = 'End';
$string['error:atleastone'] = 'You must have at least one date range configured';
$string['error:datestring'] = 'You must provide string representation for the date range';
$string['error:enddate'] = 'End date must occur after the start date';
$string['error:recurring'] = 'Recurring range must not be longer than 12 months';
$string['fallbackstring'] = 'Fallback string';
$string['fallbackstring_help'] = 'This string will be displayed if no date range applies to a date. If the fallback string is not set, then there will be no output at all.';
$string['help'] = 'Configure a string representation for your date ranges.<br /><br />If your ranges overlap the first matched date range will be applied.';
$string['issueddate'] = 'Issued date';
$string['placeholders'] = 'The following placeholders can be used in the string representation or fallback string. <br/><br /> {{range_first_year}} - first year of the matched range,<br/> {{range_last_year}} - last year of the matched range,<br/> {{recurring_range_first_year}} - first year of the matched recurring period,<br/> {{recurring_range_last_year}} - last year of the matched recurring period,<br/> {{current_year}} - the current year,<br/> {{date_year}} - a year of the users\'s date.';
$string['pluginname'] = 'Date range';
$string['preview'] = 'Preview {$a}';
$string['privacy:metadata'] = 'The Date range plugin does not store any personal data.';
$string['recurring'] = 'Recurring';
$string['recurring_help'] = 'If you mark a date range as recurring then the configured year will not be considered.';
$string['setdeleted'] = 'Delete';
$string['start'] = 'Start';

View file

@ -1,248 +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/>.
/**
* Test datarange element.
*
* @package customcertelement_daterange
* @copyright 2018 Dmitrii Metelkin <dmitriim@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
global $CFG;
require_once($CFG->dirroot . '/mod/customcert/element/daterange/tests/fixtures/fake_datarange_element.php');
/**
* Test datarange element.
*
* @package customcertelement_daterange
* @copyright 2018 Dmitrii Metelkin <dmitriim@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class customcertelement_daterange_element_test extends advanced_testcase {
/**
* Helper function to build element data.
*
* @param stdClass $data Element data.
*
* @return object
*/
protected function build_element_data(stdClass $data) {
return (object) [
'id' => 1,
'pageid' => 1,
'name' => 'Test',
'data' => json_encode($data),
'font' => 'Font',
'fontsize' => 1,
'colour' => '#EEE',
'posx' => 0,
'posy' => 0,
'width' => 100,
'refpoint' => 1
];
}
/**
* Helper function to build datarange data.
*
* @param array $dataranges A list of dataranges.
* @param string $fallbackstring Fall back string.
*
* @return object
*/
protected function build_datarange_data(array $dataranges, $fallbackstring = '') {
return (object) [
'dateitem' => 1,
'fallbackstring' => $fallbackstring,
'numranges' => count($dataranges),
'dateranges' => $dataranges,
];
}
/**
* A helper function to get datarange element for testing.
*
* @param array $dataranges A list of dataranges.
* @param string $fallbackstring Fall back strin
*
* @return \fake_datarange_element
*/
protected function get_datarange_element(array $dataranges, $fallbackstring = '') {
$datarangedata = $this->build_datarange_data($dataranges, $fallbackstring);
$elementdata = $this->build_element_data($datarangedata);
return new fake_datarange_element($elementdata);
}
/**
* Data provider for test_get_daterange_string_for_recurring_ranges.
* @return array
*/
public function get_test_get_daterange_string_for_recurring_ranges_data_provider() {
return [
['1.11.2016', 'WS 2016/2017'],
['1.11.2017', 'WS 2017/2018'],
['1.11.2018', 'WS 2018/2019'],
['1.11.2019', 'WS 2019/2020'],
['1.02.2017', 'WS 2016/2017'],
['1.02.2018', 'WS 2017/2018'],
['1.02.2019', 'WS 2018/2019'],
['1.02.2020', 'WS 2019/2020'],
['1.05.2016', 'SS 2016'],
['1.05.2017', 'SS 2017'],
['1.05.2018', 'SS 2018'],
['1.05.2019', 'SS 2019'],
];
}
/**
* Test get correct strings for recurring ranges.
*
* @dataProvider get_test_get_daterange_string_for_recurring_ranges_data_provider
*
* @param string $date Date to test.
* @param string $expected Expected result.
*/
public function test_get_daterange_string_for_recurring_ranges($date, $expected) {
$dateranges = [
(object)[
'startdate' => strtotime('01.04.2017'),
'enddate' => strtotime('30.09.2017'),
'datestring' => 'SS {{date_year}}',
'recurring' => true,
],
(object)[
'startdate' => strtotime('01.10.2017'),
'enddate' => strtotime('31.03.2018'),
'datestring' => 'WS {{recurring_range_first_year}}/{{recurring_range_last_year}}',
'recurring' => true,
],
];
$element = $this->get_datarange_element($dateranges);
$date = strtotime($date);
$this->assertEquals($expected, $element->get_daterange_string($date));
}
/**
* Test that first found element matched.
*/
public function test_that_first_matched_range_applied_first() {
$dateranges = [
(object)[
'startdate' => strtotime('01.04.2017'),
'enddate' => strtotime('30.09.2017'),
'datestring' => 'First range',
'recurring' => false,
],
(object)[
'startdate' => strtotime('01.05.2017'),
'enddate' => strtotime('01.07.2018'),
'datestring' => 'Second range',
'recurring' => false,
],
];
$element = $this->get_datarange_element($dateranges);
$date = strtotime('1.06.2017');
$this->assertEquals('First range', $element->get_daterange_string($date));
}
/**
* Test that placeholders correctly applied to matched range and fall back string.
*/
public function test_placeholders_and_fall_back_string() {
$dateranges = [
(object)[
'startdate' => strtotime('01.04.2017'),
'enddate' => strtotime('30.09.2018'),
'datestring' => '{{current_year}} - {{range_first_year}} - {{range_last_year}} - {{date_year}}',
'recurring' => false,
],
];
$fallbackstring = '{{current_year}} - {{range_first_year}} - {{range_last_year}} - {{date_year}}';
$element = $this->get_datarange_element($dateranges, $fallbackstring);
$date = strtotime('1.01.2000');
$expected = date('Y', time()) . ' - {{range_first_year}} - {{range_last_year}} - 2000';
$this->assertEquals($expected, $element->get_daterange_string($date));
$date = strtotime('1.07.2017');
$expected = date('Y', time()) . ' - 2017 - 2018 - 2017';
$this->assertEquals($expected, $element->get_daterange_string($date));
}
/**
* Test that nothing will be displayed if not matched and empty fall back string.
*/
public function test_nothing_will_be_displayed_if_empty_fallback_string() {
$dateranges = [
(object)[
'startdate' => strtotime('01.04.2017'),
'enddate' => strtotime('30.09.2018'),
'datestring' => '{{current_year}} - {{range_first_year}} - {{range_last_year}} - {{date_year}}',
'recurring' => false,
],
];
$fallbackstring = '';
$element = $this->get_datarange_element($dateranges, $fallbackstring);
$date = strtotime('1.07.2011');
$this->assertEquals($fallbackstring, $element->get_daterange_string($date));
}
/**
* Test that display recurring_range_first_year and recurring_range_last_year placeholders.
*/
public function test_recurring_range_first_year_and_recurring_range_last_year_placeholders() {
$datestring = '{{range_first_year}}-{{range_last_year}}-{{recurring_range_first_year}}-{{recurring_range_last_year}}';
$dateranges = [
(object) [
'startdate' => strtotime('01.04.2017'),
'enddate' => strtotime('30.09.2017'),
'datestring' => $datestring,
'recurring' => true,
],
(object)[
'startdate' => strtotime('01.10.2017'),
'enddate' => strtotime('31.03.2018'),
'datestring' => $datestring,
'recurring' => true,
],
];
$element = $this->get_datarange_element($dateranges);
$date = strtotime('1.05.2020');
$this->assertEquals('2017-2017-2020-2020', $element->get_daterange_string($date));
$date = strtotime('1.05.2024');
$this->assertEquals('2017-2017-2024-2024', $element->get_daterange_string($date));
$date = strtotime('1.02.2020');
$this->assertEquals('2017-2018-2019-2020', $element->get_daterange_string($date));
$date = strtotime('1.02.2024');
$this->assertEquals('2017-2018-2023-2024', $element->get_daterange_string($date));
}
}

View file

@ -1,47 +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/>.
/**
* Fake datarange element for testing.
*
* @package customcertelement_daterange
* @copyright 2018 Dmitrii Metelkin <dmitriim@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
/**
* Fake datarange element for testing.
*
* @package customcertelement_daterange
* @copyright 2018 Dmitrii Metelkin <dmitriim@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class fake_datarange_element extends \customcertelement_daterange\element {
/**
* Override protected method for testing.
*
* @param int $date
*
* @return string
*/
public function get_daterange_string($date) {
$result = parent::get_daterange_string($date);
return $result;
}
}

View file

@ -1,29 +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 date plugin.
*
* @package customcertelement_daterange
* @copyright 2018 Dmitrii Metelkin <dmitriim@catalyst-au.net>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
$plugin->version = 2021051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2021051700; // Requires this Moodle version (3.11).
$plugin->component = 'customcertelement_daterange';

View file

@ -60,7 +60,7 @@ class element extends \customcertelement_image\element {
/**
* This function renders the form elements when adding a customcert element.
*
* @param \MoodleQuickForm $mform the edit_form instance
* @param \mod_customcert\edit_element_form $mform the edit_form instance
*/
public function render_form_elements($mform) {
$mform->addElement('select', 'fileid', get_string('image', 'customcertelement_image'), self::get_images());
@ -240,7 +240,7 @@ class element extends \customcertelement_image\element {
/**
* Sets the data on the form when editing an element.
*
* @param \MoodleQuickForm $mform the edit_form instance
* @param \mod_customcert\edit_element_form $mform the edit_form instance
*/
public function definition_after_data($mform) {
global $COURSE, $SITE;

View file

@ -40,7 +40,7 @@ class provider implements \core_privacy\local\metadata\null_provider {
*
* @return string
*/
public static function get_reason() : string {
public static function get_reason() {
return 'privacy:metadata';
}
}

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 = 2017050500; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2017050500; // Requires this Moodle version (3.3).
$plugin->component = 'customcertelement_digitalsignature';

View file

@ -43,7 +43,7 @@ class element extends \mod_customcert\element {
/**
* This function renders the form elements when adding a customcert element.
*
* @param \MoodleQuickForm $mform the edit_form instance
* @param \mod_customcert\edit_element_form $mform the edit_form instance
*/
public function render_form_elements($mform) {
global $COURSE;
@ -107,7 +107,8 @@ class element extends \mod_customcert\element {
// If we are previewing this certificate then just show a demonstration grade.
if ($preview) {
$courseitem = \grade_item::fetch_course_item($courseid);
$grade = grade_format_gradevalue('100', $courseitem, true, $gradeinfo->gradeformat);;
$grade = grade_format_gradevalue('100', $courseitem, true, $gradeinfo->gradeformat);
$grade = get_string('exampledata', 'customcert', 'grade') . ' ' . $grade;
} else {
if ($gradeitem == CUSTOMCERT_GRADE_COURSE) {
$grade = \mod_customcert\element_helper::get_course_grade_info(
@ -167,7 +168,7 @@ class element extends \mod_customcert\element {
/**
* Sets the data on the form when editing an element.
*
* @param \MoodleQuickForm $mform the edit_form instance
* @param \mod_customcert\edit_element_form $mform the edit_form instance
*/
public function definition_after_data($mform) {
// Set the item and format for this element.

View file

@ -40,7 +40,7 @@ class provider implements \core_privacy\local\metadata\null_provider {
*
* @return string
*/
public static function get_reason() : string {
public static function get_reason() {
return 'privacy:metadata';
}
}

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 = 2017050500; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2017050500; // Requires this Moodle version (3.3).
$plugin->component = 'customcertelement_grade';

View file

@ -38,7 +38,7 @@ class element extends \mod_customcert\element {
/**
* This function renders the form elements when adding a customcert element.
*
* @param \MoodleQuickForm $mform the edit_form instance
* @param \mod_customcert\edit_element_form $mform the edit_form instance
*/
public function render_form_elements($mform) {
global $COURSE;
@ -99,7 +99,7 @@ class element extends \mod_customcert\element {
/**
* Sets the data on the form when editing an element.
*
* @param \MoodleQuickForm $mform the edit_form instance
* @param \mod_customcert\edit_element_form $mform the edit_form instance
*/
public function definition_after_data($mform) {
if (!empty($this->get_data())) {
@ -110,40 +110,20 @@ class element extends \mod_customcert\element {
}
/**
* Helper function that returns the grade item name.
* Helper function that returns the category name.
*
* @return string
*/
protected function get_grade_item_name() : string {
protected function get_grade_item_name() {
global $DB;
$gradeitem = $this->get_data();
// Get the course module information.
$cm = $DB->get_record('course_modules', array('id' => $this->get_data()), '*', MUST_EXIST);
$module = $DB->get_record('modules', array('id' => $cm->module), '*', MUST_EXIST);
if (strpos($gradeitem, 'gradeitem:') === 0) {
$gradeitemid = substr($gradeitem, 10);
$gradeitem = \grade_item::fetch(['id' => $gradeitemid]);
// Get the name of the item.
$itemname = $DB->get_field($module->name, 'name', array('id' => $cm->instance), MUST_EXIST);
return $gradeitem->get_name();
} else {
if (!$cm = $DB->get_record('course_modules', array('id' => $gradeitem))) {
return '';
}
if (!$module = $DB->get_record('modules', array('id' => $cm->module))) {
return '';
}
$params = [
'itemtype' => 'mod',
'itemmodule' => $module->name,
'iteminstance' => $cm->instance,
'courseid' => $cm->course,
'itemnumber' => 0
];
$gradeitem = \grade_item::fetch($params);
return $gradeitem->get_name();
}
return format_string($itemname, true, ['context' => \mod_customcert\element_helper::get_context($this->get_id())]);
}
}

View file

@ -40,7 +40,7 @@ class provider implements \core_privacy\local\metadata\null_provider {
*
* @return string
*/
public static function get_reason() : string {
public static function get_reason() {
return 'privacy:metadata';
}
}

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 = 2017050500; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2017050500; // Requires this Moodle version (3.3).
$plugin->component = 'customcertelement_gradeitemname';

View file

@ -60,7 +60,7 @@ class element extends \mod_customcert\element {
/**
* This function renders the form elements when adding a customcert element.
*
* @param \MoodleQuickForm $mform the edit_form instance
* @param \mod_customcert\edit_element_form $mform the edit_form instance
*/
public function render_form_elements($mform) {
$mform->addElement('select', 'fileid', get_string('image', 'customcertelement_image'), self::get_images());
@ -282,7 +282,7 @@ class element extends \mod_customcert\element {
/**
* Sets the data on the form when editing an element.
*
* @param \MoodleQuickForm $mform the edit_form instance
* @param \mod_customcert\edit_element_form $mform the edit_form instance
*/
public function definition_after_data($mform) {
global $COURSE, $SITE;
@ -382,14 +382,14 @@ class element extends \mod_customcert\element {
// Loop through the files uploaded in the system context.
if ($files = $fs->get_area_files(\context_system::instance()->id, 'mod_customcert', 'image', false, 'filename', false)) {
foreach ($files as $hash => $file) {
$arrfiles[$file->get_id()] = get_string('systemimage', 'customcertelement_image', $file->get_filename());
$arrfiles[$file->get_id()] = $file->get_filename();
}
}
// Loop through the files uploaded in the course context.
if ($files = $fs->get_area_files(\context_course::instance($COURSE->id)->id, 'mod_customcert', 'image', false,
'filename', false)) {
foreach ($files as $hash => $file) {
$arrfiles[$file->get_id()] = get_string('courseimage', 'customcertelement_image', $file->get_filename());
$arrfiles[$file->get_id()] = $file->get_filename();
}
}
@ -398,60 +398,4 @@ class element extends \mod_customcert\element {
return $arrfiles;
}
/**
* This handles copying data from another element of the same type.
*
* @param \stdClass $data the form data
* @return bool returns true if the data was copied successfully, false otherwise
*/
public function copy_element($data) {
global $COURSE, $DB, $SITE;
$imagedata = json_decode($data->data);
// If we are in the site context we don't have to do anything, the image is already there.
if ($COURSE->id == $SITE->id) {
return true;
}
$coursecontext = \context_course::instance($COURSE->id);
$systemcontext = \context_system::instance();
$fs = get_file_storage();
// Check that a file has been selected.
if (isset($imagedata->filearea)) {
// If the course file doesn't exist, copy the system file to the course context.
if (!$coursefile = $fs->get_file(
$coursecontext->id,
'mod_customcert',
$imagedata->filearea,
$imagedata->itemid,
$imagedata->filepath,
$imagedata->filename
)) {
$systemfile = $fs->get_file(
$systemcontext->id,
'mod_customcert',
$imagedata->filearea,
$imagedata->itemid,
$imagedata->filepath,
$imagedata->filename
);
// We want to update the context of the file if it doesn't exist in the course context.
$fieldupdates = [
'contextid' => $coursecontext->id
];
$coursefile = $fs->create_file_from_storedfile($fieldupdates, $systemfile);
}
// Set the image to the copied file in the course.
$imagedata->fileid = $coursefile->get_id();
$DB->set_field('customcert_elements', 'data', $this->save_unique_data($imagedata), ['id' => $this->get_id()]);
}
return true;
}
}

View file

@ -40,7 +40,7 @@ class provider implements \core_privacy\local\metadata\null_provider {
*
* @return string
*/
public static function get_reason() : string {
public static function get_reason() {
return 'privacy:metadata';
}
}

View file

@ -24,7 +24,6 @@
$string['alphachannel'] = 'Alpha channel';
$string['alphachannel_help'] = 'This value determines how transparent the image is. You can set the alpha channel from 0 (fully transparent) to 1 (fully opaque).';
$string['courseimage'] = 'Course image: {$a}';
$string['height'] = 'Height';
$string['height_help'] = 'Height of the image in mm. If equal to zero, it is automatically calculated.';
$string['image'] = 'Image';
@ -32,6 +31,5 @@ $string['invalidheight'] = 'The height has to be a valid number greater than or
$string['invalidwidth'] = 'The width has to be a valid number greater than or equal to 0.';
$string['pluginname'] = 'Image';
$string['privacy:metadata'] = 'The Image plugin does not store any personal data.';
$string['systemimage'] = 'Site image: {$a}';
$string['width'] = 'Width';
$string['width_help'] = 'Width of the image in mm. If equal to zero, it is automatically calculated.';

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 = 2017050500; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2017050500; // Requires this Moodle version (3.3).
$plugin->component = 'customcertelement_image';

View file

@ -1,208 +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 QR code's core interaction API.
*
* @package customcertelement_qrcode
* @copyright 2019 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace customcertelement_qrcode;
defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir . '/tcpdf/tcpdf_barcodes_2d.php');
/**
* The customcert element QR code's core interaction API.
*
* @package customcertelement_qrcode
* @copyright 2019 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class element extends \mod_customcert\element {
/**
* @var string The barcode type.
*/
const BARCODETYPE = 'QRCODE';
/**
* This function renders the form elements when adding a customcert element.
*
* @param \MoodleQuickForm $mform the edit_form instance
*/
public function render_form_elements($mform) {
\mod_customcert\element_helper::render_form_element_width($mform);
$mform->addElement('text', 'height', get_string('height', 'customcertelement_qrcode'), array('size' => 10));
$mform->setType('height', PARAM_INT);
$mform->setDefault('height', 0);
$mform->addHelpButton('height', 'height', 'customcertelement_qrcode');
if ($this->showposxy) {
\mod_customcert\element_helper::render_form_element_position($mform);
}
}
/**
* Performs validation on the element values.
*
* @param array $data the submitted data
* @param array $files the submitted files
* @return array the validation errors
*/
public function validate_form_elements($data, $files) {
// Array to return the errors.
$errors = [];
// Check if height is not set, or not numeric or less than 0.
if ((!isset($data['height'])) || (!is_numeric($data['height'])) || ($data['height'] <= 0)) {
$errors['height'] = get_string('invalidheight', 'mod_customcert');
}
if ((!isset($data['width'])) || (!is_numeric($data['width'])) || ($data['width'] <= 0)) {
$errors['width'] = get_string('invalidwidth', 'mod_customcert');
}
if ($this->showposxy) {
$errors += \mod_customcert\element_helper::validate_form_element_position($data);
}
$errors += \mod_customcert\element_helper::validate_form_element_width($data);
return $errors;
}
/**
* This will handle how form data will be saved into the data column in the
* customcert_elements table.
*
* @param \stdClass $data the form data
* @return string the json encoded array
*/
public function save_unique_data($data) {
$arrtostore = [
'width' => !empty($data->width) ? (int)$data->width : 0,
'height' => !empty($data->height) ? (int)$data->height : 0
];
return json_encode($arrtostore);
}
/**
* Sets the data on the form when editing an element.
*
* @param \MoodleQuickForm $mform the edit_form instance
*/
public function definition_after_data($mform) {
parent::definition_after_data($mform);
// Set the image, width, height and alpha channel for this element.
if (!empty($this->get_data())) {
$imageinfo = json_decode($this->get_data());
if (!empty($imageinfo->height)) {
$element = $mform->getElement('height');
$element->setValue($imageinfo->height);
}
}
}
/**
* Handles rendering the element on the pdf.
*
* @param \pdf $pdf the pdf object
* @param bool $preview true if it is a preview, false otherwise
* @param \stdClass $user the user we are rendering this for
*/
public function render($pdf, $preview, $user) {
global $DB;
// If there is no element data, we have nothing to display.
if (empty($this->get_data())) {
return;
}
$imageinfo = json_decode($this->get_data());
if ($preview) {
// Generate the URL to verify this.
$qrcodeurl = new \moodle_url('/');
$qrcodeurl = $qrcodeurl->out(false);
} else {
// Get the information we need.
$sql = "SELECT c.id, ct.contextid, ci.code
FROM {customcert_issues} ci
JOIN {customcert} c
ON ci.customcertid = c.id
JOIN {customcert_templates} ct
ON c.templateid = ct.id
JOIN {customcert_pages} cp
ON cp.templateid = ct.id
WHERE ci.userid = :userid
AND cp.id = :pageid";
// Now we can get the issue for this user.
$issue = $DB->get_record_sql($sql, array('userid' => $user->id, 'pageid' => $this->get_pageid()),
'*', MUST_EXIST);
$code = $issue->code;
// Generate the URL to verify this.
$qrcodeurl = new \moodle_url('/mod/customcert/verify_certificate.php',
[
'contextid' => $issue->contextid,
'code' => $code,
'qrcode' => 1
]
);
$qrcodeurl = $qrcodeurl->out(false);
}
$barcode = new \TCPDF2DBarcode($qrcodeurl, self::BARCODETYPE);
$image = $barcode->getBarcodePngData($imageinfo->width, $imageinfo->height);
$location = make_request_directory() . '/target';
file_put_contents($location, $image);
$pdf->Image($location, $this->get_posx(), $this->get_posy(), $imageinfo->width, $imageinfo->height);
}
/**
* Render the element in html.
*
* This function is used to render the element when we are using the
* drag and drop interface to position it.
*
* @return string the html
*/
public function render_html() {
// If there is no element data, we have nothing to display.
if (empty($this->get_data())) {
return;
}
$imageinfo = json_decode($this->get_data());
$qrcodeurl = new \moodle_url('/');
$qrcodeurl = $qrcodeurl->out(false);
$barcode = new \TCPDF2DBarcode($qrcodeurl, self::BARCODETYPE);
return $barcode->getBarcodeHTML($imageinfo->width / 10, $imageinfo->height / 10);
}
}

View file

@ -1,46 +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_qrcode.
*
* @package customcertelement_qrcode
* @copyright 2019 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace customcertelement_qrcode\privacy;
defined('MOODLE_INTERNAL') || die();
/**
* Privacy Subsystem for customcertelement_qrcode implementing null_provider.
*
* @copyright 2019 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class provider implements \core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason() : string {
return 'privacy:metadata';
}
}

View file

@ -1,29 +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 QR code plugin.
*
* @package customcertelement_qrcode
* @copyright 2019 Mark Nelson <markn@moodle.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.');
$plugin->version = 2021051700; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2021051700; // Requires this Moodle version (3.11).
$plugin->component = 'customcertelement_qrcode';

View file

@ -40,7 +40,7 @@ class provider implements \core_privacy\local\metadata\null_provider {
*
* @return string
*/
public static function get_reason() : string {
public static function get_reason() {
return 'privacy:metadata';
}
}

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 = 2017050500; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2017050500; // Requires this Moodle version (3.3).
$plugin->component = 'customcertelement_studentname';

View file

@ -38,7 +38,7 @@ class element extends \mod_customcert\element {
/**
* This function renders the form elements when adding a customcert element.
*
* @param \MoodleQuickForm $mform the edit_form instance
* @param \mod_customcert\edit_element_form $mform the edit_form instance
*/
public function render_form_elements($mform) {
$mform->addElement('select', 'teacher', get_string('teacher', 'customcertelement_teachername'),
@ -123,7 +123,7 @@ class element extends \mod_customcert\element {
/**
* Sets the data on the form when editing an element.
*
* @param \MoodleQuickForm $mform the edit_form instance
* @param \mod_customcert\edit_element_form $mform the edit_form instance
*/
public function definition_after_data($mform) {
if (!empty($this->get_data())) {

View file

@ -40,7 +40,7 @@ class provider implements \core_privacy\local\metadata\null_provider {
*
* @return string
*/
public static function get_reason() : string {
public static function get_reason() {
return 'privacy:metadata';
}
}

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 = 2017050500; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2017050500; // Requires this Moodle version (3.3).
$plugin->component = 'customcertelement_teachername';

View file

@ -38,7 +38,7 @@ class element extends \mod_customcert\element {
/**
* This function renders the form elements when adding a customcert element.
*
* @param \MoodleQuickForm $mform the edit_form instance
* @param \mod_customcert\edit_element_form $mform the edit_form instance
*/
public function render_form_elements($mform) {
$mform->addElement('textarea', 'text', get_string('text', 'customcertelement_text'));
@ -85,7 +85,7 @@ class element extends \mod_customcert\element {
/**
* Sets the data on the form when editing an element.
*
* @param \MoodleQuickForm $mform the edit_form instance
* @param \mod_customcert\edit_element_form $mform the edit_form instance
*/
public function definition_after_data($mform) {
if (!empty($this->get_data())) {
@ -100,7 +100,7 @@ class element extends \mod_customcert\element {
*
* @return string
*/
protected function get_text() : string {
protected function get_text() {
$context = \mod_customcert\element_helper::get_context($this->get_id());
return format_text($this->get_data(), FORMAT_HTML, ['context' => $context]);
}

View file

@ -40,7 +40,7 @@ class provider implements \core_privacy\local\metadata\null_provider {
*
* @return string
*/
public static function get_reason() : string {
public static function get_reason() {
return 'privacy:metadata';
}
}

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 = 2017050500; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2017050500; // Requires this Moodle version (3.3).
$plugin->component = 'customcertelement_text';

View file

@ -24,8 +24,6 @@
namespace customcertelement_userfield;
use core_user\fields;
defined('MOODLE_INTERNAL') || die();
/**
@ -40,31 +38,34 @@ class element extends \mod_customcert\element {
/**
* This function renders the form elements when adding a customcert element.
*
* @param \MoodleQuickForm $mform the edit_form instance
* @param \mod_customcert\edit_element_form $mform the edit_form instance
*/
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'),
'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();
$customfields = array();
foreach ($arrcustomfields as $key => $customfield) {
$customfields[$customfield->id] = $customfield->name;
$customfields[$customfield->id] = $key;
}
// Combine the two.
$fields = $userfields + $customfields;
@ -115,7 +116,7 @@ class element extends \mod_customcert\element {
/**
* Sets the data on the form when editing an element.
*
* @param \MoodleQuickForm $mform the edit_form instance
* @param \mod_customcert\edit_element_form $mform the edit_form instance
*/
public function definition_after_data($mform) {
if (!empty($this->get_data())) {
@ -132,7 +133,7 @@ class element extends \mod_customcert\element {
* @param bool $preview Is this a preview?
* @return string
*/
protected function get_user_field_value(\stdClass $user, bool $preview) : string {
protected function get_user_field_value(\stdClass $user, $preview) {
global $CFG, $DB;
// The user field to display.

View file

@ -40,7 +40,7 @@ class provider implements \core_privacy\local\metadata\null_provider {
*
* @return string
*/
public static function get_reason() : string {
public static function get_reason() {
return 'privacy:metadata';
}
}

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 = 2017050500; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2017050500; // Requires this Moodle version (3.3).
$plugin->component = 'customcertelement_userfield';

View file

@ -38,7 +38,7 @@ class element extends \mod_customcert\element {
/**
* This function renders the form elements when adding a customcert element.
*
* @param \MoodleQuickForm $mform the edit_form instance
* @param \mod_customcert\edit_element_form $mform the edit_form instance
*/
public function render_form_elements($mform) {
$mform->addElement('text', 'width', get_string('width', 'customcertelement_userpicture'), array('size' => 10));
@ -190,7 +190,7 @@ class element extends \mod_customcert\element {
/**
* Sets the data on the form when editing an element.
*
* @param \MoodleQuickForm $mform the edit_form instance
* @param \mod_customcert\edit_element_form $mform the edit_form instance
*/
public function definition_after_data($mform) {
// Set the image, width and height for this element.

View file

@ -40,7 +40,7 @@ class provider implements \core_privacy\local\metadata\null_provider {
*
* @return string
*/
public static function get_reason() : string {
public static function get_reason() {
return 'privacy:metadata';
}
}

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 = 2017050500; // The current module version (Date: YYYYMMDDXX).
$plugin->requires = 2017050500; // Requires this Moodle version (3.3).
$plugin->component = 'customcertelement_userpicture';

View file

@ -22,14 +22,8 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
$string['activity'] = 'Activity';
$string['addcertpage'] = 'Add page';
$string['addelement'] = 'Add element';
$string['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';
@ -47,7 +41,6 @@ $string['customcert:manageemailothers'] = 'Manage email others setting';
$string['customcert:manageverifyany'] = 'Manage verification setting';
$string['customcert:managerequiredtime'] = 'Manage time required setting';
$string['customcert:manageprotection'] = 'Manage protection setting';
$string['customcert:receiveissue'] = 'Receive a certificate';
$string['customcert:view'] = 'View a custom certificate';
$string['customcert:viewreport'] = 'View course report';
$string['customcert:viewallcertificates'] = 'View all certificates';
@ -62,9 +55,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';
@ -92,11 +82,12 @@ $string['emailstudentcertificatelinktext'] = 'View certificate';
$string['emailstudentgreeting'] = 'Dear {$a}';
$string['emailstudentsubject'] = '{$a->coursefullname}: {$a->certificatename}';
$string['emailstudents'] = 'Email students';
$string['emailstudents_help'] = 'If set this will email the students a copy of the certificate when it becomes available. <strong>Warning:</strong> Setting this to \'Yes\' before you have finished creating the certificate will email the student an incomplete certificate.';
$string['emailstudents_help'] = 'If set this will email the students a copy of the certificate when it becomes available.';
$string['emailteachers'] = 'Email teachers';
$string['emailteachers_help'] = 'If set this will email the teachers a copy of the certificate when it becomes available. <strong>Warning:</strong> Setting this to \'Yes\' before you have finished creating the certificate will email the teacher an incomplete certificate.';
$string['emailteachers_help'] = 'If set this will email the teachers a copy of the certificate when it becomes available.';
$string['emailothers'] = 'Email others';
$string['emailothers_help'] = 'If set this will email the email addresses listed here (separated by a comma) with a copy of the certificate when it becomes available. <strong>Warning:</strong> Setting this field before you have finished creating the certificate will email the addresses an incomplete certificate.';
$string['emailothers_help'] = 'If set this will email the email addresses listed here (separated by a comma) with a copy of the certificate when it becomes available.';
$string['exampledata'] = 'Example {$a}:';
$string['exampledatawarning'] = 'Some of these values may just be an example to ensure positioning of the elements is possible.';
$string['font'] = 'Font';
$string['font_help'] = 'The font used when generating this element.';
@ -105,7 +96,6 @@ $string['fontcolour_help'] = 'The colour of the font.';
$string['fontsize'] = 'Size';
$string['fontsize_help'] = 'The size of the font in points.';
$string['getcustomcert'] = 'View certificate';
$string['gradeoutcome'] = 'Outcome';
$string['height'] = 'Height';
$string['height_help'] = 'This is the height of the certificate PDF in mm. For reference an A4 piece of paper is 297mm high and a letter is 279mm high.';
$string['invalidcode'] = 'Invalid code supplied.';
@ -118,7 +108,7 @@ $string['invalidwidth'] = 'The width has to be a valid number greater than 0.';
$string['landscape'] = 'Landscape';
$string['leftmargin'] = 'Left margin';
$string['leftmargin_help'] = 'This is the left margin of the certificate PDF in mm.';
$string['listofissues'] = 'Recipients: {$a}';
$string['listofissues'] = 'Recipients';
$string['load'] = 'Load';
$string['loadtemplate'] = 'Load template';
$string['loadtemplatemsg'] = 'Are you sure you wish to load this template? This will remove any existing pages and elements for this certificate.';

Some files were not shown because too many files have changed in this diff Show more