2009-05-22 02:18:49 +00:00
< ? php
2009-07-28 09:59:21 +00:00
// This file is part of Moodle - http://moodle.org/
//
2009-05-22 02:18:49 +00:00
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
2009-07-28 09:59:21 +00:00
//
2009-05-22 02:18:49 +00:00
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
2009-04-30 03:50:00 +00:00
/**
2009-05-22 02:18:49 +00:00
* Block Class and Functions
2009-04-30 03:50:00 +00:00
*
2009-07-28 09:59:21 +00:00
* This file defines the { @ link block_manager } class ,
2009-07-09 07:35:03 +00:00
*
2010-07-25 13:35:05 +00:00
* @ package core
* @ subpackage block
* @ copyright 1999 onwards Martin Dougiamas http :// dougiamas . com
* @ license http :// www . gnu . org / copyleft / gpl . html GNU GPL v3 or later
2009-04-30 03:50:00 +00:00
*/
2004-04-18 23:20:53 +00:00
2010-07-25 13:35:05 +00:00
defined ( 'MOODLE_INTERNAL' ) || die ();
2009-07-10 05:58:59 +00:00
/** #@+
* Default names for the block regions in the standard theme .
*/
2009-05-06 09:15:05 +00:00
define ( 'BLOCK_POS_LEFT' , 'side-pre' );
define ( 'BLOCK_POS_RIGHT' , 'side-post' );
2009-07-10 05:58:59 +00:00
/**#@-*/
2004-08-22 16:48:28 +00:00
MDL-26105 Block settings should contains less options, and be more user friendly
AMOS BEGIN
MOV [page-blog-index, pagetype], [page-blog-index, blog]
MOV [page-blog-x, pagetype], [page-blog-x, blog]
MOV [page-tag-x, pagetype], [page-tag-x, tag]
MOV [page-course-view-weeks, pagetype], [page-course-view-weeks, format_weeks]
MOV [page-course-view-weeks-x, pagetype], [page-course-view-weeks-x, format_weeks]
MOV [page-course-view-topics, pagetype], [page-course-view-topics, format_topics]
MOV [page-course-view-topics-x, pagetype], [page-course-view-topics-x, format_topics]
AMOS END
2011-04-28 11:20:30 +08:00
define ( 'BUI_CONTEXTS_FRONTPAGE_ONLY' , 0 );
define ( 'BUI_CONTEXTS_FRONTPAGE_SUBS' , 1 );
define ( 'BUI_CONTEXTS_ENTIRE_SITE' , 2 );
define ( 'BUI_CONTEXTS_CURRENT' , 0 );
define ( 'BUI_CONTEXTS_CURRENT_SUBS' , 1 );
2016-11-18 17:27:38 +08:00
// 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 );
2009-05-22 02:18:49 +00:00
/**
2009-07-09 07:35:03 +00:00
* Exception thrown when someone tried to do something with a block that does
* not exist on a page .
2009-05-22 02:18:49 +00:00
*
2009-07-09 07:35:03 +00:00
* @ copyright 2009 Tim Hunt
* @ license http :// www . gnu . org / copyleft / gpl . html GNU GPL v3 or later
* @ since Moodle 2.0
2009-05-22 02:18:49 +00:00
*/
2009-05-08 06:34:40 +00:00
class block_not_on_page_exception extends moodle_exception {
2009-05-22 02:18:49 +00:00
/**
2010-08-28 11:54:24 +00:00
* Constructor
2009-07-09 07:35:03 +00:00
* @ param int $instanceid the block instance id of the block that was looked for .
* @ param object $page the current page .
2009-05-22 02:18:49 +00:00
*/
2009-05-08 06:34:40 +00:00
public function __construct ( $instanceid , $page ) {
$a = new stdClass ;
$a -> instanceid = $instanceid ;
2009-07-14 09:28:10 +00:00
$a -> url = $page -> url -> out ();
parent :: __construct ( 'blockdoesnotexistonpage' , '' , $page -> url -> out (), $a );
2009-05-08 06:34:40 +00:00
}
}
2009-05-06 09:14:01 +00:00
/**
* This class keeps track of the block that should appear on a moodle_page .
2009-05-06 09:15:05 +00:00
*
2009-07-09 07:35:03 +00:00
* The page to work with as passed to the constructor .
2009-05-08 03:11:24 +00:00
*
2009-07-09 07:35:03 +00:00
* @ copyright 2009 Tim Hunt
* @ license http :// www . gnu . org / copyleft / gpl . html GNU GPL v3 or later
* @ since Moodle 2.0
2009-05-06 09:14:01 +00:00
*/
2009-07-09 07:35:03 +00:00
class block_manager {
2009-07-30 10:29:14 +00:00
/**
* The UI normally only shows block weights between - MAX_WEIGHT and MAX_WEIGHT ,
* although other weights are valid .
*/
const MAX_WEIGHT = 10 ;
2009-05-06 09:14:01 +00:00
/// Field declarations =========================================================
2009-07-09 07:35:03 +00:00
2010-09-14 02:12:41 +00:00
/**
* the moodle_page we are managing blocks for .
* @ var moodle_page
*/
2009-05-06 09:14:01 +00:00
protected $page ;
2009-07-09 07:35:03 +00:00
/** @var array region name => 1.*/
2009-05-06 09:14:01 +00:00
protected $regions = array ();
2009-07-09 07:35:03 +00:00
/** @var string the region where new blocks are added.*/
protected $defaultregion = null ;
/** @var array will be $DB->get_records('blocks') */
protected $allblocks = null ;
/**
* @ var array blocks that this user can add to this page . Will be a subset
2009-07-14 08:37:28 +00:00
* of $allblocks , but with array keys block -> name . Access this via the
* { @ link get_addable_blocks ()} method to ensure it is lazy - loaded .
2009-07-09 07:35:03 +00:00
*/
protected $addableblocks = null ;
2009-05-06 09:14:42 +00:00
2009-05-06 09:15:05 +00:00
/**
* Will be an array region - name => array ( db rows loaded in load_blocks );
2009-05-22 02:18:49 +00:00
* @ var array
2009-05-06 09:15:05 +00:00
*/
protected $birecordsbyregion = null ;
/**
* array region - name => array ( block objects ); populated as necessary by
* the ensure_instances_exist method .
2009-05-22 02:18:49 +00:00
* @ var array
2009-05-06 09:15:05 +00:00
*/
protected $blockinstances = array ();
/**
2010-08-28 11:54:24 +00:00
* array region - name => array ( block_contents objects ) what actually needs to
2009-05-06 09:15:05 +00:00
* be displayed in each region .
2009-05-22 02:18:49 +00:00
* @ var array
2009-05-06 09:15:05 +00:00
*/
protected $visibleblockcontent = array ();
2009-05-06 09:14:42 +00:00
2009-07-09 07:35:03 +00:00
/**
* array region - name => array ( block_contents objects ) extra block - like things
* to be displayed in each region , before the real blocks .
* @ var array
*/
protected $extracontent = array ();
2009-07-30 08:22:12 +00:00
/**
2010-08-28 11:54:24 +00:00
* Used by the block move id , to track whether a block is currently being moved .
2009-07-30 08:22:12 +00:00
*
2010-08-28 11:54:24 +00:00
* When you click on the move icon of a block , first the page needs to reload with
* extra UI for choosing a new position for a particular block . In that situation
2009-07-30 08:22:12 +00:00
* this field holds the id of the block being moved .
*
* @ var integer | null
*/
protected $movingblock = null ;
2010-05-21 03:15:48 +00:00
/**
* Show only fake blocks
*/
protected $fakeblocksonly = false ;
2009-05-06 09:14:01 +00:00
/// Constructor ================================================================
/**
* Constructor .
* @ param object $page the moodle_page object object we are managing the blocks for ,
2010-08-28 11:54:24 +00:00
* or a reasonable faxilimily . ( See the comment at the top of this class
2009-05-22 02:18:49 +00:00
* and { @ link http :// en . wikipedia . org / wiki / Duck_typing })
2009-05-06 09:14:01 +00:00
*/
public function __construct ( $page ) {
$this -> page = $page ;
}
/// Getter methods =============================================================
/**
2009-05-22 02:18:49 +00:00
* Get an array of all region names on this page where a block may appear
*
2009-05-06 09:14:01 +00:00
* @ return array the internal names of the regions on this page where block may appear .
*/
public function get_regions () {
2009-12-16 18:00:58 +00:00
if ( is_null ( $this -> defaultregion )) {
2009-09-30 16:24:05 +00:00
$this -> page -> initialise_theme_and_output ();
2009-12-16 18:00:58 +00:00
}
2009-05-06 09:14:01 +00:00
return array_keys ( $this -> regions );
}
/**
2009-05-22 02:18:49 +00:00
* Get the region name of the region blocks are added to by default
*
2009-05-06 09:14:01 +00:00
* @ return string the internal names of the region where new blocks are added
* by default , and where any blocks from an unrecognised region are shown .
* ( Imagine that blocks were added with one theme selected , then you switched
* to a theme with different block positions . )
*/
public function get_default_region () {
2009-07-09 07:35:03 +00:00
$this -> page -> initialise_theme_and_output ();
2009-05-06 09:14:01 +00:00
return $this -> defaultregion ;
}
2009-05-06 09:14:42 +00:00
/**
* The list of block types that may be added to this page .
2009-05-22 02:18:49 +00:00
*
2009-07-14 10:41:59 +00:00
* @ return array block name => record from block table .
2009-05-06 09:14:42 +00:00
*/
public function get_addable_blocks () {
$this -> check_is_loaded ();
if ( ! is_null ( $this -> addableblocks )) {
return $this -> addableblocks ;
}
// Lazy load.
$this -> addableblocks = array ();
$allblocks = blocks_get_record ();
if ( empty ( $allblocks )) {
return $this -> addableblocks ;
}
2012-10-10 14:28:45 +01:00
$unaddableblocks = self :: get_undeletable_block_types ();
2016-12-02 10:00:43 +08:00
$requiredbythemeblocks = self :: get_required_by_theme_block_types ();
2009-05-06 09:15:05 +00:00
$pageformat = $this -> page -> pagetype ;
2009-05-06 09:14:42 +00:00
foreach ( $allblocks as $block ) {
2012-03-18 18:37:24 +01:00
if ( ! $bi = block_instance ( $block -> name )) {
continue ;
}
2012-10-10 14:28:45 +01:00
if ( $block -> visible && ! in_array ( $block -> name , $unaddableblocks ) &&
2016-12-02 10:00:43 +08:00
! in_array ( $block -> name , $requiredbythemeblocks ) &&
2012-03-18 18:37:24 +01:00
( $bi -> instance_allow_multiple () || ! $this -> is_block_present ( $block -> name )) &&
2009-07-14 08:37:28 +00:00
blocks_name_allowed_in_format ( $block -> name , $pageformat ) &&
2012-03-18 18:37:24 +01:00
$bi -> user_can_addto ( $this -> page )) {
2016-11-18 17:27:38 +08:00
$block -> title = $bi -> get_title ();
2009-07-14 08:37:28 +00:00
$this -> addableblocks [ $block -> name ] = $block ;
2009-05-06 09:14:42 +00:00
}
}
2016-11-18 17:27:38 +08:00
core_collator :: asort_objects_by_property ( $this -> addableblocks , 'title' );
2009-05-06 09:14:42 +00:00
return $this -> addableblocks ;
}
2009-05-22 02:18:49 +00:00
/**
2010-05-04 17:58:33 +00:00
* Given a block name , find out of any of them are currently present in the page
* @ param string $blockname - the basic name of a block ( eg " navigation " )
* @ return boolean - is there one of these blocks in the current page ?
2009-05-22 02:18:49 +00:00
*/
2010-05-04 17:58:33 +00:00
public function is_block_present ( $blockname ) {
if ( empty ( $this -> blockinstances )) {
return false ;
}
2016-11-18 21:36:52 +08:00
$undeletableblocks = self :: get_undeletable_block_types ();
2010-05-04 17:58:33 +00:00
foreach ( $this -> blockinstances as $region ) {
foreach ( $region as $instance ) {
if ( empty ( $instance -> instance -> blockname )) {
continue ;
}
if ( $instance -> instance -> blockname == $blockname ) {
2016-11-18 21:36:52 +08:00
if ( $instance -> instance -> requiredbytheme ) {
if ( ! in_array ( $block -> name , $undeletableblocks )) {
continue ;
}
}
2010-05-04 17:58:33 +00:00
return true ;
}
}
}
return false ;
2009-05-06 09:14:42 +00:00
}
/**
2009-05-22 02:18:49 +00:00
* Find out if a block type is known by the system
*
2010-08-28 11:54:24 +00:00
* @ param string $blockname the name of the type of block .
2009-05-06 09:14:42 +00:00
* @ param boolean $includeinvisible if false ( default ) only check 'visible' blocks , that is , blocks enabled by the admin .
* @ return boolean true if this block in installed .
*/
public function is_known_block_type ( $blockname , $includeinvisible = false ) {
$blocks = $this -> get_installed_blocks ();
foreach ( $blocks as $block ) {
if ( $block -> name == $blockname && ( $includeinvisible || $block -> visible )) {
return true ;
}
}
return false ;
}
/**
2009-05-22 02:18:49 +00:00
* Find out if a region exists on a page
*
2009-05-06 09:14:42 +00:00
* @ param string $region a region name
2010-08-28 11:54:24 +00:00
* @ return boolean true if this region exists on this page .
2009-05-06 09:14:42 +00:00
*/
public function is_known_region ( $region ) {
2016-03-31 15:07:22 +08:00
if ( empty ( $region )) {
return false ;
}
2009-05-06 09:14:42 +00:00
return array_key_exists ( $region , $this -> regions );
}
/**
2009-05-22 02:18:49 +00:00
* Get an array of all blocks within a given region
*
* @ param string $region a block region that exists on this page .
2009-05-06 09:14:42 +00:00
* @ return array of block instances .
*/
public function get_blocks_for_region ( $region ) {
$this -> check_is_loaded ();
2009-05-06 09:15:05 +00:00
$this -> ensure_instances_exist ( $region );
return $this -> blockinstances [ $region ];
}
/**
2009-05-22 02:18:49 +00:00
* Returns an array of block content objects that exist in a region
*
2009-07-09 07:35:03 +00:00
* @ param string $region a block region that exists on this page .
* @ return array of block block_contents objects for all the blocks in a region .
2009-05-06 09:15:05 +00:00
*/
2009-07-09 07:35:03 +00:00
public function get_content_for_region ( $region , $output ) {
2009-05-06 09:15:05 +00:00
$this -> check_is_loaded ();
2009-07-09 07:35:03 +00:00
$this -> ensure_content_created ( $region , $output );
2009-05-06 09:15:05 +00:00
return $this -> visibleblockcontent [ $region ];
2009-05-06 09:14:42 +00:00
}
2009-07-30 08:22:12 +00:00
/**
* Helper method used by get_content_for_region .
* @ param string $region region name
* @ param float $weight weight . May be fractional , since you may want to move a block
* between ones with weight 2 and 3 , say ( $weight would be 2.5 ) .
* @ return string URL for moving block $this -> movingblock to this position .
*/
protected function get_move_target_url ( $region , $weight ) {
2010-02-17 18:36:26 +00:00
return new moodle_url ( $this -> page -> url , array ( 'bui_moveid' => $this -> movingblock ,
2010-01-17 09:50:55 +00:00
'bui_newregion' => $region , 'bui_newweight' => $weight , 'sesskey' => sesskey ()));
2009-07-30 08:22:12 +00:00
}
2009-07-09 07:35:03 +00:00
/**
* Determine whether a region contains anything . ( Either any real blocks , or
* the add new block UI . )
2009-07-22 05:38:28 +00:00
*
* ( You may wonder why the $output parameter is required . Unfortunately ,
2010-08-28 11:54:24 +00:00
* because of the way that blocks work , the only reliable way to find out
2009-07-22 05:38:28 +00:00
* if a block will be visible is to get the content for output , and to
* get the content , you need a renderer . Fortunately , this is not a
2010-08-28 11:54:24 +00:00
* performance problem , because we cache the output that is generated , and
2009-07-22 05:38:28 +00:00
* in almost every case where we call region_has_content , we are about to
* output the blocks anyway , so we are not doing wasted effort . )
*
2009-07-09 07:35:03 +00:00
* @ param string $region a block region that exists on this page .
2013-06-07 10:38:39 +12:00
* @ param core_renderer $output a core_renderer . normally the global $OUTPUT .
2009-07-09 07:35:03 +00:00
* @ return boolean Whether there is anything in this region .
*/
2009-07-22 05:38:28 +00:00
public function region_has_content ( $region , $output ) {
2010-03-31 07:41:31 +00:00
2009-07-09 07:35:03 +00:00
if ( ! $this -> is_known_region ( $region )) {
return false ;
}
$this -> check_is_loaded ();
2009-07-22 05:38:28 +00:00
$this -> ensure_content_created ( $region , $output );
2011-11-06 19:48:10 +00:00
// if ($this->page->user_is_editing() && $this->page->user_can_edit_blocks()) {
// Mark Nielsen's patch - part 1
if ( $this -> page -> user_is_editing () && $this -> page -> user_can_edit_blocks () && $this -> movingblock ) {
2009-07-09 07:35:03 +00:00
// If editing is on, we need all the block regions visible, for the
// move blocks UI.
return true ;
}
2009-07-22 05:38:28 +00:00
return ! empty ( $this -> visibleblockcontent [ $region ]) || ! empty ( $this -> extracontent [ $region ]);
2009-07-09 07:35:03 +00:00
}
2009-05-06 09:14:42 +00:00
/**
2009-05-22 02:18:49 +00:00
* Get an array of all of the installed blocks .
*
2009-05-06 09:14:42 +00:00
* @ return array contents of the block table .
*/
public function get_installed_blocks () {
global $DB ;
if ( is_null ( $this -> allblocks )) {
$this -> allblocks = $DB -> get_records ( 'block' );
}
return $this -> allblocks ;
}
2012-10-10 14:28:45 +01:00
/**
2016-12-02 10:00:43 +08:00
* @ return array names of block types that must exist on every page with this theme .
*/
public static function get_required_by_theme_block_types () {
global $CFG , $PAGE ;
$requiredbythemeblocks = false ;
if ( isset ( $PAGE -> theme -> requiredblocks )) {
$requiredbythemeblocks = $PAGE -> theme -> requiredblocks ;
}
2016-12-02 22:47:57 +08:00
// We need blocks for behat, till MDL-56614 gets in.
if ( defined ( 'BEHAT_SITE_RUNNING' )) {
return array ( 'navigation' , 'settings' );
} else if ( $requiredbythemeblocks === false ) {
2016-12-02 10:00:43 +08:00
return array ( 'navigation' , 'settings' );
} else if ( $requiredbythemeblocks === '' ) {
return array ();
} else if ( is_string ( $requiredbythemeblocks )) {
return explode ( ',' , $requiredbythemeblocks );
} else {
return $requiredbythemeblocks ;
}
}
/**
* Make this block type undeletable and unaddable .
*
* @ param mixed $blockidorname string or int
*/
public static function protect_block ( $blockidorname ) {
global $DB ;
$syscontext = context_system :: instance ();
require_capability ( 'moodle/site:config' , $syscontext );
$block = false ;
if ( is_int ( $blockidorname )) {
$block = $DB -> get_record ( 'block' , array ( 'id' => $blockidorname ), 'id, name' , MUST_EXIST );
} else {
$block = $DB -> get_record ( 'block' , array ( 'name' => $blockidorname ), 'id, name' , MUST_EXIST );
}
$undeletableblocktypes = self :: get_undeletable_block_types ();
if ( ! in_array ( $block -> name , $undeletableblocktypes )) {
$undeletableblocktypes [] = $block -> name ;
set_config ( 'undeletableblocktypes' , implode ( ',' , $undeletableblocktypes ));
}
}
/**
* Make this block type deletable and addable .
*
* @ param mixed $blockidorname string or int
*/
public static function unprotect_block ( $blockidorname ) {
global $DB ;
$syscontext = context_system :: instance ();
require_capability ( 'moodle/site:config' , $syscontext );
$block = false ;
if ( is_int ( $blockidorname )) {
$block = $DB -> get_record ( 'block' , array ( 'id' => $blockidorname ), 'id, name' , MUST_EXIST );
} else {
$block = $DB -> get_record ( 'block' , array ( 'name' => $blockidorname ), 'id, name' , MUST_EXIST );
}
$undeletableblocktypes = self :: get_undeletable_block_types ();
if ( in_array ( $block -> name , $undeletableblocktypes )) {
$undeletableblocktypes = array_diff ( $undeletableblocktypes , array ( $block -> name ));
set_config ( 'undeletableblocktypes' , implode ( ',' , $undeletableblocktypes ));
}
}
/**
* Get the list of " protected " blocks via admin block manager ui .
*
2012-10-10 14:28:45 +01:00
* @ return array names of block types that cannot be added or deleted . E . g . array ( 'navigation' , 'settings' ) .
*/
public static function get_undeletable_block_types () {
2016-10-12 16:50:46 +08:00
global $CFG , $PAGE ;
$undeletableblocks = false ;
if ( isset ( $CFG -> undeletableblocktypes )) {
$undeletableblocks = $CFG -> undeletableblocktypes ;
}
2012-10-31 14:28:24 +08:00
2016-12-02 10:00:43 +08:00
if ( empty ( $undeletableblocks )) {
2016-10-25 08:30:59 +08:00
return array ();
2016-10-12 16:50:46 +08:00
} else if ( is_string ( $undeletableblocks )) {
return explode ( ',' , $undeletableblocks );
2012-10-10 14:28:45 +01:00
} else {
2016-10-12 16:50:46 +08:00
return $undeletableblocks ;
2012-10-10 14:28:45 +01:00
}
}
2009-05-06 09:14:01 +00:00
/// Setter methods =============================================================
/**
2009-05-22 02:18:49 +00:00
* Add a region to a page
*
2014-03-31 11:46:18 +13:00
* @ param string $region add a named region where blocks may appear on the current page .
* This is an internal name , like 'side-pre' , not a string to display in the UI .
* @ param bool $custom True if this is a custom block region , being added by the page rather than the theme layout .
2009-05-06 09:14:01 +00:00
*/
2014-03-31 11:46:18 +13:00
public function add_region ( $region , $custom = true ) {
global $SESSION ;
2009-05-06 09:14:01 +00:00
$this -> check_not_yet_loaded ();
2014-03-31 11:46:18 +13:00
if ( $custom ) {
if ( array_key_exists ( $region , $this -> regions )) {
// This here is EXACTLY why we should not be adding block regions into a page. It should
// ALWAYS be done in a theme layout.
debugging ( 'A custom region conflicts with a block region in the theme.' , DEBUG_DEVELOPER );
}
// We need to register this custom region against the page type being used.
// This allows us to check, when performing block actions, that unrecognised regions can be worked with.
$type = $this -> page -> pagetype ;
if ( ! isset ( $SESSION -> custom_block_regions )) {
$SESSION -> custom_block_regions = array ( $type => array ( $region ));
} else if ( ! isset ( $SESSION -> custom_block_regions [ $type ])) {
$SESSION -> custom_block_regions [ $type ] = array ( $region );
} else if ( ! in_array ( $region , $SESSION -> custom_block_regions [ $type ])) {
$SESSION -> custom_block_regions [ $type ][] = $region ;
}
}
2009-05-06 09:14:01 +00:00
$this -> regions [ $region ] = 1 ;
}
/**
2009-05-22 02:18:49 +00:00
* Add an array of regions
* @ see add_region ()
*
2009-05-06 09:14:01 +00:00
* @ param array $regions this utility method calls add_region for each array element .
*/
2014-03-31 11:46:18 +13:00
public function add_regions ( $regions , $custom = true ) {
2009-05-06 09:14:01 +00:00
foreach ( $regions as $region ) {
2014-03-31 11:46:18 +13:00
$this -> add_region ( $region , $custom );
}
}
/**
* Finds custom block regions associated with a page type and registers them with this block manager .
*
* @ param string $pagetype
*/
public function add_custom_regions_for_pagetype ( $pagetype ) {
global $SESSION ;
if ( isset ( $SESSION -> custom_block_regions [ $pagetype ])) {
foreach ( $SESSION -> custom_block_regions [ $pagetype ] as $customregion ) {
$this -> add_region ( $customregion , false );
}
2009-05-06 09:14:01 +00:00
}
}
/**
2009-05-22 02:18:49 +00:00
* Set the default region for new blocks on the page
*
2009-05-06 09:14:01 +00:00
* @ param string $defaultregion the internal names of the region where new
* blocks should be added by default , and where any blocks from an
* unrecognised region are shown .
*/
public function set_default_region ( $defaultregion ) {
$this -> check_not_yet_loaded ();
2009-09-30 22:35:48 +00:00
if ( $defaultregion ) {
$this -> check_region_is_known ( $defaultregion );
}
2009-05-06 09:14:01 +00:00
$this -> defaultregion = $defaultregion ;
}
2009-07-09 07:35:03 +00:00
/**
* Add something that looks like a block , but which isn ' t an actual block_instance ,
* to this page .
*
2010-12-13 13:23:49 +00:00
* @ param block_contents $bc the content of the block - like thing .
2009-07-09 07:35:03 +00:00
* @ param string $region a block region that exists on this page .
*/
2010-12-13 13:23:49 +00:00
public function add_fake_block ( $bc , $region ) {
2009-07-09 07:35:03 +00:00
$this -> page -> initialise_theme_and_output ();
2010-11-05 03:45:32 +00:00
if ( ! $this -> is_known_region ( $region )) {
$region = $this -> get_default_region ();
}
2009-07-09 07:35:03 +00:00
if ( array_key_exists ( $region , $this -> visibleblockcontent )) {
throw new coding_exception ( 'block_manager has already prepared the blocks in region ' .
2010-12-13 13:23:49 +00:00
$region . 'for output. It is too late to add a fake block.' );
2009-07-09 07:35:03 +00:00
}
2013-07-05 15:44:23 +12:00
if ( ! isset ( $bc -> attributes [ 'data-block' ])) {
$bc -> attributes [ 'data-block' ] = '_fake' ;
}
2014-04-10 18:41:50 +01:00
$bc -> attributes [ 'class' ] .= ' block_fake' ;
2009-07-09 07:35:03 +00:00
$this -> extracontent [ $region ][] = $bc ;
}
2010-05-31 03:33:34 +00:00
/**
* Checks to see whether all of the blocks within the given region are docked
*
2010-09-08 09:01:15 +00:00
* @ see region_uses_dock
2010-05-31 03:33:34 +00:00
* @ param string $region
* @ return bool True if all of the blocks within that region are docked
*/
public function region_completely_docked ( $region , $output ) {
2012-10-04 17:25:45 +08:00
global $CFG ;
// If theme doesn't allow docking or allowblockstodock is not set, then return.
if ( ! $this -> page -> theme -> enable_dock || empty ( $CFG -> allowblockstodock )) {
2010-05-31 03:33:34 +00:00
return false ;
}
2012-08-05 15:06:04 -05:00
// Do not dock the region when the user attemps to move a block.
if ( $this -> movingblock ) {
return false ;
}
2015-01-19 15:45:44 +00:00
// Block regions should not be docked during editing when all the blocks are hidden.
if ( $this -> page -> user_is_editing () && $this -> page -> user_can_edit_blocks ()) {
return false ;
}
2010-05-31 03:33:34 +00:00
$this -> check_is_loaded ();
$this -> ensure_content_created ( $region , $output );
2014-04-11 13:38:03 +12:00
if ( ! $this -> region_has_content ( $region , $output )) {
// If the region has no content then nothing is docked at all of course.
return false ;
}
foreach ( $this -> visibleblockcontent [ $region ] as $instance ) {
2015-01-08 14:58:26 +08:00
if ( ! get_user_preferences ( 'docked_block_instance_' . $instance -> blockinstanceid , 0 )) {
2010-05-31 03:33:34 +00:00
return false ;
}
}
return true ;
}
2010-09-08 09:01:15 +00:00
/**
* Checks to see whether any of the blocks within the given regions are docked
*
* @ see region_completely_docked
* @ param array | string $regions array of regions ( or single region )
* @ return bool True if any of the blocks within that region are docked
*/
public function region_uses_dock ( $regions , $output ) {
if ( ! $this -> page -> theme -> enable_dock ) {
return false ;
}
$this -> check_is_loaded ();
foreach (( array ) $regions as $region ) {
$this -> ensure_content_created ( $region , $output );
foreach ( $this -> visibleblockcontent [ $region ] as $instance ) {
if ( ! empty ( $instance -> content ) && get_user_preferences ( 'docked_block_instance_' . $instance -> blockinstanceid , 0 )) {
return true ;
}
}
}
return false ;
}
2009-05-06 09:14:42 +00:00
/// Actions ====================================================================
/**
* This method actually loads the blocks for our page from the database .
2009-05-22 02:18:49 +00:00
*
2009-07-15 07:41:25 +00:00
* @ param boolean | null $includeinvisible
* null ( default ) - load hidden blocks if $this -> page -> user_is_editing ();
* true - load hidden blocks .
* false - don ' t load hidden blocks .
2009-05-06 09:14:42 +00:00
*/
2009-07-15 07:41:25 +00:00
public function load_blocks ( $includeinvisible = null ) {
2009-05-07 02:56:48 +00:00
global $DB , $CFG ;
2009-09-30 16:24:05 +00:00
2009-05-06 09:15:05 +00:00
if ( ! is_null ( $this -> birecordsbyregion )) {
// Already done.
return ;
}
2009-05-06 09:14:42 +00:00
2009-05-07 02:56:48 +00:00
if ( $CFG -> version < 2009050619 ) {
// Upgrade/install not complete. Don't try too show any blocks.
$this -> birecordsbyregion = array ();
return ;
}
2009-07-09 07:35:03 +00:00
// Ensure we have been initialised.
2009-09-30 16:24:05 +00:00
if ( is_null ( $this -> defaultregion )) {
2009-07-01 05:54:26 +00:00
$this -> page -> initialise_theme_and_output ();
2009-07-09 07:35:03 +00:00
// If there are still no block regions, then there are no blocks on this page.
if ( empty ( $this -> regions )) {
$this -> birecordsbyregion = array ();
return ;
}
2009-07-01 05:54:26 +00:00
}
2010-05-21 03:15:48 +00:00
// Check if we need to load normal blocks
if ( $this -> fakeblocksonly ) {
$this -> birecordsbyregion = $this -> prepare_per_region_arrays ();
return ;
}
2016-11-18 21:36:52 +08:00
// Exclude auto created blocks if they are not undeletable in this theme.
2016-12-02 10:00:43 +08:00
$requiredbytheme = $this -> get_required_by_theme_block_types ();
$requiredbythemecheck = '' ;
$requiredbythemeparams = array ();
$requiredbythemenotparams = array ();
if ( ! empty ( $requiredbytheme )) {
list ( $testsql , $requiredbythemeparams ) = $DB -> get_in_or_equal ( $requiredbytheme , SQL_PARAMS_NAMED , 'requiredbytheme' );
list ( $testnotsql , $requiredbythemenotparams ) = $DB -> get_in_or_equal ( $requiredbytheme , SQL_PARAMS_NAMED ,
'notrequiredbytheme' , false );
$requiredbythemecheck = 'AND ((bi.blockname ' . $testsql . ' AND bi.requiredbytheme = 1) OR ' .
2016-11-18 21:36:52 +08:00
' (bi.blockname ' . $testnotsql . ' AND bi.requiredbytheme = 0))' ;
} else {
2016-12-02 10:00:43 +08:00
$requiredbythemecheck = 'AND (bi.requiredbytheme = 0)' ;
2016-11-18 21:36:52 +08:00
}
2009-05-06 09:14:42 +00:00
if ( is_null ( $includeinvisible )) {
$includeinvisible = $this -> page -> user_is_editing ();
}
if ( $includeinvisible ) {
$visiblecheck = '' ;
2009-07-15 07:41:25 +00:00
} else {
$visiblecheck = 'AND (bp.visible = 1 OR bp.visible IS NULL)' ;
2009-05-06 09:14:42 +00:00
}
$context = $this -> page -> context ;
2015-06-29 11:34:10 +01:00
$contexttest = 'bi.parentcontextid IN (:contextid2, :contextid3)' ;
2009-05-06 09:14:42 +00:00
$parentcontextparams = array ();
2013-07-04 11:07:12 +08:00
$parentcontextids = $context -> get_parent_context_ids ();
2009-05-06 09:14:42 +00:00
if ( $parentcontextids ) {
list ( $parentcontexttest , $parentcontextparams ) =
2011-04-14 15:13:28 +02:00
$DB -> get_in_or_equal ( $parentcontextids , SQL_PARAMS_NAMED , 'parentcontext' );
2009-07-10 05:58:59 +00:00
$contexttest = " ( $contexttest OR (bi.showinsubcontexts = 1 AND bi.parentcontextid $parentcontexttest )) " ;
2009-05-06 09:14:42 +00:00
}
2009-07-16 10:50:19 +00:00
$pagetypepatterns = matching_page_type_patterns ( $this -> page -> pagetype );
2009-05-06 09:14:42 +00:00
list ( $pagetypepatterntest , $pagetypepatternparams ) =
2011-04-14 15:13:28 +02:00
$DB -> get_in_or_equal ( $pagetypepatterns , SQL_PARAMS_NAMED , 'pagetypepatterntest' );
2009-05-06 09:14:42 +00:00
2013-07-05 13:02:00 +08:00
$ccselect = ', ' . context_helper :: get_preload_record_columns_sql ( 'ctx' );
$ccjoin = " LEFT JOIN { context} ctx ON (ctx.instanceid = bi.id AND ctx.contextlevel = :contextlevel) " ;
2010-03-31 07:41:31 +00:00
2015-07-21 15:41:39 +01:00
$systemcontext = context_system :: instance ();
2009-05-06 09:14:42 +00:00
$params = array (
2013-07-05 13:02:00 +08:00
'contextlevel' => CONTEXT_BLOCK ,
2009-05-06 09:14:42 +00:00
'subpage1' => $this -> page -> subpage ,
'subpage2' => $this -> page -> subpage ,
'contextid1' => $context -> id ,
'contextid2' => $context -> id ,
2015-06-29 11:34:10 +01:00
'contextid3' => $systemcontext -> id ,
2009-05-06 09:14:42 +00:00
'pagetype' => $this -> page -> pagetype ,
);
2011-02-26 11:26:13 +00:00
if ( $this -> page -> subpage === '' ) {
2013-01-28 18:57:46 +01:00
$params [ 'subpage1' ] = '' ;
$params [ 'subpage2' ] = '' ;
2011-02-26 11:26:13 +00:00
}
2009-05-06 09:14:42 +00:00
$sql = " SELECT
bi . id ,
2009-07-09 07:35:03 +00:00
bp . id AS blockpositionid ,
2009-05-06 09:14:42 +00:00
bi . blockname ,
2009-07-10 05:58:59 +00:00
bi . parentcontextid ,
2009-05-06 09:14:42 +00:00
bi . showinsubcontexts ,
bi . pagetypepattern ,
2016-11-18 21:36:52 +08:00
bi . requiredbytheme ,
2009-05-06 09:14:42 +00:00
bi . subpagepattern ,
2009-07-15 07:41:25 +00:00
bi . defaultregion ,
bi . defaultweight ,
2009-05-06 09:15:05 +00:00
COALESCE ( bp . visible , 1 ) AS visible ,
2009-05-06 09:14:42 +00:00
COALESCE ( bp . region , bi . defaultregion ) AS region ,
COALESCE ( bp . weight , bi . defaultweight ) AS weight ,
2010-03-31 07:41:31 +00:00
bi . configdata
$ccselect
2009-05-06 09:14:42 +00:00
FROM { block_instances } bi
JOIN { block } b ON bi . blockname = b . name
LEFT JOIN { block_positions } bp ON bp . blockinstanceid = bi . id
AND bp . contextid = : contextid1
AND bp . pagetype = : pagetype
AND bp . subpage = : subpage1
2010-03-31 07:41:31 +00:00
$ccjoin
2009-05-06 09:14:42 +00:00
WHERE
$contexttest
AND bi . pagetypepattern $pagetypepatterntest
AND ( bi . subpagepattern IS NULL OR bi . subpagepattern = : subpage2 )
$visiblecheck
AND b . visible = 1
2016-12-02 10:00:43 +08:00
$requiredbythemecheck
2009-05-06 09:14:42 +00:00
ORDER BY
COALESCE ( bp . region , bi . defaultregion ),
COALESCE ( bp . weight , bi . defaultweight ),
bi . id " ;
2016-11-18 21:36:52 +08:00
2016-12-02 10:00:43 +08:00
$allparams = $params + $parentcontextparams + $pagetypepatternparams + $requiredbythemeparams + $requiredbythemenotparams ;
2016-11-18 21:36:52 +08:00
$blockinstances = $DB -> get_recordset_sql ( $sql , $allparams );
2009-05-06 09:14:42 +00:00
2009-05-06 09:15:05 +00:00
$this -> birecordsbyregion = $this -> prepare_per_region_arrays ();
2009-05-06 09:14:42 +00:00
$unknown = array ();
foreach ( $blockinstances as $bi ) {
2013-07-05 11:48:36 +08:00
context_helper :: preload_from_record ( $bi );
2009-05-06 09:14:42 +00:00
if ( $this -> is_known_region ( $bi -> region )) {
2009-05-06 09:15:05 +00:00
$this -> birecordsbyregion [ $bi -> region ][] = $bi ;
2009-05-06 09:14:42 +00:00
} else {
$unknown [] = $bi ;
}
}
2009-07-09 07:35:03 +00:00
// Pages don't necessarily have a defaultregion. The one time this can
// happen is when there are no theme block regions, but the script itself
// has a block region in the main content area.
if ( ! empty ( $this -> defaultregion )) {
$this -> birecordsbyregion [ $this -> defaultregion ] =
array_merge ( $this -> birecordsbyregion [ $this -> defaultregion ], $unknown );
}
2009-05-06 09:14:42 +00:00
}
/**
* Add a block to the current page , or related pages . The block is added to
* context $this -> page -> contextid . If $pagetypepattern $subpagepattern
2009-05-22 02:18:49 +00:00
*
2009-05-06 09:14:42 +00:00
* @ param string $blockname The type of block to add .
* @ param string $region the block region on this page to add the block to .
* @ param integer $weight determines the order where this block appears in the region .
* @ param boolean $showinsubcontexts whether this block appears in subcontexts , or just the current context .
* @ param string | null $pagetypepattern which page types this block should appear on . Defaults to just the current page type .
* @ param string | null $subpagepattern which subpage this block should appear on . NULL = any ( the default ), otherwise only the specified subpage .
*/
public function add_block ( $blockname , $region , $weight , $showinsubcontexts , $pagetypepattern = NULL , $subpagepattern = NULL ) {
global $DB ;
2010-09-01 17:36:46 +00:00
// Allow invisible blocks because this is used when adding default page blocks, which
// might include invisible ones if the user makes some default blocks invisible
$this -> check_known_block_type ( $blockname , true );
2009-05-06 09:14:42 +00:00
$this -> check_region_is_known ( $region );
if ( empty ( $pagetypepattern )) {
$pagetypepattern = $this -> page -> pagetype ;
}
$blockinstance = new stdClass ;
$blockinstance -> blockname = $blockname ;
2009-07-10 05:58:59 +00:00
$blockinstance -> parentcontextid = $this -> page -> context -> id ;
2009-05-06 09:14:42 +00:00
$blockinstance -> showinsubcontexts = ! empty ( $showinsubcontexts );
$blockinstance -> pagetypepattern = $pagetypepattern ;
$blockinstance -> subpagepattern = $subpagepattern ;
$blockinstance -> defaultregion = $region ;
$blockinstance -> defaultweight = $weight ;
$blockinstance -> configdata = '' ;
2009-05-07 09:16:22 +00:00
$blockinstance -> id = $DB -> insert_record ( 'block_instances' , $blockinstance );
2009-07-13 08:37:34 +00:00
// Ensure the block context is created.
2012-07-25 16:25:55 +08:00
context_block :: instance ( $blockinstance -> id );
2009-05-08 07:47:50 +00:00
2009-05-07 09:16:22 +00:00
// If the new instance was created, allow it to do additional setup
2009-07-13 08:37:34 +00:00
if ( $block = block_instance ( $blockname , $blockinstance )) {
2009-05-07 09:16:22 +00:00
$block -> instance_create ();
}
2009-05-06 09:14:42 +00:00
}
2009-07-14 07:18:57 +00:00
public function add_block_at_end_of_default_region ( $blockname ) {
2016-10-12 16:50:46 +08:00
if ( empty ( $this -> birecordsbyregion )) {
// No blocks or block regions exist yet.
return ;
}
2009-07-14 07:18:57 +00:00
$defaulregion = $this -> get_default_region ();
2009-07-14 09:28:10 +00:00
2009-07-14 07:18:57 +00:00
$lastcurrentblock = end ( $this -> birecordsbyregion [ $defaulregion ]);
2009-07-14 09:28:10 +00:00
if ( $lastcurrentblock ) {
$weight = $lastcurrentblock -> weight + 1 ;
} else {
$weight = 0 ;
}
2009-07-14 07:18:57 +00:00
if ( $this -> page -> subpage ) {
$subpage = $this -> page -> subpage ;
} else {
$subpage = null ;
}
2009-07-14 08:37:28 +00:00
// Special case. Course view page type include the course format, but we
// want to add the block non-format-specifically.
$pagetypepattern = $this -> page -> pagetype ;
if ( strpos ( $pagetypepattern , 'course-view' ) === 0 ) {
$pagetypepattern = 'course-view-*' ;
}
2011-07-01 18:29:39 +02:00
// We should end using this for ALL the blocks, making always the 1st option
// the default one to be used. Until then, this is one hack to avoid the
// 'pagetypewarning' message on blocks initial edition (MDL-27829) caused by
// non-existing $pagetypepattern set. This way at least we guarantee one "valid"
// (the FIRST $pagetypepattern will be set)
// We are applying it to all blocks created in mod pages for now and only if the
// default pagetype is not one of the available options
if ( preg_match ( '/^mod-.*-/' , $pagetypepattern )) {
$pagetypelist = generate_page_type_patterns ( $this -> page -> pagetype , null , $this -> page -> context );
// Only go for the first if the pagetype is not a valid option
if ( is_array ( $pagetypelist ) && ! array_key_exists ( $pagetypepattern , $pagetypelist )) {
$pagetypepattern = key ( $pagetypelist );
}
}
// Surely other pages like course-report will need this too, they just are not important
// enough now. This will be decided in the coming days. (MDL-27829, MDL-28150)
2009-07-14 09:28:10 +00:00
$this -> add_block ( $blockname , $defaulregion , $weight , false , $pagetypepattern , $subpage );
2009-07-14 07:18:57 +00:00
}
2009-05-07 07:05:22 +00:00
/**
2015-02-09 09:41:32 +00:00
* Convenience method , calls add_block repeatedly for all the blocks in $blocks . Optionally , a starting weight
* can be used to decide the starting point that blocks are added in the region , the weight is passed to { @ link add_block }
* and incremented by the position of the block in the $blocks array
2009-05-22 02:18:49 +00:00
*
2009-07-14 09:28:10 +00:00
* @ param array $blocks array with array keys the region names , and values an array of block names .
2015-02-09 09:41:32 +00:00
* @ param string $pagetypepattern optional . Passed to { @ link add_block ()}
* @ param string $subpagepattern optional . Passed to { @ link add_block ()}
* @ param boolean $showinsubcontexts optional . Passed to { @ link add_block ()}
* @ param integer $weight optional . Determines the starting point that the blocks are added in the region .
2009-05-07 07:05:22 +00:00
*/
2009-08-28 08:47:31 +00:00
public function add_blocks ( $blocks , $pagetypepattern = NULL , $subpagepattern = NULL , $showinsubcontexts = false , $weight = 0 ) {
2015-02-09 09:41:32 +00:00
$initialweight = $weight ;
2014-03-31 11:46:18 +13:00
$this -> add_regions ( array_keys ( $blocks ), false );
2009-05-07 07:05:22 +00:00
foreach ( $blocks as $region => $regionblocks ) {
2015-02-09 09:41:32 +00:00
foreach ( $regionblocks as $offset => $blockname ) {
$weight = $initialweight + $offset ;
2009-08-28 08:47:31 +00:00
$this -> add_block ( $blockname , $region , $weight , $showinsubcontexts , $pagetypepattern , $subpagepattern );
2009-05-07 07:05:22 +00:00
}
}
}
2009-07-30 10:29:14 +00:00
/**
* Move a block to a new position on this page .
*
* If this block cannot appear on any other pages , then we change defaultposition / weight
2010-08-28 11:54:24 +00:00
* in the block_instances table . Otherwise we just set the position on this page .
2009-07-30 10:29:14 +00:00
*
* @ param $blockinstanceid the block instance id .
* @ param $newregion the new region name .
* @ param $newweight the new weight .
*/
public function reposition_block ( $blockinstanceid , $newregion , $newweight ) {
global $DB ;
$this -> check_region_is_known ( $newregion );
$inst = $this -> find_instance ( $blockinstanceid );
$bi = $inst -> instance ;
if ( $bi -> weight == $bi -> defaultweight && $bi -> region == $bi -> defaultregion &&
! $bi -> showinsubcontexts && strpos ( $bi -> pagetypepattern , '*' ) === false &&
( ! $this -> page -> subpage || $bi -> subpagepattern )) {
// Set default position
$newbi = new stdClass ;
$newbi -> id = $bi -> id ;
$newbi -> defaultregion = $newregion ;
$newbi -> defaultweight = $newweight ;
$DB -> update_record ( 'block_instances' , $newbi );
if ( $bi -> blockpositionid ) {
$bp = new stdClass ;
$bp -> id = $bi -> blockpositionid ;
$bp -> region = $newregion ;
$bp -> weight = $newweight ;
$DB -> update_record ( 'block_positions' , $bp );
}
} else {
// Just set position on this page.
$bp = new stdClass ;
$bp -> region = $newregion ;
$bp -> weight = $newweight ;
if ( $bi -> blockpositionid ) {
$bp -> id = $bi -> blockpositionid ;
$DB -> update_record ( 'block_positions' , $bp );
} else {
$bp -> blockinstanceid = $bi -> id ;
$bp -> contextid = $this -> page -> context -> id ;
$bp -> pagetype = $this -> page -> pagetype ;
if ( $this -> page -> subpage ) {
$bp -> subpage = $this -> page -> subpage ;
} else {
$bp -> subpage = '' ;
}
$bp -> visible = $bi -> visible ;
$DB -> insert_record ( 'block_positions' , $bp );
}
}
}
2009-05-08 06:34:40 +00:00
/**
2009-07-28 09:59:21 +00:00
* Find a given block by its instance id
2009-05-22 02:18:49 +00:00
*
2009-05-08 06:34:40 +00:00
* @ param integer $instanceid
2012-10-10 14:28:45 +01:00
* @ return block_base
2009-05-08 06:34:40 +00:00
*/
public function find_instance ( $instanceid ) {
foreach ( $this -> regions as $region => $notused ) {
$this -> ensure_instances_exist ( $region );
foreach ( $this -> blockinstances [ $region ] as $instance ) {
if ( $instance -> instance -> id == $instanceid ) {
return $instance ;
}
}
}
throw new block_not_on_page_exception ( $instanceid , $this -> page );
}
2009-05-06 09:14:01 +00:00
/// Inner workings =============================================================
2009-05-22 02:18:49 +00:00
/**
* Check whether the page blocks have been loaded yet
*
* @ return void Throws coding exception if already loaded
*/
2009-05-06 09:14:01 +00:00
protected function check_not_yet_loaded () {
2009-05-06 09:15:05 +00:00
if ( ! is_null ( $this -> birecordsbyregion )) {
2009-05-06 09:14:01 +00:00
throw new coding_exception ( 'block_manager has already loaded the blocks, to it is too late to change things that might affect which blocks are visible.' );
}
}
2009-05-22 02:18:49 +00:00
/**
* Check whether the page blocks have been loaded yet
*
* Nearly identical to the above function { @ link check_not_yet_loaded ()} except different message
*
* @ return void Throws coding exception if already loaded
*/
2009-05-06 09:14:42 +00:00
protected function check_is_loaded () {
2009-05-06 09:15:05 +00:00
if ( is_null ( $this -> birecordsbyregion )) {
2009-05-06 09:14:42 +00:00
throw new coding_exception ( 'block_manager has not yet loaded the blocks, to it is too soon to request the information you asked for.' );
}
}
2009-05-22 02:18:49 +00:00
/**
* Check if a block type is known and usable
*
* @ param string $blockname The block type name to search for
2010-08-28 11:54:24 +00:00
* @ param bool $includeinvisible Include disabled block types in the initial pass
2009-05-22 02:18:49 +00:00
* @ return void Coding Exception thrown if unknown or not enabled
*/
2009-05-06 09:14:42 +00:00
protected function check_known_block_type ( $blockname , $includeinvisible = false ) {
if ( ! $this -> is_known_block_type ( $blockname , $includeinvisible )) {
if ( $this -> is_known_block_type ( $blockname , true )) {
throw new coding_exception ( 'Unknown block type ' . $blockname );
} else {
throw new coding_exception ( 'Block type ' . $blockname . ' has been disabled by the administrator.' );
}
}
}
2009-05-22 02:18:49 +00:00
/**
* Check if a region is known by its name
*
* @ param string $region
* @ return void Coding Exception thrown if the region is not known
*/
2009-05-06 09:14:42 +00:00
protected function check_region_is_known ( $region ) {
if ( ! $this -> is_known_region ( $region )) {
throw new coding_exception ( 'Trying to reference an unknown block region ' . $region );
}
2009-05-06 09:14:01 +00:00
}
2009-05-06 09:15:05 +00:00
/**
2009-05-22 02:18:49 +00:00
* Returns an array of region names as keys and nested arrays for values
*
2009-05-06 09:15:05 +00:00
* @ return array an array where the array keys are the region names , and the array
* values are empty arrays .
*/
protected function prepare_per_region_arrays () {
$result = array ();
foreach ( $this -> regions as $region => $notused ) {
$result [ $region ] = array ();
}
return $result ;
}
2009-05-22 02:18:49 +00:00
/**
* Create a set of new block instance from a record array
*
* @ param array $birecords An array of block instance records
* @ return array An array of instantiated block_instance objects
*/
2009-05-06 09:15:05 +00:00
protected function create_block_instances ( $birecords ) {
$results = array ();
foreach ( $birecords as $record ) {
2009-08-22 11:24:39 +00:00
if ( $blockobject = block_instance ( $record -> blockname , $record , $this -> page )) {
$results [] = $blockobject ;
}
2009-05-06 09:15:05 +00:00
}
return $results ;
}
2009-07-20 03:04:08 +00:00
/**
2010-08-28 11:54:24 +00:00
* Create all the block instances for all the blocks that were loaded by
2009-07-20 03:04:08 +00:00
* load_blocks . This is used , for example , to ensure that all blocks get a
* chance to initialise themselves via the { @ link block_base :: specialize ()}
* method , before any output is done .
2016-11-18 21:36:52 +08:00
*
2016-12-02 10:00:43 +08:00
* It is also used to create any blocks that are " requiredbytheme " by the current theme .
2016-11-18 21:36:52 +08:00
* These blocks that are auto - created have requiredbytheme set on the block instance
* so they are only visible on themes that require them .
2009-07-20 03:04:08 +00:00
*/
public function create_all_block_instances () {
2016-10-12 16:50:46 +08:00
global $PAGE ;
2016-10-25 08:30:59 +08:00
$missing = false ;
2016-10-12 16:50:46 +08:00
// If there are any un-removable blocks that were not created - force them.
2016-12-02 10:00:43 +08:00
$requiredbytheme = $this -> get_required_by_theme_block_types ();
2016-11-23 11:07:32 +08:00
if ( ! $this -> fakeblocksonly ) {
2016-12-02 10:00:43 +08:00
foreach ( $requiredbytheme as $forced ) {
2016-11-23 11:07:32 +08:00
if ( empty ( $forced )) {
continue ;
}
$found = false ;
foreach ( $this -> get_regions () as $region ) {
foreach ( $this -> birecordsbyregion [ $region ] as $instance ) {
if ( $instance -> blockname == $forced ) {
$found = true ;
}
2016-10-12 16:50:46 +08:00
}
}
2016-11-23 11:07:32 +08:00
if ( ! $found ) {
$this -> add_block_required_by_theme ( $forced );
$missing = true ;
}
2016-10-12 16:50:46 +08:00
}
}
2016-10-25 08:30:59 +08:00
if ( $missing ) {
// Some blocks were missing. Lets do it again.
$this -> birecordsbyregion = null ;
$this -> load_blocks ();
}
2009-07-20 03:04:08 +00:00
foreach ( $this -> get_regions () as $region ) {
$this -> ensure_instances_exist ( $region );
}
2016-10-12 16:50:46 +08:00
2009-07-20 03:04:08 +00:00
}
2016-11-18 21:36:52 +08:00
/**
* Add a block that is required by the current theme but has not been
* created yet . This is a special type of block that only shows in themes that
* require it ( by listing it in undeletable_block_types ) .
*
* @ param string $blockname the name of the block type .
*/
protected function add_block_required_by_theme ( $blockname ) {
global $DB ;
if ( empty ( $this -> birecordsbyregion )) {
// No blocks or block regions exist yet.
return ;
}
2016-11-23 11:07:32 +08:00
// Never auto create blocks when we are showing fake blocks only.
if ( $this -> fakeblocksonly ) {
return ;
}
2016-11-28 14:46:32 +08:00
// Never add a duplicate block required by theme.
if ( $DB -> record_exists ( 'block_instances' , array ( 'blockname' => $blockname , 'requiredbytheme' => 1 ))) {
return ;
}
2016-11-18 21:36:52 +08:00
$systemcontext = context_system :: instance ();
$defaultregion = $this -> get_default_region ();
// Add a special system wide block instance only for themes that require it.
$blockinstance = new stdClass ;
$blockinstance -> blockname = $blockname ;
$blockinstance -> parentcontextid = $systemcontext -> id ;
$blockinstance -> showinsubcontexts = true ;
$blockinstance -> requiredbytheme = true ;
$blockinstance -> pagetypepattern = '*' ;
$blockinstance -> subpagepattern = null ;
$blockinstance -> defaultregion = $defaultregion ;
$blockinstance -> defaultweight = 0 ;
$blockinstance -> configdata = '' ;
$blockinstance -> id = $DB -> insert_record ( 'block_instances' , $blockinstance );
// Ensure the block context is created.
context_block :: instance ( $blockinstance -> id );
// If the new instance was created, allow it to do additional setup.
if ( $block = block_instance ( $blockname , $blockinstance )) {
$block -> instance_create ();
}
}
2009-05-22 02:18:49 +00:00
/**
2009-07-30 08:22:12 +00:00
* Return an array of content objects from a set of block instances
2009-05-22 02:18:49 +00:00
*
* @ param array $instances An array of block instances
2009-12-16 18:00:58 +00:00
* @ param renderer_base The renderer to use .
2009-07-30 08:22:12 +00:00
* @ param string $region the region name .
* @ return array An array of block_content ( and possibly block_move_target ) objects .
2009-05-22 02:18:49 +00:00
*/
2009-07-30 08:22:12 +00:00
protected function create_block_contents ( $instances , $output , $region ) {
2009-05-06 09:15:05 +00:00
$results = array ();
2009-07-30 08:22:12 +00:00
$lastweight = 0 ;
$lastblock = 0 ;
if ( $this -> movingblock ) {
$first = reset ( $instances );
if ( $first ) {
$lastweight = $first -> instance -> weight - 2 ;
}
}
2009-05-06 09:15:05 +00:00
foreach ( $instances as $instance ) {
2009-07-09 07:35:03 +00:00
$content = $instance -> get_content_for_output ( $output );
2009-07-30 08:22:12 +00:00
if ( empty ( $content )) {
continue ;
}
if ( $this -> movingblock && $lastweight != $instance -> instance -> weight &&
$content -> blockinstanceid != $this -> movingblock && $lastblock != $this -> movingblock ) {
2013-03-11 14:56:35 +08:00
$results [] = new block_move_target ( $this -> get_move_target_url ( $region , ( $lastweight + $instance -> instance -> weight ) / 2 ));
2009-07-30 08:22:12 +00:00
}
if ( $content -> blockinstanceid == $this -> movingblock ) {
$content -> add_class ( 'beingmoved' );
$content -> annotation .= get_string ( 'movingthisblockcancel' , 'block' ,
2010-02-11 16:27:53 +00:00
html_writer :: link ( $this -> page -> url , get_string ( 'cancel' )));
2009-05-06 09:15:05 +00:00
}
2009-07-30 08:22:12 +00:00
$results [] = $content ;
$lastweight = $instance -> instance -> weight ;
$lastblock = $instance -> instance -> id ;
}
if ( $this -> movingblock && $lastblock != $this -> movingblock ) {
2013-03-11 14:56:35 +08:00
$results [] = new block_move_target ( $this -> get_move_target_url ( $region , $lastweight + 1 ));
2009-05-06 09:15:05 +00:00
}
return $results ;
}
2009-05-22 02:18:49 +00:00
/**
* Ensure block instances exist for a given region
2009-07-28 09:59:21 +00:00
*
2009-05-22 02:18:49 +00:00
* @ param string $region Check for bi ' s with the instance with this name
*/
2009-05-06 09:15:05 +00:00
protected function ensure_instances_exist ( $region ) {
$this -> check_region_is_known ( $region );
if ( ! array_key_exists ( $region , $this -> blockinstances )) {
$this -> blockinstances [ $region ] =
$this -> create_block_instances ( $this -> birecordsbyregion [ $region ]);
}
}
2009-05-22 02:18:49 +00:00
/**
* Ensure that there is some content within the given region
*
* @ param string $region The name of the region to check
*/
2013-09-01 23:52:58 +01:00
public function ensure_content_created ( $region , $output ) {
2009-05-06 09:15:05 +00:00
$this -> ensure_instances_exist ( $region );
if ( ! array_key_exists ( $region , $this -> visibleblockcontent )) {
2009-07-09 07:35:03 +00:00
$contents = array ();
if ( array_key_exists ( $region , $this -> extracontent )) {
$contents = $this -> extracontent [ $region ];
}
2009-07-30 08:22:12 +00:00
$contents = array_merge ( $contents , $this -> create_block_contents ( $this -> blockinstances [ $region ], $output , $region ));
2016-11-18 17:27:38 +08:00
if (( $region == $this -> defaultregion ) && ( ! isset ( $this -> page -> theme -> addblockposition ) ||
$this -> page -> theme -> addblockposition == BLOCK_ADDBLOCK_POSITION_DEFAULT )) {
2009-07-14 07:18:57 +00:00
$addblockui = block_add_block_ui ( $this -> page , $output );
2009-07-09 07:35:03 +00:00
if ( $addblockui ) {
$contents [] = $addblockui ;
}
}
$this -> visibleblockcontent [ $region ] = $contents ;
2009-05-06 09:15:05 +00:00
}
}
2009-07-28 09:59:21 +00:00
/// Process actions from the URL ===============================================
2009-07-30 08:22:12 +00:00
/**
* Get the appropriate list of editing icons for a block . This is used
* to set { @ link block_contents :: $controls } in { @ link block_base :: get_contents_for_output ()} .
*
* @ param $output The core_renderer to use when generating the output . ( Need to get icon paths . )
* @ return an array in the format for { @ link block_contents :: $controls }
*/
public function edit_controls ( $block ) {
global $CFG ;
$controls = array ();
2010-01-17 09:50:55 +00:00
$actionurl = $this -> page -> url -> out ( false , array ( 'sesskey' => sesskey ()));
2013-03-08 14:28:28 +08:00
$blocktitle = $block -> title ;
if ( empty ( $blocktitle )) {
$blocktitle = $block -> arialabel ;
}
2009-07-30 08:22:12 +00:00
2011-08-04 13:23:58 +08:00
if ( $this -> page -> user_can_edit_blocks ()) {
// Move icon.
2013-07-08 11:44:32 +12:00
$str = new lang_string ( 'moveblock' , 'block' , $blocktitle );
2013-07-18 10:42:11 +12:00
$controls [] = new action_menu_link_primary (
2013-07-05 10:45:05 +12:00
new moodle_url ( $actionurl , array ( 'bui_moveid' => $block -> instance -> id )),
2013-07-08 11:44:32 +12:00
new pix_icon ( 't/move' , $str , 'moodle' , array ( 'class' => 'iconsmall' , 'title' => '' )),
$str ,
array ( 'class' => 'editing_move' )
2013-07-05 10:45:05 +12:00
);
2009-07-30 08:22:12 +00:00
}
if ( $this -> page -> user_can_edit_blocks () || $block -> user_can_edit ()) {
// Edit config icon - always show - needed for positioning UI.
2013-07-08 11:44:32 +12:00
$str = new lang_string ( 'configureblock' , 'block' , $blocktitle );
2013-10-25 14:14:03 +08:00
$controls [] = new action_menu_link_secondary (
2013-07-05 10:45:05 +12:00
new moodle_url ( $actionurl , array ( 'bui_editid' => $block -> instance -> id )),
2013-07-08 11:44:32 +12:00
new pix_icon ( 't/edit' , $str , 'moodle' , array ( 'class' => 'iconsmall' , 'title' => '' )),
$str ,
array ( 'class' => 'editing_edit' )
2013-07-05 10:45:05 +12:00
);
2009-07-30 08:22:12 +00:00
}
2011-08-04 13:23:58 +08:00
if ( $this -> page -> user_can_edit_blocks () && $block -> instance_can_be_hidden ()) {
// Show/hide icon.
if ( $block -> instance -> visible ) {
2013-07-08 11:44:32 +12:00
$str = new lang_string ( 'hideblock' , 'block' , $blocktitle );
$url = new moodle_url ( $actionurl , array ( 'bui_hideid' => $block -> instance -> id ));
$icon = new pix_icon ( 't/hide' , $str , 'moodle' , array ( 'class' => 'iconsmall' , 'title' => '' ));
$attributes = array ( 'class' => 'editing_hide' );
2011-08-04 13:23:58 +08:00
} else {
2013-07-08 11:44:32 +12:00
$str = new lang_string ( 'showblock' , 'block' , $blocktitle );
$url = new moodle_url ( $actionurl , array ( 'bui_showid' => $block -> instance -> id ));
$icon = new pix_icon ( 't/show' , $str , 'moodle' , array ( 'class' => 'iconsmall' , 'title' => '' ));
$attributes = array ( 'class' => 'editing_show' );
2011-08-04 13:23:58 +08:00
}
2013-10-25 14:14:03 +08:00
$controls [] = new action_menu_link_secondary ( $url , $icon , $str , $attributes );
2011-08-04 13:23:58 +08:00
}
2016-11-21 15:53:00 +08:00
// Assign roles.
2016-01-11 16:44:15 +08:00
if ( get_assignable_roles ( $block -> context , ROLENAME_SHORT )) {
2016-11-21 15:53:00 +08:00
$rolesurl = new moodle_url ( '/admin/roles/assign.php' , array ( 'contextid' => $block -> context -> id ,
'returnurl' => $this -> page -> url -> out_as_local_url ()));
2016-01-11 16:44:15 +08:00
$str = new lang_string ( 'assignrolesinblock' , 'block' , $blocktitle );
2016-11-21 15:53:00 +08:00
$controls [] = new action_menu_link_secondary (
$rolesurl ,
new pix_icon ( 'i/assignroles' , $str , 'moodle' , array ( 'class' => 'iconsmall' , 'title' => '' )),
$str , array ( 'class' => 'editing_assignroles' )
);
2016-01-11 16:44:15 +08:00
}
2015-08-06 10:19:55 +08:00
2016-11-21 15:53:00 +08:00
// Permissions.
if ( has_capability ( 'moodle/role:review' , $block -> context ) or get_overridable_roles ( $block -> context )) {
$rolesurl = new moodle_url ( '/admin/roles/permissions.php' , array ( 'contextid' => $block -> context -> id ,
'returnurl' => $this -> page -> url -> out_as_local_url ()));
$str = get_string ( 'permissions' , 'role' );
$controls [] = new action_menu_link_secondary (
$rolesurl ,
new pix_icon ( 'i/permissions' , $str , 'moodle' , array ( 'class' => 'iconsmall' , 'title' => '' )),
$str , array ( 'class' => 'editing_permissions' )
);
}
2016-01-11 16:44:15 +08:00
2016-11-21 15:53:00 +08:00
// Change permissions.
if ( has_any_capability ( array ( 'moodle/role:safeoverride' , 'moodle/role:override' , 'moodle/role:assign' ), $block -> context )) {
$rolesurl = new moodle_url ( '/admin/roles/check.php' , array ( 'contextid' => $block -> context -> id ,
'returnurl' => $this -> page -> url -> out_as_local_url ()));
$str = get_string ( 'checkpermissions' , 'role' );
2016-01-11 16:44:15 +08:00
$controls [] = new action_menu_link_secondary (
$rolesurl ,
2016-11-21 15:53:00 +08:00
new pix_icon ( 'i/checkpermissions' , $str , 'moodle' , array ( 'class' => 'iconsmall' , 'title' => '' )),
$str , array ( 'class' => 'editing_checkroles' )
2016-01-11 16:44:15 +08:00
);
2009-07-30 08:22:12 +00:00
}
2013-10-25 14:14:03 +08:00
if ( $this -> user_can_delete_block ( $block )) {
// Delete icon.
$str = new lang_string ( 'deleteblock' , 'block' , $blocktitle );
$controls [] = new action_menu_link_secondary (
new moodle_url ( $actionurl , array ( 'bui_deleteid' => $block -> instance -> id )),
new pix_icon ( 't/delete' , $str , 'moodle' , array ( 'class' => 'iconsmall' , 'title' => '' )),
$str ,
array ( 'class' => 'editing_delete' )
);
}
2009-07-30 08:22:12 +00:00
return $controls ;
}
2012-10-10 14:28:45 +01:00
/**
* @ param block_base $block a block that appears on this page .
* @ return boolean boolean whether the currently logged in user is allowed to delete this block .
*/
protected function user_can_delete_block ( $block ) {
return $this -> page -> user_can_edit_blocks () && $block -> user_can_edit () &&
$block -> user_can_addto ( $this -> page ) &&
2016-12-02 10:00:43 +08:00
! in_array ( $block -> instance -> blockname , self :: get_undeletable_block_types ()) &&
! in_array ( $block -> instance -> blockname , self :: get_required_by_theme_block_types ());
2012-10-10 14:28:45 +01:00
}
2009-07-28 09:59:21 +00:00
/**
* Process any block actions that were specified in the URL .
*
* @ return boolean true if anything was done . False if not .
*/
public function process_url_actions () {
2009-07-30 08:22:12 +00:00
if ( ! $this -> page -> user_is_editing ()) {
return false ;
}
2009-07-28 09:59:21 +00:00
return $this -> process_url_add () || $this -> process_url_delete () ||
2009-07-30 08:22:12 +00:00
$this -> process_url_show_hide () || $this -> process_url_edit () ||
$this -> process_url_move ();
2009-07-28 09:59:21 +00:00
}
/**
* Handle adding a block .
* @ return boolean true if anything was done . False if not .
*/
public function process_url_add () {
2016-11-18 17:27:38 +08:00
global $CFG , $PAGE , $OUTPUT ;
2011-09-24 15:07:27 +02:00
$blocktype = optional_param ( 'bui_addblock' , null , PARAM_PLUGIN );
2016-11-18 17:27:38 +08:00
if ( $blocktype === null ) {
2009-07-28 09:59:21 +00:00
return false ;
}
2009-11-02 17:16:28 +00:00
require_sesskey ();
2009-07-28 09:59:21 +00:00
2009-07-30 09:40:11 +00:00
if ( ! $this -> page -> user_can_edit_blocks ()) {
2009-07-28 09:59:21 +00:00
throw new moodle_exception ( 'nopermissions' , '' , $this -> page -> url -> out (), get_string ( 'addblock' ));
}
2016-11-18 17:27:38 +08:00
$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 {
2016-11-24 14:23:29 +08:00
$url = new moodle_url ( $addpage -> url , array ( 'sesskey' => sesskey ()));
echo $OUTPUT -> render_from_template ( 'core/add_block_body' ,
[ 'blocks' => array_values ( $addableblocks ),
'url' => '?' . $url -> get_query_string ( false )]);
2016-11-18 17:27:38 +08:00
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 )) {
2009-07-28 09:59:21 +00:00
throw new moodle_exception ( 'cannotaddthisblocktype' , '' , $this -> page -> url -> out (), $blocktype );
}
$this -> add_block_at_end_of_default_region ( $blocktype );
2010-08-28 11:54:24 +00:00
// If the page URL was a guess, it will contain the bui_... param, so we must make sure it is not there.
2009-07-28 09:59:21 +00:00
$this -> page -> ensure_param_not_in_url ( 'bui_addblock' );
return true ;
}
/**
* Handle deleting a block .
* @ return boolean true if anything was done . False if not .
*/
public function process_url_delete () {
2012-09-06 19:39:49 +02:00
global $CFG , $PAGE , $OUTPUT ;
2012-08-20 13:56:56 +08:00
2012-05-11 10:49:51 +08:00
$blockid = optional_param ( 'bui_deleteid' , null , PARAM_INT );
2012-08-20 13:56:56 +08:00
$confirmdelete = optional_param ( 'bui_confirm' , null , PARAM_INT );
2009-07-28 09:59:21 +00:00
if ( ! $blockid ) {
return false ;
}
2009-11-02 17:16:28 +00:00
require_sesskey ();
2009-07-28 09:59:21 +00:00
$block = $this -> page -> blocks -> find_instance ( $blockid );
2012-10-10 14:28:45 +01:00
if ( ! $this -> user_can_delete_block ( $block )) {
2009-07-28 09:59:21 +00:00
throw new moodle_exception ( 'nopermissions' , '' , $this -> page -> url -> out (), get_string ( 'deleteablock' ));
}
2012-08-20 13:56:56 +08:00
if ( ! $confirmdelete ) {
$deletepage = new moodle_page ();
$deletepage -> set_pagelayout ( 'admin' );
2016-11-18 17:27:38 +08:00
$deletepage -> blocks -> show_only_fake_blocks ( true );
2012-08-20 13:56:56 +08:00
$deletepage -> set_course ( $this -> page -> course );
$deletepage -> set_context ( $this -> page -> context );
if ( $this -> page -> cm ) {
$deletepage -> set_cm ( $this -> page -> cm );
}
2009-07-28 09:59:21 +00:00
2012-08-20 13:56:56 +08:00
$deleteurlbase = str_replace ( $CFG -> wwwroot . '/' , '/' , $this -> page -> url -> out_omit_querystring ());
$deleteurlparams = $this -> page -> url -> params ();
$deletepage -> set_url ( $deleteurlbase , $deleteurlparams );
$deletepage -> set_block_actions_done ();
// At this point we are either going to redirect, or display the form, so
// overwrite global $PAGE ready for this. (Formslib refers to it.)
$PAGE = $deletepage ;
//some functions like MoodleQuickForm::addHelpButton use $OUTPUT so we need to replace that too
$output = $deletepage -> get_renderer ( 'core' );
$OUTPUT = $output ;
$site = get_site ();
$blocktitle = $block -> get_title ();
$strdeletecheck = get_string ( 'deletecheck' , 'block' , $blocktitle );
$message = get_string ( 'deleteblockcheck' , 'block' , $blocktitle );
2013-01-03 14:22:53 +08:00
// If the block is being shown in sub contexts display a warning.
if ( $block -> instance -> showinsubcontexts == 1 ) {
$parentcontext = context :: instance_by_id ( $block -> instance -> parentcontextid );
$systemcontext = context_system :: instance ();
$messagestring = new stdClass ();
$messagestring -> location = $parentcontext -> get_context_name ();
// Checking for blocks that may have visibility on the front page and pages added on that.
if ( $parentcontext -> id != $systemcontext -> id && is_inside_frontpage ( $parentcontext )) {
$messagestring -> pagetype = get_string ( 'showonfrontpageandsubs' , 'block' );
} else {
$pagetypes = generate_page_type_patterns ( $this -> page -> pagetype , $parentcontext );
$messagestring -> pagetype = $block -> instance -> pagetypepattern ;
if ( isset ( $pagetypes [ $block -> instance -> pagetypepattern ])) {
$messagestring -> pagetype = $pagetypes [ $block -> instance -> pagetypepattern ];
}
}
$message = get_string ( 'deleteblockwarning' , 'block' , $messagestring );
}
2012-08-20 13:56:56 +08:00
$PAGE -> navbar -> add ( $strdeletecheck );
$PAGE -> set_title ( $blocktitle . ': ' . $strdeletecheck );
$PAGE -> set_heading ( $site -> fullname );
echo $OUTPUT -> header ();
2012-09-11 12:27:17 -07:00
$confirmurl = new moodle_url ( $deletepage -> url , array ( 'sesskey' => sesskey (), 'bui_deleteid' => $block -> instance -> id , 'bui_confirm' => 1 ));
2012-08-20 13:56:56 +08:00
$cancelurl = new moodle_url ( $deletepage -> url );
$yesbutton = new single_button ( $confirmurl , get_string ( 'yes' ));
$nobutton = new single_button ( $cancelurl , get_string ( 'no' ));
echo $OUTPUT -> confirm ( $message , $yesbutton , $nobutton );
echo $OUTPUT -> footer ();
// Make sure that nothing else happens after we have displayed this form.
exit ;
} else {
blocks_delete_instance ( $block -> instance );
// bui_deleteid and bui_confirm should not be in the PAGE url.
$this -> page -> ensure_param_not_in_url ( 'bui_deleteid' );
$this -> page -> ensure_param_not_in_url ( 'bui_confirm' );
return true ;
}
2009-07-28 09:59:21 +00:00
}
/**
* Handle showing or hiding a block .
* @ return boolean true if anything was done . False if not .
*/
public function process_url_show_hide () {
2012-05-11 10:49:51 +08:00
if ( $blockid = optional_param ( 'bui_hideid' , null , PARAM_INT )) {
2009-07-28 09:59:21 +00:00
$newvisibility = 0 ;
2012-05-11 10:49:51 +08:00
} else if ( $blockid = optional_param ( 'bui_showid' , null , PARAM_INT )) {
2009-07-28 09:59:21 +00:00
$newvisibility = 1 ;
} else {
return false ;
}
2009-11-02 17:16:28 +00:00
require_sesskey ();
2009-07-28 09:59:21 +00:00
$block = $this -> page -> blocks -> find_instance ( $blockid );
2009-07-30 03:44:10 +00:00
if ( ! $this -> page -> user_can_edit_blocks ()) {
2009-07-28 09:59:21 +00:00
throw new moodle_exception ( 'nopermissions' , '' , $this -> page -> url -> out (), get_string ( 'hideshowblocks' ));
2010-09-14 02:12:41 +00:00
} else if ( ! $block -> instance_can_be_hidden ()) {
return false ;
2009-07-28 09:59:21 +00:00
}
blocks_set_visibility ( $block -> instance , $this -> page , $newvisibility );
// If the page URL was a guses, it will contain the bui_... param, so we must make sure it is not there.
$this -> page -> ensure_param_not_in_url ( 'bui_hideid' );
$this -> page -> ensure_param_not_in_url ( 'bui_showid' );
return true ;
}
/**
* Handle showing / processing the submission from the block editing form .
* @ return boolean true if the form was submitted and the new config saved . Does not
* return if the editing form was displayed . False otherwise .
*/
public function process_url_edit () {
2011-06-16 17:07:30 +08:00
global $CFG , $DB , $PAGE , $OUTPUT ;
2009-07-28 09:59:21 +00:00
2012-05-11 10:49:51 +08:00
$blockid = optional_param ( 'bui_editid' , null , PARAM_INT );
2009-07-28 09:59:21 +00:00
if ( ! $blockid ) {
return false ;
}
2009-11-02 17:16:28 +00:00
require_sesskey ();
2009-07-28 09:59:21 +00:00
require_once ( $CFG -> dirroot . '/blocks/edit_form.php' );
$block = $this -> find_instance ( $blockid );
2009-07-30 03:44:10 +00:00
if ( ! $block -> user_can_edit () && ! $this -> page -> user_can_edit_blocks ()) {
2009-07-28 09:59:21 +00:00
throw new moodle_exception ( 'nopermissions' , '' , $this -> page -> url -> out (), get_string ( 'editblock' ));
}
$editpage = new moodle_page ();
2010-02-18 09:23:14 +00:00
$editpage -> set_pagelayout ( 'admin' );
2016-11-18 17:27:38 +08:00
$editpage -> blocks -> show_only_fake_blocks ( true );
2009-07-28 09:59:21 +00:00
$editpage -> set_course ( $this -> page -> course );
MDL-26105 Block settings should contains less options, and be more user friendly
AMOS BEGIN
MOV [page-blog-index, pagetype], [page-blog-index, blog]
MOV [page-blog-x, pagetype], [page-blog-x, blog]
MOV [page-tag-x, pagetype], [page-tag-x, tag]
MOV [page-course-view-weeks, pagetype], [page-course-view-weeks, format_weeks]
MOV [page-course-view-weeks-x, pagetype], [page-course-view-weeks-x, format_weeks]
MOV [page-course-view-topics, pagetype], [page-course-view-topics, format_topics]
MOV [page-course-view-topics-x, pagetype], [page-course-view-topics-x, format_topics]
AMOS END
2011-04-28 11:20:30 +08:00
//$editpage->set_context($block->context);
$editpage -> set_context ( $this -> page -> context );
2010-04-21 09:44:16 +00:00
if ( $this -> page -> cm ) {
$editpage -> set_cm ( $this -> page -> cm );
}
2010-01-18 12:12:38 +00:00
$editurlbase = str_replace ( $CFG -> wwwroot . '/' , '/' , $this -> page -> url -> out_omit_querystring ());
2009-07-28 09:59:21 +00:00
$editurlparams = $this -> page -> url -> params ();
$editurlparams [ 'bui_editid' ] = $blockid ;
$editpage -> set_url ( $editurlbase , $editurlparams );
2010-08-26 06:27:47 +00:00
$editpage -> set_block_actions_done ();
2009-07-28 09:59:21 +00:00
// At this point we are either going to redirect, or display the form, so
// overwrite global $PAGE ready for this. (Formslib refers to it.)
$PAGE = $editpage ;
2011-06-16 17:07:30 +08:00
//some functions like MoodleQuickForm::addHelpButton use $OUTPUT so we need to replace that to
$output = $editpage -> get_renderer ( 'core' );
$OUTPUT = $output ;
2009-07-28 09:59:21 +00:00
$formfile = $CFG -> dirroot . '/blocks/' . $block -> name () . '/edit_form.php' ;
if ( is_readable ( $formfile )) {
require_once ( $formfile );
$classname = 'block_' . $block -> name () . '_edit_form' ;
2010-07-18 08:05:00 +00:00
if ( ! class_exists ( $classname )) {
$classname = 'block_edit_form' ;
}
2009-07-28 09:59:21 +00:00
} else {
$classname = 'block_edit_form' ;
}
$mform = new $classname ( $editpage -> url , $block , $this -> page );
$mform -> set_data ( $block -> instance );
if ( $mform -> is_cancelled ()) {
redirect ( $this -> page -> url );
} else if ( $data = $mform -> get_data ()) {
$bi = new stdClass ;
$bi -> id = $block -> instance -> id ;
2012-12-16 22:39:07 +00:00
// This may get overwritten by the special case handling below.
2009-07-28 09:59:21 +00:00
$bi -> pagetypepattern = $data -> bui_pagetypepattern ;
2013-01-16 12:38:04 +00:00
$bi -> showinsubcontexts = ( bool ) $data -> bui_contexts ;
2009-07-28 09:59:21 +00:00
if ( empty ( $data -> bui_subpagepattern ) || $data -> bui_subpagepattern == '%@NULL@%' ) {
$bi -> subpagepattern = null ;
} else {
$bi -> subpagepattern = $data -> bui_subpagepattern ;
}
2010-01-20 09:08:04 +00:00
2012-07-25 16:25:55 +08:00
$systemcontext = context_system :: instance ();
$frontpagecontext = context_course :: instance ( SITEID );
2012-08-21 14:20:30 +08:00
$parentcontext = context :: instance_by_id ( $data -> bui_parentcontextid );
2010-01-20 09:08:04 +00:00
// Updating stickiness and contexts. See MDL-21375 for details.
if ( has_capability ( 'moodle/site:manageblocks' , $parentcontext )) { // Check permissions in destination
MDL-30340 blocks - hide some redundant pagetypepattern options at front page
The dual front-page/system-wide form to edit blocks can
be reduced asuming that, always:
A) system sets the context to system,
recursively and with page-type set to "*"
B) frontpage only sets the context to site-course,
non-recursively and with page-type set to "site-index"
C) frontpage all added sets the context to site-course,
recursively and with paget-type set to "*"
And that is the change that this patch provides, by:
1) detecting properly if we are editing blocks @ protpage
2) passing that information to the form data processor
3) setting parentcontextid, showinsubcontexts and
pagetypepattern following the A, B, C immutables above.
Finally, and affecting some other system-wide pages, there
are cases (my, user templates...) having only one possible
pagetypepattern, and it looks badly if the page has subpages, so
for those system-wide cases we are showing exceptionaly the
pagetypepattern statically. This will be revisited once MDL-30574
is decided and implemented, although perhaps it's ok to leave it
as default to places with only one pagetypepattern available.
2011-12-05 00:48:08 +01:00
// Explicitly set the default context
2010-01-20 09:08:04 +00:00
$bi -> parentcontextid = $parentcontext -> id ;
2011-12-05 10:28:54 +01:00
if ( $data -> bui_editingatfrontpage ) { // The block is being edited on the front page
2010-01-20 09:08:04 +00:00
2011-12-05 10:28:54 +01:00
// The interface here is a special case because the pagetype pattern is
// totally derived from the context menu. Here are the excpetions. MDL-30340
2010-01-20 09:08:04 +00:00
2011-12-05 10:28:54 +01:00
switch ( $data -> bui_contexts ) {
case BUI_CONTEXTS_ENTIRE_SITE :
// The user wants to show the block across the entire site
$bi -> parentcontextid = $systemcontext -> id ;
$bi -> showinsubcontexts = true ;
MDL-30340 blocks - hide some redundant pagetypepattern options at front page
The dual front-page/system-wide form to edit blocks can
be reduced asuming that, always:
A) system sets the context to system,
recursively and with page-type set to "*"
B) frontpage only sets the context to site-course,
non-recursively and with page-type set to "site-index"
C) frontpage all added sets the context to site-course,
recursively and with paget-type set to "*"
And that is the change that this patch provides, by:
1) detecting properly if we are editing blocks @ protpage
2) passing that information to the form data processor
3) setting parentcontextid, showinsubcontexts and
pagetypepattern following the A, B, C immutables above.
Finally, and affecting some other system-wide pages, there
are cases (my, user templates...) having only one possible
pagetypepattern, and it looks badly if the page has subpages, so
for those system-wide cases we are showing exceptionaly the
pagetypepattern statically. This will be revisited once MDL-30574
is decided and implemented, although perhaps it's ok to leave it
as default to places with only one pagetypepattern available.
2011-12-05 00:48:08 +01:00
$bi -> pagetypepattern = '*' ;
2011-12-05 10:28:54 +01:00
break ;
case BUI_CONTEXTS_FRONTPAGE_SUBS :
// The user wants the block shown on the front page and all subcontexts
$bi -> parentcontextid = $frontpagecontext -> id ;
$bi -> showinsubcontexts = true ;
MDL-30340 blocks - hide some redundant pagetypepattern options at front page
The dual front-page/system-wide form to edit blocks can
be reduced asuming that, always:
A) system sets the context to system,
recursively and with page-type set to "*"
B) frontpage only sets the context to site-course,
non-recursively and with page-type set to "site-index"
C) frontpage all added sets the context to site-course,
recursively and with paget-type set to "*"
And that is the change that this patch provides, by:
1) detecting properly if we are editing blocks @ protpage
2) passing that information to the form data processor
3) setting parentcontextid, showinsubcontexts and
pagetypepattern following the A, B, C immutables above.
Finally, and affecting some other system-wide pages, there
are cases (my, user templates...) having only one possible
pagetypepattern, and it looks badly if the page has subpages, so
for those system-wide cases we are showing exceptionaly the
pagetypepattern statically. This will be revisited once MDL-30574
is decided and implemented, although perhaps it's ok to leave it
as default to places with only one pagetypepattern available.
2011-12-05 00:48:08 +01:00
$bi -> pagetypepattern = '*' ;
2011-12-05 10:28:54 +01:00
break ;
case BUI_CONTEXTS_FRONTPAGE_ONLY :
// The user want to show the front page on the frontpage only
$bi -> parentcontextid = $frontpagecontext -> id ;
$bi -> showinsubcontexts = false ;
MDL-30340 blocks - hide some redundant pagetypepattern options at front page
The dual front-page/system-wide form to edit blocks can
be reduced asuming that, always:
A) system sets the context to system,
recursively and with page-type set to "*"
B) frontpage only sets the context to site-course,
non-recursively and with page-type set to "site-index"
C) frontpage all added sets the context to site-course,
recursively and with paget-type set to "*"
And that is the change that this patch provides, by:
1) detecting properly if we are editing blocks @ protpage
2) passing that information to the form data processor
3) setting parentcontextid, showinsubcontexts and
pagetypepattern following the A, B, C immutables above.
Finally, and affecting some other system-wide pages, there
are cases (my, user templates...) having only one possible
pagetypepattern, and it looks badly if the page has subpages, so
for those system-wide cases we are showing exceptionaly the
pagetypepattern statically. This will be revisited once MDL-30574
is decided and implemented, although perhaps it's ok to leave it
as default to places with only one pagetypepattern available.
2011-12-05 00:48:08 +01:00
$bi -> pagetypepattern = 'site-index' ;
2011-12-05 10:28:54 +01:00
// This is the only relevant page type anyway but we'll set it explicitly just
// in case the front page grows site-index-* subpages of its own later
break ;
2010-01-20 09:08:04 +00:00
}
2010-01-19 10:07:52 +00:00
}
}
2010-01-20 09:08:04 +00:00
MDL-26105 Block settings should contains less options, and be more user friendly
AMOS BEGIN
MOV [page-blog-index, pagetype], [page-blog-index, blog]
MOV [page-blog-x, pagetype], [page-blog-x, blog]
MOV [page-tag-x, pagetype], [page-tag-x, tag]
MOV [page-course-view-weeks, pagetype], [page-course-view-weeks, format_weeks]
MOV [page-course-view-weeks-x, pagetype], [page-course-view-weeks-x, format_weeks]
MOV [page-course-view-topics, pagetype], [page-course-view-topics, format_topics]
MOV [page-course-view-topics-x, pagetype], [page-course-view-topics-x, format_topics]
AMOS END
2011-04-28 11:20:30 +08:00
$bits = explode ( '-' , $bi -> pagetypepattern );
// hacks for some contexts
if (( $parentcontext -> contextlevel == CONTEXT_COURSE ) && ( $parentcontext -> instanceid != SITEID )) {
// For course context
// is page type pattern is mod-*, change showinsubcontext to 1
if ( $bits [ 0 ] == 'mod' || $bi -> pagetypepattern == '*' ) {
$bi -> showinsubcontexts = 1 ;
} else {
$bi -> showinsubcontexts = 0 ;
}
} else if ( $parentcontext -> contextlevel == CONTEXT_USER ) {
// for user context
// subpagepattern should be null
if ( $bits [ 0 ] == 'user' or $bits [ 0 ] == 'my' ) {
// we don't need subpagepattern in usercontext
$bi -> subpagepattern = null ;
}
}
2009-07-28 09:59:21 +00:00
$bi -> defaultregion = $data -> bui_defaultregion ;
$bi -> defaultweight = $data -> bui_defaultweight ;
$DB -> update_record ( 'block_instances' , $bi );
2009-07-29 03:51:16 +00:00
if ( ! empty ( $block -> config )) {
$config = clone ( $block -> config );
} else {
$config = new stdClass ;
}
2009-07-28 09:59:21 +00:00
foreach ( $data as $configfield => $value ) {
if ( strpos ( $configfield , 'config_' ) !== 0 ) {
continue ;
}
$field = substr ( $configfield , 7 );
$config -> $field = $value ;
}
$block -> instance_config_save ( $config );
$bp = new stdClass ;
$bp -> visible = $data -> bui_visible ;
$bp -> region = $data -> bui_region ;
$bp -> weight = $data -> bui_weight ;
$needbprecord = ! $data -> bui_visible || $data -> bui_region != $data -> bui_defaultregion ||
$data -> bui_weight != $data -> bui_defaultweight ;
if ( $block -> instance -> blockpositionid && ! $needbprecord ) {
$DB -> delete_records ( 'block_positions' , array ( 'id' => $block -> instance -> blockpositionid ));
} else if ( $block -> instance -> blockpositionid && $needbprecord ) {
$bp -> id = $block -> instance -> blockpositionid ;
$DB -> update_record ( 'block_positions' , $bp );
} else if ( $needbprecord ) {
$bp -> blockinstanceid = $block -> instance -> id ;
2009-07-29 03:51:16 +00:00
$bp -> contextid = $this -> page -> context -> id ;
2009-07-28 09:59:21 +00:00
$bp -> pagetype = $this -> page -> pagetype ;
if ( $this -> page -> subpage ) {
$bp -> subpage = $this -> page -> subpage ;
} else {
2009-07-29 03:51:16 +00:00
$bp -> subpage = '' ;
2009-07-28 09:59:21 +00:00
}
$DB -> insert_record ( 'block_positions' , $bp );
}
redirect ( $this -> page -> url );
} else {
2010-04-27 22:31:29 +00:00
$strheading = get_string ( 'blockconfiga' , 'moodle' , $block -> get_title ());
2009-07-28 09:59:21 +00:00
$editpage -> set_title ( $strheading );
$editpage -> set_heading ( $strheading );
MDL-26105 Block settings should contains less options, and be more user friendly
AMOS BEGIN
MOV [page-blog-index, pagetype], [page-blog-index, blog]
MOV [page-blog-x, pagetype], [page-blog-x, blog]
MOV [page-tag-x, pagetype], [page-tag-x, tag]
MOV [page-course-view-weeks, pagetype], [page-course-view-weeks, format_weeks]
MOV [page-course-view-weeks-x, pagetype], [page-course-view-weeks-x, format_weeks]
MOV [page-course-view-topics, pagetype], [page-course-view-topics, format_topics]
MOV [page-course-view-topics-x, pagetype], [page-course-view-topics-x, format_topics]
AMOS END
2011-04-28 11:20:30 +08:00
$bits = explode ( '-' , $this -> page -> pagetype );
if ( $bits [ 0 ] == 'tag' && ! empty ( $this -> page -> subpage )) {
// better navbar for tag pages
$editpage -> navbar -> add ( get_string ( 'tags' ), new moodle_url ( '/tag/' ));
2015-10-02 23:13:44 +08:00
$tag = core_tag_tag :: get ( $this -> page -> subpage );
MDL-26105 Block settings should contains less options, and be more user friendly
AMOS BEGIN
MOV [page-blog-index, pagetype], [page-blog-index, blog]
MOV [page-blog-x, pagetype], [page-blog-x, blog]
MOV [page-tag-x, pagetype], [page-tag-x, tag]
MOV [page-course-view-weeks, pagetype], [page-course-view-weeks, format_weeks]
MOV [page-course-view-weeks-x, pagetype], [page-course-view-weeks-x, format_weeks]
MOV [page-course-view-topics, pagetype], [page-course-view-topics, format_topics]
MOV [page-course-view-topics-x, pagetype], [page-course-view-topics-x, format_topics]
AMOS END
2011-04-28 11:20:30 +08:00
// tag search page doesn't have subpageid
if ( $tag ) {
2015-10-02 23:13:44 +08:00
$editpage -> navbar -> add ( $tag -> get_display_name (), $tag -> get_view_url ());
MDL-26105 Block settings should contains less options, and be more user friendly
AMOS BEGIN
MOV [page-blog-index, pagetype], [page-blog-index, blog]
MOV [page-blog-x, pagetype], [page-blog-x, blog]
MOV [page-tag-x, pagetype], [page-tag-x, tag]
MOV [page-course-view-weeks, pagetype], [page-course-view-weeks, format_weeks]
MOV [page-course-view-weeks-x, pagetype], [page-course-view-weeks-x, format_weeks]
MOV [page-course-view-topics, pagetype], [page-course-view-topics, format_topics]
MOV [page-course-view-topics-x, pagetype], [page-course-view-topics-x, format_topics]
AMOS END
2011-04-28 11:20:30 +08:00
}
}
$editpage -> navbar -> add ( $block -> get_title ());
$editpage -> navbar -> add ( get_string ( 'configuration' ));
2009-07-28 09:59:21 +00:00
echo $output -> header ();
echo $output -> heading ( $strheading , 2 );
$mform -> display ();
echo $output -> footer ();
exit ;
}
}
2009-07-30 08:22:12 +00:00
/**
* Handle showing / processing the submission from the block editing form .
* @ return boolean true if the form was submitted and the new config saved . Does not
* return if the editing form was displayed . False otherwise .
*/
public function process_url_move () {
global $CFG , $DB , $PAGE ;
2012-05-11 10:49:51 +08:00
$blockid = optional_param ( 'bui_moveid' , null , PARAM_INT );
2009-07-30 08:22:12 +00:00
if ( ! $blockid ) {
return false ;
}
2009-11-02 17:16:28 +00:00
require_sesskey ();
2009-07-30 08:22:12 +00:00
$block = $this -> find_instance ( $blockid );
if ( ! $this -> page -> user_can_edit_blocks ()) {
throw new moodle_exception ( 'nopermissions' , '' , $this -> page -> url -> out (), get_string ( 'editblock' ));
}
$newregion = optional_param ( 'bui_newregion' , '' , PARAM_ALPHANUMEXT );
$newweight = optional_param ( 'bui_newweight' , null , PARAM_FLOAT );
if ( ! $newregion || is_null ( $newweight )) {
// Don't have a valid target position yet, must be just starting the move.
$this -> movingblock = $blockid ;
$this -> page -> ensure_param_not_in_url ( 'bui_moveid' );
return false ;
}
2009-07-30 10:29:14 +00:00
if ( ! $this -> is_known_region ( $newregion )) {
throw new moodle_exception ( 'unknownblockregion' , '' , $this -> page -> url , $newregion );
}
// Move this block. This may involve moving other nearby blocks.
$blocks = $this -> birecordsbyregion [ $newregion ];
2009-09-09 02:44:57 +00:00
$maxweight = self :: MAX_WEIGHT ;
$minweight = - self :: MAX_WEIGHT ;
// Initialise the used weights and spareweights array with the default values
2009-07-30 10:29:14 +00:00
$spareweights = array ();
$usedweights = array ();
2009-09-09 02:44:57 +00:00
for ( $i = $minweight ; $i <= $maxweight ; $i ++ ) {
2009-07-30 10:29:14 +00:00
$spareweights [ $i ] = $i ;
$usedweights [ $i ] = array ();
}
2009-09-09 02:44:57 +00:00
// Check each block and sort out where we have used weights
2009-07-30 10:29:14 +00:00
foreach ( $blocks as $bi ) {
2009-09-09 02:44:57 +00:00
if ( $bi -> weight > $maxweight ) {
// If this statement is true then the blocks weight is more than the
// current maximum. To ensure that we can get the best block position
// we will initialise elements within the usedweights and spareweights
// arrays between the blocks weight (which will then be the new max) and
// the current max
$parseweight = $bi -> weight ;
while ( ! array_key_exists ( $parseweight , $usedweights )) {
$usedweights [ $parseweight ] = array ();
$spareweights [ $parseweight ] = $parseweight ;
$parseweight -- ;
}
$maxweight = $bi -> weight ;
} else if ( $bi -> weight < $minweight ) {
// As above except this time the blocks weight is LESS than the
// the current minimum, so we will initialise the array from the
// blocks weight (new minimum) to the current minimum
$parseweight = $bi -> weight ;
while ( ! array_key_exists ( $parseweight , $usedweights )) {
$usedweights [ $parseweight ] = array ();
$spareweights [ $parseweight ] = $parseweight ;
$parseweight ++ ;
}
$minweight = $bi -> weight ;
}
if ( $bi -> id != $block -> instance -> id ) {
unset ( $spareweights [ $bi -> weight ]);
$usedweights [ $bi -> weight ][] = $bi -> id ;
2009-07-30 10:29:14 +00:00
}
}
2009-09-09 02:44:57 +00:00
// First we find the nearest gap in the list of weights.
2009-07-30 10:29:14 +00:00
$bestdistance = max ( abs ( $newweight - self :: MAX_WEIGHT ), abs ( $newweight + self :: MAX_WEIGHT )) + 1 ;
$bestgap = null ;
foreach ( $spareweights as $spareweight ) {
if ( abs ( $newweight - $spareweight ) < $bestdistance ) {
$bestdistance = abs ( $newweight - $spareweight );
$bestgap = $spareweight ;
}
}
// If there is no gap, we have to go outside -self::MAX_WEIGHT .. self::MAX_WEIGHT.
if ( is_null ( $bestgap )) {
$bestgap = self :: MAX_WEIGHT + 1 ;
while ( ! empty ( $usedweights [ $bestgap ])) {
$bestgap ++ ;
}
}
// Now we know the gap we are aiming for, so move all the blocks along.
if ( $bestgap < $newweight ) {
$newweight = floor ( $newweight );
for ( $weight = $bestgap + 1 ; $weight <= $newweight ; $weight ++ ) {
2015-03-04 18:47:59 +00:00
if ( array_key_exists ( $weight , $usedweights )) {
foreach ( $usedweights [ $weight ] as $biid ) {
$this -> reposition_block ( $biid , $newregion , $weight - 1 );
}
2009-07-30 10:29:14 +00:00
}
}
$this -> reposition_block ( $block -> instance -> id , $newregion , $newweight );
} else {
$newweight = ceil ( $newweight );
for ( $weight = $bestgap - 1 ; $weight >= $newweight ; $weight -- ) {
2011-12-08 12:36:55 +00:00
if ( array_key_exists ( $weight , $usedweights )) {
foreach ( $usedweights [ $weight ] as $biid ) {
$this -> reposition_block ( $biid , $newregion , $weight + 1 );
}
2009-07-30 10:29:14 +00:00
}
}
$this -> reposition_block ( $block -> instance -> id , $newregion , $newweight );
}
2009-11-01 16:48:45 +00:00
2009-07-30 08:22:12 +00:00
$this -> page -> ensure_param_not_in_url ( 'bui_moveid' );
$this -> page -> ensure_param_not_in_url ( 'bui_newregion' );
$this -> page -> ensure_param_not_in_url ( 'bui_newweight' );
return true ;
}
2010-05-21 03:15:48 +00:00
/**
* Turns the display of normal blocks either on or off .
2010-07-25 13:35:05 +00:00
*
2010-05-21 03:15:48 +00:00
* @ param bool $setting
*/
public function show_only_fake_blocks ( $setting = true ) {
$this -> fakeblocksonly = $setting ;
}
2009-05-06 09:14:01 +00:00
}
2009-05-06 09:14:42 +00:00
/// Helper functions for working with block classes ============================
/**
2010-08-28 11:54:24 +00:00
* Call a class method ( one that does not require a block instance ) on a block class .
2009-05-22 02:18:49 +00:00
*
2009-05-06 09:14:42 +00:00
* @ param string $blockname the name of the block .
* @ param string $method the method name .
* @ param array $param parameters to pass to the method .
* @ return mixed whatever the method returns .
*/
2005-12-17 04:37:55 +00:00
function block_method_result ( $blockname , $method , $param = NULL ) {
2004-04-18 23:20:53 +00:00
if ( ! block_load_class ( $blockname )) {
return NULL ;
}
2005-12-17 04:37:55 +00:00
return call_user_func ( array ( 'block_' . $blockname , $method ), $param );
2004-04-18 23:20:53 +00:00
}
2009-05-06 09:14:42 +00:00
/**
2010-09-21 08:07:44 +00:00
* Creates a new instance of the specified block class .
2009-05-22 02:18:49 +00:00
*
2009-05-06 09:14:42 +00:00
* @ param string $blockname the name of the block .
* @ param $instance block_instances DB table row ( optional ) .
2009-05-06 09:15:05 +00:00
* @ param moodle_page $page the page this block is appearing on .
2009-05-06 09:14:42 +00:00
* @ return block_base the requested block instance .
*/
2009-05-06 09:15:05 +00:00
function block_instance ( $blockname , $instance = NULL , $page = NULL ) {
2004-04-18 23:20:53 +00:00
if ( ! block_load_class ( $blockname )) {
return false ;
}
2004-11-23 18:53:34 +00:00
$classname = 'block_' . $blockname ;
2004-11-08 19:36:07 +00:00
$retval = new $classname ;
2004-10-19 21:04:28 +00:00
if ( $instance !== NULL ) {
2009-05-06 09:15:05 +00:00
if ( is_null ( $page )) {
global $PAGE ;
$page = $PAGE ;
}
$retval -> _load_instance ( $instance , $page );
2004-10-19 21:04:28 +00:00
}
return $retval ;
2004-04-18 23:20:53 +00:00
}
2009-05-06 09:14:42 +00:00
/**
* Load the block class for a particular type of block .
2009-05-22 02:18:49 +00:00
*
2009-05-06 09:14:42 +00:00
* @ param string $blockname the name of the block .
* @ return boolean success or failure .
*/
2004-04-18 23:20:53 +00:00
function block_load_class ( $blockname ) {
global $CFG ;
2005-12-17 03:09:13 +00:00
if ( empty ( $blockname )) {
2005-02-08 17:07:31 +00:00
return false ;
}
2004-11-23 18:53:34 +00:00
$classname = 'block_' . $blockname ;
2005-12-17 03:09:13 +00:00
if ( class_exists ( $classname )) {
return true ;
}
2009-08-22 11:24:39 +00:00
$blockpath = $CFG -> dirroot . '/blocks/' . $blockname . '/block_' . $blockname . '.php' ;
if ( file_exists ( $blockpath )) {
require_once ( $CFG -> dirroot . '/blocks/moodleblock.class.php' );
include_once ( $blockpath );
} else {
2010-04-11 12:08:40 +00:00
//debugging("$blockname code does not exist in $blockpath", DEBUG_DEVELOPER);
2009-08-22 11:24:39 +00:00
return false ;
}
2004-04-18 23:20:53 +00:00
return class_exists ( $classname );
}
2009-07-16 10:50:19 +00:00
/**
* Given a specific page type , return all the page type patterns that might
* match it .
*
* @ param string $pagetype for example 'course-view-weeks' or 'mod-quiz-view' .
* @ return array an array of all the page type patterns that might match this page type .
*/
function matching_page_type_patterns ( $pagetype ) {
$patterns = array ( $pagetype );
$bits = explode ( '-' , $pagetype );
if ( count ( $bits ) == 3 && $bits [ 0 ] == 'mod' ) {
if ( $bits [ 2 ] == 'view' ) {
$patterns [] = 'mod-*-view' ;
} else if ( $bits [ 2 ] == 'index' ) {
$patterns [] = 'mod-*-index' ;
}
}
while ( count ( $bits ) > 0 ) {
$patterns [] = implode ( '-' , $bits ) . '-*' ;
array_pop ( $bits );
}
2010-04-27 13:04:15 +00:00
$patterns [] = '*' ;
2009-07-16 10:50:19 +00:00
return $patterns ;
}
2014-11-27 14:26:28 +08:00
/**
* Give an specific pattern , return all the page type patterns that would also match it .
*
* @ param string $pattern the pattern , e . g . 'mod-forum-*' or 'mod-quiz-view' .
* @ return array of all the page type patterns matching .
*/
function matching_page_type_patterns_from_pattern ( $pattern ) {
$patterns = array ( $pattern );
if ( $pattern === '*' ) {
return $patterns ;
}
// Only keep the part before the star because we will append -* to all the bits.
$star = strpos ( $pattern , '-*' );
if ( $star !== false ) {
$pattern = substr ( $pattern , 0 , $star );
}
$patterns = array_merge ( $patterns , matching_page_type_patterns ( $pattern ));
$patterns = array_unique ( $patterns );
return $patterns ;
}
MDL-26105 Block settings should contains less options, and be more user friendly
AMOS BEGIN
MOV [page-blog-index, pagetype], [page-blog-index, blog]
MOV [page-blog-x, pagetype], [page-blog-x, blog]
MOV [page-tag-x, pagetype], [page-tag-x, tag]
MOV [page-course-view-weeks, pagetype], [page-course-view-weeks, format_weeks]
MOV [page-course-view-weeks-x, pagetype], [page-course-view-weeks-x, format_weeks]
MOV [page-course-view-topics, pagetype], [page-course-view-topics, format_topics]
MOV [page-course-view-topics-x, pagetype], [page-course-view-topics-x, format_topics]
AMOS END
2011-04-28 11:20:30 +08:00
/**
* Given a specific page type , parent context and currect context , return all the page type patterns
* that might be used by this block .
*
* @ param string $pagetype for example 'course-view-weeks' or 'mod-quiz-view' .
* @ param stdClass $parentcontext Block ' s parent context
* @ param stdClass $currentcontext Current context of block
* @ return array an array of all the page type patterns that might match this page type .
*/
function generate_page_type_patterns ( $pagetype , $parentcontext = null , $currentcontext = null ) {
2013-06-07 18:15:28 +02:00
global $CFG ; // Required for includes bellow.
2011-05-03 16:29:05 +08:00
MDL-26105 Block settings should contains less options, and be more user friendly
AMOS BEGIN
MOV [page-blog-index, pagetype], [page-blog-index, blog]
MOV [page-blog-x, pagetype], [page-blog-x, blog]
MOV [page-tag-x, pagetype], [page-tag-x, tag]
MOV [page-course-view-weeks, pagetype], [page-course-view-weeks, format_weeks]
MOV [page-course-view-weeks-x, pagetype], [page-course-view-weeks-x, format_weeks]
MOV [page-course-view-topics, pagetype], [page-course-view-topics, format_topics]
MOV [page-course-view-topics-x, pagetype], [page-course-view-topics-x, format_topics]
AMOS END
2011-04-28 11:20:30 +08:00
$bits = explode ( '-' , $pagetype );
2011-05-03 16:29:05 +08:00
2013-06-07 18:15:28 +02:00
$core = core_component :: get_core_subsystems ();
$plugins = core_component :: get_plugin_types ();
2011-05-03 16:29:05 +08:00
2011-06-14 16:04:41 +08:00
//progressively strip pieces off the page type looking for a match
$componentarray = null ;
2011-06-17 16:23:10 +08:00
for ( $i = count ( $bits ); $i > 0 ; $i -- ) {
$possiblecomponentarray = array_slice ( $bits , 0 , $i );
$possiblecomponent = implode ( '' , $possiblecomponentarray );
2011-06-14 16:04:41 +08:00
2011-06-17 16:23:10 +08:00
// Check to see if the component is a core component
if ( array_key_exists ( $possiblecomponent , $core ) && ! empty ( $core [ $possiblecomponent ])) {
2013-06-07 18:15:28 +02:00
$libfile = $core [ $possiblecomponent ] . '/lib.php' ;
2011-06-14 16:04:41 +08:00
if ( file_exists ( $libfile )) {
require_once ( $libfile );
2011-06-17 16:23:10 +08:00
$function = $possiblecomponent . '_page_type_list' ;
if ( function_exists ( $function )) {
if ( $patterns = $function ( $pagetype , $parentcontext , $currentcontext )) {
break ;
}
2011-06-14 16:04:41 +08:00
}
MDL-26105 Block settings should contains less options, and be more user friendly
AMOS BEGIN
MOV [page-blog-index, pagetype], [page-blog-index, blog]
MOV [page-blog-x, pagetype], [page-blog-x, blog]
MOV [page-tag-x, pagetype], [page-tag-x, tag]
MOV [page-course-view-weeks, pagetype], [page-course-view-weeks, format_weeks]
MOV [page-course-view-weeks-x, pagetype], [page-course-view-weeks-x, format_weeks]
MOV [page-course-view-topics, pagetype], [page-course-view-topics, format_topics]
MOV [page-course-view-topics-x, pagetype], [page-course-view-topics-x, format_topics]
AMOS END
2011-04-28 11:20:30 +08:00
}
2011-05-03 16:29:05 +08:00
}
2011-06-14 16:04:41 +08:00
2011-06-17 16:23:10 +08:00
//check the plugin directory and look for a callback
if ( array_key_exists ( $possiblecomponent , $plugins ) && ! empty ( $plugins [ $possiblecomponent ])) {
//We've found a plugin type. Look for a plugin name by getting the next section of page type
if ( count ( $bits ) > $i ) {
$pluginname = $bits [ $i ];
2013-06-07 18:15:28 +02:00
$directory = core_component :: get_plugin_directory ( $possiblecomponent , $pluginname );
2011-06-17 16:23:10 +08:00
if ( ! empty ( $directory )){
$libfile = $directory . '/lib.php' ;
if ( file_exists ( $libfile )) {
require_once ( $libfile );
2011-11-06 11:32:12 +01:00
$function = $possiblecomponent . '_' . $pluginname . '_page_type_list' ;
if ( ! function_exists ( $function )) {
$function = $pluginname . '_page_type_list' ;
}
2011-06-17 16:23:10 +08:00
if ( function_exists ( $function )) {
if ( $patterns = $function ( $pagetype , $parentcontext , $currentcontext )) {
break ;
}
}
}
}
}
//we'll only get to here if we still don't have any patterns
//the plugin type may have a callback
2013-06-07 18:15:28 +02:00
$directory = $plugins [ $possiblecomponent ];
$libfile = $directory . '/lib.php' ;
if ( file_exists ( $libfile )) {
require_once ( $libfile );
$function = $possiblecomponent . '_page_type_list' ;
if ( function_exists ( $function )) {
if ( $patterns = $function ( $pagetype , $parentcontext , $currentcontext )) {
break ;
2011-06-17 16:23:10 +08:00
}
}
2011-06-14 16:04:41 +08:00
}
2011-05-03 16:29:05 +08:00
}
}
2011-06-14 16:04:41 +08:00
2011-05-03 16:29:05 +08:00
if ( empty ( $patterns )) {
2011-06-17 16:23:10 +08:00
$patterns = default_page_type_list ( $pagetype , $parentcontext , $currentcontext );
MDL-26105 Block settings should contains less options, and be more user friendly
AMOS BEGIN
MOV [page-blog-index, pagetype], [page-blog-index, blog]
MOV [page-blog-x, pagetype], [page-blog-x, blog]
MOV [page-tag-x, pagetype], [page-tag-x, tag]
MOV [page-course-view-weeks, pagetype], [page-course-view-weeks, format_weeks]
MOV [page-course-view-weeks-x, pagetype], [page-course-view-weeks-x, format_weeks]
MOV [page-course-view-topics, pagetype], [page-course-view-topics, format_topics]
MOV [page-course-view-topics-x, pagetype], [page-course-view-topics-x, format_topics]
AMOS END
2011-04-28 11:20:30 +08:00
}
2011-06-17 16:23:10 +08:00
2011-12-03 11:21:48 +01:00
// Ensure that the * pattern is always available if editing block 'at distance', so
// we always can 'bring back' it to the original context. MDL-30340
2012-01-15 13:37:53 +01:00
if (( ! isset ( $currentcontext ) or ! isset ( $parentcontext ) or $currentcontext -> id != $parentcontext -> id ) && ! isset ( $patterns [ '*' ])) {
2011-12-03 11:21:48 +01:00
// TODO: We could change the string here, showing its 'bring back' meaning
$patterns [ '*' ] = get_string ( 'page-x' , 'pagetype' );
}
2011-05-03 16:29:05 +08:00
return $patterns ;
}
MDL-26105 Block settings should contains less options, and be more user friendly
AMOS BEGIN
MOV [page-blog-index, pagetype], [page-blog-index, blog]
MOV [page-blog-x, pagetype], [page-blog-x, blog]
MOV [page-tag-x, pagetype], [page-tag-x, tag]
MOV [page-course-view-weeks, pagetype], [page-course-view-weeks, format_weeks]
MOV [page-course-view-weeks-x, pagetype], [page-course-view-weeks-x, format_weeks]
MOV [page-course-view-topics, pagetype], [page-course-view-topics, format_topics]
MOV [page-course-view-topics-x, pagetype], [page-course-view-topics-x, format_topics]
AMOS END
2011-04-28 11:20:30 +08:00
2011-05-03 16:29:05 +08:00
/**
* Generates a default page type list when a more appropriate callback cannot be decided upon .
*
* @ param string $pagetype
* @ param stdClass $parentcontext
* @ param stdClass $currentcontext
* @ return array
*/
2011-06-17 16:23:10 +08:00
function default_page_type_list ( $pagetype , $parentcontext = null , $currentcontext = null ) {
MDL-26105 Block settings should contains less options, and be more user friendly
AMOS BEGIN
MOV [page-blog-index, pagetype], [page-blog-index, blog]
MOV [page-blog-x, pagetype], [page-blog-x, blog]
MOV [page-tag-x, pagetype], [page-tag-x, tag]
MOV [page-course-view-weeks, pagetype], [page-course-view-weeks, format_weeks]
MOV [page-course-view-weeks-x, pagetype], [page-course-view-weeks-x, format_weeks]
MOV [page-course-view-topics, pagetype], [page-course-view-topics, format_topics]
MOV [page-course-view-topics-x, pagetype], [page-course-view-topics-x, format_topics]
AMOS END
2011-04-28 11:20:30 +08:00
// Generate page type patterns based on current page type if
// callbacks haven't been defined
2011-05-03 16:29:05 +08:00
$patterns = array ( $pagetype => $pagetype );
$bits = explode ( '-' , $pagetype );
MDL-26105 Block settings should contains less options, and be more user friendly
AMOS BEGIN
MOV [page-blog-index, pagetype], [page-blog-index, blog]
MOV [page-blog-x, pagetype], [page-blog-x, blog]
MOV [page-tag-x, pagetype], [page-tag-x, tag]
MOV [page-course-view-weeks, pagetype], [page-course-view-weeks, format_weeks]
MOV [page-course-view-weeks-x, pagetype], [page-course-view-weeks-x, format_weeks]
MOV [page-course-view-topics, pagetype], [page-course-view-topics, format_topics]
MOV [page-course-view-topics-x, pagetype], [page-course-view-topics-x, format_topics]
AMOS END
2011-04-28 11:20:30 +08:00
while ( count ( $bits ) > 0 ) {
$pattern = implode ( '-' , $bits ) . '-*' ;
$pagetypestringname = 'page-' . str_replace ( '*' , 'x' , $pattern );
// guessing page type description
if ( get_string_manager () -> string_exists ( $pagetypestringname , 'pagetype' )) {
$patterns [ $pattern ] = get_string ( $pagetypestringname , 'pagetype' );
} else {
$patterns [ $pattern ] = $pattern ;
}
array_pop ( $bits );
}
$patterns [ '*' ] = get_string ( 'page-x' , 'pagetype' );
return $patterns ;
}
2011-06-16 16:40:01 +08:00
/**
* Generates the page type list for the my moodle page
*
* @ param string $pagetype
* @ param stdClass $parentcontext
* @ param stdClass $currentcontext
* @ return array
*/
2011-06-17 16:23:10 +08:00
function my_page_type_list ( $pagetype , $parentcontext = null , $currentcontext = null ) {
2011-12-05 01:14:19 +01:00
return array ( 'my-index' => get_string ( 'page-my-index' , 'pagetype' ));
2011-06-16 16:40:01 +08:00
}
2011-05-03 16:29:05 +08:00
/**
* Generates the page type list for a module by either locating and using the modules callback
* or by generating a default list .
*
* @ param string $pagetype
* @ param stdClass $parentcontext
* @ param stdClass $currentcontext
* @ return array
*/
2011-06-17 16:23:10 +08:00
function mod_page_type_list ( $pagetype , $parentcontext = null , $currentcontext = null ) {
$patterns = plugin_page_type_list ( $pagetype , $parentcontext , $currentcontext );
2011-05-03 16:29:05 +08:00
if ( empty ( $patterns )) {
// if modules don't have callbacks
// generate two default page type patterns for modules only
$bits = explode ( '-' , $pagetype );
$patterns = array ( $pagetype => $pagetype );
if ( $bits [ 2 ] == 'view' ) {
$patterns [ 'mod-*-view' ] = get_string ( 'page-mod-x-view' , 'pagetype' );
} else if ( $bits [ 2 ] == 'index' ) {
$patterns [ 'mod-*-index' ] = get_string ( 'page-mod-x-index' , 'pagetype' );
}
}
return $patterns ;
}
2009-07-14 07:18:57 +00:00
/// Functions update the blocks if required by the request parameters ==========
/**
* Return a { @ link block_contents } representing the add a new block UI , if
* this user is allowed to see it .
*
* @ return block_contents an appropriate block_contents , or null if the user
* cannot add any blocks here .
*/
function block_add_block_ui ( $page , $output ) {
2009-08-10 03:39:21 +00:00
global $CFG , $OUTPUT ;
2009-07-14 07:18:57 +00:00
if ( ! $page -> user_is_editing () || ! $page -> user_can_edit_blocks ()) {
return null ;
}
$bc = new block_contents ();
$bc -> title = get_string ( 'addblock' );
$bc -> add_class ( 'block_adminblock' );
2013-07-05 15:44:23 +12:00
$bc -> attributes [ 'data-block' ] = 'adminblock' ;
2009-07-14 07:18:57 +00:00
2009-07-14 08:37:28 +00:00
$missingblocks = $page -> blocks -> get_addable_blocks ();
2009-07-14 07:18:57 +00:00
if ( empty ( $missingblocks )) {
2009-07-14 08:37:28 +00:00
$bc -> content = get_string ( 'noblockstoaddhere' );
2009-07-14 07:18:57 +00:00
return $bc ;
}
$menu = array ();
2009-07-14 08:37:28 +00:00
foreach ( $missingblocks as $block ) {
2016-11-18 17:27:38 +08:00
$menu [ $block -> name ] = $block -> title ;
2009-07-14 07:18:57 +00:00
}
2010-01-17 10:54:13 +00:00
$actionurl = new moodle_url ( $page -> url , array ( 'sesskey' => sesskey ()));
2010-02-10 09:37:50 +00:00
$select = new single_select ( $actionurl , 'bui_addblock' , $menu , null , array ( '' => get_string ( 'adddots' )), 'add_block' );
2012-12-05 14:24:53 +08:00
$select -> set_label ( get_string ( 'addblock' ), array ( 'class' => 'accesshide' ));
2010-02-10 09:37:50 +00:00
$bc -> content = $OUTPUT -> render ( $select );
2009-07-14 07:18:57 +00:00
return $bc ;
}
2009-05-06 09:15:05 +00:00
/**
* Actually delete from the database any blocks that are currently on this page ,
* but which should not be there according to blocks_name_allowed_in_format .
2009-05-22 02:18:49 +00:00
*
2010-08-28 11:54:24 +00:00
* @ todo Write / Fix this function . Currently returns immediately
2009-06-12 11:56:30 +00:00
* @ param $course
2009-05-06 09:15:05 +00:00
*/
2009-06-12 11:56:30 +00:00
function blocks_remove_inappropriate ( $course ) {
2009-05-06 09:15:05 +00:00
// TODO
return ;
2010-09-17 07:49:39 +00:00
/*
2009-05-06 09:15:05 +00:00
$blockmanager = blocks_get_by_page ( $page );
2004-11-08 19:36:07 +00:00
2009-12-16 18:00:58 +00:00
if ( empty ( $blockmanager )) {
2004-11-08 19:36:07 +00:00
return ;
}
2009-12-16 18:00:58 +00:00
if (( $pageformat = $page -> pagetype ) == NULL ) {
2004-11-08 19:36:07 +00:00
return ;
}
2009-05-06 09:27:02 +00:00
foreach ( $blockmanager as $region ) {
foreach ( $region as $instance ) {
2004-11-08 19:36:07 +00:00
$block = blocks_get_record ( $instance -> blockid );
2005-02-10 18:43:18 +00:00
if ( ! blocks_name_allowed_in_format ( $block -> name , $pageformat )) {
2009-07-14 08:37:28 +00:00
blocks_delete_instance ( $instance -> instance );
2004-11-08 19:36:07 +00:00
}
}
2010-09-17 07:49:39 +00:00
} */
2004-11-08 19:36:07 +00:00
}
2009-05-22 02:18:49 +00:00
/**
* Check that a given name is in a permittable format
*
* @ param string $name
* @ param string $pageformat
* @ return bool
*/
2005-02-10 18:43:18 +00:00
function blocks_name_allowed_in_format ( $name , $pageformat ) {
2009-05-06 08:36:50 +00:00
$accept = NULL ;
$maxdepth = - 1 ;
2012-03-18 18:37:24 +01:00
if ( ! $bi = block_instance ( $name )) {
return false ;
}
$formats = $bi -> applicable_formats ();
2009-05-06 08:36:50 +00:00
if ( ! $formats ) {
$formats = array ();
}
foreach ( $formats as $format => $allowed ) {
$formatregex = '/^' . str_replace ( '*' , '[^-]*' , $format ) . '.*$/' ;
$depth = substr_count ( $format , '-' );
if ( preg_match ( $formatregex , $pageformat ) && $depth > $maxdepth ) {
$maxdepth = $depth ;
$accept = $allowed ;
2005-02-10 18:43:18 +00:00
}
}
2009-05-06 08:36:50 +00:00
if ( $accept === NULL ) {
2005-02-10 18:43:18 +00:00
$accept = ! empty ( $formats [ 'all' ]);
}
return $accept ;
}
2009-05-07 09:16:22 +00:00
/**
* Delete a block , and associated data .
2009-05-22 02:18:49 +00:00
*
2009-05-07 09:16:22 +00:00
* @ param object $instance a row from the block_instances table
2010-08-28 11:54:24 +00:00
* @ param bool $nolongerused legacy parameter . Not used , but kept for backwards compatibility .
2009-05-22 02:18:49 +00:00
* @ param bool $skipblockstables for internal use only . Makes @ see blocks_delete_all_for_context () more efficient .
2009-05-07 09:16:22 +00:00
*/
function blocks_delete_instance ( $instance , $nolongerused = false , $skipblockstables = false ) {
2009-05-08 06:34:40 +00:00
global $DB ;
2016-02-23 17:22:27 +08:00
// Allow plugins to use this block before we completely delete it.
if ( $pluginsfunction = get_plugins_with_function ( 'pre_block_delete' )) {
foreach ( $pluginsfunction as $plugintype => $plugins ) {
foreach ( $plugins as $pluginfunction ) {
$pluginfunction ( $instance );
}
}
}
2009-05-08 06:34:40 +00:00
if ( $block = block_instance ( $instance -> blockname , $instance )) {
2009-05-07 09:16:22 +00:00
$block -> instance_delete ();
}
2013-07-05 15:20:34 +08:00
context_helper :: delete_instance ( CONTEXT_BLOCK , $instance -> id );
2004-11-08 19:36:07 +00:00
2009-05-07 09:16:22 +00:00
if ( ! $skipblockstables ) {
$DB -> delete_records ( 'block_positions' , array ( 'blockinstanceid' => $instance -> id ));
$DB -> delete_records ( 'block_instances' , array ( 'id' => $instance -> id ));
2010-09-20 02:28:42 +00:00
$DB -> delete_records_list ( 'user_preferences' , 'name' , array ( 'block' . $instance -> id . 'hidden' , 'docked_block_instance_' . $instance -> id ));
2005-06-13 03:32:31 +00:00
}
2009-05-07 09:16:22 +00:00
}
2005-06-13 03:32:31 +00:00
2015-08-27 18:20:59 +08:00
/**
* Delete multiple blocks at once .
*
* @ param array $instanceids A list of block instance ID .
*/
function blocks_delete_instances ( $instanceids ) {
global $DB ;
2016-04-11 10:10:00 +08:00
$limit = 1000 ;
$count = count ( $instanceids );
$chunks = [ $instanceids ];
if ( $count > $limit ) {
$chunks = array_chunk ( $instanceids , $limit );
2015-08-27 18:20:59 +08:00
}
2016-04-11 10:10:00 +08:00
// Perform deletion for each chunk.
foreach ( $chunks as $chunk ) {
$instances = $DB -> get_recordset_list ( 'block_instances' , 'id' , $chunk );
foreach ( $instances as $instance ) {
blocks_delete_instance ( $instance , false , true );
}
$instances -> close ();
$DB -> delete_records_list ( 'block_positions' , 'blockinstanceid' , $chunk );
$DB -> delete_records_list ( 'block_instances' , 'id' , $chunk );
2015-08-27 18:20:59 +08:00
2016-04-11 10:10:00 +08:00
$preferences = array ();
foreach ( $chunk as $instanceid ) {
$preferences [] = 'block' . $instanceid . 'hidden' ;
$preferences [] = 'docked_block_instance_' . $instanceid ;
}
$DB -> delete_records_list ( 'user_preferences' , 'name' , $preferences );
2015-08-27 18:20:59 +08:00
}
}
2009-05-07 09:16:22 +00:00
/**
* Delete all the blocks that belong to a particular context .
2009-05-22 02:18:49 +00:00
*
* @ param int $contextid the context id .
2009-05-07 09:16:22 +00:00
*/
function blocks_delete_all_for_context ( $contextid ) {
global $DB ;
2009-07-14 08:37:28 +00:00
$instances = $DB -> get_recordset ( 'block_instances' , array ( 'parentcontextid' => $contextid ));
2009-05-07 09:16:22 +00:00
foreach ( $instances as $instance ) {
blocks_delete_instance ( $instance , true );
2005-08-16 00:25:39 +00:00
}
2009-05-07 09:16:22 +00:00
$instances -> close ();
2009-07-10 05:58:59 +00:00
$DB -> delete_records ( 'block_instances' , array ( 'parentcontextid' => $contextid ));
2009-05-07 09:16:22 +00:00
$DB -> delete_records ( 'block_positions' , array ( 'contextid' => $contextid ));
2004-11-08 19:36:07 +00:00
}
2009-07-15 07:41:25 +00:00
/**
* Set a block to be visible or hidden on a particular page .
*
* @ param object $instance a row from the block_instances , preferably LEFT JOINed with the
* block_positions table as return by block_manager .
* @ param moodle_page $page the back to set the visibility with respect to .
* @ param integer $newvisibility 1 for visible , 0 for hidden .
*/
function blocks_set_visibility ( $instance , $page , $newvisibility ) {
global $DB ;
if ( ! empty ( $instance -> blockpositionid )) {
// Already have local information on this page.
$DB -> set_field ( 'block_positions' , 'visible' , $newvisibility , array ( 'id' => $instance -> blockpositionid ));
return ;
}
// Create a new block_positions record.
$bp = new stdClass ;
$bp -> blockinstanceid = $instance -> id ;
$bp -> contextid = $page -> context -> id ;
$bp -> pagetype = $page -> pagetype ;
if ( $page -> subpage ) {
$bp -> subpage = $page -> subpage ;
}
$bp -> visible = $newvisibility ;
$bp -> region = $instance -> defaultregion ;
$bp -> weight = $instance -> defaultweight ;
$DB -> insert_record ( 'block_positions' , $bp );
}
2009-05-06 09:14:42 +00:00
/**
2010-08-28 11:54:24 +00:00
* Get the block record for a particular blockid - that is , a particular type os block .
2009-05-22 02:18:49 +00:00
*
* @ param $int blockid block type id . If null , an array of all block types is returned .
* @ param bool $notusedanymore No longer used .
2009-05-06 09:14:42 +00:00
* @ return array | object row from block table , or all rows .
*/
function blocks_get_record ( $blockid = NULL , $notusedanymore = false ) {
global $PAGE ;
$blocks = $PAGE -> blocks -> get_installed_blocks ();
if ( $blockid === NULL ) {
return $blocks ;
} else if ( isset ( $blocks [ $blockid ])) {
return $blocks [ $blockid ];
} else {
return false ;
2004-10-19 21:04:28 +00:00
}
}
2009-05-22 02:18:49 +00:00
/**
* Find a given block by its blockid within a provide array
*
* @ param int $blockid
* @ param array $blocksarray
* @ return bool | object Instance if found else false
*/
2004-10-19 21:04:28 +00:00
function blocks_find_block ( $blockid , $blocksarray ) {
2005-08-16 00:25:39 +00:00
if ( empty ( $blocksarray )) {
return false ;
}
2004-10-19 21:04:28 +00:00
foreach ( $blocksarray as $blockgroup ) {
2005-08-16 00:25:39 +00:00
if ( empty ( $blockgroup )) {
continue ;
}
2004-10-19 21:04:28 +00:00
foreach ( $blockgroup as $instance ) {
if ( $instance -> blockid == $blockid ) {
return $instance ;
}
}
}
return false ;
}
2009-07-09 07:35:03 +00:00
// Functions for programatically adding default blocks to pages ================
2004-04-18 23:20:53 +00:00
2015-02-09 09:41:32 +00:00
/**
* Parse a list of default blocks . See config - dist for a description of the format .
*
* @ param string $blocksstr Determines the starting point that the blocks are added in the region .
* @ return array the parsed list of default blocks
*/
2009-05-07 07:05:22 +00:00
function blocks_parse_default_blocks_list ( $blocksstr ) {
2009-05-07 08:55:10 +00:00
$blocks = array ();
$bits = explode ( ':' , $blocksstr );
if ( ! empty ( $bits )) {
2009-08-28 08:47:31 +00:00
$leftbits = trim ( array_shift ( $bits ));
if ( $leftbits != '' ) {
$blocks [ BLOCK_POS_LEFT ] = explode ( ',' , $leftbits );
}
2009-05-07 08:55:10 +00:00
}
if ( ! empty ( $bits )) {
2015-02-09 09:41:32 +00:00
$rightbits = trim ( array_shift ( $bits ));
2009-08-28 08:47:31 +00:00
if ( $rightbits != '' ) {
$blocks [ BLOCK_POS_RIGHT ] = explode ( ',' , $rightbits );
}
2009-05-07 08:55:10 +00:00
}
return $blocks ;
2009-05-07 07:05:22 +00:00
}
2004-10-09 20:16:05 +00:00
2009-05-07 07:05:22 +00:00
/**
* @ return array the blocks that should be added to the site course by default .
*/
function blocks_get_default_site_course_blocks () {
global $CFG ;
2004-10-19 21:04:28 +00:00
2016-10-07 09:37:07 +01:00
if ( isset ( $CFG -> defaultblocks_site )) {
2009-05-07 08:55:10 +00:00
return blocks_parse_default_blocks_list ( $CFG -> defaultblocks_site );
2009-05-07 07:05:22 +00:00
} else {
2009-05-07 08:55:10 +00:00
return array (
2016-10-13 13:46:38 +08:00
BLOCK_POS_LEFT => array (),
BLOCK_POS_RIGHT => array ()
2009-05-07 07:05:22 +00:00
);
2004-10-19 21:04:28 +00:00
}
2009-05-07 07:05:22 +00:00
}
/**
* Add the default blocks to a course .
2009-05-22 02:18:49 +00:00
*
2009-05-07 07:05:22 +00:00
* @ param object $course a course object .
*/
function blocks_add_default_course_blocks ( $course ) {
global $CFG ;
2016-10-07 09:37:07 +01:00
if ( isset ( $CFG -> defaultblocks_override )) {
2009-05-07 07:05:22 +00:00
$blocknames = blocks_parse_default_blocks_list ( $CFG -> defaultblocks_override );
} else if ( $course -> id == SITEID ) {
$blocknames = blocks_get_default_site_course_blocks ();
2016-10-07 09:37:07 +01:00
} else if ( isset ( $CFG -> { 'defaultblocks_' . $course -> format })) {
2012-10-11 16:47:26 +08:00
$blocknames = blocks_parse_default_blocks_list ( $CFG -> { 'defaultblocks_' . $course -> format });
2004-10-19 21:04:28 +00:00
2012-10-11 16:47:26 +08:00
} else {
2013-04-08 11:34:05 +10:00
require_once ( $CFG -> dirroot . '/course/lib.php' );
2012-10-11 16:47:26 +08:00
$blocknames = course_get_format ( $course ) -> get_default_blocks ();
2009-05-07 07:05:22 +00:00
2004-10-19 21:04:28 +00:00
}
2009-05-07 08:55:10 +00:00
if ( $course -> id == SITEID ) {
$pagetypepattern = 'site-index' ;
} else {
$pagetypepattern = 'course-view-*' ;
}
2009-05-07 07:05:22 +00:00
$page = new moodle_page ();
$page -> set_course ( $course );
2009-05-07 08:55:10 +00:00
$page -> blocks -> add_blocks ( $blocknames , $pagetypepattern );
2009-05-07 07:05:22 +00:00
}
/**
* Add the default system - context blocks . E . g . the admin tree .
*/
function blocks_add_default_system_blocks () {
2010-05-04 13:04:35 +00:00
global $DB ;
2009-05-07 07:05:22 +00:00
$page = new moodle_page ();
2012-07-25 16:25:55 +08:00
$page -> set_context ( context_system :: instance ());
2016-12-02 10:00:43 +08:00
// We don't add blocks required by the theme, they will be auto-created.
2009-08-28 08:47:31 +00:00
$page -> blocks -> add_blocks ( array ( BLOCK_POS_LEFT => array ( 'admin_bookmarks' )), 'admin-*' , null , null , 2 );
2010-05-04 13:04:35 +00:00
2014-10-06 18:57:17 +08:00
if ( $defaultmypage = $DB -> get_record ( 'my_pages' , array ( 'userid' => null , 'name' => '__default' , 'private' => 1 ))) {
$subpagepattern = $defaultmypage -> id ;
} else {
$subpagepattern = null ;
}
2014-06-26 20:10:11 +08:00
$newblocks = array ( 'private_files' , 'online_users' , 'badges' , 'calendar_month' , 'calendar_upcoming' );
2016-04-11 16:54:11 +08:00
$newcontent = array ( 'lp' , 'course_overview' );
2014-10-06 18:57:17 +08:00
$page -> blocks -> add_blocks ( array ( BLOCK_POS_RIGHT => $newblocks , 'content' => $newcontent ), 'my-index' , $subpagepattern );
2009-05-07 07:05:22 +00:00
}