├── .gitattributes ├── .github └── workflows │ ├── moodle-ci.yml │ └── moodle-release.yml ├── .gitignore ├── .gitlab-ci.yml ├── CHANGELOG.md ├── README.md ├── adminlib.php ├── adminmanageplugins.php ├── amd ├── build │ ├── form-potential-user-selector.min.js │ ├── form-potential-user-selector.min.js.map │ ├── issues-list.min.js │ ├── issues-list.min.js.map │ ├── template-details.min.js │ ├── template-details.min.js.map │ ├── template-edit.min.js │ ├── template-edit.min.js.map │ ├── templates-list.min.js │ └── templates-list.min.js.map └── src │ ├── form-potential-user-selector.js │ ├── issues-list.js │ ├── template-details.js │ ├── template-edit.js │ └── templates-list.js ├── certificates.php ├── classes ├── admin_externalpage.php ├── certificate.php ├── customfield │ └── issue_handler.php ├── edit_element_form.php ├── element.php ├── element_helper.php ├── event │ ├── certificate_issued.php │ ├── certificate_regenerated.php │ ├── certificate_revoked.php │ ├── certificate_verified.php │ ├── template_created.php │ ├── template_deleted.php │ └── template_updated.php ├── external │ ├── elements.php │ ├── issues.php │ └── templates.php ├── form │ ├── category_selector.php │ ├── certificate_issues.php │ ├── details.php │ └── page.php ├── local │ └── views │ │ └── template_secondary.php ├── my_certificates_table.php ├── observer.php ├── output │ ├── element.php │ ├── email │ │ ├── renderer.php │ │ └── renderer_textemail.php │ ├── issues_page.php │ ├── page.php │ ├── page_header_button.php │ ├── template.php │ ├── templates_page.php │ ├── verify_certificate_result.php │ └── verify_certificate_results.php ├── page.php ├── permission.php ├── persistent │ ├── element.php │ ├── page.php │ └── template.php ├── plugin_manager.php ├── plugininfo │ └── certificateelement.php ├── privacy │ └── provider.php ├── reportbuilder │ ├── datasource │ │ ├── issues.php │ │ └── templates.php │ └── local │ │ ├── entities │ │ ├── issue.php │ │ └── template.php │ │ ├── filters │ │ ├── status.php │ │ └── templatepermission.php │ │ ├── formatters │ │ └── certificate.php │ │ └── systemreports │ │ ├── issues.php │ │ └── templates.php ├── template.php ├── tool_tenant.php ├── upload_image_form.php └── verify_certificate_form.php ├── customfield.php ├── db ├── access.php ├── events.php ├── install.php ├── install.xml ├── messages.php ├── services.php ├── subplugins.json ├── upgrade.php └── upgradelib.php ├── element ├── border │ ├── classes │ │ ├── element.php │ │ └── privacy │ │ │ └── provider.php │ ├── lang │ │ └── en │ │ │ └── certificateelement_border.php │ ├── pix │ │ ├── icon.png │ │ └── icon.svg │ ├── tests │ │ └── element_test.php │ └── version.php ├── code │ ├── classes │ │ ├── element.php │ │ └── privacy │ │ │ └── provider.php │ ├── lang │ │ └── en │ │ │ └── certificateelement_code.php │ ├── pix │ │ ├── icon.png │ │ └── icon.svg │ ├── tests │ │ └── element_test.php │ └── version.php ├── date │ ├── classes │ │ ├── element.php │ │ └── privacy │ │ │ └── provider.php │ ├── lang │ │ └── en │ │ │ └── certificateelement_date.php │ ├── pix │ │ ├── icon.png │ │ └── icon.svg │ ├── tests │ │ └── element_test.php │ └── version.php ├── digitalsignature │ ├── classes │ │ ├── element.php │ │ └── privacy │ │ │ └── provider.php │ ├── lang │ │ └── en │ │ │ └── certificateelement_digitalsignature.php │ ├── pix │ │ ├── icon.png │ │ └── icon.svg │ ├── tests │ │ └── element_test.php │ └── version.php ├── image │ ├── classes │ │ ├── element.php │ │ └── privacy │ │ │ └── provider.php │ ├── db │ │ └── upgrade.php │ ├── lang │ │ └── en │ │ │ └── certificateelement_image.php │ ├── pix │ │ ├── icon.png │ │ └── icon.svg │ ├── tests │ │ └── element_test.php │ └── version.php ├── program │ ├── classes │ │ ├── element.php │ │ └── privacy │ │ │ └── provider.php │ ├── lang │ │ └── en │ │ │ └── certificateelement_program.php │ ├── pix │ │ ├── icon.png │ │ └── icon.svg │ ├── tests │ │ └── element_test.php │ └── version.php ├── text │ ├── classes │ │ ├── element.php │ │ └── privacy │ │ │ └── provider.php │ ├── lang │ │ └── en │ │ │ └── certificateelement_text.php │ ├── pix │ │ ├── icon.png │ │ └── icon.svg │ ├── tests │ │ └── element_test.php │ └── version.php ├── userfield │ ├── classes │ │ ├── element.php │ │ └── privacy │ │ │ └── provider.php │ ├── lang │ │ └── en │ │ │ └── certificateelement_userfield.php │ ├── pix │ │ ├── icon.png │ │ └── icon.svg │ ├── tests │ │ └── element_test.php │ └── version.php └── userpicture │ ├── classes │ ├── element.php │ └── privacy │ │ └── provider.php │ ├── lang │ └── en │ │ └── certificateelement_userpicture.php │ ├── pix │ ├── icon.png │ └── icon.svg │ ├── tests │ └── element_test.php │ └── version.php ├── includes └── colourpicker.php ├── index.php ├── lang └── en │ ├── deprecated.txt │ └── tool_certificate.php ├── lib.php ├── manage_templates.php ├── my.php ├── my_certificates.php ├── pix ├── background.jpg ├── brokenfile.png ├── download.png ├── download.svg ├── icon.gif ├── icon.png ├── icon.svg ├── linkedin.svg ├── qrcode.png ├── signature.png └── target.gif ├── settings.php ├── styles.css ├── template.php ├── template_details.php ├── templates ├── content_heading.mustache ├── content_with_heading.mustache ├── edit_layout.mustache ├── edit_layout_elementlist.mustache ├── edit_layout_page.mustache ├── edit_layout_pdf.mustache ├── form-user-selector-suggestion.mustache ├── page_header_button.mustache ├── verify_certificate_result.mustache └── verify_certificate_results.mustache ├── tests ├── behat │ ├── admin_tree.feature │ ├── adminmanageplugins.feature │ ├── behat_tool_certificate.php │ ├── issue_certificates.feature │ ├── managing_elements.feature │ ├── managing_pages.feature │ ├── managing_templates.feature │ ├── my_certificates.feature │ ├── show_position_x_y.feature │ ├── verify_certificates.feature │ ├── view_certificate.feature │ └── view_issued_certificates.feature ├── capabilities_test.php ├── certificate_test.php ├── element_factory_test.php ├── element_helper_test.php ├── external_test.php ├── fixtures │ └── signature.crt ├── generator │ └── lib.php ├── lib_test.php ├── my_certificates_table_test.php ├── observer_test.php ├── permission_test.php ├── privacy_provider_test.php ├── reportbuilder │ └── datasource │ │ ├── issues_test.php │ │ └── templates_test.php ├── template_test.php └── upgradelib_test.php ├── upload_image.php ├── version.php └── view.php /.gitattributes: -------------------------------------------------------------------------------- 1 | amd/build/** -diff 2 | -------------------------------------------------------------------------------- /.github/workflows/moodle-release.yml: -------------------------------------------------------------------------------- 1 | # 2 | # Whenever a new tag starting with "v" is pushed, add the tagged version 3 | # to the Moodle Plugins directory at https://moodle.org/plugins 4 | # 5 | # revision: 2021070201 6 | # 7 | name: Releasing in the Plugins directory 8 | 9 | on: 10 | push: 11 | tags: 12 | - v* 13 | 14 | workflow_dispatch: 15 | inputs: 16 | tag: 17 | description: 'Tag to be released' 18 | required: true 19 | 20 | defaults: 21 | run: 22 | shell: bash 23 | 24 | jobs: 25 | release-at-moodle-org: 26 | runs-on: ubuntu-latest 27 | env: 28 | PLUGIN: tool_certificate 29 | CURL: curl -s 30 | ENDPOINT: https://moodle.org/webservice/rest/server.php 31 | TOKEN: ${{ secrets.MOODLE_ORG_TOKEN }} 32 | FUNCTION: local_plugins_add_version 33 | 34 | steps: 35 | - name: Call the service function 36 | id: add-version 37 | run: | 38 | if [[ ! -z "${{ github.event.inputs.tag }}" ]]; then 39 | TAGNAME="${{ github.event.inputs.tag }}" 40 | elif [[ $GITHUB_REF = refs/tags/* ]]; then 41 | TAGNAME="${GITHUB_REF##*/}" 42 | fi 43 | if [[ -z "${TAGNAME}" ]]; then 44 | echo "No tag name has been provided!" 45 | exit 1 46 | fi 47 | ZIPURL="https://api.github.com/repos/${{ github.repository }}/zipball/${TAGNAME}" 48 | RESPONSE=$(${CURL} ${ENDPOINT} --data-urlencode "wstoken=${TOKEN}" \ 49 | --data-urlencode "wsfunction=${FUNCTION}" \ 50 | --data-urlencode "moodlewsrestformat=json" \ 51 | --data-urlencode "frankenstyle=${PLUGIN}" \ 52 | --data-urlencode "zipurl=${ZIPURL}" \ 53 | --data-urlencode "vcssystem=git" \ 54 | --data-urlencode "vcsrepositoryurl=${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}" \ 55 | --data-urlencode "vcstag=${TAGNAME}" \ 56 | --data-urlencode "changelogurl=${GITHUB_SERVER_URL}/${GITHUB_REPOSITORY}/commits/${TAGNAME}" \ 57 | --data-urlencode "altdownloadurl=${ZIPURL}") 58 | echo "response=${RESPONSE}" >> $GITHUB_OUTPUT 59 | 60 | - name: Evaluate the response 61 | id: evaluate-response 62 | env: 63 | RESPONSE: ${{ steps.add-version.outputs.response }} 64 | run: | 65 | jq <<< ${RESPONSE} 66 | jq --exit-status ".id" <<< ${RESPONSE} > /dev/null 67 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | phpunit.xml 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Certificate manager 2 | =================== 3 | 4 | This plugin allows users to create certificate templates on the system and course category levels. 5 | Certificate templates can have user fields such as user name, profile picture, etc, and also 6 | additional dynamic fields that are added by the issuer (through API). 7 | 8 | The built-in interface allows users to issue certificates manually and browse the issued certificates. 9 | 10 | A verification code / link / QR code can be added to the certificate template. Certificates can be 11 | verified by unauthenticated users even on sites with forced login and no guest access. 12 | 13 | Other plugins can depend on this plugin to issue certificates based on some criteria, for 14 | example **Course certificates (mod_coursecertificate)** is an activity module that will automatically 15 | issue certificates when the student satisfies the access restrictions. The mod_coursecertificate 16 | plugin will send the course name and completion information to the tool_certificate plugin, so 17 | if these fields are included in the template, they will be displayed on the certificate. 18 | 19 | Acknowledgements and history 20 | ---------------------------- 21 | 22 | This plugin was originally copied from mod_customcert plugin. Big thanks to Mark Nelson for all the 23 | work on it. 24 | 25 | Certificate manager has a different approach to storing templates and issuing certificates. It is 26 | completely independent of mod_customcert and both plugins can be used at the same time without 27 | any conflicts. 28 | 29 | There are a lot of similarities but there are also significant structural differences, such as: 30 | 31 | - Templates are designed on system and course category levels (and not inside the courses) 32 | - Allows viewing cross-course reports on issued certificates 33 | - Allows issuing certificates manually and not linked to any courses 34 | - Provides API to issue certificates from other plugins with customisable dynamic fields 35 | - Generated PDFs are stored and contain information as it was at the moment when the certificate 36 | was issued; certificate is still available even if user data is changed, course is deleted, etc. 37 | - Has some improvements to the UX 38 | - It is not a course activity plugin but an admin tool plugin (see also mod_coursecertificate) 39 | 40 | API 41 | --- 42 | 43 | As mentioned above, this plugin works best in combination with other plugins. For example, in 44 | Moodle Workplace it is used by Dynamic rules to automatically issue certificates on completion 45 | of Programs, Certifications and Courses. Information about those programs, certifications and 46 | courses is added to the issue data. 47 | 48 | Plugins can implement a callback in lib.php: 49 | 50 | function PLUGINNAME_tool_certificate_fields() {} 51 | 52 | In this callback the plugin can define additional fields that the plugin can send. The Certificate 53 | Manager then will make these fields available in the Template designer. You can find an example 54 | of this callback in mod_coursecertificate. 55 | 56 | To retrieve a list of templates available in the context: 57 | 58 | \tool_certificate\permission::get_visible_templates($context) 59 | 60 | To issue certificate: 61 | 62 | $template = \tool_certificate\template::instance($templateid); 63 | $template->issue_certificate(....) 64 | -------------------------------------------------------------------------------- /adminlib.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * This file contains the classes for the admin settings of the certificate module. 19 | * 20 | * @package tool_certificate 21 | * @copyright 2018 Daniel Neis Araujo 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die(); 26 | 27 | require_once($CFG->libdir . '/adminlib.php'); 28 | 29 | /** 30 | * Admin page to manage element plugins 31 | * 32 | * @package tool_certificate 33 | * @copyright 2018 Daniel Neis Araujo 34 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 | */ 36 | class tool_certificate_admin_page_manage_element_plugins extends admin_externalpage { 37 | 38 | /** 39 | * The constructor - calls parent constructor 40 | * 41 | */ 42 | public function __construct() { 43 | $url = new moodle_url('/admin/tool/certificate/adminmanageplugins.php'); 44 | parent::__construct('tool_certificate_manageelementplugins', get_string('manageelementplugins', 'tool_certificate'), $url); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /adminmanageplugins.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Allows the admin to manage assignment plugins 19 | * 20 | * @package tool_certificate 21 | * @copyright 2018 Daniel Neis Araujo 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | require_once(__DIR__ . '/../../../config.php'); 26 | 27 | $action = optional_param('action', null, PARAM_PLUGIN); 28 | $plugin = optional_param('plugin', null, PARAM_PLUGIN); 29 | 30 | if (!empty($plugin)) { 31 | require_sesskey(); 32 | } 33 | 34 | $pluginmanager = new \tool_certificate\plugin_manager(); 35 | 36 | \admin_externalpage_setup('tool_certificate_manageelementplugins'); 37 | 38 | $pluginmanager->execute($action, $plugin); 39 | -------------------------------------------------------------------------------- /amd/build/form-potential-user-selector.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * User selector form on modal based on form-potential-user-selector 2016 Damyon Wiese. 3 | * 4 | * @module tool_certificate/form-potential-user-selector 5 | * @copyright 2018 David Matamoros 6 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 7 | */ 8 | define("tool_certificate/form-potential-user-selector",["jquery","core/ajax","core/templates","core/str"],(function($,Ajax,Templates,Str){return{processResults:function(selector,results){var users=[];return $.isArray(results)?($.each(results,(function(index,user){users.push({value:user.id,label:user._label})})),users):results},transport:function(selector,query,success,failure){Ajax.call([{methodname:"tool_certificate_potential_users_selector",args:{search:query,itemid:$(selector).data("itemid")}}])[0].then((function(results){var promises=[],i=0;return results.length<=100?($.each(results,(function(index,user){var ctx=user,identity=[];$.each(["idnumber","email","phone1","phone2","department","institution"],(function(i,k){void 0!==user[k]&&""!==user[k]&&(ctx.hasidentity=!0,identity.push(user[k]))})),ctx.identity=identity.join(", "),promises.push(Templates.render("tool_certificate/form-user-selector-suggestion",ctx))})),$.when.apply($.when,promises).then((function(){var args=arguments;$.each(results,(function(index,user){user._label=args[i],i++})),success(results)}))):Str.get_string("toomanyuserstoshow","core",">100").then((function(toomanyuserstoshow){success(toomanyuserstoshow)}))})).fail(failure)}}})); 9 | 10 | //# sourceMappingURL=form-potential-user-selector.min.js.map -------------------------------------------------------------------------------- /amd/build/template-details.min.js: -------------------------------------------------------------------------------- 1 | define("tool_certificate/template-details",["exports","core_form/dynamicform","core/notification","core/str","core/prefetch","core/toast"],(function(_exports,_dynamicform,_notification,_str,_prefetch,_toast){function _interopRequireDefault(obj){return obj&&obj.__esModule?obj:{default:obj}} 2 | /** 3 | * Module used when editing template details 4 | * 5 | * @module tool_certificate/template-details 6 | * @copyright 2022 Ruslan Kabalin 7 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 8 | */Object.defineProperty(_exports,"__esModule",{value:!0}),_exports.default=void 0,_dynamicform=_interopRequireDefault(_dynamicform),_notification=_interopRequireDefault(_notification);var _default={init:()=>{(0,_prefetch.prefetchStrings)("moodle",["changessaved"]);const dynamicForm=new _dynamicform.default(document.querySelector("#template-details"),"tool_certificate\\form\\details");dynamicForm.addEventListener(dynamicForm.events.FORM_SUBMITTED,(e=>{e.preventDefault(),dynamicForm.load({id:e.detail.id}),(0,_str.get_string)("changessaved","moodle").then((string=>((0,_toast.add)(string,{type:"success"}),null))).catch(_notification.default.exception)}))}};return _exports.default=_default,_exports.default})); 9 | 10 | //# sourceMappingURL=template-details.min.js.map -------------------------------------------------------------------------------- /amd/build/template-details.min.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"file":"template-details.min.js","sources":["../src/template-details.js"],"sourcesContent":["// This file is part of the tool_certificate plugin for Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Module used when editing template details\n *\n * @module tool_certificate/template-details\n * @copyright 2022 Ruslan Kabalin\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport DynamicForm from 'core_form/dynamicform';\nimport Notification from 'core/notification';\nimport {get_string as getString} from 'core/str';\nimport {prefetchStrings} from 'core/prefetch';\nimport {add as addToast} from 'core/toast';\n\nconst init = () => {\n prefetchStrings('moodle', [\n 'changessaved',\n ]);\n\n const dynamicForm = new DynamicForm(document.querySelector('#template-details'), 'tool_certificate\\\\form\\\\details');\n dynamicForm.addEventListener(dynamicForm.events.FORM_SUBMITTED, (e) => {\n e.preventDefault();\n dynamicForm.load({id: e.detail.id});\n getString('changessaved', 'moodle').then((string) => {\n addToast(string, {type: 'success'});\n return null;\n }).catch(Notification.exception);\n });\n};\n\nexport default {\n init: init\n};\n"],"names":["init","dynamicForm","DynamicForm","document","querySelector","addEventListener","events","FORM_SUBMITTED","e","preventDefault","load","id","detail","then","string","type","catch","Notification","exception"],"mappings":";;;;;;;wMA6Ce,CACXA,KAjBS,mCACO,SAAU,CACtB,uBAGEC,YAAc,IAAIC,qBAAYC,SAASC,cAAc,qBAAsB,mCACjFH,YAAYI,iBAAiBJ,YAAYK,OAAOC,gBAAiBC,IAC7DA,EAAEC,iBACFR,YAAYS,KAAK,CAACC,GAAIH,EAAEI,OAAOD,yBACrB,eAAgB,UAAUE,MAAMC,wBAC7BA,OAAQ,CAACC,KAAM,YACjB,QACRC,MAAMC,sBAAaC"} -------------------------------------------------------------------------------- /amd/src/template-details.js: -------------------------------------------------------------------------------- 1 | // This file is part of the tool_certificate plugin for Moodle - http://moodle.org/ 2 | // 3 | // Moodle is free software: you can redistribute it and/or modify 4 | // it under the terms of the GNU General Public License as published by 5 | // the Free Software Foundation, either version 3 of the License, or 6 | // (at your option) any later version. 7 | // 8 | // Moodle is distributed in the hope that it will be useful, 9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | // GNU General Public License for more details. 12 | // 13 | // You should have received a copy of the GNU General Public License 14 | // along with Moodle. If not, see . 15 | 16 | /** 17 | * Module used when editing template details 18 | * 19 | * @module tool_certificate/template-details 20 | * @copyright 2022 Ruslan Kabalin 21 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 22 | */ 23 | 24 | import DynamicForm from 'core_form/dynamicform'; 25 | import Notification from 'core/notification'; 26 | import {get_string as getString} from 'core/str'; 27 | import {prefetchStrings} from 'core/prefetch'; 28 | import {add as addToast} from 'core/toast'; 29 | 30 | const init = () => { 31 | prefetchStrings('moodle', [ 32 | 'changessaved', 33 | ]); 34 | 35 | const dynamicForm = new DynamicForm(document.querySelector('#template-details'), 'tool_certificate\\form\\details'); 36 | dynamicForm.addEventListener(dynamicForm.events.FORM_SUBMITTED, (e) => { 37 | e.preventDefault(); 38 | dynamicForm.load({id: e.detail.id}); 39 | getString('changessaved', 'moodle').then((string) => { 40 | addToast(string, {type: 'success'}); 41 | return null; 42 | }).catch(Notification.exception); 43 | }); 44 | }; 45 | 46 | export default { 47 | init: init 48 | }; 49 | -------------------------------------------------------------------------------- /certificates.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Manage issued certificates for a given templateid. 19 | * 20 | * @package tool_certificate 21 | * @copyright 2018 Daniel Neis Araujo 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | require_once('../../../config.php'); 26 | require_once($CFG->libdir.'/adminlib.php'); 27 | 28 | $download = optional_param('download', null, PARAM_ALPHA); 29 | $templateid = required_param('templateid', PARAM_INT); 30 | 31 | $confirm = optional_param('confirm', 0, PARAM_INT); 32 | 33 | $page = optional_param('page', 0, PARAM_INT); 34 | $perpage = optional_param('perpage', \tool_certificate\certificate::ISSUES_PER_PAGE, PARAM_INT); 35 | 36 | $pageurl = $url = new moodle_url('/admin/tool/certificate/certificates.php', ['templateid' => $templateid]); 37 | $PAGE->set_url($pageurl); 38 | $template = \tool_certificate\template::instance($templateid); 39 | if ($coursecontext = $template->get_context()->get_course_context(false)) { 40 | require_login($coursecontext->instanceid); 41 | } else { 42 | admin_externalpage_setup('tool_certificate/managetemplates', '', null, $pageurl, ['nosearch' => true]); 43 | } 44 | 45 | if (!$template->can_view_issues()) { 46 | throw new moodle_exception('issueormangenotallowed', 'tool_certificate'); 47 | } 48 | 49 | $heading = $title = $template->get_formatted_name(); 50 | if ($template->get_shared()) { 51 | $heading .= html_writer::tag('div', get_string('shared', 'tool_certificate'), 52 | ['class' => 'badge rounded-pill bg-secondary text-dark font-small ms-2 align-middle']); 53 | } 54 | $PAGE->navbar->add($title, $pageurl); 55 | $PAGE->set_title($title); 56 | $PAGE->set_heading($heading, false); 57 | 58 | // Secondary navigation. 59 | $secondarynav = new \tool_certificate\local\views\template_secondary($PAGE, $template); 60 | $secondarynav->initialise(); 61 | $PAGE->set_secondarynav($secondarynav); 62 | 63 | $outputpage = new \tool_certificate\output\issues_page($template->get_id()); 64 | 65 | $data = $outputpage->export_for_template($PAGE->get_renderer('core')); 66 | $data += ['heading' => get_string('issuedcertificates', 'tool_certificate')]; 67 | if ($template->can_issue_to_anybody()) { 68 | $data += ['addbutton' => true, 'addbuttontitle' => get_string('issuecertificates', 'tool_certificate'), 69 | 'addbuttonurl' => null, 'addbuttonattrs' => ['name' => 'data-tid', 'value' => $template->get_id()], 70 | 'addbuttonicon' => true, ]; 71 | } 72 | $PAGE->requires->js_call_amd('tool_certificate/issues-list', 'init'); 73 | 74 | echo $OUTPUT->header(); 75 | echo $OUTPUT->render_from_template('tool_certificate/content_with_heading', $data); 76 | echo $OUTPUT->footer(); 77 | -------------------------------------------------------------------------------- /classes/admin_externalpage.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Class admin_externalpage 19 | * 20 | * @package tool_certificate 21 | * @copyright 2019 Marina Glancy 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | namespace tool_certificate; 26 | 27 | defined('MOODLE_INTERNAL') || die(); 28 | 29 | global $CFG; 30 | require_once($CFG->libdir . '/adminlib.php'); 31 | 32 | /** 33 | * Class admin_externalpage 34 | * 35 | * @package tool_certificate 36 | * @copyright 2019 Marina Glancy 37 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 38 | */ 39 | class admin_externalpage extends \admin_externalpage { 40 | 41 | /** @var callable */ 42 | protected $accesscheckcallback; 43 | 44 | /** 45 | * admin_externalpage constructor. 46 | * 47 | * @param string $name 48 | * @param string $visiblename 49 | * @param string $url 50 | * @param callable $accesscheckcallback a method that will be executed to check if user has permission 51 | * to access this item. The instance of this setting ($this) is passed as an argument to this callback. 52 | * @param bool $hidden 53 | */ 54 | public function __construct(string $name, string $visiblename, string $url, callable $accesscheckcallback, 55 | bool $hidden = false) { 56 | parent::__construct($name, $visiblename, $url, [], $hidden); 57 | $this->accesscheckcallback = $accesscheckcallback; 58 | } 59 | 60 | /** 61 | * see \admin_externalpage 62 | * 63 | * @return bool Returns true for yes false for no 64 | */ 65 | public function check_access() { 66 | $callback = $this->accesscheckcallback; 67 | return $callback($this); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /classes/event/certificate_issued.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * The tool_certificate certificate issued event. 19 | * 20 | * @package tool_certificate 21 | * @copyright 2018 Daniel Neis Araujo 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | namespace tool_certificate\event; 26 | 27 | use tool_certificate\template; 28 | 29 | /** 30 | * The tool_certificate certificate issued event class. 31 | * 32 | * @package tool_certificate 33 | * @copyright 2018 Daniel Neis Araujo 34 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 | */ 36 | class certificate_issued extends \core\event\base { 37 | 38 | /** 39 | * Init method. 40 | * 41 | * @return void 42 | */ 43 | protected function init() { 44 | $this->data['crud'] = 'c'; 45 | $this->data['edulevel'] = self::LEVEL_OTHER; 46 | $this->data['objecttable'] = 'tool_certificate_issues'; 47 | } 48 | 49 | /** 50 | * Create instance of event. 51 | * 52 | * @param \stdClass $issue 53 | * @return certificate_issued 54 | */ 55 | public static function create_from_issue(\stdClass $issue) { 56 | global $DB; 57 | 58 | $context = \context_system::instance(); 59 | if ($DB->record_exists('course', ['id' => $issue->courseid])) { 60 | $context = \context_course::instance($issue->courseid); 61 | } 62 | $data = [ 63 | 'context' => $context, 64 | 'objectid' => $issue->id, 65 | 'relateduserid' => $issue->userid, 66 | 'other' => [ 67 | 'code' => $issue->code, 68 | ], 69 | ]; 70 | $event = self::create($data); 71 | $event->add_record_snapshot('tool_certificate_issues', $issue); 72 | return $event; 73 | } 74 | 75 | /** 76 | * Returns description of what happened. 77 | * 78 | * @return string 79 | */ 80 | public function get_description() { 81 | return "The certificate issue with id '$this->objectid' has been created for user with id '$this->relateduserid'."; 82 | } 83 | 84 | /** 85 | * Return localised event name. 86 | * 87 | * @return string 88 | */ 89 | public static function get_name() { 90 | return get_string('eventcertificateissued', 'tool_certificate'); 91 | } 92 | 93 | /** 94 | * Get URL related to the action 95 | * 96 | * @return \moodle_url 97 | */ 98 | public function get_url() { 99 | return template::view_url($this->other['code']); 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /classes/event/certificate_regenerated.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | namespace tool_certificate\event; 18 | 19 | use tool_certificate\template; 20 | 21 | /** 22 | * The tool_certificate certificate regenerated event class. 23 | * 24 | * @package tool_certificate 25 | * @copyright 2024 Odei Alba 26 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 27 | * 28 | * @property-read array $other { 29 | * Extra information about the event. 30 | * 31 | * - string code: The code of the issued certificate 32 | * } 33 | */ 34 | class certificate_regenerated extends \core\event\base { 35 | 36 | /** 37 | * Init method. 38 | */ 39 | protected function init() { 40 | $this->data['crud'] = 'u'; 41 | $this->data['edulevel'] = self::LEVEL_OTHER; 42 | $this->data['objecttable'] = 'tool_certificate_issues'; 43 | } 44 | 45 | /** 46 | * Create instance of event. 47 | * 48 | * @param \stdClass $issue 49 | * @return certificate_regenerated 50 | */ 51 | public static function create_from_issue(\stdClass $issue) { 52 | global $DB; 53 | 54 | $context = \context_system::instance(); 55 | if ($DB->record_exists('course', ['id' => $issue->courseid])) { 56 | $context = \context_course::instance($issue->courseid); 57 | } 58 | $data = [ 59 | 'context' => $context, 60 | 'objectid' => $issue->id, 61 | 'relateduserid' => $issue->userid, 62 | 'other' => [ 63 | 'code' => $issue->code, 64 | ], 65 | ]; 66 | $event = self::create($data); 67 | $event->add_record_snapshot('tool_certificate_issues', $issue); 68 | return $event; 69 | } 70 | 71 | /** 72 | * Returns description of what happened. 73 | * 74 | * @return string 75 | */ 76 | public function get_description() { 77 | return "The issued certificate with id '$this->objectid' has been regenerated for user with id '$this->relateduserid'."; 78 | } 79 | 80 | /** 81 | * Return localised event name. 82 | * 83 | * @return string 84 | */ 85 | public static function get_name() { 86 | return get_string('eventcertificateregenerated', 'tool_certificate'); 87 | } 88 | 89 | /** 90 | * Get URL related to the action 91 | * 92 | * @return \moodle_url 93 | */ 94 | public function get_url() { 95 | return template::view_url($this->other['code']); 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /classes/event/template_created.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * The tool_certificate template created event. 19 | * 20 | * @package tool_certificate 21 | * @copyright 2018 Daniel Neis Araujo 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | namespace tool_certificate\event; 26 | 27 | use tool_certificate\template; 28 | 29 | /** 30 | * The tool_certificate template created event class. 31 | * 32 | * @package tool_certificate 33 | * @copyright 2018 Daniel Neis Araujo 34 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 | */ 36 | class template_created extends \core\event\base { 37 | 38 | /** 39 | * Init method. 40 | * 41 | * @return void 42 | */ 43 | protected function init() { 44 | $this->data['crud'] = 'c'; 45 | $this->data['edulevel'] = self::LEVEL_OTHER; 46 | $this->data['objecttable'] = 'tool_certificate_templates'; 47 | } 48 | 49 | /** 50 | * Returns description of what happened. 51 | * 52 | * @return string 53 | */ 54 | public function get_description() { 55 | return "The user with id '$this->userid' has created the template with id '$this->objectid'."; 56 | } 57 | 58 | /** 59 | * Return localised event name. 60 | * 61 | * @return string 62 | */ 63 | public static function get_name() { 64 | return get_string('eventtemplatecreated', 'tool_certificate'); 65 | } 66 | 67 | /** 68 | * Create instance of event. 69 | * 70 | * @param template $template 71 | * @return template_created 72 | */ 73 | public static function create_from_template(template $template): template_created { 74 | $data = [ 75 | 'context' => $template->get_context(), 76 | 'objectid' => $template->get_id(), 77 | ]; 78 | $event = self::create($data); 79 | $event->add_record_snapshot('tool_certificate_templates', $template->to_record()); 80 | return $event; 81 | } 82 | 83 | /** 84 | * Get URL related to the action 85 | * 86 | * @return \moodle_url 87 | */ 88 | public function get_url() { 89 | return new \moodle_url('/admin/tool/certificate/template.php', ['id' => $this->objectid]); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /classes/event/template_deleted.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * The tool_certificate template created event. 19 | * 20 | * @package tool_certificate 21 | * @copyright 2018 Daniel Neis Araujo 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | namespace tool_certificate\event; 26 | 27 | use tool_certificate\template; 28 | 29 | /** 30 | * The tool_certificate template created event class. 31 | * 32 | * @package tool_certificate 33 | * @copyright 2018 Daniel Neis Araujo 34 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 | */ 36 | class template_deleted extends \core\event\base { 37 | 38 | /** 39 | * Init method. 40 | * 41 | * @return void 42 | */ 43 | protected function init() { 44 | $this->data['crud'] = 'd'; 45 | $this->data['edulevel'] = self::LEVEL_OTHER; 46 | $this->data['objecttable'] = 'tool_certificate_templates'; 47 | } 48 | 49 | /** 50 | * Returns description of what happened. 51 | * 52 | * @return string 53 | */ 54 | public function get_description() { 55 | return "The user with id '$this->userid' has deleted the template with id '$this->objectid'."; 56 | } 57 | 58 | /** 59 | * Return localised event name. 60 | * 61 | * @return string 62 | */ 63 | public static function get_name() { 64 | return get_string('eventtemplatedeleted', 'tool_certificate'); 65 | } 66 | 67 | /** 68 | * Get URL related to the action 69 | * 70 | * @return \moodle_url 71 | */ 72 | public function get_url() { 73 | return new \moodle_url('/admin/tool/certificate/manage_templates.php'); 74 | } 75 | 76 | /** 77 | * Create instance of event. 78 | * 79 | * @param template $template 80 | * @return template_deleted 81 | */ 82 | public static function create_from_template(template $template): template_deleted { 83 | $data = [ 84 | 'context' => $template->get_context(), 85 | 'objectid' => $template->get_id(), 86 | ]; 87 | $event = self::create($data); 88 | $event->add_record_snapshot('tool_certificate_templates', $template->to_record()); 89 | return $event; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /classes/event/template_updated.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * The tool_certificate template created event. 19 | * 20 | * @package tool_certificate 21 | * @copyright 2018 Daniel Neis Araujo 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | namespace tool_certificate\event; 26 | 27 | use tool_certificate\template; 28 | 29 | /** 30 | * The tool_certificate template created event class. 31 | * 32 | * @package tool_certificate 33 | * @copyright 2018 Daniel Neis Araujo 34 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 | */ 36 | class template_updated extends \core\event\base { 37 | 38 | /** 39 | * Init method. 40 | * 41 | * @return void 42 | */ 43 | protected function init() { 44 | $this->data['crud'] = 'u'; 45 | $this->data['edulevel'] = self::LEVEL_OTHER; 46 | $this->data['objecttable'] = 'tool_certificate_templates'; 47 | } 48 | 49 | /** 50 | * Returns description of what happened. 51 | * 52 | * @return string 53 | */ 54 | public function get_description() { 55 | return "The user with id '$this->userid' has updated the template with id '$this->objectid'."; 56 | } 57 | 58 | /** 59 | * Return localised event name. 60 | * 61 | * @return string 62 | */ 63 | public static function get_name() { 64 | return get_string('eventtemplateupdated', 'tool_certificate'); 65 | } 66 | 67 | /** 68 | * Get URL related to the action 69 | * 70 | * @return \moodle_url 71 | */ 72 | public function get_url() { 73 | return new \moodle_url('/admin/tool/certificate/template.php', ['id' => $this->objectid]); 74 | } 75 | 76 | /** 77 | * Create instance of event. 78 | * 79 | * @param template $template 80 | * @return template_updated 81 | */ 82 | public static function create_from_template(template $template): template_updated { 83 | $data = [ 84 | 'context' => $template->get_context(), 85 | 'objectid' => $template->get_id(), 86 | ]; 87 | $event = self::create($data); 88 | $event->add_record_snapshot('tool_certificate_templates', $template->to_record()); 89 | return $event; 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /classes/local/views/template_secondary.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | namespace tool_certificate\local\views; 18 | 19 | use core\navigation\views\secondary as core_secondary; 20 | use tool_certificate\template; 21 | 22 | /** 23 | * Class tool_certificate\local\views\template_secondary 24 | * 25 | * @package tool_certificate 26 | * @copyright 2022 Moodle Pty Ltd 27 | * @author 2022 Ruslan Kabalin 28 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 29 | */ 30 | class template_secondary extends core_secondary { 31 | 32 | /** @var template */ 33 | protected $template; 34 | 35 | /** 36 | * Navigation constructor. 37 | * 38 | * @param \moodle_page $page 39 | * @param template $template 40 | */ 41 | public function __construct(\moodle_page $page, template $template) { 42 | $this->template = $template; 43 | parent::__construct($page); 44 | } 45 | 46 | /** 47 | * Initialise the view based navigation based on the current context. 48 | */ 49 | public function initialise(): void { 50 | if ($this->template->can_manage()) { 51 | $this->add(get_string('template', 'tool_certificate'), 52 | new \moodle_url('/admin/tool/certificate/template.php', ['id' => $this->template->get_id()]), 53 | null, null, 'template'); 54 | $this->add(get_string('details'), 55 | new \moodle_url('/admin/tool/certificate/template_details.php', ['id' => $this->template->get_id()]), 56 | null, null, 'details'); 57 | } 58 | if ($this->template->can_view_issues()) { 59 | $this->add(get_string('issuedcertificates', 'tool_certificate'), 60 | new \moodle_url('/admin/tool/certificate/certificates.php', ['templateid' => $this->template->get_id()]), 61 | null, null, 'issuedcertificates'); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /classes/observer.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Class observer for tool_certificate. 19 | * 20 | * @package tool_certificate 21 | * @author 2020 Mikel Martín 22 | * @copyright 2020 Moodle Pty Ltd 23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 | */ 25 | 26 | /** 27 | * Class tool_certificate_observer 28 | * 29 | * @package tool_certificate 30 | * @author 2020 Mikel Martín 31 | * @copyright 2020 Moodle Pty Ltd 32 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 33 | */ 34 | class tool_certificate_observer { 35 | /** 36 | * Course deleted observer 37 | * 38 | * @param \core\event\course_content_deleted $event 39 | */ 40 | public static function on_course_content_deleted(\core\event\course_content_deleted $event): void { 41 | global $DB; 42 | 43 | $fs = get_file_storage(); 44 | $issues = $DB->get_records('tool_certificate_issues', ['courseid' => $event->courseid]); 45 | foreach ($issues as $issue) { 46 | $fs->delete_area_files(context_system::instance()->id, 'tool_certificate', 'issues', $issue->id); 47 | } 48 | 49 | $DB->delete_records('tool_certificate_issues', ['courseid' => $event->courseid]); 50 | 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /classes/output/email/renderer.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Email certificate as html renderer. 19 | * 20 | * @package tool_certificate 21 | * @copyright 2017 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | namespace tool_certificate\output\email; 26 | 27 | /** 28 | * Email certificate as html renderer. 29 | * 30 | * @package tool_certificate 31 | * @copyright 2017 Mark Nelson 32 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 33 | */ 34 | class renderer extends \plugin_renderer_base { 35 | 36 | /** 37 | * The template name for this renderer. 38 | * 39 | * @return string 40 | */ 41 | public function get_template_name() { 42 | return 'email_certificate_html'; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /classes/output/email/renderer_textemail.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Email certificate as text renderer. 19 | * 20 | * @package tool_certificate 21 | * @copyright 2017 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | namespace tool_certificate\output\email; 26 | 27 | /** 28 | * Email certificate as text renderer. 29 | * 30 | * @package tool_certificate 31 | * @copyright 2017 Mark Nelson 32 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 33 | */ 34 | class renderer_textemail extends \plugin_renderer_base { 35 | 36 | /** 37 | * The template name for this renderer. 38 | * 39 | * @return string 40 | */ 41 | public function get_template_name() { 42 | return 'email_certificate_text'; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /classes/output/issues_page.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | namespace tool_certificate\output; 18 | 19 | use core_reportbuilder\system_report_factory; 20 | use renderer_base; 21 | use tool_certificate\reportbuilder\local\systemreports\issues; 22 | use tool_certificate\template; 23 | 24 | /** 25 | * Class tool_certificate\output\issues_page 26 | * 27 | * @package tool_certificate 28 | * @copyright 2022 Moodle Pty Ltd 29 | * @author 2022 Odei Alba 30 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 31 | */ 32 | class issues_page implements \templatable, \renderable { 33 | /** @var int */ 34 | protected $templateid; 35 | 36 | /** 37 | * templates_page constructor. 38 | * 39 | * @param int $templateid 40 | */ 41 | public function __construct(int $templateid) { 42 | $this->templateid = $templateid; 43 | } 44 | 45 | /** 46 | * Implementation of exporter from templatable interface 47 | * 48 | * @param renderer_base $output 49 | * @return array 50 | */ 51 | public function export_for_template(renderer_base $output): array { 52 | $context = template::instance($this->templateid)->get_context(); 53 | $report = system_report_factory::create(issues::class, $context, 54 | '', '', 0, ['templateid' => $this->templateid]); 55 | 56 | return ['content' => $report->output()]; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /classes/output/page_header_button.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Class heading_button 19 | * 20 | * @package tool_certificate 21 | * @copyright 2019 Marina Glancy 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | namespace tool_certificate\output; 26 | 27 | use renderer_base; 28 | 29 | /** 30 | * Class heading_button 31 | * 32 | * @package tool_certificate 33 | * @copyright 2019 Marina Glancy 34 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 | */ 36 | class page_header_button implements \templatable, \renderable { 37 | 38 | /** @var string */ 39 | protected $title; 40 | /** @var array */ 41 | protected $attributes; 42 | 43 | /** 44 | * heading_button constructor. 45 | * 46 | * @param string $title 47 | * @param array $attributes 48 | */ 49 | public function __construct(string $title, array $attributes = []) { 50 | $this->title = $title; 51 | $this->attributes = $attributes; 52 | } 53 | 54 | /** 55 | * Export for template 56 | * 57 | * @param renderer_base $output 58 | * @return array|\stdClass 59 | */ 60 | public function export_for_template(renderer_base $output) { 61 | $data = ['title' => $this->title, 'attributes' => []]; 62 | foreach ($this->attributes as $key => $value) { 63 | if ($key === 'class') { 64 | $data['class'] = $value; 65 | } else { 66 | $data['attributes'][] = ['name' => $key, 'value' => $value]; 67 | } 68 | } 69 | return $data; 70 | } 71 | 72 | /** 73 | * Renders the button 74 | * 75 | * @param renderer_base $output 76 | * @return string 77 | */ 78 | public function render(renderer_base $output): string { 79 | return $output->render_from_template('tool_certificate/page_header_button', $this->export_for_template($output)); 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /classes/output/templates_page.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | namespace tool_certificate\output; 18 | 19 | use core_reportbuilder\system_report_factory; 20 | use renderer_base; 21 | use tool_certificate\reportbuilder\local\systemreports\templates; 22 | 23 | /** 24 | * Class tool_certificate\output\templates_page 25 | * 26 | * @package tool_certificate 27 | * @copyright 2022 Moodle Pty Ltd 28 | * @author 2022 Odei Alba 29 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 30 | */ 31 | class templates_page implements \templatable, \renderable { 32 | /** 33 | * templates_page constructor. 34 | */ 35 | public function __construct() { 36 | } 37 | 38 | /** 39 | * Implementation of exporter from templatable interface 40 | * 41 | * @param renderer_base $output 42 | * 43 | * @return array|\stdClass 44 | * @throws \coding_exception 45 | */ 46 | public function export_for_template(renderer_base $output) { 47 | $report = system_report_factory::create(templates::class, \context_system::instance()); 48 | 49 | return ['content' => $report->output()]; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /classes/output/verify_certificate_results.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Contains class used to prepare verification results for display. 19 | * 20 | * @package tool_certificate 21 | * @copyright 2017 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | namespace tool_certificate\output; 26 | 27 | use renderable; 28 | use templatable; 29 | 30 | /** 31 | * Class to prepare verification results for display. 32 | * 33 | * @package tool_certificate 34 | * @copyright 2017 Mark Nelson 35 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 36 | */ 37 | class verify_certificate_results implements templatable, renderable { 38 | 39 | /** 40 | * @var bool Was the code successfully verified? 41 | */ 42 | public $success; 43 | 44 | /** 45 | * @var string The message to display. 46 | */ 47 | public $message; 48 | 49 | /** 50 | * @var array The certificates issued with the matching code. 51 | */ 52 | public $issues; 53 | 54 | /** @var stdClass */ 55 | protected $issue; 56 | 57 | /** 58 | * Constructor. 59 | * 60 | * @param \stdClass $result 61 | */ 62 | public function __construct($result) { 63 | $this->success = $result->success; 64 | if ($this->success) { 65 | $this->issue = $result->issue; 66 | $this->message = get_string('verified', 'tool_certificate'); 67 | } else { 68 | $this->message = get_string('notverified', 'tool_certificate'); 69 | } 70 | } 71 | 72 | /** 73 | * Function to export the renderer data in a format that is suitable for a mustache template. 74 | * 75 | * @param \renderer_base $output Used to do a final render of any components that need to be rendered for export. 76 | * @return \stdClass|array 77 | */ 78 | public function export_for_template(\renderer_base $output) { 79 | $result = new \stdClass(); 80 | $result->success = $this->success; 81 | $result->message = $this->message; 82 | if (isset($this->issue)) { 83 | $resultissue = new verify_certificate_result($this->issue); 84 | $result->issue = $resultissue->export_for_template($output); 85 | } 86 | return $result; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /classes/persistent/page.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Class page 19 | * 20 | * @package tool_certificate 21 | * @copyright 2019 Marina Glancy 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | namespace tool_certificate\persistent; 26 | 27 | use core\persistent; 28 | 29 | /** 30 | * Class page 31 | * 32 | * @package tool_certificate 33 | * @copyright 2019 Marina Glancy 34 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 | */ 36 | class page extends persistent { 37 | 38 | /** @var string */ 39 | const TABLE = 'tool_certificate_pages'; 40 | 41 | /** 42 | * Return the definition of the properties of this model. 43 | * 44 | * @return array 45 | */ 46 | protected static function define_properties() { 47 | return [ 48 | 'templateid' => [ 49 | 'type' => PARAM_INT, 50 | ], 51 | 'width' => [ 52 | 'type' => PARAM_INT, 53 | 'default' => 297, 54 | ], 55 | 'height' => [ 56 | 'type' => PARAM_INT, 57 | 'default' => 210, 58 | ], 59 | 'leftmargin' => [ 60 | 'type' => PARAM_INT, 61 | 'default' => 0, 62 | ], 63 | 'rightmargin' => [ 64 | 'type' => PARAM_INT, 65 | 'default' => 0, 66 | ], 67 | 'sequence' => [ 68 | 'type' => PARAM_INT, 69 | 'default' => 0, 70 | ], 71 | ]; 72 | } 73 | 74 | /** 75 | * Magic setter for pageid 76 | * 77 | * @param int $value 78 | * @return element 79 | * @throws \coding_exception 80 | */ 81 | protected function set_templateid($value) { 82 | if ($this->get('id') && $this->get('templateid') && (int)$value != $this->get('templateid')) { 83 | throw new \coding_exception('Template of existing page can not be changed'); 84 | } 85 | return $this->raw_set('templateid', $value); 86 | } 87 | 88 | } 89 | -------------------------------------------------------------------------------- /classes/plugininfo/certificateelement.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Subplugin info class. 19 | * 20 | * @package tool_certificate 21 | * @copyright 2013 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | namespace tool_certificate\plugininfo; 25 | 26 | use core\plugininfo\base; 27 | 28 | /** 29 | * Subplugin info class. 30 | * 31 | * @package tool_certificate 32 | * @copyright 2013 Mark Nelson 33 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 34 | */ 35 | class certificateelement extends base { 36 | 37 | /** 38 | * Do not allow users to uninstall these plugins as it could cause certificates to break. 39 | * 40 | * @return bool 41 | */ 42 | public function is_uninstall_allowed() { 43 | return true; 44 | } 45 | 46 | /** 47 | * Loads plugin settings to the settings tree. 48 | * 49 | * @param \part_of_admin_tree $adminroot 50 | * @param string $parentnodename 51 | * @param bool $hassiteconfig whether the current user has moodle/site:config capability 52 | */ 53 | public function load_settings(\part_of_admin_tree $adminroot, $parentnodename, $hassiteconfig) { 54 | global $CFG, $USER, $DB, $OUTPUT, $PAGE; 55 | $ADMIN = $adminroot; 56 | $plugininfo = $this; 57 | 58 | if (!$this->is_installed_and_upgraded()) { 59 | return; 60 | } 61 | 62 | if (!$hassiteconfig || !file_exists($this->full_path('settings.php'))) { 63 | return; 64 | } 65 | 66 | $section = $this->get_settings_section_name(); 67 | $settings = new \admin_settingpage($section, $this->displayname, 'moodle/site:config', false); 68 | 69 | include($this->full_path('settings.php')); 70 | $ADMIN->add($parentnodename, $settings); 71 | } 72 | 73 | /** 74 | * Get the settings section name. 75 | * 76 | * @return null|string the settings section name. 77 | */ 78 | public function get_settings_section_name() { 79 | if (file_exists($this->full_path('settings.php'))) { 80 | return 'certificateelement_' . $this->name; 81 | } else { 82 | return null; 83 | } 84 | } 85 | 86 | /** 87 | * Return true if a plugin is enabled. 88 | * 89 | * @return bool 90 | */ 91 | public function is_enabled() { 92 | if ($disabled = get_config('certificateelement_' . $this->name, 'disabled')) { 93 | return $disabled == 0; 94 | } 95 | return true; 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /classes/reportbuilder/local/filters/status.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | declare(strict_types=1); 18 | 19 | namespace tool_certificate\reportbuilder\local\filters; 20 | 21 | use lang_string; 22 | use MoodleQuickForm; 23 | use core_reportbuilder\local\filters\boolean_select; 24 | 25 | /** 26 | * Certificate status report filter 27 | * 28 | * Overrides the operator language strings. 29 | * 30 | * @package tool_certificate 31 | * @copyright 2022 Moodle Pty Ltd 32 | * @author 2022 Ruslan Kabalin 33 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 34 | */ 35 | class status extends boolean_select { 36 | 37 | /** 38 | * Return an array of operators available for this filter 39 | * 40 | * @return lang_string[] 41 | */ 42 | private function get_operators(): array { 43 | return [ 44 | self::ANY_VALUE => new lang_string('filterisanyvalue', 'core_reportbuilder'), 45 | self::NOT_CHECKED => new lang_string('valid', 'tool_certificate'), 46 | self::CHECKED => new lang_string('expired', 'tool_certificate'), 47 | ]; 48 | } 49 | 50 | /** 51 | * Setup form 52 | * 53 | * @param MoodleQuickForm $mform 54 | */ 55 | public function setup_form(MoodleQuickForm $mform): void { 56 | $operatorlabel = get_string('filterfieldoperator', 'core_reportbuilder', $this->get_header()); 57 | $mform->addElement('select', "{$this->name}_operator", $operatorlabel, $this->get_operators()) 58 | ->setHiddenLabel(true); 59 | 60 | $mform->setType("{$this->name}_operator", PARAM_INT); 61 | $mform->setDefault("{$this->name}_operator", self::ANY_VALUE); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /classes/reportbuilder/local/filters/templatepermission.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | namespace tool_certificate\reportbuilder\local\filters; 18 | 19 | use core_reportbuilder\local\filters\base; 20 | use lang_string; 21 | use MoodleQuickForm; 22 | use tool_certificate\certificate; 23 | 24 | /** 25 | * Condition user has permission to access template 26 | * 27 | * @package tool_certificate 28 | * @copyright 2023 Marina Glancy 29 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 30 | */ 31 | class templatepermission extends base { 32 | 33 | /** 34 | * Return an array of operators available for this filter 35 | * 36 | * @return lang_string[] 37 | */ 38 | private function get_operators(): array { 39 | return [ 40 | 0 => new lang_string('templatepermissionany', 'tool_certificate'), 41 | 1 => new lang_string('templatepermissionyes', 'tool_certificate'), 42 | ]; 43 | } 44 | 45 | /** 46 | * Setup form 47 | * 48 | * @param MoodleQuickForm $mform 49 | */ 50 | public function setup_form(MoodleQuickForm $mform): void { 51 | $operatorlabel = get_string('filterfieldoperator', 'core_reportbuilder', $this->get_header()); 52 | $mform->addElement('select', "{$this->name}_operator", $operatorlabel, $this->get_operators()) 53 | ->setHiddenLabel(true); 54 | 55 | $mform->setType("{$this->name}_operator", PARAM_INT); 56 | $mform->setDefault("{$this->name}_operator", 0); 57 | } 58 | 59 | /** 60 | * Return filter SQL 61 | * 62 | * @param array $values 63 | * @return array 64 | */ 65 | public function get_sql_filter(array $values): array { 66 | $operator = $values["{$this->name}_operator"] ?? 0; 67 | if ($operator) { 68 | return certificate::get_visible_categories_contexts_sql($this->filter->get_field_sql()); 69 | } 70 | // Any other value. 71 | return ['', []]; 72 | } 73 | 74 | /** 75 | * Return sample filter values 76 | * 77 | * @return array 78 | */ 79 | public function get_sample_values(): array { 80 | return [ 81 | "{$this->name}_operator" => 1, 82 | ]; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /classes/tool_tenant.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Implementation of multi-tenancy (used only by plugin tool_tenant and nothing else) 19 | * 20 | * @package tool_certificate 21 | * @copyright 2020 Moodle Pty Ltd 22 | * @author 2020 Marina Glancy 23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 | */ 25 | 26 | namespace tool_certificate; 27 | 28 | /** 29 | * Implementation of multi-tenancy (used only by plugin tool_tenant and nothing else) 30 | * 31 | * @package tool_certificate 32 | * @copyright 2020 Moodle Pty Ltd 33 | * @author 2020 Marina Glancy 34 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 35 | */ 36 | class tool_tenant { 37 | 38 | /** 39 | * Callback used by tool_tenant to see which capabilities from this plugin are allowed for the "Tenant administrator" role 40 | * 41 | * @return array 42 | */ 43 | public static function get_tenant_admin_capabilities() { 44 | return [ 45 | 'tool/certificate:issue' => CAP_ALLOW, 46 | 'tool/certificate:viewallcertificates' => CAP_ALLOW, 47 | ]; 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /classes/upload_image_form.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * This file contains the class that handles uploading files. 19 | * 20 | * @package tool_certificate 21 | * @copyright 2013 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | namespace tool_certificate; 26 | 27 | defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.'); 28 | 29 | require_once($CFG->libdir.'/formslib.php'); 30 | 31 | /** 32 | * Handles uploading files. 33 | * 34 | * @package tool_certificate 35 | * @copyright 2013 Mark Nelson 36 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 37 | */ 38 | class upload_image_form extends \moodleform { 39 | 40 | /** @var array the filemanager options */ 41 | protected $filemanageroptions = []; 42 | 43 | /** 44 | * Form definition. 45 | */ 46 | public function definition() { 47 | global $CFG; 48 | 49 | $mform = $this->_form; 50 | $this->filemanageroptions = [ 51 | 'maxbytes' => $CFG->maxbytes, 52 | 'subdirs' => 1, 53 | 'accepted_types' => 'web_image', ]; 54 | $mform->addElement('filemanager', 'certificateimage', get_string('uploadimage', 'tool_certificate'), '', 55 | $this->filemanageroptions); 56 | 57 | $this->add_action_buttons(); 58 | } 59 | 60 | /** 61 | * Fill in the current page data for this certificate. 62 | */ 63 | public function definition_after_data() { 64 | $mform = $this->_form; 65 | 66 | // Editing existing instance - copy existing files into draft area. 67 | $draftitemid = file_get_submitted_draft_itemid('certificateimage'); 68 | file_prepare_draft_area($draftitemid, \context_system::instance()->id, 'tool_certificate', 'image', 0, 69 | $this->filemanageroptions); 70 | $element = $mform->getElement('certificateimage'); 71 | $element->setValue($draftitemid); 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /classes/verify_certificate_form.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * This files contains the form for verifying a certificate. 19 | * 20 | * @package tool_certificate 21 | * @copyright 2017 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | namespace tool_certificate; 26 | 27 | defined('MOODLE_INTERNAL') || die('Direct access to this script is forbidden.'); 28 | 29 | require_once($CFG->libdir . '/formslib.php'); 30 | 31 | /** 32 | * The form for verifying a certificate. 33 | * 34 | * @package tool_certificate 35 | * @copyright 2017 Mark Nelson 36 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 37 | */ 38 | class verify_certificate_form extends \moodleform { 39 | 40 | /** 41 | * Form definition. 42 | */ 43 | public function definition() { 44 | $mform =& $this->_form; 45 | 46 | $mform->addElement('text', 'code', get_string('code', 'tool_certificate')); 47 | $mform->setType('code', PARAM_ALPHANUM); 48 | $mform->addRule('code', null, 'required', null, 'client'); 49 | 50 | $mform->addElement('submit', 'verify', get_string('verify', 'tool_certificate')); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /customfield.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Manage course custom fields 19 | * 20 | * @package tool_certificate 21 | * @copyright 2019 Marina Glancy 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | require_once('../../../config.php'); 26 | require_once($CFG->libdir.'/adminlib.php'); 27 | 28 | admin_externalpage_setup('tool_certificate_customfield'); 29 | 30 | $output = $PAGE->get_renderer('core_customfield'); 31 | $handler = \tool_certificate\customfield\issue_handler::create(); 32 | $handler->create_custom_fields_if_not_exist(); 33 | $outputpage = new \core_customfield\output\management($handler); 34 | 35 | echo $output->header(), 36 | $output->heading(new lang_string('certificate_customfield', 'tool_certificate')), 37 | $output->render($outputpage), 38 | $output->footer(); 39 | -------------------------------------------------------------------------------- /db/access.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Customcert module capability definition 19 | * 20 | * @package tool_certificate 21 | * @copyright 2013 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die(); 26 | 27 | $capabilities = [ 28 | 29 | 'tool/certificate:manage' => [ 30 | 31 | 'captype' => 'write', 32 | 'contextlevel' => CONTEXT_COURSE, 33 | 'archetypes' => [ 34 | 'manager' => CAP_ALLOW, 35 | 'editingteacher' => CAP_ALLOW, 36 | ], 37 | ], 38 | 39 | 'tool/certificate:image' => [ 40 | 41 | 'captype' => 'write', 42 | 'contextlevel' => CONTEXT_SYSTEM, 43 | 'clonepermissionsfrom' => 'tool/certificate:imageforalltenants', 44 | ], 45 | 46 | 'tool/certificate:issue' => [ 47 | 48 | 'captype' => 'write', 49 | 'contextlevel' => CONTEXT_COURSE, 50 | 'archetypes' => [ 51 | 'manager' => CAP_ALLOW, 52 | 'teacher' => CAP_ALLOW, 53 | 'editingteacher' => CAP_ALLOW, 54 | ], 55 | ], 56 | 57 | 'tool/certificate:viewallcertificates' => [ 58 | 'captype' => 'read', 59 | 'contextlevel' => CONTEXT_COURSE, 60 | 'archetypes' => [ 61 | 'manager' => CAP_ALLOW, 62 | 'teacher' => CAP_ALLOW, 63 | 'editingteacher' => CAP_ALLOW, 64 | ], 65 | ], 66 | 67 | 'tool/certificate:verify' => [ 68 | 'captype' => 'read', 69 | 'contextlevel' => CONTEXT_SYSTEM, 70 | 'archetypes' => [ 71 | 'guest' => CAP_ALLOW, 72 | 'user' => CAP_ALLOW, 73 | ], 74 | ], 75 | ]; 76 | -------------------------------------------------------------------------------- /db/events.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Events for tool_certificate. 19 | * 20 | * @package tool_certificate 21 | * @copyright 2020 Moodle Pty Ltd 22 | * @author 2020 Mikel Martín 23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 | */ 25 | 26 | defined('MOODLE_INTERNAL') || die; 27 | 28 | $observers = [ 29 | [ 30 | 'eventname' => '\core\event\course_content_deleted', 31 | 'callback' => tool_certificate_observer::class . '::on_course_content_deleted', 32 | ], 33 | ]; 34 | -------------------------------------------------------------------------------- /db/install.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * tool_certificate installation script 19 | * 20 | * @package tool_certificate 21 | * @copyright 2020 Moodle Pty Ltd 22 | * @author 2020 Mikel Martín 23 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 24 | */ 25 | 26 | /** 27 | * Create a default certificate template. 28 | * 29 | * @return bool 30 | */ 31 | function xmldb_tool_certificate_install() { 32 | if (!defined('BEHAT_SITE_RUNNING') && !(defined('PHPUNIT_TEST') && PHPUNIT_TEST)) { 33 | \tool_certificate\certificate::create_demo_template(); 34 | } 35 | 36 | return true; 37 | } 38 | -------------------------------------------------------------------------------- /db/messages.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Defines message providers (types of messages being sent) 19 | * 20 | * @package tool_certificate 21 | * @copyright 2020 Mikel Martín 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | 26 | defined('MOODLE_INTERNAL') || die(); 27 | 28 | $messageproviders = [ 29 | // Notification for certificate issued. 30 | 'certificateissued' => [ 31 | 'defaults' => [ 32 | 'popup' => MESSAGE_PERMITTED + MESSAGE_DEFAULT_ENABLED, 33 | 'email' => MESSAGE_PERMITTED + MESSAGE_DEFAULT_ENABLED, 34 | ], 35 | ], 36 | ]; 37 | -------------------------------------------------------------------------------- /db/services.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Web service for tool certificate. 19 | * 20 | * @package tool_certificate 21 | * @copyright 2016 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die(); 26 | 27 | $functions = [ 28 | 'tool_certificate_revoke_issue' => [ 29 | 'classname' => \tool_certificate\external\issues::class, 30 | 'methodname' => 'revoke_issue', 31 | 'classpath' => '', 32 | 'description' => 'Revoke an issue for a certificate', 33 | 'type' => 'write', 34 | 'ajax' => true, 35 | 'services' => [MOODLE_OFFICIAL_MOBILE_SERVICE], 36 | ], 37 | 'tool_certificate_regenerate_issue_file' => [ 38 | 'classname' => \tool_certificate\external\issues::class, 39 | 'methodname' => 'regenerate_issue_file', 40 | 'description' => 'Regenerates an issue file', 41 | 'type' => 'write', 42 | 'ajax' => true, 43 | ], 44 | 'tool_certificate_duplicate_template' => [ 45 | 'classname' => \tool_certificate\external\templates::class, 46 | 'methodname' => 'duplicate_template', 47 | 'description' => 'Duplicates a template', 48 | 'type' => 'write', 49 | 'ajax' => true, 50 | ], 51 | 'tool_certificate_delete_template' => [ 52 | 'classname' => \tool_certificate\external\templates::class, 53 | 'methodname' => 'delete_template', 54 | 'description' => 'Deletes a template', 55 | 'type' => 'write', 56 | 'ajax' => true, 57 | ], 58 | 'tool_certificate_delete_element' => [ 59 | 'classname' => \tool_certificate\external\elements::class, 60 | 'methodname' => 'delete_element', 61 | 'description' => 'Deletes an element', 62 | 'type' => 'write', 63 | 'ajax' => true, 64 | ], 65 | 'tool_certificate_update_element' => [ 66 | 'classname' => \tool_certificate\external\elements::class, 67 | 'methodname' => 'update_element', 68 | 'description' => 'Updates an element', 69 | 'type' => 'write', 70 | 'ajax' => true, 71 | ], 72 | 'tool_certificate_potential_users_selector' => [ 73 | 'classname' => \tool_certificate\external\issues::class, 74 | 'methodname' => 'potential_users_selector', 75 | 'description' => 'get list of users', 76 | 'type' => 'read', 77 | 'ajax' => true, 78 | ], 79 | ]; 80 | -------------------------------------------------------------------------------- /db/subplugins.json: -------------------------------------------------------------------------------- 1 | { 2 | "subplugintypes": { 3 | "certificateelement": "element" 4 | }, 5 | "plugintypes": { 6 | "certificateelement": "admin\/tool\/certificate\/element" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /element/border/classes/privacy/provider.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Privacy Subsystem implementation for certificateelement_border. 19 | * 20 | * @package certificateelement_border 21 | * @copyright 2018 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | namespace certificateelement_border\privacy; 26 | 27 | /** 28 | * Privacy Subsystem for certificateelement_border implementing null_provider. 29 | * 30 | * @copyright 2018 Mark Nelson 31 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 32 | */ 33 | class provider implements \core_privacy\local\metadata\null_provider { 34 | 35 | /** 36 | * Get the language string identifier with the component's language 37 | * file to explain why this plugin stores no data. 38 | * 39 | * @return string 40 | */ 41 | public static function get_reason(): string { 42 | return 'privacy:metadata'; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /element/border/lang/en/certificateelement_border.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Strings for component 'certificateelement_border', language 'en'. 19 | * 20 | * @package certificateelement_border 21 | * @copyright 2013 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | $string['invalidwidth'] = 'The width has to be a valid number greater than 0.'; 26 | $string['pluginname'] = 'Border'; 27 | $string['privacy:metadata'] = 'The Border plugin does not store any personal data.'; 28 | $string['width'] = 'Width'; 29 | $string['width_help'] = 'Width of the border in mm.'; 30 | -------------------------------------------------------------------------------- /element/border/pix/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moodleworkplace/moodle-tool_certificate/d6fba3e5139872fc53778e0ec5b219beb4e7052c/element/border/pix/icon.png -------------------------------------------------------------------------------- /element/border/pix/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | Asset 23 9 | 10 | 11 | 13 | 14 | 15 | 18 | 19 | 20 | 22 | 23 | 24 | 27 | 28 | 29 | 31 | 32 | 33 | 36 | 37 | 38 | 40 | 41 | 42 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /element/border/version.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * This file contains the version information for the border plugin. 19 | * 20 | * @package certificateelement_border 21 | * @copyright 2013 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die(); 26 | 27 | // This plugin is part of Moodle Workplace product. 28 | $plugin->component = 'certificateelement_border'; 29 | $plugin->release = '5.0'; 30 | $plugin->version = 2025041400; 31 | $plugin->requires = 2025041400.00; 32 | $plugin->maturity = MATURITY_STABLE; 33 | -------------------------------------------------------------------------------- /element/code/classes/privacy/provider.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Privacy Subsystem implementation for certificateelement_code. 19 | * 20 | * @package certificateelement_code 21 | * @copyright 2018 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | namespace certificateelement_code\privacy; 26 | 27 | /** 28 | * Privacy Subsystem for certificateelement_code implementing null_provider. 29 | * 30 | * @copyright 2018 Mark Nelson 31 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 32 | */ 33 | class provider implements \core_privacy\local\metadata\null_provider { 34 | 35 | /** 36 | * Get the language string identifier with the component's language 37 | * file to explain why this plugin stores no data. 38 | * 39 | * @return string 40 | */ 41 | public static function get_reason(): string { 42 | return 'privacy:metadata'; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /element/code/lang/en/certificateelement_code.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Strings for component 'certificateelement_code', language 'en'. 19 | * 20 | * @package certificateelement_code 21 | * @copyright 2013 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | $string['display'] = 'Display'; 26 | $string['display_help'] = 'How to display the code: 27 | 28 | * Code only (default): will display only the code to verify the certificate 29 | * Code and link: will display a link to the verfication page 30 | * URL: will display the verification URL as text (usually for printed certificates where it is not possible to click a link)'; 31 | $string['displaycode'] = 'Code only'; 32 | $string['displaycodelink'] = 'Code with link'; 33 | $string['displayqrcode'] = 'QR Code'; 34 | $string['displayurl'] = 'Verification URL'; 35 | $string['pluginname'] = 'Code'; 36 | $string['privacy:metadata'] = 'The Code plugin does not store any personal data.'; 37 | -------------------------------------------------------------------------------- /element/code/pix/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moodleworkplace/moodle-tool_certificate/d6fba3e5139872fc53778e0ec5b219beb4e7052c/element/code/pix/icon.png -------------------------------------------------------------------------------- /element/code/pix/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | Asset 23 9 | 10 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /element/code/version.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * This file contains the version information for the code plugin. 19 | * 20 | * @package certificateelement_code 21 | * @copyright 2013 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die(); 26 | 27 | // This plugin is part of Moodle Workplace product. 28 | $plugin->component = 'certificateelement_code'; 29 | $plugin->release = '5.0'; 30 | $plugin->version = 2025041400; 31 | $plugin->requires = 2025041400.00; 32 | $plugin->maturity = MATURITY_STABLE; 33 | -------------------------------------------------------------------------------- /element/date/classes/privacy/provider.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Privacy Subsystem implementation for certificateelement_date. 19 | * 20 | * @package certificateelement_date 21 | * @copyright 2018 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | namespace certificateelement_date\privacy; 26 | 27 | /** 28 | * Privacy Subsystem for certificateelement_date implementing null_provider. 29 | * 30 | * @copyright 2018 Mark Nelson 31 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 32 | */ 33 | class provider implements \core_privacy\local\metadata\null_provider { 34 | 35 | /** 36 | * Get the language string identifier with the component's language 37 | * file to explain why this plugin stores no data. 38 | * 39 | * @return string 40 | */ 41 | public static function get_reason(): string { 42 | return 'privacy:metadata'; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /element/date/lang/en/certificateelement_date.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Strings for component 'certificateelement_date', language 'en'. 19 | * 20 | * @package certificateelement_date 21 | * @copyright 2013 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | $string['dateformat'] = 'Date format'; 26 | $string['dateformat_help'] = 'This is the format of the date that will be displayed'; 27 | $string['dateitem'] = 'Date item'; 28 | $string['dateitem_help'] = 'This will be the date that is printed on the certificate'; 29 | $string['expirydate'] = 'Expiry date'; 30 | $string['issueddate'] = 'Issued date'; 31 | $string['pluginname'] = 'Date'; 32 | $string['privacy:metadata'] = 'The Date plugin does not store any personal data.'; 33 | -------------------------------------------------------------------------------- /element/date/pix/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moodleworkplace/moodle-tool_certificate/d6fba3e5139872fc53778e0ec5b219beb4e7052c/element/date/pix/icon.png -------------------------------------------------------------------------------- /element/date/pix/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | Asset 23 9 | 18 | 19 | -------------------------------------------------------------------------------- /element/date/version.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * This file contains the version information for the date plugin. 19 | * 20 | * @package certificateelement_date 21 | * @copyright 2013 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die(); 26 | 27 | // This plugin is part of Moodle Workplace product. 28 | $plugin->component = 'certificateelement_date'; 29 | $plugin->release = '5.0'; 30 | $plugin->version = 2025041400; 31 | $plugin->requires = 2025041400.00; 32 | $plugin->maturity = MATURITY_STABLE; 33 | -------------------------------------------------------------------------------- /element/digitalsignature/classes/privacy/provider.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Privacy Subsystem implementation for certificateelement_digitalsignature. 19 | * 20 | * @package certificateelement_digitalsignature 21 | * @copyright 2018 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | namespace certificateelement_digitalsignature\privacy; 26 | 27 | /** 28 | * Privacy Subsystem for certificateelement_digitalsignature implementing null_provider. 29 | * 30 | * @copyright 2018 Mark Nelson 31 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 32 | */ 33 | class provider implements \core_privacy\local\metadata\null_provider { 34 | 35 | /** 36 | * Get the language string identifier with the component's language 37 | * file to explain why this plugin stores no data. 38 | * 39 | * @return string 40 | */ 41 | public static function get_reason(): string { 42 | return 'privacy:metadata'; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /element/digitalsignature/lang/en/certificateelement_digitalsignature.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Strings for component 'certificateelement_digitalsignature', language 'en'. 19 | * 20 | * @package certificateelement_digitalsignature 21 | * @copyright 2017 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | $string['digitalsignature'] = 'Digital signature'; 26 | $string['errormultipleimages'] = 'You can only select one image (either uploaded or shared)'; 27 | $string['height'] = 'Height'; 28 | $string['height_help'] = 'Height of the element in mm. The value can be automatically calculated for uploaded/shared images if set to 0, otherwise it must be specified'; 29 | $string['pluginname'] = 'Digital signature'; 30 | $string['privacy:metadata'] = 'The Digital signature plugin does not store any personal data.'; 31 | $string['signaturecontactinfo'] = 'Signature contact info'; 32 | $string['signaturelocation'] = 'Signature location'; 33 | $string['signaturename'] = 'Signature name'; 34 | $string['signaturepassword'] = 'Signature password'; 35 | $string['signaturereason'] = 'Signature reason'; 36 | $string['width'] = 'Width'; 37 | $string['width_help'] = 'Width of the element in mm. The value can be automatically calculated for uploaded/shared images if set to 0, otherwise it must be specified'; 38 | -------------------------------------------------------------------------------- /element/digitalsignature/pix/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moodleworkplace/moodle-tool_certificate/d6fba3e5139872fc53778e0ec5b219beb4e7052c/element/digitalsignature/pix/icon.png -------------------------------------------------------------------------------- /element/digitalsignature/pix/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | Asset 23 9 | 10 | 11 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /element/digitalsignature/tests/element_test.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | namespace certificateelement_digitalsignature; 18 | 19 | use advanced_testcase; 20 | use tool_certificate_generator; 21 | use core_text; 22 | 23 | /** 24 | * Unit tests for digitalsignature element. 25 | * 26 | * @package certificateelement_digitalsignature 27 | * @group tool_certificate 28 | * @covers \certificateelement_digitalsignature\element 29 | * @copyright 2018 Daniel Neis Araujo 30 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 31 | */ 32 | final class element_test extends advanced_testcase { 33 | 34 | /** 35 | * Test set up. 36 | */ 37 | public function setUp(): void { 38 | parent::setUp(); 39 | $this->resetAfterTest(); 40 | } 41 | 42 | /** 43 | * Get certificate generator 44 | * @return tool_certificate_generator 45 | */ 46 | protected function get_generator(): tool_certificate_generator { 47 | return $this->getDataGenerator()->get_plugin_generator('tool_certificate'); 48 | } 49 | 50 | public function test_render_html_content(): void { 51 | $certificate1 = $this->get_generator()->create_template((object)['name' => 'Certificate 1']); 52 | $pageid = $this->get_generator()->create_page($certificate1)->get_id(); 53 | $e = $this->get_generator()->create_element($pageid, 'digitalsignature'); 54 | // TODO: make a better test. 55 | $this->assertNotEmpty($e->render_html()); 56 | 57 | // Generate PDF for preview. 58 | $filecontents = $this->get_generator()->generate_pdf($certificate1, true); 59 | $this->assertGreaterThan(30000, core_text::strlen($filecontents, '8bit')); 60 | 61 | // Generate PDF for issue. 62 | $issue = $this->get_generator()->issue($certificate1, $this->getDataGenerator()->create_user(), time() + YEARSECS); 63 | $filecontents = $this->get_generator()->generate_pdf($certificate1, false, $issue); 64 | $this->assertGreaterThan(30000, core_text::strlen($filecontents, '8bit')); 65 | } 66 | 67 | /** 68 | * Tests that the edit element form can be initiated without any errors 69 | */ 70 | public function test_edit_element_form(): void { 71 | $this->setAdminUser(); 72 | 73 | preg_match('|^certificateelement_(\w*)\\\\|', get_class($this), $matches); 74 | $form = $this->get_generator()->create_template_and_edit_element_form($matches[1]); 75 | $this->assertNotEmpty($form->render()); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /element/digitalsignature/version.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * This file contains the version information for the digital signature plugin. 19 | * 20 | * @package certificateelement_digitalsignature 21 | * @copyright 2017 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die(); 26 | 27 | // This plugin is part of Moodle Workplace product. 28 | $plugin->component = 'certificateelement_digitalsignature'; 29 | $plugin->release = '5.0'; 30 | $plugin->version = 2025041400; 31 | $plugin->requires = 2025041400.00; 32 | $plugin->maturity = MATURITY_STABLE; 33 | -------------------------------------------------------------------------------- /element/image/classes/privacy/provider.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Privacy Subsystem implementation for certificateelement_image. 19 | * 20 | * @package certificateelement_image 21 | * @copyright 2018 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | namespace certificateelement_image\privacy; 26 | 27 | /** 28 | * Privacy Subsystem for certificateelement_image implementing null_provider. 29 | * 30 | * @copyright 2018 Mark Nelson 31 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 32 | */ 33 | class provider implements \core_privacy\local\metadata\null_provider { 34 | 35 | /** 36 | * Get the language string identifier with the component's language 37 | * file to explain why this plugin stores no data. 38 | * 39 | * @return string 40 | */ 41 | public static function get_reason(): string { 42 | return 'privacy:metadata'; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /element/image/db/upgrade.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Customcert image element upgrade code. 19 | * 20 | * @package certificateelement_image 21 | * @copyright 2017 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | /** 26 | * Customcert image element upgrade code. 27 | * 28 | * @param int $oldversion the version we are upgrading from 29 | * @return bool always true 30 | */ 31 | function xmldb_certificateelement_image_upgrade($oldversion) { 32 | global $DB; 33 | 34 | return true; 35 | } 36 | -------------------------------------------------------------------------------- /element/image/lang/en/certificateelement_image.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Strings for component 'certificateelement_image', language 'en'. 19 | * 20 | * @package certificateelement_image 21 | * @copyright 2013 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | $string['height'] = 'Height'; 26 | $string['height_help'] = 'Height of the image in mm. If equal to zero, it is automatically calculated.'; 27 | $string['imagerequired'] = 'You must either upload an image or select a shared image'; 28 | $string['invalidheight'] = 'The height has to be a valid number greater than or equal to 0.'; 29 | $string['invalidwidth'] = 'The width has to be a valid number greater than or equal to 0.'; 30 | $string['isbackground'] = 'Use as a background image'; 31 | $string['pluginname'] = 'Image'; 32 | $string['privacy:metadata'] = 'The Image plugin does not store any personal data.'; 33 | $string['selectsharedimage'] = 'Select shared image'; 34 | $string['width'] = 'Width'; 35 | $string['width_help'] = 'Width of the image in mm. If equal to zero, it is automatically calculated.'; 36 | -------------------------------------------------------------------------------- /element/image/pix/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moodleworkplace/moodle-tool_certificate/d6fba3e5139872fc53778e0ec5b219beb4e7052c/element/image/pix/icon.png -------------------------------------------------------------------------------- /element/image/pix/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | Asset 23 9 | 15 | 16 | -------------------------------------------------------------------------------- /element/image/tests/element_test.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | namespace certificateelement_image; 18 | 19 | use advanced_testcase; 20 | use tool_certificate_generator; 21 | use core_text; 22 | 23 | /** 24 | * Unit tests for image element. 25 | * 26 | * @package certificateelement_image 27 | * @group tool_certificate 28 | * @covers \certificateelement_image\element 29 | * @copyright 2018 Daniel Neis Araujo 30 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 31 | */ 32 | final class element_test extends advanced_testcase { 33 | 34 | /** 35 | * Test set up. 36 | */ 37 | public function setUp(): void { 38 | parent::setUp(); 39 | $this->resetAfterTest(); 40 | } 41 | 42 | /** 43 | * Get certificate generator 44 | * @return tool_certificate_generator 45 | */ 46 | protected function get_generator(): tool_certificate_generator { 47 | return $this->getDataGenerator()->get_plugin_generator('tool_certificate'); 48 | } 49 | 50 | public function test_render_html_content(): void { 51 | $certificate1 = $this->get_generator()->create_template((object)['name' => 'Certificate 1']); 52 | $pageid = $this->get_generator()->create_page($certificate1)->get_id(); 53 | $e = $this->get_generator()->create_element($pageid, 'image'); 54 | // TODO: make a better test. 55 | $this->assertNotEmpty($e->render_html()); 56 | 57 | // Generate PDF for preview. 58 | $filecontents = $this->get_generator()->generate_pdf($certificate1, true); 59 | $this->assertGreaterThan(30000, core_text::strlen($filecontents, '8bit')); 60 | 61 | // Generate PDF for issue. 62 | $issue = $this->get_generator()->issue($certificate1, $this->getDataGenerator()->create_user(), time() + YEARSECS); 63 | $filecontents = $this->get_generator()->generate_pdf($certificate1, false, $issue); 64 | $this->assertGreaterThan(30000, core_text::strlen($filecontents, '8bit')); 65 | } 66 | 67 | /** 68 | * Tests that the edit element form can be initiated without any errors 69 | */ 70 | public function test_edit_element_form(): void { 71 | $this->setAdminUser(); 72 | 73 | preg_match('|^certificateelement_(\w*)\\\\|', get_class($this), $matches); 74 | $form = $this->get_generator()->create_template_and_edit_element_form($matches[1]); 75 | $this->assertNotEmpty($form->render()); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /element/image/version.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * This file contains the version information for the image plugin. 19 | * 20 | * @package certificateelement_image 21 | * @copyright 2013 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die(); 26 | 27 | // This plugin is part of Moodle Workplace product. 28 | $plugin->component = 'certificateelement_image'; 29 | $plugin->release = '5.0'; 30 | $plugin->version = 2025041400; 31 | $plugin->requires = 2025041400.00; 32 | $plugin->maturity = MATURITY_STABLE; 33 | -------------------------------------------------------------------------------- /element/program/classes/privacy/provider.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Privacy Subsystem implementation for certificateelement_program. 19 | * 20 | * @package certificateelement_program 21 | * @copyright 2018 Daniel Neis Araujo 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | namespace certificateelement_program\privacy; 26 | 27 | /** 28 | * Privacy Subsystem for certificateelement_program implementing null_provider. 29 | * 30 | * @package certificateelement_program 31 | * @copyright 2018 Daniel Neis Araujo 32 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 33 | */ 34 | class provider implements \core_privacy\local\metadata\null_provider { 35 | 36 | /** 37 | * Get the language string identifier with the component's language 38 | * file to explain why this plugin stores no data. 39 | * 40 | * @return string 41 | */ 42 | public static function get_reason(): string { 43 | return 'privacy:metadata'; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /element/program/lang/en/certificateelement_program.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Strings for component 'certificateelement_program', language 'en'. 19 | * 20 | * @package certificateelement_program 21 | * @copyright 2018 Daniel Neis Araujo 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | $string['fieldoptions'] = 'Field'; 26 | $string['fieldoptions_help'] = 'The field to be displayed. If you need to display more than one field, add more instances of this element and configure accordingly.'; 27 | $string['pluginname'] = 'Dynamic fields'; 28 | $string['privacy:metadata'] = 'The dynamic fields plugin does not store any personal data.'; 29 | -------------------------------------------------------------------------------- /element/program/pix/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moodleworkplace/moodle-tool_certificate/d6fba3e5139872fc53778e0ec5b219beb4e7052c/element/program/pix/icon.png -------------------------------------------------------------------------------- /element/program/pix/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | Asset 23 9 | 15 | 16 | -------------------------------------------------------------------------------- /element/program/version.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * This file contains the version information for the program element. 19 | * 20 | * @package certificateelement_program 21 | * @copyright 2018 Daniel Neis Araujo 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die(); 26 | 27 | // This plugin is part of Moodle Workplace product. 28 | $plugin->component = 'certificateelement_program'; 29 | $plugin->release = '5.0'; 30 | $plugin->version = 2025041400; 31 | $plugin->requires = 2025041400.00; 32 | $plugin->maturity = MATURITY_STABLE; 33 | -------------------------------------------------------------------------------- /element/text/classes/privacy/provider.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Privacy Subsystem implementation for certificateelement_text. 19 | * 20 | * @package certificateelement_text 21 | * @copyright 2018 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | namespace certificateelement_text\privacy; 26 | 27 | /** 28 | * Privacy Subsystem for certificateelement_text implementing null_provider. 29 | * 30 | * @copyright 2018 Mark Nelson 31 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 32 | */ 33 | class provider implements \core_privacy\local\metadata\null_provider { 34 | 35 | /** 36 | * Get the language string identifier with the component's language 37 | * file to explain why this plugin stores no data. 38 | * 39 | * @return string 40 | */ 41 | public static function get_reason(): string { 42 | return 'privacy:metadata'; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /element/text/lang/en/certificateelement_text.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Strings for component 'certificateelement_text', language 'en'. 19 | * 20 | * @package certificateelement_text 21 | * @copyright 2013 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | $string['pluginname'] = 'Text'; 26 | $string['privacy:metadata'] = 'The Text plugin does not store any personal data.'; 27 | $string['text'] = 'Text'; 28 | $string['text_help'] = 'This is the text that will display on the PDF.'; 29 | -------------------------------------------------------------------------------- /element/text/pix/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moodleworkplace/moodle-tool_certificate/d6fba3e5139872fc53778e0ec5b219beb4e7052c/element/text/pix/icon.png -------------------------------------------------------------------------------- /element/text/pix/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | Asset 23 9 | 10 | 19 | 28 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /element/text/version.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * This file contains the version information for the text plugin. 19 | * 20 | * @package certificateelement_text 21 | * @copyright 2013 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die(); 26 | 27 | // This plugin is part of Moodle Workplace product. 28 | $plugin->component = 'certificateelement_text'; 29 | $plugin->release = '5.0'; 30 | $plugin->version = 2025041400; 31 | $plugin->requires = 2025041400.00; 32 | $plugin->maturity = MATURITY_STABLE; 33 | -------------------------------------------------------------------------------- /element/userfield/classes/privacy/provider.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Privacy Subsystem implementation for certificateelement_userfield. 19 | * 20 | * @package certificateelement_userfield 21 | * @copyright 2018 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | namespace certificateelement_userfield\privacy; 26 | 27 | /** 28 | * Privacy Subsystem for certificateelement_userfield implementing null_provider. 29 | * 30 | * @copyright 2018 Mark Nelson 31 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 32 | */ 33 | class provider implements \core_privacy\local\metadata\null_provider { 34 | 35 | /** 36 | * Get the language string identifier with the component's language 37 | * file to explain why this plugin stores no data. 38 | * 39 | * @return string 40 | */ 41 | public static function get_reason(): string { 42 | return 'privacy:metadata'; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /element/userfield/lang/en/certificateelement_userfield.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Strings for component 'certificateelement_userfield', language 'en'. 19 | * 20 | * @package certificateelement_userfield 21 | * @copyright 2013 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | $string['pluginname'] = 'User field'; 26 | $string['privacy:metadata'] = 'The User field plugin does not store any personal data.'; 27 | $string['userfield'] = 'User field'; 28 | $string['userfield_help'] = 'This is the user field that will be displayed on the PDF.'; 29 | -------------------------------------------------------------------------------- /element/userfield/pix/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moodleworkplace/moodle-tool_certificate/d6fba3e5139872fc53778e0ec5b219beb4e7052c/element/userfield/pix/icon.png -------------------------------------------------------------------------------- /element/userfield/pix/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | Asset 23 9 | 10 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /element/userfield/version.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * This file contains the version information for the userfield plugin. 19 | * 20 | * @package certificateelement_userfield 21 | * @copyright 2013 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die(); 26 | 27 | // This plugin is part of Moodle Workplace product. 28 | $plugin->component = 'certificateelement_userfield'; 29 | $plugin->release = '5.0'; 30 | $plugin->version = 2025041400; 31 | $plugin->requires = 2025041400.00; 32 | $plugin->maturity = MATURITY_STABLE; 33 | -------------------------------------------------------------------------------- /element/userpicture/classes/privacy/provider.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Privacy Subsystem implementation for certificateelement_userpicture. 19 | * 20 | * @package certificateelement_userpicture 21 | * @copyright 2018 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | namespace certificateelement_userpicture\privacy; 26 | 27 | /** 28 | * Privacy Subsystem for certificateelement_userpicture implementing null_provider. 29 | * 30 | * @copyright 2018 Mark Nelson 31 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 32 | */ 33 | class provider implements \core_privacy\local\metadata\null_provider { 34 | 35 | /** 36 | * Get the language string identifier with the component's language 37 | * file to explain why this plugin stores no data. 38 | * 39 | * @return string 40 | */ 41 | public static function get_reason(): string { 42 | return 'privacy:metadata'; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /element/userpicture/lang/en/certificateelement_userpicture.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Strings for component 'certificateelement_userpicture', language 'en'. 19 | * 20 | * @package certificateelement_userpicture 21 | * @copyright 2017 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | $string['height'] = 'Height'; 26 | $string['height_help'] = 'Height of the image in mm. If equal to zero, it is automatically calculated.'; 27 | $string['invalidheight'] = 'The height has to be a valid number greater than or equal to 0.'; 28 | $string['invalidwidth'] = 'The width has to be a valid number greater than or equal to 0.'; 29 | $string['pluginname'] = 'User picture'; 30 | $string['privacy:metadata'] = 'The User picture plugin does not store any personal data.'; 31 | $string['width'] = 'Width'; 32 | $string['width_help'] = 'Width of the image in mm. If equal to zero, it is automatically calculated.'; 33 | -------------------------------------------------------------------------------- /element/userpicture/pix/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moodleworkplace/moodle-tool_certificate/d6fba3e5139872fc53778e0ec5b219beb4e7052c/element/userpicture/pix/icon.png -------------------------------------------------------------------------------- /element/userpicture/pix/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 8 | Asset 23 9 | 10 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /element/userpicture/version.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * This file contains the version information for the userpicture plugin. 19 | * 20 | * @package certificateelement_userpicture 21 | * @copyright 2017 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die(); 26 | 27 | // This plugin is part of Moodle Workplace product. 28 | $plugin->component = 'certificateelement_userpicture'; 29 | $plugin->release = '5.0'; 30 | $plugin->version = 2025041400; 31 | $plugin->requires = 2025041400.00; 32 | $plugin->maturity = MATURITY_STABLE; 33 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Handles verifying the code for a certificate. 19 | * 20 | * @package tool_certificate 21 | * @copyright 2017 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | // This file does not need require_login because capability to verify can be granted to guests, skip codechecker here. 26 | // @codingStandardsIgnoreLine 27 | require_once('../../../config.php'); 28 | 29 | $code = optional_param('code', '', PARAM_ALPHANUM); // The code for the certificate we are verifying. 30 | 31 | if (!\tool_certificate\permission::can_verify()) { 32 | throw new moodle_exception('verifynotallowed', 'tool_certificate'); 33 | } 34 | 35 | $pageurl = new moodle_url('/admin/tool/certificate/index.php'); 36 | 37 | if ($code) { 38 | $pageurl->param('code', $code); 39 | } 40 | 41 | $heading = get_string('verifycertificates', 'tool_certificate'); 42 | 43 | $PAGE->set_url($pageurl); 44 | $PAGE->set_context(context_system::instance()); 45 | $PAGE->set_title(format_string($heading)); 46 | $PAGE->set_heading($SITE->fullname); 47 | 48 | $PAGE->navbar->add($heading); 49 | 50 | $form = new \tool_certificate\verify_certificate_form($pageurl, null, 'post', '', 51 | ['class' => 'mt-3 mb-5 p-4 bg-light']); 52 | 53 | if ($code) { 54 | $form->set_data(['code' => $code]); 55 | } 56 | 57 | $PAGE->set_heading($heading); 58 | echo $OUTPUT->header(); 59 | $form->display(); 60 | if ($form->get_data()) { 61 | $result = \tool_certificate\certificate::verify($code); 62 | $results = new \tool_certificate\output\verify_certificate_results($result); 63 | echo $OUTPUT->render($results); 64 | } 65 | echo $OUTPUT->footer(); 66 | -------------------------------------------------------------------------------- /lang/en/deprecated.txt: -------------------------------------------------------------------------------- 1 | editcertificate,tool_certificate 2 | issuenewcertificate,tool_certificate 3 | nopermissionform,tool_certificate 4 | -------------------------------------------------------------------------------- /manage_templates.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Manage certificate templates. 19 | * 20 | * @package tool_certificate 21 | * @copyright 2016 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | require_once('../../../config.php'); 26 | require_once($CFG->libdir.'/adminlib.php'); 27 | 28 | $courseid = optional_param('courseid', null, PARAM_INT); 29 | $download = optional_param('download', null, PARAM_ALPHA); 30 | $page = optional_param('page', 0, PARAM_INT); 31 | $perpage = optional_param('perpage', \tool_certificate\certificate::TEMPLATES_PER_PAGE, PARAM_INT); 32 | $pageurl = new moodle_url('/admin/tool/certificate/manage_templates.php', ['page' => $page, 'perpage' => $perpage]); 33 | 34 | $title = get_string('managetemplates', 'tool_certificate'); 35 | admin_externalpage_setup('tool_certificate/managetemplates', '', null, '', ['nosearch' => true]); 36 | $context = context_system::instance(); 37 | 38 | if (!\tool_certificate\permission::can_view_admin_tree()) { 39 | throw new moodle_exception('issueormangenotallowed', 'tool_certificate'); 40 | } 41 | 42 | $PAGE->set_secondary_navigation(false); 43 | $PAGE->set_title($title); 44 | $PAGE->set_heading($title); 45 | $PAGE->set_url($pageurl); 46 | 47 | $outputpage = new \tool_certificate\output\templates_page(); 48 | 49 | $data = $outputpage->export_for_template($PAGE->get_renderer('core')); 50 | if (\tool_certificate\permission::can_create()) { 51 | $data += ['addbutton' => true, 'addbuttontitle' => get_string('createtemplate', 'tool_certificate'), 52 | 'addbuttonurl' => null, 'addbuttonattrs' => ['name' => 'data-contextid', 'value' => $context->id], 53 | 'addbuttonicon' => true, ]; 54 | } 55 | $PAGE->requires->js_call_amd('tool_certificate/templates-list', 'init'); 56 | 57 | echo $OUTPUT->header(); 58 | echo $OUTPUT->render_from_template('tool_certificate/content_with_heading', $data); 59 | echo $OUTPUT->footer(); 60 | -------------------------------------------------------------------------------- /my.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Handles viewing the certificates for a certain user. 19 | * 20 | * @package tool_certificate 21 | * @copyright 2016 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | require_once('../../../config.php'); 26 | 27 | $userid = optional_param('userid', 0, PARAM_INT); 28 | $download = optional_param('download', null, PARAM_ALPHA); 29 | $page = optional_param('page', 0, PARAM_INT); 30 | $perpage = optional_param('perpage', \tool_certificate\certificate::ISSUES_PER_PAGE, PARAM_INT); 31 | $pageurl = $url = new moodle_url('/admin/tool/certificate/my.php', ['userid' => $userid, 32 | 'page' => $page, 'perpage' => $perpage, ]); 33 | 34 | // Requires a login. 35 | require_login(); 36 | 37 | // Check that we have a valid user. 38 | $user = \core_user::get_user($userid ?: $USER->id, '*', MUST_EXIST); 39 | if (!\tool_certificate\permission::can_view_list($user->id)) { 40 | throw new \required_capability_exception(context_system::instance(), 'tool/certificate:viewallcertificates', 41 | 'nopermission', 'error'); 42 | } 43 | 44 | $table = new \tool_certificate\my_certificates_table($user->id, $download); 45 | $table->define_baseurl($pageurl); 46 | 47 | if ($table->is_downloading()) { 48 | $table->download(); 49 | exit(); 50 | } 51 | 52 | $PAGE->set_url($pageurl); 53 | $PAGE->set_context(context_user::instance($user->id)); 54 | $PAGE->navigation->extend_for_user($user); 55 | $PAGE->set_title(get_string('mycertificates', 'tool_certificate')); 56 | 57 | $PAGE->set_pagelayout('standard'); 58 | 59 | $PAGE->navbar->add(get_string('profile'), new moodle_url('/user/profile.php', ['id' => $user->id])); 60 | $PAGE->navbar->add(get_string('mycertificates', 'tool_certificate')); 61 | 62 | echo $OUTPUT->header(); 63 | echo $OUTPUT->heading(get_string('mycertificates', 'tool_certificate')); 64 | echo html_writer::div(get_string('mycertificatesdescription', 'tool_certificate')); 65 | $table->out($perpage, false); 66 | echo $OUTPUT->footer(); 67 | -------------------------------------------------------------------------------- /my_certificates.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Handles viewing the certificates for a certain user. 19 | * 20 | * @package tool_certificate 21 | * @copyright 2016 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | require_once('../../../config.php'); 26 | 27 | $userid = optional_param('userid', 0, PARAM_INT); 28 | $pageurl = $url = new moodle_url('/admin/tool/certificate/my.php', ['userid' => $userid]); 29 | 30 | require_login(); 31 | redirect($pageurl); 32 | -------------------------------------------------------------------------------- /pix/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moodleworkplace/moodle-tool_certificate/d6fba3e5139872fc53778e0ec5b219beb4e7052c/pix/background.jpg -------------------------------------------------------------------------------- /pix/brokenfile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moodleworkplace/moodle-tool_certificate/d6fba3e5139872fc53778e0ec5b219beb4e7052c/pix/brokenfile.png -------------------------------------------------------------------------------- /pix/download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moodleworkplace/moodle-tool_certificate/d6fba3e5139872fc53778e0ec5b219beb4e7052c/pix/download.png -------------------------------------------------------------------------------- /pix/download.svg: -------------------------------------------------------------------------------- 1 | 3 | ]> -------------------------------------------------------------------------------- /pix/icon.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moodleworkplace/moodle-tool_certificate/d6fba3e5139872fc53778e0ec5b219beb4e7052c/pix/icon.gif -------------------------------------------------------------------------------- /pix/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moodleworkplace/moodle-tool_certificate/d6fba3e5139872fc53778e0ec5b219beb4e7052c/pix/icon.png -------------------------------------------------------------------------------- /pix/icon.svg: -------------------------------------------------------------------------------- 1 | Asset 23 -------------------------------------------------------------------------------- /pix/linkedin.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /pix/qrcode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moodleworkplace/moodle-tool_certificate/d6fba3e5139872fc53778e0ec5b219beb4e7052c/pix/qrcode.png -------------------------------------------------------------------------------- /pix/signature.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moodleworkplace/moodle-tool_certificate/d6fba3e5139872fc53778e0ec5b219beb4e7052c/pix/signature.png -------------------------------------------------------------------------------- /pix/target.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/moodleworkplace/moodle-tool_certificate/d6fba3e5139872fc53778e0ec5b219beb4e7052c/pix/target.gif -------------------------------------------------------------------------------- /styles.css: -------------------------------------------------------------------------------- 1 | /* Template editor */ 2 | 3 | #page-admin-tool-certificate-template [data-region="pdf"] { 4 | clear: both; 5 | position: relative; 6 | } 7 | 8 | #page-admin-tool-certificate-template [data-region="pdf"] > * { 9 | position: absolute; 10 | } 11 | 12 | #page-admin-tool-certificate-template [data-region="pdf"] [data-region="pdfelement"] { 13 | display: inline-block; 14 | word-wrap: break-word; 15 | text-decoration: none; 16 | } 17 | 18 | #page-admin-tool-certificate-template [data-region="pdf"]:not(.recalculated) [data-region="pdfelement"], 19 | #page-admin-tool-certificate-template [data-region="pdf"]:not(.recalculated) * { 20 | opacity: 0; 21 | } 22 | 23 | #page-admin-tool-certificate-template [data-region="template"] .ws-toggle .collapsed-icon-container { 24 | display: none; 25 | } 26 | #page-admin-tool-certificate-template [data-region="template"] .ws-toggle .expanded-icon-container { 27 | display: inline-block; 28 | } 29 | #page-admin-tool-certificate-template [data-region="template"] .ws-toggle.collapsed .collapsed-icon-container { 30 | display: inline-block; 31 | } 32 | #page-admin-tool-certificate-template [data-region="template"] .ws-toggle.collapsed .expanded-icon-container { 33 | display: none; 34 | } 35 | 36 | /* Elements refpoint */ 37 | 38 | #page-admin-tool-certificate-template [data-region="pdf"] [data-region="pdfelement"][data-refpoint]:before { 39 | background-image: url([[pix:tool_certificate|target]]); 40 | background-repeat: no-repeat; 41 | content: ""; 42 | display: block; 43 | float: left; 44 | height: 9px; 45 | width: 100%; 46 | background-position: left top; 47 | margin: -4px -5px -5px -4px; 48 | } 49 | 50 | #page-admin-tool-certificate-template [data-region="pdf"] [data-region="pdfelement"][data-refpoint="1"]:before { 51 | background-position: center top; 52 | margin: -4px 0 -5px 0; 53 | } 54 | 55 | #page-admin-tool-certificate-template [data-region="pdf"] [data-region="pdfelement"][data-refpoint="2"]:before { 56 | background-position: right top; 57 | margin: -4px -5px -5px 4px; 58 | } 59 | 60 | /* Page margins */ 61 | 62 | #page-admin-tool-certificate-template [data-region="pdf"] .verticalline { 63 | width: 1px; 64 | } 65 | 66 | #page-admin-tool-certificate-template [data-region="pdf"] .horizontalline { 67 | height: 1px; 68 | } 69 | 70 | #page-admin-tool-certificate-template [data-region="pdf"] .dottedline { 71 | border-left: 1px dotted black; 72 | } 73 | 74 | #page-admin-tool-certificate-template [data-region="pdf"] .solidline { 75 | border-left: 1px solid black; 76 | border-top: 1px solid black; 77 | line-height: normal; 78 | } 79 | 80 | #page-admin-tool-certificate-template #region-main { 81 | overflow: visible; 82 | } 83 | 84 | #page-admin-tool-certificate-template .modal-dialog .modal-header [data-action="hide"] { 85 | display: none; 86 | } -------------------------------------------------------------------------------- /template.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Edit certificate template 19 | * 20 | * @package tool_certificate 21 | * @copyright 2019 Marina Glancy 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | require_once(__DIR__ . '/../../../config.php'); 26 | require_once($CFG->libdir . '/adminlib.php'); 27 | 28 | $pageid = optional_param('pageid', 0, PARAM_INT); 29 | $action = optional_param('action', null, PARAM_ALPHANUMEXT); 30 | if ($pageid && $action) { 31 | $page = \tool_certificate\page::instance($pageid); 32 | $template = $page->get_template(); 33 | } else { 34 | $templateid = required_param('id', PARAM_INT); 35 | $template = \tool_certificate\template::instance($templateid); 36 | } 37 | 38 | $pageurl = new moodle_url('/admin/tool/certificate/template.php', ['id' => $template->get_id()]); 39 | if ($template->get_context()->contextlevel == CONTEXT_COURSE) { 40 | $courseid = $template->get_context()->instanceid; 41 | require_login($courseid); 42 | $manageurl = new moodle_url('/admin/tool/certificate/manage_templates.php', ['courseid' => $courseid]); 43 | $PAGE->navbar->add(get_string('managetemplates', 'tool_certificate'), $manageurl); 44 | $PAGE->set_url($pageurl); 45 | } else { 46 | admin_externalpage_setup('tool_certificate/managetemplates', '', null, $pageurl, ['nosearch' => true]); 47 | } 48 | 49 | $template->require_can_manage(); 50 | 51 | if ($action && $pageid) { 52 | require_sesskey(); 53 | if ($action === 'moveuppage') { 54 | $template->move_page($pageid, -1); 55 | } else if ($action === 'movedownpage') { 56 | $template->move_page($pageid, 1); 57 | } else if ($action === 'deletepage') { 58 | $template->delete_page($pageid); 59 | } 60 | redirect($pageurl); 61 | } 62 | 63 | $heading = $title = $template->get_formatted_name(); 64 | if ($template->get_shared()) { 65 | $heading .= html_writer::tag('div', get_string('shared', 'tool_certificate'), 66 | ['class' => 'badge rounded-pill bg-secondary text-dark font-small ms-2 align-middle']); 67 | } 68 | $PAGE->navbar->add($title, $pageurl); 69 | 70 | $PAGE->set_title($title); 71 | $PAGE->set_heading($heading, false); 72 | 73 | // Secondary navigation. 74 | $secondarynav = new \tool_certificate\local\views\template_secondary($PAGE, $template); 75 | $secondarynav->initialise(); 76 | $PAGE->set_secondarynav($secondarynav); 77 | 78 | $data = $template->get_exporter()->export($PAGE->get_renderer('core')); 79 | $data->heading = get_string('template', 'tool_certificate'); 80 | 81 | echo $OUTPUT->header(); 82 | echo $OUTPUT->render_from_template('tool_certificate/edit_layout', $data); 83 | echo $OUTPUT->footer(); 84 | -------------------------------------------------------------------------------- /template_details.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Edit template details. 19 | * 20 | * @package tool_certificate 21 | * @copyright 2022 Ruslan Kabalin 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | require_once('../../../config.php'); 26 | require_once($CFG->libdir.'/adminlib.php'); 27 | 28 | $templateid = required_param('id', PARAM_INT); 29 | 30 | $pageurl = $url = new moodle_url('/admin/tool/certificate/template_details.php', ['id' => $templateid]); 31 | $PAGE->set_url($pageurl); 32 | $template = \tool_certificate\template::instance($templateid); 33 | if ($coursecontext = $template->get_context()->get_course_context(false)) { 34 | require_login($coursecontext->instanceid); 35 | } else { 36 | admin_externalpage_setup('tool_certificate/managetemplates', '', null, $pageurl, ['nosearch' => true]); 37 | } 38 | 39 | if (!$template->can_view_issues()) { 40 | throw new moodle_exception('issueormangenotallowed', 'tool_certificate'); 41 | } 42 | 43 | $heading = $title = $template->get_formatted_name(); 44 | if ($template->get_shared()) { 45 | $heading .= html_writer::tag('div', get_string('shared', 'tool_certificate'), 46 | ['class' => 'badge rounded-pill bg-secondary text-dark font-small ms-2 align-middle']); 47 | } 48 | $PAGE->navbar->add($title, $pageurl); 49 | $PAGE->set_title($title); 50 | $PAGE->set_heading($heading, false); 51 | 52 | // Secondary navigation. 53 | $secondarynav = new \tool_certificate\local\views\template_secondary($PAGE, $template); 54 | $secondarynav->initialise(); 55 | $PAGE->set_secondarynav($secondarynav); 56 | 57 | $form = new \tool_certificate\form\details(null, null, 'post', '', [], true, ['id' => $template->get_id()]); 58 | $form->set_data_for_dynamic_submission(); 59 | 60 | $data = [ 61 | 'content' => html_writer::div($form->render(), '', ['id' => 'template-details']), 62 | 'heading' => get_string('details'), 63 | ]; 64 | 65 | $PAGE->requires->js_call_amd('tool_certificate/template-details', 'init'); 66 | 67 | echo $OUTPUT->header(); 68 | echo $OUTPUT->render_from_template('tool_certificate/content_with_heading', $data); 69 | echo $OUTPUT->footer(); 70 | -------------------------------------------------------------------------------- /templates/content_heading.mustache: -------------------------------------------------------------------------------- 1 | {{! 2 | This file is part of the tool_certificate plugin for Moodle - http://moodle.org/ 3 | 4 | Moodle is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | Moodle is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Moodle. If not, see . 16 | }} 17 | {{! 18 | @template tool_certificate/content_heading 19 | 20 | Template for showing content heading 21 | 22 | Example context (json): 23 | { 24 | "addbutton": true, 25 | "addbuttontitle": "Add", 26 | "addbuttonicon": true, 27 | "addbuttonurl": "", 28 | "addbuttonclasses": ["disabled", "p-3"], 29 | "addbuttonattrs": [{"name": "data-foo", "value": "bar"}] 30 | } 31 | }} 32 |
33 | {{#addbutton}} 34 | 37 | {{#addbuttonicon}}{{#pix}}t/add, core{{/pix}}{{/addbuttonicon}}{{#addbuttontitle}}{{addbuttontitle}}{{/addbuttontitle}} 38 | 39 | {{/addbutton}} 40 | {{#heading}} 41 |

{{{heading}}}

42 | {{/heading}} 43 |
44 |
45 | -------------------------------------------------------------------------------- /templates/content_with_heading.mustache: -------------------------------------------------------------------------------- 1 | {{! 2 | This file is part of the tool_certificate plugin for Moodle - http://moodle.org/ 3 | 4 | Moodle is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | Moodle is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Moodle. If not, see . 16 | }} 17 | {{! 18 | @template tool_certificate/content_with_heading 19 | 20 | Page with heading and content 21 | 22 | Classes required for JS: 23 | 24 | Data attibutes required for JS: 25 | 26 | Context variables required for this template: 27 | 28 | Example context (json): 29 | { 30 | "addbuttontitle": "New item", 31 | "addbuttonurl": "#", 32 | "content": "

Here goes content...

" 33 | } 34 | }} 35 | {{> tool_certificate/content_heading }} 36 | {{{content}}} -------------------------------------------------------------------------------- /templates/edit_layout.mustache: -------------------------------------------------------------------------------- 1 | {{! 2 | This file is part of the tool_certificate plugin for Moodle - http://moodle.org/ 3 | 4 | Moodle is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | Moodle is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Moodle. If not, see . 16 | }} 17 | {{! 18 | @template tool_certificate/edit_layout 19 | 20 | The certificate edit layout 21 | 22 | Classes required for JS: 23 | * None 24 | 25 | Data attibutes required for JS: 26 | 27 | Context variables required for this template: 28 | 29 | Example context (json): 30 | { 31 | "pages": [ 32 | {"id": 1, "title": "Page 1"}, 33 | { 34 | "id": 2, 35 | "title": "Page 2", 36 | "editlabel": "Edit", 37 | "deletelabel": "Delete", 38 | "pagelayout": "Page layout editor", 39 | "haselements": 1, 40 | "elements": [ 41 | {"name": "Element1", "type": "Type1", "id": 1}, 42 | {"name": "Element2", "type": "Type2", "id": 2}, 43 | {"name": "Element3", "type": "Type3", "id": 3} 44 | ] 45 | }, 46 | {"id": 3, "title": "Page 3"}, 47 | {"id": 4, "title": "Page 4"} 48 | ] 49 | } 50 | }} 51 | {{> tool_certificate/content_heading }} 52 |
53 | {{#pages}} 54 | {{> tool_certificate/edit_layout_page}} 55 | {{/pages}} 56 |
57 | {{#js}} 58 | require(['tool_certificate/template-edit'], 59 | function(T) { 60 | T.init(); 61 | } 62 | ); 63 | {{/js}} 64 | -------------------------------------------------------------------------------- /templates/edit_layout_elementlist.mustache: -------------------------------------------------------------------------------- 1 | {{! 2 | This file is part of the tool_certificate plugin for Moodle - http://moodle.org/ 3 | 4 | Moodle is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | Moodle is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Moodle. If not, see . 16 | }} 17 | {{! 18 | @template tool_certificate/edit_layout_elementlist 19 | 20 | The certificate edit layout 21 | 22 | Classes required for JS: 23 | * None 24 | 25 | Data attibutes required for JS: 26 | 27 | Context variables required for this template: 28 | 29 | Example context (json): 30 | { 31 | "haselements": 1, 32 | "elements": [ 33 | {"name": "Element1", "type": "Type1", "id": 1}, 34 | {"name": "Element2", "type": "Type2", "id": 2}, 35 | {"name": "Element3", "type": "Type3", "id": 3} 36 | ] 37 | } 38 | }} 39 | -------------------------------------------------------------------------------- /templates/edit_layout_pdf.mustache: -------------------------------------------------------------------------------- 1 | {{! 2 | This file is part of the tool_certificate plugin for Moodle - http://moodle.org/ 3 | 4 | Moodle is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | Moodle is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Moodle. If not, see . 16 | }} 17 | {{! 18 | @template tool_certificate/edit_layout_pdf 19 | 20 | The certificate edit layout 21 | 22 | Classes required for JS: 23 | * snapdraggable 24 | 25 | Data attibutes required for JS: 26 | * All data- attributes 27 | 28 | Context variables required for this template: 29 | 30 | Example context (json): 31 | { 32 | "elements": [ 33 | {"name": "Element1", "type": "Type1", "id": 1}, 34 | {"name": "Element2", "type": "Type2", "id": 2}, 35 | {"name": "Element3", "type": "Type3", "id": 3} 36 | ], 37 | "leftmargin": 10, 38 | "rightmargin": 10, 39 | "width": 200, 40 | "height": 100 41 | } 42 | }} 43 |
44 |
45 |
46 | {{#elements}} 47 | 50 | {{{html}}} 51 | 52 | {{/elements}} 53 | {{#leftmargin}} 54 |
55 | {{/leftmargin}} 56 | {{#rightmargin}} 57 |
58 | {{/rightmargin}} 59 |
60 |
61 |
62 |
63 |
-------------------------------------------------------------------------------- /templates/form-user-selector-suggestion.mustache: -------------------------------------------------------------------------------- 1 | {{! 2 | This file is part of the tool_certificate plugin for Moodle - http://moodle.org/ 3 | 4 | Moodle is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | Moodle is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Moodle. If not, see . 16 | }} 17 | {{! 18 | @template tool_certificate/form-user-selector-suggestion 19 | 20 | Template for showing a user suggestion in user selector list 21 | 22 | Example context (json): 23 | { 24 | "profileimageurlsmall": "https://raw.githubusercontent.com/moodle/moodle/master/pix/g/f1.png", 25 | "fullname": "John Smith", 26 | "hasidentity": "1", 27 | "identity": "john@smith.com" 28 | } 29 | }} 30 | 31 | 32 | {{fullname}} 33 | {{#hasidentity}} 34 | {{identity}} 35 | {{/hasidentity}} 36 | 37 | -------------------------------------------------------------------------------- /templates/page_header_button.mustache: -------------------------------------------------------------------------------- 1 | {{! 2 | This file is part of the tool_certificate plugin for Moodle - http://moodle.org/ 3 | 4 | Moodle is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | Moodle is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Moodle. If not, see . 16 | }} 17 | {{! 18 | @template tool_certificate/page_header_button 19 | 20 | Button to display in the page heading 21 | 22 | Classes required for JS: 23 | 24 | Data attibutes required for JS: 25 | 26 | Context variables required for this template: 27 | 28 | Example context (json): 29 | { 30 | "title": "Edit details", 31 | "class": "", 32 | "attributes": [ 33 | {"name": "data-id", "value": 0} 34 | ] 35 | } 36 | }} 37 |
38 | 39 |
-------------------------------------------------------------------------------- /templates/verify_certificate_result.mustache: -------------------------------------------------------------------------------- 1 | {{! 2 | This file is part of the tool_certificate plugin for Moodle - http://moodle.org/ 3 | 4 | Moodle is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | Moodle is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Moodle. If not, see . 16 | }} 17 | {{! 18 | @template tool_certificate/verify_certificate_result 19 | 20 | The certificate verification result 21 | 22 | Classes required for JS: 23 | * None 24 | 25 | Data attibutes required for JS: 26 | * All data attributes are required 27 | 28 | Context variables required for this template: 29 | * userprofileurl The URL to the user's profile 30 | * userfullname The fullname of the user 31 | * courseurl The URL of the course 32 | * coursefullname The full name of the course 33 | * certificatename The name of the certificate 34 | 35 | Example context (json): 36 | { 37 | "expired": false, 38 | "table": "
", 39 | "viewurl": "" 40 | } 41 | }} 42 | 46 | {{{table}}} 47 | {{#str}}viewcertificate, tool_certificate{{/str}} 48 | -------------------------------------------------------------------------------- /templates/verify_certificate_results.mustache: -------------------------------------------------------------------------------- 1 | {{! 2 | This file is part of the tool_certificate plugin for Moodle - http://moodle.org/ 3 | 4 | Moodle is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 3 of the License, or 7 | (at your option) any later version. 8 | 9 | Moodle is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with Moodle. If not, see . 16 | }} 17 | {{! 18 | @template tool_certificate/verify_certificate_results 19 | 20 | The certificate verification results page 21 | 22 | Classes required for JS: 23 | * None 24 | 25 | Data attibutes required for JS: 26 | * All data attributes are required 27 | 28 | Context variables required for this template: 29 | * None 30 | 31 | Example context (json): 32 | { 33 | } 34 | }} 35 | {{#success}} 36 | {{#issue}} 37 | {{> tool_certificate/verify_certificate_result }} 38 | {{/issue}} 39 | {{/success}} 40 | {{^success}} 41 | {{> core/notification_error}} 42 | {{/success}} 43 | -------------------------------------------------------------------------------- /tests/behat/adminmanageplugins.feature: -------------------------------------------------------------------------------- 1 | @tool @tool_certificate @moodleworkplace 2 | Feature: Manage certificate elements plugins 3 | In order to manage certificate elements plugins 4 | As a manager 5 | I need to be able to view, hide/show, reorder and unistall element plugins 6 | 7 | Scenario: View default element plugins 8 | When I log in as "admin" 9 | And I navigate to "Plugins > Admin tools > Manage certificate element plugins" in site administration 10 | Then I should see "Border" 11 | And I should see "Code" 12 | And I should see "Date" 13 | And I should see "Digital signature" 14 | And I should see "Image" 15 | And I should see "Dynamic fields" 16 | And I should see "Text" 17 | And I should see "User field" 18 | And I should see "User picture" 19 | 20 | Scenario: Uninstall an element plugin 21 | When I log in as "admin" 22 | And I navigate to "Plugins > Admin tools > Manage certificate element plugins" in site administration 23 | And I click on "Uninstall" "link" in the "User field" "table_row" 24 | And I press "Continue" 25 | Then I should see "Success" 26 | 27 | Scenario: Disable and enable an element plugin 28 | When I log in as "admin" 29 | And I navigate to "Plugins > Admin tools > Manage certificate element plugins" in site administration 30 | And I click on "Disable" "link" in the "User field" "table_row" 31 | Then "Enable" "link" should exist in the "User field" "table_row" 32 | And I click on "Enable" "link" in the "User field" "table_row" 33 | Then "Disable" "link" should exist in the "User field" "table_row" 34 | -------------------------------------------------------------------------------- /tests/behat/managing_pages.feature: -------------------------------------------------------------------------------- 1 | @tool @tool_certificate @moodleworkplace @javascript 2 | Feature: Being able to manage pages in a certificate template 3 | In order to ensure managing pages in a certificate template works as expected 4 | As an admin 5 | I need to manage pages in a certificate template 6 | 7 | Background: 8 | Given the following certificate templates exist: 9 | | name | numberofpages | 10 | | Certificate 1 | 1 | 11 | And I log in as "admin" 12 | And I navigate to "Certificates > Manage certificate templates" in site administration 13 | And I follow "Certificate 1" 14 | 15 | Scenario: Adding a page to a certificate template 16 | And I wait "1" seconds 17 | When I follow "New page" 18 | And I click on "Save" "button" in the ".modal.show .modal-footer" "css_element" 19 | And I should see "Page 1" 20 | And I should see "Page 2" 21 | 22 | Scenario: Deleting a page from a certificate template 23 | When I change window size to "large" 24 | When I add the element "User picture" to page "1" of the "Certificate 1" site certificate template 25 | And I click on "Save" "button" in the ".modal.show .modal-footer" "css_element" 26 | And I add the element "User field" to page "1" of the "Certificate 1" site certificate template 27 | And I click on "Save" "button" in the ".modal.show .modal-footer" "css_element" 28 | And I follow "New page" 29 | And I click on "Save" "button" in the ".modal.show .modal-footer" "css_element" 30 | And I should see "Page 1" 31 | And I should see "Page 2" 32 | And I click on "Delete" "link" in the "[data-region=\"page\"]" "css_element" 33 | And I click on "Delete" "button" in the "Confirm" "dialogue" 34 | And I should see "Page 1" 35 | And I should not see "Page 2" 36 | And I should not see "User picture" 37 | And I should not see "User field" 38 | And I log out 39 | 40 | Scenario: Rearrange pages in a certificate template 41 | When I change window size to "large" 42 | When I add the element "User picture" to page "1" of the "Certificate 1" site certificate template 43 | And I click on "Save" "button" in the ".modal.show .modal-footer" "css_element" 44 | And I follow "New page" 45 | And I click on "Save" "button" in the ".modal.show .modal-footer" "css_element" 46 | And I add the element "User field" to page "2" of the "Certificate 1" site certificate template 47 | And I click on "Save" "button" in the ".modal.show .modal-footer" "css_element" 48 | And I click on "Move down" "link" in the "//*[@data-region='page'][1]" "xpath_element" 49 | Then "User field" "text" should appear before "User picture" "text" 50 | And I click on "Move up" "link" in the "//*[@data-region='page'][2]" "xpath_element" 51 | Then "User field" "text" should appear after "User picture" "text" 52 | And I log out 53 | -------------------------------------------------------------------------------- /tests/behat/my_certificates.feature: -------------------------------------------------------------------------------- 1 | @tool @tool_certificate @moodleworkplace 2 | Feature: Being able to view the certificates you have been issued 3 | In order to ensure that a user can view the certificates they have been issued 4 | As a student 5 | I need to view the certificates I have been issued 6 | 7 | Background: 8 | Given the following "users" exist: 9 | | username | firstname | lastname | email | 10 | | student1 | Student | 1 | student1@example.com | 11 | | manager1 | Manager | 1 | manager1@example.com | 12 | And the following "courses" exist: 13 | | shortname | fullname | 14 | | C1 | Course 1 | 15 | And the following certificate templates exist: 16 | | name | 17 | | Certificate 1 | 18 | | Certificate 2 | 19 | | Certificate 3 | 20 | And the following certificate issues exist: 21 | | template | user | course | 22 | | Certificate 1 | student1 | | 23 | | Certificate 2 | student1 | C1 | 24 | 25 | @javascript @_switch_window 26 | Scenario: View your issued site certificates on the my certificates page 27 | When I log in as "student1" 28 | And I follow "Profile" in the user menu 29 | And I click on "//a[contains(.,'My certificates') and contains(@href,'tool/certificate')]" "xpath_element" 30 | And I should see "Certificate 1" in the "generaltable" "table" 31 | And I should see "Certificate 2 - Course 1" in the "generaltable" "table" 32 | And I should not see "Certificate 3" in the "generaltable" "table" 33 | And I click on "View" "link" in the "Certificate 1" "table_row" 34 | Then I can see a certificate in a new window 35 | And I should see "Certificate 1" in the "generaltable" "table" 36 | 37 | Scenario: View share certificate on LinkedIn 38 | When I log in as "student1" 39 | And the following config values are set as admin: 40 | | show_shareonlinkedin | true | tool_certificate | 41 | And I follow "Profile" in the user menu 42 | And I click on "//a[contains(.,'My certificates') and contains(@href,'tool/certificate')]" "xpath_element" 43 | Then I should see "Share on LinkedIn" 44 | And I should see a share on LinkedIn link for "Certificate 1" 45 | 46 | Scenario: Do not view share certificate on LinkedIn 47 | When I log in as "student1" 48 | And the following config values are set as admin: 49 | | show_shareonlinkedin | | tool_certificate | 50 | And I follow "Profile" in the user menu 51 | And I click on "//a[contains(.,'My certificates') and contains(@href,'tool/certificate')]" "xpath_element" 52 | Then I should not see "Share on LinkedIn" 53 | And I should not see a share on LinkedIn link for "Certificate 1" 54 | -------------------------------------------------------------------------------- /tests/behat/show_position_x_y.feature: -------------------------------------------------------------------------------- 1 | @tool @tool_certificate @moodleworkplace @javascript 2 | Feature: Being able to set a site setting to determine whether or not to display the position X and Y fields 3 | In order to ensure the show position X and Y fields setting works as expected 4 | As an admin 5 | I need to ensure admins can see the position X and Y fields depending on the site setting 6 | 7 | Background: 8 | Given the following certificate templates exist: 9 | | name | numberofpages | 10 | | Certificate 1 | 1 | 11 | 12 | Scenario: Adding an element with the show position X and Y setting enabled 13 | When I log in as "admin" 14 | When I change window size to "large" 15 | And I navigate to "Certificates > Manage certificate templates" in site administration 16 | And I follow "Certificate 1" 17 | And I add the element "Code" to page "1" of the "Certificate 1" site certificate template 18 | And I follow "Show more..." 19 | And I should see "Position X" 20 | And I should see "Position Y" 21 | And I set the following fields to these values: 22 | | Position X | 5 | 23 | | Position Y | 10 | 24 | And I click on "Save" "button" in the "Add 'Code' element" "dialogue" 25 | And I click on "Edit 'Code'" "link" in the "Code" "list_item" 26 | And the following fields match these values: 27 | | Position X | 5 | 28 | | Position Y | 10 | 29 | -------------------------------------------------------------------------------- /tests/behat/verify_certificates.feature: -------------------------------------------------------------------------------- 1 | @tool @tool_certificate @moodleworkplace 2 | Feature: Being able to verify that a certificate is valid or not 3 | In order to ensure that a user can verify a certificate is valid 4 | As an admin and non-user 5 | I need to be able to verify a certificate 6 | 7 | Background: 8 | Given the following "users" exist: 9 | | username | firstname | lastname | email | 10 | | student1 | Student | 1 | student1@example.com | 11 | And the following certificate templates exist: 12 | | name | 13 | | Certificate 1 | 14 | | Certificate 2 | 15 | 16 | Scenario: Verify a certificate as admin 17 | When the following certificate issues exist: 18 | | template | user | 19 | | Certificate 1 | student1 | 20 | | Certificate 2 | student1 | 21 | And I log in as "admin" 22 | And I visit the sites certificates verification url 23 | And I set the field "Code" to "NOTAVALIDCODE" 24 | And I press "Verify" 25 | Then I should see "Not verified" 26 | And I verify the "Certificate 1" site certificate for the user "student1" 27 | And I verify the "Certificate 2" site certificate for the user "student1" 28 | 29 | Scenario: Verify a certificate as a guest using the site-wide URL 30 | And the following certificate issues exist: 31 | | template | user | 32 | | Certificate 1 | student1 | 33 | | Certificate 2 | student1 | 34 | And I log in as "guest" 35 | And I visit the sites certificates verification url 36 | And I set the field "Code" to "NOTAVALIDCODE" 37 | And I press "Verify" 38 | Then I should see "Not verified" 39 | And I verify the "Certificate 1" site certificate for the user "student1" 40 | And I verify the "Certificate 2" site certificate for the user "student1" 41 | 42 | Scenario: Verify certificate of a removed user 43 | And the following certificate issues exist: 44 | | template | user | code | 45 | | Certificate 1 | student1 | aaaaaaaaa | 46 | And I log in as "admin" 47 | And I navigate to "Users > Accounts > Browse list of users" in site administration 48 | And I click on "Delete" "link" in the "Student 1" "table_row" 49 | And I press "Delete" 50 | And I visit the sites certificates verification url 51 | And I verify the site certificate with code "aaaaaaaaa" 52 | And I should see "Student 1" 53 | -------------------------------------------------------------------------------- /tests/behat/view_certificate.feature: -------------------------------------------------------------------------------- 1 | @tool @tool_certificate @moodleworkplace 2 | Feature: Being able to download valid certificates 3 | In order to ensure that a user can download a valid certificate 4 | As an admin and non-user 5 | I need to be able to download a certificate 6 | 7 | Background: 8 | Given the following "users" exist: 9 | | username | firstname | lastname | email | 10 | | teacher1 | Teacher | 1 | teacher1@example.com | 11 | | student1 | Student | 1 | student1@example.com | 12 | And the following certificate templates exist: 13 | | name | 14 | | Certificate 1 | 15 | | Certificate 2 | 16 | And the following certificate issues exist: 17 | | template | user | 18 | | Certificate 1 | student1 | 19 | 20 | Scenario: Download a certificate as admin 21 | When I log in as "admin" 22 | And I visit the sites certificates verification url 23 | And I verify the "Certificate 1" site certificate for the user "student1" 24 | And I click on "View certificate" "link" 25 | 26 | Scenario: Verify a certificate as a guest using the site-wide URL 27 | And the following "permission overrides" exist: 28 | | capability | permission | role | contextlevel | reference | 29 | | tool/certificate:verify | Allow | guest | System | | 30 | And I log in as "guest" 31 | And I visit the sites certificates verification url 32 | And I verify the "Certificate 1" site certificate for the user "student1" 33 | And I click on "View certificate" "link" 34 | -------------------------------------------------------------------------------- /tests/element_factory_test.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | namespace tool_certificate; 18 | 19 | use advanced_testcase; 20 | use tool_certificate_generator; 21 | use moodle_exception; 22 | 23 | /** 24 | * Unit tests for functions that deals with capabilities. 25 | * 26 | * @package tool_certificate 27 | * @group tool_certificate 28 | * @covers \tool_certificate\element 29 | * @copyright 2018 Daniel Neis Araujo 30 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 31 | */ 32 | final class element_factory_test extends advanced_testcase { 33 | /** 34 | * Test set up. 35 | */ 36 | public function setUp(): void { 37 | parent::setUp(); 38 | $this->resetAfterTest(); 39 | } 40 | 41 | /** 42 | * Get certificate generator 43 | * @return tool_certificate_generator 44 | */ 45 | protected function get_generator(): tool_certificate_generator { 46 | return $this->getDataGenerator()->get_plugin_generator('tool_certificate'); 47 | } 48 | 49 | /** 50 | * Test render_html 51 | */ 52 | public function test_get_element_instance_with_invalid_element(): void { 53 | $certificate1 = $this->get_generator()->create_template((object)['name' => 'Certificate 1']); 54 | $pageid = $this->get_generator()->create_page($certificate1)->get_id(); 55 | try { 56 | $element = (object)['pageid' => $pageid, 'element' => 'invalidelement']; 57 | \tool_certificate\element::instance(0, $element); 58 | $this->fail('Exception expected'); 59 | } catch (moodle_exception $e) { 60 | null; 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /tests/fixtures/signature.crt: -------------------------------------------------------------------------------- 1 | Bag Attributes 2 | localKeyID: 7B AB 1B 7A BE 4C 85 C0 1A A6 DC 59 3F 79 48 C3 93 38 68 9C 3 | subject=/CN=TCPDF DEMO/O=TCPDF/OU=DEMO/emailAddress=you@example.com/C=IT 4 | issuer=/CN=TCPDF DEMO/O=TCPDF/OU=DEMO/emailAddress=you@example.com/C=IT 5 | -----BEGIN CERTIFICATE----- 6 | MIIC1TCCAj6gAwIBAgIKkehOL/XGkB5cjjANBgkqhkiG9w0BAQUFADBhMRMwEQYD 7 | VQQDEwpUQ1BERiBERU1PMQ4wDAYDVQQKEwVUQ1BERjENMAsGA1UECxMEREVNTzEe 8 | MBwGCSqGSIb3DQEJARYPeW91QGV4YW1wbGUuY29tMQswCQYDVQQGEwJJVDAeFw0w 9 | OTA4MjExMjU0NDhaFw0xNDA4MjExMjU0NDhaMGExEzARBgNVBAMTClRDUERGIERF 10 | TU8xDjAMBgNVBAoTBVRDUERGMQ0wCwYDVQQLEwRERU1PMR4wHAYJKoZIhvcNAQkB 11 | Fg95b3VAZXhhbXBsZS5jb20xCzAJBgNVBAYTAklUMIGfMA0GCSqGSIb3DQEBAQUA 12 | A4GNADCBiQKBgQDAqIL0uGKmTR98Lxx2vEEE1OGKkMXFo0JViitALe7Onhxxqx0H 13 | XMUDKF5mvEVu1rcvh7/oAnAfrCuEpL/up3u1mQCgBE7WXBnFFE/AE3jCksh9OkS0 14 | Z0Xj9woN5bzxRDsGoPiOu/4xzk5qSEXt8jf2Ep90QuNkqLIRT4swAzpDbwIDAQAB 15 | o4GTMIGQMDcGA1UdEgQwMC6gEQYDVQQDDApUQ1BERiBERU1PoAwGA1UECgwFVENQ 16 | REagCwYDVQQLDARERU1PMDcGA1UdEQQwMC6gEQYDVQQDDApUQ1BERiBERU1PoAwG 17 | A1UECgwFVENQREagCwYDVQQLDARERU1PMA8GCSqGSIb3LwEBCgQCBQAwCwYDVR0P 18 | BAQDAgSQMA0GCSqGSIb3DQEBBQUAA4GBAEhTQfqX3ZNdHmpTLDbIj22RHXii2roE 19 | OavCbu9WsHoWpva0qSd+yIoD594VHvYAd29sfzDfiN+7W0aiZfDhq5jpaSQMVlN8 20 | RGYMupbHY/+a9Gz1wqxnR84mlTtIkZVRYAhsfPwy6M1BEjdMqfdh9h40JIdkdjtb 21 | 8faTCfXPePWQ 22 | -----END CERTIFICATE----- 23 | Bag Attributes 24 | localKeyID: 7B AB 1B 7A BE 4C 85 C0 1A A6 DC 59 3F 79 48 C3 93 38 68 9C 25 | Key Attributes: 26 | -----BEGIN RSA PRIVATE KEY----- 27 | MIICXQIBAAKBgQDAqIL0uGKmTR98Lxx2vEEE1OGKkMXFo0JViitALe7Onhxxqx0H 28 | XMUDKF5mvEVu1rcvh7/oAnAfrCuEpL/up3u1mQCgBE7WXBnFFE/AE3jCksh9OkS0 29 | Z0Xj9woN5bzxRDsGoPiOu/4xzk5qSEXt8jf2Ep90QuNkqLIRT4swAzpDbwIDAQAB 30 | AoGAXc+wNMmz/5Z+RlIKYia44klmqbplEx+0JULqXI4BQsrqvs67i+I4bJkznoL+ 31 | rEIRYSuQ3sCRKFsFtckjTGpxadnxkB+uwGKc6pZChv99BFX6HFR4hgBlT/BBRAQA 32 | hMDlM2JIRr4S4SMVXR7MHwGMUf9mUeanGLR3ZWtU3aXJrIECQQD7OaYUVYNEEnM9 33 | uXyjm22CuHyqyEf5gb13sK0uQty67547yJTMUQZd/sQc9KGwhzBbhrob2LO2jAhh 34 | S+f+NSRnAkEAxFHm3fMI5RgXmswxlGm4QW07a/Ueo7ZJG6xjTkFXluJhd+XHswRD 35 | dQIO3zG9nGjNUoeMrPhXhPvKqFc2F9RDuQJAQBEGin74N77gxqfr4ik79y8nE8J5 36 | oGZ2s/RJZdfFRKLg3mwbjjNHhWb4Ck5UgZkoOt8TzRApXG8/n9hktE5HFwJBALur 37 | M5AueO1Pl5kB489lNJ9OxUQRYUXMxpxuscuoCQwSwmv0O2+0/qtG2WKhUQnI4aYo 38 | L+FV0YwtivBb1jj3T/kCQQDIWOxq8eRowdaMzvJpRUHFgMcf1AVZExKyrugwYOWd 39 | KNsDxC4KaQOsPt8iT/Ulo4g/MJC0HolCOhWibKmR9Ayl 40 | -----END RSA PRIVATE KEY----- 41 | -------------------------------------------------------------------------------- /tests/observer_test.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | namespace tool_certificate; 18 | 19 | use advanced_testcase; 20 | use tool_certificate_generator; 21 | 22 | /** 23 | * Tests for functions in observer.php 24 | * 25 | * @package tool_certificate 26 | * @covers \tool_certificate_observer 27 | * @copyright 2020 Mikel Martín 28 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 29 | */ 30 | final class observer_test extends advanced_testcase { 31 | /** 32 | * Test setup 33 | */ 34 | public function setUp(): void { 35 | parent::setUp(); 36 | $this->resetAfterTest(); 37 | } 38 | 39 | /** 40 | * Get certificate generator 41 | * @return tool_certificate_generator 42 | */ 43 | protected function get_generator(): tool_certificate_generator { 44 | return $this->getDataGenerator()->get_plugin_generator('tool_certificate'); 45 | } 46 | 47 | /** 48 | * Test issues with courseid are removed when course is deleted. 49 | * 50 | * @return void 51 | */ 52 | public function test_course_deleted(): void { 53 | global $DB; 54 | 55 | $course1 = $this->getDataGenerator()->create_course(); 56 | $course2 = $this->getDataGenerator()->create_course(); 57 | 58 | $user1 = $this->getDataGenerator()->create_and_enrol($course1); 59 | $user2 = $this->getDataGenerator()->create_and_enrol($course1); 60 | 61 | $certificate1 = $this->get_generator()->create_template((object)['name' => 'Template 01']); 62 | $certificate2 = $this->get_generator()->create_template((object)['name' => 'Template 02']); 63 | // Using dummy component name. 64 | $certificate1->issue_certificate($user1->id, null, [], 'mod_myawesomecert', $course1->id); 65 | $certificate2->issue_certificate($user1->id, null, [], 'mod_myawesomecert', $course1->id); 66 | $certificate2->issue_certificate($user2->id, null, [], 'mod_myawesomecert', $course1->id); 67 | 68 | $certificate1->issue_certificate($user1->id, null, [], 'mod_myawesomecert', $course2->id); 69 | 70 | $this->assertEquals(3, $DB->count_records('tool_certificate_issues', ['courseid' => $course1->id])); 71 | $this->assertEquals(1, $DB->count_records('tool_certificate_issues', ['courseid' => $course2->id])); 72 | 73 | ob_start(); 74 | delete_course($course1); 75 | ob_end_clean(); 76 | 77 | $this->assertEmpty($DB->count_records('tool_certificate_issues', ['courseid' => $course1->id])); 78 | $this->assertEquals(1, $DB->count_records('tool_certificate_issues', ['courseid' => $course2->id])); 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /upload_image.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Handles uploading files 19 | * 20 | * @package tool_certificate 21 | * @copyright 2013 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | require('../../../config.php'); 26 | require_once($CFG->libdir.'/adminlib.php'); 27 | 28 | admin_externalpage_setup('tool_certificate/images'); 29 | 30 | $uploadform = new \tool_certificate\upload_image_form(); 31 | 32 | if ($uploadform->is_cancelled()) { 33 | redirect(new moodle_url('/admin/tool/certificate/manage_templates.php')); 34 | } else if ($data = $uploadform->get_data()) { 35 | // Handle file uploads. 36 | \tool_certificate\certificate::upload_files($data->certificateimage, \context_system::instance()->id); 37 | 38 | redirect(new moodle_url('/admin/tool/certificate/upload_image.php'), get_string('changessaved')); 39 | } 40 | 41 | $PAGE->set_heading(get_string('certificateimages', 'tool_certificate')); 42 | echo $OUTPUT->header(); 43 | $uploadform->display(); 44 | echo $OUTPUT->footer(); 45 | -------------------------------------------------------------------------------- /version.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * Code fragment to define the version of the certificate tool 19 | * 20 | * @package tool_certificate 21 | * @copyright 2013 Mark Nelson 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or late 23 | */ 24 | 25 | defined('MOODLE_INTERNAL') || die(); 26 | 27 | $plugin->component = 'tool_certificate'; 28 | $plugin->release = '5.0'; 29 | $plugin->version = 2025041400; 30 | $plugin->requires = 2025041400.00; 31 | $plugin->maturity = MATURITY_STABLE; 32 | $plugin->supported = [500, 500]; 33 | -------------------------------------------------------------------------------- /view.php: -------------------------------------------------------------------------------- 1 | . 16 | 17 | /** 18 | * View issued certificate as pdf. 19 | * 20 | * @package tool_certificate 21 | * @copyright 2018 Daniel Neis Araujo 22 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 23 | */ 24 | 25 | require_once('../../../config.php'); 26 | 27 | $issuecode = required_param('code', PARAM_TEXT); 28 | $preview = optional_param('preview', false, PARAM_BOOL); 29 | 30 | $PAGE->set_context(context_system::instance()); 31 | $PAGE->set_url(new moodle_url('/admin/tool/certificate/view.php', ['code' => $issuecode])); 32 | 33 | if ($preview) { 34 | $templateid = required_param('templateid', PARAM_INT); 35 | require_login(); 36 | $template = \tool_certificate\template::instance($templateid); 37 | if ($template->can_manage()) { 38 | $template->generate_pdf(true); 39 | } 40 | 41 | } else { 42 | $issue = \tool_certificate\template::get_issue_from_code($issuecode); 43 | $context = \context_course::instance($issue->courseid, IGNORE_MISSING) ?: null; 44 | 45 | $template = $issue ? \tool_certificate\template::instance($issue->templateid) : null; 46 | if ($template && (\tool_certificate\permission::can_verify() || 47 | \tool_certificate\permission::can_view_issue($template, $issue, $context))) { 48 | $url = $template->get_issue_file_url($issue); 49 | redirect($url); 50 | } else { 51 | throw new moodle_exception('notfound'); 52 | } 53 | } 54 | --------------------------------------------------------------------------------