This commit is contained in:
Dan Poltawski 2016-08-23 08:59:24 +01:00
commit 3f92140fc8
14 changed files with 128 additions and 35 deletions

View File

@ -764,6 +764,17 @@ class behat_base extends Behat\MinkExtension\Context\RawMinkContext {
// Joined xpath expression. Most of the time there will be no exceptions, so this pre-check
// is faster than to send the 4 xpath queries for each step.
if (!$this->getSession()->getDriver()->find($joinedxpath)) {
// Check if we have recorded any errors in driver process.
$phperrors = behat_get_shutdown_process_errors();
if (!empty($phperrors)) {
foreach ($phperrors as $error) {
$errnostring = behat_get_error_string($error['type']);
$msgs[] = $errnostring . ": " .$error['message'] . " at " . $error['file'] . ": " . $error['line'];
}
$msg = "PHP errors found:\n" . implode("\n", $msgs);
throw new \Exception(htmlentities($msg));
}
return;
}
@ -776,8 +787,20 @@ class behat_base extends Behat\MinkExtension\Context\RawMinkContext {
if (empty($errorinfoboxes)) {
$errorinfoboxes = $this->getSession()->getPage()->findAll('css', 'div.notifytiny');
}
$errorinfo = $this->get_debug_text($errorinfoboxes[0]->getHtml()) . "\n" .
$this->get_debug_text($errorinfoboxes[1]->getHtml());
// If errorinfoboxes is empty, try find ajax/JS exception in dialogue.
if (empty($errorinfoboxes)) {
$errorinfoboxes = $this->getSession()->getPage()->findAll('css', 'div.moodle-exception-message');
// If ajax/JS exception.
if ($errorinfoboxes) {
$errorinfo = $this->get_debug_text($errorinfoboxes[0]->getHtml());
}
} else {
$errorinfo = $this->get_debug_text($errorinfoboxes[0]->getHtml()) . "\n" .
$this->get_debug_text($errorinfoboxes[1]->getHtml());
}
$msg = "Moodle exception: " . $errormsg->getText() . "\n" . $errorinfo;
throw new \Exception(html_entity_decode($msg));

View File

@ -84,6 +84,36 @@ function behat_error($errorcode, $text = '') {
testing_error($errorcode, $text);
}
/**
* Return logical error string.
*
* @param int $errtype php error type.
* @return string string which will be returned.
*/
function behat_get_error_string($errtype) {
switch ($errtype) {
case E_USER_ERROR:
$errnostr = 'Fatal error';
break;
case E_WARNING:
case E_USER_WARNING:
$errnostr = 'Warning';
break;
case E_NOTICE:
case E_USER_NOTICE:
case E_STRICT:
$errnostr = 'Notice';
break;
case E_RECOVERABLE_ERROR:
$errnostr = 'Catchable';
break;
default:
$errnostr = 'Unknown error type';
}
return $errnostr;
}
/**
* PHP errors handler to use when running behat tests.
*
@ -121,35 +151,57 @@ function behat_error_handler($errno, $errstr, $errfile, $errline, $errcontext) {
// Using the default one in case there is a fatal catchable error.
default_error_handler($errno, $errstr, $errfile, $errline, $errcontext);
switch ($errno) {
case E_USER_ERROR:
$errnostr = 'Fatal error';
break;
case E_WARNING:
case E_USER_WARNING:
$errnostr = 'Warning';
break;
case E_NOTICE:
case E_USER_NOTICE:
case E_STRICT:
$errnostr = 'Notice';
break;
case E_RECOVERABLE_ERROR:
$errnostr = 'Catchable';
break;
default:
$errnostr = 'Unknown error type';
}
$errnostr = behat_get_error_string($errno);
// Wrapping the output.
echo '<div class="phpdebugmessage" data-rel="phpdebugmessage">' . PHP_EOL;
echo "$errnostr: $errstr in $errfile on line $errline" . PHP_EOL;
echo '</div>';
// If ajax script then throw exception, so the calling api catch it and show it on web page.
if (defined('AJAX_SCRIPT')) {
throw new Exception("$errnostr: $errstr in $errfile on line $errline");
} else {
// Wrapping the output.
echo '<div class="phpdebugmessage" data-rel="phpdebugmessage">' . PHP_EOL;
echo "$errnostr: $errstr in $errfile on line $errline" . PHP_EOL;
echo '</div>';
}
// Also use the internal error handler so we keep the usual behaviour.
return false;
}
/**
* Before shutdown save last error entries, so we can fail the test.
*/
function behat_shutdown_function() {
global $DB;
// If any error found, then save it.
if ($error = error_get_last()) {
// Ignore E_WARNING, as they might come via ( @ )suppression and might lead to false failure.
if (isset($error['type']) && !($error['type'] & E_WARNING)) {
$errors = behat_get_shutdown_process_errors();
$errors[] = $error;
$errorstosave = json_encode($errors);
set_config('process_errors', $errorstosave, 'tool_behat');
}
}
}
/**
* Return php errors save which were save during shutdown.
*
* @return array
*/
function behat_get_shutdown_process_errors() {
$phperrors = get_config('tool_behat', 'process_errors');
if (!empty($phperrors)) {
return json_decode($phperrors, true);
} else {
return array();
}
}
/**
* Restrict the config.php settings allowed.
*

View File

@ -1038,6 +1038,12 @@ if (isset($CFG->maintenance_later) and $CFG->maintenance_later <= time()) {
}
}
// Add behat_shutdown_function to shutdown manager, so we can capture php errors,
// but not necessary for behat CLI command as it's being captured by behat process.
if (defined('BEHAT_SITE_RUNNING') && !defined('BEHAT_TEST')) {
core_shutdown_manager::register_function('behat_shutdown_function');
}
// note: we can not block non utf-8 installations here, because empty mysql database
// might be converted to utf-8 in admin/index.php during installation

View File

@ -939,12 +939,23 @@ abstract class testing_util {
self::$tableupdated = array();
}
/**
* Delete tablesupdatedbyscenario file. This should be called before suite,
* to ensure full db reset.
*/
public static function clean_tables_updated_by_scenario_list() {
$tablesupdatedfile = self::get_tables_updated_by_scenario_list_path();
if (file_exists($tablesupdatedfile)) {
unlink($tablesupdatedfile);
}
}
/**
* Returns the path to the file which holds list of tables updated in scenario.
* @return string
*/
protected final static function get_tables_updated_by_scenario_list_path() {
return self::get_dataroot() . '/tablesupdatedbyscenario.txt';
return self::get_dataroot() . '/tablesupdatedbyscenario.json';
}
/**

View File

@ -153,6 +153,7 @@ class behat_hooks extends behat_base {
// Reset all data, before checking for check_server_status.
// If not done, then it can return apache error, while running tests.
behat_util::clean_tables_updated_by_scenario_list();
behat_util::reset_all_data();
// Check if server is running and using same version for cli and apache.

View File

@ -64,7 +64,7 @@ Y.extend(AJAXEXCEPTION, M.core.notification.info, {
this.setStdModContent(Y.WidgetStdMod.HEADER,
'<h1 id="moodle-dialogue-' + this.get('COUNT') + '-header-text">' + Y.Escape.html(config.name) + '</h1>',
Y.WidgetStdMod.REPLACE);
content = Y.Node.create('<div class="moodle-ajaxexception"></div>')
content = Y.Node.create('<div class="moodle-ajaxexception" data-rel="fatalerror"></div>')
.append(Y.Node.create('<div class="moodle-exception-message">' + Y.Escape.html(this.get('error')) + '</div>'))
.append(Y.Node.create('<div class="moodle-exception-param hidden param-debuginfo"><label>URL:</label> ' +
this.get('reproductionlink') + '</div>'))

View File

@ -1 +1 @@
YUI.add("moodle-core-notification-ajaxexception",function(e,t){var n,r,i,s,o,u,a;n="moodle-dialogue",r="notificationBase",i="yesLabel",s="noLabel",o="title",u="question",a={BASE:"moodle-dialogue-base",WRAP:"moodle-dialogue-wrap",HEADER:"moodle-dialogue-hd",BODY:"moodle-dialogue-bd",CONTENT:"moodle-dialogue-content",FOOTER:"moodle-dialogue-ft",HIDDEN:"hidden",LIGHTBOX:"moodle-dialogue-lightbox"},M.core=M.core||{};var f="Moodle AJAX exception",l;l=function(e){e.name=e.name||"Error",e.closeButton=!0,l.superclass.constructor.apply(this,[e])},e.extend(l,M.core.notification.info,{_keypress:null,initializer:function(t){var n,i=this,s=this.get("hideTimeoutDelay");this.get(r).addClass("moodle-dialogue-exception"),this.setStdModContent(e.WidgetStdMod.HEADER,'<h1 id="moodle-dialogue-'+this.get("COUNT")+'-header-text">'+e.Escape.html(t.name)+"</h1>",e.WidgetStdMod.REPLACE),n=e.Node.create('<div class="moodle-ajaxexception"></div>').append(e.Node.create('<div class="moodle-exception-message">'+e.Escape.html(this.get("error"))+"</div>")).append(e.Node.create('<div class="moodle-exception-param hidden param-debuginfo"><label>URL:</label> '+this.get("reproductionlink")+"</div>")).append(e.Node.create('<div class="moodle-exception-param hidden param-debuginfo"><label>Debug info:</label> '+e.Escape.html(this.get("debuginfo"))+"</div>")).append(e.Node.create('<div class="moodle-exception-param hidden param-stacktrace"><label>Stack trace:</label> <pre>'+e.Escape.html(this.get("stacktrace"))+"</pre></div>")),M.cfg.developerdebug&&n.all(".moodle-exception-param").removeClass("hidden"),this.setStdModContent(e.WidgetStdMod.BODY,n,e.WidgetStdMod.REPLACE),s&&(this._hideTimeout=setTimeout(function(){i.hide()},s)),this.after("visibleChange",this.visibilityChanged,this),this._keypress=e.on("key",this.hide,window,"down:13, 27",this),this.centerDialogue()},visibilityChanged:function(e){if(e.attrName==="visible"&&e.prevVal&&!e.newVal){var t=this;this._keypress.detach(),setTimeout(function(){t.destroy()},1e3)}}},{NAME:f,CSS_PREFIX:n,ATTRS:{error:{validator:e.Lang.isString,value:M.util.get_string("unknownerror","moodle")},debuginfo:{value:null},stacktrace:{value:null},reproductionlink:{setter:function(t){return t!==null&&(t=e.Escape.html(t),t='<a href="'+t+'">'+t.replace(M.cfg.wwwroot,"")+"</a>"),t},value:null},hideTimeoutDelay:{validator:e.Lang.isNumber,value:null}}}),M.core.ajaxException=l},"@VERSION@",{requires:["moodle-core-notification-dialogue"]});
YUI.add("moodle-core-notification-ajaxexception",function(e,t){var n,r,i,s,o,u,a;n="moodle-dialogue",r="notificationBase",i="yesLabel",s="noLabel",o="title",u="question",a={BASE:"moodle-dialogue-base",WRAP:"moodle-dialogue-wrap",HEADER:"moodle-dialogue-hd",BODY:"moodle-dialogue-bd",CONTENT:"moodle-dialogue-content",FOOTER:"moodle-dialogue-ft",HIDDEN:"hidden",LIGHTBOX:"moodle-dialogue-lightbox"},M.core=M.core||{};var f="Moodle AJAX exception",l;l=function(e){e.name=e.name||"Error",e.closeButton=!0,l.superclass.constructor.apply(this,[e])},e.extend(l,M.core.notification.info,{_keypress:null,initializer:function(t){var n,i=this,s=this.get("hideTimeoutDelay");this.get(r).addClass("moodle-dialogue-exception"),this.setStdModContent(e.WidgetStdMod.HEADER,'<h1 id="moodle-dialogue-'+this.get("COUNT")+'-header-text">'+e.Escape.html(t.name)+"</h1>",e.WidgetStdMod.REPLACE),n=e.Node.create('<div class="moodle-ajaxexception" data-rel="fatalerror"></div>').append(e.Node.create('<div class="moodle-exception-message">'+e.Escape.html(this.get("error"))+"</div>")).append(e.Node.create('<div class="moodle-exception-param hidden param-debuginfo"><label>URL:</label> '+this.get("reproductionlink")+"</div>")).append(e.Node.create('<div class="moodle-exception-param hidden param-debuginfo"><label>Debug info:</label> '+e.Escape.html(this.get("debuginfo"))+"</div>")).append(e.Node.create('<div class="moodle-exception-param hidden param-stacktrace"><label>Stack trace:</label> <pre>'+e.Escape.html(this.get("stacktrace"))+"</pre></div>")),M.cfg.developerdebug&&n.all(".moodle-exception-param").removeClass("hidden"),this.setStdModContent(e.WidgetStdMod.BODY,n,e.WidgetStdMod.REPLACE),s&&(this._hideTimeout=setTimeout(function(){i.hide()},s)),this.after("visibleChange",this.visibilityChanged,this),this._keypress=e.on("key",this.hide,window,"down:13, 27",this),this.centerDialogue()},visibilityChanged:function(e){if(e.attrName==="visible"&&e.prevVal&&!e.newVal){var t=this;this._keypress.detach(),setTimeout(function(){t.destroy()},1e3)}}},{NAME:f,CSS_PREFIX:n,ATTRS:{error:{validator:e.Lang.isString,value:M.util.get_string("unknownerror","moodle")},debuginfo:{value:null},stacktrace:{value:null},reproductionlink:{setter:function(t){return t!==null&&(t=e.Escape.html(t),t='<a href="'+t+'">'+t.replace(M.cfg.wwwroot,"")+"</a>"),t},value:null},hideTimeoutDelay:{validator:e.Lang.isNumber,value:null}}}),M.core.ajaxException=l},"@VERSION@",{requires:["moodle-core-notification-dialogue"]});

View File

@ -64,7 +64,7 @@ Y.extend(AJAXEXCEPTION, M.core.notification.info, {
this.setStdModContent(Y.WidgetStdMod.HEADER,
'<h1 id="moodle-dialogue-' + this.get('COUNT') + '-header-text">' + Y.Escape.html(config.name) + '</h1>',
Y.WidgetStdMod.REPLACE);
content = Y.Node.create('<div class="moodle-ajaxexception"></div>')
content = Y.Node.create('<div class="moodle-ajaxexception" data-rel="fatalerror"></div>')
.append(Y.Node.create('<div class="moodle-exception-message">' + Y.Escape.html(this.get('error')) + '</div>'))
.append(Y.Node.create('<div class="moodle-exception-param hidden param-debuginfo"><label>URL:</label> ' +
this.get('reproductionlink') + '</div>'))

View File

@ -80,7 +80,7 @@ Y.extend(EXCEPTION, M.core.notification.info, {
this.setStdModContent(Y.WidgetStdMod.HEADER,
'<h1 id="moodle-dialogue-' + config.COUNT + '-header-text">' + Y.Escape.html(config.name) + '</h1>',
Y.WidgetStdMod.REPLACE);
content = Y.Node.create('<div class="moodle-exception"></div>')
content = Y.Node.create('<div class="moodle-exception" data-rel="fatalerror"></div>')
.append(Y.Node.create('<div class="moodle-exception-message">' + Y.Escape.html(this.get('message')) + '</div>'))
.append(Y.Node.create('<div class="moodle-exception-param hidden param-filename"><label>File:</label> ' +
Y.Escape.html(this.get('fileName')) + '</div>'))

View File

@ -1 +1 @@
YUI.add("moodle-core-notification-exception",function(e,t){var n,r,i,s,o,u,a;n="moodle-dialogue",r="notificationBase",i="yesLabel",s="noLabel",o="title",u="question",a={BASE:"moodle-dialogue-base",WRAP:"moodle-dialogue-wrap",HEADER:"moodle-dialogue-hd",BODY:"moodle-dialogue-bd",CONTENT:"moodle-dialogue-content",FOOTER:"moodle-dialogue-ft",HIDDEN:"hidden",LIGHTBOX:"moodle-dialogue-lightbox"},M.core=M.core||{};var f="Moodle exception",l;l=function(t){var n=e.mix({},t);n.width=n.width||M.cfg.developerdebug?Math.floor(e.one(document.body).get("winWidth")/3)+"px":null,n.closeButton=!0;var r=["message","name","fileName","lineNumber","stack"];e.Array.each(r,function(e){n[e]=t[e]}),l.superclass.constructor.apply(this,[n])},e.extend(l,M.core.notification.info,{_hideTimeout:null,_keypress:null,initializer:function(t){var n,i=this,s=this.get("hideTimeoutDelay");this.get(r).addClass("moodle-dialogue-exception"),this.setStdModContent(e.WidgetStdMod.HEADER,'<h1 id="moodle-dialogue-'+t.COUNT+'-header-text">'+e.Escape.html(t.name)+"</h1>",e.WidgetStdMod.REPLACE),n=e.Node.create('<div class="moodle-exception"></div>').append(e.Node.create('<div class="moodle-exception-message">'+e.Escape.html(this.get("message"))+"</div>")).append(e.Node.create('<div class="moodle-exception-param hidden param-filename"><label>File:</label> '+e.Escape.html(this.get("fileName"))+"</div>")).append(e.Node.create('<div class="moodle-exception-param hidden param-linenumber"><label>Line:</label> '+e.Escape.html(this.get("lineNumber"))+"</div>")).append(e.Node.create('<div class="moodle-exception-param hidden param-stacktrace"><label>Stack trace:</label> <pre>'+this.get("stack")+"</pre></div>")),M.cfg.developerdebug&&n.all(".moodle-exception-param").removeClass("hidden"),this.setStdModContent(e.WidgetStdMod.BODY,n,e.WidgetStdMod.REPLACE),s&&(this._hideTimeout=setTimeout(function(){i.hide()},s)),this.after("visibleChange",this.visibilityChanged,this),this._keypress=e.on("key",this.hide,window,"down:13,27",this),this.centerDialogue()},visibilityChanged:function(e){if(e.attrName==="visible"&&e.prevVal&&!e.newVal){this._keypress&&this._keypress.detach();var t=this;setTimeout(function(){t.destroy()},1e3)}}},{NAME:f,CSS_PREFIX:n,ATTRS:{message:{value:""},name:{value:""},fileName:{value:""},lineNumber:{value:""},stack:{setter:function(t){var n=e.Escape.html(t).split("\n"),r=new RegExp("^(.+)@("+M.cfg.wwwroot+")?(.{0,75}).*:(\\d+)$"),i;for(i in n)n[i]=n[i].replace(r,"<div class='stacktrace-line'>ln: $4</div><div class='stacktrace-file'>$3</div><div class='stacktrace-call'>$1</div>");return n.join("")},value:""},hideTimeoutDelay:{validator:e.Lang.isNumber,value:null}}}),M.core.exception=l},"@VERSION@",{requires:["moodle-core-notification-dialogue"]});
YUI.add("moodle-core-notification-exception",function(e,t){var n,r,i,s,o,u,a;n="moodle-dialogue",r="notificationBase",i="yesLabel",s="noLabel",o="title",u="question",a={BASE:"moodle-dialogue-base",WRAP:"moodle-dialogue-wrap",HEADER:"moodle-dialogue-hd",BODY:"moodle-dialogue-bd",CONTENT:"moodle-dialogue-content",FOOTER:"moodle-dialogue-ft",HIDDEN:"hidden",LIGHTBOX:"moodle-dialogue-lightbox"},M.core=M.core||{};var f="Moodle exception",l;l=function(t){var n=e.mix({},t);n.width=n.width||M.cfg.developerdebug?Math.floor(e.one(document.body).get("winWidth")/3)+"px":null,n.closeButton=!0;var r=["message","name","fileName","lineNumber","stack"];e.Array.each(r,function(e){n[e]=t[e]}),l.superclass.constructor.apply(this,[n])},e.extend(l,M.core.notification.info,{_hideTimeout:null,_keypress:null,initializer:function(t){var n,i=this,s=this.get("hideTimeoutDelay");this.get(r).addClass("moodle-dialogue-exception"),this.setStdModContent(e.WidgetStdMod.HEADER,'<h1 id="moodle-dialogue-'+t.COUNT+'-header-text">'+e.Escape.html(t.name)+"</h1>",e.WidgetStdMod.REPLACE),n=e.Node.create('<div class="moodle-exception" data-rel="fatalerror"></div>').append(e.Node.create('<div class="moodle-exception-message">'+e.Escape.html(this.get("message"))+"</div>")).append(e.Node.create('<div class="moodle-exception-param hidden param-filename"><label>File:</label> '+e.Escape.html(this.get("fileName"))+"</div>")).append(e.Node.create('<div class="moodle-exception-param hidden param-linenumber"><label>Line:</label> '+e.Escape.html(this.get("lineNumber"))+"</div>")).append(e.Node.create('<div class="moodle-exception-param hidden param-stacktrace"><label>Stack trace:</label> <pre>'+this.get("stack")+"</pre></div>")),M.cfg.developerdebug&&n.all(".moodle-exception-param").removeClass("hidden"),this.setStdModContent(e.WidgetStdMod.BODY,n,e.WidgetStdMod.REPLACE),s&&(this._hideTimeout=setTimeout(function(){i.hide()},s)),this.after("visibleChange",this.visibilityChanged,this),this._keypress=e.on("key",this.hide,window,"down:13,27",this),this.centerDialogue()},visibilityChanged:function(e){if(e.attrName==="visible"&&e.prevVal&&!e.newVal){this._keypress&&this._keypress.detach();var t=this;setTimeout(function(){t.destroy()},1e3)}}},{NAME:f,CSS_PREFIX:n,ATTRS:{message:{value:""},name:{value:""},fileName:{value:""},lineNumber:{value:""},stack:{setter:function(t){var n=e.Escape.html(t).split("\n"),r=new RegExp("^(.+)@("+M.cfg.wwwroot+")?(.{0,75}).*:(\\d+)$"),i;for(i in n)n[i]=n[i].replace(r,"<div class='stacktrace-line'>ln: $4</div><div class='stacktrace-file'>$3</div><div class='stacktrace-call'>$1</div>");return n.join("")},value:""},hideTimeoutDelay:{validator:e.Lang.isNumber,value:null}}}),M.core.exception=l},"@VERSION@",{requires:["moodle-core-notification-dialogue"]});

View File

@ -80,7 +80,7 @@ Y.extend(EXCEPTION, M.core.notification.info, {
this.setStdModContent(Y.WidgetStdMod.HEADER,
'<h1 id="moodle-dialogue-' + config.COUNT + '-header-text">' + Y.Escape.html(config.name) + '</h1>',
Y.WidgetStdMod.REPLACE);
content = Y.Node.create('<div class="moodle-exception"></div>')
content = Y.Node.create('<div class="moodle-exception" data-rel="fatalerror"></div>')
.append(Y.Node.create('<div class="moodle-exception-message">' + Y.Escape.html(this.get('message')) + '</div>'))
.append(Y.Node.create('<div class="moodle-exception-param hidden param-filename"><label>File:</label> ' +
Y.Escape.html(this.get('fileName')) + '</div>'))

View File

@ -34,7 +34,7 @@ Y.extend(AJAXEXCEPTION, M.core.notification.info, {
this.setStdModContent(Y.WidgetStdMod.HEADER,
'<h1 id="moodle-dialogue-' + this.get('COUNT') + '-header-text">' + Y.Escape.html(config.name) + '</h1>',
Y.WidgetStdMod.REPLACE);
content = Y.Node.create('<div class="moodle-ajaxexception"></div>')
content = Y.Node.create('<div class="moodle-ajaxexception" data-rel="fatalerror"></div>')
.append(Y.Node.create('<div class="moodle-exception-message">' + Y.Escape.html(this.get('error')) + '</div>'))
.append(Y.Node.create('<div class="moodle-exception-param hidden param-debuginfo"><label>URL:</label> ' +
this.get('reproductionlink') + '</div>'))

View File

@ -50,7 +50,7 @@ Y.extend(EXCEPTION, M.core.notification.info, {
this.setStdModContent(Y.WidgetStdMod.HEADER,
'<h1 id="moodle-dialogue-' + config.COUNT + '-header-text">' + Y.Escape.html(config.name) + '</h1>',
Y.WidgetStdMod.REPLACE);
content = Y.Node.create('<div class="moodle-exception"></div>')
content = Y.Node.create('<div class="moodle-exception" data-rel="fatalerror"></div>')
.append(Y.Node.create('<div class="moodle-exception-message">' + Y.Escape.html(this.get('message')) + '</div>'))
.append(Y.Node.create('<div class="moodle-exception-param hidden param-filename"><label>File:</label> ' +
Y.Escape.html(this.get('fileName')) + '</div>'))

View File

@ -76,10 +76,10 @@ switch($requestmethod) {
switch ($class) {
case 'section':
$table = 'quiz_sections';
$section = $structure->get_section_by_id($id);
switch ($field) {
case 'getsectiontitle':
require_capability('mod/quiz:manage', $modcontext);
$section = $structure->get_section_by_id($id);
echo json_encode(array('instancesection' => $section->heading));
break;
case 'updatesectiontitle':