From b0599d309f8f84076dd3ed0b8d8bca556a13bd34 Mon Sep 17 00:00:00 2001 From: eWallah Date: Mon, 10 May 2021 16:01:30 +0200 Subject: [PATCH 01/11] issue #27 --- tests/behat/image_processing.feature | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/behat/image_processing.feature b/tests/behat/image_processing.feature index aad08e9..aa0453e 100644 --- a/tests/behat/image_processing.feature +++ b/tests/behat/image_processing.feature @@ -54,7 +54,7 @@ Feature: When the image optimiser filter is enabled, images are placeheld until And I reload the page # If the image could not be opened due to access rights, we should have a html element on a page with appropriate options. And I wait until "#page-content" "css_element" exists - And I should see "You can not enrol yourself in this course" + And I should see "You cannot enrol yourself in this course" And I log out And I directly open the image "testpng_2880x1800.png" in the test label in course "C1" # The page is reloaded to nuke image cache. From df4325642db851abe1fc9bff63413d021d779eb2 Mon Sep 17 00:00:00 2001 From: eWallah Date: Mon, 10 May 2021 16:03:55 +0200 Subject: [PATCH 02/11] prepare for phpunit9 --- tests/filter_test.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/filter_test.php b/tests/filter_test.php index ab8fdd3..bf8b6ff 100644 --- a/tests/filter_test.php +++ b/tests/filter_test.php @@ -87,7 +87,7 @@ public function test_empty_image() { ]; foreach ($sizes as $size) { $emptyimage = phpunit_util::call_internal_method($filter, 'empty_image', $size, get_class($filter)); - $this->assertContains('width="'.$size[0].'" height="'.$size[1].'"', $emptyimage); + $this->assertStringContainsString('width="'.$size[0].'" height="'.$size[1].'"', $emptyimage); } } @@ -272,7 +272,7 @@ public function test_apply_loadonvisible() { // Test filter plugin img, lazy load. $regex = '/img data-loadonvisible="'.str_replace('~pathid~', '(?:[0-9]*)', preg_quote($loadonvisibleurl, '/')).'/'; $this->assertRegExp($regex, $str); - $this->assertContains('src="data:image/svg+xml;utf8,', $str); + $this->assertStringContainsString('src="data:image/svg+xml;utf8,', $str); } @@ -349,29 +349,29 @@ public function test_filter() { $filter = new filter_imageopt($context, []); $filtered = $filter->filter($labeltxt); $prefilterurl = $CFG->wwwroot.'/pluginfile.php/'.$context->id.'/mod_label/intro/0/testpng_2880x1800.png'; - $this->assertContains($prefilterurl, $labeltxt); + $this->assertStringContainsString($prefilterurl, $labeltxt); $postfilterurl = $this->filter_imageopt_url_from_file($file, $maxwidth); $regex = '/src="'.str_replace('~pathid~', '(?:[0-9]*)', preg_quote($postfilterurl, '/')).'/'; $this->assertRegExp($regex, $filtered); // We need a space before src so it doesn't trigger on original-src. - $this->assertNotContains(' src="'.$prefilterurl, $filtered); - $this->assertNotContains('data-loadonvisible="'.$postfilterurl, $filtered); - $this->assertNotContains('data-loadonvisible="'.$prefilterurl, $filtered); + $this->assertStringNotContainsString(' src="'.$prefilterurl, $filtered); + $this->assertStringNotContainsString('data-loadonvisible="'.$postfilterurl, $filtered); + $this->assertStringNotContainsString('data-loadonvisible="'.$prefilterurl, $filtered); // Test filter plugin img, lazy load. set_config('loadonvisible', '0', 'filter_imageopt'); $filter = new filter_imageopt($context, []); $filtered = $filter->filter($labeltxt); $prefilterurl = $CFG->wwwroot.'/pluginfile.php/'.$context->id.'/mod_label/intro/0/testpng_2880x1800.png'; - $this->assertContains($prefilterurl, $labeltxt); + $this->assertStringContainsString($prefilterurl, $labeltxt); $postfilterurl = $this->filter_imageopt_url_from_file($file, $maxwidth); $regex = '/data-loadonvisible="'.str_replace('~pathid~', '(?:[0-9]*)', preg_quote($postfilterurl, '/')).'/'; $this->assertRegExp($regex, $filtered); - $this->assertNotContains('data-loadonvisible="'.$prefilterurl, $filtered); - $this->assertNotContains('src="'.$postfilterurl, $filtered); - $this->assertNotContains('src="'.$prefilterurl, $filtered); + $this->assertStringNotContainsString('data-loadonvisible="'.$prefilterurl, $filtered); + $this->assertStringNotContainsString('src="'.$postfilterurl, $filtered); + $this->assertStringNotContainsString('src="'.$prefilterurl, $filtered); } } \ No newline at end of file From 5095cd8d49a6757c23d46d54b5bd9952d154b37e Mon Sep 17 00:00:00 2001 From: eWallah Date: Mon, 10 May 2021 16:07:02 +0200 Subject: [PATCH 03/11] workflow --- .github/workflows/main.yml | 72 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 .github/workflows/main.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..aca8c46 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,72 @@ +name: Tests + +on: [push, pull_request] + +jobs: + ci: + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + moodle-branch: ['master', 'MOODLE_311_STABLE', 'MOODLE_310_STABLE', 'MOODLE_39_STABLE'] + php: ['7.4'] + database: ['mysqli'] + + name: ${{ matrix.moodle-branch }} php ${{ matrix.php }} ${{ matrix.database }} + + steps: + - name: checkout plugin + uses: actions/checkout@v2 + with: + path: this-plugin + + - name: setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + extensions: mbstring, mysqli, gd, zip + + - name: composer + run: | + composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^3 + echo $(cd ci/bin; pwd) >> $GITHUB_PATH + echo $(cd ci/vendor/bin; pwd) >> $GITHUB_PATH + sudo locale-gen en_AU.UTF-8 + sudo systemctl start mysql.service + + - name: install Moodle + run: moodle-plugin-ci install -v --db-user=root --db-pass=root --db-host=127.0.0.1 --plugin this-plugin + env: + DB: ${{ matrix.database }} + MOODLE_BRANCH: ${{ matrix.moodle-branch }} + + - name: phplint + run: moodle-plugin-ci --ansi phplint + + - name: phpcpd + run: moodle-plugin-ci --ansi phpcpd + + - name: phpmd + run: moodle-plugin-ci --ansi phpmd + + - name: phpdoc + run: moodle-plugin-ci --ansi phpdoc || true + + - name: codechecker + run: moodle-plugin-ci --ansi codechecker + + - name: validate + run: moodle-plugin-ci --ansi validate + + - name: savepoints + run: moodle-plugin-ci --ansi savepoints + + - name: mustache + run: moodle-plugin-ci --ansi mustache + + - name: phpunit + run: moodle-plugin-ci --ansi phpunit --coverage-text + + - name: behat + run: moodle-plugin-ci --ansi behat From 000d85a1e8a7633e2780e5beed7416e7108d3e26 Mon Sep 17 00:00:00 2001 From: Renaat Debleu Date: Tue, 4 Jan 2022 13:19:07 +0000 Subject: [PATCH 04/11] code review --- .github/workflows/main.yml | 41 ++++++--- amd/src/imageopt.js | 1 - classes/componentsupport/base_component.php | 24 +++++- classes/componentsupport/mod_page.php | 35 +++++++- classes/componentsupport/question.php | 29 ++++++- classes/image.php | 7 +- classes/local.php | 27 +++++- classes/privacy/provider.php | 10 ++- db/upgrade.php | 12 ++- filter.php | 24 ++++-- lang/en/filter_imageopt.php | 2 +- lib.php | 7 -- phpunit.xml | 47 +++++++++++ tests/behat/behat_filter_imageopt.php | 16 +++- tests/behat/image_processing.feature | 2 +- tests/filter_test.php | 93 +++++++++++---------- tests/privacy/privacy_test.php | 50 +++++++++++ 17 files changed, 335 insertions(+), 92 deletions(-) create mode 100644 phpunit.xml create mode 100644 tests/privacy/privacy_test.php diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index aca8c46..ca4454a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -9,9 +9,13 @@ jobs: strategy: fail-fast: false matrix: - moodle-branch: ['master', 'MOODLE_311_STABLE', 'MOODLE_310_STABLE', 'MOODLE_39_STABLE'] + moodle-branch: ['MOODLE_311_STABLE'] php: ['7.4'] database: ['mysqli'] + include: + - php: 8.0 + moodle-branch: master + database: mysqli name: ${{ matrix.moodle-branch }} php ${{ matrix.php }} ${{ matrix.database }} @@ -26,47 +30,64 @@ jobs: with: php-version: ${{ matrix.php }} extensions: mbstring, mysqli, gd, zip + ini-values: max_input_vars=5000 + coverage: xdebug - name: composer run: | - composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^3 - echo $(cd ci/bin; pwd) >> $GITHUB_PATH - echo $(cd ci/vendor/bin; pwd) >> $GITHUB_PATH - sudo locale-gen en_AU.UTF-8 - sudo systemctl start mysql.service + composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^3 + echo $(cd ci/bin; pwd) >> $GITHUB_PATH + echo $(cd ci/vendor/bin; pwd) >> $GITHUB_PATH + sudo locale-gen en_AU.UTF-8 + sudo systemctl start mysql.service + sed -i 's/phpdbg -d memory_limit=-1 -qrr//g' ci/src/Command/PHPUnitCommand.php - name: install Moodle - run: moodle-plugin-ci install -v --db-user=root --db-pass=root --db-host=127.0.0.1 --plugin this-plugin + run: moodle-plugin-ci install -v --db-user=root --db-pass=root --db-host=127.0.0.1 --plugin this-plugin env: DB: ${{ matrix.database }} MOODLE_BRANCH: ${{ matrix.moodle-branch }} - name: phplint + if: ${{ always() }} run: moodle-plugin-ci --ansi phplint - name: phpcpd + if: ${{ always() }} run: moodle-plugin-ci --ansi phpcpd - name: phpmd + if: ${{ always() }} run: moodle-plugin-ci --ansi phpmd - name: phpdoc - run: moodle-plugin-ci --ansi phpdoc || true + if: ${{ always() }} + run: moodle-plugin-ci --ansi phpdoc - name: codechecker + if: ${{ always() }} run: moodle-plugin-ci --ansi codechecker - name: validate + if: ${{ always() }} run: moodle-plugin-ci --ansi validate - name: savepoints + if: ${{ always() }} run: moodle-plugin-ci --ansi savepoints + - name: grunt + if: ${{ always() }} + run: moodle-plugin-ci --ansi grunt + - name: mustache + if: ${{ always() }} run: moodle-plugin-ci --ansi mustache - - name: phpunit + - name: phpunit + if: ${{ always() }} run: moodle-plugin-ci --ansi phpunit --coverage-text - name: behat - run: moodle-plugin-ci --ansi behat + if: ${{ always() }} + run: moodle-plugin-ci --ansi behat --profile=chrome diff --git a/amd/src/imageopt.js b/amd/src/imageopt.js index 241a34c..6b11496 100644 --- a/amd/src/imageopt.js +++ b/amd/src/imageopt.js @@ -14,7 +14,6 @@ * You should have received a copy of the GNU General Public License * along with Moodle. If not, see . * - * @package filter_imgopt * @copyright Copyright (c) 2017 Guy Thomas * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ diff --git a/classes/componentsupport/base_component.php b/classes/componentsupport/base_component.php index 0e2b16c..fa62d1b 100644 --- a/classes/componentsupport/base_component.php +++ b/classes/componentsupport/base_component.php @@ -13,10 +13,28 @@ // // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . + +/** + * Abstract class. + * + * @package filter_imageopt + * @author Guy Thomas + * @copyright Copyright (c) 2017 Guy Thomas. + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + namespace filter_imageopt\componentsupport; defined('MOODLE_INTERNAL') || die; +/** + * Abstract class. + * + * @package filter_imageopt + * @author Guy Thomas + * @copyright Copyright (c) 2017 Guy Thomas. + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ abstract class base_component { /** @@ -36,11 +54,9 @@ abstract public static function get_optimised_path(array $pathcomponents, $maxwi /** * Return the optimised url for the specfied file and original src. - * @param \filter_imageopt\componentsupport\stored_file $file - * @param type $originalsrc + * @param \stored_file $file + * @param string $originalsrc * @return \moodle_url */ abstract public static function get_optimised_src(\stored_file $file, $originalsrc); } - - diff --git a/classes/componentsupport/mod_page.php b/classes/componentsupport/mod_page.php index f9f11b6..8b1b1c4 100644 --- a/classes/componentsupport/mod_page.php +++ b/classes/componentsupport/mod_page.php @@ -27,14 +27,33 @@ use filter_imageopt\local; +/** + * Image optimiser support for page component. + * @package filter_imageopt + * @author Guy Thomas + * @copyright Copyright (c) 2020 Guy Thomas. + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ class mod_page extends base_component { + /** + * Check component. + * + * @param array $pathcomponents + * @throws \coding_exception + */ private static function check_component(array $pathcomponents) { if ($pathcomponents[1] !== 'mod_page') { throw new \coding_exception('Component is not a page ('.$pathcomponents[2].')'); } } + /** + * Get's an image file. + * + * @param array $pathcomponents + * @return \stored_file + */ public static function get_img_file(array $pathcomponents) { self::check_component($pathcomponents); @@ -53,6 +72,13 @@ public static function get_img_file(array $pathcomponents) { return $file; } + /** + * Get's an image optimised path. + * + * @param array $pathcomponents + * @param int $maxwidth + * @return string + */ public static function get_optimised_path(array $pathcomponents, $maxwidth) { self::check_component($pathcomponents); @@ -73,6 +99,13 @@ public static function get_optimised_path(array $pathcomponents, $maxwidth) { return $optimisedpath; } + /** + * Get's an image optimised source. + * + * @param \stored_file $file + * @param string $originalsrc + * @return \moodle_url + */ public static function get_optimised_src(\stored_file $file, $originalsrc) { global $CFG; @@ -96,4 +129,4 @@ public static function get_optimised_src(\stored_file $file, $originalsrc) { return $opturl; } -} \ No newline at end of file +} diff --git a/classes/componentsupport/question.php b/classes/componentsupport/question.php index 2e26e2b..682a8cd 100644 --- a/classes/componentsupport/question.php +++ b/classes/componentsupport/question.php @@ -27,8 +27,21 @@ use filter_imageopt\local; +/** + * Image optimiser support for question component. + * @package filter_imageopt + * @author Guy Thomas + * @copyright Copyright (c) 2018 Guy Thomas. + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ class question extends base_component { + /** + * Get's an image file. + * + * @param array $pathcomponents + * @return \stored_file + */ public static function get_img_file(array $pathcomponents) { if (count($pathcomponents) <= 5) { // Return null so that local lib uses default. @@ -51,6 +64,13 @@ public static function get_img_file(array $pathcomponents) { return $fs->get_file_by_hash(sha1($path)); } + /** + * Get's an image optimised path. + * + * @param array $pathcomponents + * @param int $maxwidth + * @return string + */ public static function get_optimised_path(array $pathcomponents, $maxwidth) { if (count($pathcomponents) <= 5) { // Return null so that local lib uses default. @@ -74,6 +94,13 @@ public static function get_optimised_path(array $pathcomponents, $maxwidth) { return $optimisedpath; } + /** + * Get's an image optimised source. + * + * @param \stored_file $file + * @param string $originalsrc + * @return \moodle_url + */ public static function get_optimised_src(\stored_file $file, $originalsrc) { global $CFG; @@ -88,4 +115,4 @@ public static function get_optimised_src(\stored_file $file, $originalsrc) { return $opturl; } -} \ No newline at end of file +} diff --git a/classes/image.php b/classes/image.php index 0ae5b36..edf4ac1 100644 --- a/classes/image.php +++ b/classes/image.php @@ -59,9 +59,10 @@ class image { * * @param stored_file $originalfile * @param string $resizefilepath - * @param bool | string $resizefilename - * @param int $newwidth; - * @param int $newheight; + * @param string $resizefilename + * @param int $newwidth + * @param int $newheight + * @param int $jpgquality * @return stored_file */ public static function resize ( diff --git a/classes/local.php b/classes/local.php index f88821a..e43f64c 100644 --- a/classes/local.php +++ b/classes/local.php @@ -28,10 +28,24 @@ use stored_file; +/** + * Local class for local people (we'll have no trouble here). + * + * @package filter_imageopt + * @author Guy Thomas + * @copyright Copyright (c) 2017 Guy Thomas. + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ class local { + /** + * Regex imgage source. + */ const REGEXP_IMGSRC = '/]*(src=["|\']((?:.*)(pluginfile.php(?:.*)))["|\'])(?:.*)>/isU'; + /** + * Regex source. + */ const REGEXP_SRC = '/(?:.*)(pluginfile.php(?:.*))/'; /** @@ -126,7 +140,7 @@ public static function get_url_path_by_id($id) { /** * Delete queue item by url path. - * @param $urlpath + * @param string $urlpath * @throws \dml_exception */ public static function delete_queue_item_by_path($urlpath) { @@ -137,7 +151,7 @@ public static function delete_queue_item_by_path($urlpath) { /** * Gets an img path from image src attribute. - * @param type string $src + * @param string $src * @return array */ public static function get_img_path_from_src($src) { @@ -187,7 +201,7 @@ public static function url_decode_path($pluginfilepath) { /** * Get's an image file from the plugin file path. * - * @param str $pluginfilepath pluginfile.php/ + * @param string $pluginfilepath pluginfile.php/ * @return \stored_file */ public static function get_img_file($pluginfilepath) { @@ -220,6 +234,11 @@ public static function get_img_file($pluginfilepath) { return $file; } + /** + * Get file plugin. + * + * @param string $relativepath + */ public static function file_pluginfile($relativepath) { $forcedownload = optional_param('forcedownload', 0, PARAM_BOOL); $preview = optional_param('preview', null, PARAM_ALPHANUM); @@ -229,4 +248,4 @@ public static function file_pluginfile($relativepath) { $embed = optional_param('embed', 0, PARAM_BOOL); file_pluginfile($relativepath, $forcedownload, $preview, $offline, $embed); } -} \ No newline at end of file +} diff --git a/classes/privacy/provider.php b/classes/privacy/provider.php index a519fbd..2e2894a 100644 --- a/classes/privacy/provider.php +++ b/classes/privacy/provider.php @@ -24,7 +24,13 @@ namespace filter_imageopt\privacy; -// This plugin does not store any personal user data. +/** + * Privacy provider settings + * + * @package filter_imageopt + * @copyright Copyright (c) 2018 Guy Thomas + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ class provider implements \core_privacy\local\metadata\null_provider { /** @@ -36,4 +42,4 @@ class provider implements \core_privacy\local\metadata\null_provider { public static function get_reason() : string { return 'privacy:metadata'; } -} \ No newline at end of file +} diff --git a/db/upgrade.php b/db/upgrade.php index 1122893..8801f70 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -14,8 +14,6 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -defined('MOODLE_INTERNAL') || die(); - /** * Filter * @@ -24,6 +22,14 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +defined('MOODLE_INTERNAL') || die(); + +/** + * Filter upgrade + * + * @param int $oldversion + * @return bool + */ function xmldb_filter_imageopt_upgrade($oldversion) { global $DB; @@ -56,4 +62,4 @@ function xmldb_filter_imageopt_upgrade($oldversion) { } return true; -} \ No newline at end of file +} diff --git a/filter.php b/filter.php index 782389c..bd32408 100644 --- a/filter.php +++ b/filter.php @@ -41,6 +41,11 @@ class filter_imageopt extends moodle_text_filter { */ private $config; + /** + * Construct class + * @param context $context + * @param array $localconfig + */ public function __construct(context $context, array $localconfig) { global $CFG; @@ -58,6 +63,12 @@ public function __construct(context $context, array $localconfig) { parent::__construct($context, $localconfig); } + /** + * Empty immage + * @param int $width + * @param int $height + * @return string + */ private function empty_image($width, $height) { // @codingStandardsIgnoreStart $svg = <<config->maxwidth; $optimisedavailable = false; @@ -244,7 +258,7 @@ private function apply_loadonvisible(array $match, stored_file $file, $originals if (!$imageinfo || !isset($imageinfo->width)) { return ($img); } - $width = $imageinfo->width; + $width = $imageinfo->width > $maxwidth ? $maxwidth : $imageinfo->width; $height = $imageinfo->height; $img = $this->img_add_width_height($img, $width, $height); diff --git a/lang/en/filter_imageopt.php b/lang/en/filter_imageopt.php index 7dcff4a..a63fcb9 100644 --- a/lang/en/filter_imageopt.php +++ b/lang/en/filter_imageopt.php @@ -32,4 +32,4 @@ $string['widthattributedesc'] = 'How should existing image width attributes be dealt with'; $string['widthattpreserve'] = 'Preserve user width attributes in all cases'; $string['widthattpreserveltmax'] = 'Preserve user width attributes only if less than maximum width'; -$string['privacy:metadata'] = 'The image optimiser filter creates optimised versions of pre-existing images. It does not store any information other than that relating to pre-existing images.'; \ No newline at end of file +$string['privacy:metadata'] = 'The image optimiser filter creates optimised versions of pre-existing images. It does not store any information other than that relating to pre-existing images.'; diff --git a/lib.php b/lib.php index 1700587..cb2404e 100644 --- a/lib.php +++ b/lib.php @@ -40,16 +40,12 @@ * @return bool */ function filter_imageopt_pluginfile($course, $cm, $context, $filearea, $args, $forcedownload, array $options = array()) { - global $CFG; - $urlpathid = clean_param($args[0], PARAM_INT); $originalimgpath = local::get_url_path_by_id($urlpathid); $originalfile = local::get_img_file($originalimgpath); $optimisedpath = local::get_optimised_path($originalimgpath); $optimisedurlpath = local::get_optimised_path($originalimgpath, false); - $fs = get_file_storage(); - $optimisedfile = local::get_img_file($optimisedpath); if ($optimisedfile) { @@ -61,11 +57,8 @@ function filter_imageopt_pluginfile($course, $cm, $context, $filearea, $args, $f $matches = []; preg_match($regex, $optimisedpath, $matches); $maxwidth = ($matches[1]); - $item = $originalfile->get_itemid(); - $component = $originalfile->get_component(); $filename = $originalfile->get_filename(); $filearea = $originalfile->get_filearea(); - $pathinfo = pathinfo($filename); $originalts = $originalfile->get_timemodified(); diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..5945189 --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + . + + + + + . + + + . + settings.php + version.php + + + + diff --git a/tests/behat/behat_filter_imageopt.php b/tests/behat/behat_filter_imageopt.php index efc3fb3..545d7b3 100644 --- a/tests/behat/behat_filter_imageopt.php +++ b/tests/behat/behat_filter_imageopt.php @@ -16,6 +16,7 @@ /** * Imageopt filter context + * @package filter_imageopt * @author Guy Thomas * @copyright Copyright (c) 2017 Guy Thomas. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later @@ -28,12 +29,15 @@ /** * Imageopt filter context + * @package filter_imageopt * @author Guy Thomas * @copyright Copyright (c) 2017 Guy Thomas. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class behat_filter_imageopt extends behat_base { /** + * If image optimiser is eneabled. + * * @Given /^the image optimiser filter is enabled$/ */ public function the_imageopt_filter_is_enabled() { @@ -66,6 +70,8 @@ protected function get_current_course() { } /** + * The image has been optimised + * * @Given /^the image "(?P[^"]*)" has been optimised$/ * @param string $imgfile */ @@ -74,6 +80,8 @@ public function image_optimised($imgfile) { } /** + * The image has not been optimised. + * * @Given /^the image "(?P[^"]*)" has not been optimised$/ * @param string $imgfile */ @@ -82,18 +90,18 @@ public function image_not_optimised($imgfile) { } /** + * I directly open the image in the test label in course + * * @Given /^I directly open the image "(?P[^"]*)" in the test label in course "(?P[^"]*)"$/ * @param string $imgfile * @param string $courseshortname * @throws ExpectationException */ public function open_label_image_directly($imgfile, $courseshortname) { - global $DB, $CFG; + global $DB; $course = $DB->get_record('course', ['shortname' => $courseshortname]); - $rs = $DB->get_records('label'); - $row = $DB->get_record('label', ['name' => 'test label', 'course' => $course->id]); $text = $row->intro; @@ -175,4 +183,4 @@ public function i_create_label_with_sample_images($images) { $label->name = 'test label'; $DB->update_record('label', $label); } -} \ No newline at end of file +} diff --git a/tests/behat/image_processing.feature b/tests/behat/image_processing.feature index aa0453e..23cf948 100644 --- a/tests/behat/image_processing.feature +++ b/tests/behat/image_processing.feature @@ -60,4 +60,4 @@ Feature: When the image optimiser filter is enabled, images are placeheld until # The page is reloaded to nuke image cache. And I reload the page And I wait until "#page-content" "css_element" exists - And I should see "Some courses may allow guest access" in the "#page-login-index" "css_element" \ No newline at end of file + And I should see "Some courses may allow guest access" in the "#page-login-index" "css_element" diff --git a/tests/filter_test.php b/tests/filter_test.php index bf8b6ff..f6910fa 100644 --- a/tests/filter_test.php +++ b/tests/filter_test.php @@ -22,14 +22,17 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +namespace filter_imageopt; + defined('MOODLE_INTERNAL') || die(); use filter_imageopt\local; +use stored_file; global $CFG; require_once($CFG->dirroot . '/files/externallib.php'); -require_once(__DIR__.'/../filter.php'); +require_once($CFG->dirroot . '/filter/imageopt/filter.php'); /** * Tests for filter class @@ -38,7 +41,7 @@ * @copyright Guy Thomas 2017. * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class filter_imageopt_filter_testcase extends advanced_testcase { +class filter_test extends \advanced_testcase { /** * Test regex works with sample img tag + pluginfile.php src. @@ -76,24 +79,24 @@ public function test_regex() { /** * Test empty svg image contains width and height params. - * @throws dml_exception + * @throws \dml_exception */ public function test_empty_image() { - $filter = new filter_imageopt(context_system::instance(), []); + $filter = new \filter_imageopt(\context_system::instance(), []); $sizes = [ [400, 300], [640, 480], [1024, 768] ]; foreach ($sizes as $size) { - $emptyimage = phpunit_util::call_internal_method($filter, 'empty_image', $size, get_class($filter)); + $emptyimage = \phpunit_util::call_internal_method($filter, 'empty_image', $size, get_class($filter)); $this->assertStringContainsString('width="'.$size[0].'" height="'.$size[1].'"', $emptyimage); } } /** * Test image opt url is created as expected. - * @throws dml_exception + * @throws \dml_exception */ public function test_image_opt_url() { global $CFG, $DB; @@ -104,26 +107,26 @@ public function test_image_opt_url() { set_config('maxwidth', '480', 'filter_imageopt'); $fixturefile = 'testpng_2880x1800.png'; - $context = context_system::instance(); + $context = \context_system::instance(); $file = $this->std_file_record($context, $fixturefile); - $filter = new filter_imageopt($context, []); + $filter = new \filter_imageopt($context, []); $originalurl = 'http://somesite/pluginfile.php/somefile.jpg'; - $url = phpunit_util::call_internal_method($filter, 'image_opt_url', [$file, $originalurl], get_class($filter)); + $url = \phpunit_util::call_internal_method($filter, 'image_opt_url', [$file, $originalurl], get_class($filter)); $row = $DB->get_record('filter_imageopt', ['urlpath' => 'pluginfile.php/somefile.jpg']); $urlpathid = $row->id; - $expected = new moodle_url( + $expected = new \moodle_url( $CFG->wwwroot.'/pluginfile.php/'.$context->id.'/filter_imageopt/480'.'/'.$urlpathid.'/'.$file->get_filename()); $this->assertEquals($expected, $url); } /** * Test img_add_width_height function. - * @throws dml_exception + * @throws \dml_exception */ public function test_img_add_width_height() { $this->resetAfterTest(); @@ -132,30 +135,30 @@ public function test_img_add_width_height() { set_config('maxwidth', $maxwidth, 'filter_imageopt'); $newheight = (400 / 800) * $maxwidth; - $context = context_system::instance(); - $filter = new filter_imageopt($context, []); + $context = \context_system::instance(); + $filter = new \filter_imageopt($context, []); $img = ''; - $img = phpunit_util::call_internal_method($filter, 'img_add_width_height', [$img, 800, 400], get_class($filter)); + $img = \phpunit_util::call_internal_method($filter, 'img_add_width_height', [$img, 800, 400], get_class($filter)); $expected = ''; $this->assertEquals($expected, $img); $img = ''; $expected = ''; - $img = phpunit_util::call_internal_method($filter, 'img_add_width_height', [$img, 800, 400], get_class($filter)); + $img = \phpunit_util::call_internal_method($filter, 'img_add_width_height', [$img, 800, 400], get_class($filter)); $this->assertEquals($expected, $img); } /** * Create moodle file. - * @param context $context + * @param \context $context * @param string $fixturefile name of fixture file * @return stored_file - * @throws file_exception - * @throws stored_file_creation_exception + * @throws \file_exception + * @throws \stored_file_creation_exception */ - private function std_file_record(context $context, $fixturefile) { + private function std_file_record(\context $context, $fixturefile) { global $CFG; $component = 'mod_label'; @@ -170,7 +173,7 @@ private function std_file_record(context $context, $fixturefile) { 'filename' => $fixturefile ]; - $fs = \get_file_storage(); + $fs = get_file_storage(); $file = $fs->create_file_from_pathname($filerecord, $CFG->dirroot.'/filter/imageopt/tests/fixtures/'.$fixturefile); return $file; @@ -178,7 +181,7 @@ private function std_file_record(context $context, $fixturefile) { /** * Test getting image from file path. - * @throws coding_exception + * @throws \coding_exception */ public function test_get_img_file() { @@ -190,36 +193,34 @@ public function test_get_img_file() { $fixturefile = 'testpng_2880x1800.png'; $intro = '


'; $label = $plugin->create_instance((object) ['course' => $course->id, 'intro' => $intro]); - $context = context_module::instance($label->cmid); + $context = \context_module::instance($label->cmid); $this->std_file_record($context, $fixturefile); - $filter = new filter_imageopt($context, []); - $filepath = 'pluginfile.php/'.$context->id.'/mod_label/intro/'.$fixturefile; /** @var stored_file $imgfile */ - $imgfile = phpunit_util::call_internal_method(null, 'get_img_file', [$filepath], 'filter_imageopt\local'); + $imgfile = \phpunit_util::call_internal_method(null, 'get_img_file', [$filepath], 'filter_imageopt\local'); $this->assertNotEmpty($imgfile); $this->assertEquals($fixturefile, $imgfile->get_filename()); } /** * Return image file in label and return label text + regex matches. + * @param stored_file $fixturefile * @return [string, array, stored_file] - * @throws coding_exception - * @throws file_exception + * @throws \coding_exception + * @throws \file_exception * @throws stored_file_creation_exception */ private function create_image_file_text($fixturefile) { - $dg = $this->getDataGenerator(); $course = $dg->create_course(); $plugin = $dg->get_plugin_generator('mod_label'); $intro = '


'; $label = $plugin->create_instance((object) ['course' => $course->id, 'intro' => $intro]); - $context = context_module::instance($label->cmid); + $context = \context_module::instance($label->cmid); $file = $this->std_file_record($context, $fixturefile); @@ -254,7 +255,7 @@ public function test_apply_loadonvisible() { /** @var stored_file $file */ $file = $file; - $filter = new filter_imageopt(context_helper::instance_by_id($file->get_contextid()), []); + $filter = new \filter_imageopt(\context_helper::instance_by_id($file->get_contextid()), []); $regex = local::REGEXP_IMGSRC; preg_match($regex, $labeltxt, $matches); @@ -263,7 +264,7 @@ public function test_apply_loadonvisible() { $optimisedsrc = $filter->image_opt_url($file, $originalsrc); - $str = phpunit_util::call_internal_method($filter, 'apply_loadonvisible', [$matches, $file, $originalsrc, $optimisedsrc], + $str = \phpunit_util::call_internal_method($filter, 'apply_loadonvisible', [$matches, $file, $originalsrc, $optimisedsrc], get_class($filter)); $loadonvisibleurl = $CFG->wwwroot.'/pluginfile.php/'.$file->get_contextid().'/filter_imageopt/'. @@ -271,15 +272,16 @@ public function test_apply_loadonvisible() { // Test filter plugin img, lazy load. $regex = '/img data-loadonvisible="'.str_replace('~pathid~', '(?:[0-9]*)', preg_quote($loadonvisibleurl, '/')).'/'; - $this->assertRegExp($regex, $str); + $this->assertMatchesRegularExpression($regex, $str); $this->assertStringContainsString('src="data:image/svg+xml;utf8,', $str); } /** * Get the replacement imageopt filter image url for a stored_file. + * * @param stored_file $file - * @param int $maxwidth; + * @param int $maxwidth * @return string. */ private function filter_imageopt_url_from_file(stored_file $file, $maxwidth) { @@ -293,7 +295,8 @@ private function filter_imageopt_url_from_file(stored_file $file, $maxwidth) { /** * Test processing image src. - * @throws coding_exception + * + * @throws \coding_exception */ public function test_apply_img_tag() { @@ -308,25 +311,25 @@ public function test_apply_img_tag() { list ($labeltxt, $matches, $file) = $this->create_image_file_text($fixturefile); - $context = context_helper::instance_by_id($file->get_contextid()); + $context = \context_helper::instance_by_id($file->get_contextid()); - $filter = new filter_imageopt($context, []); + $filter = new \filter_imageopt($context, []); $originalsrc = $matches[2]; $optimisedsrc = $filter->image_opt_url($file, $originalsrc); - $processed = phpunit_util::call_internal_method($filter, 'apply_img_tag', [$matches, $file, $originalsrc, $optimisedsrc], + $processed = \phpunit_util::call_internal_method($filter, 'apply_img_tag', [$matches, $file, $originalsrc, $optimisedsrc], get_class($filter)); $postfilterurl = $this->filter_imageopt_url_from_file($file, $maxwidth); $regex = '/'.str_replace('~pathid~', '(?:[0-9]*)', preg_quote($postfilterurl, '/')).'/'; - $this->assertRegExp($regex, $processed); + $this->assertMatchesRegularExpression($regex, $processed); } /** * Test main filter function. - * @throws coding_exception + * @throws \coding_exception */ public function test_filter() { global $CFG; @@ -342,17 +345,17 @@ public function test_filter() { list ($labeltxt, $matches, $file) = $this->create_image_file_text($fixturefile); - $context = context_helper::instance_by_id($file->get_contextid()); + $context = \context_helper::instance_by_id($file->get_contextid()); // Test filter plugin img, no lazy load. set_config('loadonvisible', '999', 'filter_imageopt'); // 999 does not lazy load any images. - $filter = new filter_imageopt($context, []); + $filter = new \filter_imageopt($context, []); $filtered = $filter->filter($labeltxt); $prefilterurl = $CFG->wwwroot.'/pluginfile.php/'.$context->id.'/mod_label/intro/0/testpng_2880x1800.png'; $this->assertStringContainsString($prefilterurl, $labeltxt); $postfilterurl = $this->filter_imageopt_url_from_file($file, $maxwidth); $regex = '/src="'.str_replace('~pathid~', '(?:[0-9]*)', preg_quote($postfilterurl, '/')).'/'; - $this->assertRegExp($regex, $filtered); + $this->assertMatchesRegularExpression($regex, $filtered); // We need a space before src so it doesn't trigger on original-src. $this->assertStringNotContainsString(' src="'.$prefilterurl, $filtered); @@ -361,17 +364,17 @@ public function test_filter() { // Test filter plugin img, lazy load. set_config('loadonvisible', '0', 'filter_imageopt'); - $filter = new filter_imageopt($context, []); + $filter = new \filter_imageopt($context, []); $filtered = $filter->filter($labeltxt); $prefilterurl = $CFG->wwwroot.'/pluginfile.php/'.$context->id.'/mod_label/intro/0/testpng_2880x1800.png'; $this->assertStringContainsString($prefilterurl, $labeltxt); $postfilterurl = $this->filter_imageopt_url_from_file($file, $maxwidth); $regex = '/data-loadonvisible="'.str_replace('~pathid~', '(?:[0-9]*)', preg_quote($postfilterurl, '/')).'/'; - $this->assertRegExp($regex, $filtered); + $this->assertMatchesRegularExpression($regex, $filtered); $this->assertStringNotContainsString('data-loadonvisible="'.$prefilterurl, $filtered); $this->assertStringNotContainsString('src="'.$postfilterurl, $filtered); $this->assertStringNotContainsString('src="'.$prefilterurl, $filtered); } -} \ No newline at end of file +} diff --git a/tests/privacy/privacy_test.php b/tests/privacy/privacy_test.php new file mode 100644 index 0000000..20c285e --- /dev/null +++ b/tests/privacy/privacy_test.php @@ -0,0 +1,50 @@ +. + +/** + * Tests for filter class + * @package filter_imageopt + * @author Guy Thomas + * @copyright Guy Thomas 2017. + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +namespace filter_imageopt\privacy; + +defined('MOODLE_INTERNAL') || die(); + +use \core_privacy\tests\provider_testcase; + +/** + * Tests for filter class + * @package filter_imageopt + * @author Guy Thomas + * @copyright Guy Thomas 2017. + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +class privacy_test extends provider_testcase { + + /** + * Test returning metadata. + * @coversDefaultClass filter_iplus\privacy\provider + */ + public function test_get_metadata() { + $privacy = new provider(); + $reason = $privacy->get_reason(); + $this->assertEquals($reason, 'privacy:metadata'); + $this->assertStringContainsString('does not store', get_string($reason, 'filter_imageopt')); + } +} From 94092ad0294167b707a959038ddf60ae253580df Mon Sep 17 00:00:00 2001 From: Renaat Debleu Date: Tue, 4 Jan 2022 13:57:36 +0000 Subject: [PATCH 05/11] code review --- styles.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/styles.css b/styles.css index 87ea116..f0c6714 100644 --- a/styles.css +++ b/styles.css @@ -12,7 +12,7 @@ img.imageopt_loading { /* to provide animation - loading separate assets would make the animation fliker the first time it was viewed. /* I tried to use an svg spriting technique for this but it didn't work. /* csslint ignore:start */ - 0% { + 0% { background-image: url("data:image/svg+xml;utf8,"); } 20% { From ac99ad6014bd625ee9dc73a9757610f781b06528 Mon Sep 17 00:00:00 2001 From: Renaat Debleu Date: Sun, 12 Mar 2023 23:44:21 +0100 Subject: [PATCH 06/11] grunt --- .github/workflows/main.yml | 11 +++-------- amd/build/appear.min.js | 4 +++- amd/build/appear.min.js.map | 1 + amd/build/imageopt.min.js | 23 ++++++++++++++++++++++- amd/build/imageopt.min.js.map | 1 + db/install.xml | 2 +- version.php | 2 +- 7 files changed, 32 insertions(+), 12 deletions(-) create mode 100644 amd/build/appear.min.js.map create mode 100644 amd/build/imageopt.min.js.map diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ca4454a..6fa2364 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -9,19 +9,15 @@ jobs: strategy: fail-fast: false matrix: - moodle-branch: ['MOODLE_311_STABLE'] - php: ['7.4'] + moodle-branch: ['MOODLE_401_STABLE'] + php: ['8.0'] database: ['mysqli'] - include: - - php: 8.0 - moodle-branch: master - database: mysqli name: ${{ matrix.moodle-branch }} php ${{ matrix.php }} ${{ matrix.database }} steps: - name: checkout plugin - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: path: this-plugin @@ -40,7 +36,6 @@ jobs: echo $(cd ci/vendor/bin; pwd) >> $GITHUB_PATH sudo locale-gen en_AU.UTF-8 sudo systemctl start mysql.service - sed -i 's/phpdbg -d memory_limit=-1 -qrr//g' ci/src/Command/PHPUnitCommand.php - name: install Moodle run: moodle-plugin-ci install -v --db-user=root --db-pass=root --db-host=127.0.0.1 --plugin this-plugin diff --git a/amd/build/appear.min.js b/amd/build/appear.min.js index b73bf1f..4335bf8 100644 --- a/amd/build/appear.min.js +++ b/amd/build/appear.min.js @@ -1 +1,3 @@ -define(["jquery"],function(a){var b=a;return b(),function(a){function b(b){return a(b).filter(function(){return a(this).is(":appeared")})}function c(){g=!1;for(var a=0,c=e.length;a=e&&h-k<=e+j.height()&&g+c.width()+l>=d&&g-l<=d+j.width()},a.fn.extend({appear:function(b){i=a.extend({},h,b||{});var e=this.selector||this;if(!f){var j=function(){g||(g=!0,setTimeout(c,i.interval))};a(window).scroll(j).resize(j),f=!0}return i.force_process&&setTimeout(c,i.interval),d(e),a(e)}}),a.extend({force_appear:function(){return!!f&&(c(),!0)}})}(function(){return"undefined"!=typeof module?require("jquery"):a}()),a}); \ No newline at end of file +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 new file mode 100644 index 0000000..550cb77 --- /dev/null +++ b/amd/build/appear.min.js.map @@ -0,0 +1 @@ +{"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 cf3c342..693881f 100644 --- a/amd/build/imageopt.min.js +++ b/amd/build/imageopt.min.js @@ -1 +1,22 @@ -define(["filter_imageopt/appear"],function(a){return{init:function(){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)})});var c={appeartopoffset:100,appearleftoffset:100};a("img[data-loadonvisible]").appear(c),a.force_appear(),function(){var b=location.hash;a(window).on("popstate hashchange",function(){var c=location.hash;c!==b&&window.setTimeout(function(){a.force_appear()},200),b=c})}()})}}}); \ No newline at end of file +/** + * 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 . + * + * @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 new file mode 100644 index 0000000..ec830ad --- /dev/null +++ b/amd/build/imageopt.min.js.map @@ -0,0 +1 @@ +{"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 * @copyright Copyright (c) 2017 Guy Thomas\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\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,KAAK,WAiBDD,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,gBAAkB,IAAKC,iBAAmB,MAE5DrB,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/db/install.xml b/db/install.xml index 65c2276..7816853 100644 --- a/db/install.xml +++ b/db/install.xml @@ -19,4 +19,4 @@ - \ No newline at end of file + diff --git a/version.php b/version.php index 134a6b7..cd42b05 100644 --- a/version.php +++ b/version.php @@ -22,7 +22,7 @@ */ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2021050100; +$plugin->version = 2022020800; $plugin->requires = 2011111500; $plugin->component = 'filter_imageopt'; $plugin->maturity = MATURITY_BETA; From 10fdcb89cc26d53c3766919063365c38587a5003 Mon Sep 17 00:00:00 2001 From: Renaat Debleu Date: Sun, 12 Mar 2023 23:46:12 +0100 Subject: [PATCH 07/11] cbf checks --- version.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/version.php b/version.php index cd42b05..c1d6121 100644 --- a/version.php +++ b/version.php @@ -22,8 +22,8 @@ */ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2022020800; -$plugin->requires = 2011111500; +$plugin->version = 2022020800; +$plugin->requires = 2011111500; $plugin->component = 'filter_imageopt'; -$plugin->maturity = MATURITY_BETA; -$plugin->release = '3.9.0.0'; +$plugin->maturity = MATURITY_BETA; +$plugin->release = '3.9.0.0'; From 7c24a598303f5c9ee6d11389fe56f309f0177291 Mon Sep 17 00:00:00 2001 From: Renaat Debleu Date: Mon, 13 Mar 2023 02:46:25 +0100 Subject: [PATCH 08/11] code review --- classes/componentsupport/base_component.php | 2 -- classes/componentsupport/mod_page.php | 2 -- classes/componentsupport/question.php | 2 -- classes/image.php | 7 +++---- classes/local.php | 2 -- db/upgrade.php | 2 -- filter.php | 2 -- lib.php | 2 -- tests/filter_test.php | 8 ++++++++ tests/privacy/privacy_test.php | 4 +--- 10 files changed, 12 insertions(+), 21 deletions(-) diff --git a/classes/componentsupport/base_component.php b/classes/componentsupport/base_component.php index fa62d1b..0631723 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; - /** * Abstract class. * diff --git a/classes/componentsupport/mod_page.php b/classes/componentsupport/mod_page.php index 8b1b1c4..0ed734f 100644 --- a/classes/componentsupport/mod_page.php +++ b/classes/componentsupport/mod_page.php @@ -23,8 +23,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 682a8cd..e738f69 100644 --- a/classes/componentsupport/question.php +++ b/classes/componentsupport/question.php @@ -23,8 +23,6 @@ */ namespace filter_imageopt\componentsupport; -defined('MOODLE_INTERNAL') || die; - use filter_imageopt\local; /** diff --git a/classes/image.php b/classes/image.php index edf4ac1..0ae4917 100644 --- a/classes/image.php +++ b/classes/image.php @@ -25,11 +25,10 @@ */ namespace filter_imageopt; - -defined('MOODLE_INTERNAL') || die(); - use stored_file; + +defined('MOODLE_INTERNAL') || die(); require_once($CFG->libdir.'/gdlib.php'); /** @@ -182,7 +181,7 @@ public static function resize ( if (function_exists('imagecreatetruecolor')) { $newimage = imagecreatetruecolor($newwidth, $newheight); - if ($imageinfo->mimetype != 'image/jpeg' and $imagefnc === 'imagepng') { + if ($imageinfo->mimetype != 'image/jpeg' && $imagefnc === 'imagepng') { if ($t) { // Transparent GIF hacking... $transparentcolour = imagecolorallocate($newimage , $t['red'] , $t['green'] , $t['blue']); diff --git a/classes/local.php b/classes/local.php index e43f64c..3c4f9a5 100644 --- a/classes/local.php +++ b/classes/local.php @@ -24,8 +24,6 @@ */ namespace filter_imageopt; -defined('MOODLE_INTERNAL') || die(); - use stored_file; /** diff --git a/db/upgrade.php b/db/upgrade.php index 8801f70..29402c3 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 * diff --git a/filter.php b/filter.php index bd32408..cb2fa71 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\image; use filter_imageopt\local; diff --git a/lib.php b/lib.php index cb2404e..12bafce 100644 --- a/lib.php +++ b/lib.php @@ -25,8 +25,6 @@ use filter_imageopt\image; use filter_imageopt\local; -defined('MOODLE_INTERNAL') || die(); - /** * Serves any files associated with the image optimiser filter * diff --git a/tests/filter_test.php b/tests/filter_test.php index f6910fa..a8a0b69 100644 --- a/tests/filter_test.php +++ b/tests/filter_test.php @@ -45,6 +45,7 @@ class filter_test extends \advanced_testcase { /** * Test regex works with sample img tag + pluginfile.php src. + * @covers \filter_iplus */ public function test_regex() { $regex = local::REGEXP_IMGSRC; @@ -80,6 +81,7 @@ public function test_regex() { /** * Test empty svg image contains width and height params. * @throws \dml_exception + * @covers \filter_iplus */ public function test_empty_image() { $filter = new \filter_imageopt(\context_system::instance(), []); @@ -97,6 +99,7 @@ public function test_empty_image() { /** * Test image opt url is created as expected. * @throws \dml_exception + * @covers \filter_iplus */ public function test_image_opt_url() { global $CFG, $DB; @@ -127,6 +130,7 @@ public function test_image_opt_url() { /** * Test img_add_width_height function. * @throws \dml_exception + * @covers \filter_iplus */ public function test_img_add_width_height() { $this->resetAfterTest(); @@ -182,6 +186,7 @@ private function std_file_record(\context $context, $fixturefile) { /** * Test getting image from file path. * @throws \coding_exception + * @covers \filter_iplus */ public function test_get_img_file() { @@ -236,6 +241,7 @@ private function create_image_file_text($fixturefile) { /** * Test apply load on visible. * @throws coding_exception + * @covers \filter_iplus */ public function test_apply_loadonvisible() { global $CFG; @@ -297,6 +303,7 @@ private function filter_imageopt_url_from_file(stored_file $file, $maxwidth) { * Test processing image src. * * @throws \coding_exception + * @covers \filter_iplus */ public function test_apply_img_tag() { @@ -330,6 +337,7 @@ public function test_apply_img_tag() { /** * Test main filter function. * @throws \coding_exception + * @covers \filter_iplus */ public function test_filter() { global $CFG; diff --git a/tests/privacy/privacy_test.php b/tests/privacy/privacy_test.php index 20c285e..a292aa4 100644 --- a/tests/privacy/privacy_test.php +++ b/tests/privacy/privacy_test.php @@ -24,8 +24,6 @@ namespace filter_imageopt\privacy; -defined('MOODLE_INTERNAL') || die(); - use \core_privacy\tests\provider_testcase; /** @@ -39,7 +37,7 @@ class privacy_test extends provider_testcase { /** * Test returning metadata. - * @coversDefaultClass filter_iplus\privacy\provider + * @covers \filter_iplus\privacy\provider */ public function test_get_metadata() { $privacy = new provider(); From f5e7f3b4c024a3e54267ffbc5b665ff457335c1c Mon Sep 17 00:00:00 2001 From: Renaat Debleu Date: Mon, 13 Mar 2023 02:54:59 +0100 Subject: [PATCH 09/11] wrong namespace --- tests/filter_test.php | 17 +++++++++-------- tests/privacy/privacy_test.php | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/tests/filter_test.php b/tests/filter_test.php index a8a0b69..4ce8de1 100644 --- a/tests/filter_test.php +++ b/tests/filter_test.php @@ -45,7 +45,7 @@ class filter_test extends \advanced_testcase { /** * Test regex works with sample img tag + pluginfile.php src. - * @covers \filter_iplus + * @covers \filter_imageopt */ public function test_regex() { $regex = local::REGEXP_IMGSRC; @@ -81,7 +81,7 @@ public function test_regex() { /** * Test empty svg image contains width and height params. * @throws \dml_exception - * @covers \filter_iplus + * @covers \filter_imageopt */ public function test_empty_image() { $filter = new \filter_imageopt(\context_system::instance(), []); @@ -99,7 +99,7 @@ public function test_empty_image() { /** * Test image opt url is created as expected. * @throws \dml_exception - * @covers \filter_iplus + * @covers \filter_imageopt */ public function test_image_opt_url() { global $CFG, $DB; @@ -130,7 +130,7 @@ public function test_image_opt_url() { /** * Test img_add_width_height function. * @throws \dml_exception - * @covers \filter_iplus + * @covers \filter_imageopt */ public function test_img_add_width_height() { $this->resetAfterTest(); @@ -186,7 +186,8 @@ private function std_file_record(\context $context, $fixturefile) { /** * Test getting image from file path. * @throws \coding_exception - * @covers \filter_iplus + * @covers \filter_imageopt\local + * @covers \filter_imageopt\image */ public function test_get_img_file() { @@ -241,7 +242,7 @@ private function create_image_file_text($fixturefile) { /** * Test apply load on visible. * @throws coding_exception - * @covers \filter_iplus + * @covers \filter_imageopt */ public function test_apply_loadonvisible() { global $CFG; @@ -303,7 +304,7 @@ private function filter_imageopt_url_from_file(stored_file $file, $maxwidth) { * Test processing image src. * * @throws \coding_exception - * @covers \filter_iplus + * @covers \filter_imageopt */ public function test_apply_img_tag() { @@ -337,7 +338,7 @@ public function test_apply_img_tag() { /** * Test main filter function. * @throws \coding_exception - * @covers \filter_iplus + * @covers \filter_imageopt */ public function test_filter() { global $CFG; diff --git a/tests/privacy/privacy_test.php b/tests/privacy/privacy_test.php index a292aa4..c9cb4df 100644 --- a/tests/privacy/privacy_test.php +++ b/tests/privacy/privacy_test.php @@ -37,7 +37,7 @@ class privacy_test extends provider_testcase { /** * Test returning metadata. - * @covers \filter_iplus\privacy\provider + * @covers \filter_imageopt\privacy\provider */ public function test_get_metadata() { $privacy = new provider(); From ec870b7c553ebce60e8e3dda77a52c9376a21a6e Mon Sep 17 00:00:00 2001 From: Renaat Debleu Date: Thu, 11 May 2023 11:25:34 +0200 Subject: [PATCH 10/11] php 8.1 --- .github/workflows/main.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 6fa2364..04dee53 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -9,8 +9,8 @@ jobs: strategy: fail-fast: false matrix: - moodle-branch: ['MOODLE_401_STABLE'] - php: ['8.0'] + moodle-branch: ['MOODLE_401_STABLE', 'MOODLE_402_STABLE'] + php: ['8.1'] database: ['mysqli'] name: ${{ matrix.moodle-branch }} php ${{ matrix.php }} ${{ matrix.database }} @@ -31,7 +31,7 @@ jobs: - name: composer run: | - composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^3 + composer create-project -n --no-dev --prefer-dist moodlehq/moodle-plugin-ci ci ^4 echo $(cd ci/bin; pwd) >> $GITHUB_PATH echo $(cd ci/vendor/bin; pwd) >> $GITHUB_PATH sudo locale-gen en_AU.UTF-8 From 92c461cd58ffb9d192937c9113ef665d3ee7d411 Mon Sep 17 00:00:00 2001 From: Renaat Debleu Date: Thu, 3 Aug 2023 09:10:16 +0200 Subject: [PATCH 11/11] workflow --- .github/workflows/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 04dee53..888f2ec 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -27,7 +27,7 @@ jobs: php-version: ${{ matrix.php }} extensions: mbstring, mysqli, gd, zip ini-values: max_input_vars=5000 - coverage: xdebug + coverage: pcov - name: composer run: |