diff --git a/classes/completion/completion_utils.php b/classes/completion/completion_utils.php index 8d29b71..cfb2fe1 100644 --- a/classes/completion/completion_utils.php +++ b/classes/completion/completion_utils.php @@ -124,7 +124,7 @@ public static function get_completion_challenges_array($mooduellinstance): array // Date until the challenge needs to be done. $challenge->targetdate = $mooduellinstance->cm->completionexpected ?? null; - // TODO: Calculate a user's rank within a challenge. - Will be done in a future release. + // Calculate a user's rank within a challenge. - Will be done in a future release. $challenge->challengerank = null; // Add an array of objects containing localized language strings needed by the app. diff --git a/classes/external.php b/classes/external.php index c22a016..1d11d80 100644 --- a/classes/external.php +++ b/classes/external.php @@ -27,6 +27,7 @@ use mod_mooduell\manage_tokens; use mod_mooduell\mooduell; use mod_mooduell\completion\completion_utils; +use mod_mooduell\utils\wb_payment; defined('MOODLE_INTERNAL') || die(); @@ -298,7 +299,7 @@ public static function get_quizzes_with_caps_parameters() { public static function get_mooduell_support() { global $DB; $url = get_config('mooduell', 'supporturl'); - $pay = get_config('mooduell', 'unlockplatform'); + $pay = wb_payment::pro_version_is_activated(); $badges = get_config('mooduell', 'disablebadges'); $themeimg = get_config('mod_mooduell', 'companylogo'); $themeimgalt = get_config('mod_mooduell', 'companylogoalternative'); @@ -375,11 +376,11 @@ public static function get_mooduell_purchases_returns() { 'purchases' => new external_multiple_structure(new external_single_structure( [ 'id' => new external_value(PARAM_INT, 'id'), - 'productid' => new external_value(PARAM_INT, 'productid'), + 'productid' => new external_value(PARAM_TEXT, 'productid'), 'purchasetoken' => new external_value(PARAM_TEXT, 'purchasetoken'), 'receipt' => new external_value(PARAM_TEXT, 'receipt', VALUE_OPTIONAL, ''), 'signature' => new external_value(PARAM_TEXT, 'signature', VALUE_OPTIONAL, ''), - 'orderid' => new external_value(PARAM_INT, 'orderid', VALUE_OPTIONAL, ''), + 'orderid' => new external_value(PARAM_TEXT, 'orderid', VALUE_OPTIONAL, ''), 'free' => new external_value(PARAM_INT, 'free', VALUE_OPTIONAL, 0), 'userid' => new external_value(PARAM_INT, 'userid'), 'mooduellid' => new external_value(PARAM_INT, 'mooduellid', VALUE_OPTIONAL, 0), diff --git a/classes/game_finished.php b/classes/game_finished.php index 0a190a8..d392fc4 100644 --- a/classes/game_finished.php +++ b/classes/game_finished.php @@ -69,11 +69,11 @@ public static function update_highscores_table(int $cmid) { 'gamesplayed' => $entry->played, 'gameswon' => $entry->won, 'gameslost' => $entry->lost, - 'gamesstarted' => 0, // TODO: this will be added later. - 'gamesfinished' => 0, // TODO: this will be added later. + 'gamesstarted' => 0, + 'gamesfinished' => 0, 'score' => $entry->score, 'qcorrect' => $entry->correct, - 'qplayed' => $entry->qplayed, + 'qplayed' => $entry->qplayed, 'qcpercentage' => $entry->correctpercentage, 'timecreated' => time(), 'timemodified' => time(), @@ -87,8 +87,8 @@ public static function update_highscores_table(int $cmid) { $entry = (object) $entry; // Let's have a look if the entry already exists in the DB. - $sql = 'select * from {mooduell_highscores} where mooduellid = '. - $entry->mooduellid.' and userid = '.$entry->userid; + $sql = 'select * from {mooduell_highscores} where mooduellid = ' . + $entry->mooduellid . ' and userid = ' . $entry->userid; $data = $DB->get_record_sql($sql); // If the entry could be found in the database. diff --git a/classes/mooduell.php b/classes/mooduell.php index fca0a0d..e0d8731 100644 --- a/classes/mooduell.php +++ b/classes/mooduell.php @@ -326,7 +326,6 @@ public function return_list_of_all_questions_in_quiz() { $cachetime = get_config('mooduell', 'cachetime'); if ($cachetime > 0) { - // Next we take a look in the cache. $cache = cache::make('mod_mooduell', 'questionscache'); @@ -336,7 +335,6 @@ public function return_list_of_all_questions_in_quiz() { $this->questions = $questions; return $questions; } - } $questions = []; @@ -347,7 +345,7 @@ public function return_list_of_all_questions_in_quiz() { $newquestion = new question_control($entry, $listofanswers); // Add empty combined feedback (for ddwtos questions) to prevent webservice errors. - $combinedfeedback = new stdClass; + $combinedfeedback = new stdClass(); $combinedfeedback->correctfeedback = null; $combinedfeedback->partiallycorrectfeedback = null; $combinedfeedback->incorrectfeedback = null; @@ -418,6 +416,117 @@ private function return_list_of_questions() { } return $listofquestions; } + + /** + * Updates the platform subscription. + * + * + */ + public static function update_all_subscriptions() { + + global $DB, $CFG; + + // Get Subscriptions. + list($insqlplatform, $inparams1) = $DB->get_in_or_equal($CFG->wwwroot); + list($insqlproduct, $inparams2) = $DB->get_in_or_equal('unlockplatformsubscription'); + + $params = array_merge($inparams1, $inparams2); + + $sql = "SELECT * FROM {mooduell_purchase} + WHERE platformid $insqlplatform + AND productid $insqlproduct"; + + $allpurchases = $DB->get_records_sql($sql, $params); + foreach ($allpurchases as $returnitem) { + $result = self::verify_purchase($returnitem); + + // Logic to determine if subscription is okay or not + // Request was ok. + if ($result->ok === true) { + $allproductsinreceipt = $result->data->collection; + foreach ($allproductsinreceipt as $singleproduct) { + if ($singleproduct->id === 'unlockplatformsubscription') { + // Subscription item. + if ($singleproduct->isExpired === false) { + // Extend validity for a day. + $udpatedentry = $returnitem; + $udpatedentry->validuntil = time() + (60 * 60 * 24); + $DB->update_record('mooduell_purchase', $udpatedentry); + return; + } else if ($singleproduct->isExpired === true) { + // Delete Cancel etc. + $udpatedentry = $returnitem; + $udpatedentry->productid = 'notvalid'; + $DB->update_record('mooduell_purchase', $udpatedentry); + } + } + } + } else { + // Failed verification. + // Android expired. + if ($result->code === 6778003) { + $udpatedentry = $returnitem; + $udpatedentry->productid = 'notvalid'; + $DB->update_record('mooduell_purchase', $udpatedentry); + } + return; + } + } + } + + /** + * Verifies a single purchase. + * + * @param mixed $purchase + * @return object + */ + public static function verify_purchase($purchase) { + // If sub has been purchases on ios. + if ($purchase->store === 'ios') { + $payload = [ + 'id' => 'at.wunderbyte.mooduellapp', + 'type' => 'application', + 'transaction' => [ + 'id' => 'at.wunderbyte.mooduellapp', + 'type' => 'ios-appstore', + 'appStoreReceipt' => $purchase->purchasetoken, + ], + ]; + } else { + $payload = [ + 'id' => $purchase->productid, + 'type' => $purchase->productid === 'unlockplatformsubscription' ? 'paid subscription' : 'consumeable', + 'transaction' => [ + 'type' => 'android-playstore', + 'id' => $purchase->orderid, + 'purchaseToken' => $purchase->purchasetoken, + 'signature' => $purchase->signature, + 'receipt' => $purchase->receipt, + ], + ]; + } + + $url = "https://validator.iaptic.com/v1/validate"; + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload)); + curl_setopt($ch, CURLOPT_HTTPHEADER, + [ + "Authorization: Basic " . base64_encode('at.wunderbyte.mooduellapp:4575a924-9af6-4a88-95d1-9c80aa1444b1'), + "Content-Type: application/json", + ]); + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + $responsedata = curl_exec($ch); + if (curl_errno($ch)) { + return curl_error($ch); + } + curl_close($ch); + return json_decode($responsedata); + } + + + /** * Returns List of relevant Purchases * @@ -442,17 +551,12 @@ public static function get_purchases($courses, $quizzes) { $returnitems = ['purchases' => []]; return $returnitems; } - list($insqlcourses, $inparams) = $DB->get_in_or_equal($courseids); - list($insqlquizzes, $inparams2) = $DB->get_in_or_equal($quizids); - list($insqlplatform, $inparams3) = $DB->get_in_or_equal($CFG->wwwroot); - - $params = array_merge($inparams, $inparams2, $inparams3); - + $leeway = time() - (60 * 60 * 24 * 4); + list($insqlplatform, $inparams1) = $DB->get_in_or_equal($CFG->wwwroot); + $params = $inparams1; + $params[] = $leeway; $sql = "SELECT * FROM {mooduell_purchase} - WHERE userid = {$userid} - OR courseid $insqlcourses - OR mooduellid $insqlquizzes AND ispublic = 1 - OR platformid $insqlplatform"; + WHERE platformid $insqlplatform AND validuntil > ? AND NOT productid = 'notvalid'"; $returnitems = ['purchases' => $DB->get_records_sql($sql, $params)]; return $returnitems; @@ -471,8 +575,9 @@ public static function purchase_item($purchase) { case 'unlockplatformsubscription': if ($purchase['store'] == 'ios') { // Ios. + $purchasetokenformatted = str_replace('~', '+', $purchase['purchasetoken']); $existingsub = $DB->get_records('mooduell_purchase', [ - 'productid' => $purchase['productid'], + 'purchasetoken' => $purchasetokenformatted, 'store' => 'ios', ]); } else { @@ -512,6 +617,8 @@ public static function purchase_item($purchase) { } $newdata = $purchase; $newdata['timecreated'] = time(); + // We check subscription every day. + $newdata['validuntil'] = time() + (60 * 60 * 24); $manipulatedstring = $newdata['purchasetoken']; if ($newdata['signature']) { $manipulatedsignature = $newdata['signature']; diff --git a/classes/output/list_action.php b/classes/output/list_action.php index 33fed74..bac3fa0 100644 --- a/classes/output/list_action.php +++ b/classes/output/list_action.php @@ -84,7 +84,7 @@ public function export_for_template(renderer_base $output) { * @param int $counter * @return array */ - private function render_questions_table_for_game(stdClass $game, mooduell $mooduell, int $counter = null):array { + private function render_questions_table_for_game(stdClass $game, mooduell $mooduell, int $counter = null): array { global $PAGE; $tablename = bin2hex(random_bytes(12)); diff --git a/classes/output/overview_student.php b/classes/output/overview_student.php index 8e0b4cc..3f91349 100644 --- a/classes/output/overview_student.php +++ b/classes/output/overview_student.php @@ -97,7 +97,7 @@ public function export_for_template(renderer_base $output) { * @param mooduell $mooduell * @return string */ - private function render_open_games_table(mooduell $mooduell):string { + private function render_open_games_table(mooduell $mooduell): string { return $this->render_games_table($mooduell, 'opengames'); } @@ -107,7 +107,7 @@ private function render_open_games_table(mooduell $mooduell):string { * @param mooduell $mooduell * @return string */ - private function render_finished_games_table(mooduell $mooduell):string { + private function render_finished_games_table(mooduell $mooduell): string { return $this->render_games_table($mooduell, 'finishedgames'); } @@ -118,7 +118,7 @@ private function render_finished_games_table(mooduell $mooduell):string { * @param string $action * @return string */ - private function render_games_table(mooduell $mooduell, string $action):string { + private function render_games_table(mooduell $mooduell, string $action): string { $gamestable = new table_games($action, $mooduell->cm->id); $finishedgames = $action == 'finishedgames' ? true : false; @@ -150,7 +150,7 @@ private function render_games_table(mooduell $mooduell, string $action):string { * @param mooduell $mooduell * @return string */ - private function render_highscores_table(mooduell $mooduell):string { + private function render_highscores_table(mooduell $mooduell): string { $highscorestable = new table_highscores('highscores', $mooduell->cm->id); // Sort the table by descending score by default. diff --git a/classes/output/overview_teacher.php b/classes/output/overview_teacher.php index 251e853..fb70420 100644 --- a/classes/output/overview_teacher.php +++ b/classes/output/overview_teacher.php @@ -91,7 +91,7 @@ public function export_for_template(renderer_base $output) { * @param mooduell $mooduell * @return string */ - private function render_open_games_table(mooduell $mooduell):string { + private function render_open_games_table(mooduell $mooduell): string { return $this->render_games_table($mooduell, 'opengames'); } @@ -101,7 +101,7 @@ private function render_open_games_table(mooduell $mooduell):string { * @param mooduell $mooduell * @return string */ - private function render_finished_games_table(mooduell $mooduell):string { + private function render_finished_games_table(mooduell $mooduell): string { return $this->render_games_table($mooduell, 'finishedgames'); } @@ -112,7 +112,7 @@ private function render_finished_games_table(mooduell $mooduell):string { * @param string $action * @return string */ - private function render_games_table(mooduell $mooduell, $action):string { + private function render_games_table(mooduell $mooduell, $action): string { $tablename = bin2hex(random_bytes(12)); @@ -152,7 +152,7 @@ private function render_games_table(mooduell $mooduell, $action):string { * @param mooduell $mooduell * @return string */ - private function render_highscores_table(mooduell $mooduell):string { + private function render_highscores_table(mooduell $mooduell): string { $tablename = bin2hex(random_bytes(12)); $highscorestable = new table_highscores($tablename, $mooduell->cm->id); @@ -191,7 +191,7 @@ private function render_highscores_table(mooduell $mooduell):string { * @param mooduell $mooduell * @return string */ - private function render_questions_table(mooduell $mooduell):string { + private function render_questions_table(mooduell $mooduell): string { $tablename = bin2hex(random_bytes(12)); diff --git a/classes/privacy/provider.php b/classes/privacy/provider.php index 40bbe8f..057401a 100644 --- a/classes/privacy/provider.php +++ b/classes/privacy/provider.php @@ -52,7 +52,7 @@ class provider implements * @param collection $collection a reference to the collection to use to store the metadata. * @return collection the updated collection of metadata items. */ - public static function get_metadata(collection $collection) : collection { + public static function get_metadata(collection $collection): collection { // Stores the mooduell game progress. $collection->add_database_table( 'mooduell_games', @@ -133,7 +133,7 @@ public static function get_metadata(collection $collection) : collection { * @param int $userid the userid. * @return contextlist the list of contexts containing user info for the user. */ - public static function get_contexts_for_userid(int $userid) : contextlist { + public static function get_contexts_for_userid(int $userid): contextlist { $contextlist = new contextlist(); diff --git a/classes/question_control.php b/classes/question_control.php index 435a196..42bf41f 100644 --- a/classes/question_control.php +++ b/classes/question_control.php @@ -107,7 +107,7 @@ public function __construct($data = null, $listofanswers = null) { $this->questionid = $data->id; $this->name = $data->name; if ($data->qtype == 'ddwtos') { - $this->questiontext = trim(strip_tags(html_entity_decode($data->questiontext))); + $this->questiontext = trim(strip_tags(html_entity_decode($data->questiontext, ENT_QUOTES))); } else { $this->questiontext = $data->questiontext; } @@ -143,17 +143,17 @@ public function __construct($data = null, $listofanswers = null) { // Remove HTML and decode HTML entities like " ". if (!empty($combinedfeedback->correctfeedback)) { $combinedfeedback->correctfeedback = - trim(strip_tags(html_entity_decode($combinedfeedback->correctfeedback))); + trim(strip_tags(html_entity_decode($combinedfeedback->correctfeedback, ENT_QUOTES))); } if (!empty($combinedfeedback->partiallycorrectfeedback)) { $combinedfeedback->partiallycorrectfeedback = - trim(strip_tags(html_entity_decode($combinedfeedback->partiallycorrectfeedback))); + trim(strip_tags(html_entity_decode($combinedfeedback->partiallycorrectfeedback, ENT_QUOTES))); } if (!empty($combinedfeedback->incorrectfeedback)) { $combinedfeedback->incorrectfeedback = - trim(strip_tags(html_entity_decode($combinedfeedback->incorrectfeedback))); + trim(strip_tags(html_entity_decode($combinedfeedback->incorrectfeedback, ENT_QUOTES))); } } } else { diff --git a/classes/task/update_subscription_task.php b/classes/task/update_subscription_task.php new file mode 100644 index 0000000..ae2fd64 --- /dev/null +++ b/classes/task/update_subscription_task.php @@ -0,0 +1,58 @@ +. + +/** + * update subscription task for mooduell + * + * @package mod_mooduell + * @copyright 2024 Christian Badusch + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace mod_mooduell\task; +use mod_mooduell\mooduell; + +/** + * update_subscription_task + */ +class update_subscription_task extends \core\task\scheduled_task { + /** + * Returns the taskname. + * + * @return string + */ + public function get_name() { + return get_string('updatesubscription', 'mod_mooduell'); + } + + /** + * Executes the task and checks the subscription. + * + * @return void + */ + public function execute() { + global $DB; + + $mooduell = $DB->get_record('modules', ['name' => 'mooduell']); + if ($mooduell) { + $mooduellid = $DB->get_record('course_modules', ['module' => $mooduell->id]); + if ($mooduellid) { + $mooduellinstance = new mooduell($mooduellid->id); + $mooduellinstance->update_all_subscriptions(); + } + } + } +} diff --git a/classes/utils/wb_payment.php b/classes/utils/wb_payment.php new file mode 100644 index 0000000..85a5080 --- /dev/null +++ b/classes/utils/wb_payment.php @@ -0,0 +1,114 @@ +. + +/** + * Wunderbyte Payment Methods. + * + * Contains methods for license verification and more. + * + * @package mod_mooduell + * @copyright 2023 Wunderbyte GmbH + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace mod_mooduell\utils; + +use stdClass; + +/** + * Class to handle Wunderbyte Payment Methods. + * + * Contains methods for license verification and more. + * + * @package mod_mooduell + * @copyright 2023 Wunderbyte GmbH + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class wb_payment { + + /** + * mod_mooduell_PUBLIC_KEY + * + * @var mixed + */ + const MOD_MOODUELL_PUBLIC_KEY = "-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAu8vRBnPDug2pKoGY9wQS +KNTK1SzrPuU0KC8xm22GPQZQM1XkPpvNwBp8CmXUN29r/qiPxapDNVmIH5Ectvb+ +NA7EsuVSS8xV6HfjV0tNZKIfFA4b1JD7t6l4gGDLuoppvKQV9n1JP/uZhQlFZ8Dg +7qMXGsEWRcmRGSBZxIVA+EiN35ALsR78MYWEmuAtKKtskqD4cwnAQzZhU1tZRFHz +/uSfhS2tFXQ7vjvCPIozzo9Mgy4Vr4Qoc9ohg0AfK/D3IoA/mpQFpVC+hyS+rQ0d +uqjiVvh1b0cI3ZBEwWeaNKR4Z3dVb3RHOnICCJPyxxIfSDKWDmQDMCMLa5UjvSvM +pwIDAQAB +-----END PUBLIC KEY-----"; + + /** + * Decrypt a PRO license key to get the expiration date of the license + * + * @param string $encryptedlicensekey an object containing licensekey and signature + * @return string the expiration date of the license key formatted as Y-m-d + */ + public static function decryptlicensekey(string $encryptedlicensekey): string { + global $CFG; + // Step 1: Do base64 decoding. + $encryptedlicensekey = base64_decode($encryptedlicensekey); + + // Step 2: Decrypt using public key. + openssl_public_decrypt($encryptedlicensekey, $licensekey, self::MOD_MOODUELL_PUBLIC_KEY); + + // Step 3: Do another base64 decode and decrypt using wwwroot. + $c = base64_decode($licensekey); + $ivlen = openssl_cipher_iv_length($cipher = "AES-128-CBC"); + $iv = substr($c, 0, $ivlen); + + // Bugfix when passing wrong license keys that are too short. + if (strlen($iv) != 16) { + return false; + } + + $sha2len = 32; + $ciphertextraw = substr($c, $ivlen + $sha2len); + $decryptedcontent = openssl_decrypt($ciphertextraw, $cipher, $CFG->wwwroot, $options = OPENSSL_RAW_DATA, $iv); + + return $decryptedcontent; + } + + /** + * Helper function to determine if the user has set a valid license key which has not yet expired. + * + * @return bool true if the license key is valid at current date + * @throws \dml_exception + */ + public static function pro_version_is_activated() { + // Get license key which has been set in settings.php. + $pluginconfig = get_config('mooduell'); + if (!empty($pluginconfig->licensekey)) { + $licensekeyfromsettings = $pluginconfig->licensekey; + // DEBUG: echo "License key from plugin config: $licensekey_from_settings
"; END. + + $expirationtimestamp = strtotime(self::decryptlicensekey($licensekeyfromsettings)); + // Return true if the current timestamp has not yet reached the expiration date. + if (time() < $expirationtimestamp) { + return true; + } + } + // Overriding - always use PRO for testing / debugging. + // Check if Behat OR PhpUnit tests are running. + if ((defined('BEHAT_SITE_RUNNING') && BEHAT_SITE_RUNNING) || (defined('PHPUNIT_TEST') && PHPUNIT_TEST)) { + return true; + } + return false; + } +} diff --git a/db/install.xml b/db/install.xml index 9afef82..cd73c19 100755 --- a/db/install.xml +++ b/db/install.xml @@ -160,6 +160,7 @@ + diff --git a/db/tasks.php b/db/tasks.php new file mode 100644 index 0000000..0a0a25e --- /dev/null +++ b/db/tasks.php @@ -0,0 +1,36 @@ +. + +/** + * Mooduell module scheduled tasks definition + * + * @package mod_mooduell + * @copyright 2024 Christian Badusch + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +defined('MOODLE_INTERNAL') || die(); + +$tasks = [ + ['classname' => 'mod_mooduell\task\update_subscription_task', + 'blocking' => 0, + 'minute' => '0', + 'hour' => '0', + 'day' => '*', + 'dayofweek' => '*', + 'month' => '*', + ], +]; diff --git a/db/upgrade.php b/db/upgrade.php index da983ba..68771e5 100755 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -275,5 +275,20 @@ function xmldb_mooduell_upgrade($oldversion) { upgrade_mod_savepoint(true, 2022033101, 'mooduell'); } + if ($oldversion < 2024030600) { + + // Define field validuntil to be added to mooduell_purchase. + $table = new xmldb_table('mooduell_purchase'); + $field = new xmldb_field('validuntil', XMLDB_TYPE_INTEGER, '10', null, null, null, null, 'ispublic'); + + // Conditionally launch add field validuntil. + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + + // Mooduell savepoint reached. + upgrade_mod_savepoint(true, 2024030600, 'mooduell'); + } + return true; } diff --git a/lang/de/mooduell.php b/lang/de/mooduell.php index 04102fe..3889b86 100755 --- a/lang/de/mooduell.php +++ b/lang/de/mooduell.php @@ -25,6 +25,15 @@ defined('MOODLE_INTERNAL') || die(); +$string['licensekeycfg'] = 'PRO-Version aktivieren'; +$string['licensekeycfgdesc'] = 'Mit einer PRO-Lizenz können Sie so viele Buchungsvorlagen erstellen wie Sie wollen und PRO-Features wie z.B. globale Mailvorlagen, Info-Texte für Wartelistenplätze und Benachrichtigungen für Trainer:innen nutzen.'; +$string['licensekey'] = 'PRO-Lizenz-Schlüssel'; +$string['licensekeydesc'] = 'Laden Sie hier einen gültigen Schlüssel hoch, um die PRO-Version zu aktivieren.'; +$string['license_activated'] = 'PRO-Version wurde erfolgreich aktiviert.
(Läuft ab am: '; +$string['license_invalid'] = 'Ungültiger Lizenz-Schlüssel.'; + +$string['updatesubscription'] = "Subscription status prüfen"; + $string['disablesbadges'] = 'Disble Badges'; $string['theme'] = 'Theme'; $string['themedesc'] = 'Theme für die App im JSON Format'; diff --git a/lang/en/mooduell.php b/lang/en/mooduell.php index dd44d89..7097316 100755 --- a/lang/en/mooduell.php +++ b/lang/en/mooduell.php @@ -25,6 +25,15 @@ defined('MOODLE_INTERNAL') || die(); +$string['licensekeycfg'] = 'Activate PRO version'; +$string['licensekeycfgdesc'] = 'With a PRO license you can create as many booking templates as you like and use PRO features such as global mail templates, waiting list info texts or teacher notifications.'; +$string['licensekey'] = 'PRO license key'; +$string['licensekeydesc'] = 'Upload a valid license key to activate the PRO version.'; +$string['license_activated'] = 'PRO version activated successfully.
(Expires: '; +$string['license_invalid'] = 'Invalid license key'; + +$string['updatesubscription'] = "Check subscription status"; + $string['disablesbadges'] = 'Auszeichnungen deaktivieren'; $string['theme'] = 'Theme'; $string['themedesc'] = 'Theme in JSON format'; diff --git a/settings.php b/settings.php index 00fd47d..89db7ee 100755 --- a/settings.php +++ b/settings.php @@ -24,17 +24,52 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +use mod_mooduell\utils\wb_payment; + defined('MOODLE_INTERNAL') || die(); global $ADMIN; if ($ADMIN->fulltree) { + // Has PRO version been activated? + $proversion = wb_payment::pro_version_is_activated(); + + $settings->add( + new admin_setting_heading('licensekeycfgheading', + get_string('licensekeycfg', 'mod_mooduell'), + get_string('licensekeycfgdesc', 'mod_mooduell'))); + // Dynamically change the license info text. + $licensekeydesc = get_string('licensekeydesc', 'mod_mooduell'); + + // Get license key which has been set in text field. + $pluginconfig = get_config('mooduell'); + if (!empty($pluginconfig->licensekey)) { + $licensekey = $pluginconfig->licensekey; + + $expirationdate = wb_payment::decryptlicensekey($licensekey); + if (!empty($expirationdate)) { + $licensekeydesc = "

" + .get_string('license_activated', 'mod_mooduell') + .$expirationdate + .")

"; + } else { + $licensekeydesc = "

" + .get_string('license_invalid', 'mod_mooduell') + ."

"; + } + } + + $settings->add( + new admin_setting_configtext('mooduell/licensekey', + get_string('licensekey', 'mod_mooduell'), + $licensekeydesc, '')); + $setting = new admin_setting_configcheckbox( 'mooduell/usefullnames', get_string('usefullnames', 'mod_mooduell'), "", - 0 + 0 ); $setting->set_locked_flag_options(admin_setting_flag::ENABLED, false); $settings->add($setting); @@ -152,13 +187,6 @@ 0 )); - $settings->add(new admin_setting_configcheckbox( - 'mooduell/unlockplatform', - get_string('unlockplatform', 'mod_mooduell'), - "", - 0 - )); - $settings->add(new admin_setting_configcheckbox( 'mooduell/disablebadges', get_string('disablesbadges', 'mod_mooduell'), @@ -181,7 +209,6 @@ 'themepicture', 0 )); - $settings->add(new admin_setting_configstoredfile( 'mod_mooduell/companylogoalternative', get_string('alternativelogo', 'mod_mooduell'), diff --git a/test.php b/test.php new file mode 100644 index 0000000..5e520a5 --- /dev/null +++ b/test.php @@ -0,0 +1,53 @@ +. + +/** + * Testing some functions. + * + * @package mod_mooduell + * @copyright 2024 Wunderbyte GmbH + * @author Chrsitian Badusch + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +require_once('../../config.php'); + +use mod_mooduell\mooduell; + +require_login(); + +$context = \context_system::instance(); +$PAGE->set_context($context); + +$mooduell = $DB->get_record('modules', ['name' => 'mooduell']); +if ($mooduell) { + $mooduellid = $DB->get_record('course_modules', ['module' => $mooduell->id]); + if ($mooduellid) { + $mooduellinstance = new mooduell($mooduellid->id); + $mooduellinstance->update_all_subscriptions(); + } + +} + +$PAGE->set_pagelayout('standard'); +$title = "MooDuell Testpage"; +$PAGE->set_title($title); +$PAGE->set_url('/test.php'); +$PAGE->set_heading($title); + +echo $OUTPUT->header(); + +echo $OUTPUT->footer(); diff --git a/tests/mooduell_external_test.php b/tests/mooduell_external_test.php index 4f65d66..961b6f1 100644 --- a/tests/mooduell_external_test.php +++ b/tests/mooduell_external_test.php @@ -45,7 +45,7 @@ class mooduell_external_test extends advanced_testcase { /** * Tests set up. */ - public function setUp():void { + public function setUp(): void { $this->resetAfterTest(); } @@ -174,7 +174,7 @@ public function test_get_quiz_users() { // Check users. $this->assertIsArray($users); $this->assertEquals(2, count($users)); - // TODO: no built-in methods to compare stdClass instances. + // No built-in methods to compare stdClass instances. $ids = array_map(function($item) { return $item->id; }, $users); diff --git a/version.php b/version.php index ce2fed7..6277593 100755 --- a/version.php +++ b/version.php @@ -26,7 +26,7 @@ $plugin->component = 'mod_mooduell'; $plugin->release = 'v2.1.5'; -$plugin->version = 2024020900; +$plugin->version = 2024030600; $plugin->requires = 2020061500; $plugin->maturity = MATURITY_STABLE; $plugin->dependencies = [