public function process_block($data) { global $DB, $CFG; $data = (object) $data; // Handy $oldcontextid = $data->contextid; $oldid = $data->id; $positions = isset($data->block_positions['block_position']) ? $data->block_positions['block_position'] : array(); // Look for the parent contextid if (!($data->parentcontextid = $this->get_mappingid('context', $data->parentcontextid))) { throw new restore_step_exception('restore_block_missing_parent_ctx', $data->parentcontextid); } // TODO: it would be nice to use standard plugin supports instead of this instance_allow_multiple() // If there is already one block of that type in the parent context // and the block is not multiple, stop processing // Use blockslib loader / method executor if (!($bi = block_instance($data->blockname))) { return false; } if (!$bi->instance_allow_multiple()) { // The block cannot be added twice, so we will check if the same block is already being // displayed on the same page. For this, rather than mocking a page and using the block_manager // we use a similar query to the one in block_manager::load_blocks(), this will give us // a very good idea of the blocks already displayed in the context. $params = array('blockname' => $data->blockname); // Context matching test. $context = context::instance_by_id($data->parentcontextid); $contextsql = 'bi.parentcontextid = :contextid'; $params['contextid'] = $context->id; $parentcontextids = $context->get_parent_context_ids(); if ($parentcontextids) { list($parentcontextsql, $parentcontextparams) = $DB->get_in_or_equal($parentcontextids, SQL_PARAMS_NAMED); $contextsql = "({$contextsql} OR (bi.showinsubcontexts = 1 AND bi.parentcontextid {$parentcontextsql}))"; $params = array_merge($params, $parentcontextparams); } // Page type pattern test. $pagetypepatterns = matching_page_type_patterns_from_pattern($data->pagetypepattern); list($pagetypepatternsql, $pagetypepatternparams) = $DB->get_in_or_equal($pagetypepatterns, SQL_PARAMS_NAMED); $params = array_merge($params, $pagetypepatternparams); // Sub page pattern test. $subpagepatternsql = 'bi.subpagepattern IS NULL'; if ($data->subpagepattern !== null) { $subpagepatternsql = "({$subpagepatternsql} OR bi.subpagepattern = :subpagepattern)"; $params['subpagepattern'] = $data->subpagepattern; } $exists = $DB->record_exists_sql("SELECT bi.id\n FROM {block_instances} bi\n JOIN {block} b ON b.name = bi.blockname\n WHERE bi.blockname = :blockname\n AND {$contextsql}\n AND bi.pagetypepattern {$pagetypepatternsql}\n AND {$subpagepatternsql}", $params); if ($exists) { // There is at least one very similar block visible on the page where we // are trying to restore the block. In these circumstances the block API // would not allow the user to add another instance of the block, so we // apply the same rule here. return false; } } // If there is already one block of that type in the parent context // with the same showincontexts, pagetypepattern, subpagepattern, defaultregion and configdata // stop processing $params = array('blockname' => $data->blockname, 'parentcontextid' => $data->parentcontextid, 'showinsubcontexts' => $data->showinsubcontexts, 'pagetypepattern' => $data->pagetypepattern, 'subpagepattern' => $data->subpagepattern, 'defaultregion' => $data->defaultregion); if ($birecs = $DB->get_records('block_instances', $params)) { foreach ($birecs as $birec) { if ($birec->configdata == $data->configdata) { return false; } } } // Set task old contextid, blockid and blockname once we know them $this->task->set_old_contextid($oldcontextid); $this->task->set_old_blockid($oldid); $this->task->set_blockname($data->blockname); // Let's look for anything within configdata neededing processing // (nulls and uses of legacy file.php) if ($attrstotransform = $this->task->get_configdata_encoded_attributes()) { $configdata = (array) unserialize(base64_decode($data->configdata)); foreach ($configdata as $attribute => $value) { if (in_array($attribute, $attrstotransform)) { $configdata[$attribute] = $this->contentprocessor->process_cdata($value); } } $data->configdata = base64_encode(serialize((object) $configdata)); } // Create the block instance $newitemid = $DB->insert_record('block_instances', $data); // Save the mapping (with restorefiles support) $this->set_mapping('block_instance', $oldid, $newitemid, true); // Create the block context $newcontextid = context_block::instance($newitemid)->id; // Save the block contexts mapping and sent it to task $this->set_mapping('context', $oldcontextid, $newcontextid); $this->task->set_contextid($newcontextid); $this->task->set_blockid($newitemid); // Restore block fileareas if declared $component = 'block_' . $this->task->get_blockname(); foreach ($this->task->get_fileareas() as $filearea) { // Simple match by contextid. No itemname needed $this->add_related_files($component, $filearea, null); } // Process block positions, creating them or accumulating for final step foreach ($positions as $position) { $position = (object) $position; $position->blockinstanceid = $newitemid; // The instance is always the restored one // If position is for one already mapped (known) contextid // process it now, creating the position if ($newpositionctxid = $this->get_mappingid('context', $position->contextid)) { $position->contextid = $newpositionctxid; // Create the block position $DB->insert_record('block_positions', $position); // The position belongs to an unknown context, send it to backup_ids // to process them as part of the final steps of restore. We send the // whole $position object there, hence use the low level method. } else { restore_dbops::set_backup_ids_record($this->get_restoreid(), 'block_position', $position->id, 0, null, $position); } } }
public function test_matching_page_type_patterns_from_pattern() { $pattern = '*'; $expected = array('*'); $this->assertEquals($expected, array_values(matching_page_type_patterns_from_pattern($pattern))); $pattern = 'admin-*'; $expected = array('admin-*', 'admin', '*'); $this->assertEquals($expected, array_values(matching_page_type_patterns_from_pattern($pattern))); $pattern = 'blog-index'; $expected = array('blog-index', 'blog-index-*', 'blog-*', '*'); $this->assertEquals($expected, array_values(matching_page_type_patterns_from_pattern($pattern))); $pattern = 'course-index-*'; $expected = array('course-index-*', 'course-index', 'course-*', '*'); $this->assertEquals($expected, array_values(matching_page_type_patterns_from_pattern($pattern))); $pattern = 'course-index-category'; $expected = array('course-index-category', 'course-index-category-*', 'course-index-*', 'course-*', '*'); $this->assertEquals($expected, array_values(matching_page_type_patterns_from_pattern($pattern))); $pattern = 'mod-assign-view'; $expected = array('mod-assign-view', 'mod-*-view', 'mod-assign-view-*', 'mod-assign-*', 'mod-*', '*'); $this->assertEquals($expected, array_values(matching_page_type_patterns_from_pattern($pattern))); $pattern = 'mod-assign-index'; $expected = array('mod-assign-index', 'mod-*-index', 'mod-assign-index-*', 'mod-assign-*', 'mod-*', '*'); $this->assertEquals($expected, array_values(matching_page_type_patterns_from_pattern($pattern))); $pattern = 'mod-forum-*'; $expected = array('mod-forum-*', 'mod-forum', 'mod-*', '*'); $this->assertEquals($expected, array_values(matching_page_type_patterns_from_pattern($pattern))); $pattern = 'mod-*-view'; $expected = array('mod-*-view', 'mod', 'mod-*', '*'); $this->assertEquals($expected, array_values(matching_page_type_patterns_from_pattern($pattern))); $pattern = 'mod-*-index'; $expected = array('mod-*-index', 'mod', 'mod-*', '*'); $this->assertEquals($expected, array_values(matching_page_type_patterns_from_pattern($pattern))); $pattern = 'my-index'; $expected = array('my-index', 'my-index-*', 'my-*', '*'); $this->assertEquals($expected, array_values(matching_page_type_patterns_from_pattern($pattern))); $pattern = 'user-profile'; $expected = array('user-profile', 'user-profile-*', 'user-*', '*'); $this->assertEquals($expected, array_values(matching_page_type_patterns_from_pattern($pattern))); }