MDL-49870 tool_templatelibrary: Allow docs in parent template only.
If the mustache comment containing the docs for the template is not found in the theme overridden template, search the original core/plugin template for the docs.
This commit is contained in:
+1
-1
@@ -1 +1 @@
|
||||
define(["jquery","core/ajax","core/log","core/notification","core/templates","core/config","core/str"],function(a,b,c,d,e,f,g){var h=function(b,f){g.get_string("templateselected","tool_templatelibrary",b).done(function(b){a('[data-region="displaytemplateheader"]').text(b)}).fail(d.exception);var h="@template "+b,i=f.match(/{{!([\s\S]*?)}}/g),j=0;if(null!==i)for(j=0;j<i.length;j++){var k=i[j],l=k.indexOf(h);if(-1!==l){var m=l+h.length+1;k=k.substr(m,k.length-2-m),f=k;break}}a('[data-region="displaytemplatesource"]').text(f);var n=f.match(/Example context \(json\):([\s\S]*)/),o=!1;if(n){var p=n[1].trim();try{o=a.parseJSON(p)}catch(q){c.debug("Could not parse json example context for template."),c.debug(q)}}o?e.render(b,o).done(function(b,c){a('[data-region="displaytemplateexample"]').empty(),a('[data-region="displaytemplateexample"]').append(b),e.runTemplateJS(c)}).fail(d.exception):g.get_string("templatehasnoexample","tool_templatelibrary").done(function(b){a('[data-region="displaytemplateexample"]').text(b)}).fail(d.exception)},i=function(a){var c=a.split("/"),e=c.shift(),g=c.shift();b.call([{methodname:"core_output_load_template",args:{component:e,template:g,themename:f.theme},done:function(b){h(a,b)},fail:d.exception}])};return a('[data-region="list-templates"]').on("click","[data-templatename]",function(){var b=a(this).data("templatename");i(b)}),{}});
|
||||
define(["jquery","core/ajax","core/log","core/notification","core/templates","core/config","core/str"],function(a,b,c,d,e,f,g){var h=function(a,b){var c="@template "+b,d=0,e=[];if(e=a.match(/{{!([\s\S]*?)}}/g),null!==e)for(d=0;d<e.length;d++){var f=e[d],g=f.indexOf(c);if(-1!==g){var h=g+c.length+1;return f=f.substr(h,f.length-2-h)}}return!1},i=function(b,f,i){g.get_string("templateselected","tool_templatelibrary",b).done(function(b){a('[data-region="displaytemplateheader"]').text(b)}).fail(d.exception);var j=h(f,b);j===!1&&(j=h(i,b)),j&&(f=j),a('[data-region="displaytemplatesource"]').text(f);var k=f.match(/Example context \(json\):([\s\S]*)/),l=!1;if(k){var m=k[1].trim();try{l=a.parseJSON(m)}catch(n){c.debug("Could not parse json example context for template."),c.debug(n)}}l?e.render(b,l).done(function(b,c){a('[data-region="displaytemplateexample"]').empty(),a('[data-region="displaytemplateexample"]').append(b),e.runTemplateJS(c)}).fail(d.exception):g.get_string("templatehasnoexample","tool_templatelibrary").done(function(b){a('[data-region="displaytemplateexample"]').text(b)}).fail(d.exception)},j=function(c){var e=c.split("/"),g=e.shift(),h=e.shift(),j=b.call([{methodname:"core_output_load_template",args:{component:g,template:h,themename:f.theme}},{methodname:"tool_templatelibrary_load_canonical_template",args:{component:g,template:h}}]);a.when.apply(a,j).done(function(a,b){i(c,a,b)}).fail(d.exception)};return a('[data-region="list-templates"]').on("click","[data-templatename]",function(){var b=a(this).data("templatename");j(b)}),{}});
|
||||
@@ -25,21 +25,20 @@ define(['jquery', 'core/ajax', 'core/log', 'core/notification', 'core/templates'
|
||||
function($, ajax, log, notification, templates, config, str) {
|
||||
|
||||
/**
|
||||
* Handle a template loaded response.
|
||||
* Search through a template for a template docs comment.
|
||||
*
|
||||
* @param {String} templateName The template name
|
||||
* @param {String} source The template source
|
||||
* @param {String} templateSource The raw template
|
||||
* @param {String} templateName The name of the template used to search for docs tag
|
||||
* @return {String|boolean} the correct comment or false
|
||||
*/
|
||||
var templateLoaded = function(templateName, source) {
|
||||
str.get_string('templateselected', 'tool_templatelibrary', templateName).done(function(s) {
|
||||
$('[data-region="displaytemplateheader"]').text(s);
|
||||
}).fail(notification.exception);
|
||||
var findDocsSection = function(templateSource, templateName) {
|
||||
|
||||
// Find the comment section marked with @template component/template.
|
||||
var marker = "@template " + templateName;
|
||||
var marker = "@template " + templateName,
|
||||
i = 0,
|
||||
sections = [];
|
||||
|
||||
var sections = source.match(/{{!([\s\S]*?)}}/g);
|
||||
var i = 0;
|
||||
sections = templateSource.match(/{{!([\s\S]*?)}}/g);
|
||||
|
||||
// If no sections match - show the entire file.
|
||||
if (sections !== null) {
|
||||
@@ -50,11 +49,38 @@ define(['jquery', 'core/ajax', 'core/log', 'core/notification', 'core/templates'
|
||||
// Remove {{! and }} from start and end.
|
||||
var offset = start + marker.length + 1;
|
||||
section = section.substr(offset, section.length - 2 - offset);
|
||||
source = section;
|
||||
break;
|
||||
return section;
|
||||
}
|
||||
}
|
||||
}
|
||||
// No matching comment.
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle a template loaded response.
|
||||
*
|
||||
* @param {String} templateName The template name
|
||||
* @param {String} source The template source
|
||||
* @param {String} originalSource The original template source (not theme overridden)
|
||||
*/
|
||||
var templateLoaded = function(templateName, source, originalSource) {
|
||||
str.get_string('templateselected', 'tool_templatelibrary', templateName).done(function(s) {
|
||||
$('[data-region="displaytemplateheader"]').text(s);
|
||||
}).fail(notification.exception);
|
||||
|
||||
// Find the comment section marked with @template component/template.
|
||||
var docs = findDocsSection(source, templateName);
|
||||
|
||||
if (docs === false) {
|
||||
// Docs was not in theme template, try original.
|
||||
docs = findDocsSection(originalSource, templateName);
|
||||
}
|
||||
|
||||
// If we found a docs section, limit the template library to showing this section.
|
||||
if (docs) {
|
||||
source = docs;
|
||||
}
|
||||
|
||||
$('[data-region="displaytemplatesource"]').text(source);
|
||||
|
||||
@@ -86,6 +112,7 @@ define(['jquery', 'core/ajax', 'core/log', 'core/notification', 'core/templates'
|
||||
|
||||
/**
|
||||
* Load the a template source from Moodle.
|
||||
*
|
||||
* @param {String} templateName
|
||||
*/
|
||||
var loadTemplate = function(templateName) {
|
||||
@@ -93,16 +120,26 @@ define(['jquery', 'core/ajax', 'core/log', 'core/notification', 'core/templates'
|
||||
var component = parts.shift();
|
||||
var name = parts.shift();
|
||||
|
||||
ajax.call([{
|
||||
var promises = ajax.call([{
|
||||
methodname: 'core_output_load_template',
|
||||
args:{
|
||||
component: component,
|
||||
template: name,
|
||||
themename: config.theme
|
||||
},
|
||||
done: function(source) { templateLoaded(templateName, source); },
|
||||
fail: notification.exception
|
||||
}
|
||||
}, {
|
||||
methodname: 'tool_templatelibrary_load_canonical_template',
|
||||
args:{
|
||||
component: component,
|
||||
template: name
|
||||
}
|
||||
}]);
|
||||
|
||||
// When returns a new promise that is resolved when all the passed in promises are resolved.
|
||||
// The arguments to the done become the values of each resolved promise.
|
||||
$.when.apply($, promises)
|
||||
.done( function(source, originalSource) { templateLoaded(templateName, source, originalSource); })
|
||||
.fail(notification.exception);
|
||||
};
|
||||
|
||||
// Add the event listeners.
|
||||
|
||||
@@ -23,11 +23,12 @@
|
||||
*/
|
||||
namespace tool_templatelibrary;
|
||||
|
||||
use core\output\mustache_template_finder;
|
||||
use stdClass;
|
||||
use core_component;
|
||||
use core\output\mustache_template_finder;
|
||||
use coding_exception;
|
||||
use moodle_exception;
|
||||
use required_capability_exception;
|
||||
use stdClass;
|
||||
|
||||
/**
|
||||
* API exposed by tool_templatelibrary
|
||||
@@ -103,4 +104,37 @@ class api {
|
||||
return $results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a mustache template.
|
||||
* Note - this function differs from the function core_output_load_template
|
||||
* because it will never return a theme overridden version of a template.
|
||||
*
|
||||
* @param string $component The component that holds the template.
|
||||
* @param string $template The name of the template.
|
||||
* @return string the template
|
||||
*/
|
||||
public static function load_canonical_template($component, $template) {
|
||||
// Get the list of possible template directories.
|
||||
$dirs = mustache_template_finder::get_template_directories_for_component($component);
|
||||
$filename = false;
|
||||
|
||||
foreach ($dirs as $dir) {
|
||||
// Skip theme dirs - we only want the original plugin/core template.
|
||||
if (strpos($dir, "/theme/") === false) {
|
||||
$candidate = $dir . $template . '.mustache';
|
||||
if (file_exists($candidate)) {
|
||||
$filename = $candidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($filename === false) {
|
||||
throw new moodle_exception('filenotfound', 'error');
|
||||
}
|
||||
|
||||
$templatestr = file_get_contents($filename);
|
||||
return $templatestr;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -95,4 +95,55 @@ class external extends external_api {
|
||||
public static function list_templates_returns() {
|
||||
return new external_multiple_structure(new external_value(PARAM_RAW, 'The template name (format is component/templatename)'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of load_canonical_template() parameters.
|
||||
*
|
||||
* @return external_function_parameters
|
||||
*/
|
||||
public static function load_canonical_template_parameters() {
|
||||
return new external_function_parameters(
|
||||
array('component' => new external_value(PARAM_COMPONENT, 'component containing the template'),
|
||||
'template' => new external_value(PARAM_ALPHANUMEXT, 'name of the template'))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Can this function be called directly from ajax?
|
||||
*
|
||||
* @return boolean
|
||||
* @since Moodle 2.9
|
||||
*/
|
||||
public static function load_canonical_template_is_allowed_from_ajax() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a mustache template.
|
||||
* Note - this function differs from the function core_output_load_template
|
||||
* because it will never return a theme overridden version of a template.
|
||||
*
|
||||
* @param string $component The component that holds the template.
|
||||
* @param string $template The name of the template.
|
||||
* @return string the template
|
||||
*/
|
||||
public static function load_canonical_template($component, $template) {
|
||||
$params = self::validate_parameters(self::load_canonical_template_parameters(),
|
||||
array('component' => $component,
|
||||
'template' => $template));
|
||||
|
||||
$component = $params['component'];
|
||||
$template = $params['template'];
|
||||
|
||||
return api::load_canonical_template($component, $template);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns description of load_canonical_template() result value.
|
||||
*
|
||||
* @return external_description
|
||||
*/
|
||||
public static function load_canonical_template_returns() {
|
||||
return new external_value(PARAM_RAW, 'template');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,5 +33,12 @@ $functions = array(
|
||||
'type' => 'read',
|
||||
'capabilities'=> '',
|
||||
),
|
||||
'tool_templatelibrary_load_canonical_template' => array(
|
||||
'classname' => 'tool_templatelibrary\external',
|
||||
'methodname' => 'load_canonical_template',
|
||||
'description' => 'Load a canonical template by name (not the theme overidden one).',
|
||||
'type' => 'read'
|
||||
),
|
||||
|
||||
);
|
||||
|
||||
|
||||
@@ -65,5 +65,19 @@ class tool_templatelibrary_external_testcase extends externallib_advanced_testca
|
||||
$this->assertEquals($result[0], "tool_templatelibrary/list_templates_page");
|
||||
}
|
||||
|
||||
public function test_load_canonical_template() {
|
||||
global $CFG;
|
||||
|
||||
$originaltheme = $CFG->theme;
|
||||
// Change the theme to 'base' because it overrides these templates.
|
||||
$CFG->theme = 'base';
|
||||
|
||||
$template = external::load_canonical_template('core', 'notification_problem');
|
||||
|
||||
// Only the base template should contain the docs.
|
||||
$this->assertContains('@template core/notification_problem', $template);
|
||||
|
||||
// Restore the original theme.
|
||||
$CFG->theme = $originaltheme;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,6 @@
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
$plugin->version = 2015021623; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->version = 2015050401; // The current plugin version (Date: YYYYMMDDXX).
|
||||
$plugin->requires = 2014110400; // Requires this Moodle version.
|
||||
$plugin->component = 'tool_templatelibrary'; // Full name of the plugin (used for diagnostics).
|
||||
|
||||
@@ -14,18 +14,4 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
}}
|
||||
{{!
|
||||
Moodle notification template.
|
||||
|
||||
The purpose of this template is to render a message notification.
|
||||
|
||||
Classes required for JS:
|
||||
* none
|
||||
|
||||
Data attributes required for JS:
|
||||
* none
|
||||
|
||||
Context variables required for this template:
|
||||
* message A cleaned string (use clean_text()) to display.
|
||||
}}
|
||||
<div class="notifymessage">{{{message}}}</div>
|
||||
<div class="notifymessage">{{{message}}}</div>
|
||||
|
||||
@@ -14,18 +14,4 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
}}
|
||||
{{!
|
||||
Moodle notification template.
|
||||
|
||||
The purpose of this template is to render a problem notification.
|
||||
|
||||
Classes required for JS:
|
||||
* none
|
||||
|
||||
Data attributes required for JS:
|
||||
* none
|
||||
|
||||
Context variables required for this template:
|
||||
* message A cleaned string (use clean_text()) to display.
|
||||
}}
|
||||
<div class="notifyproblem">{{{message}}}</div>
|
||||
<div class="notifyproblem">{{{message}}}</div>
|
||||
|
||||
@@ -14,18 +14,4 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
}}
|
||||
{{!
|
||||
Moodle notification template.
|
||||
|
||||
The purpose of this template is to render a message notification.
|
||||
|
||||
Classes required for JS:
|
||||
* none
|
||||
|
||||
Data attributes required for JS:
|
||||
* none
|
||||
|
||||
Context variables required for this template:
|
||||
* message A cleaned string (use clean_text()) to display.
|
||||
}}
|
||||
<div class="redirectmessage">{{{message}}}</div>
|
||||
<div class="redirectmessage">{{{message}}}</div>
|
||||
|
||||
@@ -14,18 +14,4 @@
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
}}
|
||||
{{!
|
||||
Moodle notification template.
|
||||
|
||||
The purpose of this template is to render a success notification.
|
||||
|
||||
Classes required for JS:
|
||||
* none
|
||||
|
||||
Data attributes required for JS:
|
||||
* none
|
||||
|
||||
Context variables required for this template:
|
||||
* message A cleaned string (use clean_text()) to display.
|
||||
}}
|
||||
<div class="notifysuccess">{{{message}}}</div>
|
||||
<div class="notifysuccess">{{{message}}}</div>
|
||||
|
||||
Reference in New Issue
Block a user