MDL-56586 blocks: allow theme to manage "Add a block" select

This commit is contained in:
Marina Glancy 2016-11-18 17:27:38 +08:00
parent 692c1bf345
commit b11916d3e7
8 changed files with 140 additions and 18 deletions

View file

@ -83,16 +83,19 @@ Scenario: Block should select current activity by default
When I add the "Activity results" block When I add the "Activity results" block
And I configure the "Activity results" block And I configure the "Activity results" block
Then the field "id_config_activitygradeitemid" matches value "Test assignment 1" Then the field "id_config_activitygradeitemid" matches value "Test assignment 1"
And I press "Cancel"
And I follow "Course 1" And I follow "Course 1"
And I follow "Test assignment 2" And I follow "Test assignment 2"
And I add the "Activity results" block And I add the "Activity results" block
And I configure the "Activity results" block And I configure the "Activity results" block
And the field "id_config_activitygradeitemid" matches value "Test assignment 2" And the field "id_config_activitygradeitemid" matches value "Test assignment 2"
And I press "Cancel"
And I follow "Course 1" And I follow "Course 1"
And I follow "Test assignment 3" And I follow "Test assignment 3"
And I add the "Activity results" block And I add the "Activity results" block
And I configure the "Activity results" block And I configure the "Activity results" block
And the field "id_config_activitygradeitemid" matches value "Test assignment 3" And the field "id_config_activitygradeitemid" matches value "Test assignment 3"
And I press "Cancel"
And I follow "Course 1" And I follow "Course 1"
And I follow "Test page name" And I follow "Test page name"
And I add the "Activity results" block And I add the "Activity results" block

View file

@ -42,6 +42,14 @@ define('BUI_CONTEXTS_ENTIRE_SITE', 2);
define('BUI_CONTEXTS_CURRENT', 0); define('BUI_CONTEXTS_CURRENT', 0);
define('BUI_CONTEXTS_CURRENT_SUBS', 1); define('BUI_CONTEXTS_CURRENT_SUBS', 1);
// Position of "Add block" control, to be used in theme config as a value for $THEME->addblockposition:
// - default: as a fake block that is displayed in editing mode
// - flatnav: "Add block" item in the flat navigation drawer in editing mode
// - custom: none of the above, theme will take care of displaying the control.
define('BLOCK_ADDBLOCK_POSITION_DEFAULT', 0);
define('BLOCK_ADDBLOCK_POSITION_FLATNAV', 1);
define('BLOCK_ADDBLOCK_POSITION_CUSTOM', -1);
/** /**
* Exception thrown when someone tried to do something with a block that does * Exception thrown when someone tried to do something with a block that does
* not exist on a page. * not exist on a page.
@ -216,10 +224,12 @@ class block_manager {
($bi->instance_allow_multiple() || !$this->is_block_present($block->name)) && ($bi->instance_allow_multiple() || !$this->is_block_present($block->name)) &&
blocks_name_allowed_in_format($block->name, $pageformat) && blocks_name_allowed_in_format($block->name, $pageformat) &&
$bi->user_can_addto($this->page)) { $bi->user_can_addto($this->page)) {
$block->title = $bi->get_title();
$this->addableblocks[$block->name] = $block; $this->addableblocks[$block->name] = $block;
} }
} }
core_collator::asort_objects_by_property($this->addableblocks, 'title');
return $this->addableblocks; return $this->addableblocks;
} }
@ -1141,7 +1151,8 @@ class block_manager {
$contents = $this->extracontent[$region]; $contents = $this->extracontent[$region];
} }
$contents = array_merge($contents, $this->create_block_contents($this->blockinstances[$region], $output, $region)); $contents = array_merge($contents, $this->create_block_contents($this->blockinstances[$region], $output, $region));
if ($region == $this->defaultregion) { if (($region == $this->defaultregion) && (!isset($this->page->theme->addblockposition) ||
$this->page->theme->addblockposition == BLOCK_ADDBLOCK_POSITION_DEFAULT)) {
$addblockui = block_add_block_ui($this->page, $output); $addblockui = block_add_block_ui($this->page, $output);
if ($addblockui) { if ($addblockui) {
$contents[] = $addblockui; $contents[] = $addblockui;
@ -1286,8 +1297,10 @@ class block_manager {
* @return boolean true if anything was done. False if not. * @return boolean true if anything was done. False if not.
*/ */
public function process_url_add() { public function process_url_add() {
global $CFG, $PAGE, $OUTPUT;
$blocktype = optional_param('bui_addblock', null, PARAM_PLUGIN); $blocktype = optional_param('bui_addblock', null, PARAM_PLUGIN);
if (!$blocktype) { if ($blocktype === null) {
return false; return false;
} }
@ -1297,7 +1310,54 @@ class block_manager {
throw new moodle_exception('nopermissions', '', $this->page->url->out(), get_string('addblock')); throw new moodle_exception('nopermissions', '', $this->page->url->out(), get_string('addblock'));
} }
if (!array_key_exists($blocktype, $this->get_addable_blocks())) { $addableblocks = $this->get_addable_blocks();
if ($blocktype === '') {
// Display add block selection.
$addpage = new moodle_page();
$addpage->set_pagelayout('admin');
$addpage->blocks->show_only_fake_blocks(true);
$addpage->set_course($this->page->course);
$addpage->set_context($this->page->context);
if ($this->page->cm) {
$addpage->set_cm($this->page->cm);
}
$addpagebase = str_replace($CFG->wwwroot . '/', '/', $this->page->url->out_omit_querystring());
$addpageparams = $this->page->url->params();
$addpage->set_url($addpagebase, $addpageparams);
$addpage->set_block_actions_done();
// At this point we are going to display the block selector, overwrite global $PAGE ready for this.
$PAGE = $addpage;
// Some functions use $OUTPUT so we need to replace that too.
$OUTPUT = $addpage->get_renderer('core');
$site = get_site();
$straddblock = get_string('addblock');
$PAGE->navbar->add($straddblock);
$PAGE->set_title($straddblock);
$PAGE->set_heading($site->fullname);
echo $OUTPUT->header();
echo $OUTPUT->heading($straddblock);
if (!$addableblocks) {
echo $OUTPUT->box(get_string('noblockstoaddhere'));
echo $OUTPUT->container($OUTPUT->action_link($addpage->url, get_string('back')), 'm-x-3 m-b-1');
} else {
foreach ($addableblocks as $blockname => $block) {
$url = new moodle_url($addpage->url, array('sesskey' => sesskey(), 'bui_addblock' => $blockname));
echo $OUTPUT->container($OUTPUT->single_button($url, $block->title), 'm-x-3 m-b-1');
}
echo $OUTPUT->container($OUTPUT->action_link($addpage->url, get_string('cancel')), 'm-x-3 m-b-1');
}
echo $OUTPUT->footer();
// Make sure that nothing else happens after we have displayed this form.
exit;
}
if (!array_key_exists($blocktype, $addableblocks)) {
throw new moodle_exception('cannotaddthisblocktype', '', $this->page->url->out(), $blocktype); throw new moodle_exception('cannotaddthisblocktype', '', $this->page->url->out(), $blocktype);
} }
@ -1332,6 +1392,7 @@ class block_manager {
if (!$confirmdelete) { if (!$confirmdelete) {
$deletepage = new moodle_page(); $deletepage = new moodle_page();
$deletepage->set_pagelayout('admin'); $deletepage->set_pagelayout('admin');
$deletepage->blocks->show_only_fake_blocks(true);
$deletepage->set_course($this->page->course); $deletepage->set_course($this->page->course);
$deletepage->set_context($this->page->context); $deletepage->set_context($this->page->context);
if ($this->page->cm) { if ($this->page->cm) {
@ -1452,6 +1513,7 @@ class block_manager {
$editpage = new moodle_page(); $editpage = new moodle_page();
$editpage->set_pagelayout('admin'); $editpage->set_pagelayout('admin');
$editpage->blocks->show_only_fake_blocks(true);
$editpage->set_course($this->page->course); $editpage->set_course($this->page->course);
//$editpage->set_context($block->context); //$editpage->set_context($block->context);
$editpage->set_context($this->page->context); $editpage->set_context($this->page->context);
@ -2072,12 +2134,8 @@ function block_add_block_ui($page, $output) {
$menu = array(); $menu = array();
foreach ($missingblocks as $block) { foreach ($missingblocks as $block) {
$blockobject = block_instance($block->name); $menu[$block->name] = $block->title;
if ($blockobject !== false && $blockobject->user_can_addto($page)) {
$menu[$block->name] = $blockobject->get_title();
}
} }
core_collator::asort($menu);
$actionurl = new moodle_url($page->url, array('sesskey'=>sesskey())); $actionurl = new moodle_url($page->url, array('sesskey'=>sesskey()));
$select = new single_select($actionurl, 'bui_addblock', $menu, null, array(''=>get_string('adddots')), 'add_block'); $select = new single_select($actionurl, 'bui_addblock', $menu, null, array(''=>get_string('adddots')), 'add_block');

View file

@ -3764,6 +3764,19 @@ class flat_navigation extends navigation_node_collection {
$flat->key = 'sitesettings'; $flat->key = 'sitesettings';
$this->add($flat); $this->add($flat);
} }
// Add-a-block in editing mode.
if (isset($this->page->theme->addblockposition) &&
$this->page->theme->addblockposition == BLOCK_ADDBLOCK_POSITION_FLATNAV &&
$PAGE->user_is_editing() && $PAGE->user_can_edit_blocks() &&
$PAGE->blocks->get_addable_blocks()) {
$url = new moodle_url($PAGE->url, ['bui_addblock' => '', 'sesskey' => sesskey()]);
$addablock = navigation_node::create(get_string('addblock'), $url);
$flat = new flat_navigation_node($addablock, 0);
$flat->set_showdivider(true);
$flat->key = 'addblock';
$this->add($flat);
}
} }
} }

View file

@ -546,7 +546,7 @@ class theme_config {
'rendererfactory', 'csspostprocess', 'editor_sheets', 'rarrow', 'larrow', 'uarrow', 'darrow', 'rendererfactory', 'csspostprocess', 'editor_sheets', 'rarrow', 'larrow', 'uarrow', 'darrow',
'hidefromselector', 'doctype', 'yuicssmodules', 'blockrtlmanipulations', 'hidefromselector', 'doctype', 'yuicssmodules', 'blockrtlmanipulations',
'lessfile', 'extralesscallback', 'lessvariablescallback', 'blockrendermethod', 'lessfile', 'extralesscallback', 'lessvariablescallback', 'blockrendermethod',
'scss', 'extrascsscallback', 'prescsscallback', 'csstreepostprocessor'); 'scss', 'extrascsscallback', 'prescsscallback', 'csstreepostprocessor', 'addblockposition');
foreach ($config as $key=>$value) { foreach ($config as $key=>$value) {
if (in_array($key, $configurable)) { if (in_array($key, $configurable)) {

View file

@ -152,3 +152,4 @@ $THEME->prescsscallback = 'theme_boost_get_pre_scss';
$THEME->yuicssmodules = array(); $THEME->yuicssmodules = array();
$THEME->rendererfactory = 'theme_overridden_renderer_factory'; $THEME->rendererfactory = 'theme_overridden_renderer_factory';
$THEME->undeletableblocktypes = ''; $THEME->undeletableblocktypes = '';
$THEME->addblockposition = BLOCK_ADDBLOCK_POSITION_FLATNAV;

View file

@ -38,15 +38,8 @@ require_once(__DIR__ . '/../../../../blocks/tests/behat/behat_blocks.php');
class behat_theme_boost_behat_blocks extends behat_blocks { class behat_theme_boost_behat_blocks extends behat_blocks {
public function i_add_the_block($blockname) { public function i_add_the_block($blockname) {
$this->execute('behat_forms::i_set_the_field_to', $this->execute('behat_navigation::i_select_from_flat_navigation_drawer', get_string('addblock'));
array("bui_addblock", $this->escape($blockname)) $this->execute('behat_forms::press_button', $blockname);
);
// If we are running without javascript we need to submit the form.
if (!$this->running_javascript()) {
$this->execute('behat_general::i_click_on_in_the',
array("Go", "button", "Add a block", "block"));
}
} }
public function i_open_the_blocks_action_menu($blockname) { public function i_open_the_blocks_action_menu($blockname) {

View file

@ -76,4 +76,56 @@ class behat_theme_boost_behat_navigation extends behat_navigation {
return $node; return $node;
} }
/**
* Opens the flat navigation drawer if it is not already open
*
* @When /^I open flat navigation drawer$/
* @throws ElementNotFoundException Thrown by behat_base::find
*/
public function i_open_flat_navigation_drawer() {
if (!$this->running_javascript()) {
// Navigation drawer is always open without JS.
return;
}
$xpath = "//button[contains(@data-action,'toggle-drawer')]";
$node = $this->find('xpath', $xpath);
$expanded = $node->getAttribute('aria-expanded');
if ($expanded === 'false') {
$node->click();
$this->wait_for_pending_js();
}
}
/**
* Closes the flat navigation drawer if it is open (does nothing if JS disabled)
*
* @When /^I close flat navigation drawer$/
* @throws ElementNotFoundException Thrown by behat_base::find
*/
public function i_close_flat_navigation_drawer() {
if (!$this->running_javascript()) {
// Navigation drawer can not be closed without JS.
return;
}
$xpath = "//button[contains(@data-action,'toggle-drawer')]";
$node = $this->find('xpath', $xpath);
$expanded = $node->getAttribute('aria-expanded');
if ($expanded === 'true') {
$node->click();
$this->wait_for_pending_js();
}
}
/**
* Clicks link with specified id|title|alt|text in the flat navigation drawer.
*
* @When /^I select "(?P<link_string>(?:[^"]|\\")*)" from flat navigation drawer$/
* @throws ElementNotFoundException Thrown by behat_base::find
* @param string $link
*/
public function i_select_from_flat_navigation_drawer($link) {
$this->i_open_flat_navigation_drawer();
$this->execute('behat_general::i_click_on_in_the', [$link, 'link', '#nav-drawer', 'css_element']);
}
} }

View file

@ -57,6 +57,8 @@ information provided here is intended especially for theme designer.
* CLI svgtool.php has moved from theme/base/cli to admin/cli and paths should be relative to the new location. * CLI svgtool.php has moved from theme/base/cli to admin/cli and paths should be relative to the new location.
* mod_chat will now display the 'course theme' option for all themes (previously it was only displayed on * mod_chat will now display the 'course theme' option for all themes (previously it was only displayed on
bootstrap2 based themes). bootstrap2 based themes).
* Theme can choose how to display "Add a block" control in $THEME->addblockposition, default value is
BLOCK_ADDBLOCK_POSITION_DEFAULT that displays it as a fake block in editing mode.
=== 3.1 === === 3.1 ===