Skip to content

Commit

Permalink
V402.1.3
Browse files Browse the repository at this point in the history
  • Loading branch information
gjb2048 committed Apr 10, 2024
1 parent 10b0719 commit c37045b
Show file tree
Hide file tree
Showing 50 changed files with 858 additions and 205 deletions.
26 changes: 26 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Set the default behavior, in case people don't have core.autocrlf set.
* text eol=lf

# Explicitly declare text files you want to always be normalized and converted
# to native line endings on checkout.
*.php text
*.js text
*.json text
*.css text
*.md text
*.mustache text
*.scss text
*.svg text
*.txt text
*.xml text

# Denote all files that are truly binary and should not be modified.
*.eot binary
*.jpg binary
*.gif binary
*.ico binary
*.otf binary
*.png binary
*.ttf binary
*.woff binary
*.woff2 binary
10 changes: 5 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:

steps:
- name: Check out repository code
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
path: plugin

Expand Down Expand Up @@ -59,10 +59,10 @@ 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 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
Expand Down
11 changes: 11 additions & 0 deletions Changes.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
Change Log in version 402.1.3 (2023092504)
===========================================
1. New setting 'mobileprimarynav' to control the display of the mobile primary navigation. This is found on the
'Header' tab in the theme settings.
2. New setting 'customjsfiles' to allow the addition of one or more JavaScript files to be included before 'customjs'
is output to the page. Sponsors only functionality.
3. Fix 'ORPHANED BLOCK - Originally displays in: Course page', ref: https://moodle.org/mod/forum/discuss.php?d=456522.
4. Apply 'MDL-72923 message: Fixed levels of headings in messaging drawer'.
5. Fix 'Font on file storage admin type settings'.
6. Unix file endings - use 'find . -type f -print0 | xargs -0 dos2unix' in a Git Bash on Windows if you need to.

Change Log in version 402.1.2 (2023092503)
===========================================
1. Fix missing logo in alternative header for header style one.
Expand Down
294 changes: 294 additions & 0 deletions classes/admin_setting_configstoredfiles.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,294 @@
<?php
// 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 <http://www.gnu.org/licenses/>.

/**
* Adaptable theme.
*
* @package theme_adaptable
* @copyright 2024 G J Barnard
* @author G J Barnard -
* {@link https://moodle.org/user/profile.php?id=442195}
* {@link https://gjbarnard.co.uk}
* @license https://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later.
*/

namespace theme_adaptable;

use context_system;

defined('MOODLE_INTERNAL') || die;

// Require admin library.
require_once($CFG->libdir . '/adminlib.php');

/**
* Adaptable admin_setting_configstoredfiles
*/
class admin_setting_configstoredfiles extends \admin_setting_configstoredfile {
/** @var array of strings used for detection of changes */
protected $oldhashes;

/** @var object the owner if set */
protected $owner;

/**
* Create new stored files setting.
*
* @param string $name low level setting name.
* @param string $visiblename human readable setting name.
* @param string $description description of setting.
* @param mixed $filearea file area for file storage.
* @param array $options file area options.
* @param int $itemid itemid for file storage.
*/
public function __construct($name, $visiblename, $description, $filearea, array $options = null, $itemid = 0) {
$this->oldhashes = [];
$this->owner = null;
parent::__construct($name, $visiblename, $description, $filearea, $itemid, $options);
}

/**
* Applies defaults and returns all options.
* @return array Defaults.
*/
protected function get_options() {
global $CFG;

require_once("$CFG->libdir/filelib.php");
require_once("$CFG->dirroot/repository/lib.php");
$defaults = [
'mainfile' => '', 'subdirs' => 0, 'maxbytes' => -1, 'maxfiles' => 10,
'accepted_types' => '*', 'return_types' => FILE_INTERNAL, 'areamaxbytes' => FILE_AREA_MAX_BYTES_UNLIMITED,
'context' => context_system::instance()];
foreach ($this->options as $k => $v) {
$defaults[$k] = $v;
}

return $defaults;
}

/**
* Set the owner.
*
* @param object The owner.
*/
public function set_owner($owner) {
$this->owner = $owner;
}

/**
* Return part of form with setting
* This function should always be overwritten
*
* @param mixed $data array or string depending on setting
* @param string $query
* @return string
*/
public function output_html($data, $query = '') {
if ((!is_null($this->owner)) && (method_exists($this->owner, 'get_disabled'))) {
if ($this->owner->get_disabled()) {
global $OUTPUT;

$this->write_setting('');

$context = new \stdClass();
$context->title = $this->visiblename;
$context->description = $this->description;

return $OUTPUT->render_from_template('core_admin/setting_description', $context);
}
}
return parent::output_html($data, $query);
}

/**
* Store new setting values.
*
* @param mixed $data string or array, must not be NULL.
* @return string empty string if ok, string error message otherwise.
*/
public function write_setting($data) {
global $USER;

// Let's not deal with validation here, this is for admins only.
$current = $this->get_setting();
if (empty($data) && ($current === null || $current === '')) {
// This will be the case when applying default settings (installation).
return ($this->config_write($this->name, '') ? '' : get_string('errorsetting', 'admin'));
} else if (!is_number($data)) {
// Draft item id is expected here!
return get_string('errorsetting', 'admin');
}

$options = $this->get_options();
$fs = get_file_storage();
$component = is_null($this->plugin) ? 'core' : $this->plugin;

$this->oldhashes = [];
if ($current) {
$files = $fs->get_area_files(
$options['context']->id,
$component,
$this->filearea,
$this->itemid,
'sortorder,filepath,filename',
false
);
foreach ($files as $file) {
$filepath = $file->get_filepath() . $file->get_filename();
$this->oldhashes[$filepath] = $file->get_contenthash() . $file->get_pathnamehash();
}
unset($files);
}

if ($fs->file_exists($options['context']->id, $component, $this->filearea, $this->itemid, '/', '.')) {
// Make sure the settings form was not open for more than 4 days and draft areas deleted in the meantime.
// But we can safely ignore that if the destination area is empty, so that the user is not prompt
// with an error because the draft area does not exist, as he did not use it.
$usercontext = \context_user::instance($USER->id);
if (!$fs->file_exists($usercontext->id, 'user', 'draft', $data, '/', '.') && $current !== '') {
return get_string('errorsetting', 'admin');
}
}

file_save_draft_area_files($data, $options['context']->id, $component, $this->filearea, $this->itemid, $options);
$files = $fs->get_area_files(
$options['context']->id,
$component,
$this->filearea,
$this->itemid,
'sortorder,filepath,filename',
false
);

$filepath = '';
if ($files) {
/** @var stored_file $file */
$file = reset($files);
$filepath = $file->get_filepath() . $file->get_filename();
}

return ($this->config_write($this->name, $filepath) ? '' : get_string('errorsetting', 'admin'));
}

/**
* Execute postupdatecallback if necessary.
* @param mixed $original original value before write_setting().
* @return bool true if changed, false if not.
*/
public function post_write_settings($original) {
$options = $this->get_options();
$fs = get_file_storage();
$component = is_null($this->plugin) ? 'core' : $this->plugin;

$current = $this->get_setting();
$newhashes = [];
if ($current) {
$files = $fs->get_area_files(
$options['context']->id,
$component,
$this->filearea,
$this->itemid,
'sortorder,filepath,filename',
false
);
foreach ($files as $file) {
$filepath = $file->get_filepath() . $file->get_filename();
$newhashes[$filepath] = $file->get_contenthash() . $file->get_pathnamehash();
;
}
unset($files);
}

$callcallback = false;
if (count($this->oldhashes) != count($newhashes)) {
// Definitely changed!
$callcallback = true;
} else {
// Same number of files.
foreach ($this->oldhashes as $oldhashkey => $oldhash) {
if (array_key_exists($oldhashkey, $newhashes)) {
if ($newhashes[$oldhashkey] !== $oldhash) {
$callcallback = true;
break;
}
} else {
// Different collection of files.
$callcallback = true;
break;
}
}
}
$this->oldhashes = [];
if (!$callcallback) {
return false;
}

$callbackfunction = $this->updatedcallback;
if (!empty($callbackfunction) && function_exists($callbackfunction)) {
$callbackfunction($this->get_full_name());
}
return true;
}

// Adapted from theme_config class.
/**
* Returns URL to the stored file via pluginfile.php.
*
* Note the theme must also implement pluginfile.php handler,
* theme revision is used instead of the itemid.
*
* @param string $setting
* @param string $filearea
* @param theme_config $theme
* @return array protocol relative URLs or empty if not present.
*/
public static function setting_file_urls($setting, $filearea, $theme) {
global $CFG;

if (empty($theme->settings->$setting)) {
return null;
}

$component = 'theme_' . $theme->name;
$itemid = theme_get_revision();
$syscontext = context_system::instance();
$urls = [];

$fs = get_file_storage();
$files = $fs->get_area_files(
$syscontext->id,
$component,
$filearea,
0,
'sortorder,filepath,filename',
false
); // Item id could not be 0!
foreach ($files as $file) {
$filepath = $file->get_filepath() . $file->get_filename();
$url = \moodle_url::make_file_url(
"$CFG->wwwroot/pluginfile.php",
"/$syscontext->id/$component/$filearea/$itemid" . $filepath
);
// Now this is tricky because the we can not hardcode http or https here, lets use the relative link.
// Note: unfortunately moodle_url does not support //urls yet.
$url = preg_replace('|^https?://|i', '//', $url->out(false));
$urls[] = $url;
}

return $urls;
}
}
1 change: 1 addition & 0 deletions classes/admin_setting_markdown.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

/**
* Adaptable theme.
*
* @package theme_adaptable
* @copyright 2021 G J Barnard
* {@link https://moodle.org/user/profile.php?id=442195}
Expand Down
Loading

0 comments on commit c37045b

Please sign in to comment.