From 71a4f834e27d4c6d584b1b9158fb8c8d96813050 Mon Sep 17 00:00:00 2001 From: Cameron Ball Date: Fri, 11 Mar 2022 13:09:19 +0800 Subject: [PATCH 1/6] Fix public file check in lib.php --- classes/local.php | 10 +++++----- filter.php | 6 +++--- lib.php | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/classes/local.php b/classes/local.php index 1cb693d..88d0702 100644 --- a/classes/local.php +++ b/classes/local.php @@ -70,11 +70,11 @@ public static function get_optimised_path(\stored_file $file, $filepath, $asfile $maxwidth = 480; } - if ($file->get_imageinfo()['width'] <= $maxwidth && self::file_is_public($file)) { + if ($file->get_imageinfo()['width'] <= $maxwidth && self::file_is_public($file->get_contenthash())) { $maxwidth = '-1'; } - if (self::file_is_public($file)) { + if (self::file_is_public($file->get_contenthash())) { return '/' . \context_system::instance()->id . '/filter_imageopt/public/1/imageopt/' . $maxwidth . '/' . $file->get_contenthash(); } @@ -111,7 +111,7 @@ public static function get_optimised_src(\stored_file $file, $originalsrc, $opti global $CFG; $classname = '\\filter_imageopt\\componentsupport\\'.$file->get_component(); $optimisedsrc = null; - if (!self::file_is_public($file) && class_exists($classname) && method_exists($classname, 'get_optimised_src')) { + if (!self::file_is_public($file->get_contenthash()) && class_exists($classname) && method_exists($classname, 'get_optimised_src')) { $optimisedsrc = $classname::get_optimised_src($file, $originalsrc); } if (empty($optimisedsrc)) { @@ -266,7 +266,7 @@ public static function file_pluginfile($relativepath) { file_pluginfile($relativepath, $forcedownload, $preview, $offline, $embed); } - public static function file_is_public(stored_file $file): bool { + public static function file_is_public(string $contenthash): bool { global $DB; $minduplicates = get_config('filter_imageopt', 'minduplicates'); @@ -291,6 +291,6 @@ public static function file_is_public(stored_file $file): bool { $publicfilescache->set($key, array_column($publicfiles, 'contenthash')); } - return in_array($file->get_contenthash(), $publicfilescache->get($key)); + return in_array($contenthash, $publicfilescache->get($key)); } } diff --git a/filter.php b/filter.php index 4246fb3..fa56398 100644 --- a/filter.php +++ b/filter.php @@ -155,7 +155,7 @@ public function image_opt_url(stored_file $file, $originalsrc) { $originalpath = local::get_img_path_from_src($originalsrc); $urlpathid = local::add_url_path_to_queue($originalpath); - if ($file->get_imageinfo()['width'] <= $maxwidth && local::file_is_public($file)) { + if ($file->get_imageinfo()['width'] <= $maxwidth && local::file_is_public($file->get_contenthash())) { $maxwidth = '-1'; } @@ -199,7 +199,7 @@ private function process_img_tag(array $match) { } $imageinfo = (object) $file->get_imageinfo(); - if ($imageinfo->width <= $maxwidth && !local::file_is_public($file)) { + if ($imageinfo->width <= $maxwidth && !local::file_is_public($file->get_contenthash())) { return $match[0]; } @@ -319,7 +319,7 @@ private function apply_img_tag($match, stored_file $file, $originalsrc, $optimis $maxwidth = $this->config->maxwidth; - if ($imageinfo->width < $maxwidth && !local::file_is_public($file)) { + if ($imageinfo->width < $maxwidth && !local::file_is_public($file->get_contenthash())) { return $match[0]; } diff --git a/lib.php b/lib.php index c137c17..1ea4d0d 100644 --- a/lib.php +++ b/lib.php @@ -48,7 +48,7 @@ function filter_imageopt_pluginfile($course, $cm, $context, $filearea, $args, $f return false; } - if (!local::file_is_public($file)) { + if (!local::file_is_public($args[3])) { return false; } @@ -64,7 +64,7 @@ function filter_imageopt_pluginfile($course, $cm, $context, $filearea, $args, $f $originalfile = local::get_img_file($originalimgpath); $optimisedurlpath = local::get_optimised_path($originalfile, $originalimgpath, false); $optimisedpath = local::get_optimised_path($originalfile, $originalimgpath); - $fileispublic = local::file_is_public($originalfile); + $fileispublic = local::file_is_public($originalfile->get_contenthash()); $optimisedfile = local::get_img_file($optimisedpath); if ($optimisedfile) { From c10fe099b7abc69d8ee4c3335f06f5558e939d4f Mon Sep 17 00:00:00 2001 From: Cameron Ball Date: Mon, 14 Mar 2022 09:50:41 +0800 Subject: [PATCH 2/6] Fix GHA failures --- .github/workflows/moodle-ci.yml | 110 ++++++++++++++++---------------- amd/build/appear.min.js | 5 +- amd/build/appear.min.js.map | 2 +- amd/build/imageopt.min.js | 25 +++++++- amd/build/imageopt.min.js.map | 2 +- amd/src/imageopt.js | 2 +- classes/local.php | 14 +++- db/caches.php | 2 +- tests/local_test.php | 20 +++--- 9 files changed, 105 insertions(+), 77 deletions(-) diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml index 92c52c0..d50d612 100644 --- a/.github/workflows/moodle-ci.yml +++ b/.github/workflows/moodle-ci.yml @@ -1,17 +1,18 @@ -name: Moodle Plugin CI +name: Run all tests +# Run this workflow every time a new commit pushed to your repository on: [push, pull_request] jobs: - test: - runs-on: ubuntu-18.04 - + setup: + runs-on: ubuntu-latest services: postgres: - image: postgres:9.6 + image: postgres:10 env: POSTGRES_USER: 'postgres' POSTGRES_HOST_AUTH_METHOD: 'trust' + # Health check to wait for postgres to start. ports: - 5432:5432 options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 3 @@ -23,96 +24,93 @@ jobs: ports: - 3306:3306 options: --health-cmd="mysqladmin ping" --health-interval 10s --health-timeout 5s --health-retries 3 - strategy: fail-fast: false matrix: - include: - - php: '7.4' - moodle-branch: 'MOODLE_39_STABLE' - database: pgsql - - php: '7.4' - moodle-branch: 'MOODLE_39_STABLE' - database: mariadb - - php: '7.2' - moodle-branch: 'MOODLE_39_STABLE' - database: pgsql - - php: '7.2' - moodle-branch: 'MOODLE_39_STABLE' - database: mariadb - + php-versions: ['7.3', '7.4'] + database: ['pgsql', 'mariadb'] steps: - name: Check out repository code uses: actions/checkout@v2 with: + # Clone in plugin subdir, so we can setup CI in default directory. path: plugin - - name: Setup PHP ${{ matrix.php }} - uses: shivammathur/setup-php@v2 + - name: Install node + uses: actions/setup-node@v1 with: - php-version: ${{ matrix.php }} - coverage: none + # TODO: Check if we can support .nvmrc + node-version: '14.15.0' - - name: Initialise moodle-plugin-ci + - name: Setup PHP environment + uses: shivammathur/setup-php@v2 #https://github.com/shivammathur/setup-php + with: + php-version: ${{ matrix.php-versions }} + extensions: mbstring, pgsql, mysqli + tools: phpunit + + - name: Deploy moodle-plugin-ci run: | composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^3 + # Add dirs to $PATH echo $(cd ci/bin; pwd) >> $GITHUB_PATH echo $(cd ci/vendor/bin; pwd) >> $GITHUB_PATH + # PHPUnit depends on en_AU.UTF-8 locale sudo locale-gen en_AU.UTF-8 - echo "NVM_DIR=$HOME/.nvm" >> $GITHUB_ENV - name: Install moodle-plugin-ci - run: moodle-plugin-ci install --plugin ./plugin --db-host=127.0.0.1 + # Need explicit IP to stop mysql client fail on attempt to use unix socket. + run: moodle-plugin-ci install -vvv --plugin ./plugin --db-host=127.0.0.1 env: DB: ${{ matrix.database }} - MOODLE_BRANCH: ${{ matrix.moodle-branch }} - MUSTACHE_IGNORE_NAMES: 'mobile_*.mustache' + # TODO: Omitted MOODLE_BRANCH results in regex failure, investigate. + MOODLE_BRANCH: 'master' - - name: PHP Lint + - name: Run phplint if: ${{ always() }} run: moodle-plugin-ci phplint - - name: PHP Copy/Paste Detector - continue-on-error: true # This step will show errors but will not fail + - name: Run phpcpd if: ${{ always() }} - run: moodle-plugin-ci phpcpd + run: moodle-plugin-ci phpcpd || true - - name: PHP Mess Detector - continue-on-error: true # This step will show errors but will not fail + - name: Run phpmd if: ${{ always() }} run: moodle-plugin-ci phpmd - - name: Moodle Code Checker - if: ${{ always() }} - run: moodle-plugin-ci codechecker --max-warnings 0 - - - name: Moodle PHPDoc Checker + - name: Run codechecker if: ${{ always() }} - run: moodle-plugin-ci phpdoc + run: moodle-plugin-ci codechecker - - name: Validating + - name: Run validate if: ${{ always() }} run: moodle-plugin-ci validate - - name: Check upgrade savepoints + - name: Run savepoints if: ${{ always() }} run: moodle-plugin-ci savepoints - - name: Mustache Lint + - name: Run mustache if: ${{ always() }} - run: moodle-plugin-ci mustache + run: moodle-plugin-ci phpcpd || true + env: + MUSTACHE_IGNORE_NAMES: mobile_teacher_form.mustache - - name: Grunt + - name: Run grunt if: ${{ always() }} - run: moodle-plugin-ci grunt --max-lint-warnings 0 + run: moodle-plugin-ci grunt - - name: PHPUnit tests + - name: Run phpdoc if: ${{ always() }} - run: | - moodle-plugin-ci phpunit - cd moodle - vendor/bin/phpunit --fail-on-risky --disallow-test-output -v admin/tool/dataprivacy/tests/metadata_registry_test.php - vendor/bin/phpunit --fail-on-risky --disallow-test-output -v lib/tests/externallib_test.php - vendor/bin/phpunit --fail-on-risky --disallow-test-output -v privacy/tests/provider_test.php - - name: Behat features + run: moodle-plugin-ci phpdoc + + - name: Run phpunit + if: ${{ always() }} + run: | + moodle-plugin-ci phpunit + cd moodle + vendor/bin/phpunit --fail-on-risky --disallow-test-output --filter tool_dataprivacy_metadata_registry_testcase + vendor/bin/phpunit --fail-on-risky --disallow-test-output --testsuite core_privacy_testsuite --filter provider_testcase + + - name: Run behat if: ${{ always() }} - run: moodle-plugin-ci behat --profile chrome \ No newline at end of file + run: moodle-plugin-ci behat --profile chrome diff --git a/amd/build/appear.min.js b/amd/build/appear.min.js index 2311f30..4335bf8 100644 --- a/amd/build/appear.min.js +++ b/amd/build/appear.min.js @@ -1,2 +1,3 @@ -define ("filter_imageopt/appear",["jquery"],function(a){a();(function(a){var e=[],f=!1,g=!1,h={interval:250,force_process:!1},i={},j=a(window),k=[];function b(b){return a(b).filter(function(){return a(this).is(":appeared")})}function c(){g=!1;for(var a=0,c=e.length,d;a=e&&h-k<=e+j.height()&&g+c.width()+l>=d&&g-l<=d+j.width()){return!0}else{return!1}};a.fn.extend({appear:function appear(b){i=a.extend({},h,b||{});var e=this.selector||this;if(!f){var j=function(){if(g){return}g=!0;setTimeout(c,i.interval)};a(window).scroll(j).resize(j);f=!0}if(i.force_process){setTimeout(c,i.interval)}d(e);return a(e)}});a.extend({force_appear:function force_appear(){if(f){c();return!0}return!1}})})(function(){if("undefined"!=typeof module){return require("jquery")}else{return a}}());return a}); -//# sourceMappingURL=appear.min.js.map +define("filter_imageopt/appear",["jquery"],(function(jQuery){return jQuery(),function($){var selectors=[],check_binded=!1,check_lock=!1,defaults={interval:250,force_process:!1},options={},$window=$(window),$prior_appeared=[];function process(){check_lock=!1;for(var index=0,selectorsLength=selectors.length;index=window_top&&top-appeartopoffset<=window_top+$window.height()&&left+$element.width()+appearleftoffset>=window_left&&left-appearleftoffset<=window_left+$window.width()},$.fn.extend({appear:function(opts){options=$.extend({},defaults,opts||{});var selector=this.selector||this;if(!check_binded){var on_check=function(){check_lock||(check_lock=!0,setTimeout(process,options.interval))};$(window).scroll(on_check).resize(on_check),check_binded=!0}return options.force_process&&setTimeout(process,options.interval),function(selector){selectors.push(selector),$prior_appeared.push()}(selector),$(selector)}}),$.extend({force_appear:function(){return!!check_binded&&(process(),!0)}})}("undefined"!=typeof module?require("jquery"):jQuery),jQuery})); + +//# sourceMappingURL=appear.min.js.map \ No newline at end of file diff --git a/amd/build/appear.min.js.map b/amd/build/appear.min.js.map index 0afe215..550cb77 100644 --- a/amd/build/appear.min.js.map +++ b/amd/build/appear.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/appear.js"],"names":["define","jQuery","$","selectors","check_binded","check_lock","defaults","interval","force_process","options","$window","window","$prior_appeared","appeared","selector","filter","is","process","index","selectorsLength","length","$appeared","trigger","$disappeared","not","add_selector","push","expr","element","$element","window_left","scrollLeft","window_top","scrollTop","offset","left","top","appeartopoffset","data","appearleftoffset","height","width","fn","extend","appear","opts","on_check","setTimeout","scroll","resize","force_appear","module","require"],"mappings":"AAAAA,OAAM,0BAAC,CAAC,QAAD,CAAD,CACF,SAASC,CAAT,CAAiB,CAELA,CACR,GAYC,CAAC,SAASC,CAAT,CAAY,IACNC,CAAAA,CAAS,CAAG,EADN,CAGNC,CAAY,GAHN,CAINC,CAAU,GAJJ,CAKNC,CAAQ,CAAG,CACXC,QAAQ,CAAE,GADC,CAEXC,aAAa,GAFF,CALL,CASNC,CAAO,CAAG,EATJ,CAUNC,CAAO,CAAGR,CAAC,CAACS,MAAD,CAVL,CAYNC,CAAe,CAAG,EAZZ,CAcV,QAASC,CAAAA,CAAT,CAAkBC,CAAlB,CAA4B,CACxB,MAAOZ,CAAAA,CAAC,CAACY,CAAD,CAAD,CAAYC,MAAZ,CAAmB,UAAW,CACjC,MAAOb,CAAAA,CAAC,CAAC,IAAD,CAAD,CAAQc,EAAR,CAAW,WAAX,CACV,CAFM,CAGV,CAED,QAASC,CAAAA,CAAT,EAAmB,CACfZ,CAAU,GAAV,CACA,IAAK,GAAIa,CAAAA,CAAK,CAAG,CAAZ,CAAeC,CAAe,CAAGhB,CAAS,CAACiB,MAA3C,CACGC,CADR,CAAwDH,CAAK,CAAGC,CAAhE,CAAiFD,CAAK,EAAtF,CAA0F,CAClFG,CADkF,CACtER,CAAQ,CAACV,CAAS,CAACe,CAAD,CAAV,CAD8D,CAGtFG,CAAS,CAACC,OAAV,CAAkB,QAAlB,CAA4B,CAACD,CAAD,CAA5B,EAEA,GAAIT,CAAe,CAACM,CAAD,CAAnB,CAA4B,CACxB,GAAIK,CAAAA,CAAY,CAAGX,CAAe,CAACM,CAAD,CAAf,CAAuBM,GAAvB,CAA2BH,CAA3B,CAAnB,CACAE,CAAY,CAACD,OAAb,CAAqB,WAArB,CAAkC,CAACC,CAAD,CAAlC,CACH,CACDX,CAAe,CAACM,CAAD,CAAf,CAAyBG,CAC5B,CACJ,CAED,QAASI,CAAAA,CAAT,CAAsBX,CAAtB,CAAgC,CAC5BX,CAAS,CAACuB,IAAV,CAAeZ,CAAf,EACAF,CAAe,CAACc,IAAhB,EACH,CAGDxB,CAAC,CAACyB,IAAF,CAAO,GAAP,EAAYd,QAAZ,CAAuB,SAASe,CAAT,CAAkB,CACrC,GAAIC,CAAAA,CAAQ,CAAG3B,CAAC,CAAC0B,CAAD,CAAhB,CACA,GAAI,CAACC,CAAQ,CAACb,EAAT,CAAY,UAAZ,CAAL,CAA8B,CAC1B,QACH,CAJoC,GAMjCc,CAAAA,CAAW,CAAGpB,CAAO,CAACqB,UAAR,EANmB,CAOjCC,CAAU,CAAGtB,CAAO,CAACuB,SAAR,EAPoB,CAQjCC,CAAM,CAAGL,CAAQ,CAACK,MAAT,EARwB,CASjCC,CAAI,CAAGD,CAAM,CAACC,IATmB,CAUjCC,CAAG,CAAGF,CAAM,CAACE,GAVoB,CAajCC,CAAe,CAAGR,CAAQ,CAACS,IAAT,CAAc,mBAAd,GAAuC7B,CAAO,CAAC4B,eAAR,EAA2B,CAbnD,CAcjCE,CAAgB,CAAGV,CAAQ,CAACS,IAAT,CAAc,oBAAd,GAAwC7B,CAAO,CAAC8B,gBAAR,EAA4B,CAdtD,CAgBrC,GAAIH,CAAG,CAAGP,CAAQ,CAACW,MAAT,EAAN,CAA0BH,CAA1B,EAA6CL,CAA7C,EACAI,CAAG,CAAGC,CAAN,EAAyBL,CAAU,CAAGtB,CAAO,CAAC8B,MAAR,EADtC,EAEAL,CAAI,CAAGN,CAAQ,CAACY,KAAT,EAAP,CAA0BF,CAA1B,EAA8CT,CAF9C,EAGAK,CAAI,CAAGI,CAAP,EAA2BT,CAAW,CAAGpB,CAAO,CAAC+B,KAAR,EAH7C,CAG8D,CAC1D,QACH,CALD,IAKO,CACH,QACH,CACJ,CAxBD,CA0BAvC,CAAC,CAACwC,EAAF,CAAKC,MAAL,CAAY,CAERC,MAAM,CAAE,gBAASC,CAAT,CAAe,CAEnBpC,CAAO,CAAGP,CAAC,CAACyC,MAAF,CAAS,EAAT,CAAarC,CAAb,CAAuBuC,CAAI,EAAI,EAA/B,CAAV,CACA,GAAI/B,CAAAA,CAAQ,CAAG,KAAKA,QAAL,EAAiB,IAAhC,CACA,GAAI,CAACV,CAAL,CAAmB,CACf,GAAI0C,CAAAA,CAAQ,CAAG,UAAW,CACtB,GAAIzC,CAAJ,CAAgB,CACZ,MACH,CACDA,CAAU,GAAV,CAEA0C,UAAU,CAAC9B,CAAD,CAAUR,CAAO,CAACF,QAAlB,CACb,CAPD,CASAL,CAAC,CAACS,MAAD,CAAD,CAAUqC,MAAV,CAAiBF,CAAjB,EAA2BG,MAA3B,CAAkCH,CAAlC,EACA1C,CAAY,GACf,CAED,GAAIK,CAAO,CAACD,aAAZ,CAA2B,CACvBuC,UAAU,CAAC9B,CAAD,CAAUR,CAAO,CAACF,QAAlB,CACb,CACDkB,CAAY,CAACX,CAAD,CAAZ,CACA,MAAOZ,CAAAA,CAAC,CAACY,CAAD,CACX,CAzBO,CAAZ,EA4BAZ,CAAC,CAACyC,MAAF,CAAS,CAELO,YAAY,CAAE,uBAAW,CACrB,GAAI9C,CAAJ,CAAkB,CACda,CAAO,GACP,QACH,CACD,QACH,CARI,CAAT,CAUH,CAzGA,EAyGE,UAAW,CACV,GAAsB,WAAlB,QAAOkC,CAAAA,MAAX,CAAmC,CAE/B,MAAOC,CAAAA,OAAO,CAAC,QAAD,CACjB,CAHD,IAGO,CACH,MAAOnD,CAAAA,CACV,CACJ,CAPE,EAzGF,EAkHD,MAAOA,CAAAA,CAEV,CApIC,CAAN","sourcesContent":["define(['jquery'],\n function(jQuery) {\n\n var $ = jQuery;\n $(); // This is here to stop linter moaning about unuse.\n\n /*\n * jQuery appear plugin\n *\n * Copyright (c) 2012 Andrey Sidorov\n * licensed under MIT license.\n *\n * https://github.com/morr/jquery.appear/\n *\n * Version: 0.3.6\n */\n (function($) {\n var selectors = [];\n\n var check_binded = false;\n var check_lock = false;\n var defaults = {\n interval: 250,\n force_process: false\n };\n var options = {}; // GT Mod, place options in scope for entire library.\n var $window = $(window);\n\n var $prior_appeared = [];\n\n function appeared(selector) {\n return $(selector).filter(function() {\n return $(this).is(':appeared');\n });\n }\n\n function process() {\n check_lock = false;\n for (var index = 0, selectorsLength = selectors.length; index < selectorsLength; index++) {\n var $appeared = appeared(selectors[index]);\n\n $appeared.trigger('appear', [$appeared]);\n\n if ($prior_appeared[index]) {\n var $disappeared = $prior_appeared[index].not($appeared);\n $disappeared.trigger('disappear', [$disappeared]);\n }\n $prior_appeared[index] = $appeared;\n }\n }\n\n function add_selector(selector) {\n selectors.push(selector);\n $prior_appeared.push();\n }\n\n // \"appeared\" custom filter\n $.expr[':'].appeared = function(element) {\n var $element = $(element);\n if (!$element.is(':visible')) {\n return false;\n }\n\n var window_left = $window.scrollLeft();\n var window_top = $window.scrollTop();\n var offset = $element.offset();\n var left = offset.left;\n var top = offset.top;\n\n // GT Mod - use options variable for offsets if data attribute not set.\n var appeartopoffset = $element.data('appear-top-offset') || (options.appeartopoffset || 0);\n var appearleftoffset = $element.data('appear-left-offset') || (options.appearleftoffset || 0);\n\n if (top + $element.height() + appeartopoffset >= window_top &&\n top - appeartopoffset <= window_top + $window.height() &&\n left + $element.width() + appearleftoffset >= window_left &&\n left - appearleftoffset <= window_left + $window.width()) {\n return true;\n } else {\n return false;\n }\n };\n\n $.fn.extend({\n // watching for element's appearance in browser viewport\n appear: function(opts) {\n // GT Mod, set options variable which is declared within scope of entire module.\n options = $.extend({}, defaults, opts || {});\n var selector = this.selector || this;\n if (!check_binded) {\n var on_check = function() {\n if (check_lock) {\n return;\n }\n check_lock = true;\n\n setTimeout(process, options.interval);\n };\n\n $(window).scroll(on_check).resize(on_check);\n check_binded = true;\n }\n\n if (options.force_process) {\n setTimeout(process, options.interval);\n }\n add_selector(selector);\n return $(selector);\n }\n });\n\n $.extend({\n // force elements's appearance check\n force_appear: function() {\n if (check_binded) {\n process();\n return true;\n }\n return false;\n }\n });\n })(function() {\n if (typeof module !== 'undefined') {\n // Node\n return require('jquery');\n } else {\n return jQuery;\n }\n }());\n\n return jQuery;\n\n }\n);\n"],"file":"appear.min.js"} \ No newline at end of file +{"version":3,"file":"appear.min.js","sources":["../src/appear.js"],"sourcesContent":["define(['jquery'],\n function(jQuery) {\n\n var $ = jQuery;\n $(); // This is here to stop linter moaning about unuse.\n\n /*\n * jQuery appear plugin\n *\n * Copyright (c) 2012 Andrey Sidorov\n * licensed under MIT license.\n *\n * https://github.com/morr/jquery.appear/\n *\n * Version: 0.3.6\n */\n (function($) {\n var selectors = [];\n\n var check_binded = false;\n var check_lock = false;\n var defaults = {\n interval: 250,\n force_process: false\n };\n var options = {}; // GT Mod, place options in scope for entire library.\n var $window = $(window);\n\n var $prior_appeared = [];\n\n function appeared(selector) {\n return $(selector).filter(function() {\n return $(this).is(':appeared');\n });\n }\n\n function process() {\n check_lock = false;\n for (var index = 0, selectorsLength = selectors.length; index < selectorsLength; index++) {\n var $appeared = appeared(selectors[index]);\n\n $appeared.trigger('appear', [$appeared]);\n\n if ($prior_appeared[index]) {\n var $disappeared = $prior_appeared[index].not($appeared);\n $disappeared.trigger('disappear', [$disappeared]);\n }\n $prior_appeared[index] = $appeared;\n }\n }\n\n function add_selector(selector) {\n selectors.push(selector);\n $prior_appeared.push();\n }\n\n // \"appeared\" custom filter\n $.expr[':'].appeared = function(element) {\n var $element = $(element);\n if (!$element.is(':visible')) {\n return false;\n }\n\n var window_left = $window.scrollLeft();\n var window_top = $window.scrollTop();\n var offset = $element.offset();\n var left = offset.left;\n var top = offset.top;\n\n // GT Mod - use options variable for offsets if data attribute not set.\n var appeartopoffset = $element.data('appear-top-offset') || (options.appeartopoffset || 0);\n var appearleftoffset = $element.data('appear-left-offset') || (options.appearleftoffset || 0);\n\n if (top + $element.height() + appeartopoffset >= window_top &&\n top - appeartopoffset <= window_top + $window.height() &&\n left + $element.width() + appearleftoffset >= window_left &&\n left - appearleftoffset <= window_left + $window.width()) {\n return true;\n } else {\n return false;\n }\n };\n\n $.fn.extend({\n // watching for element's appearance in browser viewport\n appear: function(opts) {\n // GT Mod, set options variable which is declared within scope of entire module.\n options = $.extend({}, defaults, opts || {});\n var selector = this.selector || this;\n if (!check_binded) {\n var on_check = function() {\n if (check_lock) {\n return;\n }\n check_lock = true;\n\n setTimeout(process, options.interval);\n };\n\n $(window).scroll(on_check).resize(on_check);\n check_binded = true;\n }\n\n if (options.force_process) {\n setTimeout(process, options.interval);\n }\n add_selector(selector);\n return $(selector);\n }\n });\n\n $.extend({\n // force elements's appearance check\n force_appear: function() {\n if (check_binded) {\n process();\n return true;\n }\n return false;\n }\n });\n })(function() {\n if (typeof module !== 'undefined') {\n // Node\n return require('jquery');\n } else {\n return jQuery;\n }\n }());\n\n return jQuery;\n\n }\n);\n"],"names":["define","jQuery","$","selectors","check_binded","check_lock","defaults","interval","force_process","options","$window","window","$prior_appeared","process","index","selectorsLength","length","$appeared","selector","filter","this","is","trigger","$disappeared","not","expr","appeared","element","$element","window_left","scrollLeft","window_top","scrollTop","offset","left","top","appeartopoffset","data","appearleftoffset","height","width","fn","extend","appear","opts","on_check","setTimeout","scroll","resize","push","add_selector","force_appear","module","require"],"mappings":"AAAAA,gCAAO,CAAC,WACJ,SAASC,eAEGA,kBAaGC,OACHC,UAAY,GAEZC,cAAe,EACfC,YAAa,EACbC,SAAW,CACXC,SAAU,IACVC,eAAe,GAEfC,QAAU,GACVC,QAAUR,EAAES,QAEZC,gBAAkB,YAQbC,UACLR,YAAa,MACR,IAAIS,MAAQ,EAAGC,gBAAkBZ,UAAUa,OAAQF,MAAQC,gBAAiBD,QAAS,KAClFG,WATMC,SASef,UAAUW,OARhCZ,EAAEgB,UAAUC,QAAO,kBACfjB,EAAEkB,MAAMC,GAAG,oBASlBJ,UAAUK,QAAQ,SAAU,CAACL,YAEzBL,gBAAgBE,OAAQ,KACpBS,aAAeX,gBAAgBE,OAAOU,IAAIP,WAC9CM,aAAaD,QAAQ,YAAa,CAACC,eAEvCX,gBAAgBE,OAASG,cAjBfC,SA2BlBhB,EAAEuB,KAAK,KAAKC,SAAW,SAASC,aACxBC,SAAW1B,EAAEyB,aACZC,SAASP,GAAG,mBACN,MAGPQ,YAAcnB,QAAQoB,aACtBC,WAAarB,QAAQsB,YACrBC,OAASL,SAASK,SAClBC,KAAOD,OAAOC,KACdC,IAAMF,OAAOE,IAGbC,gBAAkBR,SAASS,KAAK,sBAAyB5B,QAAQ2B,iBAAmB,EACpFE,iBAAmBV,SAASS,KAAK,uBAA0B5B,QAAQ6B,kBAAoB,SAEvFH,IAAMP,SAASW,SAAWH,iBAAmBL,YAC7CI,IAAMC,iBAAmBL,WAAarB,QAAQ6B,UAC9CL,KAAON,SAASY,QAAUF,kBAAoBT,aAC9CK,KAAOI,kBAAoBT,YAAcnB,QAAQ8B,SAOzDtC,EAAEuC,GAAGC,OAAO,CAERC,OAAQ,SAASC,MAEbnC,QAAUP,EAAEwC,OAAO,GAAIpC,SAAUsC,MAAQ,QACrC1B,SAAWE,KAAKF,UAAYE,SAC3BhB,aAAc,KACXyC,SAAW,WACPxC,aAGJA,YAAa,EAEbyC,WAAWjC,QAASJ,QAAQF,YAGhCL,EAAES,QAAQoC,OAAOF,UAAUG,OAAOH,UAClCzC,cAAe,SAGfK,QAAQD,eACRsC,WAAWjC,QAASJ,QAAQF,mBArDlBW,UAClBf,UAAU8C,KAAK/B,UACfN,gBAAgBqC,OAqDZC,CAAahC,UACNhB,EAAEgB,aAIjBhB,EAAEwC,OAAO,CAELS,aAAc,mBACN/C,eACAS,WACO,OAMG,oBAAXuC,OAEAC,QAAQ,UAERpD,QAIRA"} \ No newline at end of file diff --git a/amd/build/imageopt.min.js b/amd/build/imageopt.min.js index 7a512e2..f316800 100644 --- a/amd/build/imageopt.min.js +++ b/amd/build/imageopt.min.js @@ -1,2 +1,23 @@ -define ("filter_imageopt/imageopt",["filter_imageopt/appear"],function(a){return{init:function init(){var b=function(b,c){a(b).attr("src",c);a(b).removeAttr("data-loadonvisible");a(b).addClass("imageopt_loading");a(b).on("load",function(){a(b).removeClass("imageopt_loading")})};a(document).ready(function(){a(document.body).on("appear","img[data-loadonvisible]",function(c,d){d.each(function(){var c=a(this).data("loadonvisible");b(this,c)})});a("img[data-loadonvisible]").appear({appeartopoffset:100,appearleftoffset:100});a.force_appear();(function(){var b=location.hash;a(window).on("popstate hashchange",function(){var c=location.hash;if(c!==b){window.setTimeout(function(){a.force_appear()},200)}b=c})})()})}}}); -//# sourceMappingURL=imageopt.min.js.map +/** + * This file is part of Moodle - http://moodle.org/ + * + * Moodle is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Moodle is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Moodle. If not, see . + * + * @module filter_imageopt + * @copyright Copyright (c) 2017 Guy Thomas + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +define("filter_imageopt/imageopt",["filter_imageopt/appear"],(function($){return{init:function(){$(document).ready((function(){$(document.body).on("appear","img[data-loadonvisible]",(function(e,appeared){appeared.each((function(){!function(el,imgurl){$(el).attr("src",imgurl),$(el).removeAttr("data-loadonvisible"),$(el).addClass("imageopt_loading"),$(el).on("load",(function(){$(el).removeClass("imageopt_loading")}))}(this,$(this).data("loadonvisible"))}))}));var lastHash;$("img[data-loadonvisible]").appear({appeartopoffset:100,appearleftoffset:100}),$.force_appear(),lastHash=location.hash,$(window).on("popstate hashchange",(function(){var newHash=location.hash;newHash!==lastHash&&window.setTimeout((function(){$.force_appear()}),200),lastHash=newHash}))}))}}})); + +//# sourceMappingURL=imageopt.min.js.map \ No newline at end of file diff --git a/amd/build/imageopt.min.js.map b/amd/build/imageopt.min.js.map index 5e66a4e..0af98cc 100644 --- a/amd/build/imageopt.min.js.map +++ b/amd/build/imageopt.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/imageopt.js"],"names":["define","$","init","loadOptimisedImg","el","imgurl","attr","removeAttr","addClass","on","removeClass","document","ready","body","e","appeared","each","data","appear","appeartopoffset","appearleftoffset","force_appear","lastHash","location","hash","window","newHash","setTimeout"],"mappings":"AAwBAA,OAAM,4BAAC,CAAC,wBAAD,CAAD,CACF,SAASC,CAAT,CAAY,CACR,MAAO,CACHC,IAAI,CAAE,eAAW,CAQb,GAAIC,CAAAA,CAAgB,CAAG,SAASC,CAAT,CAAaC,CAAb,CAAqB,CACxCJ,CAAC,CAACG,CAAD,CAAD,CAAME,IAAN,CAAW,KAAX,CAAkBD,CAAlB,EACAJ,CAAC,CAACG,CAAD,CAAD,CAAMG,UAAN,CAAiB,oBAAjB,EACAN,CAAC,CAACG,CAAD,CAAD,CAAMI,QAAN,CAAe,kBAAf,EACAP,CAAC,CAACG,CAAD,CAAD,CAAMK,EAAN,CAAS,MAAT,CAAiB,UAAW,CACxBR,CAAC,CAACG,CAAD,CAAD,CAAMM,WAAN,CAAkB,kBAAlB,CACH,CAFD,CAGH,CAPD,CASAT,CAAC,CAACU,QAAD,CAAD,CAAYC,KAAZ,CAAkB,UAAW,CACzBX,CAAC,CAACU,QAAQ,CAACE,IAAV,CAAD,CAAiBJ,EAAjB,CAAoB,QAApB,CAA8B,yBAA9B,CAAyD,SAASK,CAAT,CAAYC,CAAZ,CAAsB,CAC3EA,CAAQ,CAACC,IAAT,CAAc,UAAW,CACrB,GAAIX,CAAAA,CAAM,CAAGJ,CAAC,CAAC,IAAD,CAAD,CAAQgB,IAAR,CAAa,eAAb,CAAb,CACAd,CAAgB,CAAC,IAAD,CAAOE,CAAP,CACnB,CAHD,CAIH,CALD,EAQAJ,CAAC,CAAC,yBAAD,CAAD,CAA6BiB,MAA7B,CADiB,CAACC,eAAe,CAAE,GAAlB,CAAuBC,gBAAgB,CAAE,GAAzC,CACjB,EACAnB,CAAC,CAACoB,YAAF,GAKA,CAAC,UAAW,CACR,GAAIC,CAAAA,CAAQ,CAAGC,QAAQ,CAACC,IAAxB,CACAvB,CAAC,CAACwB,MAAD,CAAD,CAAUhB,EAAV,CAAa,qBAAb,CAAoC,UAAW,CAC3C,GAAIiB,CAAAA,CAAO,CAAGH,QAAQ,CAACC,IAAvB,CACA,GAAIE,CAAO,GAAKJ,CAAhB,CAA0B,CACtBG,MAAM,CAACE,UAAP,CACI,UAAW,CACP1B,CAAC,CAACoB,YAAF,EACH,CAHL,CAII,GAJJ,CAMH,CACDC,CAAQ,CAAGI,CACd,CAXD,CAYH,CAdD,GAgBH,CA/BD,CAgCH,CAlDE,CAoDV,CAtDC,CAAN","sourcesContent":["/**\n * This file is part of Moodle - http://moodle.org/\n *\n * Moodle is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * Moodle is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with Moodle. If not, see .\n *\n * @package filter_imgopt\n * @copyright Copyright (c) 2017 Guy Thomas\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * Main initialising function.\n */\ndefine(['filter_imageopt/appear'],\n function($) {\n return {\n init: function() {\n\n /**\n * Load optimised image.\n * @param {Element} el\n * @param {string} imgurl\n * @returns {void}\n */\n var loadOptimisedImg = function(el, imgurl) {\n $(el).attr('src', imgurl);\n $(el).removeAttr('data-loadonvisible');\n $(el).addClass('imageopt_loading');\n $(el).on('load', function() {\n $(el).removeClass('imageopt_loading');\n });\n };\n\n $(document).ready(function() {\n $(document.body).on('appear', 'img[data-loadonvisible]', function(e, appeared) {\n appeared.each(function() {\n var imgurl = $(this).data('loadonvisible');\n loadOptimisedImg(this, imgurl);\n });\n });\n // Appear configuration - start loading images when they are out of the view port by 400px.\n var appearConf = {appeartopoffset: 100, appearleftoffset: 100};\n $('img[data-loadonvisible]').appear(appearConf);\n $.force_appear();\n\n /**\n * Listen for hash changes / popstates.\n */\n (function() {\n var lastHash = location.hash;\n $(window).on('popstate hashchange', function() {\n var newHash = location.hash;\n if (newHash !== lastHash) {\n window.setTimeout(\n function() {\n $.force_appear();\n },\n 200\n );\n }\n lastHash = newHash;\n });\n })();\n\n });\n }\n };\n }\n);\n"],"file":"imageopt.min.js"} \ No newline at end of file +{"version":3,"file":"imageopt.min.js","sources":["../src/imageopt.js"],"sourcesContent":["/**\n * This file is part of Moodle - http://moodle.org/\n *\n * Moodle is free software: you can redistribute it and/or modify\n * it under the terms of the GNU General Public License as published by\n * the Free Software Foundation, either version 3 of the License, or\n * (at your option) any later version.\n *\n * Moodle is distributed in the hope that it will be useful,\n * but WITHOUT ANY WARRANTY; without even the implied warranty of\n * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n * GNU General Public License for more details.\n *\n * You should have received a copy of the GNU General Public License\n * along with Moodle. If not, see .\n *\n * @module filter_imageopt\n * @copyright Copyright (c) 2017 Guy Thomas\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\n/**\n * Main initialising function.\n */\ndefine(['filter_imageopt/appear'],\n function($) {\n return {\n init: function() {\n\n /**\n * Load optimised image.\n * @param {Element} el\n * @param {string} imgurl\n * @returns {void}\n */\n var loadOptimisedImg = function(el, imgurl) {\n $(el).attr('src', imgurl);\n $(el).removeAttr('data-loadonvisible');\n $(el).addClass('imageopt_loading');\n $(el).on('load', function() {\n $(el).removeClass('imageopt_loading');\n });\n };\n\n $(document).ready(function() {\n $(document.body).on('appear', 'img[data-loadonvisible]', function(e, appeared) {\n appeared.each(function() {\n var imgurl = $(this).data('loadonvisible');\n loadOptimisedImg(this, imgurl);\n });\n });\n // Appear configuration - start loading images when they are out of the view port by 400px.\n var appearConf = {appeartopoffset: 100, appearleftoffset: 100};\n $('img[data-loadonvisible]').appear(appearConf);\n $.force_appear();\n\n /**\n * Listen for hash changes / popstates.\n */\n (function() {\n var lastHash = location.hash;\n $(window).on('popstate hashchange', function() {\n var newHash = location.hash;\n if (newHash !== lastHash) {\n window.setTimeout(\n function() {\n $.force_appear();\n },\n 200\n );\n }\n lastHash = newHash;\n });\n })();\n\n });\n }\n };\n }\n);\n"],"names":["define","$","init","document","ready","body","on","e","appeared","each","el","imgurl","attr","removeAttr","addClass","removeClass","loadOptimisedImg","this","data","lastHash","appear","appeartopoffset","appearleftoffset","force_appear","location","hash","window","newHash","setTimeout"],"mappings":";;;;;;;;;;;;;;;;;;;;AAwBAA,kCAAO,CAAC,2BACJ,SAASC,SACE,CACHC,KAAM,WAiBFD,EAAEE,UAAUC,OAAM,WACdH,EAAEE,SAASE,MAAMC,GAAG,SAAU,2BAA2B,SAASC,EAAGC,UACjEA,SAASC,MAAK,YAXC,SAASC,GAAIC,QAChCV,EAAES,IAAIE,KAAK,MAAOD,QAClBV,EAAES,IAAIG,WAAW,sBACjBZ,EAAES,IAAII,SAAS,oBACfb,EAAES,IAAIJ,GAAG,QAAQ,WACbL,EAAES,IAAIK,YAAY,uBAQdC,CAAiBC,KADJhB,EAAEgB,MAAMC,KAAK,4BAa1BC,SAPRlB,EAAE,2BAA2BmB,OADZ,CAACC,gBAAiB,IAAKC,iBAAkB,MAE1DrB,EAAEsB,eAMMJ,SAAWK,SAASC,KACxBxB,EAAEyB,QAAQpB,GAAG,uBAAuB,eAC5BqB,QAAUH,SAASC,KACnBE,UAAYR,UACZO,OAAOE,YACH,WACI3B,EAAEsB,iBAEN,KAGRJ,SAAWQ"} \ No newline at end of file diff --git a/amd/src/imageopt.js b/amd/src/imageopt.js index 2f5d973..3584603 100644 --- a/amd/src/imageopt.js +++ b/amd/src/imageopt.js @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with Moodle. If not, see . * - * @package filter_imgopt + * @module filter_imageopt * @copyright Copyright (c) 2017 Guy Thomas * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/classes/local.php b/classes/local.php index 88d0702..9b74d4b 100644 --- a/classes/local.php +++ b/classes/local.php @@ -60,9 +60,11 @@ class local { /** * Get the optimised path for a file path - this is the path that get's written to the db as a hash. - * @param string $filepath - * @param bool $asfilepath - if true will return the path for use with the file storage system, not urls. - * @return string + * + * @param \stored_file $file + * @param mixed $filepath + * @param bool $asfilepath If true will return the path for use with the file storage system, not urls + * @return string the optimised path */ public static function get_optimised_path(\stored_file $file, $filepath, $asfilepath = true) { $maxwidth = get_config('filter_imageopt', 'maxwidth'); @@ -266,6 +268,12 @@ public static function file_pluginfile($relativepath) { file_pluginfile($relativepath, $forcedownload, $preview, $offline, $embed); } + /** + * Returns true if a file is considered public. + * + * @param string $contenthash + * @return bool + */ public static function file_is_public(string $contenthash): bool { global $DB; diff --git a/db/caches.php b/db/caches.php index cd32d28..955b843 100644 --- a/db/caches.php +++ b/db/caches.php @@ -18,7 +18,7 @@ * Defined caches used internally by the plugin. * * - * @package tool_hurdlefailgrade + * @package filter_imageopt * @copyright 2022 Catalyst IT Australia Pty Ltd * @author Cameron Ball * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later diff --git a/tests/local_test.php b/tests/local_test.php index 4b40073..3cecfa8 100644 --- a/tests/local_test.php +++ b/tests/local_test.php @@ -125,27 +125,27 @@ public function test_file_is_public() { $filtered1 = $filter1->filter($labeltxt1); // Initial configuration, nothing should be detected as a duplicate. - $this->assertFalse(local::file_is_public(($file1))); - $this->assertFalse(local::file_is_public(($file2))); + $this->assertFalse(local::file_is_public(($file1->get_contenthash()))); + $this->assertFalse(local::file_is_public(($file2->get_contenthash()))); // Min duplicates exceeds 2, nothing should be detected as a duplicate. set_config('minduplicates', '3', 'filter_imageopt'); - $this->assertFalse(local::file_is_public(($file1))); - $this->assertFalse(local::file_is_public(($file2))); + $this->assertFalse(local::file_is_public(($file1->get_contenthash()))); + $this->assertFalse(local::file_is_public(($file2->get_contenthash()))); // Min duplicates is equal to 2, both duplicates should be detected. set_config('minduplicates', '2', 'filter_imageopt'); - $this->assertTrue(local::file_is_public(($file1))); - $this->assertTrue(local::file_is_public(($file2))); + $this->assertTrue(local::file_is_public(($file1->get_contenthash()))); + $this->assertTrue(local::file_is_public(($file2->get_contenthash()))); // Min duplicates is less than 2, both duplicates should be detected. set_config('minduplicates', '2', 'filter_imageopt'); - $this->assertTrue(local::file_is_public(($file1))); - $this->assertTrue(local::file_is_public(($file2))); + $this->assertTrue(local::file_is_public(($file1->get_contenthash()))); + $this->assertTrue(local::file_is_public(($file2->get_contenthash()))); // Min duplicates is 0, nothing should be detected as a duplicate. set_config('minduplicates', '0', 'filter_imageopt'); - $this->assertFalse(local::file_is_public(($file1))); - $this->assertFalse(local::file_is_public(($file2))); + $this->assertFalse(local::file_is_public(($file1->get_contenthash()))); + $this->assertFalse(local::file_is_public(($file2->get_contenthash()))); } } From d3abe810bceefd1be2d57c44b2b2df0c683259c9 Mon Sep 17 00:00:00 2001 From: Cameron Ball Date: Wed, 30 Mar 2022 18:01:24 +0800 Subject: [PATCH 3/6] Progressively add files to public files cache On large sites, the files table can be enourmous and it is impractical to query the entire table for duplicates at once. Instead, this patch modifies the public files check to query for instances of a file individually (as required). Each time, the content hash of that file is added to the cache and marked as either public or private. --- classes/local.php | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/classes/local.php b/classes/local.php index 9b74d4b..2fa1d79 100644 --- a/classes/local.php +++ b/classes/local.php @@ -279,26 +279,22 @@ public static function file_is_public(string $contenthash): bool { $minduplicates = get_config('filter_imageopt', 'minduplicates'); $publicfilescache = \cache::make('filter_imageopt', 'public_files'); - $key = 'public_files_' . $minduplicates; + $key = 'publicfiles' . '_' . $contenthash . '_' . $minduplicates; if (empty($minduplicates)) { return false; } if (!$publicfilescache->has($key)) { - $publicfiles = $DB->get_records_sql( - "SELECT contenthash, COUNT(contenthash) - FROM {files} - WHERE filearea <> 'draft' - AND (filearea <> 'public' OR component <> 'filter_imageopt') - GROUP BY contenthash - HAVING COUNT(contenthash) >= :count", - ['count' => $minduplicates] + $ocurrences = $DB->count_records_select( + 'files', + "contenthash = :contenthash AND filearea <> 'draft' AND (filearea <> 'public' OR component <> 'filter_imageopt')", + ['contenthash' => $contenthash] ); - $publicfilescache->set($key, array_column($publicfiles, 'contenthash')); + $publicfilescache->set($key, (int)($ocurrences >= $minduplicates)); } - return in_array($contenthash, $publicfilescache->get($key)); + return (bool)$publicfilescache->get($key); } } From dda843c30b69792066f6f36165dcf80e439854df Mon Sep 17 00:00:00 2001 From: Cameron Ball Date: Wed, 30 Mar 2022 19:00:01 +0800 Subject: [PATCH 4/6] Remove redundant call to get_img_file --- filter.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/filter.php b/filter.php index fa56398..afe1e2f 100644 --- a/filter.php +++ b/filter.php @@ -304,11 +304,6 @@ private function apply_img_tag($match, stored_file $file, $originalsrc, $optimis raise_memory_limit(MEMORY_EXTRA); - $file = local::get_img_file($match[3]); - if (!$file) { - return $match[0]; - } - $imageinfo = (object) $file->get_imageinfo(); if (empty($imageinfo) || !isset($imageinfo->width)) { return $match[0]; From 0743302f8b78b317161bae95ccfd13889f45103a Mon Sep 17 00:00:00 2001 From: Cameron Ball Date: Thu, 31 Mar 2022 16:28:28 +0800 Subject: [PATCH 5/6] Cache processed tags --- db/caches.php | 6 ++++++ filter.php | 20 ++++++++++++++++++-- version.php | 2 +- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/db/caches.php b/db/caches.php index 955b843..69c14ef 100644 --- a/db/caches.php +++ b/db/caches.php @@ -32,5 +32,11 @@ 'simplekeys' => true, 'simpledata' => true, 'staticacceleration' => true + ], + 'processed_img_tags' => [ + 'mode' => cache_store::MODE_APPLICATION, + 'simplekeys' => true, + 'simpledata' => true, + 'staticacceleration' => true ] ]; diff --git a/filter.php b/filter.php index afe1e2f..ea237b2 100644 --- a/filter.php +++ b/filter.php @@ -175,22 +175,31 @@ private function process_img_tag(array $match) { global $CFG, $DB; $maxwidth = $this->config->maxwidth; + $processedtagscache = \cache::make('filter_imageopt', 'processed_img_tags'); + $key = md5($match[0]) . '_' . $maxwidth . '_' . $this->config->loadonvisible . '_' . $this->config->minduplicates; + + if ($processedtagscache->has($key)) { + return $processedtagscache->get($key); + } $optimisedavailable = false; // Don't process images that aren't in this site or don't have a relative path. if (stripos($match[2], $CFG->wwwroot) === false && substr($match[2], 0, 1) != '/') { + $processedtagscache->set($key, $match[0]); return $match[0]; } $file = local::get_img_file($match[3]); if (!$file) { + $processedtagscache->set($key, $match[0]); return $match[0]; } // Generally, if anything is being exported then we don't want to mess with it. if ($file->get_filearea() === 'export') { + $processedtagscache->set($key, $match[0]); return $match[0]; } @@ -200,6 +209,7 @@ private function process_img_tag(array $match) { $imageinfo = (object) $file->get_imageinfo(); if ($imageinfo->width <= $maxwidth && !local::file_is_public($file->get_contenthash())) { + $processedtagscache->set($key, $match[0]); return $match[0]; } @@ -215,10 +225,16 @@ private function process_img_tag(array $match) { } if (empty($this->config->loadonvisible) || $this->config->loadonvisible < 999) { - return $this->apply_loadonvisible($match, $file, $originalsrc, $optimisedsrc, $optimisedavailable); + $applied = $this->apply_loadonvisible($match, $file, $originalsrc, $optimisedsrc, $optimisedavailable); } else { - return $this->apply_img_tag($match, $file, $originalsrc, $optimisedsrc); + $applied = $this->apply_img_tag($match, $file, $originalsrc, $optimisedsrc); } + + if ($optimisedavailable) { + $processedtagscache->set($key, $applied); + } + + return $applied; } /** diff --git a/version.php b/version.php index cd42b05..4c8691c 100644 --- a/version.php +++ b/version.php @@ -22,7 +22,7 @@ */ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2022020800; +$plugin->version = 2022033000; $plugin->requires = 2011111500; $plugin->component = 'filter_imageopt'; $plugin->maturity = MATURITY_BETA; From 5a265ef12098fee2449b0e88af44c706d60336e9 Mon Sep 17 00:00:00 2001 From: Cameron Ball Date: Thu, 7 Apr 2022 15:13:41 +0800 Subject: [PATCH 6/6] Fix codechecker warnings --- classes/componentsupport/base_component.php | 2 -- classes/componentsupport/mod_page.php | 2 -- classes/componentsupport/question.php | 2 -- classes/local.php | 4 +--- db/upgrade.php | 2 -- filter.php | 2 -- lib.php | 2 -- 7 files changed, 1 insertion(+), 15 deletions(-) diff --git a/classes/componentsupport/base_component.php b/classes/componentsupport/base_component.php index 558d073..5b2a27e 100644 --- a/classes/componentsupport/base_component.php +++ b/classes/componentsupport/base_component.php @@ -25,8 +25,6 @@ namespace filter_imageopt\componentsupport; -defined('MOODLE_INTERNAL') || die; - /** * The base component class. * diff --git a/classes/componentsupport/mod_page.php b/classes/componentsupport/mod_page.php index db05793..bd8e77a 100644 --- a/classes/componentsupport/mod_page.php +++ b/classes/componentsupport/mod_page.php @@ -24,8 +24,6 @@ */ namespace filter_imageopt\componentsupport; -defined('MOODLE_INTERNAL') || die; - use filter_imageopt\local; /** diff --git a/classes/componentsupport/question.php b/classes/componentsupport/question.php index 47d714f..b5a0436 100644 --- a/classes/componentsupport/question.php +++ b/classes/componentsupport/question.php @@ -24,8 +24,6 @@ */ namespace filter_imageopt\componentsupport; -defined('MOODLE_INTERNAL') || die; - use filter_imageopt\local; /** diff --git a/classes/local.php b/classes/local.php index 2fa1d79..179da73 100644 --- a/classes/local.php +++ b/classes/local.php @@ -24,8 +24,6 @@ */ namespace filter_imageopt; -defined('MOODLE_INTERNAL') || die(); - use stored_file; /** @@ -113,7 +111,7 @@ public static function get_optimised_src(\stored_file $file, $originalsrc, $opti global $CFG; $classname = '\\filter_imageopt\\componentsupport\\'.$file->get_component(); $optimisedsrc = null; - if (!self::file_is_public($file->get_contenthash()) && class_exists($classname) && method_exists($classname, 'get_optimised_src')) { + if (!self::file_is_public($file->get_contenthash()) && method_exists($classname, 'get_optimised_src')) { $optimisedsrc = $classname::get_optimised_src($file, $originalsrc); } if (empty($optimisedsrc)) { diff --git a/db/upgrade.php b/db/upgrade.php index 729f274..6afa94c 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -22,8 +22,6 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -defined('MOODLE_INTERNAL') || die(); - /** * Filter upgrade function. * diff --git a/filter.php b/filter.php index ea237b2..68709d7 100644 --- a/filter.php +++ b/filter.php @@ -22,8 +22,6 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -defined('MOODLE_INTERNAL') || die(); - use filter_imageopt\local; /** diff --git a/lib.php b/lib.php index 1ea4d0d..ba57951 100644 --- a/lib.php +++ b/lib.php @@ -24,8 +24,6 @@ use filter_imageopt\local; -defined('MOODLE_INTERNAL') || die(); - /** * Serves any files associated with the image optimiser filter *