Compare commits

...
9 Commits
Author SHA1 Message Date
Valentin Popov a81530d0d7 refactor: remove cross-component runtime dependencies
Moodle Plugin CI / test (push) Successful in 3m20s
2026-08-12 17:53:02 +00:00
Valentin Popov 0d4bf6a208 style: apply Moodle coding standards
Moodle Plugin CI / test (push) Successful in 1m27s
2026-08-12 17:13:30 +00:00
Valentin Popov 91111b66d3 fix(ci): copy plugin into test image
Moodle Plugin CI / test (push) Failing after 1m44s
2026-08-12 17:07:32 +00:00
Valentin Popov d35ce9b445 ci: add Moodle 5.2 Docker checks 2026-08-12 16:57:33 +00:00
Valentin Popov 482d15db8f Bump version
Signed-off-by: Valentin Popov <info@valentineus.link>
2020-05-16 01:59:03 +04:00
Valentin PopovandGitHub 9d70f553bb Merge pull request #19 from catalyst/requires-v3.0.0-stable
Set minimum required version to Moodle 3.7.0
2020-05-16 00:57:28 +04:00
Valentin PopovandGitHub b77e2a2cdb Merge pull request #18 from catalyst/issue15-v3.0.0-stable
Add null privacy provider to fix #15
2020-05-16 00:56:45 +04:00
Dmitrii Metelkin f89cdba127 Set minimum required version to Moodle 3.7.0 2020-04-22 09:21:33 +10:00
Dmitrii Metelkin 1acd3ef21d Add null privacy provider to fix #15 2020-04-22 09:16:57 +10:00
25 changed files with 514 additions and 258 deletions
+38
View File
@@ -0,0 +1,38 @@
FROM composer:2.10.2@sha256:4d71c3c2109c61d5415544264b59ad4087e4c5b7244481723664138fd36d5040 AS composer
FROM node:22.23.2-bookworm-slim@sha256:d649c27dae7ba0137b3cef5dd75baa422c08dc3d9e3fc0c23dfb172dc3cc6436 AS node
FROM moodlehq/moodle-php-apache:8.4@sha256:07cac70e0ed3f96f334ffeece92075b98adfbe4110312a3a9308b95eab8e2080
ARG MOODLE_PLUGIN_CI_COMMIT=9276f968746960275b12190b4ef8e47b1e6af674
ARG MOODLE_PLUGIN_CI_LOCK_SHA256=e5c8ce77b90f43a057ee717c52e856bf81d43387834dab36083a1c1b17a24be4
COPY --from=composer /usr/bin/composer /usr/local/bin/composer
COPY --from=node /usr/local/bin/node /usr/local/bin/node
COPY --from=node /usr/local/lib/node_modules /usr/local/lib/node_modules
RUN ln -s /usr/local/lib/node_modules/npm/bin/npm-cli.js /usr/local/bin/npm \
&& ln -s /usr/local/lib/node_modules/npm/bin/npx-cli.js /usr/local/bin/npx \
&& apt-get update \
&& DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends postgresql-client \
&& rm -rf /var/lib/apt/lists/* \
&& locale-gen en_AU.UTF-8 \
&& git init /opt/moodle-plugin-ci \
&& git -C /opt/moodle-plugin-ci remote add origin https://github.com/moodlehq/moodle-plugin-ci.git \
&& git -C /opt/moodle-plugin-ci fetch --depth 1 origin "${MOODLE_PLUGIN_CI_COMMIT}" \
&& git -C /opt/moodle-plugin-ci checkout --detach FETCH_HEAD \
&& test "$(git -C /opt/moodle-plugin-ci rev-parse HEAD)" = "${MOODLE_PLUGIN_CI_COMMIT}" \
&& echo "${MOODLE_PLUGIN_CI_LOCK_SHA256} /opt/moodle-plugin-ci/composer.lock" | sha256sum --check \
&& COMPOSER_ALLOW_SUPERUSER=1 composer install \
--working-dir=/opt/moodle-plugin-ci \
--no-dev \
--no-interaction \
--prefer-dist \
--classmap-authoritative \
&& ln -s /opt/moodle-plugin-ci/bin/moodle-plugin-ci /usr/local/bin/moodle-plugin-ci
COPY . /plugin
ENV LANG=en_AU.UTF-8
WORKDIR /workspace
+11
View File
@@ -0,0 +1,11 @@
.git
.github
.gitea
.docker
.dockerignore
.env
.env.*
compose.yaml
node_modules
vendor
*.log
+31
View File
@@ -0,0 +1,31 @@
name: Moodle Plugin CI
on:
push:
branches:
- develop
- main
pull_request:
workflow_dispatch:
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
env:
COMPOSE_PROJECT_NAME: local_webhooks_${{ gitea.run_id }}_${{ gitea.run_attempt }}
steps:
- name: Check out repository
uses: https://github.com/actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Build test image
run: docker compose build --pull ci
- name: Test plugin
run: docker compose up --abort-on-container-exit --exit-code-from ci
- name: Clean up
if: always()
run: docker compose down --volumes --remove-orphans
-76
View File
@@ -1,76 +0,0 @@
language: php
sudo: true
addons:
firefox: "latest-esr"
postgresql: "9.6"
apt:
packages:
- "oracle-java8-installer"
- "oracle-java8-set-default"
cache:
directories:
- "$HOME/.composer/cache"
- "$HOME/.npm"
php:
- 7.0
- 7.1
- 7.2
env:
global:
- MOODLE_BRANCH=MOODLE_35_STABLE
matrix:
- DB=mysqli
- DB=pgsql
before_install:
- phpenv config-rm xdebug.ini
- nvm install 8.9
- nvm use 8.9
- cd ../..
- composer selfupdate
- composer create-project -n --no-dev --prefer-dist moodlerooms/moodle-plugin-ci ci ^2
- export PATH="$(cd ci/bin; pwd):$(cd ci/vendor/bin; pwd):$PATH"
install:
- moodle-plugin-ci install
script:
- moodle-plugin-ci phplint
- moodle-plugin-ci phpcpd
- moodle-plugin-ci phpmd
- moodle-plugin-ci codechecker
- moodle-plugin-ci validate
- moodle-plugin-ci savepoints
- moodle-plugin-ci mustache
- moodle-plugin-ci grunt
- moodle-plugin-ci phpunit
- moodle-plugin-ci behat
jobs:
include:
- stage: test old
env: DB=mysqli MOODLE_BRANCH=MOODLE_33_STABLE
php: 5.6
- stage: deploy
php: 7.2
before_deploy:
- cd "$TRAVIS_REPO_SLUG"
- git stash --all
- /bin/sh build.sh
deploy:
api_key: $GITHUB_PROJECT_TOKEN
email: "info@valentineus.link"
file: "../build/*.zip"
file_glob: true
provider: releases
skip_cleanup: true
on:
tags: true
+2 -5
View File
@@ -24,10 +24,7 @@
namespace local_webhooks\event; namespace local_webhooks\event;
defined('MOODLE_INTERNAL') || die();
use core\event\base; use core\event\base;
use lang_string;
use moodle_url; use moodle_url;
/** /**
@@ -43,7 +40,7 @@ class backup_performed extends base {
* @throws \coding_exception * @throws \coding_exception
*/ */
public static function get_name() { public static function get_name() {
return new lang_string('create', 'moodle'); return get_string('create', 'local_webhooks');
} }
/** /**
@@ -52,7 +49,7 @@ class backup_performed extends base {
* @throws \coding_exception * @throws \coding_exception
*/ */
public function get_description() { public function get_description() {
return new lang_string('backup', 'moodle'); return get_string('backup', 'local_webhooks');
} }
/** /**
+2 -5
View File
@@ -24,10 +24,7 @@
namespace local_webhooks\event; namespace local_webhooks\event;
defined('MOODLE_INTERNAL') || die();
use core\event\base; use core\event\base;
use lang_string;
use moodle_url; use moodle_url;
/** /**
@@ -43,7 +40,7 @@ class backup_restored extends base {
* @throws \coding_exception * @throws \coding_exception
*/ */
public static function get_name() { public static function get_name() {
return new lang_string('update', 'moodle'); return get_string('update', 'local_webhooks');
} }
/** /**
@@ -52,7 +49,7 @@ class backup_restored extends base {
* @throws \coding_exception * @throws \coding_exception
*/ */
public function get_description() { public function get_description() {
return new lang_string('backupfinished', 'moodle'); return get_string('backupfinished', 'local_webhooks');
} }
/** /**
+2 -5
View File
@@ -24,10 +24,7 @@
namespace local_webhooks\event; namespace local_webhooks\event;
defined('MOODLE_INTERNAL') || die();
use core\event\base; use core\event\base;
use lang_string;
use moodle_url; use moodle_url;
/** /**
@@ -43,7 +40,7 @@ class response_answer extends base {
* @throws \coding_exception * @throws \coding_exception
*/ */
public static function get_name() { public static function get_name() {
return new lang_string('answer', 'moodle'); return get_string('answer', 'local_webhooks');
} }
/** /**
@@ -59,7 +56,7 @@ class response_answer extends base {
* @throws \moodle_exception * @throws \moodle_exception
*/ */
public function get_url() { public function get_url() {
return new moodle_url('/local/webhooks/editservice.php', array('serviceid' => $this->objectid)); return new moodle_url('/local/webhooks/editservice.php', ['serviceid' => $this->objectid]);
} }
/** /**
+3 -6
View File
@@ -24,10 +24,7 @@
namespace local_webhooks\event; namespace local_webhooks\event;
defined('MOODLE_INTERNAL') || die();
use core\event\base; use core\event\base;
use lang_string;
use moodle_url; use moodle_url;
/** /**
@@ -43,7 +40,7 @@ class service_added extends base {
* @throws \coding_exception * @throws \coding_exception
*/ */
public static function get_name() { public static function get_name() {
return new lang_string('create', 'moodle'); return get_string('create', 'local_webhooks');
} }
/** /**
@@ -52,7 +49,7 @@ class service_added extends base {
* @throws \coding_exception * @throws \coding_exception
*/ */
public function get_description() { public function get_description() {
return new lang_string('eventwebserviceservicecreated', 'webservice'); return get_string('eventwebserviceservicecreated', 'local_webhooks');
} }
/** /**
@@ -61,7 +58,7 @@ class service_added extends base {
* @throws \moodle_exception * @throws \moodle_exception
*/ */
public function get_url() { public function get_url() {
return new moodle_url('/local/webhooks/editservice.php', array('serviceid' => $this->objectid)); return new moodle_url('/local/webhooks/editservice.php', ['serviceid' => $this->objectid]);
} }
/** /**
+2 -5
View File
@@ -24,10 +24,7 @@
namespace local_webhooks\event; namespace local_webhooks\event;
defined('MOODLE_INTERNAL') || die();
use core\event\base; use core\event\base;
use lang_string;
use moodle_url; use moodle_url;
/** /**
@@ -43,7 +40,7 @@ class service_deleted extends base {
* @throws \coding_exception * @throws \coding_exception
*/ */
public static function get_name() { public static function get_name() {
return new lang_string('deleted', 'moodle'); return get_string('deleted', 'local_webhooks');
} }
/** /**
@@ -52,7 +49,7 @@ class service_deleted extends base {
* @throws \coding_exception * @throws \coding_exception
*/ */
public function get_description() { public function get_description() {
return new lang_string('eventwebserviceservicedeleted', 'webservice'); return get_string('eventwebserviceservicedeleted', 'local_webhooks');
} }
/** /**
+3 -6
View File
@@ -24,10 +24,7 @@
namespace local_webhooks\event; namespace local_webhooks\event;
defined('MOODLE_INTERNAL') || die();
use core\event\base; use core\event\base;
use lang_string;
use moodle_url; use moodle_url;
/** /**
@@ -43,7 +40,7 @@ class service_updated extends base {
* @throws \coding_exception * @throws \coding_exception
*/ */
public static function get_name() { public static function get_name() {
return new lang_string('update', 'moodle'); return get_string('update', 'local_webhooks');
} }
/** /**
@@ -52,7 +49,7 @@ class service_updated extends base {
* @throws \coding_exception * @throws \coding_exception
*/ */
public function get_description() { public function get_description() {
return new lang_string('eventwebserviceserviceupdated', 'webservice'); return get_string('eventwebserviceserviceupdated', 'local_webhooks');
} }
/** /**
@@ -61,7 +58,7 @@ class service_updated extends base {
* @throws \moodle_exception * @throws \moodle_exception
*/ */
public function get_url() { public function get_url() {
return new moodle_url('/local/webhooks/editservice.php', array('serviceid' => $this->objectid)); return new moodle_url('/local/webhooks/editservice.php', ['serviceid' => $this->objectid]);
} }
/** /**
+1 -1
View File
@@ -96,7 +96,7 @@ class handler {
*/ */
private static function send($data, $callback) { private static function send($data, $callback) {
$curl = new curl(); $curl = new curl();
$curl->setHeader(array('Content-Type: application/' . $callback->type)); $curl->setHeader(['Content-Type: application/' . $callback->type]);
$curl->post($callback->url, json_encode($data)); $curl->post($callback->url, json_encode($data));
$response = $curl->getResponse(); $response = $curl->getResponse();
+42
View File
@@ -0,0 +1,42 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Privacy Subsystem implementation for local_webhooks.
*
* @package local_webhooks
* @copyright 2020 Dmitrii Metelkin <dmitriim@catalyst-net.au>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace local_webhooks\privacy;
/**
* Declares that the plugin does not store personal data.
*/
class provider implements
// This plugin does not store any personal user data.
\core_privacy\local\metadata\null_provider {
/**
* Get the language string identifier with the component's language
* file to explain why this plugin stores no data.
*
* @return string
*/
public static function get_reason(): string {
return 'privacy:metadata';
}
}
+103
View File
@@ -0,0 +1,103 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Defines the service editing form.
*
* @package local_webhooks
* @copyright 2017 "Valentin Popov" <info@valentineus.link>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
require_once($CFG->libdir . '/formslib.php');
/**
* Description editing form definition.
*
* @copyright 2017 "Valentin Popov" <info@valentineus.link>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class service_edit_form extends moodleform {
/**
* Defines the standard structure of the form.
*
* @throws \coding_exception
*/
protected function definition() {
$mform =& $this->_form;
$size = ['size' => 60];
/* Form heading */
$mform->addElement('header', 'editserviceheader', new lang_string('service', 'local_webhooks'));
/* Name of the service */
$mform->addElement('text', 'title', new lang_string('name', 'local_webhooks'), $size);
$mform->addRule('title', null, 'required');
$mform->setType('title', PARAM_NOTAGS);
/* Callback address */
$mform->addElement('text', 'url', new lang_string('url', 'local_webhooks'), $size);
$mform->addRule('url', null, 'required');
$mform->setType('url', PARAM_URL);
/* Enabling the service */
$mform->addElement('advcheckbox', 'enable', new lang_string('enable', 'local_webhooks'));
$mform->setType('enable', PARAM_BOOL);
$mform->setDefault('enable', 1);
$mform->setAdvanced('enable');
/* Token */
$mform->addElement('text', 'token', new lang_string('token', 'local_webhooks'), $size);
$mform->setType('token', PARAM_NOTAGS);
/* Additional information */
$mform->addElement('text', 'other', new lang_string('sourceext', 'local_webhooks'), $size);
$mform->setType('other', PARAM_NOTAGS);
$mform->setAdvanced('other');
/* Content type */
$contenttype = [
'json' => 'application/json',
'x-www-form-urlencoded' => 'application/x-www-form-urlencoded',
];
$mform->addElement('select', 'type', new lang_string('contenttype', 'local_webhooks'), $contenttype);
$mform->setAdvanced('type');
/* Form heading */
$mform->addElement('header', 'editserviceheaderevent', new lang_string('edulevel', 'local_webhooks'));
/* List of events */
$events = [];
/* Formation of the list of elements */
foreach (local_webhooks_get_event_choices() as $component => $choices) {
foreach ($choices as $key => $eventname) {
$events[$component][] =& $mform->createElement('checkbox', $key, $eventname);
}
}
/* Displays groups of items */
foreach ($events as $key => $event) {
$mform->addGroup($event, 'events', $key, '<br />');
}
/* Control Panel */
$this->add_action_buttons();
}
}
+3 -80
View File
@@ -42,90 +42,13 @@ class service_backup_form extends moodleform {
$mform =& $this->_form; $mform =& $this->_form;
/* Form heading */ /* Form heading */
$mform->addElement('header', 'editserviceheader', new lang_string('restore', 'moodle')); $mform->addElement('header', 'editserviceheader', new lang_string('restore', 'local_webhooks'));
/* Download the file */ /* Download the file */
$mform->addElement('filepicker', 'backupfile', new lang_string('file', 'moodle')); $mform->addElement('filepicker', 'backupfile', new lang_string('file', 'local_webhooks'));
$mform->addRule('backupfile', null, 'required'); $mform->addRule('backupfile', null, 'required');
/* Control Panel */ /* Control Panel */
$this->add_action_buttons(true, new lang_string('restore', 'moodle')); $this->add_action_buttons(true, new lang_string('restore', 'local_webhooks'));
}
}
/**
* Description editing form definition.
*
* @copyright 2017 "Valentin Popov" <info@valentineus.link>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class service_edit_form extends moodleform {
/**
* Defines the standard structure of the form.
*
* @throws \coding_exception
*/
protected function definition() {
$mform =& $this->_form;
$size = ['size' => 60];
/* Form heading */
$mform->addElement('header', 'editserviceheader', new lang_string('service', 'webservice'));
/* Name of the service */
$mform->addElement('text', 'title', new lang_string('name', 'moodle'), $size);
$mform->addRule('title', null, 'required');
$mform->setType('title', PARAM_NOTAGS);
/* Callback address */
$mform->addElement('text', 'url', new lang_string('url', 'moodle'), $size);
$mform->addRule('url', null, 'required');
$mform->setType('url', PARAM_URL);
/* Enabling the service */
$mform->addElement('advcheckbox', 'enable', new lang_string('enable', 'moodle'));
$mform->setType('enable', PARAM_BOOL);
$mform->setDefault('enable', 1);
$mform->setAdvanced('enable');
/* Token */
$mform->addElement('text', 'token', new lang_string('token', 'webservice'), $size);
$mform->setType('token', PARAM_NOTAGS);
/* Additional information */
$mform->addElement('text', 'other', new lang_string('sourceext', 'plugin'), $size);
$mform->setType('other', PARAM_NOTAGS);
$mform->setAdvanced('other');
/* Content type */
$contenttype = [
'json' => 'application/json',
'x-www-form-urlencoded' => 'application/x-www-form-urlencoded',
];
$mform->addElement('select', 'type', 'Content type', $contenttype);
$mform->setAdvanced('type');
/* Form heading */
$mform->addElement('header', 'editserviceheaderevent', new lang_string('edulevel', 'moodle'));
/* List of events */
$eventlist = report_eventlist_list_generator::get_all_events_list();
$events = [];
/* Formation of the list of elements */
foreach ($eventlist as $event) {
/* Escaping event names */
$eventname = base64_encode($event['eventname']);
$events[$event['component']][] =& $mform->createElement('checkbox', $eventname, $event['eventname']);
}
/* Displays groups of items */
foreach ($events as $key => $event) {
$mform->addGroup($event, 'events', $key, '<br />');
}
/* Control Panel */
$this->add_action_buttons();
} }
} }
+44
View File
@@ -0,0 +1,44 @@
services:
postgres:
image: postgres:16.13-alpine3.22@sha256:caf536ebd910e85473a9f5e2fd1aea360c965c4a911c8555ac1f61b2102006cb
environment:
POSTGRES_HOST_AUTH_METHOD: trust
POSTGRES_USER: postgres
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 2s
timeout: 5s
retries: 15
tmpfs:
- /var/lib/postgresql/data
ci:
build:
context: .
dockerfile: .docker/ci/Dockerfile
depends_on:
postgres:
condition: service_healthy
environment:
DB: pgsql
DB_HOST: postgres
DB_USER: postgres
MOODLE_BRANCH: v5.2.2
NPM_CONFIG_FETCH_RETRIES: 5
command:
- /bin/bash
- -lc
- |
set -euo pipefail
php --version
composer --version
node --version
moodle-plugin-ci --version
moodle-plugin-ci install --plugin /plugin --branch v5.2.2 --db-host postgres
test "$$(git -C /workspace/moodle rev-parse HEAD)" = "acfa383c13dd46c83ca82894a8e95fac273fda33"
moodle-plugin-ci phplint
moodle-plugin-ci phpcs --max-warnings 0
moodle-plugin-ci phpdoc --max-warnings 0
moodle-plugin-ci validate
moodle-plugin-ci savepoints
moodle-plugin-ci phpunit --fail-on-warning
+4 -4
View File
@@ -24,12 +24,12 @@
defined('MOODLE_INTERNAL') || die(); defined('MOODLE_INTERNAL') || die();
$observers = array( $observers = [
array( [
'callback' => '\local_webhooks\handler::events', 'callback' => '\local_webhooks\handler::events',
'eventname' => '*', 'eventname' => '*',
'includefile' => null, 'includefile' => null,
'internal' => true, 'internal' => true,
'priority' => 200, 'priority' => 200,
), ],
); ];
+7 -7
View File
@@ -23,7 +23,7 @@
*/ */
require_once(__DIR__ . '/../../config.php'); require_once(__DIR__ . '/../../config.php');
require_once(__DIR__ . '/classes/service_form.php'); require_once(__DIR__ . '/classes/service_edit_form.php');
require_once(__DIR__ . '/lib.php'); require_once(__DIR__ . '/lib.php');
require_once($CFG->libdir . '/adminlib.php'); require_once($CFG->libdir . '/adminlib.php');
@@ -32,7 +32,7 @@ require_once($CFG->libdir . '/adminlib.php');
$serviceid = optional_param('serviceid', 0, PARAM_INT); $serviceid = optional_param('serviceid', 0, PARAM_INT);
/* Link generation */ /* Link generation */
$urlparameters = array('serviceid' => $serviceid); $urlparameters = ['serviceid' => $serviceid];
$baseurl = new moodle_url('/local/webhooks/editservice.php', $urlparameters); $baseurl = new moodle_url('/local/webhooks/editservice.php', $urlparameters);
$managerservice = new moodle_url('/local/webhooks/index.php'); $managerservice = new moodle_url('/local/webhooks/index.php');
@@ -54,7 +54,7 @@ if (($editing = (bool) $serviceid) === true) {
$servicerecord = local_webhooks_get_record($serviceid); $servicerecord = local_webhooks_get_record($serviceid);
if (is_array($servicerecord->events)) { if (is_array($servicerecord->events)) {
$events = array(); $events = [];
/* Escaping event names */ /* Escaping event names */
foreach ($servicerecord->events as $eventname => $eventstatus) { foreach ($servicerecord->events as $eventname => $eventstatus) {
@@ -71,7 +71,7 @@ if (($editing = (bool) $serviceid) === true) {
/* Processing of received data */ /* Processing of received data */
if (!empty($data = $mform->get_data())) { if (!empty($data = $mform->get_data())) {
if (is_array($data->events)) { if (is_array($data->events)) {
$events = array(); $events = [];
/* Deciphering event names */ /* Deciphering event names */
foreach ($data->events as $eventname => $eventstatus) { foreach ($data->events as $eventname => $eventstatus) {
@@ -85,15 +85,15 @@ if (!empty($data = $mform->get_data())) {
if ($editing) { if ($editing) {
$data->id = $serviceid; $data->id = $serviceid;
local_webhooks_update_record($data, false); local_webhooks_update_record($data, false);
redirect($managerservice, new lang_string('eventwebserviceserviceupdated', 'webservice')); redirect($managerservice, new lang_string('eventwebserviceserviceupdated', 'local_webhooks'));
} else { } else {
local_webhooks_update_record($data); local_webhooks_update_record($data);
redirect($managerservice, new lang_string('eventwebserviceservicecreated', 'webservice')); redirect($managerservice, new lang_string('eventwebserviceservicecreated', 'local_webhooks'));
} }
} }
/* The page title */ /* The page title */
$titlepage = new lang_string('externalservice', 'webservice'); $titlepage = new lang_string('externalservice', 'local_webhooks');
$PAGE->navbar->add($titlepage); $PAGE->navbar->add($titlepage);
$PAGE->set_heading($titlepage); $PAGE->set_heading($titlepage);
$PAGE->set_title($titlepage); $PAGE->set_title($titlepage);
+21 -21
View File
@@ -46,7 +46,7 @@ $context = context_system::instance();
/* Delete the service */ /* Delete the service */
if ((bool) $deleteid) { if ((bool) $deleteid) {
local_webhooks_remove_record($deleteid); local_webhooks_remove_record($deleteid);
redirect($PAGE->url, new lang_string('eventwebserviceservicedeleted', 'webservice')); redirect($PAGE->url, new lang_string('eventwebserviceservicedeleted', 'local_webhooks'));
} }
/* Retrieving a list of services */ /* Retrieving a list of services */
@@ -66,7 +66,7 @@ if ((bool) $hideshowid) {
if (!empty($callback)) { if (!empty($callback)) {
$callback->enable = !(bool) $callback->enable; $callback->enable = !(bool) $callback->enable;
local_webhooks_update_record($callback, false); local_webhooks_update_record($callback, false);
redirect($PAGE->url, new lang_string('eventwebserviceserviceupdated', 'webservice')); redirect($PAGE->url, new lang_string('eventwebserviceserviceupdated', 'local_webhooks'));
} }
} }
@@ -81,19 +81,19 @@ $table = new flexible_table('webhooks-service-table');
/* Customize the table */ /* Customize the table */
$table->define_columns( $table->define_columns(
array( [
'title', 'title',
'url', 'url',
'actions', 'actions',
) ]
); );
$table->define_headers( $table->define_headers(
array( [
new lang_string('name', 'moodle'), new lang_string('name', 'local_webhooks'),
new lang_string('url', 'moodle'), new lang_string('url', 'local_webhooks'),
new lang_string('actions', 'moodle'), new lang_string('actions', 'local_webhooks'),
) ]
); );
$table->define_baseurl($baseurl); $table->define_baseurl($baseurl);
@@ -106,26 +106,26 @@ foreach ($callbacks as $callback) {
/* Defining service status */ /* Defining service status */
$hideshowicon = 't/show'; $hideshowicon = 't/show';
$hideshowstring = new lang_string('enable', 'moodle'); $hideshowstring = new lang_string('enable', 'local_webhooks');
if ((bool) $callback->enable) { if ((bool) $callback->enable) {
$hideshowicon = 't/hide'; $hideshowicon = 't/hide';
$hideshowstring = new lang_string('disable', 'moodle'); $hideshowstring = new lang_string('disable', 'local_webhooks');
} }
/* Link to enable / disable the service */ /* Link to enable / disable the service */
$hideshowlink = new moodle_url($managerservice, array('hideshowid' => $callback->id)); $hideshowlink = new moodle_url($managerservice, ['hideshowid' => $callback->id]);
$hideshowitem = $OUTPUT->action_icon($hideshowlink, new pix_icon($hideshowicon, $hideshowstring)); $hideshowitem = $OUTPUT->action_icon($hideshowlink, new pix_icon($hideshowicon, $hideshowstring));
/* Link for editing */ /* Link for editing */
$editlink = new moodle_url($editservice, array('serviceid' => $callback->id)); $editlink = new moodle_url($editservice, ['serviceid' => $callback->id]);
$edititem = $OUTPUT->action_icon($editlink, new pix_icon('t/edit', new lang_string('edit', 'moodle'))); $edititem = $OUTPUT->action_icon($editlink, new pix_icon('t/edit', new lang_string('edit', 'local_webhooks')));
/* Link to remove */ /* Link to remove */
$deletelink = new moodle_url($managerservice, array('deleteid' => $callback->id)); $deletelink = new moodle_url($managerservice, ['deleteid' => $callback->id]);
$deleteitem = $OUTPUT->action_icon($deletelink, new pix_icon('t/delete', new lang_string('delete', 'moodle'))); $deleteitem = $OUTPUT->action_icon($deletelink, new pix_icon('t/delete', new lang_string('delete', 'local_webhooks')));
/* Adding data to the table */ /* Adding data to the table */
$table->add_data(array($titlecallback, $urlcallback, $hideshowitem . $edititem . $deleteitem)); $table->add_data([$titlecallback, $urlcallback, $hideshowitem . $edititem . $deleteitem]);
} }
/* Display the table */ /* Display the table */
@@ -133,14 +133,14 @@ $table->print_html();
/* Add service button */ /* Add service button */
$addserviceurl = new moodle_url($editservice); $addserviceurl = new moodle_url($editservice);
echo $OUTPUT->single_button($addserviceurl, new lang_string('addaservice', 'webservice'), 'get'); echo $OUTPUT->single_button($addserviceurl, new lang_string('addaservice', 'local_webhooks'), 'get');
/* Button to get a backup */ /* Button to get a backup */
$backupurl = new moodle_url($managerservice, array('getbackup' => true)); $backupurl = new moodle_url($managerservice, ['getbackup' => true]);
echo $OUTPUT->single_button($backupurl, new lang_string('backup', 'moodle'), 'get'); echo $OUTPUT->single_button($backupurl, new lang_string('backup', 'local_webhooks'), 'get');
/* Button for restoring settings */ /* Button for restoring settings */
$restorebackupurl = new moodle_url($restorebackup); $restorebackupurl = new moodle_url($restorebackup);
echo $OUTPUT->single_button($restorebackupurl, new lang_string('restore', 'moodle'), 'get'); echo $OUTPUT->single_button($restorebackupurl, new lang_string('restore', 'local_webhooks'), 'get');
echo $OUTPUT->footer(); echo $OUTPUT->footer();
+28
View File
@@ -22,4 +22,32 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
$string['actions'] = 'Actions';
$string['addaservice'] = 'Add service';
$string['answer'] = 'Answer';
$string['backup'] = 'Backup';
$string['backupfinished'] = 'Backup completed successfully';
$string['contenttype'] = 'Content type';
$string['create'] = 'Create';
$string['delete'] = 'Delete';
$string['deleted'] = 'Deleted';
$string['disable'] = 'Disable';
$string['edit'] = 'Edit';
$string['edulevel'] = 'All events';
$string['enable'] = 'Enable';
$string['errorsendingrequest'] = 'Error sending request';
$string['eventwebserviceservicecreated'] = 'Web service created';
$string['eventwebserviceservicedeleted'] = 'Web service deleted';
$string['eventwebserviceserviceupdated'] = 'Web service updated';
$string['externalservice'] = 'External service';
$string['file'] = 'File';
$string['name'] = 'Name';
$string['pluginname'] = 'WebHooks'; $string['pluginname'] = 'WebHooks';
$string['privacy:metadata'] = 'WebHooks does not store any personal data.';
$string['restore'] = 'Restore';
$string['restorefinished'] = 'Restore completed successfully';
$string['service'] = 'Service';
$string['sourceext'] = 'Additional';
$string['token'] = 'Token';
$string['update'] = 'Update';
$string['url'] = 'URL';
+46 -4
View File
@@ -26,6 +26,48 @@ defined('MOODLE_INTERNAL') || die();
require_once(__DIR__ . '/locallib.php'); require_once(__DIR__ . '/locallib.php');
/**
* Returns available event classes grouped by component.
*
* @return array
*/
function local_webhooks_get_event_choices() {
global $CFG;
$choices = [];
$debug = $CFG->debug;
// Deprecated core events emit debugging while loading; mirror the core tool_monitor workaround.
try {
$CFG->debug = DEBUG_NONE;
$classes = core_component::get_component_classes_in_namespace(null, 'event');
} finally {
$CFG->debug = $debug;
}
ksort($classes);
foreach (array_keys($classes) as $classname) {
if (
$classname === \core\event\unknown_logged::class
|| !is_subclass_of($classname, \core\event\base::class)
|| $classname::is_deprecated()
) {
continue;
}
$reflection = new ReflectionClass($classname);
if ($reflection->isAbstract()) {
continue;
}
$eventname = '\\' . ltrim($classname, '\\');
$component = core_component::get_component_from_classname($classname);
$choices[$component][base64_encode($eventname)] = $eventname;
}
return $choices;
}
/** /**
* Getting a list of all services. * Getting a list of all services.
* *
@@ -60,7 +102,7 @@ function local_webhooks_get_list_records($limitfrom = 0, $limitnum = 0) {
function local_webhooks_get_record($serviceid = 0) { function local_webhooks_get_record($serviceid = 0) {
global $DB; global $DB;
$servicerecord = $DB->get_record('local_webhooks_service', array('id' => $serviceid), '*', MUST_EXIST); $servicerecord = $DB->get_record('local_webhooks_service', ['id' => $serviceid], '*', MUST_EXIST);
if (!empty($servicerecord->events)) { if (!empty($servicerecord->events)) {
$servicerecord->events = local_webhooks_unarchive_data($servicerecord->events); $servicerecord->events = local_webhooks_unarchive_data($servicerecord->events);
@@ -91,7 +133,7 @@ function local_webhooks_remove_list_records() {
function local_webhooks_remove_record($serviceid = 0) { function local_webhooks_remove_record($serviceid = 0) {
global $DB; global $DB;
$DB->delete_records('local_webhooks_service', array('id' => $serviceid)); $DB->delete_records('local_webhooks_service', ['id' => $serviceid]);
local_webhooks_events::service_deleted($serviceid); local_webhooks_events::service_deleted($serviceid);
} }
@@ -109,7 +151,7 @@ function local_webhooks_update_record($data, $insert = true) {
global $DB; global $DB;
if (empty($data->events)) { if (empty($data->events)) {
$data->events = array(); $data->events = [];
} }
$data->events = local_webhooks_archiving_data($data->events); $data->events = local_webhooks_archiving_data($data->events);
@@ -167,7 +209,7 @@ function local_webhooks_restore_backup($listservices = '') {
* *
* @return string * @return string
*/ */
function local_webhooks_archiving_data(array $data = array()) { function local_webhooks_archiving_data(array $data = []) {
return base64_encode(gzcompress(serialize($data), 3)); return base64_encode(gzcompress(serialize($data), 3));
} }
+9 -11
View File
@@ -22,8 +22,6 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/ */
defined('MOODLE_INTERNAL') || die();
/** /**
* Description of functions of the call of events * Description of functions of the call of events
* *
@@ -41,10 +39,10 @@ class local_webhooks_events {
$context = context_system::instance(); $context = context_system::instance();
$event = local_webhooks\event\backup_performed::create( $event = local_webhooks\event\backup_performed::create(
array( [
'context' => $context, 'context' => $context,
'objectid' => 0, 'objectid' => 0,
) ]
); );
$event->trigger(); $event->trigger();
@@ -60,10 +58,10 @@ class local_webhooks_events {
$context = context_system::instance(); $context = context_system::instance();
$event = local_webhooks\event\backup_restored::create( $event = local_webhooks\event\backup_restored::create(
array( [
'context' => $context, 'context' => $context,
'objectid' => 0, 'objectid' => 0,
) ]
); );
$event->trigger(); $event->trigger();
@@ -78,20 +76,20 @@ class local_webhooks_events {
* @throws \coding_exception * @throws \coding_exception
* @throws \dml_exception * @throws \dml_exception
*/ */
public static function response_answer($objectid = 0, array $response = array()) { public static function response_answer($objectid = 0, array $response = []) {
$context = context_system::instance(); $context = context_system::instance();
$status = 'Error sending request'; $status = get_string('errorsendingrequest', 'local_webhooks');
if (!empty($response['HTTP/1.1'])) { if (!empty($response['HTTP/1.1'])) {
$status = $response['HTTP/1.1']; $status = $response['HTTP/1.1'];
} }
$event = local_webhooks\event\response_answer::create( $event = local_webhooks\event\response_answer::create(
array( [
'context' => $context, 'context' => $context,
'objectid' => $objectid, 'objectid' => $objectid,
'other' => array('status' => $status), 'other' => ['status' => $status],
) ]
); );
$event->trigger(); $event->trigger();
+2 -2
View File
@@ -48,11 +48,11 @@ if ($mform->is_cancelled()) {
if (!empty($data = $mform->get_data())) { if (!empty($data = $mform->get_data())) {
$content = $mform->get_file_content('backupfile'); $content = $mform->get_file_content('backupfile');
local_webhooks_restore_backup($content); local_webhooks_restore_backup($content);
redirect($managerservice, new lang_string('restorefinished', 'moodle')); redirect($managerservice, new lang_string('restorefinished', 'local_webhooks'));
} }
/* The page title */ /* The page title */
$titlepage = new lang_string('backup', 'moodle'); $titlepage = new lang_string('backup', 'local_webhooks');
$PAGE->navbar->add($titlepage); $PAGE->navbar->add($titlepage);
$PAGE->set_heading($titlepage); $PAGE->set_heading($titlepage);
$PAGE->set_title($titlepage); $PAGE->set_title($titlepage);
+2 -3
View File
@@ -24,11 +24,10 @@
defined('MOODLE_INTERNAL') || die(); defined('MOODLE_INTERNAL') || die();
/* @var \admin_root $ADMIN */
if ($hassiteconfig) { if ($hassiteconfig) {
$ADMIN->add( $ADMIN->add(
'server', new admin_externalpage( 'server',
new admin_externalpage(
'local_webhooks', 'local_webhooks',
new lang_string('pluginname', 'local_webhooks'), new lang_string('pluginname', 'local_webhooks'),
new moodle_url('/local/webhooks/index.php') new moodle_url('/local/webhooks/index.php')
+91
View File
@@ -0,0 +1,91 @@
<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Runtime autonomy tests.
*
* @package local_webhooks
* @copyright 2026 "Valentin Popov" <info@valentineus.link>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace local_webhooks;
/**
* Runtime autonomy tests.
*/
#[\PHPUnit\Framework\Attributes\CoversFunction('local_webhooks_get_event_choices')]
final class autonomy_test extends \advanced_testcase {
/**
* Event choices keep their storage format and custom event names are strings.
*/
public function test_event_contracts(): void {
global $CFG;
require_once($CFG->dirroot . '/local/webhooks/lib.php');
require_once($CFG->dirroot . '/local/webhooks/classes/service_edit_form.php');
$debugsettings = [$CFG->debug, $CFG->debugdisplay, $CFG->debugdeveloper];
$choices = \local_webhooks_get_event_choices();
$this->assertNotEmpty($choices);
$this->assertSame($debugsettings, [$CFG->debug, $CFG->debugdisplay, $CFG->debugdeveloper]);
foreach ($choices as $component => $events) {
foreach ($events as $key => $eventname) {
$classname = ltrim($eventname, '\\');
$this->assertSame(base64_encode($eventname), $key);
$this->assertSame($component, \core_component::get_component_from_classname($classname));
$this->assertTrue(is_subclass_of($classname, \core\event\base::class));
$this->assertFalse((new \ReflectionClass($classname))->isAbstract());
$this->assertFalse($classname::is_deprecated());
}
}
$coreevent = '\\' . \core\event\user_created::class;
$localevent = '\\' . \local_webhooks\event\service_added::class;
$unknown = '\\' . \core\event\unknown_logged::class;
$deprecated = '\\' . \core\event\role_capabilities_updated::class;
$this->assertSame($coreevent, $choices['core'][base64_encode($coreevent)]);
$this->assertSame($localevent, $choices['local_webhooks'][base64_encode($localevent)]);
$this->assertArrayNotHasKey(base64_encode($unknown), $choices['core']);
$this->assertArrayNotHasKey(base64_encode($deprecated), $choices['core']);
$events = [
\local_webhooks\event\backup_performed::class => 'create',
\local_webhooks\event\backup_restored::class => 'update',
\local_webhooks\event\response_answer::class => 'answer',
\local_webhooks\event\service_added::class => 'create',
\local_webhooks\event\service_deleted::class => 'deleted',
\local_webhooks\event\service_updated::class => 'update',
];
foreach ($events as $event => $stringkey) {
$name = $event::get_name();
$this->assertIsString($name);
$this->assertNotSame('', trim($name));
$this->assertSame(get_string($stringkey, 'local_webhooks'), $name);
}
$this->assertFalse(class_exists('report_eventlist_list_generator', false));
$form = new \service_edit_form(new \moodle_url('/local/webhooks/editservice.php'));
$html = $form->render();
$this->assertStringContainsString($coreevent, $html);
$this->assertStringContainsString($localevent, $html);
$this->assertFalse(class_exists('report_eventlist_list_generator', false));
}
}
+3 -3
View File
@@ -26,6 +26,6 @@ defined('MOODLE_INTERNAL') || die();
$plugin->component = 'local_webhooks'; $plugin->component = 'local_webhooks';
$plugin->maturity = MATURITY_STABLE; $plugin->maturity = MATURITY_STABLE;
$plugin->release = '3.0.4 (Build: 2020041400)'; $plugin->release = '3.0.5 (Build: 2020051600)';
$plugin->requires = 2019111800.00; $plugin->requires = 2019052000;
$plugin->version = 2020041400; $plugin->version = 2020051600;