diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml index 68485f3..53c873d 100644 --- a/.github/workflows/moodle-ci.yml +++ b/.github/workflows/moodle-ci.yml @@ -11,7 +11,7 @@ # name: Moodle Plugin CI -on: [ push, pull_request ] +on: [ push, pull_request, workflow_dispatch ] jobs: test: @@ -45,15 +45,19 @@ jobs: - '7.4' # minimum support version by Moodle 4.1 - '8.0' - '8.1' - - '8.3' # max. supported version by Moodle 4.4 (as of writing) - moodle-branch: [ 'MOODLE_401_STABLE', 'MOODLE_404_STABLE' ] # LTS & latest. + - '8.3' # max. supported version by Moodle 4.5 (as of writing) + moodle-branch: [ 'MOODLE_401_STABLE', 'MOODLE_405_STABLE', 'main' ] # LTS & latest. database: [ pgsql ] # We don't use any database specific features, and our test sites run mariadb already. exclude: # Moodle 4.4+ requires PHP 8.1+ - php: '8.0' - moodle-branch: 'MOODLE_404_STABLE' + moodle-branch: 'MOODLE_405_STABLE' + - php: '8.0' + moodle-branch: 'main' + - php: '7.4' + moodle-branch: 'MOODLE_405_STABLE' - php: '7.4' - moodle-branch: 'MOODLE_404_STABLE' + moodle-branch: 'main' # Moodle 4.1 does not support PHP 8.3 - php: '8.3' moodle-branch: 'MOODLE_401_STABLE' diff --git a/classes/admin/kialo_configcheckbox.php b/classes/admin/kialo_configcheckbox.php index 7bf6719..9199a45 100644 --- a/classes/admin/kialo_configcheckbox.php +++ b/classes/admin/kialo_configcheckbox.php @@ -39,6 +39,9 @@ class kialo_configcheckbox extends admin_setting_configcheckbox { */ public function force_readonly(bool $forcereadonly) { $this->forcereadonly = $forcereadonly; + + // If the checkbox is read-only, it should not be saved. It would be reset to its default otherwise when saving. + $this->nosave = $forcereadonly; } /** diff --git a/classes/kialo_config.php b/classes/kialo_config.php index 4d1dbd4..590d664 100644 --- a/classes/kialo_config.php +++ b/classes/kialo_config.php @@ -63,12 +63,27 @@ public static function get_release(): string { * @return array|string */ public function get_tool_url() { + $targeturlfromconfig = get_config('mod_kialo', 'kialourl'); // See settings.php. $targeturlfromenv = getenv('TARGET_KIALO_URL'); - if (!empty($targeturlfromenv)) { - return $targeturlfromenv; + + if (!empty($targeturlfromconfig)) { + $kialourl = $targeturlfromconfig; + + // Is the URL valid? + if (!filter_var($kialourl, FILTER_VALIDATE_URL)) { + throw new \dml_exception("Invalid Kialo URL: $kialourl"); + } + } else if (!empty($targeturlfromenv)) { + $kialourl = $targeturlfromenv; } else { - return "https://www.kialo-edu.com"; + $kialourl = "https://www.kialo-edu.com"; + } + + // Ensure $kialourl is a proper URL and does not have a trailing slash. + if (!preg_match('/^https?:\/\//', $kialourl)) { + $kialourl = "https://" . $kialourl; } + return rtrim($kialourl, '/'); } /** diff --git a/development/.env.example b/development/.env.example index 6617caf..5f73843 100644 --- a/development/.env.example +++ b/development/.env.example @@ -17,3 +17,10 @@ MOODLE_HOST=192.168.X.X:8080 # and use that, since `moodle` is the hostname of the Moodle Docker container, # which is accessible from within the Kialo Docker container. # MOODLE_HOST=moodle:8080 + +# Moodle branch to use. By default we use the latest version (the `main` branch). +# If you want to use a specific other version, use the corresponding branch name. +# For example MOODLE_405_STABLE for Moodle 4.5. See https://github.com/moodle/moodle/branches. +# Note: If you change your Moodle branch, the Docker image needs to be rebuilt, +# by running `docker compose up --build`. +MOODLE_BRANCH=main diff --git a/development/.gitignore b/development/.gitignore index 60675ec..3534072 100644 --- a/development/.gitignore +++ b/development/.gitignore @@ -1,4 +1,5 @@ moodle/ +moodle_mod/ .env ## Bundle diff --git a/development/README.md b/development/README.md index 2071469..e164307 100644 --- a/development/README.md +++ b/development/README.md @@ -56,7 +56,13 @@ This also enables web services for mobile (required for the mobile app) and enab By default there is only one user with the username "user" and password "kialo1234". This is the admin user. The folder `moodle` is mounted locally in the `development` folder. To test changes to the plugin code, -you can use `development/sync.sh` to copy over the code into the `moodle/mod/kialo` folder. +you can use `development/sync.sh` to copy over the code into the `moodle/mod/kialo` folder.A + +### Moodle versions + +The Docker setup is configured to run the latest moodle version (`main` branch) by default. +If you want to run a specific version, like one of the LTS versions, you can change the `MOODLE_VERSION` in the `.env` file. +See `.env.example` for details. ### Using the Moodle Mobile app diff --git a/development/config/config.php b/development/config/config.php deleted file mode 100644 index be1081b..0000000 --- a/development/config/config.php +++ /dev/null @@ -1,84 +0,0 @@ -. - -// Moodle configuration file. -// Will be copied to Moodle when starting the docker compose setup. -// -// phpcs:disable - -unset($CFG); -global $CFG; -$CFG = new stdClass(); - -$CFG->dbtype = 'mariadb'; -$CFG->dblibrary = 'native'; -$CFG->dbhost = 'mariadb'; -$CFG->dbname = 'bitnami_moodle'; -$CFG->dbuser = 'bn_moodle'; -$CFG->dbpass = ''; -$CFG->prefix = 'mdl_'; -$CFG->dboptions = array ( - 'dbpersist' => 0, - 'dbport' => 3306, - 'dbsocket' => '', - 'dbcollation' => 'utf8mb4_unicode_ci', -); - -if (empty($_SERVER['HTTP_HOST'])) { - $_SERVER['HTTP_HOST'] = '127.0.0.1:8080'; -} -if (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') { - $CFG->wwwroot = 'https://' . $_SERVER['HTTP_HOST']; -} else { - $CFG->wwwroot = 'http://' . $_SERVER['HTTP_HOST']; -} -$CFG->dataroot = '/bitnami/moodledata'; -$CFG->admin = 'admin'; - -$CFG->directorypermissions = 02775; - -//========================================================================= -// PHPUNIT SUPPORT -//========================================================================= - $CFG->phpunit_prefix = 'phpu_'; - $CFG->phpunit_dataroot = '/bitnami/moodledata/phpunit'; - $CFG->phpunit_directorypermissions = 02777; // optional - $CFG->phpunit_profilingenabled = true; // optional to profile PHPUnit runs. - -//========================================================================= -// Custom settings for development -//========================================================================= - -// Force a debugging mode regardless the settings in the site administration - @error_reporting(E_ALL | E_STRICT); // NOT FOR PRODUCTION SERVERS! - @ini_set('display_errors', '1'); // NOT FOR PRODUCTION SERVERS! - $CFG->debug = (E_ALL | E_STRICT); // === DEBUG_DEVELOPER - NOT FOR PRODUCTION SERVERS! - $CFG->debugdisplay = 1; // NOT FOR PRODUCTION SERVERS! - -// disable some caching so that we don't constantly have to manually purge caches in the web UI -$CFG->cachetemplates = false; -$CFG->langstringcache = false; - -// This setting is only used during the installation process. So once the Moodle site is installed, it is ignored. -$CFG->setsitepresetduringinstall = 'kialo-admin-preset.xml'; - -// Make sure that the temp directories are not deleted during the backup process. Allows easier testing of the backup process. -$CFG->keeptempdirectoriesonbackup = true; - -require_once(__DIR__ . '/lib/setup.php'); - -// There is no php closing tag in this file, -// it is intentional because it prevents trailing whitespace problems! diff --git a/development/docker-compose.yml b/development/docker-compose.yml index 2eaff94..44edb3d 100644 --- a/development/docker-compose.yml +++ b/development/docker-compose.yml @@ -1,34 +1,44 @@ -# https://hub.docker.com/r/bitnami/moodle -version: '2' +name: mod_kialo services: mariadb: - image: docker.io/bitnami/mariadb:10.6 + image: docker.io/bitnami/mariadb:10.7 ports: - '8833:3306' - '8443:443' environment: # ALLOW_EMPTY_PASSWORD is recommended only for development. - ALLOW_EMPTY_PASSWORD=yes - - MARIADB_USER=bn_moodle - - MARIADB_DATABASE=bitnami_moodle + - MARIADB_USER=moodle + - MARIADB_DATABASE=moodle - MARIADB_CHARACTER_SET=utf8mb4 - MARIADB_COLLATE=utf8mb4_unicode_ci + # liveness probe + healthcheck: + test: ["CMD", "mysqladmin", "status", "-uroot"] + interval: 2s + timeout: 1s + retries: 10 moodle: - image: docker.io/bitnami/moodle:4.4 + build: + dockerfile: Dockerfile + context: moodleimage + args: + # main (latest), MOODLE_405_STABLE etc, see https://github.com/moodle/moodle/branches + MOODLE_BRANCH: ${MOODLE_BRANCH:-main} + # 7.4, 8.0, 8.1, 8.3 etc., see https://moodledev.io/general/development/policies/php + PHP_VERSION: ${PHP_VERSION:-8.1} ports: - - '8080:8080' + - '8080:80' environment: - MOODLE_DATABASE_HOST=mariadb - MOODLE_DATABASE_PORT_NUMBER=3306 - - MOODLE_DATABASE_USER=bn_moodle - - MOODLE_DATABASE_NAME=bitnami_moodle - ALLOW_EMPTY_PASSWORD=yes - MOODLE_PASSWORD=kialo1234 # you can override the following by creating a .env file in the same directory as this file - TARGET_KIALO_URL=${TARGET_KIALO_URL:-http://localhost:5000} - - MOODLE_HOST=${MOODLE_HOST:-localhost:8080} + - MOODLE_HOST=http://${MOODLE_HOST:-localhost:8080} volumes: - - './moodle:/bitnami/moodle' + - './moodle_mod:/var/www/html/mod/kialo' depends_on: - mariadb moodleapp: diff --git a/development/moodleimage/Dockerfile b/development/moodleimage/Dockerfile new file mode 100644 index 0000000..b9ca5c7 --- /dev/null +++ b/development/moodleimage/Dockerfile @@ -0,0 +1,20 @@ +# See https://moodledev.io/general/development/policies/php for the list of available PHP versions. +# Different versions of Moodle require different versions of PHP. +ARG PHP_VERSION="8.1" + +FROM moodlehq/moodle-php-apache:${PHP_VERSION} + +# See https://moodledev.io/general/releases for the list of available versions. +# See https://github.com/moodle/moodle/branches for the available branches. +# Branch names follow the pattern MOODLE_XYZ_STABLE, e.g. MOODLE_404_STABLE for Moodle 4.4. +# main is the default and most up-to-date branch, it includes upcoming versions before they are stable. +ARG MOODLE_BRANCH="main" +ENV MOODLE_BRANCH=${MOODLE_BRANCH} + +RUN git clone git://git.moodle.org/moodle.git /var/www/html --depth=1 --branch ${MOODLE_BRANCH} + +COPY entrypoint.sh /usr/local/bin/entrypoint.sh +COPY config.php /var/www/html/config_kialo.php + +ENTRYPOINT ["entrypoint.sh"] +CMD ["apache2-foreground"] diff --git a/development/moodleimage/config.php b/development/moodleimage/config.php new file mode 100644 index 0000000..02a3a0e --- /dev/null +++ b/development/moodleimage/config.php @@ -0,0 +1,39 @@ +wwwroot = 'https://' . $_SERVER['HTTP_HOST']; +} else { + $CFG->wwwroot = 'http://' . $_SERVER['HTTP_HOST']; +} + +//========================================================================= +// PHPUNIT SUPPORT +//========================================================================= + $CFG->phpunit_prefix = 'phpu_'; + $CFG->phpunit_dataroot = '/var/www/moodledata/phpunit'; + $CFG->phpunit_directorypermissions = 02777; // optional + $CFG->phpunit_profilingenabled = true; // optional to profile PHPUnit runs. + +//========================================================================= +// Custom settings for development +//========================================================================= + +// Force a debugging mode regardless the settings in the site administration + @error_reporting(E_ALL | E_STRICT); // NOT FOR PRODUCTION SERVERS! + @ini_set('display_errors', '1'); // NOT FOR PRODUCTION SERVERS! + $CFG->debug = (E_ALL | E_STRICT); // === DEBUG_DEVELOPER - NOT FOR PRODUCTION SERVERS! + $CFG->debugdisplay = 1; // NOT FOR PRODUCTION SERVERS! + +// Make sure that the temp directories are not deleted during the backup process. Allows easier testing of the backup process. +$CFG->keeptempdirectoriesonbackup = true; + +require_once(__DIR__ . '/lib/setup.php'); diff --git a/development/moodleimage/entrypoint.sh b/development/moodleimage/entrypoint.sh new file mode 100755 index 0000000..a403526 --- /dev/null +++ b/development/moodleimage/entrypoint.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +# Install Moodle. See https://docs.moodle.org/404/en/Installing_Moodle#Command_line_installer +chown -R www-data /var/www/html +su - www-data -s /bin/bash -c "php /var/www/html/admin/cli/install.php --non-interactive --agree-license --allow-unstable --wwwroot=$MOODLE_HOST --dataroot=/var/www/moodledata --dbtype=mariadb --dbhost=$MOODLE_DATABASE_HOST --dbname=moodle --dbuser=moodle --dbport=$MOODLE_DATABASE_PORT_NUMBER --fullname=Moodle --shortname=moodle --adminuser=user --adminpass=$MOODLE_PASSWORD --adminemail=sre@kialo.com --supportemail=sre@kialo.com" + +# Amend the config.php file to include our own config for development. +# The line should be added before the last line "require_once(__DIR__ . '/lib/setup.php');". +sed -i '/require_once/i\require_once(__DIR__ . "/config_kialo.php");' /var/www/html/config.php + +exec /usr/local/bin/moodle-docker-php-entrypoint "$@" diff --git a/development/sync.sh b/development/sync.sh index 41f9bf3..8ec55e0 100755 --- a/development/sync.sh +++ b/development/sync.sh @@ -1,12 +1,6 @@ # Ensure this script is executed in the same folder cd "$(dirname "$0")" -# Ensure the directory exists -mkdir -p ./moodle/mod/kialo - # syncs the content of the development version of this plugin to the copy in the docker moodle installation (/moodle/mod/kialo) -rsync -atm --delete --delete-excluded --exclude={'/development','/.[!.]*'} .. ./moodle/mod/kialo +rsync -atm --delete --delete-excluded --exclude={'/development','/.[!.]*'} .. ./moodle_mod echo "Synced plugin." - -cp config/config.php moodle/config.php -echo "Synced config.php" diff --git a/development/tests-init.sh b/development/tests-init.sh index 87956b3..13ff589 100755 --- a/development/tests-init.sh +++ b/development/tests-init.sh @@ -1,2 +1,2 @@ # needs to run once initially and again whenever new tests are added -docker exec -i development-moodle-1 /bin/bash -c "cd /bitnami/moodle; php admin/tool/phpunit/cli/init.php" +docker exec -i mod_kialo-moodle-1 /bin/bash -c "cd /var/www/html; php admin/tool/phpunit/cli/init.php" diff --git a/development/tests-privacy.sh b/development/tests-privacy.sh index 8c60748..6e6ef34 100755 --- a/development/tests-privacy.sh +++ b/development/tests-privacy.sh @@ -1,2 +1,5 @@ +# Ensure files are up-to-date +./sync.sh + # Run the tests -docker exec -i development-moodle-1 /bin/bash -c "cd /bitnami/moodle; vendor/bin/phpunit --testsuite core_privacy_testsuite --filter kialo" +docker exec -i mod_kialo-moodle-1 /bin/bash -c "cd /var/www/html; vendor/bin/phpunit --testsuite core_privacy_testsuite --filter kialo" diff --git a/development/tests-run-all.sh b/development/tests-run-all.sh index 96ffe17..62ad3a3 100755 --- a/development/tests-run-all.sh +++ b/development/tests-run-all.sh @@ -1,2 +1,5 @@ +# Ensure files are up-to-date +./sync.sh + # Run the tests -docker exec -i development-moodle-1 /bin/bash -c "cd /bitnami/moodle; vendor/bin/phpunit --testsuite mod_kialo_testsuite" +docker exec -i mod_kialo-moodle-1 /bin/bash -c "cd /var/www/html; vendor/bin/phpunit --testsuite mod_kialo_testsuite" diff --git a/development/tests-run.sh b/development/tests-run.sh index 6ebbe9a..78c3831 100755 --- a/development/tests-run.sh +++ b/development/tests-run.sh @@ -1,3 +1,6 @@ +# Ensure files are up-to-date +./sync.sh + # Run a specific test file (path relative to mod/kialo/tests) # Example: ./tests-run.sh classes/mod_kialo_test.php -docker exec -i development-moodle-1 /bin/bash -c "cd /bitnami/moodle; vendor/bin/phpunit mod/kialo/tests/$1" +docker exec -i mod_kialo-moodle-1 /bin/bash -c "cd /var/www/html; vendor/bin/phpunit mod/kialo/tests/$1" diff --git a/lang/en/kialo.php b/lang/en/kialo.php index 6a305fc..5ec8c24 100644 --- a/lang/en/kialo.php +++ b/lang/en/kialo.php @@ -54,6 +54,8 @@ $string['kialofieldset'] = 'Kialo Fieldset'; $string['kialoname'] = 'Activity Name'; $string['kialosettings'] = 'Settings'; +$string['kialourl'] = 'Kialo URL'; +$string['kialourl_desc'] = 'The URL of the Kialo instance to use.'; $string['modulename'] = 'Kialo Discussion'; $string['modulename_help'] = 'The Kialo Discussion activity allows you to include a Kialo discussion in your Moodle course. Students can participate in the discussion directly from Moodle, without having to manually create Kialo accounts. Kialo discussions are a great way to teach and train critical thinking, argumentation and to facilitate thoughtful classroom discussions.'; $string['modulename_link'] = 'https://support.kialo-edu.com/en/hc/moodle'; diff --git a/settings.php b/settings.php index c6a706a..a441834 100644 --- a/settings.php +++ b/settings.php @@ -35,7 +35,8 @@ // Terms and conditions need to have been accepted before the activity can be used. if ($ADMIN->fulltree) { - $setting = new kialo_configcheckbox( + $termswerealreadyaccepted = get_config('mod_kialo', 'acceptterms') == 1; + $acceptterms = new kialo_configcheckbox( 'mod_kialo/acceptterms', new lang_string('acceptterms', 'mod_kialo'), new lang_string('acceptterms_desc', 'mod_kialo', [ @@ -43,15 +44,29 @@ "privacy" => MOD_KIALO_PRIVACY_LINK, "data_security" => MOD_KIALO_DATA_SECURITY_LINK, ]), - 0 + $termswerealreadyaccepted ? 1 : 0, ); // Once the terms have been accepted, they cannot be unaccepted. - $setting->force_readonly(get_config('mod_kialo', 'acceptterms')); + if ($termswerealreadyaccepted) { + $acceptterms->force_readonly(get_config('mod_kialo', 'acceptterms')); + } // Enable the module once the terms have been accepted. - $setting->set_updatedcallback('kialo_update_visibility_depending_on_accepted_terms'); + $acceptterms->set_updatedcallback('kialo_update_visibility_depending_on_accepted_terms'); /** @var admin_settingpage $settings */ - $settings->add($setting); + $settings->add($acceptterms); + + // For internal Kialo use only: Allow changing the Kialo target URL. + if (!empty(getenv('TARGET_KIALO_URL'))) { + $kialourl = new admin_setting_configtext( + 'mod_kialo/kialourl', + new lang_string('kialourl', 'mod_kialo'), + new lang_string('kialourl_desc', 'mod_kialo'), + 'https://www.kialo-edu.com', + ); + + $settings->add($kialourl); + } } diff --git a/tests/classes/kialo_config_test.php b/tests/classes/kialo_config_test.php index 51018c8..24b9140 100644 --- a/tests/classes/kialo_config_test.php +++ b/tests/classes/kialo_config_test.php @@ -33,27 +33,44 @@ * Tests the mod_kialo config. */ final class kialo_config_test extends \advanced_testcase { + public function setUp(): void { + parent::setUp(); + + $this->resetAfterTest(); + + // The variable TARGET_KIALO_URL is only set in Kialo test environments. By default it's not defined. + putenv("TARGET_KIALO_URL="); + set_config('kialourl', null, 'mod_kialo'); + } + /** * Tests the default tool URL. * @covers \mod_kialo\kialo_config::get_instance::get_tool_url */ public function test_default_tool_url(): void { - // The variable TARGET_KIALO_URL is only set in Kialo test environments. By default it's not defined. - putenv("TARGET_KIALO_URL="); - // In production, kialo-edu.com is always the endpoint for our plugin. $this->assertEquals("https://www.kialo-edu.com", kialo_config::get_instance()->get_tool_url()); } /** - * Tests that the tool URL can be overridden. + * Tests that the tool URL can be overridden via environment variable. * @covers \mod_kialo\kialo_config::get_instance::get_tool_url */ - public function test_custom_tool_url(): void { + public function test_custom_tool_url_via_env(): void { putenv("TARGET_KIALO_URL=http://localhost:5000"); $this->assertEquals("http://localhost:5000", kialo_config::get_instance()->get_tool_url()); } + /** + * Tests that the tool URL can be overridden via environment config, and it that is has precedence over the env var. + * @covers \mod_kialo\kialo_config::get_instance::get_tool_url + */ + public function test_custom_tool_url_via_config(): void { + set_config('kialourl', 'https://www.example.com', 'mod_kialo'); + putenv("TARGET_KIALO_URL=http://localhost:5000"); + $this->assertEquals("https://www.example.com", kialo_config::get_instance()->get_tool_url()); + } + /** * Tests private key generation. * @covers \mod_kialo\kialo_config::get_instance::get_platform_keychain