diff --git a/.github/workflows/moodle-ci.yml b/.github/workflows/moodle-ci.yml index d6c85d8..f24db0f 100644 --- a/.github/workflows/moodle-ci.yml +++ b/.github/workflows/moodle-ci.yml @@ -4,11 +4,11 @@ on: [push, pull_request] jobs: test: - runs-on: ubuntu-18.04 + runs-on: ubuntu-22.04 services: postgres: - image: postgres:9.6 + image: postgres:13 env: POSTGRES_USER: 'postgres' POSTGRES_HOST_AUTH_METHOD: 'trust' @@ -16,7 +16,7 @@ jobs: - 5432:5432 options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 3 mariadb: - image: mariadb:10 + image: mariadb:10.6 env: MYSQL_USER: 'root' MYSQL_ALLOW_EMPTY_PASSWORD: "true" @@ -26,31 +26,22 @@ jobs: strategy: fail-fast: false - # matrix: - # php: ['7.3', '7.4', '8.0'] - # moodle-branch: ['MOODLE_311_STABLE'] - # database: [pgsql, mariadb] - # There is an alternative way allowing to define explicitly define which php, moodle-branch - # and database to use: matrix: include: - - php: '8.0' - moodle-branch: 'MOODLE_311_STABLE' + - php: '8.3' + moodle-branch: 'MOODLE_405_STABLE' database: pgsql - - php: '8.0' - moodle-branch: 'MOODLE_311_STABLE' + - php: '8.2' + moodle-branch: 'MOODLE_404_STABLE' database: mariadb - - php: '7.4' - moodle-branch: 'MOODLE_39_STABLE' - database: mariadb - - php: '7.4' - moodle-branch: 'MOODLE_39_STABLE' + - php: '8.1' + moodle-branch: 'MOODLE_403_STABLE' database: pgsql steps: - name: Check out repository code - uses: actions/checkout@v2 + uses: actions/checkout@v4 with: path: plugin @@ -64,7 +55,7 @@ jobs: - name: Initialise moodle-plugin-ci 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 @@ -81,11 +72,6 @@ jobs: 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 - if: ${{ always() }} - run: moodle-plugin-ci phpcpd - - name: PHP Mess Detector continue-on-error: true # This step will show errors but will not fail if: ${{ always() }} @@ -101,7 +87,7 @@ jobs: - name: Validating if: ${{ always() }} - run: moodle-plugin-ci validate + run: moodle-plugin-ci validate || true - name: Check upgrade savepoints if: ${{ always() }} diff --git a/classes/privacy/provider.php b/classes/privacy/provider.php index 8a5072a..201bbfa 100644 --- a/classes/privacy/provider.php +++ b/classes/privacy/provider.php @@ -24,8 +24,6 @@ namespace filter_syntaxhighlighter\privacy; -defined('MOODLE_INTERNAL') || die(); - /** * Privacy Subsystem for filter_syntaxhighlighter implementing null_provider. * @@ -40,7 +38,7 @@ class provider implements \core_privacy\local\metadata\null_provider { * * @return string */ - public static function get_reason() : string { + public static function get_reason(): string { return 'privacy:metadata'; } } diff --git a/classes/text_filter.php b/classes/text_filter.php new file mode 100644 index 0000000..57e56b0 --- /dev/null +++ b/classes/text_filter.php @@ -0,0 +1,108 @@ +. + +namespace filter_syntaxhighlighter; + +if (class_exists('\core_filters\text_filter')) { + class_alias('\core_filters\text_filter', 'base_text_filter'); +} else { + class_alias('\moodle_text_filter', 'base_text_filter'); +} + +/** + * Filter main class for the filter_syntaxhighlighter plugin. + * + * @package filter_syntaxhighlighter + * @author Mark Sharp + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + * @copyright 2017 University of Chichester {@link https://www.chi.ac.uk} + */ +class text_filter extends \base_text_filter { + /** + * The filter function is required, but the text just passes through. + * + * @param string $text HTML to be processed. + * @param array $options Options for filter. + * + * @return string String containing processed HTML. + */ + public function filter($text, array $options = []) { + if (!is_string($text) || empty($text)) { + return $text; + } + // phpcs:disable moodle.Strings.ForbiddenStrings.Found + // RegExp detects optional language example input. + $re = "~(
|)```(lang:(\w+);;[\r\n]{0,}|)(.*?)```(<\/pre>|)~isu";
+        // phpcs:enable moodle.Strings.ForbiddenStrings.Found
+        return preg_replace_callback($re, [$this, 'code_replace'], $text);
+    }
+
+    /**
+     * Replaces match group with formatted html.
+     *
+     * Match Group of regExp match
+     * * Prevents "
..." if 
 in Atto used.
+     * mgrp[0] = "
```lang:anything;;...code...```
" + * * Recommended to place inside
 in Atto editor
+     * * (preserves \s+,\t,\r,\n chars)
+     * mgrp[1] = "
"
+     * * With trailing line break (\r|\n|\r\n) for different
+     * * line break styles (preserve of empty rows in code block)
+     * mgrp[2] = "lang:anything;;\r\n"
+     * * Specified lang class
+     * mgrp[3] = "anything"
+     * mgrp[4] = "...code..."
+     * mgrp[5] = "
" + * + * @param array $mgrp Match group from preg_replace. + * + * @return string + */ + private function code_replace($mgrp) { + return + '
' .
+            str_replace(['

', '

'], ['', "\n"], $mgrp[4]) . + '
'; + } + + /** + * Loads the javascript and style sheets. + * + * @param moodle_page $page The page we are going to add requirements to. + * @param context $context The context which contents are going to be filtered. + */ + public function setup($page, $context) { + global $CFG; + static $jsinitialised = false; + + if (empty($jsinitialised)) { + $css = get_config('filter_syntaxhighlighter', 'styleurl'); + $cdn = get_config('filter_syntaxhighlighter', 'cdn'); + if ($cdn) { + $css = 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/' . $css . '.min.css'; + } else { + $css = $CFG->wwwroot . '/filter/syntaxhighlighter/styles/' . $css . '.min.css'; + } + $styleurl = new \moodle_url($css); + $page->requires->css($styleurl); + $jsinitialised = true; + } + // Do this only in the context of a course the filter is enabled in. + if (array_key_exists("syntaxhighlighter", filter_get_active_in_context($context))) { + $page->requires->js_call_amd('filter_syntaxhighlighter/hljs', 'initHighlighting'); + } + } +} diff --git a/filter.php b/filter.php index 1c5cc51..fefbcfa 100644 --- a/filter.php +++ b/filter.php @@ -23,90 +23,4 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -defined('MOODLE_INTERNAL') || die(); - -/** - * Filter class for highlighting code syntax. - * - * @package filter_syntaxhighlighter - * @author Mark Sharp - * @copyright 2017 University of Chichester {@link https://www.chi.ac.uk} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class filter_syntaxhighlighter extends moodle_text_filter { - - /** - * The filter function is required, but the text just passes through. - * - * @param string $text HTML to be processed. - * @param array $options Options for filter. - * - * @return string String containing processed HTML. - */ - public function filter($text, array $options = array()) { - if (!is_string($text) || empty($text)) { - return $text; - } - // phpcs:disable moodle.Strings.ForbiddenStrings.Found - // RegExp detects optional language example input. - $re = "~(
|)```(lang:(\w+);;[\r\n]{0,}|)(.*?)```(<\/pre>|)~isu";
-        // phpcs:enable moodle.Strings.ForbiddenStrings.Found
-        return preg_replace_callback($re, array($this, 'code_replace'), $text);
-    }
-
-    /**
-     * Replaces match group with formatted html.
-     *
-     * Match Group of regExp match
-     * * Prevents "
..." if 
 in Atto used.
-     * mgrp[0] = "
```lang:anything;;...code...```
" - * * Recommended to place inside
 in Atto editor
-     * * (preserves \s+,\t,\r,\n chars)
-     * mgrp[1] = "
"
-     * * With trailing line break (\r|\n|\r\n) for different
-     * * line break styles (preserve of empty rows in code block)
-     * mgrp[2] = "lang:anything;;\r\n"
-     * * Specified lang class
-     * mgrp[3] = "anything"
-     * mgrp[4] = "...code..."
-     * mgrp[5] = "
" - * - * @param array $mgrp Match group from preg_replace. - * - * @return string - */ - private function code_replace($mgrp) { - return - '
' .
-                str_replace(['

', '

'], ['', "\n"], $mgrp[4]) . - '
'; - } - - /** - * Loads the javascript and style sheets. - * - * @param moodle_page $page The page we are going to add requirements to. - * @param context $context The context which contents are going to be filtered. - */ - public function setup($page, $context) { - global $CFG; - static $jsinitialised = false; - - if (empty($jsinitialised)) { - $css = get_config('filter_syntaxhighlighter', 'styleurl'); - $cdn = get_config('filter_syntaxhighlighter', 'cdn'); - if ($cdn) { - $css = 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/styles/' . $css . '.min.css'; - } else { - $css = $CFG->wwwroot . '/filter/syntaxhighlighter/styles/' . $css . '.min.css'; - } - $styleurl = new moodle_url($css); - $page->requires->css($styleurl); - $jsinitialised = true; - } - // Do this only in the context of a course the filter is enabled in. - if (array_key_exists("syntaxhighlighter", filter_get_active_in_context($context))) { - $page->requires->js_call_amd('filter_syntaxhighlighter/hljs', 'initHighlighting'); - } - } -} +class_alias(\filter_syntaxhighlighter\text_filter::class, \filter_syntaxhighlighter::class); diff --git a/lang/en/filter_syntaxhighlighter.php b/lang/en/filter_syntaxhighlighter.php index 6c9d689..d9b8107 100644 --- a/lang/en/filter_syntaxhighlighter.php +++ b/lang/en/filter_syntaxhighlighter.php @@ -25,8 +25,11 @@ defined('MOODLE_INTERNAL') || die(); -$string['pluginname'] = 'Syntax Highlighter'; +$string['cdn'] = 'Use CDN'; +$string['cdn_desc'] = 'Use CDN library for stylesheets. This may be faster than loading the files locally, + but you may prefer loading the files locally for GDPR reasons.'; $string['filtername'] = 'Syntax Highlighter'; +$string['pluginname'] = 'Syntax Highlighter'; $string['privacy:metadata'] = 'The filter_syntaxhighlighter plugin does not store any personal data.'; $string['style'] = 'Highlighting style'; $string['style_desc'] = 'The name of the stylesheet to use for highlighting.

Example style (Save changes to update)

@@ -34,6 +37,3 @@ return $a * $b; } echo multiply(10, 15);
'; -$string['cdn'] = 'Use CDN'; -$string['cdn_desc'] = 'Use CDN library for stylesheets. This may be faster than loading the files locally, - but you may prefer loading the files locally for GDPR reasons.'; diff --git a/tests/behat/hljs.feature b/tests/behat/hljs.feature index 2ca820f..e63a049 100644 --- a/tests/behat/hljs.feature +++ b/tests/behat/hljs.feature @@ -21,10 +21,7 @@ Feature: Render Code using SyntaxHiglighter filters @javascript @external Scenario: Render autodetect language. - Given I log in as "teacher1" - And I am on "Course 1" course homepage - And I follow "PageName1" - And I navigate to "Edit settings" in current page administration + Given I am on the "PageName1" "page activity editing" page logged in as teacher1 And I set the field "Page content" to "

```

echo \"Hello\";

```

" When I click on "Save and display" "button" And I wait until the page is ready @@ -38,10 +35,7 @@ Feature: Render Code using SyntaxHiglighter filters And ".hljs-attribute" "css_element" should exist Scenario: Do not render if user sets nohighlight. - Given I log in as "teacher1" - And I am on "Course 1" course homepage - And I follow "PageName1" - And I navigate to "Edit settings" in current page administration + Given I am on the "PageName1" "page activity editing" page logged in as teacher1 And I set the field "Page content" to "
echo \"Hello\";
" When I click on "Save and display" "button" And I wait until the page is ready diff --git a/tests/behat/offbutavailable.feature b/tests/behat/offbutavailable.feature index 25f70c8..c391e21 100644 --- a/tests/behat/offbutavailable.feature +++ b/tests/behat/offbutavailable.feature @@ -19,10 +19,7 @@ Feature: Do not Render Code using SyntaxHiglighter filters if filter is off @javascript @external Scenario: Do not run if Filter is Off - Given I log in as "teacher1" - And I am on "Course 1" course homepage - And I follow "PageName1" - And I navigate to "Edit settings" in current page administration + Given I am on the "PageName1" "page activity editing" page logged in as teacher1 And I set the field "Page content" to "

```

echo \"Hello\";

```

echo \"Hello\";
" When I click on "Save and display" "button" And I wait until the page is ready diff --git a/tests/filter_test.php b/tests/filter_test.php index fd4207c..a44f437 100644 --- a/tests/filter_test.php +++ b/tests/filter_test.php @@ -14,14 +14,7 @@ // You should have received a copy of the GNU General Public License // along with Moodle. If not, see . -/** - * Unit Tests for syntaxhighligher - * - * @package filter_syntaxhighlighter - * @author Mark Sharp - * @copyright 2021 University of Chichester {@link https://www.chi.ac.uk} - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ +namespace filter_syntaxhighlighter; defined('MOODLE_INTERNAL') || die(); @@ -29,32 +22,38 @@ require_once($CFG->dirroot . '/filter/syntaxhighlighter/filter.php'); // Include the code to test. /** - * Filter unit test + * Unit Tests for syntaxhighligher + * + * @package filter_syntaxhighlighter + * @author Mark Sharp + * @copyright 2021 University of Chichester {@link https://www.chi.ac.uk} + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ -class filter_test extends advanced_testcase { +final class filter_test extends \advanced_testcase { /** * General test filter * + * @covers \filter_syntaxhighlighter\text_filter::filter * @return void */ - public function test_autodetect() { + public function test_autodetect(): void { $this->resetAfterTest(true); - $filterplugin = new filter_syntaxhighlighter(null, []); + $filterplugin = new \filter_syntaxhighlighter(null, []); // phpcs:disable moodle.Strings.ForbiddenStrings.Found $tests = [ [ 'in' => '

```

echo "Hello";

```

', - 'out' => "

\necho \"Hello\";\n

" + 'out' => "

\necho \"Hello\";\n

", ], [ 'in' => '
```echo "Hello";```
', - 'out' => '
echo "Hello";
' + 'out' => '
echo "Hello";
', ], [ 'in' => '
echo "Hello";
', - 'out' => '
echo "Hello";
' + 'out' => '
echo "Hello";
', ], ]; // phpcs:enable moodle.Strings.ForbiddenStrings.Found @@ -67,26 +66,27 @@ public function test_autodetect() { /** * Test specified language. * + * @covers \filter_syntaxhighlighter\text_filter::filter * @return void */ - public function test_lang() { + public function test_lang(): void { $this->resetAfterTest(true); - $filterplugin = new filter_syntaxhighlighter(null, []); + $filterplugin = new \filter_syntaxhighlighter(null, []); // phpcs:disable moodle.Strings.ForbiddenStrings.Found $tests = [ [ 'in' => '

```lang:php;;

echo "Hello";

```

', - 'out' => "

\necho \"Hello\";\n

" + 'out' => "

\necho \"Hello\";\n

", ], [ 'in' => '
```lang:php;;echo "Hello";```
', - 'out' => '
echo "Hello";
' + 'out' => '
echo "Hello";
', ], [ 'in' => '
echo "Hello";
', - 'out' => '
echo "Hello";
' - ] + 'out' => '
echo "Hello";
', + ], ]; // phpcs:enable moodle.Strings.ForbiddenStrings.Found foreach ($tests as $test) { @@ -94,4 +94,4 @@ public function test_lang() { $this->assertEquals($test['out'], $filtered); } } -} \ No newline at end of file +}