MDL-26405 restore - dispatch able to skip branches
after this change any restore_structure_step processor method is able to instruct the dispatcher about to skip any path below it. Until now, we were doing the checks on each child processor method, but that was inneficient and prone to errors (easy to miss the check in a child so some orphaned piezes of restore may be causing mess here and there). Once implemented, it's simlpy a matter of the parent deciding if all its children must be processed or no. Easier for developers and also small speed improvement because avoids unnecesary dispatching/processing to happen. Surely only will be used in parts of core, like in question_categories, saving 50-60 sub processors (sub-paths) to be dispatched.
This commit is contained in:
@@ -2219,7 +2219,7 @@ class restore_create_categories_and_questions extends restore_structure_step {
|
||||
|
||||
// Check we have one mapping for this category
|
||||
if (!$mapping = $this->get_mapping('question_category', $oldid)) {
|
||||
return; // No mapping = this category doesn't need to be created/mapped
|
||||
return self::SKIP_ALL_CHILDREN; // No mapping = this category doesn't need to be created/mapped
|
||||
}
|
||||
|
||||
// Check we have to create the category (newitemid = 0)
|
||||
|
||||
@@ -38,6 +38,11 @@ abstract class restore_structure_step extends restore_step {
|
||||
protected $elementsoldid; // Array to store last oldid used on each element
|
||||
protected $elementsnewid; // Array to store last newid used on each element
|
||||
|
||||
protected $pathlock; // Path currently locking processing of children
|
||||
|
||||
const SKIP_ALL_CHILDREN = -991399; // To instruct the dispatcher about to ignore
|
||||
// all children below path processor returning it
|
||||
|
||||
/**
|
||||
* Constructor - instantiates one object of this class
|
||||
*/
|
||||
@@ -50,10 +55,11 @@ abstract class restore_structure_step extends restore_step {
|
||||
$this->pathelements = array();
|
||||
$this->elementsoldid = array();
|
||||
$this->elementsnewid = array();
|
||||
$this->pathlock = null;
|
||||
parent::__construct($name, $task);
|
||||
}
|
||||
|
||||
public function execute() {
|
||||
final public function execute() {
|
||||
|
||||
if (!$this->execute_condition()) { // Check any condition to execute this
|
||||
return;
|
||||
@@ -106,18 +112,37 @@ abstract class restore_structure_step extends restore_step {
|
||||
* Receive one chunk of information form the xml parser processor and
|
||||
* dispatch it, following the naming rules
|
||||
*/
|
||||
public function process($data) {
|
||||
final public function process($data) {
|
||||
if (!array_key_exists($data['path'], $this->pathelements)) { // Incorrect path, must not happen
|
||||
throw new restore_step_exception('restore_structure_step_missing_path', $data['path']);
|
||||
}
|
||||
$element = $this->pathelements[$data['path']];
|
||||
$object = $element->get_processing_object();
|
||||
$method = $element->get_processing_method();
|
||||
$rdata = null;
|
||||
if (empty($object)) { // No processing object defined
|
||||
throw new restore_step_exception('restore_structure_step_missing_pobject', $object);
|
||||
}
|
||||
$rdata = $object->$method($data['tags']); // Dispatch to proper object/method
|
||||
if ($rdata !== null) { // If the method has returned any info, set element data to it
|
||||
// Release the lock if we aren't anymore within children of it
|
||||
if (!is_null($this->pathlock) and strpos($data['path'], $this->pathlock) === false) {
|
||||
$this->pathlock = null;
|
||||
}
|
||||
if (is_null($this->pathlock)) { // Only dispatch if there isn't any lock
|
||||
$rdata = $object->$method($data['tags']); // Dispatch to proper object/method
|
||||
}
|
||||
|
||||
// If the dispatched method returns SKIP_ALL_CHILDREN, we grab current path in order to
|
||||
// lock dispatching to any children
|
||||
if ($rdata === self::SKIP_ALL_CHILDREN) {
|
||||
// Check we haven't any previous lock
|
||||
if (!is_null($this->pathlock)) {
|
||||
throw new restore_step_exception('restore_structure_step_already_skipping', $data['path']);
|
||||
}
|
||||
// Set the lock
|
||||
$this->pathlock = $data['path'] . '/'; // Lock everything below current path
|
||||
|
||||
// Continue with normal processing of return values
|
||||
} else if ($rdata !== null) { // If the method has returned any info, set element data to it
|
||||
$element->set_data($rdata);
|
||||
} else { // Else, put the original parsed data
|
||||
$element->set_data($data);
|
||||
|
||||
Reference in New Issue
Block a user