Removed non-functional premium handling code. All features now normally available.
This commit is contained in:
parent
30fb9dd149
commit
fbe34189f6
|
@ -29,7 +29,6 @@ import {loadStrings} from './util/string-helper';
|
||||||
import {processStudyplan} from './studyplan-processor';
|
import {processStudyplan} from './studyplan-processor';
|
||||||
import {download, upload} from './downloader';
|
import {download, upload} from './downloader';
|
||||||
import {studyplanTiming} from './util/date-helper';
|
import {studyplanTiming} from './util/date-helper';
|
||||||
import {premiumenabled, premiumstatus} from "./util/premium";
|
|
||||||
import mFormComponents from "./util/mform-helper";
|
import mFormComponents from "./util/mform-helper";
|
||||||
Vue.use(mFormComponents);
|
Vue.use(mFormComponents);
|
||||||
|
|
||||||
|
@ -145,7 +144,6 @@ export function init(contextid, categoryid, options) {
|
||||||
|
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
premiumenabled,
|
|
||||||
dropdownTitle() {
|
dropdownTitle() {
|
||||||
if (this.activestudyplan && this.activestudyplan.name) {
|
if (this.activestudyplan && this.activestudyplan.name) {
|
||||||
return this.activestudyplan.name;
|
return this.activestudyplan.name;
|
||||||
|
|
|
@ -17,7 +17,6 @@ import Debugger from './util/debugger';
|
||||||
import Config from 'core/config';
|
import Config from 'core/config';
|
||||||
import {processStudyplan, objCopy} from './studyplan-processor';
|
import {processStudyplan, objCopy} from './studyplan-processor';
|
||||||
import TSComponents from './treestudyplan-components';
|
import TSComponents from './treestudyplan-components';
|
||||||
import {premiumenabled} from "./util/premium";
|
|
||||||
import FitTextVue from './util/fittext-vue';
|
import FitTextVue from './util/fittext-vue';
|
||||||
|
|
||||||
|
|
||||||
|
@ -926,7 +925,6 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
premiumenabled,
|
|
||||||
formatDatetime,
|
formatDatetime,
|
||||||
onLineHeightChange(lineid) {
|
onLineHeightChange(lineid) {
|
||||||
// All layers for this line have the first slot send an update message on layer height change.
|
// All layers for this line have the first slot send an update message on layer height change.
|
||||||
|
@ -1044,7 +1042,7 @@ export default {
|
||||||
><div class="r-studyline-handle" :style="'background-color: ' + value.color"></div>
|
><div class="r-studyline-handle" :style="'background-color: ' + value.color"></div>
|
||||||
<div class="r-studyline-title"><div>
|
<div class="r-studyline-title"><div>
|
||||||
<abbr v-b-tooltip.hover :title="value.name">{{ value.shortname }}</abbr>
|
<abbr v-b-tooltip.hover :title="value.name">{{ value.shortname }}</abbr>
|
||||||
<template v-if="premiumenabled() && enrollable">
|
<template v-if="enrollable">
|
||||||
<template v-if="teachermode">
|
<template v-if="teachermode">
|
||||||
<br>
|
<br>
|
||||||
<a v-if="!canEnrol"
|
<a v-if="!canEnrol"
|
||||||
|
|
|
@ -16,7 +16,6 @@ import Debugger from './util/debugger';
|
||||||
import Config from 'core/config';
|
import Config from 'core/config';
|
||||||
import {download, upload} from './downloader';
|
import {download, upload} from './downloader';
|
||||||
import {processStudyplan, processStudyplanPage} from './studyplan-processor';
|
import {processStudyplan, processStudyplanPage} from './studyplan-processor';
|
||||||
import {premiumenabled} from "./util/premium";
|
|
||||||
import FitTextVue from './util/fittext-vue';
|
import FitTextVue from './util/fittext-vue';
|
||||||
import {settings} from "./util/settings";
|
import {settings} from "./util/settings";
|
||||||
import TSComponents from './treestudyplan-components';
|
import TSComponents from './treestudyplan-components';
|
||||||
|
@ -820,7 +819,6 @@ export default {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
premiumenabled,
|
|
||||||
showModal() {
|
showModal() {
|
||||||
this.show = true;
|
this.show = true;
|
||||||
this.loadAssociations();
|
this.loadAssociations();
|
||||||
|
@ -863,19 +861,17 @@ export default {
|
||||||
return;
|
return;
|
||||||
}).catch(notification.exception);
|
}).catch(notification.exception);
|
||||||
|
|
||||||
if (premiumenabled()) {
|
self.loading.coaches = true;
|
||||||
self.loading.coaches = true;
|
call([{
|
||||||
call([{
|
methodname: 'local_treestudyplan_associated_coaches',
|
||||||
methodname: 'local_treestudyplan_associated_coaches',
|
args: {
|
||||||
args: {
|
'studyplan_id': self.value.id,
|
||||||
'studyplan_id': self.value.id,
|
}
|
||||||
}
|
}])[0].then((response) => {
|
||||||
}])[0].then((response) => {
|
self.association.coaches = response.map(self.userOptionModel);
|
||||||
self.association.coaches = response.map(self.userOptionModel);
|
self.loading.coaches = false;
|
||||||
self.loading.coaches = false;
|
return;
|
||||||
return;
|
}).catch(notification.exception);
|
||||||
}).catch(notification.exception);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
searchCohorts(searchtext) {
|
searchCohorts(searchtext) {
|
||||||
const self = this;
|
const self = this;
|
||||||
|
@ -999,65 +995,59 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
searchCoaches(searchtext) {
|
searchCoaches(searchtext) {
|
||||||
if (premiumenabled()) {
|
const self = this;
|
||||||
const self = this;
|
if (searchtext.length > 0) {
|
||||||
if (searchtext.length > 0) {
|
call([{
|
||||||
call([{
|
methodname: 'local_treestudyplan_find_coach',
|
||||||
methodname: 'local_treestudyplan_find_coach',
|
args: {
|
||||||
args: {
|
like: searchtext,
|
||||||
like: searchtext,
|
'studyplan_id': self.value.id,
|
||||||
'studyplan_id': self.value.id,
|
}
|
||||||
}
|
}])[0].then((response) => {
|
||||||
}])[0].then((response) => {
|
self.search.coaches = response.map(self.userOptionModel);
|
||||||
self.search.coaches = response.map(self.userOptionModel);
|
return;
|
||||||
return;
|
}).catch(notification.exception);
|
||||||
}).catch(notification.exception);
|
} else {
|
||||||
} else {
|
self.search.coaches = [];
|
||||||
self.search.coaches = [];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
coachAssociate() {
|
coachAssociate() {
|
||||||
if (premiumenabled()) {
|
const self = this;
|
||||||
const self = this;
|
const associated = self.association.coaches;
|
||||||
const associated = self.association.coaches;
|
const search = self.search.coaches;
|
||||||
const search = self.search.coaches;
|
const searchselected = self.selected.search.coaches;
|
||||||
const searchselected = self.selected.search.coaches;
|
for (const i in searchselected) {
|
||||||
for (const i in searchselected) {
|
const r = searchselected[i];
|
||||||
const r = searchselected[i];
|
|
||||||
|
|
||||||
call([{
|
call([{
|
||||||
methodname: 'local_treestudyplan_connect_coach',
|
methodname: 'local_treestudyplan_connect_coach',
|
||||||
args: {
|
args: {
|
||||||
'studyplan_id': self.value.id,
|
'studyplan_id': self.value.id,
|
||||||
'user_id': r,
|
'user_id': r,
|
||||||
},
|
},
|
||||||
}])[0].then((response) => {
|
}])[0].then((response) => {
|
||||||
if (response.success) {
|
if (response.success) {
|
||||||
transportItem(associated, search, r);
|
transportItem(associated, search, r);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}).catch(notification.exception);
|
}).catch(notification.exception);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
coachDisassociate() {
|
coachDisassociate() {
|
||||||
if (premiumenabled()) {
|
const self = this;
|
||||||
const self = this;
|
const associatedselected = self.selected.associated.coaches;
|
||||||
const associatedselected = self.selected.associated.coaches;
|
for (const i in associatedselected) {
|
||||||
for (const i in associatedselected) {
|
const r = associatedselected[i];
|
||||||
const r = associatedselected[i];
|
|
||||||
|
|
||||||
call([{
|
call([{
|
||||||
methodname: 'local_treestudyplan_disconnect_coach',
|
methodname: 'local_treestudyplan_disconnect_coach',
|
||||||
args: {
|
args: {
|
||||||
'studyplan_id': self.value.id,
|
'studyplan_id': self.value.id,
|
||||||
'user_id': r,
|
'user_id': r,
|
||||||
}
|
}
|
||||||
}])[0].then(() => {
|
}])[0].then(() => {
|
||||||
return;
|
return;
|
||||||
}).catch(notification.exception);
|
}).catch(notification.exception);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -1163,7 +1153,7 @@ export default {
|
||||||
</b-row>
|
</b-row>
|
||||||
</b-container>
|
</b-container>
|
||||||
</b-tab>
|
</b-tab>
|
||||||
<b-tab :title="text.coaches" v-if="premiumenabled()">
|
<b-tab :title="text.coaches">
|
||||||
<b-container>
|
<b-container>
|
||||||
<b-row class='mb-2 mt-2'>
|
<b-row class='mb-2 mt-2'>
|
||||||
<b-col>{{text.associated_coaches}}</b-col>
|
<b-col>{{text.associated_coaches}}</b-col>
|
||||||
|
@ -1509,7 +1499,6 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
premiumenabled,
|
|
||||||
columns(page) {
|
columns(page) {
|
||||||
return 1 + (page.periods * 2);
|
return 1 + (page.periods * 2);
|
||||||
},
|
},
|
||||||
|
@ -2144,7 +2133,6 @@ export default {
|
||||||
<!-- hsluv-picker v-model="create.studyline.color" horizontal displaysize="175" ></hsluv-picker -->
|
<!-- hsluv-picker v-model="create.studyline.color" horizontal displaysize="175" ></hsluv-picker -->
|
||||||
</b-col>
|
</b-col>
|
||||||
</b-row>
|
</b-row>
|
||||||
<template v-if="premiumenabled()">
|
|
||||||
<b-row>
|
<b-row>
|
||||||
<b-col cols="3">{{ text.studyline_enrollable}}</b-col>
|
<b-col cols="3">{{ text.studyline_enrollable}}</b-col>
|
||||||
<b-col>
|
<b-col>
|
||||||
|
@ -2170,7 +2158,6 @@ export default {
|
||||||
></b-form-select>
|
></b-form-select>
|
||||||
</b-col>
|
</b-col>
|
||||||
</b-row>
|
</b-row>
|
||||||
</template>
|
|
||||||
</b-container>
|
</b-container>
|
||||||
</b-modal>
|
</b-modal>
|
||||||
<b-modal
|
<b-modal
|
||||||
|
@ -2204,7 +2191,6 @@ export default {
|
||||||
<input type="color" v-model="edit.studyline.data.color" />
|
<input type="color" v-model="edit.studyline.data.color" />
|
||||||
</b-col>
|
</b-col>
|
||||||
</b-row>
|
</b-row>
|
||||||
<template v-if="premiumenabled()">
|
|
||||||
<b-row>
|
<b-row>
|
||||||
<b-col cols="3">{{ text.studyline_enrollable}}</b-col>
|
<b-col cols="3">{{ text.studyline_enrollable}}</b-col>
|
||||||
<b-col>
|
<b-col>
|
||||||
|
@ -2229,7 +2215,6 @@ export default {
|
||||||
></b-form-select>
|
></b-form-select>
|
||||||
</b-col>
|
</b-col>
|
||||||
</b-row>
|
</b-row>
|
||||||
</template>
|
|
||||||
</b-container>
|
</b-container>
|
||||||
</b-modal>
|
</b-modal>
|
||||||
</b-tab>
|
</b-tab>
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
/* eslint no-var: "error" */
|
|
||||||
/* eslint-env es6*/
|
|
||||||
|
|
||||||
import {call} from 'core/ajax';
|
|
||||||
import notification from 'core/notification';
|
|
||||||
|
|
||||||
// Prepare default value.
|
|
||||||
let premiumstatusCache = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if premium status is enabled.
|
|
||||||
* @returns {Bool} True/False
|
|
||||||
*/
|
|
||||||
export function premiumenabled() {
|
|
||||||
const premium = premiumstatus();
|
|
||||||
if (premium) {
|
|
||||||
return (premium.enabled) ? true : false;
|
|
||||||
} else {
|
|
||||||
return true; // Temporarily return true, that is easier than going full async.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get premium status object
|
|
||||||
* @returns {Object} The premium status object
|
|
||||||
*/
|
|
||||||
function premiumstatus() {
|
|
||||||
if (!premiumstatusCache) {
|
|
||||||
// Retrieve premium status if needed.
|
|
||||||
call([{
|
|
||||||
methodname: 'local_treestudyplan_premiumstatus',
|
|
||||||
args: {}
|
|
||||||
}])[0].then((response) => {
|
|
||||||
premiumstatusCache = response;
|
|
||||||
return;
|
|
||||||
}).catch(notification.exception);
|
|
||||||
}
|
|
||||||
return premiumstatusCache;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Preload premium status.
|
|
||||||
premiumstatus();
|
|
|
@ -8,7 +8,7 @@ import notification from 'core/notification';
|
||||||
let settingcache = null;
|
let settingcache = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if premium status is enabled.
|
* Retrieve settings.
|
||||||
* @param {String} key
|
* @param {String} key
|
||||||
* @returns {*}
|
* @returns {*}
|
||||||
*/
|
*/
|
||||||
|
@ -39,5 +39,5 @@ function loadsettings() {
|
||||||
return settingcache;
|
return settingcache;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Preload premium status.
|
// Preload settings.
|
||||||
loadsettings();
|
loadsettings();
|
|
@ -27,7 +27,6 @@ defined('MOODLE_INTERNAL') || die();
|
||||||
require_once($CFG->dirroot.'/repository/lib.php');
|
require_once($CFG->dirroot.'/repository/lib.php');
|
||||||
use local_treestudyplan\aggregator;
|
use local_treestudyplan\aggregator;
|
||||||
use local_treestudyplan\studyplan;
|
use local_treestudyplan\studyplan;
|
||||||
use local_treestudyplan\premium;
|
|
||||||
use local_treestudyplan\debug;
|
use local_treestudyplan\debug;
|
||||||
use local_treestudyplan\studyplanservice;
|
use local_treestudyplan\studyplanservice;
|
||||||
use local_treestudyplan\courseservice;
|
use local_treestudyplan\courseservice;
|
||||||
|
@ -236,14 +235,12 @@ class studyplan_editform extends formbase {
|
||||||
[],
|
[],
|
||||||
);
|
);
|
||||||
|
|
||||||
if (premium::enabled()) {
|
$field = 'template';
|
||||||
$field = 'template';
|
$mform->addElement('advcheckbox', $field,
|
||||||
$mform->addElement('advcheckbox', $field,
|
get_string('studyplan_template', 'local_treestudyplan'),
|
||||||
get_string('studyplan_template', 'local_treestudyplan'),
|
get_string('studyplan_template_details', 'local_treestudyplan'),
|
||||||
get_string('studyplan_template_details', 'local_treestudyplan'),
|
[],
|
||||||
[],
|
);
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$aggregators = [];
|
$aggregators = [];
|
||||||
|
|
|
@ -1,476 +0,0 @@
|
||||||
<?php
|
|
||||||
// This file is part of the Studyplan plugin for Moodle
|
|
||||||
//
|
|
||||||
// Moodle is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// Moodle is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU General Public License
|
|
||||||
// along with Moodle. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine premium status
|
|
||||||
* @package local_treestudyplan
|
|
||||||
* @copyright 2023 P.M. Kuipers
|
|
||||||
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace local_treestudyplan;
|
|
||||||
defined('MOODLE_INTERNAL') || die();
|
|
||||||
|
|
||||||
require_once($CFG->libdir.'/externallib.php');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle badge information in the same style as the other classes
|
|
||||||
*/
|
|
||||||
class premium extends \external_api {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Toggle the variable below to enable support for premium stuff.
|
|
||||||
* If set to false, all premium features will be enabled and no premium settings panel will be visible.
|
|
||||||
* @var bool
|
|
||||||
*/
|
|
||||||
private static $premiumsupported = false;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Certficate code
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private static $premiumcrt = "-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDSzCCAjMCFFlyhmKf1fN7U5lQL/dtlsyP24AQMA0GCSqGSIb3DQEBCwUAMGEx
|
|
||||||
CzAJBgNVBAYTAk5MMRYwFAYDVQQIDA1Ob29yZC1Ib2xsYW5kMRowGAYDVQQKDBFN
|
|
||||||
aXFyYSBFbmdpbmVlcmluZzEeMBwGA1UEAwwVVHJlZVN0dWR5cGxhbiBQcmVtaXVt
|
|
||||||
MCAXDTI0MDIxMDE2MDQwM1oYDzIxMjQwMTE3MTYwNDAzWjBhMQswCQYDVQQGEwJO
|
|
||||||
TDEWMBQGA1UECAwNTm9vcmQtSG9sbGFuZDEaMBgGA1UECgwRTWlxcmEgRW5naW5l
|
|
||||||
ZXJpbmcxHjAcBgNVBAMMFVRyZWVTdHVkeXBsYW4gUHJlbWl1bTCCASIwDQYJKoZI
|
|
||||||
hvcNAQEBBQADggEPADCCAQoCggEBAOD7+Nf5UBYGmIadI+kRM7vSPGA12F6cyZuZ
|
|
||||||
O/JsdCWzZx3cCgVYt29DxHRvFVGrhGGLsoaMY9iXc9LdeO02jKqL3RoPo2kc5moT
|
|
||||||
SNarsKZcGZXgqo5NATmdMLqQpKAy41H0ybgXZDLq5XKs9YIRlkwSpzQTNeP49mOl
|
|
||||||
48giVX3icbpMw1TdQotalKXAtcs62o+guQJNANpjBRxPXssrmDoNXrJcAtUjNOjx
|
|
||||||
8M+8tCmwkKwBoK8F3wWxIo04kZ9KILtybMmn4VJJ6SwLEf4StphTIoru8zS7XUt8
|
|
||||||
3HbV3PsiyYErPlwIcobfcjwZJpub23bzetvxRvhpeIpLhrTGrPMCAwEAATANBgkq
|
|
||||||
hkiG9w0BAQsFAAOCAQEAQwkbP6m3sdQgXEK3mYYZvvs6R/FI9QPu/9ICA+dgfj4y
|
|
||||||
7wvL0toYYR5oXdhO9At3MYmS+0bFUmqoTS+cxsC4COpEKFbRBWwbJ3NXAw14Hx2U
|
|
||||||
ELLqMZGJNOwNV+3ZdhADrwA++AjUqu144ObrcNUqo4+A4h9R8qj+o0J50Gvwja9R
|
|
||||||
Uh67LsF4Ls8fUtqzpqct94bUl6MPMHlH4qpZlgndmQdgOwLWeQEmM8X3WtSJH90S
|
|
||||||
n8FqBInMBhGu1uz0Qeo09ke0RHRnghP9EXfig/veMegASZeEhFqmS2Bdiy6gqeZ5
|
|
||||||
Klc5I28bGbvxIV5pnL6ZSjHEDp2WreM8HB0XFJwU+Q==
|
|
||||||
-----END CERTIFICATE-----";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cached status
|
|
||||||
* @var object
|
|
||||||
*/
|
|
||||||
private static $cachedpremiumstatus = null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if premium is supported
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public static function supported() {
|
|
||||||
return self::$premiumsupported;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decrypt encrypted data
|
|
||||||
* @param string $encrypted Encrypted data
|
|
||||||
*/
|
|
||||||
private static function decrypt($encrypted) {
|
|
||||||
// Get the public key.
|
|
||||||
$key = \openssl_get_publickey(self::$premiumcrt);
|
|
||||||
if ($key === false) {
|
|
||||||
throw new \ParseError("Error parsing public key data)");
|
|
||||||
}
|
|
||||||
// Determine the key size.
|
|
||||||
$keysize = \openssl_pkey_get_details($key)["bits"];
|
|
||||||
$blocksize = ($keysize / 8); // Bits / 8. Whether padded or not.
|
|
||||||
|
|
||||||
// Decode data in.
|
|
||||||
$b64 = \base64_decode($encrypted);
|
|
||||||
if ($b64 === false) {
|
|
||||||
throw new \ParseError("Error in base64 decoding");
|
|
||||||
}
|
|
||||||
|
|
||||||
$data = \str_split($b64, $blocksize);
|
|
||||||
$decrypted = "";
|
|
||||||
$i = 0;
|
|
||||||
foreach ($data as $chunk) {
|
|
||||||
if (\openssl_public_decrypt($chunk, $dchunk, $key, \OPENSSL_PKCS1_PADDING)) {
|
|
||||||
$decrypted .= $dchunk;
|
|
||||||
} else {
|
|
||||||
throw new \ParseError("Error decrypting chunk $i ({$blocksize} bytes)");
|
|
||||||
}
|
|
||||||
$i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated in PHP 8.0 and up, but included to be compatible with 7.4.
|
|
||||||
if (\PHP_MAJOR_VERSION < 8) {
|
|
||||||
\openssl_pkey_free($key);
|
|
||||||
}
|
|
||||||
|
|
||||||
return $decrypted;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Trim headers from key data
|
|
||||||
* @param string $data the key dat with headers
|
|
||||||
* @return string Key without headers
|
|
||||||
*/
|
|
||||||
private static function trim_headers($data) {
|
|
||||||
// Headers are repeated in this function for easier testing and copy-pasting into other projects.
|
|
||||||
$startheader = "----- BEGIN ACTIVATION KEY -----";
|
|
||||||
$endheader = "----- END ACTIVATION KEY -----";
|
|
||||||
|
|
||||||
$parts = preg_split("/\r?\n/", \trim($data));
|
|
||||||
if (count($parts) > 2) {
|
|
||||||
$start = -1;
|
|
||||||
$end = -1;
|
|
||||||
for ($i = 0; $i < count($parts); $i++) {
|
|
||||||
// Make sure all unicode spaces are converted to normal spaces before comparing.
|
|
||||||
$p = trim(preg_replace('/\s+/u', ' ', $parts[$i]));
|
|
||||||
|
|
||||||
if ($p == $startheader) {
|
|
||||||
$start = $i + 1;
|
|
||||||
}
|
|
||||||
if ($start > 0 && $p == $endheader) {
|
|
||||||
$end = $i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($start < 0 || $end < 0 || $end - $start <= 0) {
|
|
||||||
throw new \ParseError("Invalid activation key wrappers");
|
|
||||||
} else {
|
|
||||||
$keyslice = array_slice($parts, $start, $end - $start);
|
|
||||||
return implode("\n", $keyslice);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
throw new \ParseError("Invalid activation key");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if premium status is enabled
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public static function enabled() {
|
|
||||||
if (self::$premiumsupported) {
|
|
||||||
$status = self::premiumstatus();
|
|
||||||
return $status->enabled;
|
|
||||||
} else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the premium key includes a specific intent in addition to the treestudyplan.
|
|
||||||
* @param string $intent The intent to search for
|
|
||||||
* @return bool
|
|
||||||
*/
|
|
||||||
public static function has_intent($intent) {
|
|
||||||
$status = self::premiumstatus();
|
|
||||||
if ($status->enabled) {
|
|
||||||
return \in_array(\strtolower($intent), $status->intents);
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate debug info.
|
|
||||||
*/
|
|
||||||
public static function debuginfo() {
|
|
||||||
$s = "<pre>";
|
|
||||||
try {
|
|
||||||
$activationkey = \get_config("local_treestudyplan", "premium_key");
|
|
||||||
if (strlen($activationkey) > 0) {
|
|
||||||
$keydata = self::trim_headers($activationkey);
|
|
||||||
$json = self::decrypt($keydata);
|
|
||||||
$s .= "Decoded key data:\n----\n";
|
|
||||||
$s .= $json . "\n----\n";
|
|
||||||
$decoded = \json_decode($json, false);
|
|
||||||
$s .= "Read as object:\n----\n";
|
|
||||||
$s .= \json_encode($decoded, \JSON_PRETTY_PRINT) ."\n----\n";
|
|
||||||
$status = self::premiumstatus();
|
|
||||||
$s .= "Parsed premium status block:\n----\n";
|
|
||||||
$s .= \json_encode($status, \JSON_PRETTY_PRINT) ."\n----\n";
|
|
||||||
$s .= "Message: " . self::statusdescription() . "\n";
|
|
||||||
} else {
|
|
||||||
$s .= "Premium key empty";
|
|
||||||
}
|
|
||||||
} catch (\Throwable $x) {
|
|
||||||
$s .= "!!! " . get_class($x) . ": " . $x->getCode() . " | " . $x->getMessage(). "\n";
|
|
||||||
$stack = explode("\n", $x->getTraceAsString());
|
|
||||||
foreach ($stack as $l) {
|
|
||||||
$s .= " " . trim($l) ."\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$s .= "</pre>";
|
|
||||||
return $s;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Determine, cache and retrieve premium status
|
|
||||||
* @return object
|
|
||||||
*/
|
|
||||||
protected static function premiumstatus() {
|
|
||||||
if (!isset(self::$cachedpremiumstatus)) {
|
|
||||||
|
|
||||||
// Initialize default object.
|
|
||||||
$o = new \stdClass;
|
|
||||||
$o->enabled = false;
|
|
||||||
$o->intents = [];
|
|
||||||
$o->name = "";
|
|
||||||
$o->website = "";
|
|
||||||
$o->expires = "";
|
|
||||||
$o->expired = false;
|
|
||||||
$o->issued = "";
|
|
||||||
try {
|
|
||||||
$activationkey = \get_config("local_treestudyplan", "premium_key");
|
|
||||||
if (strlen($activationkey) > 0) {
|
|
||||||
|
|
||||||
$keydata = self::trim_headers($activationkey);
|
|
||||||
$json = self::decrypt($keydata);
|
|
||||||
$decoded = \json_decode($json, false);
|
|
||||||
|
|
||||||
if (is_object($decoded)) {
|
|
||||||
|
|
||||||
// Copy basic data/.
|
|
||||||
$keys = ["name", "website", "expires", "issued"];
|
|
||||||
foreach ($keys as $k) {
|
|
||||||
if (isset($decoded->$k)) {
|
|
||||||
$o->$k = $decoded->$k;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!empty($decoded->intent)) {
|
|
||||||
$o->intents = explode(",", $decoded->intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert dates to DateTime for.
|
|
||||||
$now = new \DateTime();
|
|
||||||
$issuedate = new \DateTime($o->issued);
|
|
||||||
if ($o->expires == 'never') {
|
|
||||||
// If expiry date == never.
|
|
||||||
$expirydate = new \DateTime(); // Default to now and add a year.
|
|
||||||
$expirydate->add(new \DateInterval("P1Y"));
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
$expirydate = new \DateTime($o->expires);
|
|
||||||
} catch (\Exception $x) {
|
|
||||||
$expirydate = new \DateTime(); // Default to now.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (\in_array('treestudyplan', $o->intents)
|
|
||||||
&& !empty($o->issued)
|
|
||||||
&& self::website_match($o->website)
|
|
||||||
) {
|
|
||||||
if ($expirydate > $now) {
|
|
||||||
$o->enabled = true;
|
|
||||||
$o->expired = false;
|
|
||||||
} else {
|
|
||||||
$o->expired = true;
|
|
||||||
$o->enabled = false;
|
|
||||||
}
|
|
||||||
// Format dates localized.
|
|
||||||
$o->issued = \userdate($issuedate->getTimestamp(), \get_string('strftimedate', 'langconfig'));
|
|
||||||
if ($o->expires == "never") {
|
|
||||||
$o->expires = \get_string("premium:never", 'local_treestudyplan');
|
|
||||||
} else {
|
|
||||||
$o->expires = \userdate($expirydate->getTimestamp(), \get_string('strftimedate', 'langconfig'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (\ParseError $x) {
|
|
||||||
$o->status = \get_string("premium:invalidactivationcontent", "local_treestudyplan");
|
|
||||||
}
|
|
||||||
self::$cachedpremiumstatus = $o;
|
|
||||||
|
|
||||||
}
|
|
||||||
return self::$cachedpremiumstatus;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the current site matches the provided key
|
|
||||||
* @param string $key Website pattern to match against
|
|
||||||
*/
|
|
||||||
private static function website_match($key) {
|
|
||||||
global $CFG;
|
|
||||||
$site = $CFG->wwwroot;
|
|
||||||
|
|
||||||
// Add double slashes to key and site if no scheme is set.
|
|
||||||
// Basically: if no double slashes present before any dots, slashes or @s.
|
|
||||||
if (!\preg_match_all('#^[^./@]*?//#', $key)) {
|
|
||||||
$key = "//".$key;
|
|
||||||
}
|
|
||||||
if (!\preg_match_all('#^[^./@]*?//#', $site)) {
|
|
||||||
$site = "//".$site;
|
|
||||||
}
|
|
||||||
// Use parse_url() to split path and host.
|
|
||||||
$keyurl = (object)\parse_url($key);
|
|
||||||
$siteurl = (object)\parse_url($site);
|
|
||||||
|
|
||||||
// No match if host is empty on key or site.
|
|
||||||
if (empty($keyurl->host) || empty($siteurl->host)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($keyurl->host == "*") {
|
|
||||||
// Value * matches all.
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// First match the host part.
|
|
||||||
$keyparts = \array_reverse(\explode(".", $keyurl->host));
|
|
||||||
$siteparts = \array_reverse(\explode(".", $siteurl->host));
|
|
||||||
|
|
||||||
// Trim starting www from both parts, since site.domain and www.site.domain should be treated as the same.
|
|
||||||
if (($x = \array_pop($keyparts)) != "www") {
|
|
||||||
\array_push($keyparts, $x);
|
|
||||||
}
|
|
||||||
if (($x = \array_pop($siteparts)) != "www") {
|
|
||||||
\array_push($siteparts, $x);
|
|
||||||
}
|
|
||||||
|
|
||||||
for ($i = 0; $i < count($keyparts); $i++) {
|
|
||||||
// No match if the site does not have a part, but the key does. Unless the key part is .
|
|
||||||
if (!isset($siteparts[$i])) {
|
|
||||||
if ($keyparts[$i] != "*") {
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
$i++; // Increment $i by one before break, to make sure the comparison following this loop holds.
|
|
||||||
break; // Stop comparison. Host part matches.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now do a proper case insensitive check for matching.
|
|
||||||
// Uses fnmatch to easily handle shell type wildcards.
|
|
||||||
if (! \fnmatch($keyparts[$i], $siteparts[$i], \FNM_CASEFOLD)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Fail if the site has a deeper subdomain than the key, unless the deepest key subdomain is .
|
|
||||||
if ($keyparts[$i - 1] != '*' && count($siteparts) > ($i)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we made it here then the host part matches. Now check the path.
|
|
||||||
// If path is /*, matches all subpaths including /.
|
|
||||||
$keypath = empty($keyurl->path) ? "/" : $keyurl->path;
|
|
||||||
$sitepath = empty($siteurl->path) ? "/" : $siteurl->path;
|
|
||||||
|
|
||||||
// Trim trailing / from both paths before comparison.
|
|
||||||
if (\strlen($sitepath) > 1) {
|
|
||||||
$sitepath = \rtrim($sitepath, "/");
|
|
||||||
}
|
|
||||||
if (\strlen($keypath) > 1) {
|
|
||||||
$keypath = \rtrim($keypath, "/");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do a case insensitive fnmatch on the site so wildcards are matched too.
|
|
||||||
return \fnmatch($keypath, $sitepath, \FNM_CASEFOLD);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parameter description for webservice function get_premiumstatus
|
|
||||||
*/
|
|
||||||
public static function get_premiumstatus_parameters(): \external_function_parameters {
|
|
||||||
return new \external_function_parameters([]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return value description for webservice function get_premiumstatus
|
|
||||||
*/
|
|
||||||
public static function get_premiumstatus_returns(): \external_description {
|
|
||||||
return new \external_single_structure([
|
|
||||||
"enabled" => new \external_value(PARAM_BOOL, 'premium status enabled'),
|
|
||||||
"website" => new \external_value(PARAM_TEXT, 'premium registration website'),
|
|
||||||
"name" => new \external_value(PARAM_TEXT, 'premium registration name'),
|
|
||||||
"expires" => new \external_value(PARAM_TEXT, 'premium registration expiry date'),
|
|
||||||
"expired" => new \external_value(PARAM_BOOL, 'premium status expired'),
|
|
||||||
"intents" => new \external_multiple_structure(
|
|
||||||
new \external_value(PARAM_TEXT), 'additional intents included in the license'
|
|
||||||
),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get premium status information for webservice
|
|
||||||
* @return object
|
|
||||||
*/
|
|
||||||
public static function get_premiumstatus() {
|
|
||||||
if (self::$premiumsupported) {
|
|
||||||
$status = self::premiumstatus();
|
|
||||||
$keys = [
|
|
||||||
"enabled",
|
|
||||||
"website",
|
|
||||||
"name",
|
|
||||||
"expires",
|
|
||||||
"expired",
|
|
||||||
"intents",
|
|
||||||
];
|
|
||||||
|
|
||||||
$result = [];
|
|
||||||
foreach ($keys as $param) {
|
|
||||||
$result[$param] = $status->$param;
|
|
||||||
}
|
|
||||||
return $result;
|
|
||||||
} else {
|
|
||||||
return [
|
|
||||||
"enabled" => true,
|
|
||||||
"website" => '*',
|
|
||||||
"name" => '*',
|
|
||||||
"expires" => '',
|
|
||||||
"expired" => false,
|
|
||||||
"intents" => [],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a descriptive text of the current premium status
|
|
||||||
* @return string HTML description of premium status.
|
|
||||||
*/
|
|
||||||
public static function statusdescription() {
|
|
||||||
$status = self::premiumstatus();
|
|
||||||
|
|
||||||
$msg = new \stdClass;
|
|
||||||
$msg->name = $status->name;
|
|
||||||
$msg->issued = $status->issued;
|
|
||||||
$msg->expires = $status->expires;
|
|
||||||
if ($status->website != "*") {
|
|
||||||
$msg->sitestatus = \get_string("premium:onsite", 'local_treestudyplan', $status);
|
|
||||||
} else {
|
|
||||||
$msg->sitestatus = \get_string("premium:anywhere", 'local_treestudyplan');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($status->enabled) {
|
|
||||||
return \get_string("premium:active", 'local_treestudyplan', $msg);
|
|
||||||
} else if ($status->expired) {
|
|
||||||
return \get_string("premium:expired", 'local_treestudyplan', $msg);
|
|
||||||
} else if (!self::website_match($status->website)) {
|
|
||||||
return \get_string("premium:siteinvalid", 'local_treestudyplan', $status->website);
|
|
||||||
} else {
|
|
||||||
return \get_string("premium:notregistered", 'local_treestudyplan', $msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Throw an error if premium status is not enabled
|
|
||||||
* @param string $message Message translation key to use in exception
|
|
||||||
*/
|
|
||||||
public static function require_premium($message="premiumfeature:warning") {
|
|
||||||
if (! self::enabled()) {
|
|
||||||
throw new \moodle_exception($message, "local_treestudyplan");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -556,7 +556,7 @@ class studentstudyplanservice extends \external_api {
|
||||||
\external_api::validate_context(\context_system::instance());
|
\external_api::validate_context(\context_system::instance());
|
||||||
|
|
||||||
// Return empty list if coach role not enabled.
|
// Return empty list if coach role not enabled.
|
||||||
if (! (premium::enabled() && \get_config("local_treestudyplan", "enablecoach"))) {
|
if (! (\get_config("local_treestudyplan", "enablecoach"))) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -810,7 +810,7 @@ class studyplan {
|
||||||
public function is_coach($user=null) {
|
public function is_coach($user=null) {
|
||||||
global $DB, $USER;
|
global $DB, $USER;
|
||||||
|
|
||||||
if (! (premium::enabled() && \get_config("local_treestudyplan", "enablecoach"))) {
|
if (! (\get_config("local_treestudyplan", "enablecoach"))) {
|
||||||
// If coach role is not available, return false immediately.
|
// If coach role is not available, return false immediately.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,6 @@
|
||||||
|
|
||||||
require_once("../../config.php");
|
require_once("../../config.php");
|
||||||
|
|
||||||
use local_treestudyplan\premium;
|
|
||||||
|
|
||||||
require_once($CFG->libdir.'/weblib.php');
|
require_once($CFG->libdir.'/weblib.php');
|
||||||
|
|
||||||
|
@ -37,7 +36,6 @@ $PAGE->set_context($systemcontext);
|
||||||
$PAGE->set_title(get_string('coaching_plans', 'local_treestudyplan'));
|
$PAGE->set_title(get_string('coaching_plans', 'local_treestudyplan'));
|
||||||
$PAGE->set_heading(get_string('coaching_plans', 'local_treestudyplan'));
|
$PAGE->set_heading(get_string('coaching_plans', 'local_treestudyplan'));
|
||||||
|
|
||||||
premium::require_premium();
|
|
||||||
if (! (\get_config("local_treestudyplan", "enablecoach"))) {
|
if (! (\get_config("local_treestudyplan", "enablecoach"))) {
|
||||||
throw new \moodle_exception("error:coachdisabled", "local_treestudyplan");
|
throw new \moodle_exception("error:coachdisabled", "local_treestudyplan");
|
||||||
}
|
}
|
||||||
|
|
|
@ -754,18 +754,6 @@ $functions = [
|
||||||
'capabilities' => 'local/treestudyplan:viewuserreports',
|
'capabilities' => 'local/treestudyplan:viewuserreports',
|
||||||
'loginrequired' => true,
|
'loginrequired' => true,
|
||||||
],
|
],
|
||||||
/***************************
|
|
||||||
* Premium status functions
|
|
||||||
***************************/
|
|
||||||
'local_treestudyplan_premiumstatus' => [ // Web service function name.
|
|
||||||
'classname' => '\local_treestudyplan\premium', // Class containing the external function.
|
|
||||||
'methodname' => 'get_premiumstatus', // External function name.
|
|
||||||
'description' => 'Retrieve premium status info',
|
|
||||||
'type' => 'read', // Database rights of the web service function (read, write).
|
|
||||||
'ajax' => true,
|
|
||||||
'capabilities' => '',
|
|
||||||
'loginrequired' => false,
|
|
||||||
],
|
|
||||||
/***************************
|
/***************************
|
||||||
* Studyline enrollment functions
|
* Studyline enrollment functions
|
||||||
***************************/
|
***************************/
|
||||||
|
|
|
@ -139,13 +139,13 @@
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>local/treestudyplan:lineunenrol</td>
|
<td>local/treestudyplan:lineunenrol</td>
|
||||||
<td>(Premium feature related) Users with this right in addition to <i>viewuserreports</i> can unregister students from an registerable line</td>
|
<td>Users with this right in addition to <i>viewuserreports</i> can unregister students from an registerable line</td>
|
||||||
<td>manager</td>
|
<td>manager</td>
|
||||||
<td>System and/or category</td>
|
<td>System and/or category</td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>local/treestudyplan:coach</td>
|
<td>local/treestudyplan:coach</td>
|
||||||
<td>(Premium feature related) Users with this right can be selected as coaches in the given context</td>
|
<td>Users with this right can be selected as coaches in the given context</td>
|
||||||
<td>manager</td>
|
<td>manager</td>
|
||||||
<td>System and/or category</td>
|
<td>System and/or category</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
|
@ -166,7 +166,7 @@ print <<<END
|
||||||
<b-button
|
<b-button
|
||||||
variant='danger' href='#' role='presentation' @click="importStudyplan "
|
variant='danger' href='#' role='presentation' @click="importStudyplan "
|
||||||
><i class='fa fa-upload'></i> {{ text.advanced_import_from_file }}</b-button
|
><i class='fa fa-upload'></i> {{ text.advanced_import_from_file }}</b-button
|
||||||
><mform v-if="premiumenabled && templatecount > 0"
|
><mform v-if="templatecount > 0"
|
||||||
name="studyplan_fromtemplateform"
|
name="studyplan_fromtemplateform"
|
||||||
:params="{contextid: contextid }"
|
:params="{contextid: contextid }"
|
||||||
@saved="onStudyPlanCreated"
|
@saved="onStudyPlanCreated"
|
||||||
|
|
|
@ -474,31 +474,6 @@ $string["error:nostudyplaneditaccess"] = 'Error: You do not have access to manag
|
||||||
$string["error:nocategoriesvisible"] = 'Error: You have no viewing permissions in any category. Therefore the course list remains empty.';
|
$string["error:nocategoriesvisible"] = 'Error: You have no viewing permissions in any category. Therefore the course list remains empty.';
|
||||||
$string["error:usernotassociated"] = 'Error: Requested student is not associated with this studyplan';
|
$string["error:usernotassociated"] = 'Error: Requested student is not associated with this studyplan';
|
||||||
|
|
||||||
$string["premium:never"] = 'never';
|
|
||||||
$string["premium:anywhere"] = 'for use anywhere';
|
|
||||||
$string["premium:onsite"] = 'for use on site <b>{$a->website}</b>';
|
|
||||||
$string["premium:active"] = 'Premium access <b class="text-success">enabled</b>.<br> Registered to <b>{$a->name}</b> {$a->sitestatus}<br>Expires <b>{$a->expires}</b>';
|
|
||||||
$string["premium:notregistered"] = 'Premium access <b>disabled</b> ';
|
|
||||||
$string["premium:invalidactivationcontent"] = 'Premium activation key not recognized';
|
|
||||||
$string["premium:siteinvalid"] = 'Premium access <b>disabled</b>. Activation key is only valid for use on <b>{$a}</b>';
|
|
||||||
$string["premium:expired"] = 'Premium access <b class="text-danger">expired</b> on <b>{$a->expires}</b><br>Was registered to <b>{$a->name}</b> {$a->sitestatus}';
|
|
||||||
$string["settingspage_premium"] = 'Premium registration';
|
|
||||||
$string["setting_premium_heading"] = 'Premium features';
|
|
||||||
$string["settingdesc_premium_heading"] = 'To access premium features, you need a registration key.
|
|
||||||
<br>Premium features include:
|
|
||||||
<ul>
|
|
||||||
<li>Overview of grades for all students in a studyplan.</li>
|
|
||||||
<li>Rows in a studyplan which a student can choose to unlock.</li>
|
|
||||||
<li>Coach role, which allows a linked coach to follow student progress and limited options to make changes to the studyplan content.</li>
|
|
||||||
</ul>';
|
|
||||||
$string["setting_premium_status"] = 'Current premium status';
|
|
||||||
$string["setting_premium_key"] = 'Activation key';
|
|
||||||
$string["settingdesc_premium_key"] = 'Paste the premium key you received in the box above.<br> <b>Attention!</b> The lines <i>----- BEGIN ACTIVATION KEY -----</i> and <i>----- END ACTIVATION KEY -----</i> are part of the key.';
|
|
||||||
$string["setting_premium_debug"] = 'Debug info for premium key';
|
|
||||||
|
|
||||||
$string["premiumfeature:morestudyplans"] = 'Creating more than 5 studyplans in a single category is a premium feature.';
|
|
||||||
$string["premiumfeature:morecategories"] = 'Creating studyplans in more than 20 categories is a premium feature.';
|
|
||||||
$string["premiumfeature:warning"] = 'The features on this page are only accessible if your site has premium features enabled.';
|
|
||||||
$string["error:coachdisabled"] = "The coach page has been disabled by the system administrator";
|
$string["error:coachdisabled"] = "The coach page has been disabled by the system administrator";
|
||||||
$string["overall"] = 'Course';
|
$string["overall"] = 'Course';
|
||||||
$string["studyplan_report"] = 'Studyplan result overview';
|
$string["studyplan_report"] = 'Studyplan result overview';
|
||||||
|
|
|
@ -475,31 +475,6 @@ $string["error:nostudyplaneditaccess"] = 'Fout: Je hebt geen rechten om studiepl
|
||||||
$string["error:nocategoriesvisible"] = 'Fout: Je kunt geen cursussen in een categorie bekijken. Daarom blijft de cursuslijst leeg';
|
$string["error:nocategoriesvisible"] = 'Fout: Je kunt geen cursussen in een categorie bekijken. Daarom blijft de cursuslijst leeg';
|
||||||
$string["error:usernotassociated"] = 'Fout: De gevraagde student is niet gekoppeld aan dit studieplan';
|
$string["error:usernotassociated"] = 'Fout: De gevraagde student is niet gekoppeld aan dit studieplan';
|
||||||
|
|
||||||
$string["premium:never"] = 'nooit';
|
|
||||||
$string["premium:anywhere"] = 'voor gebruik overal';
|
|
||||||
$string["premium:onsite"] = 'voor gebruik op {$a->website}';
|
|
||||||
$string["premium:active"] = 'Premium toegang <b class="text-success">ingeschakeld</b>.<br>Uitgegeven aan <b>{$a->name}</b> {$a->sitestatus}<br>Verloopt op<b>{$a->expires}</b>';
|
|
||||||
$string["premium:notregistered"] = 'Premium toegang staat <b>uitgeschakeld</n>';
|
|
||||||
$string["premium:invalidactivationcontent"] = 'Premium activeringssleutel niet herkend';
|
|
||||||
$string["premium:siteinvalid"] = 'Premium toegang staat <b>uitgeschakeld</n>. Activeringssleutel is alleen voor gebruik op <b>{$a}</b>';
|
|
||||||
$string["premium:expired"] = 'Premium toegang is <b class="text-danger">verlopen</b> op <b>{$a->expires}</b><br>Was uitgegeven aan <b>{$a->name}</b> {$a->sitestatus}';
|
|
||||||
$string["settingspage_premium"] = 'Premium registratie';
|
|
||||||
$string["setting_premium_heading"] = 'Premium features';
|
|
||||||
$string["settingdesc_premium_heading"] = 'Voor premium toegang is een activeringssleutel vereist.
|
|
||||||
<br>Premium toegang bevat onder andere:
|
|
||||||
<ul>
|
|
||||||
<li>Overzichtsrapport van alle resultaten van studenten in een studieplan.</li>
|
|
||||||
<li>Leerlijnen die student kan ontsluiten.</li>
|
|
||||||
<li>Coach rol, waarbij een coach gekoppeld kan worden aan een studieplan, de voortgang van studenten hierin kan volgen en de inhoud hiervan beperkt kan aanpassen.</li>
|
|
||||||
</ul>';
|
|
||||||
$string["setting_premium_status"] = 'Premium status';
|
|
||||||
$string["setting_premium_key"] = 'Activatiesleutel';
|
|
||||||
$string["settingdesc_premium_key"] = 'Plak de activatiesleutel in het tekstvak hierboven.<br> <b>Let op!</b> De regels <i>----- BEGIN ACTIVATION KEY -----</i> en <i>----- END ACTIVATION KEY -----</i> zijn onderdeel van de sleutel.';
|
|
||||||
$string["setting_premium_debug"] = 'Debug info voor premium key';
|
|
||||||
|
|
||||||
$string["premiumfeature:morestudyplans"] = 'Meer dan 5 studieplannen in één categorie aanmaken kan alleen met premium toegang.';
|
|
||||||
$string["premiumfeature:morecategories"] = 'In meer dan 20 categoriën een studieplan aanmaken kan alleen met premium toegang.';
|
|
||||||
$string["premiumfeature:warning"] = 'De functies in deze pagina kun je alleen gebruiken met premium toegang.';
|
|
||||||
$string["error:coachdisabled"] = "De coach functie is uitgeschakeld";
|
$string["error:coachdisabled"] = "De coach functie is uitgeschakeld";
|
||||||
$string["overall"] = 'Cursus voltooid';
|
$string["overall"] = 'Cursus voltooid';
|
||||||
$string["studyplan_report"] = 'Studieplan resultatenoverzicht';
|
$string["studyplan_report"] = 'Studieplan resultatenoverzicht';
|
||||||
|
|
5
lib.php
5
lib.php
|
@ -25,7 +25,6 @@
|
||||||
require_once($CFG->dirroot.'/course/modlib.php');
|
require_once($CFG->dirroot.'/course/modlib.php');
|
||||||
|
|
||||||
use local_treestudyplan\local\helpers\webservicehelper;
|
use local_treestudyplan\local\helpers\webservicehelper;
|
||||||
use local_treestudyplan\premium;
|
|
||||||
use local_treestudyplan\studyplan;
|
use local_treestudyplan\studyplan;
|
||||||
use local_treestudyplan\studyplanpage;
|
use local_treestudyplan\studyplanpage;
|
||||||
|
|
||||||
|
@ -56,7 +55,7 @@ function local_treestudyplan_autofill_customusermenuitems() {
|
||||||
"/local/treestudyplan/view-plan.php" => ["included" => false, "strkey" => "link_viewplan"],
|
"/local/treestudyplan/view-plan.php" => ["included" => false, "strkey" => "link_viewplan"],
|
||||||
"/local/treestudyplan/edit-plan.php" => ["included" => false, "strkey" => "link_editplan"],
|
"/local/treestudyplan/edit-plan.php" => ["included" => false, "strkey" => "link_editplan"],
|
||||||
];
|
];
|
||||||
if ((premium::enabled() && \get_config("local_treestudyplan", "enablecoach"))) {
|
if (\get_config("local_treestudyplan", "enablecoach")) {
|
||||||
// Also include the coach role if enabled.
|
// Also include the coach role if enabled.
|
||||||
$navitems["/local/treestudyplan/coach.php"] = ["included" => false, "strkey" => "link_coach"];
|
$navitems["/local/treestudyplan/coach.php"] = ["included" => false, "strkey" => "link_coach"];
|
||||||
}
|
}
|
||||||
|
@ -203,7 +202,7 @@ function local_treestudyplan_extend_navigation(global_navigation $navigation) {
|
||||||
INNER JOIN {local_treestudyplan} t ON c.studyplan_id = t.id
|
INNER JOIN {local_treestudyplan} t ON c.studyplan_id = t.id
|
||||||
WHERE c.user_id = :user_id";
|
WHERE c.user_id = :user_id";
|
||||||
|
|
||||||
if ((premium::enabled() && \get_config("local_treestudyplan", "enablecoach")) &&
|
if (\get_config("local_treestudyplan", "enablecoach") &&
|
||||||
(has_capability('local/treestudyplan:coach', context_system::instance())
|
(has_capability('local/treestudyplan:coach', context_system::instance())
|
||||||
|| webservicehelper::has_capability_in_any_category('local/treestudyplan:coach')
|
|| webservicehelper::has_capability_in_any_category('local/treestudyplan:coach')
|
||||||
) && $DB->count_records_sql($coachsql, ["user_id" => $USER->id]) > 0
|
) && $DB->count_records_sql($coachsql, ["user_id" => $USER->id]) > 0
|
||||||
|
|
|
@ -25,7 +25,6 @@ require_once("../../config.php");
|
||||||
|
|
||||||
use local_treestudyplan\contextinfo;
|
use local_treestudyplan\contextinfo;
|
||||||
use local_treestudyplan\studyplanpage;
|
use local_treestudyplan\studyplanpage;
|
||||||
use local_treestudyplan\premium;
|
|
||||||
|
|
||||||
require_once($CFG->libdir.'/weblib.php');
|
require_once($CFG->libdir.'/weblib.php');
|
||||||
|
|
||||||
|
@ -48,10 +47,6 @@ $PAGE->set_pagelayout('report');
|
||||||
$PAGE->set_title(get_string('studyplan_report', 'local_treestudyplan'));
|
$PAGE->set_title(get_string('studyplan_report', 'local_treestudyplan'));
|
||||||
$PAGE->set_heading(get_string('studyplan_report', 'local_treestudyplan'));
|
$PAGE->set_heading(get_string('studyplan_report', 'local_treestudyplan'));
|
||||||
|
|
||||||
if (!premium::enabled()) {
|
|
||||||
throw new \moodle_exception("error:nopremiumaccess", "local_treestudyplan", "", premium::statusdescription());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!has_capability('local/treestudyplan:viewuserreports', $context)) {
|
if (!has_capability('local/treestudyplan:viewuserreports', $context)) {
|
||||||
throw new \moodle_exception("error:nostudyplanviewaccess", "local_treestudyplan", "", $contextname);
|
throw new \moodle_exception("error:nostudyplanviewaccess", "local_treestudyplan", "", $contextname);
|
||||||
}
|
}
|
||||||
|
|
53
settings.php
53
settings.php
|
@ -25,7 +25,6 @@
|
||||||
defined('MOODLE_INTERNAL') || die();
|
defined('MOODLE_INTERNAL') || die();
|
||||||
|
|
||||||
use local_treestudyplan\aggregator;
|
use local_treestudyplan\aggregator;
|
||||||
use local_treestudyplan\premium;
|
|
||||||
|
|
||||||
if ($hassiteconfig) {
|
if ($hassiteconfig) {
|
||||||
|
|
||||||
|
@ -158,13 +157,11 @@ if ($hassiteconfig) {
|
||||||
false,
|
false,
|
||||||
));
|
));
|
||||||
|
|
||||||
if (premium::enabled()) {
|
$page->add(new admin_setting_configcheckbox('local_treestudyplan/enablecoach',
|
||||||
$page->add(new admin_setting_configcheckbox('local_treestudyplan/enablecoach',
|
get_string('setting_enablecoach', 'local_treestudyplan'),
|
||||||
get_string('setting_enablecoach', 'local_treestudyplan'),
|
get_string('settingdesc_enablecoach', 'local_treestudyplan'),
|
||||||
get_string('settingdesc_enablecoach', 'local_treestudyplan'),
|
false,
|
||||||
false,
|
));
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
$page->add(new admin_setting_configselect('local_treestudyplan/display_field',
|
$page->add(new admin_setting_configselect('local_treestudyplan/display_field',
|
||||||
get_string('setting_display_field', 'local_treestudyplan'),
|
get_string('setting_display_field', 'local_treestudyplan'),
|
||||||
|
@ -382,44 +379,4 @@ if ($hassiteconfig) {
|
||||||
'local_treestudyplan_doc',
|
'local_treestudyplan_doc',
|
||||||
get_string('cfg_help', 'local_treestudyplan', null, true),
|
get_string('cfg_help', 'local_treestudyplan', null, true),
|
||||||
$CFG->wwwroot . '/local/treestudyplan/doc.php/index.htm'));
|
$CFG->wwwroot . '/local/treestudyplan/doc.php/index.htm'));
|
||||||
|
|
||||||
/**************************************
|
|
||||||
*
|
|
||||||
* Settings page: Premium registration
|
|
||||||
*
|
|
||||||
*************************************/
|
|
||||||
if (\local_treestudyplan\premium::supported() || $CFG->debugdeveloper) {
|
|
||||||
$pagepremium = new admin_settingpage('local_treestudyplan_settings_premium',
|
|
||||||
get_string('settingspage_premium', 'local_treestudyplan', null, true));
|
|
||||||
|
|
||||||
// Description heading.
|
|
||||||
$pagepremium->add(new admin_setting_heading('local_treestudyplan/premium_heading',
|
|
||||||
get_string('setting_premium_heading', 'local_treestudyplan'),
|
|
||||||
get_string('settingdesc_premium_heading', 'local_treestudyplan')
|
|
||||||
));
|
|
||||||
|
|
||||||
// Description heading.
|
|
||||||
$pagepremium->add(new admin_setting_description('local_treestudyplan/premium_status',
|
|
||||||
get_string('setting_premium_status', 'local_treestudyplan'),
|
|
||||||
premium::statusdescription() . "<br> <br>" // Add empty row at end.
|
|
||||||
));
|
|
||||||
|
|
||||||
$pagepremium->add(new admin_setting_configtextarea('local_treestudyplan/premium_key',
|
|
||||||
get_string('setting_premium_key', 'local_treestudyplan'),
|
|
||||||
get_string('settingdesc_premium_key', 'local_treestudyplan'),
|
|
||||||
"",
|
|
||||||
PARAM_RAW
|
|
||||||
));
|
|
||||||
|
|
||||||
if ($CFG->debugdeveloper) {
|
|
||||||
// Show decrypted key data.
|
|
||||||
$pagepremium->add(new admin_setting_description('local_treestudyplan/premium_debug',
|
|
||||||
get_string('setting_premium_debug', 'local_treestudyplan'),
|
|
||||||
premium::debuginfo() . "<br> <br>" // Add empty row at end.
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add settings page2 to the admin settings category.
|
|
||||||
$ADMIN->add('local_treestudyplan', $pagepremium);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user