From 3133520615dceb2df38a16b4b3b1166a1f9079e7 Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Fri, 8 Nov 2024 23:52:59 +0800 Subject: [PATCH] MDL-83424 core: Update component/plugin resolution to include new paths --- .grunt/components.js | 15 +-- .grunt/tasks/componentlibrary.js | 4 +- .grunt/tasks/ignorefiles.js | 6 +- .grunt/tasks/jsconfig.js | 4 +- .grunt/tasks/sass.js | 9 +- composer.json | 4 +- lib/components.json | 135 +++++++++++++++++++++++++ {public/lib => lib}/plugins.json | 0 public/lib/classes/component.php | 139 ++++++++++++++------------ public/lib/classes/plugin_manager.php | 2 +- public/lib/deprecatedlib.php | 4 +- public/lib/setup.php | 1 + public/lib/tests/component_test.php | 84 ++++++++-------- 13 files changed, 281 insertions(+), 126 deletions(-) create mode 100644 lib/components.json rename {public/lib => lib}/plugins.json (100%) diff --git a/.grunt/components.js b/.grunt/components.js index 44047e74b07..363f38c826e 100644 --- a/.grunt/components.js +++ b/.grunt/components.js @@ -47,8 +47,6 @@ const fetchComponentData = () => { const components = JSON.parse(fs.readFileSync(`${gruntFilePath}/lib/components.json`)); const pluginData = JSON.parse(fs.readFileSync(`${gruntFilePath}/lib/plugins.json`)); - componentData.pluginTypes = components.plugintypes; - const standardPlugins = Object.entries(pluginData.standard).map( ([pluginType, pluginNames]) => { return pluginNames.map(pluginName => `${pluginType}_${pluginName}`); @@ -56,18 +54,21 @@ const fetchComponentData = () => { ).reduce((acc, val) => acc.concat(val), []); // Build the list of moodle subsystems. - componentData.subsystems.lib = 'core'; - componentData.pathList.push(process.cwd() + path.sep + 'lib'); + componentData.subsystems['public/lib'] = 'core'; + componentData.pathList.push(`${process.cwd()}/public/lib`); for (const [component, thisPath] of Object.entries(components.subsystems)) { if (thisPath) { // Prefix "core_" to the front of the subsystems. componentData.subsystems[thisPath] = `core_${component}`; - componentData.pathList.push(process.cwd() + path.sep + thisPath); + componentData.pathList.push(`${process.cwd()}/${thisPath}`); } } // The list of components includes the list of subsystems. - componentData.components = {...componentData.subsystems}; + componentData.components = Object.fromEntries( + Object.entries(componentData.subsystems) + .map(([path, name]) => ([path, name])) + ); const subpluginAdder = (subpluginType, subpluginTypePath) => { glob.sync(`${subpluginTypePath}/*/version.php`).forEach(versionPath => { @@ -104,7 +105,7 @@ const fetchComponentData = () => { }); } else if (subpluginList.plugintypes) { Object.entries(subpluginList.plugintypes).forEach(([subpluginType, subpluginTypePath]) => { - subpluginAdder(subpluginType, subpluginTypePath); + subpluginAdder(subpluginType, `public/${subpluginTypePath}`); }); } } diff --git a/.grunt/tasks/componentlibrary.js b/.grunt/tasks/componentlibrary.js index 9b37ce8d671..308e85b9d8e 100644 --- a/.grunt/tasks/componentlibrary.js +++ b/.grunt/tasks/componentlibrary.js @@ -30,7 +30,7 @@ module.exports = grunt => { * @param {string} path * @returns {string} */ - const getCLPath = path => `admin/tool/componentlibrary/${path}`; + const getCLPath = path => `public/admin/tool/componentlibrary/${path}`; /** * Get a spawn handler. @@ -97,7 +97,7 @@ module.exports = grunt => { '--source-map', '--embed-sources', '--precision', 6, - '--load-path', process.cwd(), + '--load-path', `${process.cwd()}/public`, getCLPath('hugo/scss/docs.scss'), getCLPath('hugo/dist/css/docs.css'), ]); diff --git a/.grunt/tasks/ignorefiles.js b/.grunt/tasks/ignorefiles.js index feb2db43757..c90fae11283 100644 --- a/.grunt/tasks/ignorefiles.js +++ b/.grunt/tasks/ignorefiles.js @@ -84,10 +84,10 @@ module.exports = grunt => { const stylelintIgnores = [ '# Generated by "grunt ignorefiles"', '**/yui/build/*', - 'theme/boost/style/moodle.css', - 'theme/classic/style/moodle.css', + 'public/theme/boost/style/moodle.css', + 'public/theme/classic/style/moodle.css', 'jsdoc/styles/*.css', - 'admin/tool/componentlibrary/hugo/dist/css/docs.css', + 'public/admin/tool/componentlibrary/hugo/dist/css/docs.css', ].concat(thirdPartyPaths); grunt.file.write('.stylelintignore', stylelintIgnores.join('\n') + '\n'); diff --git a/.grunt/tasks/jsconfig.js b/.grunt/tasks/jsconfig.js index 9e32c2ebcbe..33fbfb50d40 100644 --- a/.grunt/tasks/jsconfig.js +++ b/.grunt/tasks/jsconfig.js @@ -43,8 +43,8 @@ module.exports = (grunt) => { const componentData = fetchComponentData().components; for (const [thisPath, component] of Object.entries(componentData)) { - jsconfigData.compilerOptions.paths[`${component}/*`] = [`${thisPath}/amd/src/*`]; - jsconfigData.include.push(`${thisPath}/amd/src/**/*`); + jsconfigData.compilerOptions.paths[`${component}/*`] = [`public/${thisPath}/amd/src/*`]; + jsconfigData.include.push(`public/${thisPath}/amd/src/**/*`); } grunt.file.write('jsconfig.json', JSON.stringify(jsconfigData, null, " ") + "\n"); diff --git a/.grunt/tasks/sass.js b/.grunt/tasks/sass.js index 6365e57eb67..4005cab123e 100644 --- a/.grunt/tasks/sass.js +++ b/.grunt/tasks/sass.js @@ -27,13 +27,16 @@ module.exports = grunt => { sass: { dist: { files: { - "theme/boost/style/moodle.css": "theme/boost/scss/preset/default.scss", - "theme/classic/style/moodle.css": "theme/classic/scss/classicgrunt.scss" + "public/theme/boost/style/moodle.css": "public/theme/boost/scss/preset/default.scss", + "public/theme/classic/style/moodle.css": "public/theme/classic/scss/classicgrunt.scss" } }, options: { implementation: require('sass'), - includePaths: ["theme/boost/scss/", "theme/classic/scss/"] + includePaths: [ + "public/theme/boost/scss/", + "public/theme/classic/scss/", + ] } }, }); diff --git a/composer.json b/composer.json index b15c852651b..d2fe183f6d4 100644 --- a/composer.json +++ b/composer.json @@ -22,8 +22,8 @@ "Moodle\\BehatExtension": "lib/behat/extension/" }, "psr-4": { - "core_testing\\": "lib/testing/classes/", - "core_phpunit\\": "lib/phpunit/classes/" + "core_testing\\": "public/lib/testing/classes/", + "core_phpunit\\": "public/lib/phpunit/classes/" } }, "minimum-stability": "dev", diff --git a/lib/components.json b/lib/components.json new file mode 100644 index 00000000000..5506a6688fc --- /dev/null +++ b/lib/components.json @@ -0,0 +1,135 @@ +{ + "plugintypes": { + "aiplacement": "public/ai/placement", + "aiprovider": "public/ai/provider", + "antivirus": "public/lib/antivirus", + "availability": "public/availability/condition", + "qtype": "public/question/type", + "mod": "public/mod", + "auth": "public/auth", + "calendartype": "public/calendar/type", + "communication": "public/communication/provider", + "customfield": "public/customfield/field", + "enrol": "public/enrol", + "message": "public/message/output", + "block": "public/blocks", + "media": "public/media/player", + "filter": "public/filter", + "editor": "public/lib/editor", + "format": "public/course/format", + "dataformat": "public/dataformat", + "profilefield": "public/user/profile/field", + "report": "public/report", + "coursereport": "public/course/report", + "gradeexport": "public/grade/export", + "gradeimport": "public/grade/import", + "gradepenalty": "public/grade/penalty", + "gradereport": "public/grade/report", + "gradingform": "public/grade/grading/form", + "mlbackend": "public/lib/mlbackend", + "webservice": "public/webservice", + "repository": "public/repository", + "portfolio": "public/portfolio", + "search": "public/search/engine", + "qbank": "public/question/bank", + "qbehaviour": "public/question/behaviour", + "qformat": "public/question/format", + "plagiarism": "public/plagiarism", + "tool": "public/admin/tool", + "cachestore": "public/cache/stores", + "cachelock": "public/cache/locks", + "fileconverter": "public/files/converter", + "contenttype": "public/contentbank/contenttype", + "theme": "public/theme", + "local": "public/local", + "h5plib": "public/h5p/h5plib", + "paygw": "public/payment/gateway", + "smsgateway": "public/sms/gateway" + }, + "subsystems": { + "ai": "public/ai", + "access": null, + "admin": "public/admin", + "adminpresets": "public/admin/presets", + "analytics": "public/analytics", + "antivirus": "public/lib/antivirus", + "auth": "public/auth", + "availability": "public/availability", + "backup": "public/backup/util/ui", + "badges": "public/badges", + "block": "public/blocks", + "blog": "public/blog", + "bulkusers": null, + "cache": "public/cache", + "calendar": "public/calendar", + "cohort": "public/cohort", + "comment": "public/comment", + "communication": "public/communication", + "competency": "public/competency", + "completion": "public/completion", + "contentbank": "public/contentbank", + "countries": null, + "course": "public/course", + "courseformat": "public/course/format", + "currencies": null, + "customfield": "public/customfield", + "dbtransfer": null, + "debug": null, + "editor": "public/lib/editor", + "edufields": null, + "enrol": "public/enrol", + "error": null, + "external": "public/lib/external", + "favourites": "public/favourites", + "filepicker": null, + "fileconverter": "public/files/converter", + "files": "public/files", + "filters": "public/filter", + "form": "public/lib/form", + "grades": "public/grade", + "grading": "public/grade/grading", + "group": "public/group", + "help": null, + "hub": null, + "h5p": "public/h5p", + "imscc": null, + "install": null, + "iso6392": null, + "langconfig": null, + "license": null, + "mathslib": null, + "media": "public/media", + "message": "public/message", + "mimetypes": null, + "mnet": "public/mnet", + "my": "public/my", + "notes": "public/notes", + "pagetype": null, + "payment" : "public/payment", + "pix": null, + "plagiarism": "public/plagiarism", + "plugin": null, + "portfolio": "public/portfolio", + "privacy": "public/privacy", + "question": "public/question", + "rating": "public/rating", + "report": "public/report", + "reportbuilder": "public/reportbuilder", + "repository": "public/repository", + "rss": "public/rss", + "role": "public/admin/roles", + "search": "public/search", + "sms": "public/sms", + "table": "public/lib/table", + "tag": "public/tag", + "timezones": null, + "user": "public/user", + "userkey": "public/lib/userkey", + "webservice": "public/webservice", + "xapi": "public/lib/xapi" + }, + "deprecatedplugintypes": + { + "mnetservice": "public/mnet/service" + } +} diff --git a/public/lib/plugins.json b/lib/plugins.json similarity index 100% rename from public/lib/plugins.json rename to lib/plugins.json diff --git a/public/lib/classes/component.php b/public/lib/classes/component.php index eb188c5b4d8..b51bc3c8508 100644 --- a/public/lib/classes/component.php +++ b/public/lib/classes/component.php @@ -110,64 +110,64 @@ class component { protected static $filestomap = ['lib.php', 'settings.php']; /** @var array associative array of PSR-0 namespaces and corresponding paths. */ protected static $psr0namespaces = [ - 'Mustache' => 'lib/mustache/src/Mustache', + 'Mustache' => 'public/lib/mustache/src/Mustache', ]; /** @var array> associative array of PRS-4 namespaces and corresponding paths. */ protected static $psr4namespaces = [ - \Aws::class => 'lib/aws-sdk/src', - \CFPropertyList::class => 'lib/plist/src/CFPropertyList', - \Complex::class => 'lib/phpspreadsheet/markbaker/complex/classes/src', - \Composer\Pcre::class => 'lib/composer/pcre/src', - \DI::class => 'lib/php-di/php-di/src', - \GeoIp2::class => 'lib/maxmind/GeoIp2/src', - \FastRoute::class => 'lib/nikic/fast-route/src', - \Firebase\JWT::class => 'lib/php-jwt/src', - \GuzzleHttp::class => 'lib/guzzlehttp/guzzle/src', - \GuzzleHttp\Promise::class => 'lib/guzzlehttp/promises/src', - \GuzzleHttp\Psr7::class => 'lib/guzzlehttp/psr7/src', - \Html2Text::class => 'lib/html2text/src', - \IMSGlobal\LTI::class => 'lib/ltiprovider/src', - \Invoker::class => 'lib/php-di/invoker/src', - \JmesPath::class => 'lib/jmespath/src', - \Kevinrob\GuzzleCache::class => 'lib/guzzlehttp/kevinrob/guzzlecache/src', - \Laravel\SerializableClosure::class => 'lib/laravel/serializable-closure/src', - \lbuchs\WebAuthn::class => 'lib/webauthn/src', - \libphonenumber::class => 'lib/giggsey/libphonenumber-for-php-lite/src', - \Matrix::class => 'lib/phpspreadsheet/markbaker/matrix/classes/src', - \MatthiasMullie\Minify::class => 'lib/minify/matthiasmullie-minify/src', - \MatthiasMullie\PathConverter::class => 'lib/minify/matthiasmullie-pathconverter/src', - \MaxMind\Db::class => 'lib/maxmind/MaxMind/src/MaxMind/Db', - \Michelf::class => 'lib/markdown/Michelf', + \Aws::class => 'public/lib/aws-sdk/src', + \CFPropertyList::class => 'public/lib/plist/src/CFPropertyList', + \Complex::class => 'public/lib/phpspreadsheet/markbaker/complex/classes/src', + \Composer\Pcre::class => 'public/lib/composer/pcre/src', + \DI::class => 'public/lib/php-di/php-di/src', + \GeoIp2::class => 'public/lib/maxmind/GeoIp2/src', + \FastRoute::class => 'public/lib/nikic/fast-route/src', + \Firebase\JWT::class => 'public/lib/php-jwt/src', + \GuzzleHttp::class => 'public/lib/guzzlehttp/guzzle/src', + \GuzzleHttp\Promise::class => 'public/lib/guzzlehttp/promises/src', + \GuzzleHttp\Psr7::class => 'public/lib/guzzlehttp/psr7/src', + \Html2Text::class => 'public/lib/html2text/src', + \IMSGlobal\LTI::class => 'public/lib/ltiprovider/src', + \Invoker::class => 'public/lib/php-di/invoker/src', + \JmesPath::class => 'public/lib/jmespath/src', + \Kevinrob\GuzzleCache::class => 'public/lib/guzzlehttp/kevinrob/guzzlecache/src', + \Laravel\SerializableClosure::class => 'public/lib/laravel/serializable-closure/src', + \lbuchs\WebAuthn::class => 'public/lib/webauthn/src', + \libphonenumber::class => 'public/lib/giggsey/libphonenumber-for-php-lite/src', + \Matrix::class => 'public/lib/phpspreadsheet/markbaker/matrix/classes/src', + \MatthiasMullie\Minify::class => 'public/lib/minify/matthiasmullie-minify/src', + \MatthiasMullie\PathConverter::class => 'public/lib/minify/matthiasmullie-pathconverter/src', + \MaxMind\Db::class => 'public/lib/maxmind/MaxMind/src/MaxMind/Db', + \Michelf::class => 'public/lib/markdown/Michelf', \MoodleHQ::class => [ - 'lib/rtlcss/src/MoodleHQ', + 'public/lib/rtlcss/src/MoodleHQ', ], - \OpenSpout::class => 'lib/openspout/src', - \Packback\Lti1p3::class => 'lib/lti1p3/src', - \PHPMailer\PHPMailer::class => 'lib/phpmailer/src', - \PhpOffice\PhpSpreadsheet::class => 'lib/phpspreadsheet/phpspreadsheet/src/PhpSpreadsheet', - \PhpXmlRpc::class => 'lib/phpxmlrpc/src', - \Phpml::class => 'lib/mlbackend/php/phpml/src/Phpml', - \Psr\Clock::class => 'lib/psr/clock/src', - \Psr\Container::class => 'lib/psr/container/src', - \Psr\EventDispatcher::class => 'lib/psr/event-dispatcher/src', - \Psr\Http\Client::class => 'lib/psr/http-client/src', + \OpenSpout::class => 'public/lib/openspout/src', + \Packback\Lti1p3::class => 'public/lib/lti1p3/src', + \PHPMailer\PHPMailer::class => 'public/lib/phpmailer/src', + \PhpOffice\PhpSpreadsheet::class => 'public/lib/phpspreadsheet/phpspreadsheet/src/PhpSpreadsheet', + \PhpXmlRpc::class => 'public/lib/phpxmlrpc/src', + \Phpml::class => 'public/lib/mlbackend/php/phpml/src/Phpml', + \Psr\Clock::class => 'public/lib/psr/clock/src', + \Psr\Container::class => 'public/lib/psr/container/src', + \Psr\EventDispatcher::class => 'public/lib/psr/event-dispatcher/src', + \Psr\Http\Client::class => 'public/lib/psr/http-client/src', \Psr\Http\Message::class => [ - 'lib/psr/http-factory/src', - 'lib/psr/http-message/src', + 'public/lib/psr/http-factory/src', + 'public/lib/psr/http-message/src', ], \Psr\Http\Server::class => [ - "lib/psr/http-server-handler/src", - "lib/psr/http-server-middleware/src", + "public/lib/psr/http-server-handler/src", + "public/lib/psr/http-server-middleware/src", ], - \Psr\Log::class => "lib/psr/log/src", - \Psr\SimpleCache::class => 'lib/psr/simple-cache/src', - \RedeyeVentures::class => 'lib/geopattern-php/src', - \Sabberworm\CSS::class => 'lib/php-css-parser/src', - \ScssPhp\ScssPhp::class => 'lib/scssphp/src', - \SimplePie::class => 'lib/simplepie/src', - \Slim::class => 'lib/slim/slim/Slim', - \Spatie\Cloneable::class => 'lib/spatie/php-cloneable/src', - \ZipStream::class => 'lib/zipstream/src', + \Psr\Log::class => "public/lib/psr/log/src", + \Psr\SimpleCache::class => 'public/lib/psr/simple-cache/src', + \RedeyeVentures::class => 'public/lib/geopattern-php/src', + \Sabberworm\CSS::class => 'public/lib/php-css-parser/src', + \ScssPhp\ScssPhp::class => 'public/lib/scssphp/src', + \SimplePie::class => 'public/lib/simplepie/src', + \Slim::class => 'public/lib/slim/slim/Slim', + \Spatie\Cloneable::class => 'public/lib/spatie/php-cloneable/src', + \ZipStream::class => 'public/lib/zipstream/src', ]; /** @@ -180,13 +180,13 @@ class component { * @var array */ protected static $composerautoloadfiles = [ - 'lib/aws-sdk/src/functions.php', - 'lib/guzzlehttp/guzzle/src/functions_include.php', - 'lib/jmespath/src/JmesPath.php', - 'lib/nikic/fast-route/src/functions.php', - 'lib/php-di/php-di/src/functions.php', - 'lib/ralouphie/getallheaders/src/getallheaders.php', - 'lib/symfony/deprecation-contracts/function.php', + 'public/lib/aws-sdk/src/functions.php', + 'public/lib/guzzlehttp/guzzle/src/functions_include.php', + 'public/lib/jmespath/src/JmesPath.php', + 'public/lib/nikic/fast-route/src/functions.php', + 'public/lib/php-di/php-di/src/functions.php', + 'public/lib/ralouphie/getallheaders/src/getallheaders.php', + 'public/lib/symfony/deprecation-contracts/function.php', ]; /** @@ -202,7 +202,7 @@ class component { // Load any composer-driven autoload files. // This is intended to mimic the behaviour of the standard Composer Autoloader. foreach (static::$composerautoloadfiles as $file) { - $path = dirname(__DIR__, 2) . '/' . $file; + $path = dirname(__DIR__, 3) . '/' . $file; if (file_exists($path)) { require_once($path); } @@ -341,7 +341,8 @@ class component { // No, move to the next prefix. return false; } - $path = $CFG->dirroot . '/' . $path; + + $path = $CFG->root . '/' . $path; // Get the relative class name. $relativeclass = substr($class, $len); @@ -700,7 +701,7 @@ $cache = ' . var_export($cache, true) . '; } } - $info[$subsystem] = empty($path) ? null : "{$CFG->dirroot}/{$path}"; + $info[$subsystem] = empty($path) ? null : "{$CFG->root}/{$path}"; } return $info; @@ -743,7 +744,7 @@ $cache = ' . var_export($cache, true) . '; if ($CFG->admin !== 'admin' && strpos($path, 'admin/') === 0) { $path = $CFG->admin . substr($path, 5); } - $plugintypesmap[$sourcekey][$plugintype] = "{$CFG->dirroot}/{$path}"; + $plugintypesmap[$sourcekey][$plugintype] = "{$CFG->root}/{$path}"; } } @@ -863,7 +864,7 @@ $cache = ' . var_export($cache, true) . '; */ protected static function fetch_component_source(string $key) { if (null === self::$componentsource) { - self::$componentsource = (array) json_decode(file_get_contents(__DIR__ . '/../components.json')); + self::$componentsource = (array) json_decode(file_get_contents(dirname(__DIR__, 3) . '/lib/components.json')); } return !empty(self::$componentsource[$key]) ? (array) self::$componentsource[$key] : []; @@ -879,8 +880,8 @@ $cache = ' . var_export($cache, true) . '; $types = []; $subplugins = []; - if (str_contains($ownerdir, $CFG->dirroot)) { - $plugindir = substr($ownerdir, strlen($CFG->dirroot) + 1); + if (str_contains($ownerdir, $CFG->root)) { + $plugindir = substr($ownerdir, strlen($CFG->root) + 1); } else { $realownerdir = realpath($ownerdir); $realroot = realpath(dirname(__DIR__, 2)); @@ -908,6 +909,10 @@ $cache = ' . var_export($cache, true) . '; "See MDL-83705 for further information.", ); $subplugins = (array) $subpluginsjson->plugintypes; + array_walk( + $subplugins, + fn (string &$path): string => $path = str_starts_with($path, 'public/') ? $path : "public/{$path}", + ); } else if (empty($subpluginjson->deprecatedplugintypes) && empty($subpluginsjson->deletedplugintypes)) { error_log("No plugintypes defined in $ownerdir/db/subplugins.json"); } @@ -932,6 +937,10 @@ $cache = ' . var_export($cache, true) . '; if (property_exists($subpluginsjson, 'subplugintypes') && property_exists($subpluginsjson, 'plugintypes')) { $subplugintypes = (array) $subpluginsjson->subplugintypes; $plugintypes = (array) $subpluginsjson->plugintypes; + array_walk( + $plugintypes, + fn (string &$path): string => $path = str_starts_with($path, 'public/') ? $path : "public/{$path}", + ); if (count($subplugintypes) !== count(($plugintypes))) { error_log("Subplugintypes and plugintypes are not in sync in $ownerdir/db/subplugins.json"); } @@ -968,11 +977,11 @@ $cache = ' . var_export($cache, true) . '; if ($CFG->admin !== 'admin' && strpos($dir, 'admin/') === 0) { $dir = preg_replace('|^admin/|', "$CFG->admin/", $dir); } - if (!is_dir("$CFG->dirroot/$dir")) { + if (!is_dir("$CFG->root/$dir")) { error_log("Invalid subtype directory '$dir' detected in '$ownerdir'."); continue; } - $types[$key][$subtype] = "$CFG->dirroot/$dir"; + $types[$key][$subtype] = "$CFG->root/$dir"; } } diff --git a/public/lib/classes/plugin_manager.php b/public/lib/classes/plugin_manager.php index d49e1a2e2a1..3aac2db8499 100644 --- a/public/lib/classes/plugin_manager.php +++ b/public/lib/classes/plugin_manager.php @@ -347,7 +347,7 @@ class plugin_manager { */ protected static function load_standard_plugins(): stdClass { if (static::$standardplugincache === null) { - $data = file_get_contents(dirname(__DIR__) . '/plugins.json'); + $data = file_get_contents(dirname(__DIR__, 3) . '/lib/plugins.json'); static::$standardplugincache = json_decode($data, false); } diff --git a/public/lib/deprecatedlib.php b/public/lib/deprecatedlib.php index 00408da725e..117c3dbb490 100644 --- a/public/lib/deprecatedlib.php +++ b/public/lib/deprecatedlib.php @@ -90,11 +90,11 @@ function get_plugin_types($fullpaths = true) { debugging('Short paths are deprecated when using get_plugin_types(), please fix the code to use fullpaths instead.', DEBUG_DEVELOPER); - $dlength = strlen($CFG->dirroot); + $dlength = strlen($CFG->root); foreach ($types as $k => $v) { if ($k === 'theme') { - $types[$k] = 'theme'; + $types[$k] = 'public/theme'; continue; } $types[$k] = substr($v, $dlength+1); diff --git a/public/lib/setup.php b/public/lib/setup.php index eb4c8593d31..88c4c236ec7 100644 --- a/public/lib/setup.php +++ b/public/lib/setup.php @@ -60,6 +60,7 @@ if (!isset($CFG)) { // We can detect real dirroot path reliably since PHP 4.0.2, // it can not be anything else, there is no point in having this in config.php $CFG->dirroot = dirname(__DIR__); +$CFG->root = dirname($CFG->dirroot); // File permissions on created directories in the $CFG->dataroot if (!isset($CFG->directorypermissions)) { diff --git a/public/lib/tests/component_test.php b/public/lib/tests/component_test.php index 6868467bb0c..c74caefbb41 100644 --- a/public/lib/tests/component_test.php +++ b/public/lib/tests/component_test.php @@ -148,7 +148,7 @@ final class component_test extends \advanced_testcase { $plugintypes = component::get_plugin_types(); foreach ($plugintypes as $plugintype => $fulldir) { - $this->assertStringStartsWith("$CFG->dirroot/", $fulldir); + $this->assertStringStartsWith("$CFG->root/", $fulldir); } } @@ -170,7 +170,7 @@ final class component_test extends \advanced_testcase { $this->resetDebugging(); foreach ($plugintypes as $plugintype => $fulldir) { - $this->assertSame($fulldir, $CFG->dirroot . '/' . $realplugintypes[$plugintype]); + $this->assertSame($fulldir, $CFG->root . '/' . $realplugintypes[$plugintype]); } } @@ -747,12 +747,12 @@ final class component_test extends \advanced_testcase { $directory = str_replace('\\', '/', $CFG->dirroot) . "/lib/tests/fixtures/component/"; $psr0 = [ - 'psr0' => 'lib/tests/fixtures/component/psr0', - 'overlap' => 'lib/tests/fixtures/component/overlap', + 'psr0' => 'public/lib/tests/fixtures/component/psr0', + 'overlap' => 'public/lib/tests/fixtures/component/overlap', ]; $psr4 = [ - 'psr4' => 'lib/tests/fixtures/component/psr4', - 'overlap' => 'lib/tests/fixtures/component/overlap', + 'psr4' => 'public/lib/tests/fixtures/component/psr4', + 'overlap' => 'public/lib/tests/fixtures/component/overlap', ]; return [ 'PSR-0 Classloading - Root' => [ @@ -1038,21 +1038,21 @@ final class component_test extends \advanced_testcase { 'prefix' => "Test", 'path' => 'test/src', 'separators' => ['_'], - 'result' => $CFG->dirroot . "/test/src/With/Underscores.php", + 'result' => $CFG->root . "/test/src/With/Underscores.php", ], 'Getting a file with slashes' => [ 'classname' => 'Test\\With\\Slashes', 'prefix' => "Test", 'path' => 'test/src', 'separators' => ['\\'], - 'result' => $CFG->dirroot . "/test/src/With/Slashes.php", + 'result' => $CFG->root . "/test/src/With/Slashes.php", ], 'Getting a file with multiple namespaces' => [ 'classname' => 'Test\\With\\Multiple\\Namespaces', 'prefix' => "Test\\With", 'path' => 'test/src', 'separators' => ['\\'], - 'result' => $CFG->dirroot . "/test/src/Multiple/Namespaces.php", + 'result' => $CFG->root . "/test/src/Multiple/Namespaces.php", ], 'Getting a file with multiple namespaces (non-existent)' => [ 'classname' => 'Nonexistent\\Namespace\\Test', @@ -1287,7 +1287,7 @@ final class component_test extends \advanced_testcase { foreach ($xml as $lib) { $base = realpath(dirname($xmlpath)); $fullpath = "{$base}/{$lib->location}"; - $relativepath = substr($fullpath, strlen($CFG->dirroot)); + $relativepath = substr($fullpath, strlen($CFG->root)); $libs[$relativepath] = [ 'name' => (string) $lib->name, @@ -1421,23 +1421,26 @@ final class component_test extends \advanced_testcase { $this->resetAfterTest(); $vfileroot = \org\bovigo\vfs\vfsStream::setup('root', null, [ - 'plugintype' => [ - 'exampleplugin' => [ - 'db' => [ - 'subplugins.json' => json_encode([ - 'subplugintypes' => [ - 'exampleplugina' => 'apples', - ], - ]), - 'subplugins.php' => '', + 'public' => [ + 'plugintype' => [ + 'exampleplugin' => [ + 'db' => [ + 'subplugins.json' => json_encode([ + 'subplugintypes' => [ + 'exampleplugina' => 'apples', + ], + ]), + 'subplugins.php' => '', + ], + 'apples' => [], ], - 'apples' => [], ], ], ]); - $CFG->dirroot = $vfileroot->url(); - $pluginroot = $vfileroot->getChild('plugintype/exampleplugin'); + $CFG->root = $vfileroot->url(); + $CFG->dirroot = $vfileroot->getChild('public')->url(); + $pluginroot = $vfileroot->getChild('public/plugintype/exampleplugin'); $rcm = new \ReflectionMethod(\core\component::class, 'fetch_subtypes'); $subplugins = $rcm->invoke(null, $pluginroot->url()); @@ -1457,23 +1460,26 @@ final class component_test extends \advanced_testcase { $this->resetAfterTest(); $vfileroot = \org\bovigo\vfs\vfsStream::setup('root', null, [ - 'plugintype' => [ - 'exampleplugin' => [ - 'db' => [ - 'subplugins.json' => json_encode([ - 'plugintypes' => [ - 'exampleplugina' => 'plugintype/exampleplugin/apples', - ], - ]), - 'subplugins.php' => '', + 'public' => [ + 'plugintype' => [ + 'exampleplugin' => [ + 'db' => [ + 'subplugins.json' => json_encode([ + 'plugintypes' => [ + 'exampleplugina' => 'plugintype/exampleplugin/apples', + ], + ]), + 'subplugins.php' => '', + ], + 'apples' => [], ], - 'apples' => [], ], ], ]); - $CFG->dirroot = $vfileroot->url(); - $pluginroot = $vfileroot->getChild('plugintype/exampleplugin'); + $CFG->root = $vfileroot->url(); + $CFG->dirroot = $vfileroot->getchild('public')->url(); + $pluginroot = $vfileroot->getChild('public/plugintype/exampleplugin'); $logdir = make_request_directory(); $logfile = "{$logdir}/error.log"; @@ -1643,7 +1649,7 @@ final class component_test extends \advanced_testcase { // Inject the 'fake' plugin type. $this->add_full_mocked_plugintype( plugintype: 'fake', - path: 'lib/tests/fixtures/fakeplugins/fake' + path: 'public/lib/tests/fixtures/fakeplugins/fake', ); $componenthashbefore = component::get_all_component_hash(); @@ -1715,7 +1721,7 @@ final class component_test extends \advanced_testcase { // Inject the 'fake' plugin type. $this->add_full_mocked_plugintype( plugintype: 'fake', - path: 'lib/tests/fixtures/fakeplugins/fake', + path: 'public/lib/tests/fixtures/fakeplugins/fake', ); // Delete the fake plugintype via mocking component sources. @@ -1766,7 +1772,7 @@ final class component_test extends \advanced_testcase { // 3. fulldeletedsubtype_demo: a deleted subplugin type. $this->add_full_mocked_plugintype( plugintype: 'fake', - path: 'lib/tests/fixtures/fakeplugins/fake', + path: 'public/lib/tests/fixtures/fakeplugins/fake', subpluginsupport: true ); $this->assert_deprecation_apis_subplugins(); @@ -1787,7 +1793,7 @@ final class component_test extends \advanced_testcase { // 3. fulldeletedsubtype_demo: a deleted subplugin type. $this->add_full_mocked_plugintype( plugintype: 'fake', - path: 'lib/tests/fixtures/fakeplugins/fake', + path: 'public/lib/tests/fixtures/fakeplugins/fake', subpluginsupport: true ); @@ -1816,7 +1822,7 @@ final class component_test extends \advanced_testcase { // 3. fulldeletedsubtype_demo: a deleted subplugin type. $this->add_full_mocked_plugintype( plugintype: 'fake', - path: 'lib/tests/fixtures/fakeplugins/fake', + path: 'public/lib/tests/fixtures/fakeplugins/fake', subpluginsupport: true ); -- 2.43.0