diff --git a/.babelrc.json b/.babelrc.json deleted file mode 100755 index bc92ecff3da0..000000000000 --- a/.babelrc.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "presets": [ - [ - "@babel/preset-env", - ] - ] -} diff --git a/.eslintrc.json b/.eslintrc.json index 1a92f678f798..04a297f376ad 100755 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -9,14 +9,7 @@ // globals from the browser environment. "document": "readonly", "window": "readonly", - "il": "writable", - // globals from the mocha testing framework. - "beforeEach": "readonly", - "afterEach": "readonly", - "describe": "readonly", - "before": "readonly", - "after": "readonly", - "it": "readonly" + "il": "writable" }, // minified and bundled scripts are exempt from the // code-style. diff --git a/.github/workflows/checks.yml b/.github/workflows/checks.yml index 0a103e4a9f57..ba623ab3da0c 100755 --- a/.github/workflows/checks.yml +++ b/.github/workflows/checks.yml @@ -12,7 +12,7 @@ jobs: fail-fast: false matrix: php: [8.3, 8.4] - nodejs: [ 20.x ] + nodejs: [ 23.x ] steps: - name: Checkout code uses: actions/checkout@v2 @@ -44,7 +44,7 @@ jobs: GHRUN: "yes" - name: JS Unit Test - run: exit 0 # npm test + run: npm test env: GHRUN: "yes" diff --git a/.mocharc.json b/.mocharc.json deleted file mode 100755 index 41fb1c30763e..000000000000 --- a/.mocharc.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "require": [ - "@babel/register" - ], - "spec": [ - "components/ILIAS/**/tests/**/*.js" - ] -} diff --git a/Customizing/README.md b/Customizing/README.md deleted file mode 100755 index 315562dee557..000000000000 --- a/Customizing/README.md +++ /dev/null @@ -1,58 +0,0 @@ -# Customizing - - - -1. [Introduction](#introduction) -1. [System Language Changes](#system-language-changes) -1. [Skins and Styles](#skins-and-styles) -1. [Plugins](#plugins) - - - - -## Introduction - -This directory holds all customized files for this ILIAS installation. - -On the top level two directories may be created: `/Customizing/global` for -global changes and `/Customizing/clients` for changes that should be applied to -clients. - -The clients directory holds a subdirectory for each client: - -``` -/Customizing/clients/ -``` - -At the time being, only user agreements can be offered for clients! Customized -skins and languages are only supported globally. - - -## System Language Changes - -You may change terms used in the user interface of ILIAS. To do this, use the -same format as is used in the language files in directory `/lang`. Store the -values to be overwritten in files ending with `.lang.local` and put them into -the `/global/lang` directory. Client specific changes are not supported yet. - -``` -/global/lang/ilias_.lang.local -``` - -Example: - -``` -/global/lang/ilias_en.lang.local -``` - - -## Skins and Styles - -You find all information about how to create your own skin in the [Custom -Styles](/templates/Readme.md#custom-styles) documentation. - - -## Plugins - -Plugins are installed under `/global/plugins`. Each plugin should come with its -own documentation stating the exact target directory. diff --git a/Customizing/global/plugins/.gitkeep b/Customizing/global/plugins/.gitkeep deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/components/ILIAS/AccessControl/classes/Setup/class.ilAccessRBACSetupAgent.php b/components/ILIAS/AccessControl/classes/Setup/class.ilAccessRBACSetupAgent.php index 617ee0667dfb..b0339d03e1ef 100755 --- a/components/ILIAS/AccessControl/classes/Setup/class.ilAccessRBACSetupAgent.php +++ b/components/ILIAS/AccessControl/classes/Setup/class.ilAccessRBACSetupAgent.php @@ -18,27 +18,33 @@ declare(strict_types=1); -use ILIAS\Setup; +use ILIAS\AccessControl\Setup\AccessControl10DBUpdateSteps; +use ILIAS\Setup\Agent\NullAgent; +use ILIAS\Setup\Objective; use ILIAS\Setup\Config; +use ILIAS\Setup\Metrics\Storage; /** * @author Tim Schmitz */ -class ilAccessRBACSetupAgent extends Setup\Agent\NullAgent +class ilAccessRBACSetupAgent extends NullAgent { /** * @inheritdoc */ - public function getUpdateObjective(?Setup\Config $config = null): Setup\Objective + public function getUpdateObjective(Config $config = null): Objective { - return new ilDatabaseUpdateStepsExecutedObjective(new ilAccessRBACDeleteDbkSteps()); + return new ilDatabaseUpdateStepsExecutedObjective(new AccessControl10DBUpdateSteps()); } /** * @inheritdoc */ - public function getStatusObjective(Setup\Metrics\Storage $storage): Setup\Objective + public function getStatusObjective(Storage $storage): Objective { - return new ilDatabaseUpdateStepsMetricsCollectedObjective($storage, new ilAccessRBACDeleteDbkSteps()); + return new ilDatabaseUpdateStepsMetricsCollectedObjective( + $storage, + new AccessControl10DBUpdateSteps() + ); } } diff --git a/components/ILIAS/UICore/classes/class.ilUIFramework.php b/components/ILIAS/AccessControl/src/Setup/AccessControl10DBUpdateSteps.php old mode 100755 new mode 100644 similarity index 55% rename from components/ILIAS/UICore/classes/class.ilUIFramework.php rename to components/ILIAS/AccessControl/src/Setup/AccessControl10DBUpdateSteps.php index 4a498f4ebecc..12d1eeda28b7 --- a/components/ILIAS/UICore/classes/class.ilUIFramework.php +++ b/components/ILIAS/AccessControl/src/Setup/AccessControl10DBUpdateSteps.php @@ -18,23 +18,21 @@ declare(strict_types=1); -/** - * @author Alex Killing - * @author Thibeau Fuhrer - */ -class ilUIFramework +namespace ILIAS\AccessControl\Setup; + +class AccessControl10DBUpdateSteps implements \ilDatabaseUpdateSteps { - public const BOOTSTRAP_JS = "./assets/js/bootstrap.min.js"; + protected \ilDBInterface $db; - public static function init(?ilGlobalTemplateInterface $template = null): void + public function prepare(\ilDBInterface $db): void { - global $DIC; + $this->db = $db; + } - $template = $template ?? $DIC->ui()->mainTemplate(); - $template->addJavaScript( - self::BOOTSTRAP_JS, - true, - 0 - ); + public function step_1(): void + { + if (!$this->db->indexExistsByFields('rbac_templates', ['type', 'ops_id'])) { + $this->db->addIndex('rbac_templates', ['type', 'ops_id'], 'toi'); + } } } diff --git a/components/ILIAS/AdvancedMetaData/classes/Record/class.ilAdvancedMDRecordGUI.php b/components/ILIAS/AdvancedMetaData/classes/Record/class.ilAdvancedMDRecordGUI.php index 7339db61158b..e9fdf9a2ed08 100755 --- a/components/ILIAS/AdvancedMetaData/classes/Record/class.ilAdvancedMDRecordGUI.php +++ b/components/ILIAS/AdvancedMetaData/classes/Record/class.ilAdvancedMDRecordGUI.php @@ -341,7 +341,7 @@ public function writeEditForm(?int $a_obj_id = null, ?int $a_sub_id = null): boo */ private function parseSearch(): void { - // this is NOT used for the global search, see ilLuceneAdvancedSearchFields::getFormElement() + // this is NOT used for the global search // (so searchable flag is NOT relevant) // // current usage: wiki page element "[amd] page list" diff --git a/components/ILIAS/App/tests/RootFolderTest.php b/components/ILIAS/App/tests/RootFolderTest.php index 4430acd8fe16..cd5201237cb2 100755 --- a/components/ILIAS/App/tests/RootFolderTest.php +++ b/components/ILIAS/App/tests/RootFolderTest.php @@ -25,11 +25,9 @@ final class RootFolderTest extends TestCase { private const array ALLOWED_ROOT_FOLDER_FILES = [ - '.babelrc.json', '.eslintrc.json', '.gitignore', '.htaccess', - '.mocharc.json', '.phpunit.result.cache', 'captainhook.local.json', 'phpstan.local.neon', @@ -60,7 +58,6 @@ final class RootFolderTest extends TestCase 'artifacts', 'cli', 'components', - 'Customizing', 'docs', 'extern', 'lang', diff --git a/components/ILIAS/Authentication/Authentication.php b/components/ILIAS/Authentication/Authentication.php index 8390519017fc..414e42e6eb48 100644 --- a/components/ILIAS/Authentication/Authentication.php +++ b/components/ILIAS/Authentication/Authentication.php @@ -64,8 +64,8 @@ public function offsetUnset(mixed $offset): void ); $contribute[Component\Resource\PublicAsset::class] = fn() => - new Component\Resource\Endpoint($this, "sessioncheck.php"); + new Component\Resource\Endpoint($this, 'sessioncheck.php'); $contribute[Component\Resource\PublicAsset::class] = fn() => - new Component\Resource\ComponentJS($this, "session_reminder.js"); + new Component\Resource\ComponentJS($this, 'js/dist/SessionReminder.min.js'); } } diff --git a/components/ILIAS/Authentication/classes/Cron/class.ilAuthDestroyExpiredSessionsCron.php b/components/ILIAS/Authentication/classes/Cron/class.ilAuthDestroyExpiredSessionsCron.php index 1f2dda127417..20e7b429c4d0 100755 --- a/components/ILIAS/Authentication/classes/Cron/class.ilAuthDestroyExpiredSessionsCron.php +++ b/components/ILIAS/Authentication/classes/Cron/class.ilAuthDestroyExpiredSessionsCron.php @@ -50,7 +50,7 @@ public function getDescription(): string public function hasAutoActivation(): bool { - return true; + return false; } public function hasFlexibleSchedule(): bool @@ -58,9 +58,17 @@ public function hasFlexibleSchedule(): bool return true; } + public function getValidScheduleTypes(): array + { + return [ + \ILIAS\Cron\Job\Schedule\JobScheduleType::IN_MINUTES, + \ILIAS\Cron\Job\Schedule\JobScheduleType::IN_HOURS + ]; + } + public function getDefaultScheduleType(): \ILIAS\Cron\Job\Schedule\JobScheduleType { - return \ILIAS\Cron\Job\Schedule\JobScheduleType::IN_HOURS; + return \ILIAS\Cron\Job\Schedule\JobScheduleType::IN_MINUTES; } public function getDefaultScheduleValue(): ?int diff --git a/components/ILIAS/Authentication/classes/class.ilObjAuthSettingsGUI.php b/components/ILIAS/Authentication/classes/class.ilObjAuthSettingsGUI.php index 3cbc602c492b..07bb9d53c39b 100755 --- a/components/ILIAS/Authentication/classes/class.ilObjAuthSettingsGUI.php +++ b/components/ILIAS/Authentication/classes/class.ilObjAuthSettingsGUI.php @@ -181,7 +181,12 @@ private function authSettingsObject( $page_content = [ $this->ui_factory->panel()->standard( $this->lng->txt('auth_select'), - $this->ui_factory->legacy()->content($generalSettingsTpl->get()), + $this->ui_factory->legacy()->content(implode('', [ + $this->ui_renderer->render($this->ui_factory->messageBox()->info( + $this->lng->txt('auth_mode_default_change_info') + )), + $generalSettingsTpl->get() + ])), ) ]; diff --git a/components/ILIAS/Authentication/classes/class.ilSessionReminder.php b/components/ILIAS/Authentication/classes/class.ilSessionReminder.php index 78edf6cc64bc..373d48ba845e 100755 --- a/components/ILIAS/Authentication/classes/class.ilSessionReminder.php +++ b/components/ILIAS/Authentication/classes/class.ilSessionReminder.php @@ -26,9 +26,7 @@ class ilSessionReminder public const LEAD_TIME_DISABLED = 0; public const MIN_LEAD_TIME = 1; public const SUGGESTED_LEAD_TIME = 5; - private ClockInterface $clock; - private ilObjUser $user; - private ilSetting $settings; + private int $lead_time = self::SUGGESTED_LEAD_TIME; private int $expiration_time = 0; private int $current_time = 0; @@ -36,14 +34,10 @@ class ilSessionReminder private int $seconds_until_reminder = 0; public function __construct( - ilObjUser $user, - ClockInterface $clock, - ilSetting $settings + private ilObjUser $user, + private ClockInterface $clock, + private ilSetting $settings ) { - $this->user = $user; - $this->clock = $clock; - $this->settings = $settings; - $this->init(); } @@ -79,10 +73,8 @@ private function buildValidLeadTime(int $lead_time): int $min_value = self::MIN_LEAD_TIME; $max_value = $this->getMaxPossibleLeadTime(); - if ( - $lead_time !== self::LEAD_TIME_DISABLED && - ($lead_time < $min_value || $lead_time > $max_value) - ) { + if ($lead_time !== self::LEAD_TIME_DISABLED && + ($lead_time < $min_value || $lead_time > $max_value)) { $lead_time = self::SUGGESTED_LEAD_TIME; } diff --git a/components/ILIAS/Authentication/classes/class.ilSessionReminderCheck.php b/components/ILIAS/Authentication/classes/class.ilSessionReminderCheck.php index 6782d488ba2b..a021f2b998a5 100755 --- a/components/ILIAS/Authentication/classes/class.ilSessionReminderCheck.php +++ b/components/ILIAS/Authentication/classes/class.ilSessionReminderCheck.php @@ -27,57 +27,53 @@ class ilSessionReminderCheck { - private GlobalHttpState $http; - private Refinery $refinery; - private ilLanguage $lng; - private ilDBInterface $db; - private ilIniFile $clientIni; - private ilLogger $logger; - private ClockInterface $clock; - public function __construct( - GlobalHttpState $http, - Refinery $refinery, - ilLanguage $lng, - ilDBInterface $db, - ilIniFile $clientIni, - ilLogger $logger, - ClockInterface $utcClock, + private GlobalHttpState $http, + private Refinery $refinery, + private ilLanguage $lng, + private ilDBInterface $db, + private ilIniFile $client_ini, + private ilLogger $logger, + private ClockInterface $clock, + private ilSetting $settings ) { - $this->http = $http; - $this->refinery = $refinery; - $this->lng = $lng; - $this->db = $db; - $this->clientIni = $clientIni; - $this->logger = $logger; - $this->clock = $utcClock; } public function handle(): ResponseInterface { - $sessionIdHash = ilUtil::stripSlashes( + $hash = ilUtil::stripSlashes( $this->http->wrapper()->post()->retrieve( 'hash', $this->refinery->kindlyTo()->string() ) ); - $this->logger->debug('Session reminder call for session id hash: ' . $sessionIdHash); + $this->logger->debug('Session reminder call for session id hash: ' . $hash); // disable session writing and extension of expiration time ilSession::enableWebAccessWithoutSession(true); $response = ['remind' => false]; + $concat = $this->db->concat( + [ + ['usess.session_id'], + ['usess.user_id'], + ['od.create_date'] + ] + ); $res = $this->db->queryF( - 'SELECT expires, user_id, data FROM usr_session WHERE MD5(session_id) = %s', - ['text'], - [$sessionIdHash] + 'SELECT usess.expires, usess.user_id, usess.data ' . + 'FROM usr_session usess ' . + 'INNER JOIN object_data od ON od.obj_id = usess.user_id ' . + "WHERE SHA2($concat, 256) = %s", + [ilDBConstants::T_TEXT], + [$hash] ); $num = $this->db->numRows($res); - if (0 === $num) { + if ($num === 0) { $response['message'] = 'ILIAS could not determine the session data.'; return $this->toJsonResponse($response); } @@ -93,11 +89,12 @@ public function handle(): ResponseInterface return $this->toJsonResponse($response); } - $expiration_time = (int) $data['expires']; - if (null === $expiration_time) { + $expiration_time = $data['expires']; + if ($expiration_time === null) { $response['message'] = 'ILIAS could not determine the expiration time from the session data.'; return $this->toJsonResponse($response); } + $expiration_time = (int) $data['expires']; if ($this->isSessionAlreadyExpired($expiration_time)) { $response['message'] = 'The session is already expired. The client should have received a remind command before.'; @@ -111,7 +108,11 @@ public function handle(): ResponseInterface return $this->toJsonResponse($response); } - $session_reminder = ilSessionReminder::byLoggedInUser(); + $session_reminder = new ilSessionReminder( + $ilUser, + $this->clock, + $this->settings + ); $reminder_time = $expiration_time - ($session_reminder->getEffectiveLeadTime() * 60); if ($reminder_time > $this->clock->now()->getTimestamp()) { // session will expire in minutes @@ -133,7 +134,7 @@ public function handle(): ResponseInterface } $response = [ - 'extend_url' => './ilias.php?baseClass=ilDashboardGUI', + 'extend_url' => './ilias.php?baseClass=' . ilDashboardGUI::class, 'txt' => str_replace( "\\n", '%0A', @@ -141,7 +142,7 @@ public function handle(): ResponseInterface $this->lng->txt('session_reminder_alert'), ilDatePresentation::secondsToString($expiration_time - $this->clock->now()->getTimestamp()), $formatted_expiration_time, - $this->clientIni->readVariable('client', 'name') . ' | ' . ilUtil::_getHttpPath() + $this->client_ini->readVariable('client', 'name') . ' | ' . ilUtil::_getHttpPath() ) ), 'remind' => true diff --git a/components/ILIAS/Authentication/classes/class.ilSessionReminderGUI.php b/components/ILIAS/Authentication/classes/class.ilSessionReminderGUI.php index a274bb858483..7bf2ba7c199a 100755 --- a/components/ILIAS/Authentication/classes/class.ilSessionReminderGUI.php +++ b/components/ILIAS/Authentication/classes/class.ilSessionReminderGUI.php @@ -20,47 +20,44 @@ class ilSessionReminderGUI { - private ilSessionReminder $sessionReminder; - private ilGlobalTemplateInterface $page; - private ilLanguage $lng; - public function __construct( - ilSessionReminder $sessionReminder, - ilGlobalTemplateInterface $page, - ilLanguage $language + private readonly ilSessionReminder $session_reminder, + private readonly ilGlobalTemplateInterface $page, + private readonly ilLanguage $lng, + private readonly ilLoggerFactory $logger_factory ) { - $this->sessionReminder = $sessionReminder; - $this->page = $page; - $this->lng = $language; } public function populatePage(): void { - if (!$this->sessionReminder->isActive()) { + if (!$this->session_reminder->isActive()) { return; } - iljQueryUtil::initjQuery($this->page); - - $this->page->addJavaScript('assets/js/session_reminder.js'); + $this->page->addJavaScript('assets/js/SessionReminder.min.js'); $url = './sessioncheck.php?client_id=' . CLIENT_ID . '&lang=' . $this->lng->getLangKey(); - $devMode = defined('DEVMODE') && DEVMODE ? 1 : 0; - $clientId = defined('CLIENT_ID') ? CLIENT_ID : ''; - $sessionId = session_id(); - $sessionHash = md5($sessionId); + $client_id = defined('CLIENT_ID') ? CLIENT_ID : ''; + $hash = hash( + 'sha256', + implode('', [ + session_id(), + $this->session_reminder->getUser()->getId(), + $this->session_reminder->getUser()->getCreateDate() + ]) + ); + $log_level = $this->logger_factory->getSettings()->getLevelByComponent('auth'); $javascript = <<page->addOnLoadCode($javascript); } diff --git a/components/ILIAS/Authentication/resources/js/dist/SessionReminder.min.js b/components/ILIAS/Authentication/resources/js/dist/SessionReminder.min.js new file mode 100644 index 000000000000..1cf72f07e9f0 --- /dev/null +++ b/components/ILIAS/Authentication/resources/js/dist/SessionReminder.min.js @@ -0,0 +1,15 @@ +/** + * This file is part of ILIAS, a powerful learning management system + * published by ILIAS open source e-Learning e.V. + * + * ILIAS is licensed with the GPL-3.0, + * see https://www.gnu.org/licenses/gpl-3.0.en.html + * You should have received a copy of said license along with the + * source code, too. + * + * If this is not the case or you just want to try ILIAS, you'll find + * us at: + * https://www.ilias.de + * https://github.com/ILIAS-eLearning + */ +!function(e){"use strict";class t{#e;#t;#s;#i;#r;#n;constructor(e,t,s,i,r){this.#e=e,this.#i=s,this.#s=t,this.#n=i,this.#r=r;const n=this.#s.getItem(this.#r);this.#t=n?{...i,...n}:i,t.notifyOnUpdate(this.#r,(e=>{null!==e&&(this.#t={...this.#t,...e},this.#i.info(`State updated: ${JSON.stringify(this.#t)}`))}))}get(){return{...this.#t}}update(e){this.#t={...this.#t,...e},this.#s.setItem(this.#r,this.#t),this.#i.info(`State updated (incl. storage): ${JSON.stringify(this.#t)}`)}}class s{#e;#s;#i;#o;#a;#l={};constructor(e,t,s,i,r){this.#e=e,this.#s=t,this.#i=s,this.#o=i,this.#a=r,this.#e.addEventListener("storage",(e=>{if(e.key&&e.key.startsWith(`${this.#o}_${this.#a}_`)){const t=e.key.replace(`${this.#o}_${this.#a}_`,"");if(Object.prototype.hasOwnProperty.call(this.#l,t)){const s=JSON.parse(e.newValue),i=s?s.value:null;this.#i.info(`Storage event: Item ${e.key} changed to: ${e.newValue}`),this.#l[t].forEach((e=>{e(i)}))}else this.#i.info(`Storage event: Could not find subscriber for item: ${t}`)}})),this.gc()}notifyOnUpdate(e,t){Object.prototype.hasOwnProperty.call(this.#l,e)||(this.#l[e]=[]),this.#l[e].push(t)}setItem(e,t){const s={lastChange:(new Date).getTime(),value:t};this.#s.setItem(`${this.#o}_${this.#a}_${e}`,JSON.stringify(s))}getItem(e,t={}){const s=this.#s.getItem(`${this.#o}_${this.#a}_${e}`);if(null===s)return t;return JSON.parse(s).value||t}gc(){this.#e.setInterval((()=>{for(const[e,t]of Object.entries(this.#s))if(-1!==e.indexOf(this.#o)&&Object.prototype.hasOwnProperty.call(this.#s,e)){let s=t;"string"==typeof s&&(s=JSON.parse(s)),s.lastChange<(new Date).getTime()-864e5&&(this.#s.removeItem(e),this.#i.debug(`Garbage collected: ${e}`))}}),6e4)}}class i{#e;#c;#h;#g=null;#d;constructor(e,t,s){this.#e=e,this.#c=t,this.#h=s,this.#d=!1,this.#u()}#u(){this.#g=this.#e.setInterval((()=>this.#f()),this.#h)}stop(){this.#g&&(this.#e.clearInterval(this.#g),this.#g=null)}#f(){if(!this.#d)try{this.#d=!0,this.#c()}finally{this.#d=!1}}}class r{#b;#t;#i;#p;#m;#e;constructor(e,t,s,i,r){this.#b=e,this.#t=t,this.#i=s,this.#m=i,this.#e=r}run(){this.#e.addEventListener("beforeunload",(()=>{this.#t.update({status:"unlocked"}),this.#i.info("Unlocked session reminder on browser's unload event")})),this.#i.info("Session reminder started"),this.#t.get().hash!==this.#b.hash&&(this.#t.update({activation:"enabled",status:"unlocked",hash:this.#b.hash}),this.#i.info("Session cookie changed after new login or session reminder initially started for current session: Released lock and enabled reminder.")),this.#p=new this.#m(this.#e,this.#c.bind(this),1e3*this.#b.frequency),this.#i.info("Started periodical executer")}#c(){const e=this.#t.get();if("disabled"===e.activation||"locked"===e.status)return void this.#i.info("Session reminder disabled or locked for current user session");this.#t.update({status:"locked"}),this.#i.info("Session reminder locked"),this.#p.stop(),this.#i.info("Stopped periodical executer");const t=new FormData;t.append("hash",this.#b.hash),fetch(this.#b.url,{method:"POST",body:t}).then((e=>e.json())).then((e=>{try{if("object"!=typeof e||null===e||Array.isArray(e)||void 0===JSON.stringify(e))throw new Error("The response body seems not to be valid JSON")}catch(e){throw new Error("Invalid response format",{cause:e})}if(e.message&&"string"==typeof e.message&&this.#i.info(e.message),!e.remind)return void this.#i.info("Reminder of session expiration not necessary: Session reminder unlocked");if(!this.#e.confirm(e.txt))return this.#t.update({activation:"disabled",status:"unlocked"}),void this.#i.info("User disabled reminder for current session: Session reminder disabled but unlocked");fetch(e.extend_url,{method:"GET"}).then((()=>(this.#i.info("Session extended successfully"),new Promise((e=>{e(!0)}))))).catch((e=>{this.#i.error("Fetch error occurred:",e)}))})).catch((e=>{this.#i.error("Fetch error occurred:",e)})).finally((()=>{this.#t.update({status:"unlocked"}),this.#i.info("Unlocked session reminder"),this.#p=new this.#m(this.#e,this.#c.bind(this),1e3*this.#b.frequency),this.#i.info("Restarted periodical executer")}))}}class n{static defineLogLevel(e,t){return{value:e,name:t}}static TRACE=n.defineLogLevel(50,"TRACE");static DEBUG=n.defineLogLevel(100,"DEBUG");static INFO=n.defineLogLevel(200,"INFO");static NOTICE=n.defineLogLevel(250,"NOTICE");static WARNING=n.defineLogLevel(300,"WARN");static ERROR=n.defineLogLevel(400,"ERROR");static CRITICAL=n.defineLogLevel(500,"CRITICAL");static ALERT=n.defineLogLevel(550,"ALERT");static EMERGENCY=n.defineLogLevel(600,"EMERGENCY");static OFF=n.defineLogLevel(1e3,"OFF");static LEVELS=[n.TRACE,n.DEBUG,n.INFO,n.NOTICE,n.WARNING,n.ERROR,n.CRITICAL,n.ALERT,n.EMERGENCY,n.OFF];#w;#E;constructor(e,t=n.DEBUG){this.#w=e,this.setLevel(t)}setLevel(e){e&&"value"in e&&(this.#E=e)}getLevel(){return this.#E}enabledFor(e){return e.value>=this.#E.value}logMessage(e,t){if(!this.enabledFor(e))return;let s=t,[i,...r]=s;"string"==typeof i&&(i=`SessionReminder | ${i}`,s=[i,...r]),e.name.toLowerCase()in this.#w?this.#w[e.name.toLowerCase()](...s):this.#w.error(...s)}trace(...e){this.logMessage(n.TRACE,e)}debug(...e){this.logMessage(n.DEBUG,e)}info(...e){this.logMessage(n.INFO,e)}notice(...e){this.logMessage(n.NOTICE,e)}warn(...e){this.logMessage(n.WARNING,e)}error(...e){this.logMessage(n.ERROR,e)}critical(...e){this.logMessage(n.CRITICAL,e)}alert(...e){this.logMessage(n.ALERT,e)}emergency(...e){this.logMessage(n.EMERGENCY,e)}log(...e){this.info(...e)}static levelForNumericValue(e){if(Number.isNaN(e))return n.DEBUG;for(const t of n.LEVELS)if(Number.parseInt(e,10)===t.value)return t;return n.DEBUG}}e.SessionReminder=e.SessionReminder||(()=>{let e=null;return{init(o,a,l){if(e)return e.logger?.warning("SessionReminder init() called again; already running."),e;const c={url:"",clientId:"",hash:"",frequency:60,logLevel:n.INFO.value},h=Object.fromEntries(Object.entries({...c,...o}).filter((([e])=>e in c))),g=new n(l,n.levelForNumericValue(h.logLevel));"localStorage"in a||g.warn("No 'localStorage' support.");const d="localStorage"in a?a.localStorage:(()=>{const e={};return{removeItem:t=>{delete e[t]},getItem:t=>e[t]??null,setItem:(t,s)=>{e[t]=s}}})(),u=new s(a,d,g,"il_sr",h.clientId),f=new t(a,u,g,{activation:"disabled",status:"unlocked",hash:""},"state");return e=new r(h,f,g,i,a),e},run(){if(!e)throw new Error("SessionReminder not initialized. Call init() first.");e.run(),this.run=()=>{e.logger?.warning("SessionReminder run() called again; already running.")}}}})()}(il); diff --git a/components/ILIAS/Authentication/resources/js/rollup.config.js b/components/ILIAS/Authentication/resources/js/rollup.config.js new file mode 100644 index 000000000000..556110e75d63 --- /dev/null +++ b/components/ILIAS/Authentication/resources/js/rollup.config.js @@ -0,0 +1,45 @@ +/** + * This file is part of ILIAS, a powerful learning management system + * published by ILIAS open source e-Learning e.V. + * + * ILIAS is licensed with the GPL-3.0, + * see https://www.gnu.org/licenses/gpl-3.0.en.html + * You should have received a copy of said license along with the + * source code, too. + * + * If this is not the case or you just want to try ILIAS, you'll find + * us at: + * https://www.ilias.de + * https://github.com/ILIAS-eLearning + * + ******************************************************************** */ + +import terser from '@rollup/plugin-terser'; +import copyright from '../../../../../scripts/Copyright-Checker/copyright.js'; +import preserveCopyright from '../../../../../scripts/Copyright-Checker/preserveCopyright.js'; + +export default [ + { + input: './src/index.js', + output: { + file: './dist/SessionReminder.min.js', + format: 'iife', + banner: copyright, + plugins: [ + terser({ + format: { + comments: preserveCopyright, + }, + }), + ], + globals: { + il: 'il', + window: 'window', + console: 'console', + localStorage: 'localStorage', + confirm: 'confirm', + }, + }, + external: ['il', 'window', 'console', 'localStorage', 'confirm'], + }, +]; diff --git a/components/ILIAS/Authentication/resources/js/src/Logger.js b/components/ILIAS/Authentication/resources/js/src/Logger.js new file mode 100644 index 000000000000..d006b02dc935 --- /dev/null +++ b/components/ILIAS/Authentication/resources/js/src/Logger.js @@ -0,0 +1,194 @@ +/** + * This file is part of ILIAS, a powerful learning management system + * published by ILIAS open source e-Learning e.V. + * + * ILIAS is licensed with the GPL-3.0, + * see https://www.gnu.org/licenses/gpl-3.0.en.html + * You should have received a copy of said license along with the + * source code, too. + * + * If this is not the case or you just want to try ILIAS, you'll find + * us at: + * https://www.ilias.de + * https://github.com/ILIAS-eLearning + * + ******************************************************************** */ + +/** + * @typedef {Object} LogLevel + * @property {number} value + * @property {string} name + */ + +export default class Logger { + /** + * @param {number} value - The code of the log level + * @param {string} name - The readable log level name + * @returns {LogLevel} + */ + static defineLogLevel(value, name) { + return { value, name }; + } + + static TRACE = Logger.defineLogLevel(50, 'TRACE'); + + static DEBUG = Logger.defineLogLevel(100, 'DEBUG'); + + static INFO = Logger.defineLogLevel(200, 'INFO'); + + static NOTICE = Logger.defineLogLevel(250, 'NOTICE'); + + static WARNING = Logger.defineLogLevel(300, 'WARN'); + + static ERROR = Logger.defineLogLevel(400, 'ERROR'); + + static CRITICAL = Logger.defineLogLevel(500, 'CRITICAL'); + + static ALERT = Logger.defineLogLevel(550, 'ALERT'); + + static EMERGENCY = Logger.defineLogLevel(600, 'EMERGENCY'); + + static OFF = Logger.defineLogLevel(1000, 'OFF'); + + static LEVELS = [ + Logger.TRACE, Logger.DEBUG, Logger.INFO, Logger.NOTICE, + Logger.WARNING, Logger.ERROR, Logger.CRITICAL, Logger.ALERT, + Logger.EMERGENCY, Logger.OFF, + ]; + + /** + * @type {Console} + */ + #consoleObj; + + /** + * @type {LogLevel} + */ + #level; + + /** + * @param {Console} consoleObj - The console object for logging. + * @param {LogLevel} level - The logging level. + */ + constructor(consoleObj, level = Logger.DEBUG) { + this.#consoleObj = consoleObj; + this.setLevel(level); + } + + /** + * @param {LogLevel} level + */ + setLevel(level) { + if (level && 'value' in level) { + this.#level = level; + } + } + + /** + * @returns {LogLevel} + */ + getLevel() { + return this.#level; + } + + /** + * @param {LogLevel} level + * @returns {boolean} + */ + enabledFor(level) { + return level.value >= this.#level.value; + } + + /** + * + * @param {LogLevel} level + * @param {...*} args + */ + logMessage(level, args) { + if (!this.enabledFor(level)) { + return; + } + + let argumentList = args; + + let [firstElement, ...rest] = argumentList; + if (typeof firstElement === 'string') { + firstElement = `SessionReminder | ${firstElement}`; + argumentList = [firstElement, ...rest]; + } + + if (level.name.toLowerCase() in this.#consoleObj) { + this.#consoleObj[level.name.toLowerCase()](...argumentList); + } else { + this.#consoleObj.error(...argumentList); + } + } + + /** + * @param {...*} args + */ + trace(...args) { this.logMessage(Logger.TRACE, args); } + + /** + * @param {...*} args + */ + debug(...args) { this.logMessage(Logger.DEBUG, args); } + + /** + * @param {...*} args + */ + info(...args) { this.logMessage(Logger.INFO, args); } + + /** + * @param {...*} args + */ + notice(...args) { this.logMessage(Logger.NOTICE, args); } + + /** + * @param {...*} args + */ + warn(...args) { this.logMessage(Logger.WARNING, args); } + + /** + * @param {...*} args + */ + error(...args) { this.logMessage(Logger.ERROR, args); } + + /** + * @param {...*} args + */ + critical(...args) { this.logMessage(Logger.CRITICAL, args); } + + /** + * @param {...*} args + */ + alert(...args) { this.logMessage(Logger.ALERT, args); } + + /** + * @param {...*} args + */ + emergency(...args) { this.logMessage(Logger.EMERGENCY, args); } + + /** + * @param {...*} args + */ + log(...args) { this.info(...args); } + + /** + * @param {number} numericLevel - The log level to be used (e.g. provided from backend config) + * @returns {LogLevel} + */ + static levelForNumericValue(numericLevel) { + if (Number.isNaN(numericLevel)) { + return Logger.DEBUG; + } + + for (const level of Logger.LEVELS) { + if (Number.parseInt(numericLevel, 10) === level.value) { + return level; + } + } + + return Logger.DEBUG; + } +} diff --git a/components/ILIAS/Authentication/resources/js/src/PeriodicalExecuter.js b/components/ILIAS/Authentication/resources/js/src/PeriodicalExecuter.js new file mode 100644 index 000000000000..5e263f1b1d7b --- /dev/null +++ b/components/ILIAS/Authentication/resources/js/src/PeriodicalExecuter.js @@ -0,0 +1,81 @@ +/** + * This file is part of ILIAS, a powerful learning management system + * published by ILIAS open source e-Learning e.V. + * + * ILIAS is licensed with the GPL-3.0, + * see https://www.gnu.org/licenses/gpl-3.0.en.html + * You should have received a copy of said license along with the + * source code, too. + * + * If this is not the case or you just want to try ILIAS, you'll find + * us at: + * https://www.ilias.de + * https://github.com/ILIAS-eLearning + * + ******************************************************************** */ + +/** + * @callback NoArgsCallback + * @returns {void} + */ + +export default class PeriodicalExecuter { + /** + * @type {Window} + */ + #windowObj; + + /** + * @type {NoArgsCallback} + */ + #callback; + + /** + * @type {number} + */ + #frequency; + + /** + * @type {number | null} + */ + #timer = null; + + /** + * @type {boolean} + */ + #currentlyExecuting; + + /** + * @param {Window} windowObj - The global window object. + * @param {NoArgsCallback} callback - The function to execute periodically. + * @param {number} frequency - The execution interval in milliseconds. + */ + constructor(windowObj, callback, frequency) { + this.#windowObj = windowObj; + this.#callback = callback; + this.#frequency = frequency; + this.#currentlyExecuting = false; + this.#registerCallback(); + } + + #registerCallback() { + this.#timer = this.#windowObj.setInterval(() => this.#onTimerEvent(), this.#frequency); + } + + stop() { + if (!this.#timer) return; + this.#windowObj.clearInterval(this.#timer); + this.#timer = null; + } + + #onTimerEvent() { + if (!this.#currentlyExecuting) { + try { + this.#currentlyExecuting = true; + this.#callback(); + } finally { + this.#currentlyExecuting = false; + } + } + } +} diff --git a/components/ILIAS/Authentication/resources/js/src/SessionReminder.js b/components/ILIAS/Authentication/resources/js/src/SessionReminder.js new file mode 100644 index 000000000000..c6e01dcd3cfa --- /dev/null +++ b/components/ILIAS/Authentication/resources/js/src/SessionReminder.js @@ -0,0 +1,168 @@ +/** + * This file is part of ILIAS, a powerful learning management system + * published by ILIAS open source e-Learning e.V. + * + * ILIAS is licensed with the GPL-3.0, + * see https://www.gnu.org/licenses/gpl-3.0.en.html + * You should have received a copy of said license along with the + * source code, too. + * + * If this is not the case or you just want to try ILIAS, you'll find + * us at: + * https://www.ilias.de + * https://github.com/ILIAS-eLearning + * + ******************************************************************** */ + +export default class SessionReminder { + /** + * @type {Object} + */ + #options; + + /** + * @type {State} + */ + #state; + + /** + * @type {Logger} + */ + #logger; + + /** + * @type {PeriodicalExecuter} + */ + #executer; + + /** + * @type {typeof PeriodicalExecuter} + */ + #periodicalExecuter; + + /** + * @type {Window} + */ + #windowObj; + + /** + * @param {Object} options - Configuration options. + * @param {State} state - The state. + * @param {Logger} logger - The logger. + * @param {typeof PeriodicalExecuter} PeriodicalExecuter - Class for periodic execution. + * @param {Window} windowObj - The global window object. + */ + constructor( + options, + state, + logger, + PeriodicalExecuter, + windowObj, + ) { + this.#options = options; + this.#state = state; + this.#logger = logger; + this.#periodicalExecuter = PeriodicalExecuter; + this.#windowObj = windowObj; + } + + run() { + this.#windowObj.addEventListener('beforeunload', () => { + this.#state.update({ status: 'unlocked' }); + this.#logger.info("Unlocked session reminder on browser's unload event"); + }); + + this.#logger.info('Session reminder started'); + + if (this.#state.get().hash !== this.#options.hash) { + this.#state.update({ activation: 'enabled', status: 'unlocked', hash: this.#options.hash }); + this.#logger.info( + 'Session cookie changed after new login or session reminder initially started ' + + 'for current session: Released lock and enabled reminder.', + ); + } + + this.#executer = new this.#periodicalExecuter( + this.#windowObj, + this.#callback.bind(this), + this.#options.frequency * 1000, + ); + this.#logger.info('Started periodical executer'); + } + + #callback() { + const state = this.#state.get(); + if (state.activation === 'disabled' || state.status === 'locked') { + this.#logger.info('Session reminder disabled or locked for current user session'); + return; + } + + this.#state.update({ status: 'locked' }); + this.#logger.info('Session reminder locked'); + this.#executer.stop(); + this.#logger.info('Stopped periodical executer'); + + const formData = new FormData(); + formData.append('hash', this.#options.hash); + + fetch(this.#options.url, { + method: 'POST', + body: formData, + }) + .then((response) => response.json()) + .then((data) => { + try { + if (typeof data !== 'object' + || data === null + || Array.isArray(data) + || JSON.stringify(data) === undefined) { + throw new Error('The response body seems not to be valid JSON'); + } + } catch (e) { + throw new Error('Invalid response format', { cause: e }); + } + + if (data.message && typeof data.message === 'string') { + this.#logger.info(data.message); + } + + if (!data.remind) { + this.#logger.info('Reminder of session expiration not necessary: Session reminder unlocked'); + return; + } + + const extend = this.#windowObj.confirm(data.txt); + if (!extend) { + this.#state.update({ activation: 'disabled', status: 'unlocked' }); + this.#logger.info('User disabled reminder for current session: Session reminder disabled but unlocked'); + return; + } + + fetch(data.extend_url, { method: 'GET' }) + .then(() => { + this.#logger.info('Session extended successfully'); + return new Promise( + (resolve) => { + resolve(true); + }, + ); + }) + .catch((error) => { + this.#logger.error('Fetch error occurred:', error); + }); + }) + .catch((error) => { + this.#logger.error('Fetch error occurred:', error); + }) + .finally(() => { + this.#state.update({ status: 'unlocked' }); + this.#logger.info('Unlocked session reminder'); + this.#executer = new this.#periodicalExecuter( + this.#windowObj, + this.#callback.bind(this), + this.#options.frequency * 1000, + ); + this.#logger.info('Restarted periodical executer'); + }); + } +} diff --git a/components/ILIAS/Authentication/resources/js/src/State.js b/components/ILIAS/Authentication/resources/js/src/State.js new file mode 100644 index 000000000000..574a5730781d --- /dev/null +++ b/components/ILIAS/Authentication/resources/js/src/State.js @@ -0,0 +1,108 @@ +/** + * This file is part of ILIAS, a powerful learning management system + * published by ILIAS open source e-Learning e.V. + * + * ILIAS is licensed with the GPL-3.0, + * see https://www.gnu.org/licenses/gpl-3.0.en.html + * You should have received a copy of said license along with the + * source code, too. + * + * If this is not the case or you just want to try ILIAS, you'll find + * us at: + * https://www.ilias.de + * https://github.com/ILIAS-eLearning + * + ******************************************************************** */ + +/** + * @typedef {Object} SessionState + * @property {'disabled'|'enabled'} activation + * @property {'locked'|'unlocked'} status + * @property {string} hash + */ + +/** + * @typedef {Object} PartialSessionState + * @property {'disabled'|'enabled'} [activation] + * @property {'locked'|'unlocked'} [status] + * @property {string} [hash] + */ + +export default class State { + /** + * @type {Window} + */ + #windowObj; + + /** + * @type {SessionState} + */ + #state; + + /** + * @type {Storage} + */ + #storage; + + /** + * @type {Logger} + */ + #logger; + + /** + * @type {string} + */ + #key; + + /** + * @type {SessionState + */ + #initialState; + + /** + * + * @param {Window} windowObj - The global window object. + * @param {Storage} storage - The storrage mechanism (e.g., localStorage). + * @param {Logger} logger - The logger. + * @param {SessionState} initialState - The initial state to be stored. + * @param {string} key - The key under which the state is stored. + */ + constructor(windowObj, storage, logger, initialState, key) { + this.#windowObj = windowObj; + this.#logger = logger; + this.#storage = storage; + this.#initialState = initialState; + this.#key = key; + + const saved = this.#storage.getItem(this.#key); + this.#state = saved ? { ...initialState, ...saved } : initialState; + + storage.notifyOnUpdate( + this.#key, + (updates) => { + if (updates !== null) { + this.#state = { ...this.#state, ...updates }; + this.#logger.info(`State updated: ${JSON.stringify(this.#state)}`); + } + }, + ); + } + + /** + * Returns the current state. + * @returns {SessionState} + */ + get() { + return { ...this.#state }; + } + + /** + * + * @param {PartialSessionState} updates + */ + update(updates) { + this.#state = { ...this.#state, ...updates }; + this.#storage.setItem(this.#key, this.#state); + this.#logger.info(`State updated (incl. storage): ${JSON.stringify(this.#state)}`); + } +} diff --git a/components/ILIAS/Authentication/resources/js/src/Storage.js b/components/ILIAS/Authentication/resources/js/src/Storage.js new file mode 100644 index 000000000000..876af6652a13 --- /dev/null +++ b/components/ILIAS/Authentication/resources/js/src/Storage.js @@ -0,0 +1,163 @@ +/** + * This file is part of ILIAS, a powerful learning management system + * published by ILIAS open source e-Learning e.V. + * + * ILIAS is licensed with the GPL-3.0, + * see https://www.gnu.org/licenses/gpl-3.0.en.html + * You should have received a copy of said license along with the + * source code, too. + * + * If this is not the case or you just want to try ILIAS, you'll find + * us at: + * https://www.ilias.de + * https://github.com/ILIAS-eLearning + * + ******************************************************************** */ + +/** + * @typedef {Object} LogLevel + * @property {number} value + * @property {string} name + */ + +/** + * @callback GenericCallback + * @param {*} value + * @returns {void} + */ + +/** + * @typedef {Object.} Subscribers + */ + +export default class Storage { + /** + * @type {Window} + */ + #windowObj; + + /** + * @type {Storage} + */ + #storage; + + /** + * @type {Logger} + */ + #logger; + + /** + * @type {string} + */ + #namespace; + + /** + * @type {string} + */ + #prefix; + + /** + * @type {Subscribers} + */ + #subscribers = {}; + + /** + * @param {Window} windowObj - The global window object. + * @param {Storage} storage - The storage mechanism (e.g., localStorage). + * @param {Logger} logger - The logger. + * @param {string} namespace - The namespace for keys. + * @param {string} prefix - The prefix for keys. + */ + constructor(windowObj, storage, logger, namespace, prefix) { + this.#windowObj = windowObj; + this.#storage = storage; + this.#logger = logger; + this.#namespace = namespace; + this.#prefix = prefix; + + this.#windowObj.addEventListener('storage', (event) => { + if (event.key && event.key.startsWith(`${this.#namespace}_${this.#prefix}_`)) { + const key = event.key.replace(`${this.#namespace}_${this.#prefix}_`, ''); + + if (Object.prototype.hasOwnProperty.call(this.#subscribers, key)) { + const item = JSON.parse(event.newValue); + const value = item ? item.value : null; + + this.#logger.info(`Storage event: Item ${event.key} changed to: ${event.newValue}`); + + this.#subscribers[key].forEach((callback) => { + callback(value); + }); + } else { + this.#logger.info(`Storage event: Could not find subscriber for item: ${key}`); + } + } + }); + + this.gc(); + } + + /** + * @param {string} key - The key to listen for a change. + * @param {GenericCallback} callback - A callback function to be executed when the value changes. + */ + notifyOnUpdate(key, callback) { + if (!Object.prototype.hasOwnProperty.call(this.#subscribers, key)) { + this.#subscribers[key] = []; + } + + this.#subscribers[key].push(callback); + } + + /** + * + * @param {string} key - The keyword to store the value under. + * @param {object} value - The value to store. + */ + + setItem(key, value) { + const item = { + lastChange: (new Date()).getTime(), + value, + }; + + this.#storage.setItem(`${this.#namespace}_${this.#prefix}_${key}`, JSON.stringify(item)); + } + + /** + * Retrieves the stored value. + * @param {string} key - The keyword to store the value under. + * @param {object} defaultValue - A default valur. + * @returns {object} The parsed state object. + */ + getItem(key, defaultValue = {}) { + const item = this.#storage.getItem(`${this.#namespace}_${this.#prefix}_${key}`); + if (item === null) { + return defaultValue; + } + + const parseItem = JSON.parse(item); + + return parseItem.value || defaultValue; + } + + gc() { + this.#windowObj.setInterval(() => { + for (const [key, value] of Object.entries(this.#storage)) { + if (key.indexOf(this.#namespace) !== -1 + && Object.prototype.hasOwnProperty.call(this.#storage, key) + ) { + let item = value; + if (typeof item === 'string') { + item = JSON.parse(item); + } + + if (item.lastChange < (new Date()).getTime() - (24 * 60 * 60 * 1000)) { + this.#storage.removeItem(key); + this.#logger.debug(`Garbage collected: ${key}`); + } + } + } + }, (60 * 1000)); + } +} diff --git a/components/ILIAS/Authentication/resources/js/src/index.js b/components/ILIAS/Authentication/resources/js/src/index.js new file mode 100644 index 000000000000..e1ce27863331 --- /dev/null +++ b/components/ILIAS/Authentication/resources/js/src/index.js @@ -0,0 +1,108 @@ +/** + * This file is part of ILIAS, a powerful learning management system + * published by ILIAS open source e-Learning e.V. + * + * ILIAS is licensed with the GPL-3.0, + * see https://www.gnu.org/licenses/gpl-3.0.en.html + * You should have received a copy of said license along with the + * source code, too. + * + * If this is not the case or you just want to try ILIAS, you'll find + * us at: + * https://www.ilias.de + * https://github.com/ILIAS-eLearning + * + ******************************************************************** */ + +import il from 'il'; +import State from './State.js'; +import Storage from './Storage.js'; +import PeriodicalExecuter from './PeriodicalExecuter.js'; +import SessionReminder from './SessionReminder.js'; +import Logger from './Logger.js'; + +il.SessionReminder = il.SessionReminder || (() => { + let instance = null; + + return { + init(serverOptions, windowObj, consoleObj) { + if (instance) { + instance.logger?.warning('SessionReminder init() called again; already running.'); + return instance; + } + + const defaultOptions = { + url: '', + clientId: '', + hash: '', + frequency: 60, + logLevel: Logger.INFO.value, + }; + + const options = Object.fromEntries( + Object.entries({ ...defaultOptions, ...serverOptions }) + .filter(([key]) => key in defaultOptions), + ); + + const logger = new Logger( + consoleObj, + Logger.levelForNumericValue(options.logLevel), + ); + + if (!('localStorage' in windowObj)) { + logger.warn("No 'localStorage' support."); + } + + const ls = 'localStorage' in windowObj ? windowObj.localStorage : (() => { + const items = {}; + return { + removeItem: (key) => { delete items[key]; }, + getItem: (key) => items[key] ?? null, + setItem: (key, value) => { items[key] = value; }, + }; + })(); + + const storage = new Storage( + windowObj, + ls, + logger, + 'il_sr', + options.clientId, + ); + + const state = new State( + windowObj, + storage, + logger, + { + activation: 'disabled', + status: 'unlocked', + hash: '', + }, + 'state', + ); + + instance = new SessionReminder( + options, + state, + logger, + PeriodicalExecuter, + windowObj, + ); + + return instance; + }, + + run() { + if (!instance) { + throw new Error('SessionReminder not initialized. Call init() first.'); + } + + instance.run(); + + this.run = () => { + instance.logger?.warning('SessionReminder run() called again; already running.'); + }; + }, + }; +})(); diff --git a/components/ILIAS/Authentication/resources/session_reminder.js b/components/ILIAS/Authentication/resources/session_reminder.js deleted file mode 100644 index 1a7090119690..000000000000 --- a/components/ILIAS/Authentication/resources/session_reminder.js +++ /dev/null @@ -1,341 +0,0 @@ -(function ($) { - "use strict"; - - class Cookies { - /** - * - * @type {{secure: bool, SameSite: string, expires: number|Date, path: string, domain: string}} - */ - static #defaultParameters = { - secure: window.location.protocol === "https:", - SameSite: "Lax" - }; - - /** - * - * @param {string} value - * @returns {string} - */ - static #readValue(value) { - if (value[0] === '"') { - value = value.slice(1, -1) - } - - return value.replace(/(%[\dA-F]{2})+/gi, decodeURIComponent); - }; - - /** - * - * @param {string} value - * @returns {string} - */ - static #writeValue(value) { - return encodeURIComponent(value).replace( - /%(2[346BF]|3[AC-F]|40|5[BDE]|60|7[BCD])/g, - decodeURIComponent - ); - }; - - /** - * - * @param {string} name - * @returns {string} - */ - static #encodeName(name) { - name = encodeURIComponent(name) - .replace(/%(2[346B]|5E|60|7C)/g, decodeURIComponent) - .replace(/[()]/g, escape)//https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/escape - - return name; - }; - - /** - * - * @param {{secure: bool, SameSite: string, expires: number|Date, path: string, domain: string}} attributes - * @returns {string} - */ - static #attributesToString(attributes) { - let text = ""; - - for (const attributeName in attributes) { - if (!attributes.hasOwnProperty(attributeName) || !attributes[attributeName]) { - continue; - } - - if (attributeName === "domain") { - text += "; domain=" + attributes[attributeName].split(";")[0]; - } - - if (attributeName === "path") { - text += "; path=" + attributes[attributeName].split(";")[0]; - } - - if (attributeName === "expires" && attributes[attributeName] instanceof Date) { - text += "; expires=" + attributes[attributeName].toUTCString(); - } - - if (attributeName === "SameSite") { - text += "; SameSite=" + attributes[attributeName].split(";")[0]; - } - - if (attributeName === "secure" && attributes[attributeName] === true) { - text += "; secure"; - } - } - - return text; - }; - - /** - * - * @param {string} name - * @param {string} value - * @param {{secure: bool, SameSite: string, expires: number|Date, path: string, domain: string}} attributes - */ - static set(name, value, attributes) { - attributes = Object.assign({}, Cookies.#defaultParameters, attributes); - - if (typeof attributes.expires === "number") { - attributes.expires = new Date(Date.now() + attributes.expires * 864e5) - } - - document.cookie = name + "=" + Cookies.#writeValue(value) + Cookies.#attributesToString( - attributes); - } - - /** - * - * @param {string} name - * @returns {string|undefined} - */ - static get(name) { - const cookies = document.cookie ? document.cookie.split("; ") : []; - let cookieJar = {}; - - for (let i = 0; i < cookies.length; i++) { - const parts = cookies[i].split("="), - cookie = parts.slice(1).join("="); - - try { - cookieJar[decodeURIComponent(parts[0])] = Cookies.#readValue( - cookie, - decodeURIComponent(parts[0]) - ); - } - catch (e) { - } - } - - return cookieJar[name]; - } - - /** - * - * @param {string} name - */ - remove(name) { - Cookies.set( - name, - '', - { expires: -1 } - ); - } - } - - class PeriodicalExecuter { - #callback; - #frequency; - #timer; - #currentlyExecuting; - - /** - * @param {function} callback - * @param {number} frequency - */ - constructor(callback, frequency) { - this.#callback = callback; - this.#frequency = frequency; - this.#currentlyExecuting = false; - this.#registerCallback(); - } - - #registerCallback() { - this.#timer = setInterval(() => { - this.#onTimerEvent() - }, this.#frequency); - } - - #execute() { - this.#callback(this); - } - - stop() { - if (!this.#timer) return; - clearInterval(this.#timer); - this.#timer = null; - } - - #onTimerEvent() { - if (!this.#currentlyExecuting) { - try { - this.#currentlyExecuting = true; - this.#execute(); - } finally { - this.#currentlyExecuting = false; - } - } - } - } - - $.fn.ilSessionReminder = function (method) { - let session_reminder_executer = null, - session_reminder_locked = false; - - const internals = { - log: function (message) { - if (this.properties.debug) { - console.log(message); - } - }, - properties: {} - }; - - const ilSessionReminderCallback = function () { - const properties = internals.properties, - cookie_prefix = "il_sr_" + properties.client_id + "_"; - - if (Cookies.get(cookie_prefix + "activation") == "disabled" || - Cookies.get(cookie_prefix + "status") == "locked") { - internals.log("Session reminder disabled or locked for current user session"); - return; - } - - Cookies.set(cookie_prefix + "status", "locked"); - session_reminder_locked = true; - internals.log("Session reminder locked"); - $.ajax({ - url: properties.url, - dataType: 'json', - type: 'POST', - data: { - hash: properties.hash - }, - success: function (response) { - if (response.message && typeof response.message == "string") { - internals.log(response.message); - } - - if (response.remind) { - session_reminder_executer.stop(); - - const extend = confirm(unescape(response.txt)); - - if (extend == true) { - $.ajax({ - url: response.extend_url, - type: 'GET', - success: function () { - session_reminder_executer = new PeriodicalExecuter( - ilSessionReminderCallback, - properties.frequency * 1000 - ); - Cookies.set(cookie_prefix + "status", "unlocked"); - session_reminder_locked = false; - internals.log("User extends session: Session reminder unlocked"); - } - }).fail(function () { - session_reminder_executer = new PeriodicalExecuter( - ilSessionReminderCallback, - properties.frequency * 1000 - ); - Cookies.set(cookie_prefix + "status", "unlocked"); - session_reminder_locked = false; - internals.log("XHR Failure: Session reminder unlocked"); - }); - } else { - Cookies.set(cookie_prefix + "activation", "disabled"); - Cookies.set(cookie_prefix + "status", "unlocked"); - session_reminder_locked = false; - internals.log( - "User disabled reminder for current session: Session reminder disabled but unlocked"); - session_reminder_executer = new PeriodicalExecuter( - ilSessionReminderCallback, - properties.frequency * 1000 - ); - } - } else { - Cookies.set(cookie_prefix + "status", "unlocked"); - session_reminder_locked = false; - internals.log("Reminder of session expiration not necessary: Session reminder unlocked"); - } - } - }).fail(function () { - Cookies.set(cookie_prefix + "status", "unlocked"); - session_reminder_locked = false; - internals.log("XHR Failure: Session reminder unlocked"); - }); - }; - - const methods = { - init: function (params) { - return this.each(function () { - const $this = $(this); - - if ($this.data('sessionreminder')) { - return; - } - - const data = { - properties: $.extend( - true, {}, - { - url: "", - client_id: "", - hash: "", - frequency: 60, - debug: 0 - }, - params - ) - }; - - $this.data("sessionreminder", data); - internals.properties = data.properties; - - const properties = internals.properties, - cookie_prefix = "il_sr_" + properties.client_id + "_"; - - $(window).on('beforeunload', function () { - if (session_reminder_locked) { - Cookies.set(cookie_prefix + "status", "unlocked"); - internals.log("Unlocked session reminder on unload event"); - } - }); - - internals.log("Session reminder started"); - if (Cookies.get(cookie_prefix + "session_id_hash") !== properties.hash) { - Cookies.set(cookie_prefix + "activation", "enabled"); - Cookies.set(cookie_prefix + "status", "unlocked"); - Cookies.set(cookie_prefix + "session_id_hash", properties.hash); - internals.log( - "Session cookie changed after new login or session reminder initially started " + - "for current session: Release lock and enabled reminder" - ); - } - - session_reminder_executer = new PeriodicalExecuter( - ilSessionReminderCallback, properties.frequency * 1000 - ); - }); - } - }; - - if (methods[method]) { - return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); - } else if (typeof method === "object" || !method) { - return methods.init.apply(this, arguments); - } else { - $.error("Method " + method + " does not exist on jQuery.ilSessionReminder"); - } - }; -})(jQuery); diff --git a/components/ILIAS/Authentication/resources/sessioncheck.php b/components/ILIAS/Authentication/resources/sessioncheck.php index 154fe92cf67a..a494647d7f73 100644 --- a/components/ILIAS/Authentication/resources/sessioncheck.php +++ b/components/ILIAS/Authentication/resources/sessioncheck.php @@ -41,6 +41,7 @@ $DIC['ilClientIniFile'], $DIC->logger()->auth(), (new DataFactory())->clock()->utc(), + $DIC->settings() ) )->handle() ); diff --git a/components/ILIAS/Authentication/tests/LocalUserPasswordTest.php b/components/ILIAS/Authentication/tests/LocalUserPasswordTest.php index 510d63767444..03d178a7ad95 100644 --- a/components/ILIAS/Authentication/tests/LocalUserPasswordTest.php +++ b/components/ILIAS/Authentication/tests/LocalUserPasswordTest.php @@ -101,16 +101,23 @@ public function testExceptionIsRaisedIfPasswordManagerIsCreatedWithoutValidFacto */ public function testInstanceCanBeCreated(): void { + $call_count = 0; $factory_mock = $this->getMockBuilder(LocalUserPasswordEncoderFactory::class)->disableOriginalConstructor()->getMock(); - $factory_mock->expects($this->exactly(2))->method('getSupportedEncoderNames')->will($this->onConsecutiveCalls( - [ - 'mockencoder', - 'second_mockencoder' - ], - [ - 'mockencoder' - ] - )); + $factory_mock + ->expects($this->exactly(2)) + ->method('getSupportedEncoderNames') + ->willReturnCallback(function () use (&$call_count) { + $call_count++; + if ($call_count === 1) { + return [ + 'mockencoder', + 'second_mockencoder' + ]; + } + return [ + 'mockencoder' + ]; + }); $password_manager = new LocalUserPasswordManager([ 'password_encoder' => 'md5', diff --git a/components/ILIAS/BackgroundTasks/src/Implementation/Bucket/BasicBucket.php b/components/ILIAS/BackgroundTasks/src/Implementation/Bucket/BasicBucket.php index 07352a4c671b..7fcdc9e285a9 100755 --- a/components/ILIAS/BackgroundTasks/src/Implementation/Bucket/BasicBucket.php +++ b/components/ILIAS/BackgroundTasks/src/Implementation/Bucket/BasicBucket.php @@ -207,7 +207,7 @@ public function getDescription(): string public function setDescription(string $description): void { - $this->description = $description; + $this->description = mb_substr($description, 0, 255); } /** diff --git a/components/ILIAS/BackgroundTasks_/classes/Setup/class.ilBackgroundTasksConfigStoredObjective.php b/components/ILIAS/BackgroundTasks_/classes/Setup/class.ilBackgroundTasksConfigStoredObjective.php index 48bdb9f33e6a..6f1fb1a3e3ee 100755 --- a/components/ILIAS/BackgroundTasks_/classes/Setup/class.ilBackgroundTasksConfigStoredObjective.php +++ b/components/ILIAS/BackgroundTasks_/classes/Setup/class.ilBackgroundTasksConfigStoredObjective.php @@ -59,6 +59,12 @@ public function achieve(Environment $environment): Environment $ini->addGroup("background_tasks"); } + if ($this->config->getType() === \ilBackgroundTasksSetupConfig::TYPE_ASYNCHRONOUS) { + $io = $environment->getResource(Setup\Environment::RESOURCE_ADMIN_INTERACTION); + /** @var Setup\CLI\IOWrapper $io */ + $io->inform('Asynchronous background tasks need SOAP administration to be enabled. Make sure to enable it in your configuarion.'); + } + $ini->setVariable("background_tasks", "concurrency", $this->config->getType()); $ini->setVariable("background_tasks", "number_of_concurrent_tasks", $this->config->getMaxCurrentTasks()); diff --git a/components/ILIAS/Badge/tests/BadgeManagementSessionRepositoryTest.php b/components/ILIAS/Badge/tests/BadgeManagementSessionRepositoryTest.php index ad7810aa745a..725ffb02a05b 100755 --- a/components/ILIAS/Badge/tests/BadgeManagementSessionRepositoryTest.php +++ b/components/ILIAS/Badge/tests/BadgeManagementSessionRepositoryTest.php @@ -18,9 +18,6 @@ use PHPUnit\Framework\TestCase; -/** - * @author Alexander Killing - */ class BadgeManagementSessionRepositoryTest extends TestCase { protected ilBadgeManagementSessionRepository $repo; diff --git a/components/ILIAS/Badge/tests/ModalTest.php b/components/ILIAS/Badge/tests/ModalTest.php index 67b24b9fb271..8514f5a0672c 100755 --- a/components/ILIAS/Badge/tests/ModalTest.php +++ b/components/ILIAS/Badge/tests/ModalTest.php @@ -34,7 +34,6 @@ use ILIAS\UI\Component\Item\Standard as Item; use ILIAS\UI\Component\Listing\Factory as Listing; use ILIAS\UI\Factory as UI; -use ILIAS\UI\Renderer; use PHPUnit\Framework\TestCase; use ilBadge; use ilLanguage; diff --git a/components/ILIAS/Badge/tests/PresentationHeaderTest.php b/components/ILIAS/Badge/tests/PresentationHeaderTest.php index 0ef4e69b8762..5d1feb5b02e0 100755 --- a/components/ILIAS/Badge/tests/PresentationHeaderTest.php +++ b/components/ILIAS/Badge/tests/PresentationHeaderTest.php @@ -31,6 +31,7 @@ use ilCtrl; use ILIAS\UI\Component\Component; use ilLanguage; +use PHPUnit\Framework\Attributes\DataProvider; class PresentationHeaderTest extends TestCase { @@ -41,16 +42,14 @@ public function testConstruct(): void $this->assertInstanceOf(PresentationHeader::class, $head); } - /** - * @dataProvider showProvider - */ + #[DataProvider('showProvider')] public function testShow(bool $additional = false): void { $mode = $this->getMockBuilder(Mode::class)->disableOriginalConstructor()->getMock(); - $mode->expects(self::once())->method('withActive')->with('tile_view')->willReturn($mode); + $mode->expects($this->once())->method('withActive')->with('tile_view')->willReturn($mode); $view_control = $this->getMockBuilder(ViewControl::class)->disableOriginalConstructor()->getMock(); - $view_control->expects(self::once())->method('mode')->with([ + $view_control->expects($this->once())->method('mode')->with([ 'tile_view' => 'list URL', 'table_view' => 'manage URL', ])->willReturn($mode); @@ -65,7 +64,7 @@ public function testShow(bool $additional = false): void $toolbar = $this->getMockBuilder(ilToolbarGUI::class)->disableOriginalConstructor()->getMock(); $toolbar - ->expects(self::exactly($additional + 1)) + ->expects($this->exactly($additional + 1)) ->method('addStickyItem') ->willReturnCallback( function ($component) use (&$consecutive_expected) { @@ -76,7 +75,7 @@ function ($component) use (&$consecutive_expected) { $factory = $this->getMockBuilder(UI::class)->disableOriginalConstructor()->getMock(); - $factory->expects(self::once())->method('viewControl')->willReturn($view_control); + $factory->expects($this->once())->method('viewControl')->willReturn($view_control); $ui = $this->getMockBuilder(UIServices::class)->disableOriginalConstructor()->getMock(); $ui->method('factory')->willReturn($factory); @@ -87,7 +86,7 @@ function ($component) use (&$consecutive_expected) { ]; $ctrl = $this->getMockBuilder(ilCtrl::class)->disableOriginalConstructor()->getMock(); $ctrl - ->expects(self::exactly(2)) + ->expects($this->exactly(2)) ->method('getLinkTargetByClass') ->willReturnCallback( function ($class, $cmd) use (&$consecutive) { @@ -102,7 +101,7 @@ function ($class, $cmd) use (&$consecutive) { $language->method('txt')->willReturnCallback(static fn(string $name): string => $name); $container = $this->getMockBuilder(Container::class)->disableOriginalConstructor()->getMock(); - $container->expects(self::once())->method('toolbar')->willReturn($toolbar); + $container->expects($this->once())->method('toolbar')->willReturn($toolbar); $container->method('ui')->willReturn($ui); $container->method('ctrl')->willReturn($ctrl); $container->method('language')->willReturn($language); diff --git a/components/ILIAS/Badge/tests/SortingTest.php b/components/ILIAS/Badge/tests/SortingTest.php index c60035a1fb2d..2d110550e053 100755 --- a/components/ILIAS/Badge/tests/SortingTest.php +++ b/components/ILIAS/Badge/tests/SortingTest.php @@ -24,6 +24,8 @@ use ilBadge; use ilBadgeAssignment; use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\Attributes\Depends; class SortingTest extends TestCase { @@ -33,10 +35,8 @@ public function testConstruct(): void $this->assertInstanceOf(Sorting::class, $sort); } - /** - * @depends testConstruct - * @dataProvider sortProvider - */ + #[DataProvider('sortProvider')] + #[Depends('testConstruct')] public function testSorting(array $input, string $key, string $label, string $what, string $method, array $equal, array $less, array $greater): void { $sort = new Sorting(...$input); @@ -47,9 +47,7 @@ public function testSorting(array $input, string $key, string $label, string $wh $this->assertEquals(1, $this->sign($sort->compare($this->pair($what, $method, $greater[0]), $this->pair($what, $method, $greater[1])))); } - /** - * @depends testConstruct - */ + #[Depends('testConstruct')] public function testOptions(): void { $this->assertEquals([ @@ -65,8 +63,8 @@ public static function sortProvider(): array return [ 'Default sort is title_asc' => [[], 'title_asc', 'sort_by_title_asc', 'badge', 'getTitle', ['A', 'a'], ['f', 'G'], ['d', 'c']], 'Descending title' => [['title_desc'], 'title_desc', 'sort_by_title_desc', 'badge', 'getTitle', ['A', 'a'], ['d', 'c'], ['f', 'G']], - 'Ascending date' => [['date_asc'], 'date_asc', 'sort_by_date_asc', 'assignment', 'getTimestamp', ['7', '7'], [8, 30], [20, 6]], - 'Ascending date' => [['date_desc'], 'date_desc', 'sort_by_date_desc', 'assignment', 'getTimestamp', [7, 7], [20, 6], [8, 30]], + 'Ascending date' => [['date_asc'], 'date_asc', 'sort_by_date_asc', 'assignment', 'getTimestamp', [7, 7], [8, 30], [20, 6]], + 'Descending date' => [['date_desc'], 'date_desc', 'sort_by_date_desc', 'assignment', 'getTimestamp', [7, 7], [20, 6], [8, 30]], 'Random input results in title_asc' => [['Lorem ipsum'], 'title_asc', 'sort_by_title_asc', 'badge', 'getTitle', ['A', 'a'], ['f', 'G'], ['d', 'c']] ]; } diff --git a/components/ILIAS/Badge/tests/TileTest.php b/components/ILIAS/Badge/tests/TileTest.php index 6b15e53cab0b..36f1e8e4a6c6 100755 --- a/components/ILIAS/Badge/tests/TileTest.php +++ b/components/ILIAS/Badge/tests/TileTest.php @@ -20,34 +20,21 @@ namespace ILIAS\Badge\test; -use Exception; use ILIAS\DI\Container; use ILIAS\DI\UIServices; use ILIAS\Badge\BadgeParent; use ILIAS\Badge\Modal; use ILIAS\Badge\ModalContent; use ILIAS\Badge\Tile; -use ILIAS\UI\Component\Button\Factory as Button; -use ILIAS\UI\Component\Button\Standard as StandardButton; use ILIAS\UI\Component\Button\Button as ButtonComponent; -use ILIAS\UI\Component\Card\Factory as Card; -use ILIAS\UI\Component\Card\Standard as StandardCard; -use ILIAS\UI\Component\Component; -use ILIAS\UI\Component\Image\Factory as Image; use ILIAS\UI\Component\Image\Image as ImageComponent; -use ILIAS\UI\Component\Modal\Factory as UIModal; use ILIAS\UI\Component\Modal\Modal as ModalComponent; -use ILIAS\UI\Component\Modal\Lightbox; -use ILIAS\UI\Component\Modal\LightboxCardPage; -use ILIAS\UI\Factory as UI; use PHPUnit\Framework\TestCase; use ilBadge; -use ilBadgeAssignment; use ilCtrl; use ilLanguage; -use ILIAS\ResourceStorage\Identification\ResourceIdentification; use ILIAS\ResourceStorage\Services; -use ILIAS\Badge\ilBadgeImage; +use PHPUnit\Framework\Attributes\DataProvider; class TileTest extends TestCase { @@ -62,9 +49,7 @@ public function testConstruct(): void $this->assertInstanceOf(Tile::class, new Tile($container, $parent, $modal, $sign_file, $format_date)); } - /** - * @dataProvider provideAsVariants - */ + #[DataProvider('provideAsVariants')] public function testAs(string $method, array $expected_components): void { $signed_file = '/some-signed-file'; @@ -88,7 +73,7 @@ public function testAs(string $method, array $expected_components): void $container->method('language')->willReturn($language); $container->method('resourceStorage')->willReturn($resource_storage); $format_date = function (int $x): void { - throw new Exception('Should not be called.'); + throw new \RuntimeException('Should not be called.'); }; $sign_file = function (string $path) use ($signed_file, $badge_image_path): string { return $signed_file; @@ -103,7 +88,7 @@ public function testAs(string $method, array $expected_components): void $components = $tile->$method($modal_content); - $this->assertSame(count($expected_components), count($components)); + $this->assertCount(\count($expected_components), $components); array_map($this->assertInstanceOf(...), $expected_components, $components); } diff --git a/components/ILIAS/COPage/IntLink/class.ilInternalLinkGUI.php b/components/ILIAS/COPage/IntLink/class.ilInternalLinkGUI.php index 5b6b2d240d11..189daba369ad 100755 --- a/components/ILIAS/COPage/IntLink/class.ilInternalLinkGUI.php +++ b/components/ILIAS/COPage/IntLink/class.ilInternalLinkGUI.php @@ -70,6 +70,7 @@ public function __construct( $this->lng->loadLanguageModule("link"); $this->lng->loadLanguageModule("content"); + $this->lng->loadLanguageModule("copg"); $this->ctrl->saveParameter($this, array("linkmode", "link_par_ref_id", "link_par_obj_id", "link_par_fold_id", "link_type")); @@ -327,7 +328,7 @@ public function showLinkHelp(): void $tpl->setCurrentBlock("chapter_list"); $tpl->setVariable("TXT_CONTENT_OBJECT", $this->lng->txt("obj_lm")); $tpl->setVariable("TXT_CONT_TITLE", $cont_obj->getTitle()); - $tpl->setVariable("THEAD", $this->lng->txt("pages")); + $tpl->setVariable("THEAD", $this->lng->txt("copg_pages")); $tpl->setCurrentBlock("change_cont_obj"); @@ -622,7 +623,7 @@ public function showLinkHelp(): void $tpl->setCurrentBlock("chapter_list"); $tpl->setVariable("TXT_CONTENT_OBJECT", $this->lng->txt("obj_" . ilObject::_lookupType($prtf_id))); $tpl->setVariable("TXT_CONT_TITLE", ilObject::_lookupTitle($prtf_id)); - $tpl->setVariable("THEAD", $this->lng->txt("pages")); + $tpl->setVariable("THEAD", $this->lng->txt("copg_pages")); foreach ($ppages as $ppage) { $this->renderLink( diff --git a/components/ILIAS/Calendar/classes/class.ilCalendarCategory.php b/components/ILIAS/Calendar/classes/class.ilCalendarCategory.php index 57a6c810dc53..81298a224cb0 100755 --- a/components/ILIAS/Calendar/classes/class.ilCalendarCategory.php +++ b/components/ILIAS/Calendar/classes/class.ilCalendarCategory.php @@ -247,7 +247,7 @@ public function add(): int * The title needs to be truncated to fit into the table column. This is a pretty * brute force method for doing so, but right now I can't find a better place for it. */ - $this->db->quote(substr($this->getTitle(), 0, 128), 'text') . ", " . + $this->db->quote(mb_substr($this->getTitle(), 0, 128), 'text') . ", " . $this->db->quote($this->getLocationType(), 'integer') . ', ' . $this->db->quote($this->getRemoteUrl(), 'text') . ', ' . $this->db->quote($this->getRemoteUser(), 'text') . ', ' . @@ -274,7 +274,7 @@ public function update(): void * The title needs to be truncated to fit into the table column. This is a pretty * brute force method for doing so, but right now I can't find a better place for it. */ - "title = " . $this->db->quote(substr($this->getTitle(), 0, 128), 'text') . ", " . + "title = " . $this->db->quote(mb_substr($this->getTitle(), 0, 128), 'text') . ", " . "loc_type = " . $this->db->quote($this->getLocationType(), 'integer') . ', ' . "remote_url = " . $this->db->quote($this->getRemoteUrl(), 'text') . ', ' . "remote_user = " . $this->db->quote($this->getRemoteUser(), 'text') . ', ' . diff --git a/components/ILIAS/Certificate/tests/UserCertificateAPITest.php b/components/ILIAS/Certificate/tests/UserCertificateAPITest.php index 3ddf4763c424..b6ae0fb46ec5 100755 --- a/components/ILIAS/Certificate/tests/UserCertificateAPITest.php +++ b/components/ILIAS/Certificate/tests/UserCertificateAPITest.php @@ -20,9 +20,6 @@ use ILIAS\Certificate\API\Repository\UserDataRepository; -/** - * @author Niels Theen - */ class UserCertificateAPITest extends ilCertificateBaseTestCase { public function testUserDataCall(): void diff --git a/components/ILIAS/Certificate/tests/bootstrap.php b/components/ILIAS/Certificate/tests/bootstrap.php index 1a96e285cab4..5e6f02cb98d3 100755 --- a/components/ILIAS/Certificate/tests/bootstrap.php +++ b/components/ILIAS/Certificate/tests/bootstrap.php @@ -18,8 +18,5 @@ declare(strict_types=1); -/** - * @author Niels Theen - */ require_once __DIR__ . '/../../../../vendor/composer/vendor/autoload.php'; require_once __DIR__ . '/ilCertificateBaseTestCase.php'; diff --git a/components/ILIAS/Certificate/tests/ilApiUserCertificateRepositoryTest.php b/components/ILIAS/Certificate/tests/ilApiUserCertificateRepositoryTest.php index 52e455c81b67..51013aef576b 100755 --- a/components/ILIAS/Certificate/tests/ilApiUserCertificateRepositoryTest.php +++ b/components/ILIAS/Certificate/tests/ilApiUserCertificateRepositoryTest.php @@ -18,9 +18,6 @@ declare(strict_types=1); -/** - * @author Niels Theen - */ class ilApiUserCertificateRepositoryTest extends ilCertificateBaseTestCase { private \ilDBInterface&\PHPUnit\Framework\MockObject\MockObject $database; diff --git a/components/ILIAS/Certificate/tests/ilCertificateActiveValidatorTest.php b/components/ILIAS/Certificate/tests/ilCertificateActiveValidatorTest.php index ac2e27b5d4cf..a8edd5709639 100755 --- a/components/ILIAS/Certificate/tests/ilCertificateActiveValidatorTest.php +++ b/components/ILIAS/Certificate/tests/ilCertificateActiveValidatorTest.php @@ -18,9 +18,6 @@ declare(strict_types=1); -/** - * @author Niels Theen - */ class ilCertificateActiveValidatorTest extends \PHPUnit\Framework\TestCase { public function testCertificatesAreActiveAndJavaServerIsActive(): void diff --git a/components/ILIAS/Certificate/tests/ilCertificateBaseTestCase.php b/components/ILIAS/Certificate/tests/ilCertificateBaseTestCase.php index 9b959581bc56..bf11aafd9ed5 100755 --- a/components/ILIAS/Certificate/tests/ilCertificateBaseTestCase.php +++ b/components/ILIAS/Certificate/tests/ilCertificateBaseTestCase.php @@ -21,10 +21,6 @@ use ILIAS\DI\Container; use PHPUnit\Framework\TestCase; -/** - * Class ilCertificateBaseTestCase - * @author Michael Jansen - */ abstract class ilCertificateBaseTestCase extends TestCase { protected ?Container $dic; @@ -44,10 +40,7 @@ protected function setUp(): void parent::setUp(); } - /** - * @param mixed $value - */ - protected function setGlobalVariable(string $name, $value): void + protected function setGlobalVariable(string $name, mixed $value): void { global $DIC; diff --git a/components/ILIAS/Certificate/tests/ilCertificateCloneActionTest.php b/components/ILIAS/Certificate/tests/ilCertificateCloneActionTest.php index 549ab5623420..9298f960ec0b 100755 --- a/components/ILIAS/Certificate/tests/ilCertificateCloneActionTest.php +++ b/components/ILIAS/Certificate/tests/ilCertificateCloneActionTest.php @@ -18,9 +18,6 @@ declare(strict_types=1); -/** - * @author Niels Theen - */ class ilCertificateCloneActionTest extends ilCertificateBaseTestCase { public function testCloneCertificate(): void diff --git a/components/ILIAS/Certificate/tests/ilCertificateCronTest.php b/components/ILIAS/Certificate/tests/ilCertificateCronTest.php index 67db0c0604b2..d0239faf270c 100755 --- a/components/ILIAS/Certificate/tests/ilCertificateCronTest.php +++ b/components/ILIAS/Certificate/tests/ilCertificateCronTest.php @@ -20,9 +20,6 @@ use ILIAS\Cron\Job\Schedule\JobScheduleType; -/** - * @author Niels Theen - */ class ilCertificateCronTest extends ilCertificateBaseTestCase { public function testGetTitle(): void diff --git a/components/ILIAS/Certificate/tests/ilCertificateDownloadValidatorTest.php b/components/ILIAS/Certificate/tests/ilCertificateDownloadValidatorTest.php index ed4458f80115..d1280e18e137 100755 --- a/components/ILIAS/Certificate/tests/ilCertificateDownloadValidatorTest.php +++ b/components/ILIAS/Certificate/tests/ilCertificateDownloadValidatorTest.php @@ -18,9 +18,6 @@ declare(strict_types=1); -/** - * @author Niels Theen - */ class ilCertificateDownloadValidatorTest extends ilCertificateBaseTestCase { public function testValidationSucceedsAndReturnsTrue(): void diff --git a/components/ILIAS/Certificate/tests/ilCertificateObjectsForUserPreloaderTest.php b/components/ILIAS/Certificate/tests/ilCertificateObjectsForUserPreloaderTest.php index 20b8806239c3..2f07a98b4336 100755 --- a/components/ILIAS/Certificate/tests/ilCertificateObjectsForUserPreloaderTest.php +++ b/components/ILIAS/Certificate/tests/ilCertificateObjectsForUserPreloaderTest.php @@ -18,9 +18,6 @@ declare(strict_types=1); -/** - * @author Niels Theen - */ class ilCertificateObjectsForUserPreloaderTest extends ilCertificateBaseTestCase { public function testUsersWithCertifcatesWillBePreoloaded(): void diff --git a/components/ILIAS/Certificate/tests/ilCertificatePdfActionTest.php b/components/ILIAS/Certificate/tests/ilCertificatePdfActionTest.php index a088b3065a92..03502c730ddc 100755 --- a/components/ILIAS/Certificate/tests/ilCertificatePdfActionTest.php +++ b/components/ILIAS/Certificate/tests/ilCertificatePdfActionTest.php @@ -18,9 +18,6 @@ declare(strict_types=1); -/** - * @author Niels Theen - */ class ilCertificatePdfActionTest extends ilCertificateBaseTestCase { public function testCreatePdfWillCreatedAndIsDownloadable(): void diff --git a/components/ILIAS/Certificate/tests/ilCertificateQueueEntryTest.php b/components/ILIAS/Certificate/tests/ilCertificateQueueEntryTest.php index 617bc185b679..fb91ee661a35 100755 --- a/components/ILIAS/Certificate/tests/ilCertificateQueueEntryTest.php +++ b/components/ILIAS/Certificate/tests/ilCertificateQueueEntryTest.php @@ -18,9 +18,6 @@ declare(strict_types=1); -/** - * @author Niels Theen - */ class ilCertificateQueueEntryTest extends ilCertificateBaseTestCase { public function testEntryCanBeInstantiated(): void diff --git a/components/ILIAS/Certificate/tests/ilCertificateQueueRepositoryTest.php b/components/ILIAS/Certificate/tests/ilCertificateQueueRepositoryTest.php index bcef646755f5..90b9e5f004d0 100755 --- a/components/ILIAS/Certificate/tests/ilCertificateQueueRepositoryTest.php +++ b/components/ILIAS/Certificate/tests/ilCertificateQueueRepositoryTest.php @@ -18,9 +18,6 @@ declare(strict_types=1); -/** - * @author Niels Theen - */ class ilCertificateQueueRepositoryTest extends ilCertificateBaseTestCase { public function testEntryCanBeAddedToQueue(): void diff --git a/components/ILIAS/Certificate/tests/ilCertificateTemplateDeleteActionTest.php b/components/ILIAS/Certificate/tests/ilCertificateTemplateDeleteActionTest.php index 1ceb18c3ab23..69013bab7226 100755 --- a/components/ILIAS/Certificate/tests/ilCertificateTemplateDeleteActionTest.php +++ b/components/ILIAS/Certificate/tests/ilCertificateTemplateDeleteActionTest.php @@ -18,9 +18,6 @@ declare(strict_types=1); -/** - * @author Niels Theen - */ class ilCertificateTemplateDeleteActionTest extends ilCertificateBaseTestCase { public function testDeleteTemplateAndUseOldThumbnail(): void diff --git a/components/ILIAS/Certificate/tests/ilCertificateTemplateExportActionTest.php b/components/ILIAS/Certificate/tests/ilCertificateTemplateExportActionTest.php index 1f6719014a88..f53702571773 100755 --- a/components/ILIAS/Certificate/tests/ilCertificateTemplateExportActionTest.php +++ b/components/ILIAS/Certificate/tests/ilCertificateTemplateExportActionTest.php @@ -20,9 +20,6 @@ use ILIAS\ResourceStorage\Services as IRSS; -/** - * @author Niels Theen - */ class ilCertificateTemplateExportActionTest extends ilCertificateBaseTestCase { public function testExport(): void diff --git a/components/ILIAS/Certificate/tests/ilCertificateTemplateImportActionTest.php b/components/ILIAS/Certificate/tests/ilCertificateTemplateImportActionTest.php index 20df310210ce..9fca66fcb492 100755 --- a/components/ILIAS/Certificate/tests/ilCertificateTemplateImportActionTest.php +++ b/components/ILIAS/Certificate/tests/ilCertificateTemplateImportActionTest.php @@ -23,9 +23,6 @@ use ILIAS\ResourceStorage\Services as IRSS; use ILIAS\ResourceStorage\Identification\ResourceIdentification; -/** - * @author Niels Theen - */ class ilCertificateTemplateImportActionTest extends ilCertificateBaseTestCase { public function testCertificateCanBeImportedWithBackgroundImage(): void diff --git a/components/ILIAS/Certificate/tests/ilCertificateTemplatePreviewActionTest.php b/components/ILIAS/Certificate/tests/ilCertificateTemplatePreviewActionTest.php index 8149a4dd446b..d1f3f8b8c620 100755 --- a/components/ILIAS/Certificate/tests/ilCertificateTemplatePreviewActionTest.php +++ b/components/ILIAS/Certificate/tests/ilCertificateTemplatePreviewActionTest.php @@ -20,9 +20,6 @@ use ILIAS\ResourceStorage\Services as IRSS; -/** - * @author Niels Theen - */ class ilCertificateTemplatePreviewActionTest extends ilCertificateBaseTestCase { public function testA(): void diff --git a/components/ILIAS/Certificate/tests/ilCertificateTemplateRepositoryTest.php b/components/ILIAS/Certificate/tests/ilCertificateTemplateRepositoryTest.php index 94222cfaab63..0a660b64fc2b 100755 --- a/components/ILIAS/Certificate/tests/ilCertificateTemplateRepositoryTest.php +++ b/components/ILIAS/Certificate/tests/ilCertificateTemplateRepositoryTest.php @@ -18,9 +18,6 @@ declare(strict_types=1); -/** - * @author Niels Theen - */ class ilCertificateTemplateRepositoryTest extends ilCertificateBaseTestCase { public function testCertificateWillBeSavedToTheDatabase(): void @@ -460,9 +457,6 @@ function () use (&$consecutive) { $this->assertSame(30, $templates[1]->getObjId()); } - /** - * - */ public function testFetchFirstCreatedTemplateFailsBecauseNothingWasSaved(): never { $this->expectException(ilException::class); diff --git a/components/ILIAS/Certificate/tests/ilCertificateTypeClassMapTest.php b/components/ILIAS/Certificate/tests/ilCertificateTypeClassMapTest.php index 25f52bb83b11..ed7da5fa08d6 100755 --- a/components/ILIAS/Certificate/tests/ilCertificateTypeClassMapTest.php +++ b/components/ILIAS/Certificate/tests/ilCertificateTypeClassMapTest.php @@ -22,9 +22,6 @@ use ILIAS\Course\Certificate\CoursePlaceholderValues; use ILIAS\Test\Certificate\TestPlaceholderValues; -/** - * @author Niels Theen - */ class ilCertificateTypeClassMapTest extends ilCertificateBaseTestCase { private ilCertificateTypeClassMap $classMap; diff --git a/components/ILIAS/Certificate/tests/ilCertificateUserForObjectPreloaderTest.php b/components/ILIAS/Certificate/tests/ilCertificateUserForObjectPreloaderTest.php index 2905d5075c71..7e1dbaffb87d 100755 --- a/components/ILIAS/Certificate/tests/ilCertificateUserForObjectPreloaderTest.php +++ b/components/ILIAS/Certificate/tests/ilCertificateUserForObjectPreloaderTest.php @@ -18,9 +18,6 @@ declare(strict_types=1); -/** - * @author Niels Theen - */ class ilCertificateUserForObjectPreloaderTest extends ilCertificateBaseTestCase { public function testUsersWithCertifcatesWillBePreoloaded(): void diff --git a/components/ILIAS/Certificate/tests/ilCertificateValueReplacementTest.php b/components/ILIAS/Certificate/tests/ilCertificateValueReplacementTest.php index 2008885c2408..476e53f5abe3 100755 --- a/components/ILIAS/Certificate/tests/ilCertificateValueReplacementTest.php +++ b/components/ILIAS/Certificate/tests/ilCertificateValueReplacementTest.php @@ -18,9 +18,6 @@ declare(strict_types=1); -/** - * @author Niels Theen - */ class ilCertificateValueReplacementTest extends ilCertificateBaseTestCase { public function testReplace(): void diff --git a/components/ILIAS/Certificate/tests/ilDefaultPlaceholderDescriptionTest.php b/components/ILIAS/Certificate/tests/ilDefaultPlaceholderDescriptionTest.php index 0ac746e417d5..9b06e62e0833 100755 --- a/components/ILIAS/Certificate/tests/ilDefaultPlaceholderDescriptionTest.php +++ b/components/ILIAS/Certificate/tests/ilDefaultPlaceholderDescriptionTest.php @@ -18,9 +18,6 @@ declare(strict_types=1); -/** - * @author Niels Theen - */ class ilDefaultPlaceholderDescriptionTest extends ilCertificateBaseTestCase { public function testCreateHtmlDescription(): void diff --git a/components/ILIAS/Certificate/tests/ilDefaultPlaceholderValuesTest.php b/components/ILIAS/Certificate/tests/ilDefaultPlaceholderValuesTest.php index 71f7a998845d..284b7046b2eb 100755 --- a/components/ILIAS/Certificate/tests/ilDefaultPlaceholderValuesTest.php +++ b/components/ILIAS/Certificate/tests/ilDefaultPlaceholderValuesTest.php @@ -18,9 +18,6 @@ declare(strict_types=1); -/** - * @author Niels Theen - */ class ilDefaultPlaceholderValuesTest extends ilCertificateBaseTestCase { public function testGetPlaceholderValues(): void diff --git a/components/ILIAS/Certificate/tests/ilFormFieldParserTest.php b/components/ILIAS/Certificate/tests/ilFormFieldParserTest.php index 129078867a7a..11d2a37f88cc 100755 --- a/components/ILIAS/Certificate/tests/ilFormFieldParserTest.php +++ b/components/ILIAS/Certificate/tests/ilFormFieldParserTest.php @@ -18,9 +18,6 @@ declare(strict_types=1); -/** - * @author Niels Theen - */ class ilFormFieldParserTest extends ilCertificateBaseTestCase { public function testA4(): void diff --git a/components/ILIAS/Certificate/tests/ilPageFormatsTest.php b/components/ILIAS/Certificate/tests/ilPageFormatsTest.php index 59f38955fbf0..90ed4fca3daf 100755 --- a/components/ILIAS/Certificate/tests/ilPageFormatsTest.php +++ b/components/ILIAS/Certificate/tests/ilPageFormatsTest.php @@ -18,9 +18,6 @@ declare(strict_types=1); -/** - * @author Niels Theen - */ class ilPageFormatsTest extends ilCertificateBaseTestCase { public function testFetchFormats(): void diff --git a/components/ILIAS/Certificate/tests/ilPdfGeneratorTest.php b/components/ILIAS/Certificate/tests/ilPdfGeneratorTest.php index 4082a75e559e..b4d28e1b0d73 100755 --- a/components/ILIAS/Certificate/tests/ilPdfGeneratorTest.php +++ b/components/ILIAS/Certificate/tests/ilPdfGeneratorTest.php @@ -21,15 +21,11 @@ use ILIAS\ResourceStorage\Services as IRSS; use ILIAS\Certificate\ValueObject\CertificateId; use ILIAS\Filesystem\Filesystem; +use PHPUnit\Framework\Attributes\DoesNotPerformAssertions; -/** - * @author Niels Theen - */ class ilPdfGeneratorTest extends ilCertificateBaseTestCase { - /** - * @doesNotPerformAssertions - */ + #[DoesNotPerformAssertions] public function testGenerateSpecificCertificate(): void { if (!defined('CLIENT_WEB_DIR')) { @@ -106,9 +102,7 @@ public function testGenerateSpecificCertificate(): void $pdfGenerator->generate(100); } - /** - * @doesNotPerformAssertions - */ + #[DoesNotPerformAssertions] public function testGenerateCurrentActiveCertificate(): void { if (!defined('CLIENT_WEB_DIR')) { diff --git a/components/ILIAS/Certificate/tests/ilUserCertificateApiGUITest.php b/components/ILIAS/Certificate/tests/ilUserCertificateApiGUITest.php index 94cea0f4636f..12a2ba40b146 100755 --- a/components/ILIAS/Certificate/tests/ilUserCertificateApiGUITest.php +++ b/components/ILIAS/Certificate/tests/ilUserCertificateApiGUITest.php @@ -20,9 +20,6 @@ use Psr\Http\Message\ServerRequestInterface; -/** - * @author Niels Theen - */ class ilUserCertificateApiGUITest extends ilCertificateBaseTestCase { public function testCreationOfGuiClass(): void diff --git a/components/ILIAS/Certificate/tests/ilUserCertificateRepositoryTest.php b/components/ILIAS/Certificate/tests/ilUserCertificateRepositoryTest.php index 40d4bd100601..c86fe3f8d3f0 100755 --- a/components/ILIAS/Certificate/tests/ilUserCertificateRepositoryTest.php +++ b/components/ILIAS/Certificate/tests/ilUserCertificateRepositoryTest.php @@ -20,9 +20,6 @@ use ILIAS\Certificate\ValueObject\CertificateId; -/** - * @author Niels Theen - */ class ilUserCertificateRepositoryTest extends ilCertificateBaseTestCase { public function testSaveOfUserCertificateToDatabase(): void @@ -240,9 +237,6 @@ public function testFetchActiveCertificateForUserObjectCombination(): void $this->assertSame(141, $result->getId()); } - /** - * - */ public function testFetchNoActiveCertificateLeadsToException(): never { $this->expectException(ilException::class); diff --git a/components/ILIAS/Certificate/tests/ilUserCertificateTableProviderTest.php b/components/ILIAS/Certificate/tests/ilUserCertificateTableProviderTest.php index bab32a75a769..040f71215551 100755 --- a/components/ILIAS/Certificate/tests/ilUserCertificateTableProviderTest.php +++ b/components/ILIAS/Certificate/tests/ilUserCertificateTableProviderTest.php @@ -18,9 +18,6 @@ declare(strict_types=1); -/** - * @author Niels Theen - */ class ilUserCertificateTableProviderTest extends ilCertificateBaseTestCase { public function testFetchingDataSetForTableWithoutParamtersAndWithoutFilters(): void diff --git a/components/ILIAS/Certificate/tests/ilUserCertificateTest.php b/components/ILIAS/Certificate/tests/ilUserCertificateTest.php index 09f2d4caa3db..555841137656 100755 --- a/components/ILIAS/Certificate/tests/ilUserCertificateTest.php +++ b/components/ILIAS/Certificate/tests/ilUserCertificateTest.php @@ -20,9 +20,6 @@ use ILIAS\Certificate\ValueObject\CertificateId; -/** - * @author Niels Theen - */ class ilUserCertificateTest extends ilCertificateBaseTestCase { public function testCreateUserCertificate(): void diff --git a/components/ILIAS/Certificate/tests/ilXlsFoParserTest.php b/components/ILIAS/Certificate/tests/ilXlsFoParserTest.php index 3a051f73511a..8e1154ed918c 100755 --- a/components/ILIAS/Certificate/tests/ilXlsFoParserTest.php +++ b/components/ILIAS/Certificate/tests/ilXlsFoParserTest.php @@ -18,6 +18,8 @@ declare(strict_types=1); +use PHPUnit\Framework\Attributes\DataProvider; + class ilXlsFoParserTest extends ilCertificateBaseTestCase { /** @@ -521,9 +523,9 @@ public static function nonBreakingSpaceIsAddedDataProvider(): Generator } /** - * @dataProvider nonBreakingSpaceIsAddedDataProvider * @param array{"certificate_text": string, "pageformat": string, "pagewidth"?: string, "pageheight"?: string, "margin_body": array{"top": string, "right": string, "bottom": string, "left": string}} $form_data */ + #[DataProvider('nonBreakingSpaceIsAddedDataProvider')] public function testTransformingParagraphsWithNoTextAndNoChildrenResultsInNonBreakingSpaceXslFoBlock( array $form_data, string $fo @@ -619,9 +621,9 @@ public static function noNonBreakingSpaceIsAddedDataProvider(): Generator } /** - * @dataProvider noNonBreakingSpaceIsAddedDataProvider * @param array{"certificate_text": string, "pageformat": string, "pagewidth"?: string, "pageheight"?: string, "margin_body": array{"top": string, "right": string, "bottom": string, "left": string}} $form_data */ + #[DataProvider('noNonBreakingSpaceIsAddedDataProvider')] public function testTransformingParagraphsWithTextOrChildrenResultsNotInNonBreakingSpaceXslFoBlock( array $form_data, string $fo diff --git a/components/ILIAS/Certificate/tests/samples/ilCertificateTemplateTest.php b/components/ILIAS/Certificate/tests/samples/ilCertificateTemplateTest.php index 52cba4730589..5315bc649f59 100755 --- a/components/ILIAS/Certificate/tests/samples/ilCertificateTemplateTest.php +++ b/components/ILIAS/Certificate/tests/samples/ilCertificateTemplateTest.php @@ -18,9 +18,6 @@ declare(strict_types=1); -/** - * @author Niels Theen - */ class ilCertificateTemplateTest extends ilCertificateBaseTestCase { public function testCreateCertificateTemplate(): void diff --git a/components/ILIAS/Chatroom/classes/class.ilObjChatroomGUI.php b/components/ILIAS/Chatroom/classes/class.ilObjChatroomGUI.php index f82b92164328..b9b723e30d18 100755 --- a/components/ILIAS/Chatroom/classes/class.ilObjChatroomGUI.php +++ b/components/ILIAS/Chatroom/classes/class.ilObjChatroomGUI.php @@ -270,11 +270,6 @@ protected function infoScreen(): void $info->enableNews(); } - $info->addMetaDataSections( - $this->getObject()->getId(), - 0, - $this->getObject()->getType() - ); $this->ctrl->forwardCommand($info); } diff --git a/components/ILIAS/Chatroom/tests/ilChatroomAbstractTaskTestBase.php b/components/ILIAS/Chatroom/tests/ilChatroomAbstractTaskTestBase.php index 2713a329f56a..e2179543efcf 100644 --- a/components/ILIAS/Chatroom/tests/ilChatroomAbstractTaskTestBase.php +++ b/components/ILIAS/Chatroom/tests/ilChatroomAbstractTaskTestBase.php @@ -22,18 +22,11 @@ use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\MockObject\Rule\InvocationOrder; -/** - * Class ilChatroomAbstractTaskTest - * @author Thomas Joußen - */ abstract class ilChatroomAbstractTaskTestBase extends ilChatroomAbstractTestBase { - /** @var MockObject&ilChatroomObjectGUI */ - protected $gui; - /** @var MockObject&ilChatroomServerConnector */ - protected $ilChatroomServerConnectorMock; - /** @var MockObject&ilObjChatroom */ - protected $object; + protected MockObject&ilChatroomObjectGUI $gui; + protected MockObject&ilChatroomServerConnector $ilChatroomServerConnectorMock; + protected MockObject&ilObjChatroom $object; protected function setUp(): void { diff --git a/components/ILIAS/Chatroom/tests/ilChatroomAbstractTestBase.php b/components/ILIAS/Chatroom/tests/ilChatroomAbstractTestBase.php index 04f183f59b81..b13fd537a388 100644 --- a/components/ILIAS/Chatroom/tests/ilChatroomAbstractTestBase.php +++ b/components/ILIAS/Chatroom/tests/ilChatroomAbstractTestBase.php @@ -22,16 +22,10 @@ use PHPUnit\Framework\TestCase; use PHPUnit\Framework\MockObject\MockObject; -/** - * Class ilChatroomAbstractTest - * @author Thomas Joußen - */ abstract class ilChatroomAbstractTestBase extends TestCase { - /** @var MockObject&ilChatroom */ - protected $ilChatroomMock; - /** @var MockObject&ilChatroomUser */ - protected $ilChatroomUserMock; + protected MockObject&ilChatroom $ilChatroomMock; + protected MockObject&ilChatroomUser $ilChatroomUserMock; private ?Container $dic = null; protected function setUp(): void @@ -59,10 +53,7 @@ protected function tearDown(): void parent::tearDown(); } - /** - * @return ilChatroomUser&MockObject - */ - protected function createIlChatroomUserMock(): ilChatroomUser + protected function createIlChatroomUserMock(): ilChatroomUser&MockObject { $this->ilChatroomUserMock = $this->getMockBuilder(ilChatroomUser::class)->disableOriginalConstructor()->onlyMethods( ['getUserId', 'getUsername'] @@ -71,10 +62,7 @@ protected function createIlChatroomUserMock(): ilChatroomUser return $this->ilChatroomUserMock; } - /** - * @return ilDBInterface&MockObject - */ - protected function createGlobalIlDBMock(): ilDBInterface + protected function createGlobalIlDBMock(): ilDBInterface&MockObject { $db = $this->getMockBuilder(ilDBInterface::class)->getMock(); $db->method('quote')->willReturnCallback(static function ($arg): string { diff --git a/components/ILIAS/Chatroom/tests/ilChatroomServerSettingsTest.php b/components/ILIAS/Chatroom/tests/ilChatroomServerSettingsTest.php index 42de2442e575..9dc3c65aeb84 100644 --- a/components/ILIAS/Chatroom/tests/ilChatroomServerSettingsTest.php +++ b/components/ILIAS/Chatroom/tests/ilChatroomServerSettingsTest.php @@ -19,11 +19,8 @@ declare(strict_types=1); use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\Attributes\DataProvider; -/** - * Class ilChatroomServerSettingsTest - * @author Thomas Joußen - */ class ilChatroomServerSettingsTest extends TestCase { protected ilChatroomServerSettings $settings; @@ -64,8 +61,8 @@ public static function setterAndGettersProvider(): array /** * @param callable(mixed): void $assertionCallback * @param mixed $value - * @dataProvider setterAndGettersProvider */ + #[DataProvider('setterAndGettersProvider')] public function testSettersAndGetters(string $property, callable $assertionCallback, $value): void { $setter = 'set' . ucfirst($property); diff --git a/components/ILIAS/Chatroom/tests/ilChatroomUserTest.php b/components/ILIAS/Chatroom/tests/ilChatroomUserTest.php index ca9815a5546f..7b6e45b1785a 100644 --- a/components/ILIAS/Chatroom/tests/ilChatroomUserTest.php +++ b/components/ILIAS/Chatroom/tests/ilChatroomUserTest.php @@ -19,15 +19,11 @@ declare(strict_types=1); use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\Attributes\DataProvider; -/** - * Class ilChatroomUserTest - * @author Thomas Joußen - */ class ilChatroomUserTest extends ilChatroomAbstractTestBase { - /** @var ilObjUser&MockObject */ - protected ilObjUser $ilUserMock; + protected ilObjUser&MockObject $ilUserMock; protected ilChatroomUser $user; public function testGetUserIdIfNotAnonymous(): void @@ -70,9 +66,7 @@ public function testGetUserIdRandomGeneratedIfAnonymous(): void $this->assertNotNull($this->user->getUserId()); } - /** - * @dataProvider usernameDataProvider - */ + #[DataProvider('usernameDataProvider')] public function testSetUsername(string $username, string $expected): void { $this->user->setUsername($username); diff --git a/components/ILIAS/Chatroom/tests/ilObjChatroomAccessTest.php b/components/ILIAS/Chatroom/tests/ilObjChatroomAccessTest.php index 236c0e265f36..4d016392c1ba 100644 --- a/components/ILIAS/Chatroom/tests/ilObjChatroomAccessTest.php +++ b/components/ILIAS/Chatroom/tests/ilObjChatroomAccessTest.php @@ -27,8 +27,7 @@ class ilObjChatroomAccessTest extends ilChatroomAbstractTestBase { protected ilObjChatroomAccess $access; - /** @var ilDBInterface&MockObject */ - protected ilDBInterface $db; + protected ilDBInterface&MockObject $db; public function testCommandDefitionFullfilsExpectations(): void { diff --git a/components/ILIAS/Chatroom/tests/ilObjChatroomAdminAccessTest.php b/components/ILIAS/Chatroom/tests/ilObjChatroomAdminAccessTest.php index 21401244f5d8..e9250ef835a5 100644 --- a/components/ILIAS/Chatroom/tests/ilObjChatroomAdminAccessTest.php +++ b/components/ILIAS/Chatroom/tests/ilObjChatroomAdminAccessTest.php @@ -20,15 +20,10 @@ use PHPUnit\Framework\MockObject\MockObject; -/** - * Class ilObjChatroomAdminAccessTest - * @author Thomas Joußen - */ class ilObjChatroomAdminAccessTest extends ilChatroomAbstractTestBase { protected ilObjChatroomAdminAccess $adminAccess; - /** @var ilRbacSystem&MockObject */ - protected ilRbacSystem $ilAccessMock; + protected ilRbacSystem&MockObject $ilAccessMock; public function testCommandDefitionFullfilsExpectations(): void { diff --git a/components/ILIAS/Chatroom/tests/ilObjChatroomTest.php b/components/ILIAS/Chatroom/tests/ilObjChatroomTest.php index b75bceb1763e..16f52f754e80 100644 --- a/components/ILIAS/Chatroom/tests/ilObjChatroomTest.php +++ b/components/ILIAS/Chatroom/tests/ilObjChatroomTest.php @@ -18,10 +18,6 @@ declare(strict_types=1); -/** - * Class ilObjChatroomTest - * @author Thomas Joußen - */ class ilObjChatroomTest extends ilChatroomAbstractTestBase { protected ilObjChatroom $object; diff --git a/components/ILIAS/Contact/tests/ilAwarenessUserProviderApprovedContactsTestCase.php b/components/ILIAS/Contact/tests/ilAwarenessUserProviderApprovedContactsTestCase.php index 822be592c0ef..164b4813087d 100644 --- a/components/ILIAS/Contact/tests/ilAwarenessUserProviderApprovedContactsTestCase.php +++ b/components/ILIAS/Contact/tests/ilAwarenessUserProviderApprovedContactsTestCase.php @@ -20,6 +20,7 @@ use ILIAS\DI\Container; use ilAwarenessUserProviderApprovedContacts as ApprovedContacts; +use PHPUnit\Framework\Attributes\Depends; class ilAwarenessUserProviderApprovedContactsTestCase extends ilBuddySystemBaseTestCase { @@ -28,8 +29,8 @@ public function testConstruct(): ApprovedContacts $user = $this->getMockBuilder(ilObjUser::class)->disableOriginalConstructor()->getMock(); $language = $this->getMockBuilder(ilLanguage::class)->disableOriginalConstructor()->getMock(); $container = $this->getMockBuilder(Container::class)->disableOriginalConstructor()->getMock(); - $container->expects(self::once())->method('user')->willReturn($user); - $container->expects(self::once())->method('language')->willReturn($language); + $container->expects($this->once())->method('user')->willReturn($user); + $container->expects($this->once())->method('language')->willReturn($language); $instance = new ApprovedContacts($container); @@ -38,9 +39,7 @@ public function testConstruct(): ApprovedContacts return $instance; } - /** - * @depends testConstruct - */ + #[Depends('testConstruct')] public function testGetProviderId(ApprovedContacts $instance): void { $this->assertSame('contact_requests', $instance->getProviderId()); @@ -59,20 +58,18 @@ public function testGetInfo(): void public function testGetInitialUserSet(): void { $user = $this->getMockBuilder(ilObjUser::class)->disableOriginalConstructor()->getMock(); - $user->expects(self::once())->method('isAnonymous')->willReturn(true); + $user->expects($this->once())->method('isAnonymous')->willReturn(true); $language = $this->getMockBuilder(ilLanguage::class)->disableOriginalConstructor()->getMock(); $container = $this->getMockBuilder(Container::class)->disableOriginalConstructor()->getMock(); - $container->expects(self::once())->method('user')->willReturn($user); - $container->expects(self::once())->method('language')->willReturn($language); + $container->expects($this->once())->method('user')->willReturn($user); + $container->expects($this->once())->method('language')->willReturn($language); $instance = new ApprovedContacts($container); $this->assertEquals([], $instance->getInitialUserSet()); } - /** - * @depends testConstruct - */ + #[Depends('testConstruct')] public function testIsHighlighted(ApprovedContacts $instance): void { $this->assertFalse($instance->isHighlighted()); @@ -84,12 +81,12 @@ private function expectTranslation(string $method, string $languageKey): void $user = $this->getMockBuilder(ilObjUser::class)->disableOriginalConstructor()->getMock(); $language = $this->getMockBuilder(ilLanguage::class)->disableOriginalConstructor()->getMock(); - $language->expects(self::once())->method('loadLanguageModule')->with('contact'); - $language->expects(self::once())->method('txt')->with($languageKey)->willReturn($expected); + $language->expects($this->once())->method('loadLanguageModule')->with('contact'); + $language->expects($this->once())->method('txt')->with($languageKey)->willReturn($expected); $container = $this->getMockBuilder(Container::class)->disableOriginalConstructor()->getMock(); - $container->expects(self::once())->method('user')->willReturn($user); - $container->expects(self::once())->method('language')->willReturn($language); + $container->expects($this->once())->method('user')->willReturn($user); + $container->expects($this->once())->method('language')->willReturn($language); $instance = new ApprovedContacts($container); $this->assertSame($expected, $instance->$method()); diff --git a/components/ILIAS/Contact/tests/ilAwarenessUserProviderContactRequestsTestCase.php b/components/ILIAS/Contact/tests/ilAwarenessUserProviderContactRequestsTestCase.php index 4845f2b46500..d2d29a1ea202 100644 --- a/components/ILIAS/Contact/tests/ilAwarenessUserProviderContactRequestsTestCase.php +++ b/components/ILIAS/Contact/tests/ilAwarenessUserProviderContactRequestsTestCase.php @@ -24,15 +24,8 @@ class ilAwarenessUserProviderContactRequestsTestCase extends ilBuddySystemBaseTestCase { - /** - * @var ilObjUser|MockObject - */ - private $user; - - /** - * @var ilLanguage|MockObject - */ - private $language; + private ilObjUser|MockObject $user; + private ilLanguage|MockObject $language; public function testConstruct(): void { @@ -58,7 +51,7 @@ public function testGetInitialUserSet(): void { $instance = $this->create(); - $this->user->expects(self::once())->method('isAnonymous')->willReturn(true); + $this->user->expects($this->once())->method('isAnonymous')->willReturn(true); $this->assertEquals([], $instance->getInitialUserSet()); } @@ -74,8 +67,8 @@ private function expectTranslation(string $method, string $languageKey): void $instance = $this->create(); - $this->language->expects(self::once())->method('loadLanguageModule')->with('contact'); - $this->language->expects(self::once())->method('txt')->with($languageKey)->willReturn($expected); + $this->language->expects($this->once())->method('loadLanguageModule')->with('contact'); + $this->language->expects($this->once())->method('txt')->with($languageKey)->willReturn($expected); $this->assertSame($expected, $instance->$method()); } @@ -86,8 +79,8 @@ private function create(): Contacts $this->language = $this->getMockBuilder(ilLanguage::class)->disableOriginalConstructor()->getMock(); $container = $this->getMockBuilder(Container::class)->disableOriginalConstructor()->getMock(); - $container->expects(self::once())->method('user')->willReturn($this->user); - $container->expects(self::once())->method('language')->willReturn($this->language); + $container->expects($this->once())->method('user')->willReturn($this->user); + $container->expects($this->once())->method('language')->willReturn($this->language); return new Contacts($container); } diff --git a/components/ILIAS/Contact/tests/ilBuddyListTestCase.php b/components/ILIAS/Contact/tests/ilBuddyListTestCase.php index f5d796c1345c..cd8bbf5f0a46 100644 --- a/components/ILIAS/Contact/tests/ilBuddyListTestCase.php +++ b/components/ILIAS/Contact/tests/ilBuddyListTestCase.php @@ -18,10 +18,6 @@ declare(strict_types=1); -/** - * Class ilBuddyListTest - * @author Michael Jansen - */ class ilBuddyListTestCase extends ilBuddySystemBaseTestCase { private const BUDDY_LIST_OWNER_ID = -1; @@ -516,7 +512,6 @@ private function setPriorRelationState( ): void { $object = new ReflectionObject($relation); $property = $object->getProperty('priorState'); - $property->setAccessible(true); $property->setValue($relation, $state); } diff --git a/components/ILIAS/Contact/tests/ilBuddySystemRelationCollectionTestCase.php b/components/ILIAS/Contact/tests/ilBuddySystemRelationCollectionTestCase.php index b51378644535..4a91de8def46 100644 --- a/components/ILIAS/Contact/tests/ilBuddySystemRelationCollectionTestCase.php +++ b/components/ILIAS/Contact/tests/ilBuddySystemRelationCollectionTestCase.php @@ -18,15 +18,11 @@ declare(strict_types=1); -/** - * Class ilBuddySystemRelationCollectionTest - * @author Michael Jansen - */ +use PHPUnit\Framework\Attributes\DataProvider; + class ilBuddySystemRelationCollectionTestCase extends ilBuddySystemBaseTestCase { - /** - * @dataProvider provideElements - */ + #[DataProvider('provideElements')] public function testElementsCanBeInitiallyAdded(array $elements): void { $collection = new ilBuddySystemRelationCollection($elements); @@ -43,9 +39,7 @@ public function testElementsCanBeInitiallyAdded(array $elements): void } } - /** - * @dataProvider provideElements - */ + #[DataProvider('provideElements')] public function testElementsCanBeAddedAndRemoved(array $elements): void { $collection = new ilBuddySystemRelationCollection(); @@ -94,14 +88,12 @@ public function testElementsCanBeAddedAndRemoved(array $elements): void $this->assertSame(5, reset($data)); } - /** - * @dataProvider provideElements - */ + #[DataProvider('provideElements')] public function testIterator(array $elements): void { $collection = new ilBuddySystemRelationCollection($elements); $iterations = 0; - foreach ($collection->getIterator() as $key => $item) { + foreach ($collection as $key => $item) { $this->assertSame($elements[$key], $item, "Item $key not match"); $iterations++; } @@ -149,11 +141,11 @@ public function testElementsCanBeFiltered(): void */ public static function provideElements(): array { - $relation1 = $this->getMockBuilder(ilBuddySystemRelation::class)->disableOriginalConstructor()->getMock(); - $relation2 = $this->getMockBuilder(ilBuddySystemRelation::class)->disableOriginalConstructor()->getMock(); - $relation3 = $this->getMockBuilder(ilBuddySystemRelation::class)->disableOriginalConstructor()->getMock(); - $relation4 = $this->getMockBuilder(ilBuddySystemRelation::class)->disableOriginalConstructor()->getMock(); - $relation5 = $this->getMockBuilder(ilBuddySystemRelation::class)->disableOriginalConstructor()->getMock(); + $relation1 = new ilBuddySystemRelation(new ilBuddySystemUnlinkedRelationState(), 1, 2, false, time()); + $relation2 = new ilBuddySystemRelation(new ilBuddySystemUnlinkedRelationState(), 3, 4, false, time()); + $relation3 = new ilBuddySystemRelation(new ilBuddySystemUnlinkedRelationState(), 5, 6, false, time()); + $relation4 = new ilBuddySystemRelation(new ilBuddySystemUnlinkedRelationState(), 7, 8, false, time()); + $relation5 = new ilBuddySystemRelation(new ilBuddySystemUnlinkedRelationState(), 9, 10, false, time()); return [ 'indexed' => [[0, 1, 2, 3, 4, 5]], diff --git a/components/ILIAS/Contact/tests/ilBuddySystemRelationRepositoryTestCase.php b/components/ILIAS/Contact/tests/ilBuddySystemRelationRepositoryTestCase.php index c16421fab605..61edaa58fef7 100644 --- a/components/ILIAS/Contact/tests/ilBuddySystemRelationRepositoryTestCase.php +++ b/components/ILIAS/Contact/tests/ilBuddySystemRelationRepositoryTestCase.php @@ -18,10 +18,6 @@ declare(strict_types=1); -/** - * Class ilBuddySystemRelationRepositoryTest - * @author Michael Jansen - */ class ilBuddySystemRelationRepositoryTestCase extends ilBuddySystemBaseTestCase { public function testSqlRepositoryDelegatesDeletionToDatabaseAbstraction(): void diff --git a/components/ILIAS/Contact/tests/ilBuddySystemRelationTestCase.php b/components/ILIAS/Contact/tests/ilBuddySystemRelationTestCase.php index 0c4b6c491f96..bddef18fd9fd 100644 --- a/components/ILIAS/Contact/tests/ilBuddySystemRelationTestCase.php +++ b/components/ILIAS/Contact/tests/ilBuddySystemRelationTestCase.php @@ -18,10 +18,6 @@ declare(strict_types=1); -/** - * Class ilBuddySystemRelationTest - * @author Michael Jansen - */ class ilBuddySystemRelationTestCase extends ilBuddySystemBaseTestCase { private const RELATION_OWNER_ID = -1; diff --git a/components/ILIAS/Contact/tests/states/ilBuddySystemBaseStateTestCase.php b/components/ILIAS/Contact/tests/states/ilBuddySystemBaseStateTestCase.php index a46e0d530175..a91a0a7d414b 100644 --- a/components/ILIAS/Contact/tests/states/ilBuddySystemBaseStateTestCase.php +++ b/components/ILIAS/Contact/tests/states/ilBuddySystemBaseStateTestCase.php @@ -18,10 +18,6 @@ declare(strict_types=1); -/** - * Class ilBuddySystemBaseStateTest - * @author Michael Jansen - */ abstract class ilBuddySystemBaseStateTestCase extends ilBuddySystemBaseTestCase { private const RELATION_OWNER_ID = -1; diff --git a/components/ILIAS/Contact/tests/states/ilBuddySystemLinkedStateRelationTest.php b/components/ILIAS/Contact/tests/states/ilBuddySystemLinkedStateRelationTest.php index fd275ddb557c..dca5945365da 100644 --- a/components/ILIAS/Contact/tests/states/ilBuddySystemLinkedStateRelationTest.php +++ b/components/ILIAS/Contact/tests/states/ilBuddySystemLinkedStateRelationTest.php @@ -18,10 +18,6 @@ declare(strict_types=1); -/** - * Class ilBuddySystemLinkedStateRelationTest - * @author Michael Jansen - */ class ilBuddySystemLinkedStateRelationTest extends ilBuddySystemBaseStateTestCase { public function getInitialState(): ilBuddySystemRelationState diff --git a/components/ILIAS/Contact/tests/states/ilBuddySystemRelationStateInitiatorShouldNotBeAbleToApproveIgnoredRequestRuleTestCase.php b/components/ILIAS/Contact/tests/states/ilBuddySystemRelationStateInitiatorShouldNotBeAbleToApproveIgnoredRequestRuleTestCase.php index 64f2ee185ea7..b06ab14e7e9a 100644 --- a/components/ILIAS/Contact/tests/states/ilBuddySystemRelationStateInitiatorShouldNotBeAbleToApproveIgnoredRequestRuleTestCase.php +++ b/components/ILIAS/Contact/tests/states/ilBuddySystemRelationStateInitiatorShouldNotBeAbleToApproveIgnoredRequestRuleTestCase.php @@ -34,8 +34,8 @@ public function testConstruct(): void public function testMatches(): void { $relation = $this->getMockBuilder(ilBuddySystemRelation::class)->disableOriginalConstructor()->getMock(); - $relation->expects(self::once())->method('isIgnored')->willReturn(true); - $relation->expects(self::once())->method('isOwnedByActor')->willReturn(true); + $relation->expects($this->once())->method('isIgnored')->willReturn(true); + $relation->expects($this->once())->method('isOwnedByActor')->willReturn(true); $instance = new DontApprove($relation); $this->assertTrue($instance->matches()); @@ -44,8 +44,8 @@ public function testMatches(): void public function testMatchesIgnored(): void { $relation = $this->getMockBuilder(ilBuddySystemRelation::class)->disableOriginalConstructor()->getMock(); - $relation->expects(self::once())->method('isIgnored')->willReturn(false); - $relation->expects(self::never())->method('isOwnedByActor'); + $relation->expects($this->once())->method('isIgnored')->willReturn(false); + $relation->expects($this->never())->method('isOwnedByActor'); $instance = new DontApprove($relation); $this->assertFalse($instance->matches()); @@ -54,8 +54,8 @@ public function testMatchesIgnored(): void public function testMatchesOwned(): void { $relation = $this->getMockBuilder(ilBuddySystemRelation::class)->disableOriginalConstructor()->getMock(); - $relation->expects(self::once())->method('isIgnored')->willReturn(true); - $relation->expects(self::once())->method('isOwnedByActor')->willReturn(false); + $relation->expects($this->once())->method('isIgnored')->willReturn(true); + $relation->expects($this->once())->method('isOwnedByActor')->willReturn(false); $instance = new DontApprove($relation); $this->assertFalse($instance->matches()); diff --git a/components/ILIAS/Contact/tests/states/ilBuddySystemRelationStateInitiatorShouldOnlyBeAbleToCancelRequestRuleTestCase.php b/components/ILIAS/Contact/tests/states/ilBuddySystemRelationStateInitiatorShouldOnlyBeAbleToCancelRequestRuleTestCase.php index 756d3e443601..785c1f4d1e21 100644 --- a/components/ILIAS/Contact/tests/states/ilBuddySystemRelationStateInitiatorShouldOnlyBeAbleToCancelRequestRuleTestCase.php +++ b/components/ILIAS/Contact/tests/states/ilBuddySystemRelationStateInitiatorShouldOnlyBeAbleToCancelRequestRuleTestCase.php @@ -34,8 +34,8 @@ public function testConstruct(): void public function testMatches(): void { $relation = $this->mock(ilBuddySystemRelation::class); - $relation->expects(self::once())->method('isRequested')->willReturn(true); - $relation->expects(self::once())->method('isOwnedByActor')->willReturn(true); + $relation->expects($this->once())->method('isRequested')->willReturn(true); + $relation->expects($this->once())->method('isOwnedByActor')->willReturn(true); $instance = new Cancel($relation); $this->assertTrue($instance->matches()); @@ -44,8 +44,8 @@ public function testMatches(): void public function testMatchesRequested(): void { $relation = $this->mock(ilBuddySystemRelation::class); - $relation->expects(self::once())->method('isRequested')->willReturn(false); - $relation->expects(self::never())->method('isOwnedByActor'); + $relation->expects($this->once())->method('isRequested')->willReturn(false); + $relation->expects($this->never())->method('isOwnedByActor'); $instance = new Cancel($relation); $this->assertFalse($instance->matches()); @@ -54,8 +54,8 @@ public function testMatchesRequested(): void public function testMatchesOwned(): void { $relation = $this->mock(ilBuddySystemRelation::class); - $relation->expects(self::once())->method('isRequested')->willReturn(true); - $relation->expects(self::once())->method('isOwnedByActor')->willReturn(false); + $relation->expects($this->once())->method('isRequested')->willReturn(true); + $relation->expects($this->once())->method('isOwnedByActor')->willReturn(false); $instance = new Cancel($relation); $this->assertFalse($instance->matches()); diff --git a/components/ILIAS/Contact/tests/states/ilBuddySystemRelationStateNullFilterRuleTestCase.php b/components/ILIAS/Contact/tests/states/ilBuddySystemRelationStateNullFilterRuleTestCase.php index b9dd60aa7a0b..f7f83b6eed40 100644 --- a/components/ILIAS/Contact/tests/states/ilBuddySystemRelationStateNullFilterRuleTestCase.php +++ b/components/ILIAS/Contact/tests/states/ilBuddySystemRelationStateNullFilterRuleTestCase.php @@ -18,6 +18,8 @@ declare(strict_types=1); +use PHPUnit\Framework\Attributes\Depends; + class ilBuddySystemRelationStateNullFilterRuleTestCase extends ilBuddySystemBaseTestCase { public function testConstruct(): ilBuddySystemRelationStateNullFilterRule @@ -32,17 +34,13 @@ public function testConstruct(): ilBuddySystemRelationStateNullFilterRule return $instance; } - /** - * @depends testConstruct - */ + #[Depends('testConstruct')] public function testMatches(ilBuddySystemRelationStateNullFilterRule $instance): void { $this->assertTrue($instance->matches()); } - /** - * @depends testConstruct - */ + #[Depends('testConstruct')] public function testInvoke(ilBuddySystemRelationStateNullFilterRule $instance): void { $this->assertTrue($instance($this->getMockBuilder(ilBuddySystemRelationState::class)->disableOriginalConstructor()->getMock())); @@ -57,12 +55,12 @@ public function testGetStates(): void $filtered = $this->getMockBuilder(ilBuddySystemRelationStateCollection::class)->disableOriginalConstructor()->getMock(); $collection = $this->getMockBuilder(ilBuddySystemRelationStateCollection::class)->disableOriginalConstructor()->getMock(); - $collection->expects(self::once())->method('filter')->with($instance)->willReturn($filtered); + $collection->expects($this->once())->method('filter')->with($instance)->willReturn($filtered); $state = $this->getMockBuilder(ilBuddySystemRelationState::class)->disableOriginalConstructor()->getMock(); - $state->expects(self::once())->method('getPossibleTargetStates')->willReturn($collection); + $state->expects($this->once())->method('getPossibleTargetStates')->willReturn($collection); - $relation->expects(self::once())->method('getState')->willReturn($state); + $relation->expects($this->once())->method('getState')->willReturn($state); $this->assertEquals($filtered, $instance->getStates()); } diff --git a/components/ILIAS/Contact/tests/states/ilBuddySystemRelationStateReceiverShouldNotBeAbleToCancelRequestRuleTestCase.php b/components/ILIAS/Contact/tests/states/ilBuddySystemRelationStateReceiverShouldNotBeAbleToCancelRequestRuleTestCase.php index 1ca0d427e1e9..5954bb8642dd 100644 --- a/components/ILIAS/Contact/tests/states/ilBuddySystemRelationStateReceiverShouldNotBeAbleToCancelRequestRuleTestCase.php +++ b/components/ILIAS/Contact/tests/states/ilBuddySystemRelationStateReceiverShouldNotBeAbleToCancelRequestRuleTestCase.php @@ -34,8 +34,8 @@ public function testConstruct(): void public function testMatches(): void { $relation = $this->mock(ilBuddySystemRelation::class); - $relation->expects(self::once())->method('isRequested')->willReturn(true); - $relation->expects(self::once())->method('isOwnedByActor')->willReturn(false); + $relation->expects($this->once())->method('isRequested')->willReturn(true); + $relation->expects($this->once())->method('isOwnedByActor')->willReturn(false); $instance = new DontCancel($relation); $this->assertTrue($instance->matches()); @@ -44,8 +44,8 @@ public function testMatches(): void public function testMatchesRequested(): void { $relation = $this->mock(ilBuddySystemRelation::class); - $relation->expects(self::once())->method('isRequested')->willReturn(false); - $relation->expects(self::never())->method('isOwnedByActor'); + $relation->expects($this->once())->method('isRequested')->willReturn(false); + $relation->expects($this->never())->method('isOwnedByActor'); $instance = new DontCancel($relation); $this->assertFalse($instance->matches()); @@ -54,8 +54,8 @@ public function testMatchesRequested(): void public function testMatchesOwned(): void { $relation = $this->mock(ilBuddySystemRelation::class); - $relation->expects(self::once())->method('isRequested')->willReturn(true); - $relation->expects(self::once())->method('isOwnedByActor')->willReturn(true); + $relation->expects($this->once())->method('isRequested')->willReturn(true); + $relation->expects($this->once())->method('isOwnedByActor')->willReturn(true); $instance = new DontCancel($relation); $this->assertFalse($instance->matches()); diff --git a/components/ILIAS/Contact/tests/states/ilBuddySystemRelationStateReceiverShouldOnlyBeAbleToApproveIgnoredRequestRuleTestCase.php b/components/ILIAS/Contact/tests/states/ilBuddySystemRelationStateReceiverShouldOnlyBeAbleToApproveIgnoredRequestRuleTestCase.php index 4e3641febd5b..a8ea1524ce56 100644 --- a/components/ILIAS/Contact/tests/states/ilBuddySystemRelationStateReceiverShouldOnlyBeAbleToApproveIgnoredRequestRuleTestCase.php +++ b/components/ILIAS/Contact/tests/states/ilBuddySystemRelationStateReceiverShouldOnlyBeAbleToApproveIgnoredRequestRuleTestCase.php @@ -34,8 +34,8 @@ public function testConstruct(): void public function testMatches(): void { $relation = $this->mock(ilBuddySystemRelation::class); - $relation->expects(self::once())->method('isIgnored')->willReturn(true); - $relation->expects(self::once())->method('isOwnedByActor')->willReturn(false); + $relation->expects($this->once())->method('isIgnored')->willReturn(true); + $relation->expects($this->once())->method('isOwnedByActor')->willReturn(false); $instance = new Approve($relation); $this->assertTrue($instance->matches()); @@ -44,8 +44,8 @@ public function testMatches(): void public function testMatchesIgnored(): void { $relation = $this->mock(ilBuddySystemRelation::class); - $relation->expects(self::once())->method('isIgnored')->willReturn(false); - $relation->expects(self::never())->method('isOwnedByActor'); + $relation->expects($this->once())->method('isIgnored')->willReturn(false); + $relation->expects($this->never())->method('isOwnedByActor'); $instance = new Approve($relation); $this->assertFalse($instance->matches()); @@ -54,8 +54,8 @@ public function testMatchesIgnored(): void public function testMatchesOwned(): void { $relation = $this->mock(ilBuddySystemRelation::class); - $relation->expects(self::once())->method('isIgnored')->willReturn(true); - $relation->expects(self::once())->method('isOwnedByActor')->willReturn(true); + $relation->expects($this->once())->method('isIgnored')->willReturn(true); + $relation->expects($this->once())->method('isOwnedByActor')->willReturn(true); $instance = new Approve($relation); $this->assertFalse($instance->matches()); diff --git a/components/ILIAS/Contact/tests/states/ilBuddySystemRequestIgnoredStateRelationTest.php b/components/ILIAS/Contact/tests/states/ilBuddySystemRequestIgnoredStateRelationTest.php index 615c276cc429..37b028da40cc 100644 --- a/components/ILIAS/Contact/tests/states/ilBuddySystemRequestIgnoredStateRelationTest.php +++ b/components/ILIAS/Contact/tests/states/ilBuddySystemRequestIgnoredStateRelationTest.php @@ -18,10 +18,6 @@ declare(strict_types=1); -/** - * Class ilBuddySystemRequestIgnoredStateRelationTest - * @author Michael Jansen - */ class ilBuddySystemRequestIgnoredStateRelationTest extends ilBuddySystemBaseStateTestCase { public function getInitialState(): ilBuddySystemRelationState diff --git a/components/ILIAS/Contact/tests/states/ilBuddySystemRequestedStateRelationTest.php b/components/ILIAS/Contact/tests/states/ilBuddySystemRequestedStateRelationTest.php index 24c04f7e7693..58ba9a722827 100644 --- a/components/ILIAS/Contact/tests/states/ilBuddySystemRequestedStateRelationTest.php +++ b/components/ILIAS/Contact/tests/states/ilBuddySystemRequestedStateRelationTest.php @@ -18,10 +18,6 @@ declare(strict_types=1); -/** - * Class ilBuddySystemRequestedStateRelationTest - * @author Michael Jansen - */ class ilBuddySystemRequestedStateRelationTest extends ilBuddySystemBaseStateTestCase { public function getInitialState(): ilBuddySystemRelationState diff --git a/components/ILIAS/Contact/tests/states/ilBuddySystemUnlinkedStateRelationTest.php b/components/ILIAS/Contact/tests/states/ilBuddySystemUnlinkedStateRelationTest.php index bb97dc176c26..c788b2264611 100644 --- a/components/ILIAS/Contact/tests/states/ilBuddySystemUnlinkedStateRelationTest.php +++ b/components/ILIAS/Contact/tests/states/ilBuddySystemUnlinkedStateRelationTest.php @@ -18,10 +18,6 @@ declare(strict_types=1); -/** - * Class ilBuddySystemUnlinkedStateRelationTest - * @author Michael Jansen - */ class ilBuddySystemUnlinkedStateRelationTest extends ilBuddySystemBaseStateTestCase { public function getInitialState(): ilBuddySystemRelationState diff --git a/components/ILIAS/Container/Content/ObjectiveView/class.ObjectiveRenderer.php b/components/ILIAS/Container/Content/ObjectiveView/class.ObjectiveRenderer.php index c726938e0b1c..0618566c71b4 100755 --- a/components/ILIAS/Container/Content/ObjectiveView/class.ObjectiveRenderer.php +++ b/components/ILIAS/Container/Content/ObjectiveView/class.ObjectiveRenderer.php @@ -262,7 +262,6 @@ protected function renderTest( } $node_data['title'] = $title; - return "
" . $this->renderer->getItemRenderer()->renderItem($node_data) . "
"; } diff --git a/components/ILIAS/Container/Content/ObjectiveView/class.ilContainerObjectiveGUI.php b/components/ILIAS/Container/Content/ObjectiveView/class.ilContainerObjectiveGUI.php index 9bdc5313d1c9..c2cd20fb9a5d 100755 --- a/components/ILIAS/Container/Content/ObjectiveView/class.ilContainerObjectiveGUI.php +++ b/components/ILIAS/Container/Content/ObjectiveView/class.ilContainerObjectiveGUI.php @@ -45,7 +45,6 @@ public function __construct( \ILIAS\Container\Content\ItemPresentationManager $item_presentation ) { global $DIC; - $this->tabs = $DIC->tabs(); $this->toolbar = $DIC->toolbar(); $this->logger = $DIC->logger()->crs(); @@ -161,6 +160,16 @@ public function getMainContent(): string return $tpl->get(); } + public function initRenderer(): void + { + parent::initRenderer(); + $this->loc_settings = ilLOSettings::getInstanceByObjId($this->getContainerObject()->getId()); + $this->objective_map = $this->buildObjectiveMap(); + $this->renderer->setItemModifierClosure(function (ilObjectListGUI $a_item_list_gui, array $a_item) { + $this->addItemDetails($a_item_list_gui, $a_item); + }); + } + public function renderItemList(): string { $this->initRenderer(); @@ -468,9 +477,7 @@ protected function addItemDetails(ilObjectListGUI $a_item_list_gui, array $a_ite $lng = $this->lng; $ilCtrl = $this->ctrl; $ilUser = $this->user; - $item_ref_id = $a_item["ref_id"]; - if (is_array($this->objective_map)) { $details = []; if (isset($this->objective_map["material"][$item_ref_id])) { diff --git a/components/ILIAS/Container/Content/class.ItemRenderer.php b/components/ILIAS/Container/Content/class.ItemRenderer.php index 1c5bf5e1a835..2e78e6ad2dd2 100755 --- a/components/ILIAS/Container/Content/class.ItemRenderer.php +++ b/components/ILIAS/Container/Content/class.ItemRenderer.php @@ -38,6 +38,7 @@ class ItemRenderer protected string $view_mode; protected InternalGUIService $gui; protected InternalDomainService $domain; + protected ?\Closure $item_modifier_closure = null; protected array $list_gui = []; public function __construct( @@ -140,8 +141,9 @@ public function renderItem( } } - if (method_exists($this, "addItemDetails")) { - $this->addItemDetails($item_list_gui, $a_item_data); + if ($this->item_modifier_closure instanceof \Closure) { + $c = $this->item_modifier_closure; + $c($item_list_gui, $a_item_data); } // show subitems of sessions @@ -239,6 +241,11 @@ public function renderItem( return $html; } + public function setItemModifierClosure(\Closure $f): void + { + $this->item_modifier_closure = $f; + } + public function renderCard( array $a_item_data, int $a_position = 0, diff --git a/components/ILIAS/Container/Content/class.ilContainerRenderer.php b/components/ILIAS/Container/Content/class.ilContainerRenderer.php index 75e2775f0fbb..57965a272ba2 100755 --- a/components/ILIAS/Container/Content/class.ilContainerRenderer.php +++ b/components/ILIAS/Container/Content/class.ilContainerRenderer.php @@ -67,6 +67,7 @@ class ilContainerRenderer protected ?Closure $block_prefix_closure = null; protected ?Closure $block_postfix_closure = null; protected ?Closure $item_hidden_closure = null; + protected ?Closure $item_modifier_closure = null; protected \ILIAS\Container\Content\BlockSessionRepository $block_repo; public function __construct( @@ -145,6 +146,12 @@ public function setItemHiddenClosure(Closure $f): void $this->item_hidden_closure = $f; } + public function setItemModifierClosure(Closure $f): void + { + $this->item_renderer->setItemModifierClosure($f); + $this->item_modifier_closure = $f; + } + protected function getViewMode(): int { return $this->view_mode; diff --git a/components/ILIAS/ContentPage/classes/class.ilContentPagePageConfig.php b/components/ILIAS/ContentPage/classes/class.ilContentPagePageConfig.php index ae559088f6ef..40bb5f394f63 100755 --- a/components/ILIAS/ContentPage/classes/class.ilContentPagePageConfig.php +++ b/components/ILIAS/ContentPage/classes/class.ilContentPagePageConfig.php @@ -28,6 +28,7 @@ public function init(): void $this->setEnablePermissionChecks(true); $this->setMultiLangSupport(true); $this->setUsePageContainer(false); + $this->setEnableAnchors(true); $this->setEnablePCType('Map', true); $mediaPoolSettings = new ilSetting('mobs'); diff --git a/components/ILIAS/ContentPage/tests/PageReadingTimeTest.php b/components/ILIAS/ContentPage/tests/PageReadingTimeTest.php index 6638e06c028b..c5e8e70c2311 100755 --- a/components/ILIAS/ContentPage/tests/PageReadingTimeTest.php +++ b/components/ILIAS/ContentPage/tests/PageReadingTimeTest.php @@ -24,11 +24,8 @@ use PHPUnit\Framework\TestCase; use TypeError; use stdClass; +use PHPUnit\Framework\Attributes\DataProvider; -/** - * Class PageReadingTimeTest - * @author Michael Jansen - */ class PageReadingTimeTest extends TestCase { public static function mixedReadingTypesProvider(): array @@ -44,11 +41,8 @@ public static function mixedReadingTypesProvider(): array ]; } - /** - * @param mixed $mixedType - * @dataProvider mixedReadingTypesProvider - */ - public function testPageReadingTimeValueThrowsExceptionWhenConstructedWithInvalidTypes($mixedType): void + #[DataProvider('mixedReadingTypesProvider')] + public function testPageReadingTimeValueThrowsExceptionWhenConstructedWithInvalidTypes(mixed $mixedType): void { $this->expectException(TypeError::class); diff --git a/components/ILIAS/Course/classes/class.ilCourseExporter.php b/components/ILIAS/Course/classes/class.ilCourseExporter.php index c1353d5cf2ae..b1b67514bf90 100755 --- a/components/ILIAS/Course/classes/class.ilCourseExporter.php +++ b/components/ILIAS/Course/classes/class.ilCourseExporter.php @@ -17,15 +17,15 @@ *********************************************************************/ declare(strict_types=0); + /** * Folder export * @author Stefan Meyer - * @ingroup ServicesBooking */ class ilCourseExporter extends ilXmlExporter { - public const ENTITY_OBJECTIVE = 'objectives'; - public const ENTITY_MAIN = 'crs'; + public const string ENTITY_OBJECTIVE = 'objectives'; + public const string ENTITY_MAIN = 'crs'; protected ilXmlWriter $writer; protected ilLogger $logger; @@ -178,19 +178,26 @@ public function getXmlRepresentation(string $a_entity, string $a_schema_version, public function getValidSchemaVersions(string $a_entity): array { return [ + "11.0" => [ + "namespace" => 'http://www.ilias.de/Modules/Course/crs/11', + "xsd_file" => 'ilias_crs_11_0.xsd', + "uses_dataset" => false, + "min" => "11.0", + "max" => "" + ], "10.0" => [ "namespace" => 'http://www.ilias.de/Modules/Course/crs/10', - "xsd_file" => 'ilias_crs_10.xsd', + "xsd_file" => 'ilias_crs_10_0.xsd', "uses_dataset" => false, "min" => "10.0", - "max" => "" + "max" => "10.999" ], "9.0" => [ "namespace" => 'http://www.ilias.de/Modules/Course/crs/9', "xsd_file" => 'ilias_crs_9_0.xsd', "uses_dataset" => false, "min" => "9.0", - "max" => "" + "max" => "9.999" ], "4.1.0" => [ "namespace" => "http://www.ilias.de/Modules/Course/crs/4_1", @@ -204,7 +211,7 @@ public function getValidSchemaVersions(string $a_entity): array "xsd_file" => "ilias_crs_5_0.xsd", "uses_dataset" => false, "min" => "5.0.0", - "max" => "" + "max" => "8.999" ] ]; } diff --git a/components/ILIAS/Course/classes/class.ilCourseXMLParser.php b/components/ILIAS/Course/classes/class.ilCourseXMLParser.php index 89f55dc4e4da..369bca67e41b 100755 --- a/components/ILIAS/Course/classes/class.ilCourseXMLParser.php +++ b/components/ILIAS/Course/classes/class.ilCourseXMLParser.php @@ -17,20 +17,18 @@ *********************************************************************/ declare(strict_types=0); + /** * Course XML Parser * @author Stefan Meyer - * @version $Id$ - * @extends ilMDSaxParser */ -class ilCourseXMLParser extends ilMDSaxParser implements ilSaxSubsetParser +class ilCourseXMLParser extends ilSaxParser implements ilSaxSubsetParser { - public const MODE_SOAP = 1; - public const MODE_EXPORT = 2; + public const int MODE_SOAP = 1; + public const int MODE_EXPORT = 2; private int $mode = self::MODE_EXPORT; - private bool $in_meta_data = false; private bool $in_availability = false; private bool $in_registration = false; private bool $in_period = false; @@ -45,10 +43,6 @@ class ilCourseXMLParser extends ilMDSaxParser implements ilSaxSubsetParser private ?ilObjCourse $course_obj; private ?ilLogger $log; protected ilSetting $setting; - /** - * @var false - */ - protected ?ilMD $md_obj = null; protected ilSaxController $sax_controller; protected ilCourseParticipants $course_members; protected ilCourseWaitingList $course_waiting_list; @@ -68,9 +62,6 @@ public function __construct(ilObjCourse $a_course_obj, string $a_xml_file = '') $this->course_waiting_list = new ilCourseWaitingList($this->course_obj->getId()); // flip the array so we can use array_key_exists $this->course_members_array = array_flip($this->course_members->getParticipants()); - - $this->md_obj = new ilMD($this->course_obj->getId(), 0, 'crs'); - $this->setMDObject($this->md_obj); } public function setMode(int $a_mode): void @@ -83,23 +74,6 @@ public function getMode(): int return $this->mode; } - public function startParsing(): void - { - parent::startParsing(); - - // rewrite autogenerated entry - $general = $this->getMDObject()->getGeneral(); - $identifier_ids = $general->getIdentifierIds(); - if (!isset($identifier_ids[0])) { - return; - } - $identifier = $general->getIdentifier($identifier_ids[0]); - $identifier->setEntry( - 'il__' . $this->getMDObject()->getObjType() . '_' . $this->getMDObject()->getObjId() - ); - $identifier->update(); - } - /** * @inheritDoc */ @@ -119,10 +93,6 @@ public function setHandlers($a_xml_parser): void public function handlerBeginTag($a_xml_parser, string $a_name, array $a_attribs): void { $a_attribs = $this->trimAndStripAttribs($a_attribs); - if ($this->in_meta_data) { - parent::handlerBeginTag($a_xml_parser, $a_name, $a_attribs); - return; - } switch ($a_name) { case 'Course': @@ -275,11 +245,6 @@ public function handlerBeginTag($a_xml_parser, string $a_name, array $a_attribs) $this->course_obj->setSubscriptionLimitationType(ilCourseConstants::IL_CRS_SUBSCRIPTION_DEACTIVATED); break; - case "MetaData": - $this->in_meta_data = true; - parent::handlerBeginTag($a_xml_parser, $a_name, $a_attribs); - break; - case 'ContainerSetting': $this->current_container_setting = ($a_attribs['id'] ?? ''); break; @@ -508,24 +473,14 @@ private function handleWaitingList(array $a_attribs, array $id_data): void */ public function handlerEndTag($a_xml_parser, string $a_name): void { - $this->cdata = $this->trimAndStrip((string) $this->cdata); - if ($this->in_meta_data) { - parent::handlerEndTag($a_xml_parser, $a_name); - } + $this->cdata = $this->trimAndStrip($this->cdata); switch ($a_name) { case 'Course': $this->log->write('CourseXMLParser: import_id = ' . $this->course_obj->getImportId()); - /* - * This needs to be before MDUpdateListener, since otherwise container settings are - * overwritten by ilContainer::update in MDUpdateListener, see #24733. - */ + $this->course_obj->readContainerSettings(); - if ($this->getMode() === self::MODE_SOAP) { - $this->course_obj->MDUpdateListener('General'); - $this->adv_md_handler->save(); - } // see #26169 $transl = ilObjectTranslation::getInstance($this->course_obj->getId()); if ($transl->getDefaultTitle() !== "") { @@ -537,6 +492,18 @@ public function handlerEndTag($a_xml_parser, string $a_name): void $this->course_obj->update(); break; + case "Title": + $transl = ilObjectTranslation::getInstance($this->course_obj->getId()); + $this->course_obj->setTitle(trim($this->cdata)); + $transl->setDefaultTitle(trim($this->cdata)); + break; + + case "Description": + $transl = ilObjectTranslation::getInstance($this->course_obj->getId()); + $this->course_obj->setDescription(trim($this->cdata)); + $transl->setDefaultDescription(trim($this->cdata)); + break; + case 'Settings': break; @@ -624,11 +591,6 @@ public function handlerEndTag($a_xml_parser, string $a_name): void $this->course_obj->setSubscriptionPassword(trim($this->cdata)); break; - case 'MetaData': - $this->in_meta_data = false; - parent::handlerEndTag($a_xml_parser, $a_name); - break; - case 'ContainerSetting': if ($this->current_container_setting) { ilContainer::_writeContainerSetting( @@ -683,10 +645,6 @@ public function handlerEndTag($a_xml_parser, string $a_name): void public function handlerCharacterData($a_xml_parser, string $a_data): void { - // call meta data handler - if ($this->in_meta_data) { - parent::handlerCharacterData($a_xml_parser, $a_data); - } if ($a_data != "\n") { // Replace multiple tabs with one space $a_data = preg_replace("/\t+/", " ", $a_data); @@ -694,4 +652,18 @@ public function handlerCharacterData($a_xml_parser, string $a_data): void $this->cdata .= $a_data; } } + + protected function trimAndStripAttribs(array $attribs): array + { + $ret = []; + foreach ($attribs as $k => $v) { + $ret[$k] = $this->trimAndStrip((string) $v); + } + return $ret; + } + + protected function trimAndStrip(string $input): string + { + return ilUtil::stripSlashes(trim($input)); + } } diff --git a/components/ILIAS/Course/classes/class.ilCourseXMLWriter.php b/components/ILIAS/Course/classes/class.ilCourseXMLWriter.php index a69245a1a176..d8a715295b82 100755 --- a/components/ILIAS/Course/classes/class.ilCourseXMLWriter.php +++ b/components/ILIAS/Course/classes/class.ilCourseXMLWriter.php @@ -26,14 +26,13 @@ * The author is responsible for well-formedness and validity * of the xml document. * @author Stefan Meyer - * @version $Id$ */ class ilCourseXMLWriter extends ilXmlWriter { - public const MODE_SOAP = 1; - public const MODE_EXPORT = 2; + public const int MODE_SOAP = 1; + public const int MODE_EXPORT = 2; - public const EXPORT_VERSION = '8.0'; + public const string EXPORT_VERSION = '8.0'; private int $mode = self::MODE_SOAP; @@ -70,8 +69,8 @@ public function start(): void if ($this->getMode() == self::MODE_SOAP) { $this->__buildHeader(); $this->__buildCourseStart(); - $this->__buildMetaData(); $this->__buildAdvancedMetaData(); + $this->__buildTitleDescription(); if ($this->attach_users) { $this->__buildAdmin(); $this->__buildTutor(); @@ -114,6 +113,15 @@ public function __buildHeader(): void $this->xmlHeader(); } + public function __buildTitleDescription(): void + { + $this->xmlElement('Title', null, $this->course_obj->getTitle()); + + if ($desc = $this->course_obj->getDescription()) { + $this->xmlElement('Description', null, $desc); + } + } + public function __buildCourseStart(): void { $attrs["exportVersion"] = self::EXPORT_VERSION; @@ -122,13 +130,6 @@ public function __buildCourseStart(): void $this->xmlStartTag("Course", $attrs); } - public function __buildMetaData(): void - { - $md2xml = new ilMD2XML($this->course_obj->getId(), $this->course_obj->getId(), 'crs'); - $md2xml->startExport(); - $this->appendXML($md2xml->getXML()); - } - private function __buildAdvancedMetaData(): void { ilAdvancedMDValues::_appendXMLByObjId($this, $this->course_obj->getId()); diff --git a/components/ILIAS/Course/classes/class.ilObjCourse.php b/components/ILIAS/Course/classes/class.ilObjCourse.php index 48cefd180192..da76ef667f3c 100755 --- a/components/ILIAS/Course/classes/class.ilObjCourse.php +++ b/components/ILIAS/Course/classes/class.ilObjCourse.php @@ -22,17 +22,17 @@ */ class ilObjCourse extends ilContainer implements ilMembershipRegistrationCodes { - public const CAL_REG_START = 1; - public const CAL_REG_END = 2; - public const CAL_ACTIVATION_START = 3; - public const CAL_ACTIVATION_END = 4; - public const CAL_COURSE_START = 5; - public const CAL_COURSE_END = 6; - public const CAL_COURSE_TIMING_START = 7; - public const CAL_COURSE_TIMING_END = 8; - - public const STATUS_DETERMINATION_LP = 1; - public const STATUS_DETERMINATION_MANUAL = 2; + public const int CAL_REG_START = 1; + public const int CAL_REG_END = 2; + public const int CAL_ACTIVATION_START = 3; + public const int CAL_ACTIVATION_END = 4; + public const int CAL_COURSE_START = 5; + public const int CAL_COURSE_END = 6; + public const int CAL_COURSE_TIMING_START = 7; + public const int CAL_COURSE_TIMING_END = 8; + + public const int STATUS_DETERMINATION_LP = 1; + public const int STATUS_DETERMINATION_MANUAL = 2; private string $contact_consultation = ''; private string $contact_phone = ''; @@ -578,17 +578,15 @@ public function read(): void $this->__readSettings(); } - public function create($a_upload = false): int + public function create(): int { global $DIC; $ilAppEventHandler = $DIC['ilAppEventHandler']; - $id = parent::create($a_upload); + $id = parent::create(); - if (!$a_upload) { - $this->createMetaData(); - } + $this->createMetaData(); $this->__createDefaultSettings(); $this->app_event_handler->raise( 'components/ILIAS/Course', @@ -730,17 +728,12 @@ public function hasWaitingListAutoFill(): bool /** * Clone course (no member data) - * - * @access public - * @param int target ref_id - * @param int copy id - * */ - public function cloneObject(int $a_target_id, int $a_copy_id = 0, bool $a_omit_tree = false): ?ilObject + public function cloneObject(int $target_id, int $copy_id = 0, bool $omit_tree = false): ?ilObject { global $DIC; - $new_obj = parent::cloneObject($a_target_id, $a_copy_id, $a_omit_tree); + $new_obj = parent::cloneObject($target_id, $copy_id, $omit_tree); $this->cloneAutoGeneratedRoles($new_obj); $this->cloneMetaData($new_obj); @@ -748,7 +741,7 @@ public function cloneObject(int $a_target_id, int $a_copy_id = 0, bool $a_omit_t $new_obj->getMemberObject()->add($this->user->getId(), ilParticipants::IL_CRS_ADMIN); $new_obj->getMemberObject()->updateContact($this->user->getId(), 1); - $cwo = ilCopyWizardOptions::_getInstance($a_copy_id); + $cwo = ilCopyWizardOptions::_getInstance($copy_id); if ($cwo->isRootNode($this->getRefId())) { $this->setOfflineStatus(true); } @@ -784,29 +777,29 @@ public function cloneObject(int $a_target_id, int $a_copy_id = 0, bool $a_omit_t /** * @inheritDoc */ - public function cloneDependencies(int $a_target_id, int $a_copy_id): bool + public function cloneDependencies(int $target_id, int $copy_id): bool { - parent::cloneDependencies($a_target_id, $a_copy_id); + parent::cloneDependencies($target_id, $copy_id); // Clone course start objects $start = new ilContainerStartObjects($this->getRefId(), $this->getId()); - $start->cloneDependencies($a_target_id, $a_copy_id); + $start->cloneDependencies($target_id, $copy_id); // Clone course item settings - ilObjectActivation::cloneDependencies($this->getRefId(), $a_target_id, $a_copy_id); + ilObjectActivation::cloneDependencies($this->getRefId(), $target_id, $copy_id); // clone objective settings - ilLOSettings::cloneSettings($a_copy_id, $this->getId(), ilObject::_lookupObjId($a_target_id)); + ilLOSettings::cloneSettings($copy_id, $this->getId(), ilObject::_lookupObjId($target_id)); // Clone course learning objectives $crs_objective = new ilCourseObjective($this); - $crs_objective->ilClone($a_target_id, $a_copy_id); + $crs_objective->ilClone($target_id, $copy_id); // clone membership limitation foreach (\ilObjCourseGrouping::_getGroupings($this->getId()) as $grouping_id) { $this->course_logger->info('Handling grouping id: ' . $grouping_id); $grouping = new \ilObjCourseGrouping($grouping_id); - $grouping->cloneGrouping($a_target_id, $a_copy_id); + $grouping->cloneGrouping($target_id, $copy_id); } return true; } @@ -900,9 +893,7 @@ public function hasContactData(): bool /** * delete course and all related data - * - * @access public - * @return boolean true if all object data were removed; false if only a references were removed + * return true if all object data were removed; false if only a references were removed */ public function delete(): bool { @@ -1029,7 +1020,7 @@ public function updateSettings(): void 'integer' ) . ', ' . 'min_members = ' . $this->db->quote($this->getSubscriptionMinMembers(), 'integer') . ' ' . - "WHERE obj_id = " . $this->db->quote($this->getId(), 'integer') . ""; + "WHERE obj_id = " . $this->db->quote($this->getId(), 'integer'); $res = $this->db->manipulate($query); @@ -1302,9 +1293,9 @@ public function initDefaultRoles(): void * Each permission is granted by computing the intersection of the * template il_crs_non_member and the permission template of the parent role. */ - public function setParentRolePermissions(int $a_parent_ref): bool + public function setParentRolePermissions(int $parent_ref_id): bool { - $parent_roles = $this->rbac_review->getParentRoleIds($a_parent_ref); + $parent_roles = $this->rbac_review->getParentRoleIds($parent_ref_id); foreach ($parent_roles as $parent_role) { $this->rbac_admin->initIntersectionPermissions( $this->getRefId(), @@ -1353,7 +1344,7 @@ public function getLocalCourseRoles($a_translate = false): array $role_arr = $this->rbac_review->getRolesOfRoleFolder($this->getRefId()); foreach ($role_arr as $role_id) { - if ($this->rbac_review->isAssignable($role_id, $this->getRefId()) == true) { + if ($this->rbac_review->isAssignable($role_id, $this->getRefId())) { $role_Obj = ilObjectFactory::getInstanceByObjId($role_id); if ($a_translate) { $role_name = ilObjRole::_getTranslation($role_Obj->getTitle()); diff --git a/components/ILIAS/Cron/tests/CronJobEntityTest.php b/components/ILIAS/Cron/tests/CronJobEntityTest.php index 46e5c76e0c58..3fcad259440f 100755 --- a/components/ILIAS/Cron/tests/CronJobEntityTest.php +++ b/components/ILIAS/Cron/tests/CronJobEntityTest.php @@ -23,12 +23,10 @@ use ILIAS\Cron\Job\JobEntity; use ILIAS\Cron\Job\JobResult; use ILIAS\Cron\CronJob; +use PHPUnit\Framework\Attributes\Depends; class CronJobEntityTest extends TestCase { - /** - * @param CronJob|null $job_instance - */ private function getEntity( ?CronJob $job_instance = null, ?int $schedule_type = null, @@ -73,9 +71,7 @@ public function testEntityCollectionCanBeCreatedWithItems(): \ILIAS\Cron\Job\Col return $entities; } - /** - * @depends testEntityCollectionCanBeCreatedWithItems - */ + #[Depends('testEntityCollectionCanBeCreatedWithItems')] public function testCollectionCanBeChanged( \ILIAS\Cron\Job\Collection\JobEntities $entities ): \ILIAS\Cron\Job\Collection\JobEntities { @@ -86,9 +82,7 @@ public function testCollectionCanBeChanged( return $entities; } - /** - * @depends testCollectionCanBeChanged - */ + #[Depends('testCollectionCanBeChanged')] public function testCollectionCanBeFilteredAndSliced(\ILIAS\Cron\Job\Collection\JobEntities $entities): void { $this->assertCount(0, $entities->filter(static function (JobEntity $entity): bool { diff --git a/components/ILIAS/Cron/tests/CronJobScheduleTest.php b/components/ILIAS/Cron/tests/CronJobScheduleTest.php index cd137a5add00..2405b4806218 100755 --- a/components/ILIAS/Cron/tests/CronJobScheduleTest.php +++ b/components/ILIAS/Cron/tests/CronJobScheduleTest.php @@ -22,6 +22,7 @@ use ILIAS\Cron\Job\Schedule\JobScheduleType; use ILIAS\Cron\Job\JobResult; use ILIAS\Cron\CronJob; +use PHPUnit\Framework\Attributes\DataProvider; class CronJobScheduleTest extends TestCase { @@ -434,9 +435,9 @@ function (): DateTimeImmutable { } /** - * @dataProvider jobProvider * @param null|callable(): DateTimeImmutable $last_run_datetime_callable */ + #[DataProvider('jobProvider')] public function testSchedule( CronJob $job_instance, bool $is_manual_run, @@ -575,9 +576,9 @@ function (): DateTimeImmutable { } /** - * @dataProvider weeklyScheduleProvider * @param callable(): DateTimeImmutable $last_run_datetime_provider */ + #[DataProvider('weeklyScheduleProvider')] public function testWeeklySchedules( CronJob $job_instance, callable $last_run_datetime_provider, diff --git a/components/ILIAS/Data/tests/ClientIdTest.php b/components/ILIAS/Data/tests/ClientIdTest.php index 65e6cc9f59f4..cab201255fcf 100755 --- a/components/ILIAS/Data/tests/ClientIdTest.php +++ b/components/ILIAS/Data/tests/ClientIdTest.php @@ -71,20 +71,14 @@ public static function invalidClientIdProvider(): array ]; } - /** - * @param string $value - * @dataProvider clientIdProvider - */ + #[\PHPUnit\Framework\Attributes\DataProvider('clientIdProvider')] public function testValidArguments(string $value): void { $clientId = $this->f->clientId($value); $this->assertEquals($value, $clientId->toString()); } - /** - * @param string $value - * @dataProvider invalidClientIdProvider - */ + #[\PHPUnit\Framework\Attributes\DataProvider('invalidClientIdProvider')] public function testInvalidArguments(string $value): void { try { diff --git a/components/ILIAS/Data/tests/DataSizeTest.php b/components/ILIAS/Data/tests/DataSizeTest.php index aa57eebef746..eb16f107329a 100755 --- a/components/ILIAS/Data/tests/DataSizeTest.php +++ b/components/ILIAS/Data/tests/DataSizeTest.php @@ -48,9 +48,7 @@ public static function provideDataSizes(): array ]; } - /** - * @dataProvider provideDataSizes - */ + #[\PHPUnit\Framework\Attributes\DataProvider('provideDataSizes')] public function testDifferentDataSizes(int $bytes, string $expected_representation): void { $datasize = new DataSize($bytes, DataSize::Byte); @@ -58,9 +56,7 @@ public function testDifferentDataSizes(int $bytes, string $expected_representati $this->assertEquals($expected_representation, $datasize->__toString()); } - /** - * @dataProvider tDataProvider - */ + #[\PHPUnit\Framework\Attributes\DataProvider('tDataProvider')] public function test_normal($a, $b, $expected, $expected_in_bytes): void { $ds = new DataSize($a, $b); diff --git a/components/ILIAS/Data/tests/LanguageTagTest.php b/components/ILIAS/Data/tests/LanguageTagTest.php index 004331be1e05..4883d48ad988 100755 --- a/components/ILIAS/Data/tests/LanguageTagTest.php +++ b/components/ILIAS/Data/tests/LanguageTagTest.php @@ -32,9 +32,7 @@ public function testFromString(): void $this->assertInstanceOf(LanguageTag::class, $tag); } - /** - * @dataProvider saveToRun - */ + #[\PHPUnit\Framework\Attributes\DataProvider('SaveToRun')] public function testParse(string $input, bool $isOk): void { if (!$isOk) { @@ -44,9 +42,7 @@ public function testParse(string $input, bool $isOk): void $this->assertInstanceOf(LanguageTag::class, $tag); } - /** - * @dataProvider risky - */ + #[\PHPUnit\Framework\Attributes\DataProvider('risky')] public function testRisky(string $input, bool $isOk): void { $this->testParse($input, $isOk); diff --git a/components/ILIAS/Data/tests/LinkTest.php b/components/ILIAS/Data/tests/LinkTest.php index fa32fa99729c..b666fd5febc9 100755 --- a/components/ILIAS/Data/tests/LinkTest.php +++ b/components/ILIAS/Data/tests/LinkTest.php @@ -44,9 +44,7 @@ public function testFactory(): Link return $link; } - /** - * @depends testFactory - */ + #[\PHPUnit\Framework\Attributes\Depends('testFactory')] public function testValues(Link $link): void { $this->assertEquals( diff --git a/components/ILIAS/Data/tests/OrderTest.php b/components/ILIAS/Data/tests/OrderTest.php index 24b07f1e46a2..3aaeddc8a9b6 100755 --- a/components/ILIAS/Data/tests/OrderTest.php +++ b/components/ILIAS/Data/tests/OrderTest.php @@ -34,9 +34,7 @@ public function testFactory(): Order return $order; } - /** - * @depends testFactory - */ + #[\PHPUnit\Framework\Attributes\Depends('testFactory')] public function testValues(Order $order): void { $this->assertEquals( @@ -45,9 +43,7 @@ public function testValues(Order $order): void ); } - /** - * @depends testFactory - */ + #[\PHPUnit\Framework\Attributes\Depends('testFactory')] public function testAppend(Order $order): Order { $order = $order->append('sub2', Order::DESC); @@ -61,9 +57,7 @@ public function testAppend(Order $order): Order return $order; } - /** - * @depends testFactory - */ + #[\PHPUnit\Framework\Attributes\Depends('testFactory')] public function testJoinOne(Order $order): void { $this->assertEquals( @@ -77,9 +71,7 @@ function ($pre, $k, $v) { ); } - /** - * @depends testAppend - */ + #[\PHPUnit\Framework\Attributes\Depends('testAppend')] public function testJoinMore(Order $order): void { $this->assertEquals( @@ -93,18 +85,14 @@ function ($pre, $k, $v) { ); } - /** - * @depends testFactory - */ + #[\PHPUnit\Framework\Attributes\Depends('testFactory')] public function testInvalidDirection(Order $order): void { $this->expectException(TypeError::class); $order = $order->append('sub3', -1); } - /** - * @depends testFactory - */ + #[\PHPUnit\Framework\Attributes\Depends('testFactory')] public function testInvalidSubject(Order $order): void { $this->expectException(InvalidArgumentException::class); diff --git a/components/ILIAS/Data/tests/RangeTest.php b/components/ILIAS/Data/tests/RangeTest.php index 93af3f8d8e09..3d48dc9ea291 100755 --- a/components/ILIAS/Data/tests/RangeTest.php +++ b/components/ILIAS/Data/tests/RangeTest.php @@ -34,26 +34,20 @@ public function testFactory(): Range return $range; } - /** - * @depends testFactory - */ + #[\PHPUnit\Framework\Attributes\Depends('testFactory')] public function testValues(Range $range): void { $this->assertEquals(1, $range->getStart()); $this->assertEquals(2, $range->getLength()); } - /** - * @depends testFactory - */ + #[\PHPUnit\Framework\Attributes\Depends('testFactory')] public function testEndCalculation(Range $range): void { $this->assertEquals(3, $range->getEnd()); } - /** - * @depends testFactory - */ + #[\PHPUnit\Framework\Attributes\Depends('testFactory')] public function testWithLength(Range $range): Range { $range = $range->withLength(3); @@ -63,9 +57,7 @@ public function testWithLength(Range $range): Range return $range; } - /** - * @depends testWithLength - */ + #[\PHPUnit\Framework\Attributes\Depends('testWithLength')] public function testWithStart(Range $range): Range { $range = $range->withStart(3); @@ -75,9 +67,7 @@ public function testWithStart(Range $range): Range return $range; } - /** - * @depends testWithStart - */ + #[\PHPUnit\Framework\Attributes\Depends('testWithStart')] public function testUnpack(Range $range): void { $this->assertEquals( @@ -86,18 +76,14 @@ public function testUnpack(Range $range): void ); } - /** - * @depends testFactory - */ + #[\PHPUnit\Framework\Attributes\Depends('testFactory')] public function testNegativeStart(Range $range): void { $this->expectException(InvalidArgumentException::class); $range = $range->withStart(-5); } - /** - * @depends testFactory - */ + #[\PHPUnit\Framework\Attributes\Depends('testFactory')] public function testNegativeLength(Range $range): void { $this->expectException(InvalidArgumentException::class); @@ -118,9 +104,7 @@ public function testConstructionWrongLength(): void $range = $f->range(1, -2); } - /** - * @dataProvider cropCases - */ + #[\PHPUnit\Framework\Attributes\DataProvider('cropCases')] public function testCroppedTo($start, $length, $max, $has_changed): void { $f = new ILIAS\Data\Factory(); diff --git a/components/ILIAS/Data/tests/Text/Shape/MarkdownShapeTest.php b/components/ILIAS/Data/tests/Text/Shape/MarkdownShapeTest.php index 411d215b808b..039cfbadabbf 100644 --- a/components/ILIAS/Data/tests/Text/Shape/MarkdownShapeTest.php +++ b/components/ILIAS/Data/tests/Text/Shape/MarkdownShapeTest.php @@ -66,18 +66,14 @@ public static function stringToPlainDataProvider(): array ]; } - /** - * @dataProvider stringToHTMLDataProvider - */ + #[\PHPUnit\Framework\Attributes\DataProvider('stringToHTMLDataProvider')] public function testToHTML(string $markdown_string, HTML $expected_html): void { $text = $this->markdown_shape->fromString($markdown_string); $this->assertEquals($expected_html, $this->markdown_shape->toHTML($text)); } - /** - * @dataProvider stringToPlainDataProvider - */ + #[\PHPUnit\Framework\Attributes\DataProvider('stringToPlainDataProvider')] public function testToPlainText(string $markdown_string, PlainText $expected_text): void { $text = $this->markdown_shape->fromString($markdown_string); diff --git a/components/ILIAS/Data/tests/Text/Shape/SimpleDocumentMarkdownShapeTest.php b/components/ILIAS/Data/tests/Text/Shape/SimpleDocumentMarkdownShapeTest.php index cb05909558ab..8af338a1fe8b 100644 --- a/components/ILIAS/Data/tests/Text/Shape/SimpleDocumentMarkdownShapeTest.php +++ b/components/ILIAS/Data/tests/Text/Shape/SimpleDocumentMarkdownShapeTest.php @@ -68,9 +68,7 @@ public static function stringComplianceDataProvider(): array ]; } - /** - * @dataProvider constructDataProvider - */ + #[\PHPUnit\Framework\Attributes\DataProvider('constructDataProvider')] public function testGetSupportedStructure( Structure $dp_bold, Structure $dp_italic, @@ -109,9 +107,7 @@ public function testGetSupportedStructure( $this->assertEquals($expected, $supported_structure); } - /** - * @dataProvider stringComplianceDataProvider - */ + #[\PHPUnit\Framework\Attributes\DataProvider('stringComplianceDataProvider')] public function testIsRawStringCompliant(string $markdown_string, bool $compliance): void { $this->assertEquals($this->simple_doc_markdown_shape->isRawStringCompliant($markdown_string), $compliance); diff --git a/components/ILIAS/Data/tests/Text/Shape/WordOnlyMarkdownShapeTest.php b/components/ILIAS/Data/tests/Text/Shape/WordOnlyMarkdownShapeTest.php index 341d3f43a854..f921f8b00dcf 100644 --- a/components/ILIAS/Data/tests/Text/Shape/WordOnlyMarkdownShapeTest.php +++ b/components/ILIAS/Data/tests/Text/Shape/WordOnlyMarkdownShapeTest.php @@ -56,9 +56,7 @@ public static function stringComplianceDataProvider(): array ]; } - /** - * @dataProvider constructDataProvider - */ + #[\PHPUnit\Framework\Attributes\DataProvider('constructDataProvider')] public function testGetSupportedStructure(Structure $dp_bold, Structure $dp_italic): void { $supported_structure = $this->word_only_markdown_shape->getSupportedStructure(); @@ -70,9 +68,7 @@ public function testGetSupportedStructure(Structure $dp_bold, Structure $dp_ital $this->assertEquals($exptected, $supported_structure); } - /** - * @dataProvider stringComplianceDataProvider - */ + #[\PHPUnit\Framework\Attributes\DataProvider('stringComplianceDataProvider')] public function testIsRawStringCompliant(string $markdown_string, bool $compliance): void { $this->assertEquals($compliance, $this->word_only_markdown_shape->isRawStringCompliant($markdown_string)); diff --git a/components/ILIAS/Data/tests/URITest.php b/components/ILIAS/Data/tests/URITest.php index 0c9b62a741f6..cb017f6eb3da 100755 --- a/components/ILIAS/Data/tests/URITest.php +++ b/components/ILIAS/Data/tests/URITest.php @@ -83,17 +83,13 @@ class URITest extends TestCase ]; - /** - * @doesNotPerformAssertions - */ + #[\PHPUnit\Framework\Attributes\DoesNotPerformAssertions] public function test_init(): \ILIAS\Data\URI { return new ILIAS\Data\URI(self::URI_COMPLETE); } - /** - * @depends test_init - */ + #[\PHPUnit\Framework\Attributes\Depends('test_init')] public function test_ipv4(): void { $uri = new ILIAS\Data\URI(self::URI_COMPLETE_IPV4); @@ -106,10 +102,8 @@ public function test_ipv4(): void $this->assertEquals('fragment', $uri->getFragment()); } - /** - * @depends test_init - * @dataProvider provideIPv6addresses - */ + #[\PHPUnit\Framework\Attributes\DataProvider('provideIPv6addresses')] + #[\PHPUnit\Framework\Attributes\Depends('test_init')] public function testIPv6(string $host): void { $uri = new ILIAS\Data\URI('http://' . $host); @@ -146,9 +140,7 @@ public static function provideIPv6addresses(): array ]; } - /** - * @depends test_init - */ + #[\PHPUnit\Framework\Attributes\Depends('test_init')] public function test_localhost(): void { $uri = new ILIAS\Data\URI(self::URI_COMPLETE_LOCALHOST); @@ -162,9 +154,7 @@ public function test_localhost(): void } - /** - * @depends test_init - */ + #[\PHPUnit\Framework\Attributes\Depends('test_init')] public function test_components($uri): void { $this->assertEquals('g+it', $uri->getSchema()); @@ -176,17 +166,13 @@ public function test_components($uri): void $this->assertEquals('fragment', $uri->getFragment()); } - /** - * @depends test_init - */ + #[\PHPUnit\Framework\Attributes\Depends('test_init')] public function test_base_uri($uri): void { $this->assertEquals('g+it://github.com:8080/someaccount/somerepo/somerepo.git', $uri->getBaseURI()); } - /** - * @depends test_init - */ + #[\PHPUnit\Framework\Attributes\Depends('test_init')] public function test_base_uri_idempotent($uri): void { $base_uri = $uri->getBaseURI(); @@ -211,9 +197,7 @@ public function test_base_uri_idempotent($uri): void } - /** - * @depends test_init - */ + #[\PHPUnit\Framework\Attributes\Depends('test_init')] public function test_no_path(): void { $uri = new ILIAS\Data\URI(self::URI_NO_PATH_1); @@ -235,9 +219,7 @@ public function test_no_path(): void $this->assertEquals('fragment', $uri->getFragment()); } - /** - * @depends test_init - */ + #[\PHPUnit\Framework\Attributes\Depends('test_init')] public function test_no_query(): void { $uri = new ILIAS\Data\URI(self::URI_NO_QUERY_1); @@ -259,9 +241,7 @@ public function test_no_query(): void $this->assertEquals('fragment', $uri->getFragment()); } - /** - * @depends test_init - */ + #[\PHPUnit\Framework\Attributes\Depends('test_init')] public function test_authority_and_query(): void { $uri = new ILIAS\Data\URI(self::URI_AUTHORITY_AND_QUERY_1); @@ -283,9 +263,7 @@ public function test_authority_and_query(): void $this->assertNull($uri->getFragment()); } - /** - * @depends test_init - */ + #[\PHPUnit\Framework\Attributes\Depends('test_init')] public function test_authority_and_fragment(): void { $uri = new ILIAS\Data\URI(self::URI_AUTHORITY_AND_FRAGMENT); @@ -297,9 +275,8 @@ public function test_authority_and_fragment(): void $this->assertNull($uri->getQuery()); $this->assertEquals('fragment$,;:A!\'*+()ar_1=val_1&', $uri->getFragment()); } - /** - * @depends test_init - */ + + #[\PHPUnit\Framework\Attributes\Depends('test_init')] public function test_authority_path_fragment(): void { $uri = new ILIAS\Data\URI(self::URI_AUTHORITY_PATH_FRAGMENT); @@ -312,9 +289,7 @@ public function test_authority_path_fragment(): void $this->assertEquals('frag:A!\'*+()arment', $uri->getFragment()); } - /** - * @depends test_init - */ + #[\PHPUnit\Framework\Attributes\Depends('test_init')] public function test_path(): void { $uri = new ILIAS\Data\URI(self::URI_PATH); @@ -328,9 +303,7 @@ public function test_path(): void $this->assertEquals('git://git$,;hub.com:8080/someacc$,;ount/somerepo/somerepo.git', $uri->getBaseURI()); } - /** - * @depends test_init - */ + #[\PHPUnit\Framework\Attributes\Depends('test_init')] public function test_authority_only(): void { $uri = new ILIAS\Data\URI(self::URI_AUTHORITY_ONLY); @@ -344,63 +317,49 @@ public function test_authority_only(): void $this->assertEquals('git://git$,;hub.com', $uri->getBaseURI()); } - /** - * @depends test_init - */ + #[\PHPUnit\Framework\Attributes\Depends('test_init')] public function test_no_schema(): void { $this->expectException(TypeError::class); new ILIAS\Data\URI(self::URI_NO_SCHEMA); } - /** - * @depends test_init - */ + #[\PHPUnit\Framework\Attributes\Depends('test_init')] public function test_no_authority(): void { $this->expectException(TypeError::class); new ILIAS\Data\URI(self::URI_NO_AUTHORITY); } - /** - * @depends test_init - */ + #[\PHPUnit\Framework\Attributes\Depends('test_init')] public function test_wrong_char_in_schema(): void { $this->expectException(TypeError::class); new ILIAS\Data\URI(self::URI_WRONG_SCHEMA); } - /** - * @depends test_init - */ + #[\PHPUnit\Framework\Attributes\Depends('test_init')] public function test_wrong_authority_in_schema_1(): void { $this->expectException(InvalidArgumentException::class); new ILIAS\Data\URI(self::URI_WRONG_AUTHORITY_1); } - /** - * @depends test_init - */ + #[\PHPUnit\Framework\Attributes\Depends('test_init')] public function test_wrong_authority_in_schema_2(): void { $this->expectException(InvalidArgumentException::class); new ILIAS\Data\URI(self::URI_WRONG_AUTHORITY_2); } - /** - * @depends test_init - */ + #[\PHPUnit\Framework\Attributes\Depends('test_init')] public function test_uri_invalid(): void { $this->expectException(InvalidArgumentException::class); new ILIAS\Data\URI(self::URI_INVALID); } - /** - * @depends test_init - */ + #[\PHPUnit\Framework\Attributes\Depends('test_init')] public function test_realpctenc(): void { $uri = new ILIAS\Data\URI(self::URI_REALPCTENC); @@ -408,63 +367,49 @@ public function test_realpctenc(): void $this->assertEquals(self::PARAMS_REALPCTENC, $uri->getParameters()); } - /** - * @depends test_init - */ + #[\PHPUnit\Framework\Attributes\Depends('test_init')] public function test_fakepcenc(): void { $this->expectException(InvalidArgumentException::class); new ILIAS\Data\URI(self::URI_FAKEPCENC); } - /** - * @depends test_init - */ + #[\PHPUnit\Framework\Attributes\Depends('test_init')] public function test_alphadigit_start_host(): void { $this->expectException(InvalidArgumentException::class); new ILIAS\Data\URI(self::URI_HOST_ALPHADIG_START_1); } - /** - * @depends test_init - */ + #[\PHPUnit\Framework\Attributes\Depends('test_init')] public function test_alphadigit_start_host_2(): void { $this->expectException(InvalidArgumentException::class); new ILIAS\Data\URI(self::URI_HOST_ALPHADIG_START_2); } - /** - * @depends test_init - */ + #[\PHPUnit\Framework\Attributes\Depends('test_init')] public function test_alphadigit_start_host_3(): void { $this->expectException(InvalidArgumentException::class); new ILIAS\Data\URI(self::URI_HOST_ALPHADIG_START_3); } - /** - * @depends test_init - */ + #[\PHPUnit\Framework\Attributes\Depends('test_init')] public function test_alphadigit_start_host_4(): void { $this->expectException(InvalidArgumentException::class); new ILIAS\Data\URI(self::URI_HOST_ALPHADIG_START_4); } - /** - * @depends test_init - */ + #[\PHPUnit\Framework\Attributes\Depends('test_init')] public function test_alphadigit_start_host_5(): void { $this->expectException(InvalidArgumentException::class); new ILIAS\Data\URI(self::URI_HOST_ALPHADIG_START_5); } - /** - * @depends test_init - */ + #[\PHPUnit\Framework\Attributes\Depends('test_init')] public function test_with_schema($uri): void { $this->assertEquals('g+it', $uri->getSchema()); @@ -484,9 +429,7 @@ public function test_with_schema($uri): void $this->assertEquals('fragment', $uri->getFragment()); } - /** - * @depends test_with_schema - */ + #[\PHPUnit\Framework\Attributes\Depends('test_with_schema')] public function test_with_schema_invalid_1(): void { $this->expectException(InvalidArgumentException::class); @@ -494,9 +437,7 @@ public function test_with_schema_invalid_1(): void $uri->withSchema(''); } - /** - * @depends test_with_schema - */ + #[\PHPUnit\Framework\Attributes\Depends('test_with_schema')] public function test_with_schema_invalid_2(): void { $this->expectException(InvalidArgumentException::class); @@ -504,9 +445,7 @@ public function test_with_schema_invalid_2(): void $uri->withSchema('1aa'); } - /** - * @depends test_init - */ + #[\PHPUnit\Framework\Attributes\Depends('test_init')] public function test_with_port($uri): void { $this->assertEquals('g+it', $uri->getSchema()); @@ -535,9 +474,7 @@ public function test_with_port($uri): void } - /** - * @depends test_with_port - */ + #[\PHPUnit\Framework\Attributes\Depends('test_with_port')] public function test_with_port_invalid_1(): void { $this->expectException(TypeError::class); @@ -545,9 +482,7 @@ public function test_with_port_invalid_1(): void $uri->withPort('a111'); } - /** - * @depends test_with_port - */ + #[\PHPUnit\Framework\Attributes\Depends('test_with_port')] public function test_with_port_invalid_2(): void { $this->expectException(TypeError::class); @@ -555,9 +490,7 @@ public function test_with_port_invalid_2(): void $uri->withPort('foo'); } - /** - * @depends test_init - */ + #[\PHPUnit\Framework\Attributes\Depends('test_init')] public function test_with_host($uri): void { $this->assertEquals('g+it', $uri->getSchema()); @@ -577,10 +510,7 @@ public function test_with_host($uri): void $this->assertEquals('fragment', $uri->getFragment()); } - - /** - * @depends test_with_host - */ + #[\PHPUnit\Framework\Attributes\Depends('test_with_host')] public function test_with_host_invalid_1(): void { $this->expectException(InvalidArgumentException::class); @@ -588,9 +518,6 @@ public function test_with_host_invalid_1(): void $uri->withHost('-foo-.de'); } - /** - * @depends test_with_host - */ public function test_with_host_invalid_3(): void { $this->expectException(InvalidArgumentException::class); @@ -598,9 +525,7 @@ public function test_with_host_invalid_3(): void $uri->withHost(''); } - /** - * @depends test_with_host - */ + #[\PHPUnit\Framework\Attributes\Depends('test_with_host')] public function test_with_host_invalid_4(): void { $this->expectException(InvalidArgumentException::class); @@ -608,9 +533,7 @@ public function test_with_host_invalid_4(): void $uri->withHost('ilias.de">assertEquals('g+it', $uri->getSchema()); @@ -686,9 +609,7 @@ public function test_with_authority($uri): void $this->assertEquals('fragment', $uri->getFragment()); } - /** - * @depends test_with_authority - */ + #[\PHPUnit\Framework\Attributes\Depends('test_with_authority')] public function test_with_authority_invalid_1(): void { $this->expectException(InvalidArgumentException::class); @@ -696,9 +617,7 @@ public function test_with_authority_invalid_1(): void $uri->withAuthority('-foo-.de'); } - /** - * @depends test_with_authority - */ + #[\PHPUnit\Framework\Attributes\Depends('test_with_authority')] public function test_with_authority_invalid_2(): void { $this->expectException(InvalidArgumentException::class); @@ -707,9 +626,7 @@ public function test_with_authority_invalid_2(): void } - /** - * @depends test_with_authority - */ + #[\PHPUnit\Framework\Attributes\Depends('test_with_authority')] public function test_with_authority_invalid_3(): void { $this->expectException(InvalidArgumentException::class); @@ -717,9 +634,7 @@ public function test_with_authority_invalid_3(): void $uri->withHost('ilias.de:'); } - /** - * @depends test_with_authority - */ + #[\PHPUnit\Framework\Attributes\Depends('test_with_authority')] public function test_with_authority_invalid_4(): void { $this->expectException(InvalidArgumentException::class); @@ -727,9 +642,7 @@ public function test_with_authority_invalid_4(): void $uri->withHost('ilias.de: '); } - /** - * @depends test_with_authority - */ + #[\PHPUnit\Framework\Attributes\Depends('test_with_authority')] public function test_with_authority_invalid_5(): void { $this->expectException(InvalidArgumentException::class); @@ -737,9 +650,7 @@ public function test_with_authority_invalid_5(): void $uri->withHost('ilias.de:aaa'); } - /** - * @depends test_with_authority - */ + #[\PHPUnit\Framework\Attributes\Depends('test_with_authority')] public function test_with_authority_invalid_6(): void { $this->expectException(InvalidArgumentException::class); @@ -748,9 +659,7 @@ public function test_with_authority_invalid_6(): void } - /** - * @depends test_with_authority - */ + #[\PHPUnit\Framework\Attributes\Depends('test_with_authority')] public function test_with_authority_invalid_7(): void { $this->expectException(InvalidArgumentException::class); @@ -759,9 +668,7 @@ public function test_with_authority_invalid_7(): void } - /** - * @depends test_with_authority - */ + #[\PHPUnit\Framework\Attributes\Depends('test_with_authority')] public function test_with_authority_invalid_8(): void { $this->expectException(InvalidArgumentException::class); @@ -769,9 +676,7 @@ public function test_with_authority_invalid_8(): void $uri->withAuthority(' :80'); } - /** - * @depends test_init - */ + #[\PHPUnit\Framework\Attributes\Depends('test_init')] public function test_with_path($uri): void { $this->assertEquals('g+it', $uri->getSchema()); @@ -799,9 +704,7 @@ public function test_with_path($uri): void $this->assertEquals('fragment', $uri->getFragment()); } - /** - * @depends test_with_path - */ + #[\PHPUnit\Framework\Attributes\Depends('test_with_path')] public function test_with_path_invalid_1(): void { $this->expectException(InvalidArgumentException::class); @@ -809,9 +712,7 @@ public function test_with_path_invalid_1(): void $uri->withPath('/