| 1 | efrain | 1 | <?php
 | 
        
           |  |  | 2 |   | 
        
           |  |  | 3 | // This file is part of Moodle - http://moodle.org/
 | 
        
           |  |  | 4 | //
 | 
        
           |  |  | 5 | // Moodle is free software: you can redistribute it and/or modify
 | 
        
           |  |  | 6 | // it under the terms of the GNU General Public License as published by
 | 
        
           |  |  | 7 | // the Free Software Foundation, either version 3 of the License, or
 | 
        
           |  |  | 8 | // (at your option) any later version.
 | 
        
           |  |  | 9 | //
 | 
        
           |  |  | 10 | // Moodle is distributed in the hope that it will be useful,
 | 
        
           |  |  | 11 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
        
           |  |  | 12 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
        
           |  |  | 13 | // GNU General Public License for more details.
 | 
        
           |  |  | 14 | //
 | 
        
           |  |  | 15 | // You should have received a copy of the GNU General Public License
 | 
        
           |  |  | 16 | // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
 | 
        
           |  |  | 17 |   | 
        
           |  |  | 18 | /**
 | 
        
           |  |  | 19 |  * Block Class and Functions
 | 
        
           |  |  | 20 |  *
 | 
        
           |  |  | 21 |  * This file defines the {@link block_manager} class,
 | 
        
           |  |  | 22 |  *
 | 
        
           |  |  | 23 |  * @package    core
 | 
        
           |  |  | 24 |  * @subpackage block
 | 
        
           |  |  | 25 |  * @copyright  1999 onwards Martin Dougiamas  http://dougiamas.com
 | 
        
           |  |  | 26 |  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 | 
        
           |  |  | 27 |  */
 | 
        
           |  |  | 28 |   | 
        
           |  |  | 29 | defined('MOODLE_INTERNAL') || die();
 | 
        
           |  |  | 30 |   | 
        
           |  |  | 31 | /**#@+
 | 
        
           |  |  | 32 |  * Default names for the block regions in the standard theme.
 | 
        
           |  |  | 33 |  */
 | 
        
           |  |  | 34 | define('BLOCK_POS_LEFT',  'side-pre');
 | 
        
           |  |  | 35 | define('BLOCK_POS_RIGHT', 'side-post');
 | 
        
           |  |  | 36 | /**#@-*/
 | 
        
           |  |  | 37 |   | 
        
           |  |  | 38 | define('BUI_CONTEXTS_FRONTPAGE_ONLY', 0);
 | 
        
           |  |  | 39 | define('BUI_CONTEXTS_FRONTPAGE_SUBS', 1);
 | 
        
           |  |  | 40 | define('BUI_CONTEXTS_ENTIRE_SITE', 2);
 | 
        
           |  |  | 41 |   | 
        
           |  |  | 42 | define('BUI_CONTEXTS_CURRENT', 0);
 | 
        
           |  |  | 43 | define('BUI_CONTEXTS_CURRENT_SUBS', 1);
 | 
        
           |  |  | 44 |   | 
        
           |  |  | 45 | // Position of "Add block" control, to be used in theme config as a value for $THEME->addblockposition:
 | 
        
           |  |  | 46 | // - default: as a fake block that is displayed in editing mode
 | 
        
           |  |  | 47 | // - flatnav: "Add block" item in the flat navigation drawer in editing mode
 | 
        
           |  |  | 48 | // - custom: none of the above, theme will take care of displaying the control.
 | 
        
           |  |  | 49 | define('BLOCK_ADDBLOCK_POSITION_DEFAULT', 0);
 | 
        
           |  |  | 50 | define('BLOCK_ADDBLOCK_POSITION_FLATNAV', 1);
 | 
        
           |  |  | 51 | define('BLOCK_ADDBLOCK_POSITION_CUSTOM', -1);
 | 
        
           |  |  | 52 |   | 
        
           |  |  | 53 | /**
 | 
        
           |  |  | 54 |  * Exception thrown when someone tried to do something with a block that does
 | 
        
           |  |  | 55 |  * not exist on a page.
 | 
        
           |  |  | 56 |  *
 | 
        
           |  |  | 57 |  * @copyright 2009 Tim Hunt
 | 
        
           |  |  | 58 |  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 | 
        
           |  |  | 59 |  * @since     Moodle 2.0
 | 
        
           |  |  | 60 |  */
 | 
        
           |  |  | 61 | class block_not_on_page_exception extends moodle_exception {
 | 
        
           |  |  | 62 |     /**
 | 
        
           |  |  | 63 |      * Constructor
 | 
        
           |  |  | 64 |      * @param int $instanceid the block instance id of the block that was looked for.
 | 
        
           |  |  | 65 |      * @param object $page the current page.
 | 
        
           |  |  | 66 |      */
 | 
        
           |  |  | 67 |     public function __construct($instanceid, $page) {
 | 
        
           |  |  | 68 |         $a = new stdClass;
 | 
        
           |  |  | 69 |         $a->instanceid = $instanceid;
 | 
        
           |  |  | 70 |         $a->url = $page->url->out();
 | 
        
           |  |  | 71 |         parent::__construct('blockdoesnotexistonpage', '', $page->url->out(), $a);
 | 
        
           |  |  | 72 |     }
 | 
        
           |  |  | 73 | }
 | 
        
           |  |  | 74 |   | 
        
           |  |  | 75 | /**
 | 
        
           |  |  | 76 |  * This class keeps track of the block that should appear on a moodle_page.
 | 
        
           |  |  | 77 |  *
 | 
        
           |  |  | 78 |  * The page to work with as passed to the constructor.
 | 
        
           |  |  | 79 |  *
 | 
        
           |  |  | 80 |  * @copyright 2009 Tim Hunt
 | 
        
           |  |  | 81 |  * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 | 
        
           |  |  | 82 |  * @since     Moodle 2.0
 | 
        
           |  |  | 83 |  */
 | 
        
           |  |  | 84 | class block_manager {
 | 
        
           |  |  | 85 |     /**
 | 
        
           |  |  | 86 |      * The UI normally only shows block weights between -MAX_WEIGHT and MAX_WEIGHT,
 | 
        
           |  |  | 87 |      * although other weights are valid.
 | 
        
           |  |  | 88 |      */
 | 
        
           |  |  | 89 |     const MAX_WEIGHT = 10;
 | 
        
           |  |  | 90 |   | 
        
           |  |  | 91 | /// Field declarations =========================================================
 | 
        
           |  |  | 92 |   | 
        
           |  |  | 93 |     /**
 | 
        
           |  |  | 94 |      * the moodle_page we are managing blocks for.
 | 
        
           |  |  | 95 |      * @var moodle_page
 | 
        
           |  |  | 96 |      */
 | 
        
           |  |  | 97 |     protected $page;
 | 
        
           |  |  | 98 |   | 
        
           |  |  | 99 |     /** @var array region name => 1.*/
 | 
        
           |  |  | 100 |     protected $regions = array();
 | 
        
           |  |  | 101 |   | 
        
           |  |  | 102 |     /** @var string the region where new blocks are added.*/
 | 
        
           |  |  | 103 |     protected $defaultregion = null;
 | 
        
           |  |  | 104 |   | 
        
           |  |  | 105 |     /** @var array will be $DB->get_records('blocks') */
 | 
        
           |  |  | 106 |     protected $allblocks = null;
 | 
        
           |  |  | 107 |   | 
        
           |  |  | 108 |     /**
 | 
        
           |  |  | 109 |      * @var array blocks that this user can add to this page. Will be a subset
 | 
        
           |  |  | 110 |      * of $allblocks, but with array keys block->name. Access this via the
 | 
        
           |  |  | 111 |      * {@link get_addable_blocks()} method to ensure it is lazy-loaded.
 | 
        
           |  |  | 112 |      */
 | 
        
           |  |  | 113 |     protected $addableblocks = null;
 | 
        
           |  |  | 114 |   | 
        
           |  |  | 115 |     /**
 | 
        
           |  |  | 116 |      * Will be an array region-name => array(db rows loaded in load_blocks);
 | 
        
           |  |  | 117 |      * @var array
 | 
        
           |  |  | 118 |      */
 | 
        
           |  |  | 119 |     protected $birecordsbyregion = null;
 | 
        
           |  |  | 120 |   | 
        
           |  |  | 121 |     /**
 | 
        
           |  |  | 122 |      * array region-name => array(block objects); populated as necessary by
 | 
        
           |  |  | 123 |      * the ensure_instances_exist method.
 | 
        
           |  |  | 124 |      * @var array
 | 
        
           |  |  | 125 |      */
 | 
        
           |  |  | 126 |     protected $blockinstances = array();
 | 
        
           |  |  | 127 |   | 
        
           |  |  | 128 |     /**
 | 
        
           |  |  | 129 |      * array region-name => array(block_contents objects) what actually needs to
 | 
        
           |  |  | 130 |      * be displayed in each region.
 | 
        
           |  |  | 131 |      * @var array
 | 
        
           |  |  | 132 |      */
 | 
        
           |  |  | 133 |     protected $visibleblockcontent = array();
 | 
        
           |  |  | 134 |   | 
        
           |  |  | 135 |     /**
 | 
        
           |  |  | 136 |      * array region-name => array(block_contents objects) extra block-like things
 | 
        
           |  |  | 137 |      * to be displayed in each region, before the real blocks.
 | 
        
           |  |  | 138 |      * @var array
 | 
        
           |  |  | 139 |      */
 | 
        
           |  |  | 140 |     protected $extracontent = array();
 | 
        
           |  |  | 141 |   | 
        
           |  |  | 142 |     /**
 | 
        
           |  |  | 143 |      * Used by the block move id, to track whether a block is currently being moved.
 | 
        
           |  |  | 144 |      *
 | 
        
           |  |  | 145 |      * When you click on the move icon of a block, first the page needs to reload with
 | 
        
           |  |  | 146 |      * extra UI for choosing a new position for a particular block. In that situation
 | 
        
           |  |  | 147 |      * this field holds the id of the block being moved.
 | 
        
           |  |  | 148 |      *
 | 
        
           |  |  | 149 |      * @var integer|null
 | 
        
           |  |  | 150 |      */
 | 
        
           |  |  | 151 |     protected $movingblock = null;
 | 
        
           |  |  | 152 |   | 
        
           |  |  | 153 |     /**
 | 
        
           |  |  | 154 |      * Show only fake blocks
 | 
        
           |  |  | 155 |      */
 | 
        
           |  |  | 156 |     protected $fakeblocksonly = false;
 | 
        
           |  |  | 157 |   | 
        
           |  |  | 158 | /// Constructor ================================================================
 | 
        
           |  |  | 159 |   | 
        
           |  |  | 160 |     /**
 | 
        
           |  |  | 161 |      * Constructor.
 | 
        
           |  |  | 162 |      * @param object $page the moodle_page object object we are managing the blocks for,
 | 
        
           |  |  | 163 |      * or a reasonable faxilimily. (See the comment at the top of this class
 | 
        
           |  |  | 164 |      * and {@link http://en.wikipedia.org/wiki/Duck_typing})
 | 
        
           |  |  | 165 |      */
 | 
        
           |  |  | 166 |     public function __construct($page) {
 | 
        
           |  |  | 167 |         $this->page = $page;
 | 
        
           |  |  | 168 |     }
 | 
        
           |  |  | 169 |   | 
        
           |  |  | 170 | /// Getter methods =============================================================
 | 
        
           |  |  | 171 |   | 
        
           |  |  | 172 |     /**
 | 
        
           |  |  | 173 |      * Get an array of all region names on this page where a block may appear
 | 
        
           |  |  | 174 |      *
 | 
        
           |  |  | 175 |      * @return array the internal names of the regions on this page where block may appear.
 | 
        
           |  |  | 176 |      */
 | 
        
           |  |  | 177 |     public function get_regions() {
 | 
        
           |  |  | 178 |         if (is_null($this->defaultregion)) {
 | 
        
           |  |  | 179 |             $this->page->initialise_theme_and_output();
 | 
        
           |  |  | 180 |         }
 | 
        
           |  |  | 181 |         return array_keys($this->regions);
 | 
        
           |  |  | 182 |     }
 | 
        
           |  |  | 183 |   | 
        
           |  |  | 184 |     /**
 | 
        
           |  |  | 185 |      * Get the region name of the region blocks are added to by default
 | 
        
           |  |  | 186 |      *
 | 
        
           |  |  | 187 |      * @return string the internal names of the region where new blocks are added
 | 
        
           |  |  | 188 |      * by default, and where any blocks from an unrecognised region are shown.
 | 
        
           |  |  | 189 |      * (Imagine that blocks were added with one theme selected, then you switched
 | 
        
           |  |  | 190 |      * to a theme with different block positions.)
 | 
        
           |  |  | 191 |      */
 | 
        
           |  |  | 192 |     public function get_default_region() {
 | 
        
           |  |  | 193 |         $this->page->initialise_theme_and_output();
 | 
        
           |  |  | 194 |         return $this->defaultregion;
 | 
        
           |  |  | 195 |     }
 | 
        
           |  |  | 196 |   | 
        
           |  |  | 197 |     /**
 | 
        
           |  |  | 198 |      * The list of block types that may be added to this page.
 | 
        
           |  |  | 199 |      *
 | 
        
           |  |  | 200 |      * @return array block name => record from block table.
 | 
        
           |  |  | 201 |      */
 | 
        
           |  |  | 202 |     public function get_addable_blocks() {
 | 
        
           |  |  | 203 |         $this->check_is_loaded();
 | 
        
           |  |  | 204 |   | 
        
           |  |  | 205 |         if (!is_null($this->addableblocks)) {
 | 
        
           |  |  | 206 |             return $this->addableblocks;
 | 
        
           |  |  | 207 |         }
 | 
        
           |  |  | 208 |   | 
        
           |  |  | 209 |         // Lazy load.
 | 
        
           |  |  | 210 |         $this->addableblocks = array();
 | 
        
           |  |  | 211 |   | 
        
           |  |  | 212 |         $allblocks = blocks_get_record();
 | 
        
           |  |  | 213 |         if (empty($allblocks)) {
 | 
        
           |  |  | 214 |             return $this->addableblocks;
 | 
        
           |  |  | 215 |         }
 | 
        
           |  |  | 216 |   | 
        
           |  |  | 217 |         $undeletableblocks = self::get_undeletable_block_types();
 | 
        
           |  |  | 218 |         $unaddablebythemeblocks = $this->get_unaddable_by_theme_block_types();
 | 
        
           |  |  | 219 |         $requiredbythemeblocks = $this->get_required_by_theme_block_types();
 | 
        
           |  |  | 220 |         $pageformat = $this->page->pagetype;
 | 
        
           |  |  | 221 |         foreach($allblocks as $block) {
 | 
        
           |  |  | 222 |             if (!$bi = block_instance($block->name)) {
 | 
        
           |  |  | 223 |                 continue;
 | 
        
           |  |  | 224 |             }
 | 
        
           |  |  | 225 |             if ($block->visible && !in_array($block->name, $undeletableblocks) &&
 | 
        
           |  |  | 226 |                     !in_array($block->name, $requiredbythemeblocks) &&
 | 
        
           |  |  | 227 |                     !in_array($block->name, $unaddablebythemeblocks) &&
 | 
        
           |  |  | 228 |                     $bi->can_block_be_added($this->page) &&
 | 
        
           |  |  | 229 |                     ($bi->instance_allow_multiple() || !$this->is_block_present($block->name)) &&
 | 
        
           |  |  | 230 |                     blocks_name_allowed_in_format($block->name, $pageformat) &&
 | 
        
           |  |  | 231 |                     $bi->user_can_addto($this->page)) {
 | 
        
           |  |  | 232 |                 $block->title = $bi->get_title();
 | 
        
           |  |  | 233 |                 $this->addableblocks[$block->name] = $block;
 | 
        
           |  |  | 234 |             }
 | 
        
           |  |  | 235 |         }
 | 
        
           |  |  | 236 |   | 
        
           |  |  | 237 |         core_collator::asort_objects_by_property($this->addableblocks, 'title');
 | 
        
           |  |  | 238 |         return $this->addableblocks;
 | 
        
           |  |  | 239 |     }
 | 
        
           |  |  | 240 |   | 
        
           |  |  | 241 |     /**
 | 
        
           |  |  | 242 |      * Given a block name, find out of any of them are currently present in the page
 | 
        
           |  |  | 243 |   | 
        
           |  |  | 244 |      * @param string $blockname - the basic name of a block (eg "navigation")
 | 
        
           |  |  | 245 |      * @return boolean - is there one of these blocks in the current page?
 | 
        
           |  |  | 246 |      */
 | 
        
           |  |  | 247 |     public function is_block_present($blockname) {
 | 
        
           | 1441 | ariadna | 248 |         if (empty($this->birecordsbyregion)) {
 | 
        
           | 1 | efrain | 249 |             return false;
 | 
        
           |  |  | 250 |         }
 | 
        
           |  |  | 251 |   | 
        
           |  |  | 252 |         $requiredbythemeblocks = $this->get_required_by_theme_block_types();
 | 
        
           | 1441 | ariadna | 253 |         foreach ($this->birecordsbyregion as $region) {
 | 
        
           | 1 | efrain | 254 |             foreach ($region as $instance) {
 | 
        
           | 1441 | ariadna | 255 |                 if (empty($instance->blockname)) {
 | 
        
           | 1 | efrain | 256 |                     continue;
 | 
        
           |  |  | 257 |                 }
 | 
        
           | 1441 | ariadna | 258 |                 if ($instance->blockname == $blockname) {
 | 
        
           |  |  | 259 |                     if ($instance->requiredbytheme) {
 | 
        
           | 1 | efrain | 260 |                         if (!in_array($blockname, $requiredbythemeblocks)) {
 | 
        
           |  |  | 261 |                             continue;
 | 
        
           |  |  | 262 |                         }
 | 
        
           |  |  | 263 |                     }
 | 
        
           |  |  | 264 |                     return true;
 | 
        
           |  |  | 265 |                 }
 | 
        
           |  |  | 266 |             }
 | 
        
           |  |  | 267 |         }
 | 
        
           |  |  | 268 |         return false;
 | 
        
           |  |  | 269 |     }
 | 
        
           |  |  | 270 |   | 
        
           |  |  | 271 |     /**
 | 
        
           |  |  | 272 |      * Find out if a block type is known by the system
 | 
        
           |  |  | 273 |      *
 | 
        
           |  |  | 274 |      * @param string $blockname the name of the type of block.
 | 
        
           |  |  | 275 |      * @param boolean $includeinvisible if false (default) only check 'visible' blocks, that is, blocks enabled by the admin.
 | 
        
           |  |  | 276 |      * @return boolean true if this block in installed.
 | 
        
           |  |  | 277 |      */
 | 
        
           |  |  | 278 |     public function is_known_block_type($blockname, $includeinvisible = false) {
 | 
        
           |  |  | 279 |         $blocks = $this->get_installed_blocks();
 | 
        
           |  |  | 280 |         foreach ($blocks as $block) {
 | 
        
           |  |  | 281 |             if ($block->name == $blockname && ($includeinvisible || $block->visible)) {
 | 
        
           |  |  | 282 |                 return true;
 | 
        
           |  |  | 283 |             }
 | 
        
           |  |  | 284 |         }
 | 
        
           |  |  | 285 |         return false;
 | 
        
           |  |  | 286 |     }
 | 
        
           |  |  | 287 |   | 
        
           |  |  | 288 |     /**
 | 
        
           |  |  | 289 |      * Find out if a region exists on a page
 | 
        
           |  |  | 290 |      *
 | 
        
           |  |  | 291 |      * @param string $region a region name
 | 
        
           |  |  | 292 |      * @return boolean true if this region exists on this page.
 | 
        
           |  |  | 293 |      */
 | 
        
           |  |  | 294 |     public function is_known_region($region) {
 | 
        
           |  |  | 295 |         if (empty($region)) {
 | 
        
           |  |  | 296 |             return false;
 | 
        
           |  |  | 297 |         }
 | 
        
           |  |  | 298 |         return array_key_exists($region, $this->regions);
 | 
        
           |  |  | 299 |     }
 | 
        
           |  |  | 300 |   | 
        
           |  |  | 301 |     /**
 | 
        
           |  |  | 302 |      * Get an array of all blocks within a given region
 | 
        
           |  |  | 303 |      *
 | 
        
           |  |  | 304 |      * @param string $region a block region that exists on this page.
 | 
        
           |  |  | 305 |      * @return array of block instances.
 | 
        
           |  |  | 306 |      */
 | 
        
           |  |  | 307 |     public function get_blocks_for_region($region) {
 | 
        
           |  |  | 308 |         $this->check_is_loaded();
 | 
        
           |  |  | 309 |         $this->ensure_instances_exist($region);
 | 
        
           |  |  | 310 |         return $this->blockinstances[$region];
 | 
        
           |  |  | 311 |     }
 | 
        
           |  |  | 312 |   | 
        
           |  |  | 313 |     /**
 | 
        
           |  |  | 314 |      * Returns an array of block content objects that exist in a region
 | 
        
           |  |  | 315 |      *
 | 
        
           |  |  | 316 |      * @param string $region a block region that exists on this page.
 | 
        
           |  |  | 317 |      * @return array of block block_contents objects for all the blocks in a region.
 | 
        
           |  |  | 318 |      */
 | 
        
           |  |  | 319 |     public function get_content_for_region($region, $output) {
 | 
        
           |  |  | 320 |         $this->check_is_loaded();
 | 
        
           |  |  | 321 |         $this->ensure_content_created($region, $output);
 | 
        
           |  |  | 322 |         return $this->visibleblockcontent[$region];
 | 
        
           |  |  | 323 |     }
 | 
        
           |  |  | 324 |   | 
        
           |  |  | 325 |     /**
 | 
        
           |  |  | 326 |      * Returns an array of block content objects for all the existings regions
 | 
        
           |  |  | 327 |      *
 | 
        
           |  |  | 328 |      * @param renderer_base $output the rendered to use
 | 
        
           |  |  | 329 |      * @return array of block block_contents objects for all the blocks in all regions.
 | 
        
           |  |  | 330 |      * @since  Moodle 3.3
 | 
        
           |  |  | 331 |      */
 | 
        
           |  |  | 332 |     public function get_content_for_all_regions($output) {
 | 
        
           |  |  | 333 |         $contents = array();
 | 
        
           |  |  | 334 |         $this->check_is_loaded();
 | 
        
           |  |  | 335 |   | 
        
           |  |  | 336 |         foreach ($this->regions as $region => $val) {
 | 
        
           |  |  | 337 |             $this->ensure_content_created($region, $output);
 | 
        
           |  |  | 338 |             $contents[$region] = $this->visibleblockcontent[$region];
 | 
        
           |  |  | 339 |         }
 | 
        
           |  |  | 340 |         return $contents;
 | 
        
           |  |  | 341 |     }
 | 
        
           |  |  | 342 |   | 
        
           |  |  | 343 |     /**
 | 
        
           |  |  | 344 |      * Helper method used by get_content_for_region.
 | 
        
           |  |  | 345 |      * @param string $region region name
 | 
        
           |  |  | 346 |      * @param float $weight weight. May be fractional, since you may want to move a block
 | 
        
           |  |  | 347 |      * between ones with weight 2 and 3, say ($weight would be 2.5).
 | 
        
           |  |  | 348 |      * @return moodle_url URL for moving block $this->movingblock to this position.
 | 
        
           |  |  | 349 |      */
 | 
        
           |  |  | 350 |     protected function get_move_target_url($region, $weight) {
 | 
        
           |  |  | 351 |         return new moodle_url($this->page->url, array('bui_moveid' => $this->movingblock,
 | 
        
           |  |  | 352 |                 'bui_newregion' => $region, 'bui_newweight' => $weight, 'sesskey' => sesskey()));
 | 
        
           |  |  | 353 |     }
 | 
        
           |  |  | 354 |   | 
        
           |  |  | 355 |     /**
 | 
        
           |  |  | 356 |      * Determine whether a region contains anything. (Either any real blocks, or
 | 
        
           |  |  | 357 |      * the add new block UI.)
 | 
        
           |  |  | 358 |      *
 | 
        
           |  |  | 359 |      * (You may wonder why the $output parameter is required. Unfortunately,
 | 
        
           |  |  | 360 |      * because of the way that blocks work, the only reliable way to find out
 | 
        
           |  |  | 361 |      * if a block will be visible is to get the content for output, and to
 | 
        
           |  |  | 362 |      * get the content, you need a renderer. Fortunately, this is not a
 | 
        
           |  |  | 363 |      * performance problem, because we cache the output that is generated, and
 | 
        
           |  |  | 364 |      * in almost every case where we call region_has_content, we are about to
 | 
        
           |  |  | 365 |      * output the blocks anyway, so we are not doing wasted effort.)
 | 
        
           |  |  | 366 |      *
 | 
        
           |  |  | 367 |      * @param string $region a block region that exists on this page.
 | 
        
           |  |  | 368 |      * @param core_renderer $output a core_renderer. normally the global $OUTPUT.
 | 
        
           |  |  | 369 |      * @return boolean Whether there is anything in this region.
 | 
        
           |  |  | 370 |      */
 | 
        
           |  |  | 371 |     public function region_has_content($region, $output) {
 | 
        
           |  |  | 372 |   | 
        
           |  |  | 373 |         if (!$this->is_known_region($region)) {
 | 
        
           |  |  | 374 |             return false;
 | 
        
           |  |  | 375 |         }
 | 
        
           |  |  | 376 |         $this->check_is_loaded();
 | 
        
           |  |  | 377 |         $this->ensure_content_created($region, $output);
 | 
        
           |  |  | 378 |         // if ($this->page->user_is_editing() && $this->page->user_can_edit_blocks()) {
 | 
        
           |  |  | 379 |         // Mark Nielsen's patch - part 1
 | 
        
           |  |  | 380 |         if ($this->page->user_is_editing() && $this->page->user_can_edit_blocks() && $this->movingblock) {
 | 
        
           |  |  | 381 |             // If editing is on, we need all the block regions visible, for the
 | 
        
           |  |  | 382 |             // move blocks UI.
 | 
        
           |  |  | 383 |             return true;
 | 
        
           |  |  | 384 |         }
 | 
        
           |  |  | 385 |         return !empty($this->visibleblockcontent[$region]) || !empty($this->extracontent[$region]);
 | 
        
           |  |  | 386 |     }
 | 
        
           |  |  | 387 |   | 
        
           |  |  | 388 |     /**
 | 
        
           |  |  | 389 |      * Determine whether a region contains any fake blocks.
 | 
        
           |  |  | 390 |      *
 | 
        
           |  |  | 391 |      * (Fake blocks are typically added to the extracontent array per region)
 | 
        
           |  |  | 392 |      *
 | 
        
           |  |  | 393 |      * @param string $region a block region that exists on this page.
 | 
        
           |  |  | 394 |      * @return boolean Whether there are fake blocks in this region.
 | 
        
           |  |  | 395 |      */
 | 
        
           |  |  | 396 |     public function region_has_fakeblocks($region): bool {
 | 
        
           |  |  | 397 |         return !empty($this->extracontent[$region]);
 | 
        
           |  |  | 398 |     }
 | 
        
           |  |  | 399 |   | 
        
           |  |  | 400 |     /**
 | 
        
           |  |  | 401 |      * Get an array of all of the installed blocks.
 | 
        
           |  |  | 402 |      *
 | 
        
           |  |  | 403 |      * @return array contents of the block table.
 | 
        
           |  |  | 404 |      */
 | 
        
           |  |  | 405 |     public function get_installed_blocks() {
 | 
        
           |  |  | 406 |         global $DB;
 | 
        
           |  |  | 407 |         if (is_null($this->allblocks)) {
 | 
        
           |  |  | 408 |             $this->allblocks = $DB->get_records('block');
 | 
        
           |  |  | 409 |         }
 | 
        
           |  |  | 410 |         return $this->allblocks;
 | 
        
           |  |  | 411 |     }
 | 
        
           |  |  | 412 |   | 
        
           |  |  | 413 |     /**
 | 
        
           |  |  | 414 |      * @return array names of block types that must exist on every page with this theme.
 | 
        
           |  |  | 415 |      */
 | 
        
           |  |  | 416 |     public function get_required_by_theme_block_types() {
 | 
        
           |  |  | 417 |         $requiredbythemeblocks = false;
 | 
        
           |  |  | 418 |         if (isset($this->page->theme->requiredblocks)) {
 | 
        
           |  |  | 419 |             $requiredbythemeblocks = $this->page->theme->requiredblocks;
 | 
        
           |  |  | 420 |         }
 | 
        
           |  |  | 421 |   | 
        
           |  |  | 422 |         if ($requiredbythemeblocks === false) {
 | 
        
           |  |  | 423 |             return array('navigation', 'settings');
 | 
        
           |  |  | 424 |         } else if ($requiredbythemeblocks === '') {
 | 
        
           |  |  | 425 |             return array();
 | 
        
           |  |  | 426 |         } else if (is_string($requiredbythemeblocks)) {
 | 
        
           |  |  | 427 |             return explode(',', $requiredbythemeblocks);
 | 
        
           |  |  | 428 |         } else {
 | 
        
           |  |  | 429 |             return $requiredbythemeblocks;
 | 
        
           |  |  | 430 |         }
 | 
        
           |  |  | 431 |     }
 | 
        
           |  |  | 432 |   | 
        
           |  |  | 433 |     /**
 | 
        
           |  |  | 434 |      * It returns the list of blocks that can't be displayed in the "Add a block" list.
 | 
        
           |  |  | 435 |      * This information is taken from the unaddableblocks theme setting.
 | 
        
           |  |  | 436 |      *
 | 
        
           |  |  | 437 |      * @return array A list with the blocks that won't be displayed in the "Add a block" list.
 | 
        
           |  |  | 438 |      */
 | 
        
           |  |  | 439 |     public function get_unaddable_by_theme_block_types(): array {
 | 
        
           |  |  | 440 |         $unaddablebythemeblocks = [];
 | 
        
           |  |  | 441 |         if (isset($this->page->theme->settings->unaddableblocks) && !empty($this->page->theme->settings->unaddableblocks)) {
 | 
        
           |  |  | 442 |             $unaddablebythemeblocks = array_map('trim', explode(',', $this->page->theme->settings->unaddableblocks));
 | 
        
           |  |  | 443 |         }
 | 
        
           |  |  | 444 |   | 
        
           |  |  | 445 |         return $unaddablebythemeblocks;
 | 
        
           |  |  | 446 |     }
 | 
        
           |  |  | 447 |   | 
        
           |  |  | 448 |     /**
 | 
        
           |  |  | 449 |      * Make this block type undeletable and unaddable.
 | 
        
           |  |  | 450 |      *
 | 
        
           |  |  | 451 |      * @param mixed $blockidorname string or int
 | 
        
           |  |  | 452 |      */
 | 
        
           |  |  | 453 |     public static function protect_block($blockidorname) {
 | 
        
           |  |  | 454 |         global $DB;
 | 
        
           |  |  | 455 |   | 
        
           |  |  | 456 |         $syscontext = context_system::instance();
 | 
        
           |  |  | 457 |   | 
        
           |  |  | 458 |         require_capability('moodle/site:config', $syscontext);
 | 
        
           |  |  | 459 |   | 
        
           |  |  | 460 |         $block = false;
 | 
        
           |  |  | 461 |         if (is_int($blockidorname)) {
 | 
        
           |  |  | 462 |             $block = $DB->get_record('block', array('id' => $blockidorname), 'id, name', MUST_EXIST);
 | 
        
           |  |  | 463 |         } else {
 | 
        
           |  |  | 464 |             $block = $DB->get_record('block', array('name' => $blockidorname), 'id, name', MUST_EXIST);
 | 
        
           |  |  | 465 |         }
 | 
        
           |  |  | 466 |         $undeletableblocktypes = self::get_undeletable_block_types();
 | 
        
           |  |  | 467 |         if (!in_array($block->name, $undeletableblocktypes)) {
 | 
        
           |  |  | 468 |             $undeletableblocktypes[] = $block->name;
 | 
        
           |  |  | 469 |             set_config('undeletableblocktypes', implode(',', $undeletableblocktypes));
 | 
        
           |  |  | 470 |             add_to_config_log('block_protect', "0", "1", $block->name);
 | 
        
           |  |  | 471 |         }
 | 
        
           |  |  | 472 |     }
 | 
        
           |  |  | 473 |   | 
        
           |  |  | 474 |     /**
 | 
        
           |  |  | 475 |      * Make this block type deletable and addable.
 | 
        
           |  |  | 476 |      *
 | 
        
           |  |  | 477 |      * @param mixed $blockidorname string or int
 | 
        
           |  |  | 478 |      */
 | 
        
           |  |  | 479 |     public static function unprotect_block($blockidorname) {
 | 
        
           |  |  | 480 |         global $DB;
 | 
        
           |  |  | 481 |   | 
        
           |  |  | 482 |         $syscontext = context_system::instance();
 | 
        
           |  |  | 483 |   | 
        
           |  |  | 484 |         require_capability('moodle/site:config', $syscontext);
 | 
        
           |  |  | 485 |   | 
        
           |  |  | 486 |         $block = false;
 | 
        
           |  |  | 487 |         if (is_int($blockidorname)) {
 | 
        
           |  |  | 488 |             $block = $DB->get_record('block', array('id' => $blockidorname), 'id, name', MUST_EXIST);
 | 
        
           |  |  | 489 |         } else {
 | 
        
           |  |  | 490 |             $block = $DB->get_record('block', array('name' => $blockidorname), 'id, name', MUST_EXIST);
 | 
        
           |  |  | 491 |         }
 | 
        
           |  |  | 492 |         $undeletableblocktypes = self::get_undeletable_block_types();
 | 
        
           |  |  | 493 |         if (in_array($block->name, $undeletableblocktypes)) {
 | 
        
           |  |  | 494 |             $undeletableblocktypes = array_diff($undeletableblocktypes, array($block->name));
 | 
        
           |  |  | 495 |             set_config('undeletableblocktypes', implode(',', $undeletableblocktypes));
 | 
        
           |  |  | 496 |             add_to_config_log('block_protect', "1", "0", $block->name);
 | 
        
           |  |  | 497 |         }
 | 
        
           |  |  | 498 |   | 
        
           |  |  | 499 |     }
 | 
        
           |  |  | 500 |   | 
        
           |  |  | 501 |     /**
 | 
        
           |  |  | 502 |      * Get the list of "protected" blocks via admin block manager ui.
 | 
        
           |  |  | 503 |      *
 | 
        
           |  |  | 504 |      * @return array names of block types that cannot be added or deleted. E.g. array('navigation','settings').
 | 
        
           |  |  | 505 |      */
 | 
        
           |  |  | 506 |     public static function get_undeletable_block_types() {
 | 
        
           |  |  | 507 |         global $CFG;
 | 
        
           |  |  | 508 |         $undeletableblocks = false;
 | 
        
           |  |  | 509 |         if (isset($CFG->undeletableblocktypes)) {
 | 
        
           |  |  | 510 |             $undeletableblocks = $CFG->undeletableblocktypes;
 | 
        
           |  |  | 511 |         }
 | 
        
           |  |  | 512 |   | 
        
           |  |  | 513 |         if (empty($undeletableblocks)) {
 | 
        
           |  |  | 514 |             return array();
 | 
        
           |  |  | 515 |         } else if (is_string($undeletableblocks)) {
 | 
        
           |  |  | 516 |             return explode(',', $undeletableblocks);
 | 
        
           |  |  | 517 |         } else {
 | 
        
           |  |  | 518 |             return $undeletableblocks;
 | 
        
           |  |  | 519 |         }
 | 
        
           |  |  | 520 |     }
 | 
        
           |  |  | 521 |   | 
        
           |  |  | 522 | /// Setter methods =============================================================
 | 
        
           |  |  | 523 |   | 
        
           |  |  | 524 |     /**
 | 
        
           |  |  | 525 |      * Add a region to a page
 | 
        
           |  |  | 526 |      *
 | 
        
           |  |  | 527 |      * @param string $region add a named region where blocks may appear on the current page.
 | 
        
           |  |  | 528 |      *      This is an internal name, like 'side-pre', not a string to display in the UI.
 | 
        
           |  |  | 529 |      * @param bool $custom True if this is a custom block region, being added by the page rather than the theme layout.
 | 
        
           |  |  | 530 |      */
 | 
        
           |  |  | 531 |     public function add_region($region, $custom = true) {
 | 
        
           |  |  | 532 |         global $SESSION;
 | 
        
           |  |  | 533 |         $this->check_not_yet_loaded();
 | 
        
           |  |  | 534 |         if ($custom) {
 | 
        
           |  |  | 535 |             if (array_key_exists($region, $this->regions)) {
 | 
        
           |  |  | 536 |                 // This here is EXACTLY why we should not be adding block regions into a page. It should
 | 
        
           |  |  | 537 |                 // ALWAYS be done in a theme layout.
 | 
        
           |  |  | 538 |                 debugging('A custom region conflicts with a block region in the theme.', DEBUG_DEVELOPER);
 | 
        
           |  |  | 539 |             }
 | 
        
           |  |  | 540 |             // We need to register this custom region against the page type being used.
 | 
        
           |  |  | 541 |             // This allows us to check, when performing block actions, that unrecognised regions can be worked with.
 | 
        
           |  |  | 542 |             $type = $this->page->pagetype;
 | 
        
           |  |  | 543 |             if (!isset($SESSION->custom_block_regions)) {
 | 
        
           |  |  | 544 |                 $SESSION->custom_block_regions = array($type => array($region));
 | 
        
           |  |  | 545 |             } else if (!isset($SESSION->custom_block_regions[$type])) {
 | 
        
           |  |  | 546 |                 $SESSION->custom_block_regions[$type] = array($region);
 | 
        
           |  |  | 547 |             } else if (!in_array($region, $SESSION->custom_block_regions[$type])) {
 | 
        
           |  |  | 548 |                 $SESSION->custom_block_regions[$type][] = $region;
 | 
        
           |  |  | 549 |             }
 | 
        
           |  |  | 550 |         }
 | 
        
           |  |  | 551 |         $this->regions[$region] = 1;
 | 
        
           |  |  | 552 |   | 
        
           |  |  | 553 |         // Checking the actual property instead of calling get_default_region as it ends up in a recursive call.
 | 
        
           |  |  | 554 |         if (empty($this->defaultregion)) {
 | 
        
           |  |  | 555 |             $this->set_default_region($region);
 | 
        
           |  |  | 556 |         }
 | 
        
           |  |  | 557 |     }
 | 
        
           |  |  | 558 |   | 
        
           |  |  | 559 |     /**
 | 
        
           |  |  | 560 |      * Add an array of regions
 | 
        
           |  |  | 561 |      * @see add_region()
 | 
        
           |  |  | 562 |      *
 | 
        
           |  |  | 563 |      * @param array $regions this utility method calls add_region for each array element.
 | 
        
           |  |  | 564 |      */
 | 
        
           |  |  | 565 |     public function add_regions($regions, $custom = true) {
 | 
        
           |  |  | 566 |         foreach ($regions as $region) {
 | 
        
           |  |  | 567 |             $this->add_region($region, $custom);
 | 
        
           |  |  | 568 |         }
 | 
        
           |  |  | 569 |     }
 | 
        
           |  |  | 570 |   | 
        
           |  |  | 571 |     /**
 | 
        
           |  |  | 572 |      * Finds custom block regions associated with a page type and registers them with this block manager.
 | 
        
           |  |  | 573 |      *
 | 
        
           |  |  | 574 |      * @param string $pagetype
 | 
        
           |  |  | 575 |      */
 | 
        
           |  |  | 576 |     public function add_custom_regions_for_pagetype($pagetype) {
 | 
        
           |  |  | 577 |         global $SESSION;
 | 
        
           |  |  | 578 |         if (isset($SESSION->custom_block_regions[$pagetype])) {
 | 
        
           |  |  | 579 |             foreach ($SESSION->custom_block_regions[$pagetype] as $customregion) {
 | 
        
           |  |  | 580 |                 $this->add_region($customregion, false);
 | 
        
           |  |  | 581 |             }
 | 
        
           |  |  | 582 |         }
 | 
        
           |  |  | 583 |     }
 | 
        
           |  |  | 584 |   | 
        
           |  |  | 585 |     /**
 | 
        
           |  |  | 586 |      * Set the default region for new blocks on the page
 | 
        
           |  |  | 587 |      *
 | 
        
           |  |  | 588 |      * @param string $defaultregion the internal names of the region where new
 | 
        
           |  |  | 589 |      * blocks should be added by default, and where any blocks from an
 | 
        
           |  |  | 590 |      * unrecognised region are shown.
 | 
        
           |  |  | 591 |      */
 | 
        
           |  |  | 592 |     public function set_default_region($defaultregion) {
 | 
        
           |  |  | 593 |         $this->check_not_yet_loaded();
 | 
        
           |  |  | 594 |         if ($defaultregion) {
 | 
        
           |  |  | 595 |             $this->check_region_is_known($defaultregion);
 | 
        
           |  |  | 596 |         }
 | 
        
           |  |  | 597 |         $this->defaultregion = $defaultregion;
 | 
        
           |  |  | 598 |     }
 | 
        
           |  |  | 599 |   | 
        
           |  |  | 600 |     /**
 | 
        
           |  |  | 601 |      * Add something that looks like a block, but which isn't an actual block_instance,
 | 
        
           |  |  | 602 |      * to this page.
 | 
        
           |  |  | 603 |      *
 | 
        
           |  |  | 604 |      * @param block_contents $bc the content of the block-like thing.
 | 
        
           |  |  | 605 |      * @param string $region a block region that exists on this page.
 | 
        
           |  |  | 606 |      */
 | 
        
           |  |  | 607 |     public function add_fake_block($bc, $region) {
 | 
        
           |  |  | 608 |         $this->page->initialise_theme_and_output();
 | 
        
           |  |  | 609 |         if (!$this->is_known_region($region)) {
 | 
        
           |  |  | 610 |             $region = $this->get_default_region();
 | 
        
           |  |  | 611 |         }
 | 
        
           |  |  | 612 |         if (array_key_exists($region, $this->visibleblockcontent)) {
 | 
        
           |  |  | 613 |             throw new coding_exception('block_manager has already prepared the blocks in region ' .
 | 
        
           |  |  | 614 |                     $region . 'for output. It is too late to add a fake block.');
 | 
        
           |  |  | 615 |         }
 | 
        
           |  |  | 616 |         if (!isset($bc->attributes['data-block'])) {
 | 
        
           |  |  | 617 |             $bc->attributes['data-block'] = '_fake';
 | 
        
           |  |  | 618 |         }
 | 
        
           |  |  | 619 |         $bc->attributes['class'] .= ' block_fake';
 | 
        
           |  |  | 620 |         $this->extracontent[$region][] = $bc;
 | 
        
           |  |  | 621 |     }
 | 
        
           |  |  | 622 |   | 
        
           |  |  | 623 |     /**
 | 
        
           |  |  | 624 |      * Checks to see whether all of the blocks within the given region are docked
 | 
        
           |  |  | 625 |      *
 | 
        
           |  |  | 626 |      * @see region_uses_dock
 | 
        
           |  |  | 627 |      * @param string $region
 | 
        
           |  |  | 628 |      * @return bool True if all of the blocks within that region are docked
 | 
        
           |  |  | 629 |      *
 | 
        
           |  |  | 630 |      * Return false as from MDL-64506
 | 
        
           |  |  | 631 |      */
 | 
        
           |  |  | 632 |     public function region_completely_docked($region, $output) {
 | 
        
           |  |  | 633 |         return false;
 | 
        
           |  |  | 634 |     }
 | 
        
           |  |  | 635 |   | 
        
           |  |  | 636 |     /**
 | 
        
           |  |  | 637 |      * Checks to see whether any of the blocks within the given regions are docked
 | 
        
           |  |  | 638 |      *
 | 
        
           |  |  | 639 |      * @see region_completely_docked
 | 
        
           |  |  | 640 |      * @param array|string $regions array of regions (or single region)
 | 
        
           |  |  | 641 |      * @return bool True if any of the blocks within that region are docked
 | 
        
           |  |  | 642 |      *
 | 
        
           |  |  | 643 |      * Return false as from MDL-64506
 | 
        
           |  |  | 644 |      */
 | 
        
           |  |  | 645 |     public function region_uses_dock($regions, $output) {
 | 
        
           |  |  | 646 |         return false;
 | 
        
           |  |  | 647 |     }
 | 
        
           |  |  | 648 |   | 
        
           |  |  | 649 | /// Actions ====================================================================
 | 
        
           |  |  | 650 |   | 
        
           |  |  | 651 |     /**
 | 
        
           |  |  | 652 |      * This method actually loads the blocks for our page from the database.
 | 
        
           |  |  | 653 |      *
 | 
        
           |  |  | 654 |      * @param boolean|null $includeinvisible
 | 
        
           |  |  | 655 |      *      null (default) - load hidden blocks if $this->page->user_is_editing();
 | 
        
           |  |  | 656 |      *      true - load hidden blocks.
 | 
        
           |  |  | 657 |      *      false - don't load hidden blocks.
 | 
        
           |  |  | 658 |      */
 | 
        
           |  |  | 659 |     public function load_blocks($includeinvisible = null) {
 | 
        
           |  |  | 660 |         global $DB, $CFG;
 | 
        
           |  |  | 661 |   | 
        
           |  |  | 662 |         if (!is_null($this->birecordsbyregion)) {
 | 
        
           |  |  | 663 |             // Already done.
 | 
        
           |  |  | 664 |             return;
 | 
        
           |  |  | 665 |         }
 | 
        
           |  |  | 666 |   | 
        
           |  |  | 667 |         if ($CFG->version < 2009050619) {
 | 
        
           |  |  | 668 |             // Upgrade/install not complete. Don't try too show any blocks.
 | 
        
           |  |  | 669 |             $this->birecordsbyregion = array();
 | 
        
           |  |  | 670 |             return;
 | 
        
           |  |  | 671 |         }
 | 
        
           |  |  | 672 |   | 
        
           |  |  | 673 |         // Ensure we have been initialised.
 | 
        
           |  |  | 674 |         if (is_null($this->defaultregion)) {
 | 
        
           |  |  | 675 |             $this->page->initialise_theme_and_output();
 | 
        
           |  |  | 676 |             // If there are still no block regions, then there are no blocks on this page.
 | 
        
           |  |  | 677 |             if (empty($this->regions)) {
 | 
        
           |  |  | 678 |                 $this->birecordsbyregion = array();
 | 
        
           |  |  | 679 |                 return;
 | 
        
           |  |  | 680 |             }
 | 
        
           |  |  | 681 |         }
 | 
        
           |  |  | 682 |   | 
        
           |  |  | 683 |         // Check if we need to load normal blocks
 | 
        
           |  |  | 684 |         if ($this->fakeblocksonly) {
 | 
        
           |  |  | 685 |             $this->birecordsbyregion = $this->prepare_per_region_arrays();
 | 
        
           |  |  | 686 |             return;
 | 
        
           |  |  | 687 |         }
 | 
        
           |  |  | 688 |   | 
        
           |  |  | 689 |         // Exclude auto created blocks if they are not undeletable in this theme.
 | 
        
           |  |  | 690 |         $requiredbytheme = $this->get_required_by_theme_block_types();
 | 
        
           |  |  | 691 |         $requiredbythemecheck = '';
 | 
        
           |  |  | 692 |         $requiredbythemeparams = array();
 | 
        
           |  |  | 693 |         $requiredbythemenotparams = array();
 | 
        
           |  |  | 694 |         if (!empty($requiredbytheme)) {
 | 
        
           |  |  | 695 |             list($testsql, $requiredbythemeparams) = $DB->get_in_or_equal($requiredbytheme, SQL_PARAMS_NAMED, 'requiredbytheme');
 | 
        
           |  |  | 696 |             list($testnotsql, $requiredbythemenotparams) = $DB->get_in_or_equal($requiredbytheme, SQL_PARAMS_NAMED,
 | 
        
           |  |  | 697 |                                                                                 'notrequiredbytheme', false);
 | 
        
           |  |  | 698 |             $requiredbythemecheck = 'AND ((bi.blockname ' . $testsql . ' AND bi.requiredbytheme = 1) OR ' .
 | 
        
           |  |  | 699 |                                 ' (bi.blockname ' . $testnotsql . ' AND bi.requiredbytheme = 0))';
 | 
        
           |  |  | 700 |         } else {
 | 
        
           |  |  | 701 |             $requiredbythemecheck = 'AND (bi.requiredbytheme = 0)';
 | 
        
           |  |  | 702 |         }
 | 
        
           |  |  | 703 |   | 
        
           |  |  | 704 |         if (is_null($includeinvisible)) {
 | 
        
           |  |  | 705 |             $includeinvisible = $this->page->user_is_editing();
 | 
        
           |  |  | 706 |         }
 | 
        
           |  |  | 707 |         if ($includeinvisible) {
 | 
        
           |  |  | 708 |             $visiblecheck = '';
 | 
        
           |  |  | 709 |         } else {
 | 
        
           |  |  | 710 |             $visiblecheck = 'AND (bp.visible = 1 OR bp.visible IS NULL) AND (bs.visible = 1 OR bs.visible IS NULL)';
 | 
        
           |  |  | 711 |         }
 | 
        
           |  |  | 712 |   | 
        
           |  |  | 713 |         $context = $this->page->context;
 | 
        
           |  |  | 714 |         $contexttest = 'bi.parentcontextid IN (:contextid2, :contextid3)';
 | 
        
           |  |  | 715 |         $parentcontextparams = array();
 | 
        
           |  |  | 716 |         $parentcontextids = $context->get_parent_context_ids();
 | 
        
           |  |  | 717 |         if ($parentcontextids) {
 | 
        
           |  |  | 718 |             list($parentcontexttest, $parentcontextparams) =
 | 
        
           |  |  | 719 |                     $DB->get_in_or_equal($parentcontextids, SQL_PARAMS_NAMED, 'parentcontext');
 | 
        
           |  |  | 720 |             $contexttest = "($contexttest OR (bi.showinsubcontexts = 1 AND bi.parentcontextid $parentcontexttest))";
 | 
        
           |  |  | 721 |         }
 | 
        
           |  |  | 722 |   | 
        
           |  |  | 723 |         $pagetypepatterns = matching_page_type_patterns($this->page->pagetype);
 | 
        
           |  |  | 724 |         list($pagetypepatterntest, $pagetypepatternparams) =
 | 
        
           |  |  | 725 |                 $DB->get_in_or_equal($pagetypepatterns, SQL_PARAMS_NAMED, 'pagetypepatterntest');
 | 
        
           |  |  | 726 |   | 
        
           |  |  | 727 |         $ccselect = ', ' . context_helper::get_preload_record_columns_sql('ctx');
 | 
        
           |  |  | 728 |         $ccjoin = "LEFT JOIN {context} ctx ON (ctx.instanceid = bi.id AND ctx.contextlevel = :contextlevel)";
 | 
        
           |  |  | 729 |   | 
        
           |  |  | 730 |         $systemcontext = context_system::instance();
 | 
        
           |  |  | 731 |         $params = array(
 | 
        
           |  |  | 732 |             'contextlevel' => CONTEXT_BLOCK,
 | 
        
           |  |  | 733 |             'subpage1' => $this->page->subpage,
 | 
        
           |  |  | 734 |             'subpage2' => $this->page->subpage,
 | 
        
           |  |  | 735 |             'subpage3' => $this->page->subpage,
 | 
        
           |  |  | 736 |             'contextid1' => $context->id,
 | 
        
           |  |  | 737 |             'contextid2' => $context->id,
 | 
        
           |  |  | 738 |             'contextid3' => $systemcontext->id,
 | 
        
           |  |  | 739 |             'contextid4' => $systemcontext->id,
 | 
        
           |  |  | 740 |             'pagetype' => $this->page->pagetype,
 | 
        
           |  |  | 741 |             'pagetype2' => $this->page->pagetype,
 | 
        
           |  |  | 742 |         );
 | 
        
           |  |  | 743 |         if ($this->page->subpage === '') {
 | 
        
           |  |  | 744 |             $params['subpage1'] = '';
 | 
        
           |  |  | 745 |             $params['subpage2'] = '';
 | 
        
           |  |  | 746 |             $params['subpage3'] = '';
 | 
        
           |  |  | 747 |         }
 | 
        
           |  |  | 748 |         $sql = "SELECT
 | 
        
           |  |  | 749 |                     bi.id,
 | 
        
           |  |  | 750 |                     COALESCE(bp.id, bs.id) AS blockpositionid,
 | 
        
           |  |  | 751 |                     bi.blockname,
 | 
        
           |  |  | 752 |                     bi.parentcontextid,
 | 
        
           |  |  | 753 |                     bi.showinsubcontexts,
 | 
        
           |  |  | 754 |                     bi.pagetypepattern,
 | 
        
           |  |  | 755 |                     bi.requiredbytheme,
 | 
        
           |  |  | 756 |                     bi.subpagepattern,
 | 
        
           |  |  | 757 |                     bi.defaultregion,
 | 
        
           |  |  | 758 |                     bi.defaultweight,
 | 
        
           |  |  | 759 |                     COALESCE(bp.visible, bs.visible, 1) AS visible,
 | 
        
           |  |  | 760 |                     COALESCE(bp.region, bs.region, bi.defaultregion) AS region,
 | 
        
           |  |  | 761 |                     COALESCE(bp.weight, bs.weight, bi.defaultweight) AS weight,
 | 
        
           |  |  | 762 |                     bi.configdata
 | 
        
           |  |  | 763 |                     $ccselect
 | 
        
           |  |  | 764 |   | 
        
           |  |  | 765 |                 FROM {block_instances} bi
 | 
        
           |  |  | 766 |                 JOIN {block} b ON bi.blockname = b.name
 | 
        
           |  |  | 767 |                 LEFT JOIN {block_positions} bp ON bp.blockinstanceid = bi.id
 | 
        
           |  |  | 768 |                                                   AND bp.contextid = :contextid1
 | 
        
           |  |  | 769 |                                                   AND bp.pagetype = :pagetype
 | 
        
           |  |  | 770 |                                                   AND bp.subpage = :subpage1
 | 
        
           |  |  | 771 |                 LEFT JOIN {block_positions} bs ON bs.blockinstanceid = bi.id
 | 
        
           |  |  | 772 |                                                   AND bs.contextid = :contextid4
 | 
        
           |  |  | 773 |                                                   AND bs.pagetype = :pagetype2
 | 
        
           |  |  | 774 |                                                   AND bs.subpage = :subpage3
 | 
        
           |  |  | 775 |                 $ccjoin
 | 
        
           |  |  | 776 |   | 
        
           |  |  | 777 |                 WHERE
 | 
        
           |  |  | 778 |                 $contexttest
 | 
        
           |  |  | 779 |                 AND bi.pagetypepattern $pagetypepatterntest
 | 
        
           |  |  | 780 |                 AND (bi.subpagepattern IS NULL OR bi.subpagepattern = :subpage2)
 | 
        
           |  |  | 781 |                 $visiblecheck
 | 
        
           |  |  | 782 |                 AND b.visible = 1
 | 
        
           |  |  | 783 |                 $requiredbythemecheck
 | 
        
           |  |  | 784 |   | 
        
           |  |  | 785 |                 ORDER BY
 | 
        
           |  |  | 786 |                     COALESCE(bp.region, bs.region, bi.defaultregion),
 | 
        
           |  |  | 787 |                     COALESCE(bp.weight, bs.weight, bi.defaultweight),
 | 
        
           |  |  | 788 |                     bi.id";
 | 
        
           |  |  | 789 |   | 
        
           |  |  | 790 |         $allparams = $params + $parentcontextparams + $pagetypepatternparams + $requiredbythemeparams + $requiredbythemenotparams;
 | 
        
           |  |  | 791 |         $blockinstances = $DB->get_recordset_sql($sql, $allparams);
 | 
        
           |  |  | 792 |   | 
        
           |  |  | 793 |         $this->birecordsbyregion = $this->prepare_per_region_arrays();
 | 
        
           |  |  | 794 |         $unknown = array();
 | 
        
           |  |  | 795 |         foreach ($blockinstances as $bi) {
 | 
        
           |  |  | 796 |             context_helper::preload_from_record($bi);
 | 
        
           |  |  | 797 |             if ($this->is_known_region($bi->region)) {
 | 
        
           |  |  | 798 |                 $this->birecordsbyregion[$bi->region][] = $bi;
 | 
        
           |  |  | 799 |             } else {
 | 
        
           |  |  | 800 |                 $unknown[] = $bi;
 | 
        
           |  |  | 801 |             }
 | 
        
           |  |  | 802 |         }
 | 
        
           |  |  | 803 |         $blockinstances->close();
 | 
        
           |  |  | 804 |   | 
        
           |  |  | 805 |         // Pages don't necessarily have a defaultregion. The  one time this can
 | 
        
           |  |  | 806 |         // happen is when there are no theme block regions, but the script itself
 | 
        
           |  |  | 807 |         // has a block region in the main content area.
 | 
        
           |  |  | 808 |         if (!empty($this->defaultregion)) {
 | 
        
           |  |  | 809 |             $this->birecordsbyregion[$this->defaultregion] =
 | 
        
           |  |  | 810 |                     array_merge($this->birecordsbyregion[$this->defaultregion], $unknown);
 | 
        
           |  |  | 811 |         }
 | 
        
           |  |  | 812 |     }
 | 
        
           |  |  | 813 |   | 
        
           |  |  | 814 |     /**
 | 
        
           |  |  | 815 |      * Add a block to the current page, or related pages. The block is added to
 | 
        
           |  |  | 816 |      * context $this->page->contextid. If $pagetypepattern $subpagepattern
 | 
        
           |  |  | 817 |      *
 | 
        
           |  |  | 818 |      * @param string $blockname The type of block to add.
 | 
        
           |  |  | 819 |      * @param string $region the block region on this page to add the block to.
 | 
        
           |  |  | 820 |      * @param integer $weight determines the order where this block appears in the region.
 | 
        
           |  |  | 821 |      * @param boolean $showinsubcontexts whether this block appears in subcontexts, or just the current context.
 | 
        
           |  |  | 822 |      * @param string|null $pagetypepattern which page types this block should appear on. Defaults to just the current page type.
 | 
        
           |  |  | 823 |      * @param string|null $subpagepattern which subpage this block should appear on. NULL = any (the default), otherwise only the specified subpage.
 | 
        
           |  |  | 824 |      * @return block_base
 | 
        
           |  |  | 825 |      */
 | 
        
           |  |  | 826 |     public function add_block($blockname, $region, $weight, $showinsubcontexts, $pagetypepattern = NULL, $subpagepattern = NULL) {
 | 
        
           |  |  | 827 |         global $DB;
 | 
        
           |  |  | 828 |         // Allow invisible blocks because this is used when adding default page blocks, which
 | 
        
           |  |  | 829 |         // might include invisible ones if the user makes some default blocks invisible
 | 
        
           |  |  | 830 |         $this->check_known_block_type($blockname, true);
 | 
        
           |  |  | 831 |         $this->check_region_is_known($region);
 | 
        
           |  |  | 832 |   | 
        
           |  |  | 833 |         if (empty($pagetypepattern)) {
 | 
        
           |  |  | 834 |             $pagetypepattern = $this->page->pagetype;
 | 
        
           |  |  | 835 |         }
 | 
        
           |  |  | 836 |   | 
        
           | 1441 | ariadna | 837 |         if (!empty($this->birecordsbyregion)) {
 | 
        
           |  |  | 838 |             $addableblocks = $this->get_addable_blocks();
 | 
        
           |  |  | 839 |   | 
        
           |  |  | 840 |             if (!array_key_exists($blockname, $addableblocks)) {
 | 
        
           |  |  | 841 |                 throw new moodle_exception('blockcannotadd');
 | 
        
           |  |  | 842 |             }
 | 
        
           |  |  | 843 |         }
 | 
        
           |  |  | 844 |   | 
        
           | 1 | efrain | 845 |         $blockinstance = new stdClass;
 | 
        
           |  |  | 846 |         $blockinstance->blockname = $blockname;
 | 
        
           |  |  | 847 |         $blockinstance->parentcontextid = $this->page->context->id;
 | 
        
           |  |  | 848 |         $blockinstance->showinsubcontexts = !empty($showinsubcontexts);
 | 
        
           |  |  | 849 |         $blockinstance->pagetypepattern = $pagetypepattern;
 | 
        
           |  |  | 850 |         $blockinstance->subpagepattern = $subpagepattern;
 | 
        
           |  |  | 851 |         $blockinstance->defaultregion = $region;
 | 
        
           |  |  | 852 |         $blockinstance->defaultweight = $weight;
 | 
        
           |  |  | 853 |         $blockinstance->configdata = '';
 | 
        
           |  |  | 854 |         $blockinstance->timecreated = time();
 | 
        
           |  |  | 855 |         $blockinstance->timemodified = $blockinstance->timecreated;
 | 
        
           |  |  | 856 |         $blockinstance->id = $DB->insert_record('block_instances', $blockinstance);
 | 
        
           |  |  | 857 |   | 
        
           |  |  | 858 |         // Ensure the block context is created.
 | 
        
           |  |  | 859 |         context_block::instance($blockinstance->id);
 | 
        
           |  |  | 860 |   | 
        
           |  |  | 861 |         // If the new instance was created, allow it to do additional setup
 | 
        
           |  |  | 862 |         if ($block = block_instance($blockname, $blockinstance)) {
 | 
        
           |  |  | 863 |             $block->instance_create();
 | 
        
           |  |  | 864 |         }
 | 
        
           |  |  | 865 |   | 
        
           |  |  | 866 |         if (!is_null($this->birecordsbyregion)) {
 | 
        
           |  |  | 867 |             // If blocks were already loaded on this page, reload them.
 | 
        
           |  |  | 868 |             $this->birecordsbyregion = null;
 | 
        
           |  |  | 869 |             $this->load_blocks();
 | 
        
           |  |  | 870 |         }
 | 
        
           |  |  | 871 |         return $block;
 | 
        
           |  |  | 872 |     }
 | 
        
           |  |  | 873 |   | 
        
           |  |  | 874 |     /**
 | 
        
           |  |  | 875 |      * When passed a block name create a new instance of the block in the specified region.
 | 
        
           |  |  | 876 |      *
 | 
        
           |  |  | 877 |      * @param string $blockname Name of the block to add.
 | 
        
           |  |  | 878 |      * @param null|string $blockregion If defined add the new block to the specified region.
 | 
        
           |  |  | 879 |      * @return ?block_base
 | 
        
           |  |  | 880 |      */
 | 
        
           |  |  | 881 |     public function add_block_at_end_of_default_region($blockname, $blockregion = null) {
 | 
        
           |  |  | 882 |         if (empty($this->birecordsbyregion)) {
 | 
        
           |  |  | 883 |             // No blocks or block regions exist yet.
 | 
        
           |  |  | 884 |             return null;
 | 
        
           |  |  | 885 |         }
 | 
        
           |  |  | 886 |   | 
        
           |  |  | 887 |         if ($blockregion === null) {
 | 
        
           |  |  | 888 |             $defaulregion = $this->get_default_region();
 | 
        
           |  |  | 889 |         } else {
 | 
        
           |  |  | 890 |             $defaulregion = $blockregion;
 | 
        
           |  |  | 891 |         }
 | 
        
           |  |  | 892 |   | 
        
           |  |  | 893 |         $lastcurrentblock = end($this->birecordsbyregion[$defaulregion]);
 | 
        
           |  |  | 894 |         if ($lastcurrentblock) {
 | 
        
           |  |  | 895 |             $weight = $lastcurrentblock->weight + 1;
 | 
        
           |  |  | 896 |         } else {
 | 
        
           |  |  | 897 |             $weight = 0;
 | 
        
           |  |  | 898 |         }
 | 
        
           |  |  | 899 |   | 
        
           |  |  | 900 |         if ($this->page->subpage) {
 | 
        
           |  |  | 901 |             $subpage = $this->page->subpage;
 | 
        
           |  |  | 902 |         } else {
 | 
        
           |  |  | 903 |             $subpage = null;
 | 
        
           |  |  | 904 |         }
 | 
        
           |  |  | 905 |   | 
        
           |  |  | 906 |         // Special case. Course view page type include the course format, but we
 | 
        
           |  |  | 907 |         // want to add the block non-format-specifically.
 | 
        
           |  |  | 908 |         $pagetypepattern = $this->page->pagetype;
 | 
        
           |  |  | 909 |         if (strpos($pagetypepattern, 'course-view') === 0) {
 | 
        
           |  |  | 910 |             $pagetypepattern = 'course-view-*';
 | 
        
           |  |  | 911 |         }
 | 
        
           |  |  | 912 |   | 
        
           |  |  | 913 |         // We should end using this for ALL the blocks, making always the 1st option
 | 
        
           |  |  | 914 |         // the default one to be used. Until then, this is one hack to avoid the
 | 
        
           |  |  | 915 |         // 'pagetypewarning' message on blocks initial edition (MDL-27829) caused by
 | 
        
           |  |  | 916 |         // non-existing $pagetypepattern set. This way at least we guarantee one "valid"
 | 
        
           |  |  | 917 |         // (the FIRST $pagetypepattern will be set)
 | 
        
           |  |  | 918 |   | 
        
           |  |  | 919 |         // We are applying it to all blocks created in mod pages for now and only if the
 | 
        
           |  |  | 920 |         // default pagetype is not one of the available options
 | 
        
           |  |  | 921 |         if (preg_match('/^mod-.*-/', $pagetypepattern)) {
 | 
        
           |  |  | 922 |             $pagetypelist = generate_page_type_patterns($this->page->pagetype, null, $this->page->context);
 | 
        
           |  |  | 923 |             // Only go for the first if the pagetype is not a valid option
 | 
        
           |  |  | 924 |             if (is_array($pagetypelist) && !array_key_exists($pagetypepattern, $pagetypelist)) {
 | 
        
           |  |  | 925 |                 $pagetypepattern = key($pagetypelist);
 | 
        
           |  |  | 926 |             }
 | 
        
           |  |  | 927 |         }
 | 
        
           |  |  | 928 |         // Surely other pages like course-report will need this too, they just are not important
 | 
        
           |  |  | 929 |         // enough now. This will be decided in the coming days. (MDL-27829, MDL-28150)
 | 
        
           |  |  | 930 |   | 
        
           |  |  | 931 |         return $this->add_block($blockname, $defaulregion, $weight, false, $pagetypepattern, $subpage);
 | 
        
           |  |  | 932 |     }
 | 
        
           |  |  | 933 |   | 
        
           |  |  | 934 |     /**
 | 
        
           |  |  | 935 |      * Convenience method, calls add_block repeatedly for all the blocks in $blocks. Optionally, a starting weight
 | 
        
           |  |  | 936 |      * can be used to decide the starting point that blocks are added in the region, the weight is passed to {@link add_block}
 | 
        
           |  |  | 937 |      * and incremented by the position of the block in the $blocks array
 | 
        
           |  |  | 938 |      *
 | 
        
           |  |  | 939 |      * @param array $blocks array with array keys the region names, and values an array of block names.
 | 
        
           |  |  | 940 |      * @param string|null $pagetypepattern optional. Passed to {@see self::add_block()}
 | 
        
           |  |  | 941 |      * @param string|null $subpagepattern optional. Passed to {@see self::add_block()}
 | 
        
           |  |  | 942 |      * @param bool $showinsubcontexts optional. Passed to {@see self::add_block()}
 | 
        
           |  |  | 943 |      * @param int $weight optional. Determines the starting point that the blocks are added in the region.
 | 
        
           |  |  | 944 |      */
 | 
        
           |  |  | 945 |     public function add_blocks($blocks, $pagetypepattern = NULL, $subpagepattern = NULL, $showinsubcontexts=false, $weight=0) {
 | 
        
           |  |  | 946 |         $initialweight = $weight;
 | 
        
           |  |  | 947 |         $this->add_regions(array_keys($blocks), false);
 | 
        
           |  |  | 948 |         foreach ($blocks as $region => $regionblocks) {
 | 
        
           |  |  | 949 |             foreach ($regionblocks as $offset => $blockname) {
 | 
        
           |  |  | 950 |                 $weight = $initialweight + $offset;
 | 
        
           |  |  | 951 |                 $this->add_block($blockname, $region, $weight, $showinsubcontexts, $pagetypepattern, $subpagepattern);
 | 
        
           |  |  | 952 |             }
 | 
        
           |  |  | 953 |         }
 | 
        
           |  |  | 954 |     }
 | 
        
           |  |  | 955 |   | 
        
           |  |  | 956 |     /**
 | 
        
           | 1441 | ariadna | 957 |      * Given an array of blocks in the format used by {@see add_blocks}, removes any blocks from
 | 
        
           |  |  | 958 |      * the list if they are not installed in the system.
 | 
        
           |  |  | 959 |      *
 | 
        
           |  |  | 960 |      * @param array $blocks Array keyed by region
 | 
        
           |  |  | 961 |      * @return array Updated array
 | 
        
           |  |  | 962 |      */
 | 
        
           |  |  | 963 |     public function filter_nonexistent_blocks(array $blocks): array {
 | 
        
           |  |  | 964 |         $installed = array_fill_keys(
 | 
        
           |  |  | 965 |             array_map(fn($block) => $block->name, $this->get_installed_blocks()),
 | 
        
           |  |  | 966 |             true,
 | 
        
           |  |  | 967 |         );
 | 
        
           |  |  | 968 |         $result = [];
 | 
        
           |  |  | 969 |         foreach ($blocks as $region => $regionblocks) {
 | 
        
           |  |  | 970 |             $result[$region] = [];
 | 
        
           |  |  | 971 |             foreach ($regionblocks as $blockname) {
 | 
        
           |  |  | 972 |                 if (array_key_exists($blockname, $installed)) {
 | 
        
           |  |  | 973 |                     $result[$region][] = $blockname;
 | 
        
           |  |  | 974 |                 }
 | 
        
           |  |  | 975 |             }
 | 
        
           |  |  | 976 |         }
 | 
        
           |  |  | 977 |         return $result;
 | 
        
           |  |  | 978 |     }
 | 
        
           |  |  | 979 |   | 
        
           |  |  | 980 |     /**
 | 
        
           | 1 | efrain | 981 |      * Move a block to a new position on this page.
 | 
        
           |  |  | 982 |      *
 | 
        
           |  |  | 983 |      * If this block cannot appear on any other pages, then we change defaultposition/weight
 | 
        
           |  |  | 984 |      * in the block_instances table. Otherwise we just set the position on this page.
 | 
        
           |  |  | 985 |      *
 | 
        
           |  |  | 986 |      * @param $blockinstanceid the block instance id.
 | 
        
           |  |  | 987 |      * @param $newregion the new region name.
 | 
        
           |  |  | 988 |      * @param $newweight the new weight.
 | 
        
           |  |  | 989 |      */
 | 
        
           |  |  | 990 |     public function reposition_block($blockinstanceid, $newregion, $newweight) {
 | 
        
           |  |  | 991 |         global $DB;
 | 
        
           |  |  | 992 |   | 
        
           |  |  | 993 |         $this->check_region_is_known($newregion);
 | 
        
           |  |  | 994 |         $inst = $this->find_instance($blockinstanceid);
 | 
        
           |  |  | 995 |   | 
        
           |  |  | 996 |         $bi = $inst->instance;
 | 
        
           |  |  | 997 |         if ($bi->weight == $bi->defaultweight && $bi->region == $bi->defaultregion &&
 | 
        
           |  |  | 998 |                 !$bi->showinsubcontexts && strpos($bi->pagetypepattern, '*') === false &&
 | 
        
           |  |  | 999 |                 (!$this->page->subpage || $bi->subpagepattern)) {
 | 
        
           |  |  | 1000 |   | 
        
           |  |  | 1001 |             // Set default position
 | 
        
           |  |  | 1002 |             $newbi = new stdClass;
 | 
        
           |  |  | 1003 |             $newbi->id = $bi->id;
 | 
        
           |  |  | 1004 |             $newbi->defaultregion = $newregion;
 | 
        
           |  |  | 1005 |             $newbi->defaultweight = $newweight;
 | 
        
           |  |  | 1006 |             $newbi->timemodified = time();
 | 
        
           |  |  | 1007 |             $DB->update_record('block_instances', $newbi);
 | 
        
           |  |  | 1008 |   | 
        
           |  |  | 1009 |             if ($bi->blockpositionid) {
 | 
        
           |  |  | 1010 |                 $bp = new stdClass;
 | 
        
           |  |  | 1011 |                 $bp->id = $bi->blockpositionid;
 | 
        
           |  |  | 1012 |                 $bp->region = $newregion;
 | 
        
           |  |  | 1013 |                 $bp->weight = $newweight;
 | 
        
           |  |  | 1014 |                 $DB->update_record('block_positions', $bp);
 | 
        
           |  |  | 1015 |             }
 | 
        
           |  |  | 1016 |   | 
        
           |  |  | 1017 |         } else {
 | 
        
           |  |  | 1018 |             // Just set position on this page.
 | 
        
           |  |  | 1019 |             $bp = new stdClass;
 | 
        
           |  |  | 1020 |             $bp->region = $newregion;
 | 
        
           |  |  | 1021 |             $bp->weight = $newweight;
 | 
        
           |  |  | 1022 |   | 
        
           |  |  | 1023 |             if ($bi->blockpositionid) {
 | 
        
           |  |  | 1024 |                 $bp->id = $bi->blockpositionid;
 | 
        
           |  |  | 1025 |                 $DB->update_record('block_positions', $bp);
 | 
        
           |  |  | 1026 |   | 
        
           |  |  | 1027 |             } else {
 | 
        
           |  |  | 1028 |                 $bp->blockinstanceid = $bi->id;
 | 
        
           |  |  | 1029 |                 $bp->contextid = $this->page->context->id;
 | 
        
           |  |  | 1030 |                 $bp->pagetype = $this->page->pagetype;
 | 
        
           |  |  | 1031 |                 if ($this->page->subpage) {
 | 
        
           |  |  | 1032 |                     $bp->subpage = $this->page->subpage;
 | 
        
           |  |  | 1033 |                 } else {
 | 
        
           |  |  | 1034 |                     $bp->subpage = '';
 | 
        
           |  |  | 1035 |                 }
 | 
        
           |  |  | 1036 |                 $bp->visible = $bi->visible;
 | 
        
           |  |  | 1037 |                 $DB->insert_record('block_positions', $bp);
 | 
        
           |  |  | 1038 |             }
 | 
        
           |  |  | 1039 |         }
 | 
        
           |  |  | 1040 |     }
 | 
        
           |  |  | 1041 |   | 
        
           |  |  | 1042 |     /**
 | 
        
           |  |  | 1043 |      * Find a given block by its instance id
 | 
        
           |  |  | 1044 |      *
 | 
        
           |  |  | 1045 |      * @param integer $instanceid
 | 
        
           |  |  | 1046 |      * @return block_base
 | 
        
           |  |  | 1047 |      */
 | 
        
           |  |  | 1048 |     public function find_instance($instanceid) {
 | 
        
           |  |  | 1049 |         foreach ($this->regions as $region => $notused) {
 | 
        
           |  |  | 1050 |             $this->ensure_instances_exist($region);
 | 
        
           |  |  | 1051 |             foreach($this->blockinstances[$region] as $instance) {
 | 
        
           |  |  | 1052 |                 if ($instance->instance->id == $instanceid) {
 | 
        
           |  |  | 1053 |                     return $instance;
 | 
        
           |  |  | 1054 |                 }
 | 
        
           |  |  | 1055 |             }
 | 
        
           |  |  | 1056 |         }
 | 
        
           |  |  | 1057 |         throw new block_not_on_page_exception($instanceid, $this->page);
 | 
        
           |  |  | 1058 |     }
 | 
        
           |  |  | 1059 |   | 
        
           |  |  | 1060 | /// Inner workings =============================================================
 | 
        
           |  |  | 1061 |   | 
        
           |  |  | 1062 |     /**
 | 
        
           |  |  | 1063 |      * Check whether the page blocks have been loaded yet
 | 
        
           |  |  | 1064 |      *
 | 
        
           |  |  | 1065 |      * @return void Throws coding exception if already loaded
 | 
        
           |  |  | 1066 |      */
 | 
        
           |  |  | 1067 |     protected function check_not_yet_loaded() {
 | 
        
           |  |  | 1068 |         if (!is_null($this->birecordsbyregion)) {
 | 
        
           |  |  | 1069 |             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.');
 | 
        
           |  |  | 1070 |         }
 | 
        
           |  |  | 1071 |     }
 | 
        
           |  |  | 1072 |   | 
        
           |  |  | 1073 |     /**
 | 
        
           |  |  | 1074 |      * Check whether the page blocks have been loaded yet
 | 
        
           |  |  | 1075 |      *
 | 
        
           |  |  | 1076 |      * Nearly identical to the above function {@link check_not_yet_loaded()} except different message
 | 
        
           |  |  | 1077 |      *
 | 
        
           |  |  | 1078 |      * @return void Throws coding exception if already loaded
 | 
        
           |  |  | 1079 |      */
 | 
        
           |  |  | 1080 |     protected function check_is_loaded() {
 | 
        
           |  |  | 1081 |         if (is_null($this->birecordsbyregion)) {
 | 
        
           |  |  | 1082 |             throw new coding_exception('block_manager has not yet loaded the blocks, to it is too soon to request the information you asked for.');
 | 
        
           |  |  | 1083 |         }
 | 
        
           |  |  | 1084 |     }
 | 
        
           |  |  | 1085 |   | 
        
           |  |  | 1086 |     /**
 | 
        
           |  |  | 1087 |      * Check if a block type is known and usable
 | 
        
           |  |  | 1088 |      *
 | 
        
           |  |  | 1089 |      * @param string $blockname The block type name to search for
 | 
        
           |  |  | 1090 |      * @param bool $includeinvisible Include disabled block types in the initial pass
 | 
        
           |  |  | 1091 |      * @return void Coding Exception thrown if unknown or not enabled
 | 
        
           |  |  | 1092 |      */
 | 
        
           |  |  | 1093 |     protected function check_known_block_type($blockname, $includeinvisible = false) {
 | 
        
           |  |  | 1094 |         if (!$this->is_known_block_type($blockname, $includeinvisible)) {
 | 
        
           |  |  | 1095 |             if ($this->is_known_block_type($blockname, true)) {
 | 
        
           |  |  | 1096 |                 throw new coding_exception('Unknown block type ' . $blockname);
 | 
        
           |  |  | 1097 |             } else {
 | 
        
           |  |  | 1098 |                 throw new coding_exception('Block type ' . $blockname . ' has been disabled by the administrator.');
 | 
        
           |  |  | 1099 |             }
 | 
        
           |  |  | 1100 |         }
 | 
        
           |  |  | 1101 |     }
 | 
        
           |  |  | 1102 |   | 
        
           |  |  | 1103 |     /**
 | 
        
           |  |  | 1104 |      * Check if a region is known by its name
 | 
        
           |  |  | 1105 |      *
 | 
        
           |  |  | 1106 |      * @param string $region
 | 
        
           |  |  | 1107 |      * @return void Coding Exception thrown if the region is not known
 | 
        
           |  |  | 1108 |      */
 | 
        
           |  |  | 1109 |     protected function check_region_is_known($region) {
 | 
        
           |  |  | 1110 |         if (!$this->is_known_region($region)) {
 | 
        
           |  |  | 1111 |             throw new coding_exception('Trying to reference an unknown block region ' . $region);
 | 
        
           |  |  | 1112 |         }
 | 
        
           |  |  | 1113 |     }
 | 
        
           |  |  | 1114 |   | 
        
           |  |  | 1115 |     /**
 | 
        
           |  |  | 1116 |      * Returns an array of region names as keys and nested arrays for values
 | 
        
           |  |  | 1117 |      *
 | 
        
           |  |  | 1118 |      * @return array an array where the array keys are the region names, and the array
 | 
        
           |  |  | 1119 |      * values are empty arrays.
 | 
        
           |  |  | 1120 |      */
 | 
        
           |  |  | 1121 |     protected function prepare_per_region_arrays() {
 | 
        
           |  |  | 1122 |         $result = array();
 | 
        
           |  |  | 1123 |         foreach ($this->regions as $region => $notused) {
 | 
        
           |  |  | 1124 |             $result[$region] = array();
 | 
        
           |  |  | 1125 |         }
 | 
        
           |  |  | 1126 |         return $result;
 | 
        
           |  |  | 1127 |     }
 | 
        
           |  |  | 1128 |   | 
        
           |  |  | 1129 |     /**
 | 
        
           |  |  | 1130 |      * Create a set of new block instance from a record array
 | 
        
           |  |  | 1131 |      *
 | 
        
           |  |  | 1132 |      * @param array $birecords An array of block instance records
 | 
        
           |  |  | 1133 |      * @return array An array of instantiated block_instance objects
 | 
        
           |  |  | 1134 |      */
 | 
        
           |  |  | 1135 |     protected function create_block_instances($birecords) {
 | 
        
           |  |  | 1136 |         $results = array();
 | 
        
           |  |  | 1137 |         foreach ($birecords as $record) {
 | 
        
           |  |  | 1138 |             if ($blockobject = block_instance($record->blockname, $record, $this->page)) {
 | 
        
           |  |  | 1139 |                 $results[] = $blockobject;
 | 
        
           |  |  | 1140 |             }
 | 
        
           |  |  | 1141 |         }
 | 
        
           |  |  | 1142 |         return $results;
 | 
        
           |  |  | 1143 |     }
 | 
        
           |  |  | 1144 |   | 
        
           |  |  | 1145 |     /**
 | 
        
           |  |  | 1146 |      * Create all the block instances for all the blocks that were loaded by
 | 
        
           |  |  | 1147 |      * load_blocks. This is used, for example, to ensure that all blocks get a
 | 
        
           |  |  | 1148 |      * chance to initialise themselves via the {@link block_base::specialize()}
 | 
        
           |  |  | 1149 |      * method, before any output is done.
 | 
        
           |  |  | 1150 |      *
 | 
        
           |  |  | 1151 |      * It is also used to create any blocks that are "requiredbytheme" by the current theme.
 | 
        
           |  |  | 1152 |      * These blocks that are auto-created have requiredbytheme set on the block instance
 | 
        
           |  |  | 1153 |      * so they are only visible on themes that require them.
 | 
        
           |  |  | 1154 |      */
 | 
        
           |  |  | 1155 |     public function create_all_block_instances() {
 | 
        
           |  |  | 1156 |         $missing = false;
 | 
        
           |  |  | 1157 |   | 
        
           |  |  | 1158 |         // If there are any un-removable blocks that were not created - force them.
 | 
        
           |  |  | 1159 |         $requiredbytheme = $this->get_required_by_theme_block_types();
 | 
        
           |  |  | 1160 |         if (!$this->fakeblocksonly) {
 | 
        
           |  |  | 1161 |             foreach ($requiredbytheme as $forced) {
 | 
        
           |  |  | 1162 |                 if (empty($forced)) {
 | 
        
           |  |  | 1163 |                     continue;
 | 
        
           |  |  | 1164 |                 }
 | 
        
           |  |  | 1165 |                 $found = false;
 | 
        
           |  |  | 1166 |                 foreach ($this->get_regions() as $region) {
 | 
        
           |  |  | 1167 |                     foreach($this->birecordsbyregion[$region] as $instance) {
 | 
        
           |  |  | 1168 |                         if ($instance->blockname == $forced) {
 | 
        
           |  |  | 1169 |                             $found = true;
 | 
        
           |  |  | 1170 |                         }
 | 
        
           |  |  | 1171 |                     }
 | 
        
           |  |  | 1172 |                 }
 | 
        
           |  |  | 1173 |                 if (!$found) {
 | 
        
           |  |  | 1174 |                     $this->add_block_required_by_theme($forced);
 | 
        
           |  |  | 1175 |                     $missing = true;
 | 
        
           |  |  | 1176 |                 }
 | 
        
           |  |  | 1177 |             }
 | 
        
           |  |  | 1178 |         }
 | 
        
           |  |  | 1179 |   | 
        
           |  |  | 1180 |         if ($missing) {
 | 
        
           |  |  | 1181 |             // Some blocks were missing. Lets do it again.
 | 
        
           |  |  | 1182 |             $this->birecordsbyregion = null;
 | 
        
           |  |  | 1183 |             $this->load_blocks();
 | 
        
           |  |  | 1184 |         }
 | 
        
           |  |  | 1185 |         foreach ($this->get_regions() as $region) {
 | 
        
           |  |  | 1186 |             $this->ensure_instances_exist($region);
 | 
        
           |  |  | 1187 |         }
 | 
        
           |  |  | 1188 |   | 
        
           |  |  | 1189 |     }
 | 
        
           |  |  | 1190 |   | 
        
           |  |  | 1191 |     /**
 | 
        
           |  |  | 1192 |      * Add a block that is required by the current theme but has not been
 | 
        
           |  |  | 1193 |      * created yet. This is a special type of block that only shows in themes that
 | 
        
           |  |  | 1194 |      * require it (by listing it in undeletable_block_types).
 | 
        
           |  |  | 1195 |      *
 | 
        
           |  |  | 1196 |      * @param string $blockname the name of the block type.
 | 
        
           |  |  | 1197 |      */
 | 
        
           |  |  | 1198 |     protected function add_block_required_by_theme($blockname) {
 | 
        
           |  |  | 1199 |         global $DB;
 | 
        
           |  |  | 1200 |   | 
        
           |  |  | 1201 |         if (empty($this->birecordsbyregion)) {
 | 
        
           |  |  | 1202 |             // No blocks or block regions exist yet.
 | 
        
           |  |  | 1203 |             return;
 | 
        
           |  |  | 1204 |         }
 | 
        
           |  |  | 1205 |   | 
        
           |  |  | 1206 |         // Never auto create blocks when we are showing fake blocks only.
 | 
        
           |  |  | 1207 |         if ($this->fakeblocksonly) {
 | 
        
           |  |  | 1208 |             return;
 | 
        
           |  |  | 1209 |         }
 | 
        
           |  |  | 1210 |   | 
        
           |  |  | 1211 |         // Never add a duplicate block required by theme.
 | 
        
           |  |  | 1212 |         if ($DB->record_exists('block_instances', array('blockname' => $blockname, 'requiredbytheme' => 1))) {
 | 
        
           |  |  | 1213 |             return;
 | 
        
           |  |  | 1214 |         }
 | 
        
           |  |  | 1215 |   | 
        
           |  |  | 1216 |         $systemcontext = context_system::instance();
 | 
        
           |  |  | 1217 |         $defaultregion = $this->get_default_region();
 | 
        
           |  |  | 1218 |         // Add a special system wide block instance only for themes that require it.
 | 
        
           |  |  | 1219 |         $blockinstance = new stdClass;
 | 
        
           |  |  | 1220 |         $blockinstance->blockname = $blockname;
 | 
        
           |  |  | 1221 |         $blockinstance->parentcontextid = $systemcontext->id;
 | 
        
           |  |  | 1222 |         $blockinstance->showinsubcontexts = true;
 | 
        
           |  |  | 1223 |         $blockinstance->requiredbytheme = true;
 | 
        
           |  |  | 1224 |         $blockinstance->pagetypepattern = '*';
 | 
        
           |  |  | 1225 |         $blockinstance->subpagepattern = null;
 | 
        
           |  |  | 1226 |         $blockinstance->defaultregion = $defaultregion;
 | 
        
           |  |  | 1227 |         $blockinstance->defaultweight = 0;
 | 
        
           |  |  | 1228 |         $blockinstance->configdata = '';
 | 
        
           |  |  | 1229 |         $blockinstance->timecreated = time();
 | 
        
           |  |  | 1230 |         $blockinstance->timemodified = $blockinstance->timecreated;
 | 
        
           |  |  | 1231 |         $blockinstance->id = $DB->insert_record('block_instances', $blockinstance);
 | 
        
           |  |  | 1232 |   | 
        
           |  |  | 1233 |         // Ensure the block context is created.
 | 
        
           |  |  | 1234 |         context_block::instance($blockinstance->id);
 | 
        
           |  |  | 1235 |   | 
        
           |  |  | 1236 |         // If the new instance was created, allow it to do additional setup.
 | 
        
           |  |  | 1237 |         if ($block = block_instance($blockname, $blockinstance)) {
 | 
        
           |  |  | 1238 |             $block->instance_create();
 | 
        
           |  |  | 1239 |         }
 | 
        
           |  |  | 1240 |     }
 | 
        
           |  |  | 1241 |   | 
        
           |  |  | 1242 |     /**
 | 
        
           |  |  | 1243 |      * Return an array of content objects from a set of block instances
 | 
        
           |  |  | 1244 |      *
 | 
        
           |  |  | 1245 |      * @param array $instances An array of block instances
 | 
        
           |  |  | 1246 |      * @param renderer_base The renderer to use.
 | 
        
           |  |  | 1247 |      * @param string $region the region name.
 | 
        
           |  |  | 1248 |      * @return array An array of block_content (and possibly block_move_target) objects.
 | 
        
           |  |  | 1249 |      */
 | 
        
           |  |  | 1250 |     protected function create_block_contents($instances, $output, $region) {
 | 
        
           |  |  | 1251 |         $results = array();
 | 
        
           |  |  | 1252 |   | 
        
           |  |  | 1253 |         $lastweight = 0;
 | 
        
           |  |  | 1254 |         $lastblock = 0;
 | 
        
           |  |  | 1255 |         if ($this->movingblock) {
 | 
        
           |  |  | 1256 |             $first = reset($instances);
 | 
        
           |  |  | 1257 |             if ($first) {
 | 
        
           |  |  | 1258 |                 $lastweight = $first->instance->weight - 2;
 | 
        
           |  |  | 1259 |             }
 | 
        
           |  |  | 1260 |         }
 | 
        
           |  |  | 1261 |   | 
        
           |  |  | 1262 |         foreach ($instances as $instance) {
 | 
        
           |  |  | 1263 |             $content = $instance->get_content_for_output($output);
 | 
        
           |  |  | 1264 |             if (empty($content)) {
 | 
        
           |  |  | 1265 |                 continue;
 | 
        
           |  |  | 1266 |             }
 | 
        
           |  |  | 1267 |   | 
        
           |  |  | 1268 |             if ($this->movingblock && $lastweight != $instance->instance->weight &&
 | 
        
           |  |  | 1269 |                     $content->blockinstanceid != $this->movingblock && $lastblock != $this->movingblock) {
 | 
        
           |  |  | 1270 |                 $results[] = new block_move_target($this->get_move_target_url($region, ($lastweight + $instance->instance->weight)/2));
 | 
        
           |  |  | 1271 |             }
 | 
        
           |  |  | 1272 |   | 
        
           |  |  | 1273 |             if ($content->blockinstanceid == $this->movingblock) {
 | 
        
           |  |  | 1274 |                 $content->add_class('beingmoved');
 | 
        
           |  |  | 1275 |                 $content->annotation .= get_string('movingthisblockcancel', 'block',
 | 
        
           |  |  | 1276 |                         html_writer::link($this->page->url, get_string('cancel')));
 | 
        
           |  |  | 1277 |             }
 | 
        
           |  |  | 1278 |   | 
        
           |  |  | 1279 |             $results[] = $content;
 | 
        
           |  |  | 1280 |             $lastweight = $instance->instance->weight;
 | 
        
           |  |  | 1281 |             $lastblock = $instance->instance->id;
 | 
        
           |  |  | 1282 |         }
 | 
        
           |  |  | 1283 |   | 
        
           |  |  | 1284 |         if ($this->movingblock && $lastblock != $this->movingblock) {
 | 
        
           |  |  | 1285 |             $results[] = new block_move_target($this->get_move_target_url($region, $lastweight + 1));
 | 
        
           |  |  | 1286 |         }
 | 
        
           |  |  | 1287 |         return $results;
 | 
        
           |  |  | 1288 |     }
 | 
        
           |  |  | 1289 |   | 
        
           |  |  | 1290 |     /**
 | 
        
           |  |  | 1291 |      * Ensure block instances exist for a given region
 | 
        
           |  |  | 1292 |      *
 | 
        
           |  |  | 1293 |      * @param string $region Check for bi's with the instance with this name
 | 
        
           |  |  | 1294 |      */
 | 
        
           |  |  | 1295 |     protected function ensure_instances_exist($region) {
 | 
        
           |  |  | 1296 |         $this->check_region_is_known($region);
 | 
        
           |  |  | 1297 |         if (!array_key_exists($region, $this->blockinstances)) {
 | 
        
           |  |  | 1298 |             $this->blockinstances[$region] =
 | 
        
           |  |  | 1299 |                     $this->create_block_instances($this->birecordsbyregion[$region]);
 | 
        
           |  |  | 1300 |         }
 | 
        
           |  |  | 1301 |     }
 | 
        
           |  |  | 1302 |   | 
        
           |  |  | 1303 |     /**
 | 
        
           |  |  | 1304 |      * Ensure that there is some content within the given region
 | 
        
           |  |  | 1305 |      *
 | 
        
           |  |  | 1306 |      * @param string $region The name of the region to check
 | 
        
           |  |  | 1307 |      */
 | 
        
           |  |  | 1308 |     public function ensure_content_created($region, $output) {
 | 
        
           |  |  | 1309 |         $this->ensure_instances_exist($region);
 | 
        
           |  |  | 1310 |   | 
        
           |  |  | 1311 |         if (!has_capability('moodle/block:view', $this->page->context) ) {
 | 
        
           |  |  | 1312 |             $this->visibleblockcontent[$region] = [];
 | 
        
           |  |  | 1313 |             return;
 | 
        
           |  |  | 1314 |         }
 | 
        
           |  |  | 1315 |   | 
        
           |  |  | 1316 |         if (!array_key_exists($region, $this->visibleblockcontent)) {
 | 
        
           |  |  | 1317 |             $contents = array();
 | 
        
           |  |  | 1318 |             if (array_key_exists($region, $this->extracontent)) {
 | 
        
           |  |  | 1319 |                 $contents = $this->extracontent[$region];
 | 
        
           |  |  | 1320 |             }
 | 
        
           |  |  | 1321 |             $contents = array_merge($contents, $this->create_block_contents($this->blockinstances[$region], $output, $region));
 | 
        
           |  |  | 1322 |             if (($region == $this->defaultregion) && (!isset($this->page->theme->addblockposition) ||
 | 
        
           |  |  | 1323 |                     $this->page->theme->addblockposition == BLOCK_ADDBLOCK_POSITION_DEFAULT)) {
 | 
        
           |  |  | 1324 |                 $addblockui = block_add_block_ui($this->page, $output);
 | 
        
           |  |  | 1325 |                 if ($addblockui) {
 | 
        
           |  |  | 1326 |                     $contents[] = $addblockui;
 | 
        
           |  |  | 1327 |                 }
 | 
        
           |  |  | 1328 |             }
 | 
        
           |  |  | 1329 |             $this->visibleblockcontent[$region] = $contents;
 | 
        
           |  |  | 1330 |         }
 | 
        
           |  |  | 1331 |     }
 | 
        
           |  |  | 1332 |   | 
        
           |  |  | 1333 | /// Process actions from the URL ===============================================
 | 
        
           |  |  | 1334 |   | 
        
           |  |  | 1335 |     /**
 | 
        
           |  |  | 1336 |      * Get the appropriate list of editing icons for a block. This is used
 | 
        
           |  |  | 1337 |      * to set {@link block_contents::$controls} in {@link block_base::get_contents_for_output()}.
 | 
        
           |  |  | 1338 |      *
 | 
        
           |  |  | 1339 |      * @param block_base $block
 | 
        
           |  |  | 1340 |      * @return array an array in the format for {@link block_contents::$controls}
 | 
        
           |  |  | 1341 |      */
 | 
        
           |  |  | 1342 |     public function edit_controls($block) {
 | 
        
           |  |  | 1343 |         global $CFG;
 | 
        
           |  |  | 1344 |   | 
        
           |  |  | 1345 |         $controls = array();
 | 
        
           |  |  | 1346 |         $actionurl = $this->page->url->out(false, array('sesskey'=> sesskey()));
 | 
        
           |  |  | 1347 |         $blocktitle = $block->title;
 | 
        
           |  |  | 1348 |         if (empty($blocktitle)) {
 | 
        
           |  |  | 1349 |             $blocktitle = $block->arialabel;
 | 
        
           |  |  | 1350 |         }
 | 
        
           |  |  | 1351 |   | 
        
           |  |  | 1352 |         if ($this->page->user_can_edit_blocks()) {
 | 
        
           |  |  | 1353 |             // Move icon.
 | 
        
           |  |  | 1354 |             $str = new lang_string('moveblock', 'block', $blocktitle);
 | 
        
           |  |  | 1355 |             $controls[] = new action_menu_link_primary(
 | 
        
           |  |  | 1356 |                 new moodle_url($actionurl, array('bui_moveid' => $block->instance->id)),
 | 
        
           |  |  | 1357 |                 new pix_icon('t/move', $str, 'moodle', array('class' => 'iconsmall', 'title' => '')),
 | 
        
           |  |  | 1358 |                 $str,
 | 
        
           |  |  | 1359 |                 array('class' => 'editing_move')
 | 
        
           |  |  | 1360 |             );
 | 
        
           |  |  | 1361 |   | 
        
           |  |  | 1362 |         }
 | 
        
           |  |  | 1363 |   | 
        
           |  |  | 1364 |         if ($this->page->user_can_edit_blocks() || $block->user_can_edit()) {
 | 
        
           |  |  | 1365 |             // Edit config icon - always show - needed for positioning UI.
 | 
        
           |  |  | 1366 |             $str = new lang_string('configureblock', 'block', $blocktitle);
 | 
        
           |  |  | 1367 |             $editactionurl = new moodle_url($actionurl, ['bui_editid' => $block->instance->id]);
 | 
        
           |  |  | 1368 |             $editactionurl->remove_params(['sesskey']);
 | 
        
           |  |  | 1369 |   | 
        
           |  |  | 1370 |             // Handle editing block on admin index page, prevent the page redirecting before block action can begin.
 | 
        
           |  |  | 1371 |             if ($editactionurl->compare(new moodle_url('/admin/index.php'), URL_MATCH_BASE)) {
 | 
        
           |  |  | 1372 |                 $editactionurl->param('cache', 1);
 | 
        
           |  |  | 1373 |             }
 | 
        
           |  |  | 1374 |   | 
        
           |  |  | 1375 |             $controls[] = new action_menu_link_secondary(
 | 
        
           |  |  | 1376 |                 $editactionurl,
 | 
        
           | 1441 | ariadna | 1377 |                 new pix_icon('i/settings', $str, 'moodle', ['class' => 'iconsmall', 'title' => '']),
 | 
        
           | 1 | efrain | 1378 |                 $str,
 | 
        
           |  |  | 1379 |                 [
 | 
        
           |  |  | 1380 |                     'class' => 'editing_edit',
 | 
        
           |  |  | 1381 |                     'data-action' => 'editblock',
 | 
        
           |  |  | 1382 |                     'data-blockid' => $block->instance->id,
 | 
        
           |  |  | 1383 |                     'data-blockform' => self::get_block_edit_form_class($block->name()),
 | 
        
           |  |  | 1384 |                     'data-header' => $str,
 | 
        
           |  |  | 1385 |                 ]
 | 
        
           |  |  | 1386 |             );
 | 
        
           |  |  | 1387 |   | 
        
           |  |  | 1388 |         }
 | 
        
           |  |  | 1389 |   | 
        
           |  |  | 1390 |         if ($this->page->user_can_edit_blocks() && $block->instance_can_be_hidden()) {
 | 
        
           |  |  | 1391 |             // Show/hide icon.
 | 
        
           |  |  | 1392 |             if ($block->instance->visible) {
 | 
        
           |  |  | 1393 |                 $str = new lang_string('hideblock', 'block', $blocktitle);
 | 
        
           |  |  | 1394 |                 $url = new moodle_url($actionurl, array('bui_hideid' => $block->instance->id));
 | 
        
           |  |  | 1395 |                 $icon = new pix_icon('t/hide', $str, 'moodle', array('class' => 'iconsmall', 'title' => ''));
 | 
        
           |  |  | 1396 |                 $attributes = array('class' => 'editing_hide');
 | 
        
           |  |  | 1397 |             } else {
 | 
        
           |  |  | 1398 |                 $str = new lang_string('showblock', 'block', $blocktitle);
 | 
        
           |  |  | 1399 |                 $url = new moodle_url($actionurl, array('bui_showid' => $block->instance->id));
 | 
        
           |  |  | 1400 |                 $icon = new pix_icon('t/show', $str, 'moodle', array('class' => 'iconsmall', 'title' => ''));
 | 
        
           |  |  | 1401 |                 $attributes = array('class' => 'editing_show');
 | 
        
           |  |  | 1402 |             }
 | 
        
           |  |  | 1403 |             $controls[] = new action_menu_link_secondary($url, $icon, $str, $attributes);
 | 
        
           |  |  | 1404 |         }
 | 
        
           |  |  | 1405 |   | 
        
           |  |  | 1406 |         // Assign roles.
 | 
        
           |  |  | 1407 |         if (get_assignable_roles($block->context, ROLENAME_SHORT)) {
 | 
        
           |  |  | 1408 |             $rolesurl = new moodle_url('/admin/roles/assign.php', array('contextid' => $block->context->id,
 | 
        
           |  |  | 1409 |                 'returnurl' => $this->page->url->out_as_local_url()));
 | 
        
           |  |  | 1410 |             $str = new lang_string('assignrolesinblock', 'block', $blocktitle);
 | 
        
           |  |  | 1411 |             $controls[] = new action_menu_link_secondary(
 | 
        
           |  |  | 1412 |                 $rolesurl,
 | 
        
           |  |  | 1413 |                 new pix_icon('i/assignroles', $str, 'moodle', array('class' => 'iconsmall', 'title' => '')),
 | 
        
           |  |  | 1414 |                 $str, array('class' => 'editing_assignroles')
 | 
        
           |  |  | 1415 |             );
 | 
        
           |  |  | 1416 |         }
 | 
        
           |  |  | 1417 |   | 
        
           |  |  | 1418 |         // Permissions.
 | 
        
           |  |  | 1419 |         if (has_capability('moodle/role:review', $block->context) or get_overridable_roles($block->context)) {
 | 
        
           |  |  | 1420 |             $rolesurl = new moodle_url('/admin/roles/permissions.php', array('contextid' => $block->context->id,
 | 
        
           |  |  | 1421 |                 'returnurl' => $this->page->url->out_as_local_url()));
 | 
        
           |  |  | 1422 |             $str = get_string('permissions', 'role');
 | 
        
           |  |  | 1423 |             $controls[] = new action_menu_link_secondary(
 | 
        
           |  |  | 1424 |                 $rolesurl,
 | 
        
           |  |  | 1425 |                 new pix_icon('i/permissions', $str, 'moodle', array('class' => 'iconsmall', 'title' => '')),
 | 
        
           |  |  | 1426 |                 $str, array('class' => 'editing_permissions')
 | 
        
           |  |  | 1427 |             );
 | 
        
           |  |  | 1428 |         }
 | 
        
           |  |  | 1429 |   | 
        
           |  |  | 1430 |         // Change permissions.
 | 
        
           |  |  | 1431 |         if (has_any_capability(array('moodle/role:safeoverride', 'moodle/role:override', 'moodle/role:assign'), $block->context)) {
 | 
        
           |  |  | 1432 |             $rolesurl = new moodle_url('/admin/roles/check.php', array('contextid' => $block->context->id,
 | 
        
           |  |  | 1433 |                 'returnurl' => $this->page->url->out_as_local_url()));
 | 
        
           |  |  | 1434 |             $str = get_string('checkpermissions', 'role');
 | 
        
           |  |  | 1435 |             $controls[] = new action_menu_link_secondary(
 | 
        
           |  |  | 1436 |                 $rolesurl,
 | 
        
           |  |  | 1437 |                 new pix_icon('i/checkpermissions', $str, 'moodle', array('class' => 'iconsmall', 'title' => '')),
 | 
        
           |  |  | 1438 |                 $str, array('class' => 'editing_checkroles')
 | 
        
           |  |  | 1439 |             );
 | 
        
           |  |  | 1440 |         }
 | 
        
           |  |  | 1441 |   | 
        
           |  |  | 1442 |         if ($this->user_can_delete_block($block)) {
 | 
        
           |  |  | 1443 |             // Delete icon.
 | 
        
           |  |  | 1444 |             $str = new lang_string('deleteblock', 'block', $blocktitle);
 | 
        
           |  |  | 1445 |             $deleteactionurl = new moodle_url($actionurl, ['bui_deleteid' => $block->instance->id]);
 | 
        
           |  |  | 1446 |             $deleteactionurl->remove_params(['sesskey']);
 | 
        
           |  |  | 1447 |   | 
        
           |  |  | 1448 |             // Handle deleting block on admin index page, prevent the page redirecting before block action can begin.
 | 
        
           |  |  | 1449 |             if ($deleteactionurl->compare(new moodle_url('/admin/index.php'), URL_MATCH_BASE)) {
 | 
        
           |  |  | 1450 |                 $deleteactionurl->param('cache', 1);
 | 
        
           |  |  | 1451 |             }
 | 
        
           |  |  | 1452 |   | 
        
           |  |  | 1453 |             $deleteconfirmationurl = new moodle_url($actionurl, [
 | 
        
           |  |  | 1454 |                 'bui_deleteid' => $block->instance->id,
 | 
        
           |  |  | 1455 |                 'bui_confirm' => 1,
 | 
        
           |  |  | 1456 |                 'sesskey' => sesskey(),
 | 
        
           |  |  | 1457 |             ]);
 | 
        
           |  |  | 1458 |   | 
        
           | 1441 | ariadna | 1459 |             $deleteblockmessage = json_encode(['deleteblockcheck', 'block', $blocktitle]);
 | 
        
           |  |  | 1460 |   | 
        
           |  |  | 1461 |             // If the block is being shown in sub contexts display a warning.
 | 
        
           |  |  | 1462 |             if ($block->instance->showinsubcontexts == 1) {
 | 
        
           |  |  | 1463 |                 $parentcontext = context::instance_by_id($block->instance->parentcontextid);
 | 
        
           |  |  | 1464 |                 $systemcontext = context_system::instance();
 | 
        
           |  |  | 1465 |                 $messagestring = new stdClass();
 | 
        
           |  |  | 1466 |                 $messagestring->location = $parentcontext->get_context_name();
 | 
        
           |  |  | 1467 |   | 
        
           |  |  | 1468 |                 // Checking for blocks that may have visibility on the front page and pages added on that.
 | 
        
           |  |  | 1469 |                 if ($parentcontext->id != $systemcontext->id && is_inside_frontpage($parentcontext)) {
 | 
        
           |  |  | 1470 |                     $messagestring->pagetype = get_string('showonfrontpageandsubs', 'block');
 | 
        
           |  |  | 1471 |                 } else {
 | 
        
           |  |  | 1472 |                     $pagetypes = generate_page_type_patterns($this->page->pagetype, $parentcontext);
 | 
        
           |  |  | 1473 |                     $messagestring->pagetype = $block->instance->pagetypepattern;
 | 
        
           |  |  | 1474 |                     if (isset($pagetypes[$block->instance->pagetypepattern])) {
 | 
        
           |  |  | 1475 |                         $messagestring->pagetype = $pagetypes[$block->instance->pagetypepattern];
 | 
        
           |  |  | 1476 |                     }
 | 
        
           |  |  | 1477 |                 }
 | 
        
           |  |  | 1478 |   | 
        
           |  |  | 1479 |                 $deleteblockmessage = json_encode(['deleteblockwarning', 'block', $messagestring]);
 | 
        
           |  |  | 1480 |             }
 | 
        
           |  |  | 1481 |   | 
        
           | 1 | efrain | 1482 |             $controls[] = new action_menu_link_secondary(
 | 
        
           |  |  | 1483 |                 $deleteactionurl,
 | 
        
           |  |  | 1484 |                 new pix_icon('t/delete', $str, 'moodle', array('class' => 'iconsmall', 'title' => '')),
 | 
        
           |  |  | 1485 |                 $str,
 | 
        
           |  |  | 1486 |                 [
 | 
        
           |  |  | 1487 |                     'class' => 'editing_delete',
 | 
        
           |  |  | 1488 |                     'data-modal' => 'confirmation',
 | 
        
           |  |  | 1489 |                     'data-modal-title-str' => json_encode(['deletecheck_modal', 'block']),
 | 
        
           | 1441 | ariadna | 1490 |                     'data-modal-content-str' => $deleteblockmessage,
 | 
        
           | 1 | efrain | 1491 |                     'data-modal-yes-button-str' => json_encode(['delete', 'core']),
 | 
        
           |  |  | 1492 |                     'data-modal-toast' => 'true',
 | 
        
           |  |  | 1493 |                     'data-modal-toast-confirmation-str' => json_encode(['deleteblockinprogress', 'block', $blocktitle]),
 | 
        
           |  |  | 1494 |                     'data-modal-destination' => $deleteconfirmationurl->out(false),
 | 
        
           |  |  | 1495 |                 ]
 | 
        
           |  |  | 1496 |             );
 | 
        
           |  |  | 1497 |         }
 | 
        
           |  |  | 1498 |   | 
        
           |  |  | 1499 |         if (!empty($CFG->contextlocking) && has_capability('moodle/site:managecontextlocks', $block->context)) {
 | 
        
           |  |  | 1500 |             $parentcontext = $block->context->get_parent_context();
 | 
        
           |  |  | 1501 |             if (empty($parentcontext) || empty($parentcontext->locked)) {
 | 
        
           |  |  | 1502 |                 if ($block->context->locked) {
 | 
        
           |  |  | 1503 |                     $lockicon = 'i/unlock';
 | 
        
           |  |  | 1504 |                     $lockstring = get_string('managecontextunlock', 'admin');
 | 
        
           |  |  | 1505 |                 } else {
 | 
        
           |  |  | 1506 |                     $lockicon = 'i/lock';
 | 
        
           |  |  | 1507 |                     $lockstring = get_string('managecontextlock', 'admin');
 | 
        
           |  |  | 1508 |                 }
 | 
        
           |  |  | 1509 |                 $controls[] = new action_menu_link_secondary(
 | 
        
           |  |  | 1510 |                     new moodle_url(
 | 
        
           |  |  | 1511 |                         '/admin/lock.php',
 | 
        
           |  |  | 1512 |                         [
 | 
        
           |  |  | 1513 |                             'id' => $block->context->id,
 | 
        
           |  |  | 1514 |                         ]
 | 
        
           |  |  | 1515 |                     ),
 | 
        
           |  |  | 1516 |                     new pix_icon($lockicon, $lockstring, 'moodle', array('class' => 'iconsmall', 'title' => '')),
 | 
        
           |  |  | 1517 |                     $lockstring,
 | 
        
           |  |  | 1518 |                     ['class' => 'editing_lock']
 | 
        
           |  |  | 1519 |                 );
 | 
        
           |  |  | 1520 |             }
 | 
        
           |  |  | 1521 |         }
 | 
        
           |  |  | 1522 |   | 
        
           |  |  | 1523 |         return $controls;
 | 
        
           |  |  | 1524 |     }
 | 
        
           |  |  | 1525 |   | 
        
           |  |  | 1526 |     /**
 | 
        
           |  |  | 1527 |      * @param block_base $block a block that appears on this page.
 | 
        
           |  |  | 1528 |      * @return boolean boolean whether the currently logged in user is allowed to delete this block.
 | 
        
           |  |  | 1529 |      */
 | 
        
           |  |  | 1530 |     protected function user_can_delete_block($block) {
 | 
        
           |  |  | 1531 |         return $this->page->user_can_edit_blocks() && $block->user_can_edit() &&
 | 
        
           |  |  | 1532 |                 $block->user_can_addto($this->page) &&
 | 
        
           |  |  | 1533 |                 !in_array($block->instance->blockname, self::get_undeletable_block_types()) &&
 | 
        
           |  |  | 1534 |                 !in_array($block->instance->blockname, $this->get_required_by_theme_block_types());
 | 
        
           |  |  | 1535 |     }
 | 
        
           |  |  | 1536 |   | 
        
           |  |  | 1537 |     /**
 | 
        
           |  |  | 1538 |      * Process any block actions that were specified in the URL.
 | 
        
           |  |  | 1539 |      *
 | 
        
           |  |  | 1540 |      * @return boolean true if anything was done. False if not.
 | 
        
           |  |  | 1541 |      */
 | 
        
           |  |  | 1542 |     public function process_url_actions() {
 | 
        
           |  |  | 1543 |         if (!$this->page->user_is_editing()) {
 | 
        
           |  |  | 1544 |             return false;
 | 
        
           |  |  | 1545 |         }
 | 
        
           |  |  | 1546 |         return $this->process_url_add() || $this->process_url_delete() ||
 | 
        
           |  |  | 1547 |             $this->process_url_show_hide() || $this->process_url_edit() ||
 | 
        
           |  |  | 1548 |             $this->process_url_move();
 | 
        
           |  |  | 1549 |     }
 | 
        
           |  |  | 1550 |   | 
        
           |  |  | 1551 |     /**
 | 
        
           |  |  | 1552 |      * Handle adding a block.
 | 
        
           |  |  | 1553 |      * @return boolean true if anything was done. False if not.
 | 
        
           |  |  | 1554 |      */
 | 
        
           |  |  | 1555 |     public function process_url_add() {
 | 
        
           |  |  | 1556 |         global $CFG, $PAGE, $OUTPUT;
 | 
        
           |  |  | 1557 |   | 
        
           |  |  | 1558 |         $blocktype = optional_param('bui_addblock', null, PARAM_PLUGIN);
 | 
        
           |  |  | 1559 |         $blockregion = optional_param('bui_blockregion', null, PARAM_TEXT);
 | 
        
           |  |  | 1560 |   | 
        
           |  |  | 1561 |         if ($blocktype === null) {
 | 
        
           |  |  | 1562 |             return false;
 | 
        
           |  |  | 1563 |         }
 | 
        
           |  |  | 1564 |   | 
        
           |  |  | 1565 |         require_sesskey();
 | 
        
           |  |  | 1566 |   | 
        
           |  |  | 1567 |         if (!$this->page->user_can_edit_blocks()) {
 | 
        
           |  |  | 1568 |             throw new moodle_exception('nopermissions', '', $this->page->url->out(), get_string('addblock'));
 | 
        
           |  |  | 1569 |         }
 | 
        
           |  |  | 1570 |   | 
        
           |  |  | 1571 |         $addableblocks = $this->get_addable_blocks();
 | 
        
           |  |  | 1572 |   | 
        
           |  |  | 1573 |         if ($blocktype === '') {
 | 
        
           |  |  | 1574 |             // Display add block selection.
 | 
        
           |  |  | 1575 |             $addpage = new moodle_page();
 | 
        
           |  |  | 1576 |             $addpage->set_pagelayout('admin');
 | 
        
           |  |  | 1577 |             $addpage->blocks->show_only_fake_blocks(true);
 | 
        
           |  |  | 1578 |             $addpage->set_course($this->page->course);
 | 
        
           |  |  | 1579 |             $addpage->set_context($this->page->context);
 | 
        
           |  |  | 1580 |             if ($this->page->cm) {
 | 
        
           |  |  | 1581 |                 $addpage->set_cm($this->page->cm);
 | 
        
           |  |  | 1582 |             }
 | 
        
           |  |  | 1583 |   | 
        
           |  |  | 1584 |             $addpagebase = str_replace($CFG->wwwroot . '/', '/', $this->page->url->out_omit_querystring());
 | 
        
           |  |  | 1585 |             $addpageparams = $this->page->url->params();
 | 
        
           |  |  | 1586 |             $addpage->set_url($addpagebase, $addpageparams);
 | 
        
           |  |  | 1587 |             $addpage->set_block_actions_done();
 | 
        
           |  |  | 1588 |             // At this point we are going to display the block selector, overwrite global $PAGE ready for this.
 | 
        
           |  |  | 1589 |             $PAGE = $addpage;
 | 
        
           |  |  | 1590 |             // Some functions use $OUTPUT so we need to replace that too.
 | 
        
           |  |  | 1591 |             /** @var core_renderer $OUTPUT */
 | 
        
           |  |  | 1592 |             $OUTPUT = $addpage->get_renderer('core');
 | 
        
           |  |  | 1593 |   | 
        
           |  |  | 1594 |             $site = get_site();
 | 
        
           |  |  | 1595 |             $straddblock = get_string('addblock');
 | 
        
           |  |  | 1596 |   | 
        
           |  |  | 1597 |             $PAGE->navbar->add($straddblock);
 | 
        
           |  |  | 1598 |             $PAGE->set_title($straddblock);
 | 
        
           |  |  | 1599 |             $PAGE->set_heading($site->fullname);
 | 
        
           |  |  | 1600 |             echo $OUTPUT->header();
 | 
        
           |  |  | 1601 |             echo $OUTPUT->heading($straddblock);
 | 
        
           |  |  | 1602 |   | 
        
           |  |  | 1603 |             if (!$addableblocks) {
 | 
        
           |  |  | 1604 |                 echo $OUTPUT->box(get_string('noblockstoaddhere'));
 | 
        
           |  |  | 1605 |                 echo $OUTPUT->container($OUTPUT->action_link($addpage->url, get_string('back')), 'mx-3 mb-1');
 | 
        
           |  |  | 1606 |             } else {
 | 
        
           |  |  | 1607 |                 $url = new moodle_url($addpage->url, array('sesskey' => sesskey()));
 | 
        
           |  |  | 1608 |                 echo $OUTPUT->render_from_template('core/add_block_body',
 | 
        
           |  |  | 1609 |                     ['blocks' => array_values($addableblocks),
 | 
        
           |  |  | 1610 |                      'url' => '?' . $url->get_query_string(false)]);
 | 
        
           |  |  | 1611 |                 echo $OUTPUT->container($OUTPUT->action_link($addpage->url, get_string('cancel')), 'mx-3 mb-1');
 | 
        
           |  |  | 1612 |             }
 | 
        
           |  |  | 1613 |   | 
        
           |  |  | 1614 |             echo $OUTPUT->footer();
 | 
        
           |  |  | 1615 |             // Make sure that nothing else happens after we have displayed this form.
 | 
        
           |  |  | 1616 |             exit;
 | 
        
           |  |  | 1617 |         }
 | 
        
           |  |  | 1618 |   | 
        
           |  |  | 1619 |         if (!array_key_exists($blocktype, $addableblocks)) {
 | 
        
           |  |  | 1620 |             throw new moodle_exception('cannotaddthisblocktype', '', $this->page->url->out(), $blocktype);
 | 
        
           |  |  | 1621 |         }
 | 
        
           |  |  | 1622 |   | 
        
           |  |  | 1623 |         $this->add_block_at_end_of_default_region($blocktype, $blockregion);
 | 
        
           |  |  | 1624 |   | 
        
           |  |  | 1625 |         // If the page URL was a guess, it will contain the bui_... param, so we must make sure it is not there.
 | 
        
           |  |  | 1626 |         $this->page->ensure_param_not_in_url('bui_addblock');
 | 
        
           |  |  | 1627 |   | 
        
           |  |  | 1628 |         return true;
 | 
        
           |  |  | 1629 |     }
 | 
        
           |  |  | 1630 |   | 
        
           |  |  | 1631 |     /**
 | 
        
           |  |  | 1632 |      * Handle deleting a block.
 | 
        
           |  |  | 1633 |      * @return boolean true if anything was done. False if not.
 | 
        
           |  |  | 1634 |      */
 | 
        
           |  |  | 1635 |     public function process_url_delete() {
 | 
        
           |  |  | 1636 |         global $CFG, $PAGE, $OUTPUT;
 | 
        
           |  |  | 1637 |   | 
        
           |  |  | 1638 |         $blockid = optional_param('bui_deleteid', null, PARAM_INT);
 | 
        
           |  |  | 1639 |         $confirmdelete = optional_param('bui_confirm', null, PARAM_INT);
 | 
        
           |  |  | 1640 |   | 
        
           |  |  | 1641 |         if (!$blockid) {
 | 
        
           |  |  | 1642 |             return false;
 | 
        
           |  |  | 1643 |         }
 | 
        
           |  |  | 1644 |   | 
        
           |  |  | 1645 |         $block = $this->page->blocks->find_instance($blockid);
 | 
        
           |  |  | 1646 |         if (!$this->user_can_delete_block($block)) {
 | 
        
           |  |  | 1647 |             throw new moodle_exception('nopermissions', '', $this->page->url->out(), get_string('deleteablock'));
 | 
        
           |  |  | 1648 |         }
 | 
        
           |  |  | 1649 |   | 
        
           |  |  | 1650 |         if (!$confirmdelete) {
 | 
        
           |  |  | 1651 |             $deletepage = new moodle_page();
 | 
        
           |  |  | 1652 |             $deletepage->set_pagelayout('admin');
 | 
        
           |  |  | 1653 |             $deletepage->blocks->show_only_fake_blocks(true);
 | 
        
           |  |  | 1654 |             $deletepage->set_course($this->page->course);
 | 
        
           |  |  | 1655 |             $deletepage->set_context($this->page->context);
 | 
        
           |  |  | 1656 |             if ($this->page->cm) {
 | 
        
           |  |  | 1657 |                 $deletepage->set_cm($this->page->cm);
 | 
        
           |  |  | 1658 |             }
 | 
        
           |  |  | 1659 |   | 
        
           |  |  | 1660 |             $deleteurlbase = str_replace($CFG->wwwroot . '/', '/', $this->page->url->out_omit_querystring());
 | 
        
           |  |  | 1661 |             $deleteurlparams = $this->page->url->params();
 | 
        
           |  |  | 1662 |             $deletepage->set_url($deleteurlbase, $deleteurlparams);
 | 
        
           |  |  | 1663 |             $deletepage->set_block_actions_done();
 | 
        
           |  |  | 1664 |             $deletepage->set_secondarynav($this->get_secondarynav($block));
 | 
        
           |  |  | 1665 |             // At this point we are either going to redirect, or display the form, so
 | 
        
           |  |  | 1666 |             // overwrite global $PAGE ready for this. (Formslib refers to it.)
 | 
        
           |  |  | 1667 |             $PAGE = $deletepage;
 | 
        
           |  |  | 1668 |             //some functions like MoodleQuickForm::addHelpButton use $OUTPUT so we need to replace that too
 | 
        
           |  |  | 1669 |             /** @var core_renderer $output */
 | 
        
           |  |  | 1670 |             $output = $deletepage->get_renderer('core');
 | 
        
           |  |  | 1671 |             $OUTPUT = $output;
 | 
        
           |  |  | 1672 |   | 
        
           |  |  | 1673 |             $site = get_site();
 | 
        
           |  |  | 1674 |             $blocktitle = $block->get_title();
 | 
        
           |  |  | 1675 |             $strdeletecheck = get_string('deletecheck', 'block', $blocktitle);
 | 
        
           |  |  | 1676 |             $message = get_string('deleteblockcheck', 'block', $blocktitle);
 | 
        
           |  |  | 1677 |   | 
        
           |  |  | 1678 |             // If the block is being shown in sub contexts display a warning.
 | 
        
           |  |  | 1679 |             if ($block->instance->showinsubcontexts == 1) {
 | 
        
           |  |  | 1680 |                 $parentcontext = context::instance_by_id($block->instance->parentcontextid);
 | 
        
           |  |  | 1681 |                 $systemcontext = context_system::instance();
 | 
        
           |  |  | 1682 |                 $messagestring = new stdClass();
 | 
        
           |  |  | 1683 |                 $messagestring->location = $parentcontext->get_context_name();
 | 
        
           |  |  | 1684 |   | 
        
           |  |  | 1685 |                 // Checking for blocks that may have visibility on the front page and pages added on that.
 | 
        
           |  |  | 1686 |                 if ($parentcontext->id != $systemcontext->id && is_inside_frontpage($parentcontext)) {
 | 
        
           |  |  | 1687 |                     $messagestring->pagetype = get_string('showonfrontpageandsubs', 'block');
 | 
        
           |  |  | 1688 |                 } else {
 | 
        
           |  |  | 1689 |                     $pagetypes = generate_page_type_patterns($this->page->pagetype, $parentcontext);
 | 
        
           |  |  | 1690 |                     $messagestring->pagetype = $block->instance->pagetypepattern;
 | 
        
           |  |  | 1691 |                     if (isset($pagetypes[$block->instance->pagetypepattern])) {
 | 
        
           |  |  | 1692 |                         $messagestring->pagetype = $pagetypes[$block->instance->pagetypepattern];
 | 
        
           |  |  | 1693 |                     }
 | 
        
           |  |  | 1694 |                 }
 | 
        
           |  |  | 1695 |   | 
        
           |  |  | 1696 |                 $message = get_string('deleteblockwarning', 'block', $messagestring);
 | 
        
           |  |  | 1697 |             }
 | 
        
           |  |  | 1698 |   | 
        
           |  |  | 1699 |             $PAGE->navbar->add($strdeletecheck);
 | 
        
           |  |  | 1700 |             $PAGE->set_title($blocktitle . ': ' . $strdeletecheck);
 | 
        
           |  |  | 1701 |             $PAGE->set_heading($site->fullname);
 | 
        
           |  |  | 1702 |             echo $OUTPUT->header();
 | 
        
           |  |  | 1703 |             $confirmurl = new moodle_url($deletepage->url, array('sesskey' => sesskey(), 'bui_deleteid' => $block->instance->id, 'bui_confirm' => 1));
 | 
        
           |  |  | 1704 |             $cancelurl = new moodle_url($deletepage->url);
 | 
        
           |  |  | 1705 |             $yesbutton = new single_button($confirmurl, get_string('yes'));
 | 
        
           |  |  | 1706 |             $nobutton = new single_button($cancelurl, get_string('no'));
 | 
        
           |  |  | 1707 |             echo $OUTPUT->confirm($message, $yesbutton, $nobutton);
 | 
        
           |  |  | 1708 |             echo $OUTPUT->footer();
 | 
        
           |  |  | 1709 |             // Make sure that nothing else happens after we have displayed this form.
 | 
        
           |  |  | 1710 |             exit;
 | 
        
           |  |  | 1711 |         } else {
 | 
        
           |  |  | 1712 |             require_sesskey();
 | 
        
           |  |  | 1713 |   | 
        
           |  |  | 1714 |             blocks_delete_instance($block->instance);
 | 
        
           |  |  | 1715 |             // bui_deleteid and bui_confirm should not be in the PAGE url.
 | 
        
           |  |  | 1716 |             $this->page->ensure_param_not_in_url('bui_deleteid');
 | 
        
           |  |  | 1717 |             $this->page->ensure_param_not_in_url('bui_confirm');
 | 
        
           |  |  | 1718 |             return true;
 | 
        
           |  |  | 1719 |         }
 | 
        
           |  |  | 1720 |     }
 | 
        
           |  |  | 1721 |   | 
        
           |  |  | 1722 |     /**
 | 
        
           |  |  | 1723 |      * Returns the name of the class for block editing and makes sure it is autoloaded
 | 
        
           |  |  | 1724 |      *
 | 
        
           |  |  | 1725 |      * @param string $blockname name of the block plugin (without block_ prefix)
 | 
        
           |  |  | 1726 |      * @return string
 | 
        
           |  |  | 1727 |      */
 | 
        
           |  |  | 1728 |     public static function get_block_edit_form_class(string $blockname): string {
 | 
        
           |  |  | 1729 |         global $CFG;
 | 
        
           |  |  | 1730 |         require_once("$CFG->dirroot/blocks/moodleblock.class.php");
 | 
        
           |  |  | 1731 |         $blockname = clean_param($blockname, PARAM_PLUGIN);
 | 
        
           |  |  | 1732 |         $formfile = $CFG->dirroot . '/blocks/' . $blockname . '/edit_form.php';
 | 
        
           |  |  | 1733 |         if (is_readable($formfile)) {
 | 
        
           |  |  | 1734 |             require_once($CFG->dirroot . '/blocks/edit_form.php');
 | 
        
           |  |  | 1735 |             require_once($formfile);
 | 
        
           |  |  | 1736 |             $classname = 'block_' . $blockname . '_edit_form';
 | 
        
           |  |  | 1737 |             if (!class_exists($classname)) {
 | 
        
           |  |  | 1738 |                 $classname = 'block_edit_form';
 | 
        
           |  |  | 1739 |             }
 | 
        
           |  |  | 1740 |         } else {
 | 
        
           |  |  | 1741 |             require_once($CFG->dirroot . '/blocks/edit_form.php');
 | 
        
           |  |  | 1742 |             $classname = 'block_edit_form';
 | 
        
           |  |  | 1743 |         }
 | 
        
           |  |  | 1744 |         return $classname;
 | 
        
           |  |  | 1745 |     }
 | 
        
           |  |  | 1746 |   | 
        
           |  |  | 1747 |     /**
 | 
        
           |  |  | 1748 |      * Handle showing or hiding a block.
 | 
        
           |  |  | 1749 |      * @return boolean true if anything was done. False if not.
 | 
        
           |  |  | 1750 |      */
 | 
        
           |  |  | 1751 |     public function process_url_show_hide() {
 | 
        
           |  |  | 1752 |         if ($blockid = optional_param('bui_hideid', null, PARAM_INT)) {
 | 
        
           |  |  | 1753 |             $newvisibility = 0;
 | 
        
           |  |  | 1754 |         } else if ($blockid = optional_param('bui_showid', null, PARAM_INT)) {
 | 
        
           |  |  | 1755 |             $newvisibility = 1;
 | 
        
           |  |  | 1756 |         } else {
 | 
        
           |  |  | 1757 |             return false;
 | 
        
           |  |  | 1758 |         }
 | 
        
           |  |  | 1759 |   | 
        
           |  |  | 1760 |         require_sesskey();
 | 
        
           |  |  | 1761 |   | 
        
           |  |  | 1762 |         $block = $this->page->blocks->find_instance($blockid);
 | 
        
           |  |  | 1763 |   | 
        
           |  |  | 1764 |         if (!$this->page->user_can_edit_blocks()) {
 | 
        
           |  |  | 1765 |             throw new moodle_exception('nopermissions', '', $this->page->url->out(), get_string('hideshowblocks'));
 | 
        
           |  |  | 1766 |         } else if (!$block->instance_can_be_hidden()) {
 | 
        
           |  |  | 1767 |             return false;
 | 
        
           |  |  | 1768 |         }
 | 
        
           |  |  | 1769 |   | 
        
           |  |  | 1770 |         blocks_set_visibility($block->instance, $this->page, $newvisibility);
 | 
        
           |  |  | 1771 |   | 
        
           |  |  | 1772 |         // If the page URL was a guses, it will contain the bui_... param, so we must make sure it is not there.
 | 
        
           |  |  | 1773 |         $this->page->ensure_param_not_in_url('bui_hideid');
 | 
        
           |  |  | 1774 |         $this->page->ensure_param_not_in_url('bui_showid');
 | 
        
           |  |  | 1775 |   | 
        
           |  |  | 1776 |         return true;
 | 
        
           |  |  | 1777 |     }
 | 
        
           |  |  | 1778 |   | 
        
           |  |  | 1779 |     /**
 | 
        
           |  |  | 1780 |      * Convenience function to check whether a block is implementing a secondary nav class and return it
 | 
        
           |  |  | 1781 |      * initialised to the calling function
 | 
        
           |  |  | 1782 |      *
 | 
        
           |  |  | 1783 |      * @param block_base $block
 | 
        
           |  |  | 1784 |      * @return \core\navigation\views\secondary
 | 
        
           |  |  | 1785 |      */
 | 
        
           |  |  | 1786 |     protected function get_secondarynav(block_base $block): \core\navigation\views\secondary {
 | 
        
           |  |  | 1787 |         $class = "core_block\\navigation\\views\\secondary";
 | 
        
           | 1441 | ariadna | 1788 |   | 
        
           |  |  | 1789 |         // Check whether block defines its own secondary navigation.
 | 
        
           | 1 | efrain | 1790 |         if (class_exists("block_{$block->name()}\\navigation\\views\\secondary")) {
 | 
        
           |  |  | 1791 |             $class = "block_{$block->name()}\\navigation\\views\\secondary";
 | 
        
           |  |  | 1792 |         }
 | 
        
           | 1441 | ariadna | 1793 |   | 
        
           | 1 | efrain | 1794 |         $secondarynav = new $class($this->page);
 | 
        
           |  |  | 1795 |         $secondarynav->initialise();
 | 
        
           |  |  | 1796 |         return $secondarynav;
 | 
        
           |  |  | 1797 |     }
 | 
        
           |  |  | 1798 |   | 
        
           |  |  | 1799 |     /**
 | 
        
           |  |  | 1800 |      * Handle showing/processing the submission from the block editing form.
 | 
        
           |  |  | 1801 |      * @return boolean true if the form was submitted and the new config saved. Does not
 | 
        
           |  |  | 1802 |      *      return if the editing form was displayed. False otherwise.
 | 
        
           |  |  | 1803 |      */
 | 
        
           |  |  | 1804 |     public function process_url_edit() {
 | 
        
           |  |  | 1805 |         global $CFG, $DB, $PAGE, $OUTPUT;
 | 
        
           |  |  | 1806 |   | 
        
           |  |  | 1807 |         $blockid = optional_param('bui_editid', null, PARAM_INT);
 | 
        
           |  |  | 1808 |         if (!$blockid) {
 | 
        
           |  |  | 1809 |             return false;
 | 
        
           |  |  | 1810 |         }
 | 
        
           |  |  | 1811 |   | 
        
           |  |  | 1812 |         require_once($CFG->dirroot . '/blocks/edit_form.php');
 | 
        
           |  |  | 1813 |   | 
        
           |  |  | 1814 |         $block = $this->find_instance($blockid);
 | 
        
           |  |  | 1815 |   | 
        
           |  |  | 1816 |         if (!$block->user_can_edit() && !$this->page->user_can_edit_blocks()) {
 | 
        
           |  |  | 1817 |             throw new moodle_exception('nopermissions', '', $this->page->url->out(), get_string('editblock'));
 | 
        
           |  |  | 1818 |         }
 | 
        
           |  |  | 1819 |   | 
        
           |  |  | 1820 |         $editpage = new moodle_page();
 | 
        
           |  |  | 1821 |         $editpage->set_pagelayout('admin');
 | 
        
           |  |  | 1822 |         $editpage->blocks->show_only_fake_blocks(true);
 | 
        
           |  |  | 1823 |         $editpage->set_course($this->page->course);
 | 
        
           |  |  | 1824 |         //$editpage->set_context($block->context);
 | 
        
           |  |  | 1825 |         $editpage->set_context($this->page->context);
 | 
        
           |  |  | 1826 |         $editpage->set_secondarynav($this->get_secondarynav($block));
 | 
        
           |  |  | 1827 |   | 
        
           |  |  | 1828 |         if ($this->page->cm) {
 | 
        
           |  |  | 1829 |             $editpage->set_cm($this->page->cm);
 | 
        
           |  |  | 1830 |         }
 | 
        
           |  |  | 1831 |         $editurlbase = str_replace($CFG->wwwroot . '/', '/', $this->page->url->out_omit_querystring());
 | 
        
           |  |  | 1832 |         $editurlparams = $this->page->url->params();
 | 
        
           |  |  | 1833 |         $editurlparams['bui_editid'] = $blockid;
 | 
        
           |  |  | 1834 |         $editpage->set_url($editurlbase, $editurlparams);
 | 
        
           |  |  | 1835 |         $editpage->set_block_actions_done();
 | 
        
           |  |  | 1836 |         // At this point we are either going to redirect, or display the form, so
 | 
        
           |  |  | 1837 |         // overwrite global $PAGE ready for this. (Formslib refers to it.)
 | 
        
           |  |  | 1838 |         $PAGE = $editpage;
 | 
        
           |  |  | 1839 |         //some functions like MoodleQuickForm::addHelpButton use $OUTPUT so we need to replace that to
 | 
        
           |  |  | 1840 |         $output = $editpage->get_renderer('core');
 | 
        
           |  |  | 1841 |         $OUTPUT = $output;
 | 
        
           |  |  | 1842 |   | 
        
           |  |  | 1843 |         $classname = self::get_block_edit_form_class($block->name());
 | 
        
           |  |  | 1844 |         /** @var block_edit_form $mform */
 | 
        
           |  |  | 1845 |         $mform = new $classname($editpage->url->out(false), ['page' => $this->page, 'block' => $block, 'actionbuttons' => true]);
 | 
        
           |  |  | 1846 |         $mform->set_data($block->instance);
 | 
        
           |  |  | 1847 |   | 
        
           |  |  | 1848 |         if ($mform->is_cancelled()) {
 | 
        
           |  |  | 1849 |             redirect($this->page->url);
 | 
        
           |  |  | 1850 |   | 
        
           |  |  | 1851 |         } else if ($data = $mform->get_data()) {
 | 
        
           |  |  | 1852 |   | 
        
           |  |  | 1853 |             $this->save_block_data($block, $data);
 | 
        
           |  |  | 1854 |             redirect($this->page->url);
 | 
        
           |  |  | 1855 |   | 
        
           |  |  | 1856 |         } else {
 | 
        
           |  |  | 1857 |             $strheading = get_string('blockconfiga', 'moodle', $block->get_title());
 | 
        
           |  |  | 1858 |             $editpage->set_title($strheading);
 | 
        
           |  |  | 1859 |             $editpage->set_heading($strheading);
 | 
        
           |  |  | 1860 |             $bits = explode('-', $this->page->pagetype);
 | 
        
           |  |  | 1861 |             if ($bits[0] == 'tag' && !empty($this->page->subpage)) {
 | 
        
           |  |  | 1862 |                 // better navbar for tag pages
 | 
        
           |  |  | 1863 |                 $editpage->navbar->add(get_string('tags'), new moodle_url('/tag/'));
 | 
        
           |  |  | 1864 |                 $tag = core_tag_tag::get($this->page->subpage);
 | 
        
           |  |  | 1865 |                 // tag search page doesn't have subpageid
 | 
        
           |  |  | 1866 |                 if ($tag) {
 | 
        
           |  |  | 1867 |                     $editpage->navbar->add($tag->get_display_name(), $tag->get_view_url());
 | 
        
           |  |  | 1868 |                 }
 | 
        
           |  |  | 1869 |             }
 | 
        
           |  |  | 1870 |             $editpage->navbar->add($block->get_title());
 | 
        
           |  |  | 1871 |             $editpage->navbar->add(get_string('configuration'));
 | 
        
           |  |  | 1872 |             echo $output->header();
 | 
        
           |  |  | 1873 |             $mform->display();
 | 
        
           |  |  | 1874 |             echo $output->footer();
 | 
        
           |  |  | 1875 |             exit;
 | 
        
           |  |  | 1876 |         }
 | 
        
           |  |  | 1877 |     }
 | 
        
           |  |  | 1878 |   | 
        
           |  |  | 1879 |     /**
 | 
        
           |  |  | 1880 |      * Updates block configuration in the database
 | 
        
           |  |  | 1881 |      *
 | 
        
           |  |  | 1882 |      * @param block_base $block
 | 
        
           |  |  | 1883 |      * @param stdClass $data data from the block edit form
 | 
        
           |  |  | 1884 |      * @return void
 | 
        
           |  |  | 1885 |      */
 | 
        
           |  |  | 1886 |     public function save_block_data(block_base $block, stdClass $data): void {
 | 
        
           |  |  | 1887 |         global $DB;
 | 
        
           |  |  | 1888 |   | 
        
           |  |  | 1889 |         $bi = new stdClass;
 | 
        
           |  |  | 1890 |         $bi->id = $block->instance->id;
 | 
        
           |  |  | 1891 |   | 
        
           |  |  | 1892 |         // This may get overwritten by the special case handling below.
 | 
        
           |  |  | 1893 |         $bi->pagetypepattern = $data->bui_pagetypepattern;
 | 
        
           |  |  | 1894 |         $bi->showinsubcontexts = (bool) $data->bui_contexts;
 | 
        
           |  |  | 1895 |         if (empty($data->bui_subpagepattern) || $data->bui_subpagepattern == '%@NULL@%') {
 | 
        
           |  |  | 1896 |             $bi->subpagepattern = null;
 | 
        
           |  |  | 1897 |         } else {
 | 
        
           |  |  | 1898 |             $bi->subpagepattern = $data->bui_subpagepattern;
 | 
        
           |  |  | 1899 |         }
 | 
        
           |  |  | 1900 |   | 
        
           |  |  | 1901 |         $systemcontext = context_system::instance();
 | 
        
           |  |  | 1902 |         $frontpagecontext = context_course::instance(SITEID);
 | 
        
           |  |  | 1903 |         $parentcontext = context::instance_by_id($data->bui_parentcontextid);
 | 
        
           |  |  | 1904 |   | 
        
           |  |  | 1905 |         // Updating stickiness and contexts.  See MDL-21375 for details.
 | 
        
           |  |  | 1906 |         if (has_capability('moodle/site:manageblocks', $parentcontext)) { // Check permissions in destination.
 | 
        
           |  |  | 1907 |   | 
        
           |  |  | 1908 |             // Explicitly set the default context.
 | 
        
           |  |  | 1909 |             $bi->parentcontextid = $parentcontext->id;
 | 
        
           |  |  | 1910 |   | 
        
           |  |  | 1911 |             if ($data->bui_editingatfrontpage) {   // The block is being edited on the front page.
 | 
        
           |  |  | 1912 |   | 
        
           |  |  | 1913 |                 // The interface here is a special case because the pagetype pattern is
 | 
        
           |  |  | 1914 |                 // totally derived from the context menu.  Here are the excpetions.   MDL-30340 .
 | 
        
           |  |  | 1915 |   | 
        
           |  |  | 1916 |                 switch ($data->bui_contexts) {
 | 
        
           |  |  | 1917 |                     case BUI_CONTEXTS_ENTIRE_SITE:
 | 
        
           |  |  | 1918 |                         // The user wants to show the block across the entire site.
 | 
        
           |  |  | 1919 |                         $bi->parentcontextid = $systemcontext->id;
 | 
        
           |  |  | 1920 |                         $bi->showinsubcontexts = true;
 | 
        
           |  |  | 1921 |                         $bi->pagetypepattern = '*';
 | 
        
           |  |  | 1922 |                         break;
 | 
        
           |  |  | 1923 |                     case BUI_CONTEXTS_FRONTPAGE_SUBS:
 | 
        
           |  |  | 1924 |                         // The user wants the block shown on the front page and all subcontexts.
 | 
        
           |  |  | 1925 |                         $bi->parentcontextid = $frontpagecontext->id;
 | 
        
           |  |  | 1926 |                         $bi->showinsubcontexts = true;
 | 
        
           |  |  | 1927 |                         $bi->pagetypepattern = '*';
 | 
        
           |  |  | 1928 |                         break;
 | 
        
           |  |  | 1929 |                     case BUI_CONTEXTS_FRONTPAGE_ONLY:
 | 
        
           |  |  | 1930 |                         // The user want to show the front page on the frontpage only.
 | 
        
           |  |  | 1931 |                         $bi->parentcontextid = $frontpagecontext->id;
 | 
        
           |  |  | 1932 |                         $bi->showinsubcontexts = false;
 | 
        
           |  |  | 1933 |                         $bi->pagetypepattern = 'site-index';
 | 
        
           |  |  | 1934 |                         // This is the only relevant page type anyway but we'll set it explicitly just
 | 
        
           |  |  | 1935 |                         // in case the front page grows site-index-* subpages of its own later.
 | 
        
           |  |  | 1936 |                         break;
 | 
        
           |  |  | 1937 |                 }
 | 
        
           |  |  | 1938 |             }
 | 
        
           |  |  | 1939 |         }
 | 
        
           |  |  | 1940 |   | 
        
           |  |  | 1941 |         $bits = explode('-', $bi->pagetypepattern);
 | 
        
           |  |  | 1942 |         // Hacks for some contexts.
 | 
        
           |  |  | 1943 |         if (($parentcontext->contextlevel == CONTEXT_COURSE) && ($parentcontext->instanceid != SITEID)) {
 | 
        
           |  |  | 1944 |             // For course context
 | 
        
           |  |  | 1945 |             // is page type pattern is mod-*, change showinsubcontext to 1.
 | 
        
           |  |  | 1946 |             if ($bits[0] == 'mod' || $bi->pagetypepattern == '*') {
 | 
        
           |  |  | 1947 |                 $bi->showinsubcontexts = 1;
 | 
        
           |  |  | 1948 |             } else {
 | 
        
           |  |  | 1949 |                 $bi->showinsubcontexts = 0;
 | 
        
           |  |  | 1950 |             }
 | 
        
           |  |  | 1951 |         } else if ($parentcontext->contextlevel == CONTEXT_USER) {
 | 
        
           |  |  | 1952 |             // For user context subpagepattern should be null.
 | 
        
           |  |  | 1953 |             if ($bits[0] == 'user' || $bits[0] == 'my') {
 | 
        
           |  |  | 1954 |                 // We don't need subpagepattern in usercontext.
 | 
        
           |  |  | 1955 |                 $bi->subpagepattern = null;
 | 
        
           |  |  | 1956 |             }
 | 
        
           |  |  | 1957 |         }
 | 
        
           |  |  | 1958 |   | 
        
           |  |  | 1959 |         $bi->defaultregion = $data->bui_defaultregion;
 | 
        
           |  |  | 1960 |         $bi->defaultweight = $data->bui_defaultweight;
 | 
        
           |  |  | 1961 |         $bi->timemodified = time();
 | 
        
           |  |  | 1962 |         $DB->update_record('block_instances', $bi);
 | 
        
           |  |  | 1963 |   | 
        
           |  |  | 1964 |         if (!empty($block->config)) {
 | 
        
           |  |  | 1965 |             $config = clone($block->config);
 | 
        
           |  |  | 1966 |         } else {
 | 
        
           |  |  | 1967 |             $config = new stdClass;
 | 
        
           |  |  | 1968 |         }
 | 
        
           |  |  | 1969 |         foreach ($data as $configfield => $value) {
 | 
        
           |  |  | 1970 |             if (strpos($configfield, 'config_') !== 0) {
 | 
        
           |  |  | 1971 |                 continue;
 | 
        
           |  |  | 1972 |             }
 | 
        
           |  |  | 1973 |             $field = substr($configfield, 7);
 | 
        
           |  |  | 1974 |             $config->$field = $value;
 | 
        
           |  |  | 1975 |         }
 | 
        
           |  |  | 1976 |         $block->instance_config_save($config);
 | 
        
           |  |  | 1977 |   | 
        
           |  |  | 1978 |         $bp = new stdClass;
 | 
        
           |  |  | 1979 |         $bp->visible = $data->bui_visible;
 | 
        
           |  |  | 1980 |         $bp->region = $data->bui_region;
 | 
        
           |  |  | 1981 |         $bp->weight = $data->bui_weight;
 | 
        
           |  |  | 1982 |         $needbprecord = !$data->bui_visible || $data->bui_region != $data->bui_defaultregion ||
 | 
        
           |  |  | 1983 |                 $data->bui_weight != $data->bui_defaultweight;
 | 
        
           |  |  | 1984 |   | 
        
           |  |  | 1985 |         if ($block->instance->blockpositionid && !$needbprecord) {
 | 
        
           |  |  | 1986 |             $DB->delete_records('block_positions', array('id' => $block->instance->blockpositionid));
 | 
        
           |  |  | 1987 |   | 
        
           |  |  | 1988 |         } else if ($block->instance->blockpositionid && $needbprecord) {
 | 
        
           |  |  | 1989 |             $bp->id = $block->instance->blockpositionid;
 | 
        
           |  |  | 1990 |             $DB->update_record('block_positions', $bp);
 | 
        
           |  |  | 1991 |   | 
        
           |  |  | 1992 |         } else if ($needbprecord) {
 | 
        
           |  |  | 1993 |             $bp->blockinstanceid = $block->instance->id;
 | 
        
           |  |  | 1994 |             $bp->contextid = $this->page->context->id;
 | 
        
           |  |  | 1995 |             $bp->pagetype = $this->page->pagetype;
 | 
        
           |  |  | 1996 |             if ($this->page->subpage) {
 | 
        
           |  |  | 1997 |                 $bp->subpage = $this->page->subpage;
 | 
        
           |  |  | 1998 |             } else {
 | 
        
           |  |  | 1999 |                 $bp->subpage = '';
 | 
        
           |  |  | 2000 |             }
 | 
        
           |  |  | 2001 |             $DB->insert_record('block_positions', $bp);
 | 
        
           |  |  | 2002 |         }
 | 
        
           |  |  | 2003 |     }
 | 
        
           |  |  | 2004 |   | 
        
           |  |  | 2005 |     /**
 | 
        
           |  |  | 2006 |      * Handle showing/processing the submission from the block editing form.
 | 
        
           |  |  | 2007 |      * @return boolean true if the form was submitted and the new config saved. Does not
 | 
        
           |  |  | 2008 |      *      return if the editing form was displayed. False otherwise.
 | 
        
           |  |  | 2009 |      */
 | 
        
           |  |  | 2010 |     public function process_url_move() {
 | 
        
           |  |  | 2011 |         global $CFG, $DB, $PAGE;
 | 
        
           |  |  | 2012 |   | 
        
           |  |  | 2013 |         $blockid = optional_param('bui_moveid', null, PARAM_INT);
 | 
        
           |  |  | 2014 |         if (!$blockid) {
 | 
        
           |  |  | 2015 |             return false;
 | 
        
           |  |  | 2016 |         }
 | 
        
           |  |  | 2017 |   | 
        
           |  |  | 2018 |         require_sesskey();
 | 
        
           |  |  | 2019 |   | 
        
           |  |  | 2020 |         $block = $this->find_instance($blockid);
 | 
        
           |  |  | 2021 |   | 
        
           |  |  | 2022 |         if (!$this->page->user_can_edit_blocks()) {
 | 
        
           |  |  | 2023 |             throw new moodle_exception('nopermissions', '', $this->page->url->out(), get_string('editblock'));
 | 
        
           |  |  | 2024 |         }
 | 
        
           |  |  | 2025 |   | 
        
           |  |  | 2026 |         $newregion = optional_param('bui_newregion', '', PARAM_ALPHANUMEXT);
 | 
        
           |  |  | 2027 |         $newweight = optional_param('bui_newweight', null, PARAM_FLOAT);
 | 
        
           |  |  | 2028 |         if (!$newregion || is_null($newweight)) {
 | 
        
           |  |  | 2029 |             // Don't have a valid target position yet, must be just starting the move.
 | 
        
           |  |  | 2030 |             $this->movingblock = $blockid;
 | 
        
           |  |  | 2031 |             $this->page->ensure_param_not_in_url('bui_moveid');
 | 
        
           |  |  | 2032 |             return false;
 | 
        
           |  |  | 2033 |         }
 | 
        
           |  |  | 2034 |   | 
        
           |  |  | 2035 |         if (!$this->is_known_region($newregion)) {
 | 
        
           |  |  | 2036 |             throw new moodle_exception('unknownblockregion', '', $this->page->url, $newregion);
 | 
        
           |  |  | 2037 |         }
 | 
        
           |  |  | 2038 |   | 
        
           |  |  | 2039 |         // Move this block. This may involve moving other nearby blocks.
 | 
        
           |  |  | 2040 |         $blocks = $this->birecordsbyregion[$newregion];
 | 
        
           |  |  | 2041 |   | 
        
           |  |  | 2042 |         $maxweight = self::MAX_WEIGHT;
 | 
        
           |  |  | 2043 |         $minweight = -self::MAX_WEIGHT;
 | 
        
           |  |  | 2044 |   | 
        
           |  |  | 2045 |         // Initialise the used weights and spareweights array with the default values
 | 
        
           |  |  | 2046 |         $spareweights = array();
 | 
        
           |  |  | 2047 |         $usedweights = array();
 | 
        
           |  |  | 2048 |         for ($i = $minweight; $i <= $maxweight; $i++) {
 | 
        
           |  |  | 2049 |             $spareweights[$i] = $i;
 | 
        
           |  |  | 2050 |             $usedweights[$i] = array();
 | 
        
           |  |  | 2051 |         }
 | 
        
           |  |  | 2052 |   | 
        
           |  |  | 2053 |         // Check each block and sort out where we have used weights
 | 
        
           |  |  | 2054 |         foreach ($blocks as $bi) {
 | 
        
           |  |  | 2055 |             if ($bi->weight > $maxweight) {
 | 
        
           |  |  | 2056 |                 // If this statement is true then the blocks weight is more than the
 | 
        
           |  |  | 2057 |                 // current maximum. To ensure that we can get the best block position
 | 
        
           |  |  | 2058 |                 // we will initialise elements within the usedweights and spareweights
 | 
        
           |  |  | 2059 |                 // arrays between the blocks weight (which will then be the new max) and
 | 
        
           |  |  | 2060 |                 // the current max
 | 
        
           |  |  | 2061 |                 $parseweight = $bi->weight;
 | 
        
           |  |  | 2062 |                 while (!array_key_exists($parseweight, $usedweights)) {
 | 
        
           |  |  | 2063 |                     $usedweights[$parseweight] = array();
 | 
        
           |  |  | 2064 |                     $spareweights[$parseweight] = $parseweight;
 | 
        
           |  |  | 2065 |                     $parseweight--;
 | 
        
           |  |  | 2066 |                 }
 | 
        
           |  |  | 2067 |                 $maxweight = $bi->weight;
 | 
        
           |  |  | 2068 |             } else if ($bi->weight < $minweight) {
 | 
        
           |  |  | 2069 |                 // As above except this time the blocks weight is LESS than the
 | 
        
           |  |  | 2070 |                 // the current minimum, so we will initialise the array from the
 | 
        
           |  |  | 2071 |                 // blocks weight (new minimum) to the current minimum
 | 
        
           |  |  | 2072 |                 $parseweight = $bi->weight;
 | 
        
           |  |  | 2073 |                 while (!array_key_exists($parseweight, $usedweights)) {
 | 
        
           |  |  | 2074 |                     $usedweights[$parseweight] = array();
 | 
        
           |  |  | 2075 |                     $spareweights[$parseweight] = $parseweight;
 | 
        
           |  |  | 2076 |                     $parseweight++;
 | 
        
           |  |  | 2077 |                 }
 | 
        
           |  |  | 2078 |                 $minweight = $bi->weight;
 | 
        
           |  |  | 2079 |             }
 | 
        
           |  |  | 2080 |             if ($bi->id != $block->instance->id) {
 | 
        
           |  |  | 2081 |                 unset($spareweights[$bi->weight]);
 | 
        
           |  |  | 2082 |                 $usedweights[$bi->weight][] = $bi->id;
 | 
        
           |  |  | 2083 |             }
 | 
        
           |  |  | 2084 |         }
 | 
        
           |  |  | 2085 |   | 
        
           |  |  | 2086 |         // First we find the nearest gap in the list of weights.
 | 
        
           |  |  | 2087 |         $bestdistance = max(abs($newweight - self::MAX_WEIGHT), abs($newweight + self::MAX_WEIGHT)) + 1;
 | 
        
           |  |  | 2088 |         $bestgap = null;
 | 
        
           |  |  | 2089 |         foreach ($spareweights as $spareweight) {
 | 
        
           |  |  | 2090 |             if (abs($newweight - $spareweight) < $bestdistance) {
 | 
        
           |  |  | 2091 |                 $bestdistance = abs($newweight - $spareweight);
 | 
        
           |  |  | 2092 |                 $bestgap = $spareweight;
 | 
        
           |  |  | 2093 |             }
 | 
        
           |  |  | 2094 |         }
 | 
        
           |  |  | 2095 |   | 
        
           |  |  | 2096 |         // If there is no gap, we have to go outside -self::MAX_WEIGHT .. self::MAX_WEIGHT.
 | 
        
           |  |  | 2097 |         if (is_null($bestgap)) {
 | 
        
           |  |  | 2098 |             $bestgap = self::MAX_WEIGHT + 1;
 | 
        
           |  |  | 2099 |             while (!empty($usedweights[$bestgap])) {
 | 
        
           |  |  | 2100 |                 $bestgap++;
 | 
        
           |  |  | 2101 |             }
 | 
        
           |  |  | 2102 |         }
 | 
        
           |  |  | 2103 |   | 
        
           |  |  | 2104 |         // Now we know the gap we are aiming for, so move all the blocks along.
 | 
        
           |  |  | 2105 |         if ($bestgap < $newweight) {
 | 
        
           |  |  | 2106 |             $newweight = floor($newweight);
 | 
        
           |  |  | 2107 |             for ($weight = $bestgap + 1; $weight <= $newweight; $weight++) {
 | 
        
           |  |  | 2108 |                 if (array_key_exists($weight, $usedweights)) {
 | 
        
           |  |  | 2109 |                     foreach ($usedweights[$weight] as $biid) {
 | 
        
           |  |  | 2110 |                         $this->reposition_block($biid, $newregion, $weight - 1);
 | 
        
           |  |  | 2111 |                     }
 | 
        
           |  |  | 2112 |                 }
 | 
        
           |  |  | 2113 |             }
 | 
        
           |  |  | 2114 |             $this->reposition_block($block->instance->id, $newregion, $newweight);
 | 
        
           |  |  | 2115 |         } else {
 | 
        
           |  |  | 2116 |             $newweight = ceil($newweight);
 | 
        
           |  |  | 2117 |             for ($weight = $bestgap - 1; $weight >= $newweight; $weight--) {
 | 
        
           |  |  | 2118 |                 if (array_key_exists($weight, $usedweights)) {
 | 
        
           |  |  | 2119 |                     foreach ($usedweights[$weight] as $biid) {
 | 
        
           |  |  | 2120 |                         $this->reposition_block($biid, $newregion, $weight + 1);
 | 
        
           |  |  | 2121 |                     }
 | 
        
           |  |  | 2122 |                 }
 | 
        
           |  |  | 2123 |             }
 | 
        
           |  |  | 2124 |             $this->reposition_block($block->instance->id, $newregion, $newweight);
 | 
        
           |  |  | 2125 |         }
 | 
        
           |  |  | 2126 |   | 
        
           |  |  | 2127 |         $this->page->ensure_param_not_in_url('bui_moveid');
 | 
        
           |  |  | 2128 |         $this->page->ensure_param_not_in_url('bui_newregion');
 | 
        
           |  |  | 2129 |         $this->page->ensure_param_not_in_url('bui_newweight');
 | 
        
           |  |  | 2130 |         return true;
 | 
        
           |  |  | 2131 |     }
 | 
        
           |  |  | 2132 |   | 
        
           |  |  | 2133 |     /**
 | 
        
           |  |  | 2134 |      * Turns the display of normal blocks either on or off.
 | 
        
           |  |  | 2135 |      *
 | 
        
           |  |  | 2136 |      * @param bool $setting
 | 
        
           |  |  | 2137 |      */
 | 
        
           |  |  | 2138 |     public function show_only_fake_blocks($setting = true) {
 | 
        
           |  |  | 2139 |         $this->fakeblocksonly = $setting;
 | 
        
           |  |  | 2140 |     }
 | 
        
           |  |  | 2141 | }
 | 
        
           |  |  | 2142 |   | 
        
           |  |  | 2143 | /// Helper functions for working with block classes ============================
 | 
        
           |  |  | 2144 |   | 
        
           |  |  | 2145 | /**
 | 
        
           |  |  | 2146 |  * Call a class method (one that does not require a block instance) on a block class.
 | 
        
           |  |  | 2147 |  *
 | 
        
           |  |  | 2148 |  * @param string $blockname the name of the block.
 | 
        
           |  |  | 2149 |  * @param string $method the method name.
 | 
        
           |  |  | 2150 |  * @param array $param parameters to pass to the method.
 | 
        
           |  |  | 2151 |  * @return mixed whatever the method returns.
 | 
        
           |  |  | 2152 |  */
 | 
        
           |  |  | 2153 | function block_method_result($blockname, $method, $param = NULL) {
 | 
        
           |  |  | 2154 |     if(!block_load_class($blockname)) {
 | 
        
           |  |  | 2155 |         return NULL;
 | 
        
           |  |  | 2156 |     }
 | 
        
           |  |  | 2157 |     return call_user_func(array('block_'.$blockname, $method), $param);
 | 
        
           |  |  | 2158 | }
 | 
        
           |  |  | 2159 |   | 
        
           |  |  | 2160 | /**
 | 
        
           |  |  | 2161 |  * Returns a new instance of the specified block instance id.
 | 
        
           |  |  | 2162 |  *
 | 
        
           |  |  | 2163 |  * @param int $blockinstanceid
 | 
        
           |  |  | 2164 |  * @return block_base the requested block instance.
 | 
        
           |  |  | 2165 |  */
 | 
        
           |  |  | 2166 | function block_instance_by_id($blockinstanceid) {
 | 
        
           |  |  | 2167 |     global $DB;
 | 
        
           |  |  | 2168 |   | 
        
           |  |  | 2169 |     $blockinstance = $DB->get_record('block_instances', ['id' => $blockinstanceid]);
 | 
        
           |  |  | 2170 |     $instance = block_instance($blockinstance->blockname, $blockinstance);
 | 
        
           |  |  | 2171 |     return $instance;
 | 
        
           |  |  | 2172 | }
 | 
        
           |  |  | 2173 |   | 
        
           |  |  | 2174 | /**
 | 
        
           |  |  | 2175 |  * Creates a new instance of the specified block class.
 | 
        
           |  |  | 2176 |  *
 | 
        
           |  |  | 2177 |  * @param string $blockname the name of the block.
 | 
        
           |  |  | 2178 |  * @param stdClass $instance block_instances DB table row (optional).
 | 
        
           |  |  | 2179 |  * @param moodle_page $page the page this block is appearing on.
 | 
        
           |  |  | 2180 |  * @return block_base|false the requested block instance.
 | 
        
           |  |  | 2181 |  */
 | 
        
           |  |  | 2182 | function block_instance($blockname, $instance = NULL, $page = NULL) {
 | 
        
           |  |  | 2183 |     if(!block_load_class($blockname)) {
 | 
        
           |  |  | 2184 |         return false;
 | 
        
           |  |  | 2185 |     }
 | 
        
           |  |  | 2186 |     $classname = 'block_'.$blockname;
 | 
        
           |  |  | 2187 |     /** @var block_base $retval */
 | 
        
           |  |  | 2188 |     $retval = new $classname;
 | 
        
           |  |  | 2189 |     if($instance !== NULL) {
 | 
        
           |  |  | 2190 |         if (is_null($page)) {
 | 
        
           |  |  | 2191 |             global $PAGE;
 | 
        
           |  |  | 2192 |             $page = $PAGE;
 | 
        
           |  |  | 2193 |         }
 | 
        
           |  |  | 2194 |         $retval->_load_instance($instance, $page);
 | 
        
           |  |  | 2195 |     }
 | 
        
           |  |  | 2196 |     return $retval;
 | 
        
           |  |  | 2197 | }
 | 
        
           |  |  | 2198 |   | 
        
           |  |  | 2199 | /**
 | 
        
           |  |  | 2200 |  * Load the block class for a particular type of block.
 | 
        
           |  |  | 2201 |  *
 | 
        
           |  |  | 2202 |  * @param string $blockname the name of the block.
 | 
        
           |  |  | 2203 |  * @return boolean success or failure.
 | 
        
           |  |  | 2204 |  */
 | 
        
           |  |  | 2205 | function block_load_class($blockname) {
 | 
        
           |  |  | 2206 |     global $CFG;
 | 
        
           |  |  | 2207 |   | 
        
           | 11 | efrain | 2208 |     $blocknameclean = clean_param($blockname, PARAM_PLUGIN);
 | 
        
           |  |  | 2209 |     if (empty($blockname) || empty($blocknameclean)) {
 | 
        
           | 1 | efrain | 2210 |         return false;
 | 
        
           |  |  | 2211 |     }
 | 
        
           |  |  | 2212 |   | 
        
           |  |  | 2213 |     $classname = 'block_'.$blockname;
 | 
        
           |  |  | 2214 |   | 
        
           |  |  | 2215 |     if(class_exists($classname)) {
 | 
        
           |  |  | 2216 |         return true;
 | 
        
           |  |  | 2217 |     }
 | 
        
           |  |  | 2218 |   | 
        
           |  |  | 2219 |     $blockpath = $CFG->dirroot.'/blocks/'.$blockname.'/block_'.$blockname.'.php';
 | 
        
           |  |  | 2220 |   | 
        
           |  |  | 2221 |     if (file_exists($blockpath)) {
 | 
        
           |  |  | 2222 |         require_once($CFG->dirroot.'/blocks/moodleblock.class.php');
 | 
        
           |  |  | 2223 |         include_once($blockpath);
 | 
        
           |  |  | 2224 |     }else{
 | 
        
           |  |  | 2225 |         //debugging("$blockname code does not exist in $blockpath", DEBUG_DEVELOPER);
 | 
        
           |  |  | 2226 |         return false;
 | 
        
           |  |  | 2227 |     }
 | 
        
           |  |  | 2228 |   | 
        
           |  |  | 2229 |     return class_exists($classname);
 | 
        
           |  |  | 2230 | }
 | 
        
           |  |  | 2231 |   | 
        
           |  |  | 2232 | /**
 | 
        
           |  |  | 2233 |  * Given a specific page type, return all the page type patterns that might
 | 
        
           |  |  | 2234 |  * match it.
 | 
        
           |  |  | 2235 |  *
 | 
        
           |  |  | 2236 |  * @param string $pagetype for example 'course-view-weeks' or 'mod-quiz-view'.
 | 
        
           |  |  | 2237 |  * @return array an array of all the page type patterns that might match this page type.
 | 
        
           |  |  | 2238 |  */
 | 
        
           |  |  | 2239 | function matching_page_type_patterns($pagetype) {
 | 
        
           |  |  | 2240 |     $patterns = array($pagetype);
 | 
        
           |  |  | 2241 |     $bits = explode('-', $pagetype);
 | 
        
           |  |  | 2242 |     if (count($bits) == 3 && $bits[0] == 'mod') {
 | 
        
           |  |  | 2243 |         if ($bits[2] == 'view') {
 | 
        
           |  |  | 2244 |             $patterns[] = 'mod-*-view';
 | 
        
           |  |  | 2245 |         } else if ($bits[2] == 'index') {
 | 
        
           |  |  | 2246 |             $patterns[] = 'mod-*-index';
 | 
        
           |  |  | 2247 |         }
 | 
        
           |  |  | 2248 |     }
 | 
        
           |  |  | 2249 |     while (count($bits) > 0) {
 | 
        
           |  |  | 2250 |         $patterns[] = implode('-', $bits) . '-*';
 | 
        
           |  |  | 2251 |         array_pop($bits);
 | 
        
           |  |  | 2252 |     }
 | 
        
           |  |  | 2253 |     $patterns[] = '*';
 | 
        
           |  |  | 2254 |     return $patterns;
 | 
        
           |  |  | 2255 | }
 | 
        
           |  |  | 2256 |   | 
        
           |  |  | 2257 | /**
 | 
        
           |  |  | 2258 |  * Give an specific pattern, return all the page type patterns that would also match it.
 | 
        
           |  |  | 2259 |  *
 | 
        
           |  |  | 2260 |  * @param  string $pattern the pattern, e.g. 'mod-forum-*' or 'mod-quiz-view'.
 | 
        
           |  |  | 2261 |  * @return array of all the page type patterns matching.
 | 
        
           |  |  | 2262 |  */
 | 
        
           |  |  | 2263 | function matching_page_type_patterns_from_pattern($pattern) {
 | 
        
           |  |  | 2264 |     $patterns = array($pattern);
 | 
        
           |  |  | 2265 |     if ($pattern === '*') {
 | 
        
           |  |  | 2266 |         return $patterns;
 | 
        
           |  |  | 2267 |     }
 | 
        
           |  |  | 2268 |   | 
        
           |  |  | 2269 |     // Only keep the part before the star because we will append -* to all the bits.
 | 
        
           |  |  | 2270 |     $star = strpos($pattern, '-*');
 | 
        
           |  |  | 2271 |     if ($star !== false) {
 | 
        
           |  |  | 2272 |         $pattern = substr($pattern, 0, $star);
 | 
        
           |  |  | 2273 |     }
 | 
        
           |  |  | 2274 |   | 
        
           |  |  | 2275 |     $patterns = array_merge($patterns, matching_page_type_patterns($pattern));
 | 
        
           |  |  | 2276 |     $patterns = array_unique($patterns);
 | 
        
           |  |  | 2277 |   | 
        
           |  |  | 2278 |     return $patterns;
 | 
        
           |  |  | 2279 | }
 | 
        
           |  |  | 2280 |   | 
        
           |  |  | 2281 | /**
 | 
        
           |  |  | 2282 |  * Given a specific page type, parent context and currect context, return all the page type patterns
 | 
        
           |  |  | 2283 |  * that might be used by this block.
 | 
        
           |  |  | 2284 |  *
 | 
        
           |  |  | 2285 |  * @param string $pagetype for example 'course-view-weeks' or 'mod-quiz-view'.
 | 
        
           |  |  | 2286 |  * @param stdClass $parentcontext Block's parent context
 | 
        
           |  |  | 2287 |  * @param stdClass $currentcontext Current context of block
 | 
        
           |  |  | 2288 |  * @return array an array of all the page type patterns that might match this page type.
 | 
        
           |  |  | 2289 |  */
 | 
        
           |  |  | 2290 | function generate_page_type_patterns($pagetype, $parentcontext = null, $currentcontext = null) {
 | 
        
           |  |  | 2291 |     global $CFG; // Required for includes bellow.
 | 
        
           |  |  | 2292 |   | 
        
           |  |  | 2293 |     $bits = explode('-', $pagetype);
 | 
        
           |  |  | 2294 |   | 
        
           |  |  | 2295 |     $core = core_component::get_core_subsystems();
 | 
        
           |  |  | 2296 |     $plugins = core_component::get_plugin_types();
 | 
        
           |  |  | 2297 |   | 
        
           |  |  | 2298 |     //progressively strip pieces off the page type looking for a match
 | 
        
           |  |  | 2299 |     $componentarray = null;
 | 
        
           |  |  | 2300 |     for ($i = count($bits); $i > 0; $i--) {
 | 
        
           |  |  | 2301 |         $possiblecomponentarray = array_slice($bits, 0, $i);
 | 
        
           |  |  | 2302 |         $possiblecomponent = implode('', $possiblecomponentarray);
 | 
        
           |  |  | 2303 |   | 
        
           |  |  | 2304 |         // Check to see if the component is a core component
 | 
        
           |  |  | 2305 |         if (array_key_exists($possiblecomponent, $core) && !empty($core[$possiblecomponent])) {
 | 
        
           |  |  | 2306 |             $libfile = $core[$possiblecomponent].'/lib.php';
 | 
        
           |  |  | 2307 |             if (file_exists($libfile)) {
 | 
        
           |  |  | 2308 |                 require_once($libfile);
 | 
        
           |  |  | 2309 |                 $function = $possiblecomponent.'_page_type_list';
 | 
        
           |  |  | 2310 |                 if (function_exists($function)) {
 | 
        
           |  |  | 2311 |                     if ($patterns = $function($pagetype, $parentcontext, $currentcontext)) {
 | 
        
           |  |  | 2312 |                         break;
 | 
        
           |  |  | 2313 |                     }
 | 
        
           |  |  | 2314 |                 }
 | 
        
           |  |  | 2315 |             }
 | 
        
           |  |  | 2316 |         }
 | 
        
           |  |  | 2317 |   | 
        
           |  |  | 2318 |         //check the plugin directory and look for a callback
 | 
        
           |  |  | 2319 |         if (array_key_exists($possiblecomponent, $plugins) && !empty($plugins[$possiblecomponent])) {
 | 
        
           |  |  | 2320 |   | 
        
           |  |  | 2321 |             //We've found a plugin type. Look for a plugin name by getting the next section of page type
 | 
        
           |  |  | 2322 |             if (count($bits) > $i) {
 | 
        
           |  |  | 2323 |                 $pluginname = $bits[$i];
 | 
        
           |  |  | 2324 |                 $directory = core_component::get_plugin_directory($possiblecomponent, $pluginname);
 | 
        
           |  |  | 2325 |                 if (!empty($directory)){
 | 
        
           |  |  | 2326 |                     $libfile = $directory.'/lib.php';
 | 
        
           |  |  | 2327 |                     if (file_exists($libfile)) {
 | 
        
           |  |  | 2328 |                         require_once($libfile);
 | 
        
           |  |  | 2329 |                         $function = $possiblecomponent.'_'.$pluginname.'_page_type_list';
 | 
        
           |  |  | 2330 |                         if (!function_exists($function)) {
 | 
        
           |  |  | 2331 |                             $function = $pluginname.'_page_type_list';
 | 
        
           |  |  | 2332 |                         }
 | 
        
           |  |  | 2333 |                         if (function_exists($function)) {
 | 
        
           |  |  | 2334 |                             if ($patterns = $function($pagetype, $parentcontext, $currentcontext)) {
 | 
        
           |  |  | 2335 |                                 break;
 | 
        
           |  |  | 2336 |                             }
 | 
        
           |  |  | 2337 |                         }
 | 
        
           |  |  | 2338 |                     }
 | 
        
           |  |  | 2339 |                 }
 | 
        
           |  |  | 2340 |             }
 | 
        
           |  |  | 2341 |   | 
        
           |  |  | 2342 |             //we'll only get to here if we still don't have any patterns
 | 
        
           |  |  | 2343 |             //the plugin type may have a callback
 | 
        
           |  |  | 2344 |             $directory = $plugins[$possiblecomponent];
 | 
        
           |  |  | 2345 |             $libfile = $directory.'/lib.php';
 | 
        
           |  |  | 2346 |             if (file_exists($libfile)) {
 | 
        
           |  |  | 2347 |                 require_once($libfile);
 | 
        
           |  |  | 2348 |                 $function = $possiblecomponent.'_page_type_list';
 | 
        
           |  |  | 2349 |                 if (function_exists($function)) {
 | 
        
           |  |  | 2350 |                     if ($patterns = $function($pagetype, $parentcontext, $currentcontext)) {
 | 
        
           |  |  | 2351 |                         break;
 | 
        
           |  |  | 2352 |                     }
 | 
        
           |  |  | 2353 |                 }
 | 
        
           |  |  | 2354 |             }
 | 
        
           |  |  | 2355 |         }
 | 
        
           |  |  | 2356 |     }
 | 
        
           |  |  | 2357 |   | 
        
           |  |  | 2358 |     if (empty($patterns)) {
 | 
        
           |  |  | 2359 |         $patterns = default_page_type_list($pagetype, $parentcontext, $currentcontext);
 | 
        
           |  |  | 2360 |     }
 | 
        
           |  |  | 2361 |   | 
        
           |  |  | 2362 |     // Ensure that the * pattern is always available if editing block 'at distance', so
 | 
        
           |  |  | 2363 |     // we always can 'bring back' it to the original context. MDL-30340
 | 
        
           |  |  | 2364 |     if ((!isset($currentcontext) or !isset($parentcontext) or $currentcontext->id != $parentcontext->id) && !isset($patterns['*'])) {
 | 
        
           |  |  | 2365 |         // TODO: We could change the string here, showing its 'bring back' meaning
 | 
        
           |  |  | 2366 |         $patterns['*'] = get_string('page-x', 'pagetype');
 | 
        
           |  |  | 2367 |     }
 | 
        
           |  |  | 2368 |   | 
        
           |  |  | 2369 |     return $patterns;
 | 
        
           |  |  | 2370 | }
 | 
        
           |  |  | 2371 |   | 
        
           |  |  | 2372 | /**
 | 
        
           |  |  | 2373 |  * Generates a default page type list when a more appropriate callback cannot be decided upon.
 | 
        
           |  |  | 2374 |  *
 | 
        
           |  |  | 2375 |  * @param string $pagetype
 | 
        
           |  |  | 2376 |  * @param stdClass $parentcontext
 | 
        
           |  |  | 2377 |  * @param stdClass $currentcontext
 | 
        
           |  |  | 2378 |  * @return array
 | 
        
           |  |  | 2379 |  */
 | 
        
           |  |  | 2380 | function default_page_type_list($pagetype, $parentcontext = null, $currentcontext = null) {
 | 
        
           |  |  | 2381 |     // Generate page type patterns based on current page type if
 | 
        
           |  |  | 2382 |     // callbacks haven't been defined
 | 
        
           |  |  | 2383 |     $patterns = array($pagetype => $pagetype);
 | 
        
           |  |  | 2384 |     $bits = explode('-', $pagetype);
 | 
        
           |  |  | 2385 |     while (count($bits) > 0) {
 | 
        
           |  |  | 2386 |         $pattern = implode('-', $bits) . '-*';
 | 
        
           |  |  | 2387 |         $pagetypestringname = 'page-'.str_replace('*', 'x', $pattern);
 | 
        
           |  |  | 2388 |         // guessing page type description
 | 
        
           |  |  | 2389 |         if (get_string_manager()->string_exists($pagetypestringname, 'pagetype')) {
 | 
        
           |  |  | 2390 |             $patterns[$pattern] = get_string($pagetypestringname, 'pagetype');
 | 
        
           |  |  | 2391 |         } else {
 | 
        
           |  |  | 2392 |             $patterns[$pattern] = $pattern;
 | 
        
           |  |  | 2393 |         }
 | 
        
           |  |  | 2394 |         array_pop($bits);
 | 
        
           |  |  | 2395 |     }
 | 
        
           |  |  | 2396 |     $patterns['*'] = get_string('page-x', 'pagetype');
 | 
        
           |  |  | 2397 |     return $patterns;
 | 
        
           |  |  | 2398 | }
 | 
        
           |  |  | 2399 |   | 
        
           |  |  | 2400 | /**
 | 
        
           |  |  | 2401 |  * Generates the page type list for the my moodle page
 | 
        
           |  |  | 2402 |  *
 | 
        
           |  |  | 2403 |  * @param string $pagetype
 | 
        
           |  |  | 2404 |  * @param stdClass $parentcontext
 | 
        
           |  |  | 2405 |  * @param stdClass $currentcontext
 | 
        
           |  |  | 2406 |  * @return array
 | 
        
           |  |  | 2407 |  */
 | 
        
           |  |  | 2408 | function my_page_type_list($pagetype, $parentcontext = null, $currentcontext = null) {
 | 
        
           |  |  | 2409 |     return array('my-index' => get_string('page-my-index', 'pagetype'));
 | 
        
           |  |  | 2410 | }
 | 
        
           |  |  | 2411 |   | 
        
           |  |  | 2412 | /**
 | 
        
           |  |  | 2413 |  * Generates the page type list for a module by either locating and using the modules callback
 | 
        
           |  |  | 2414 |  * or by generating a default list.
 | 
        
           |  |  | 2415 |  *
 | 
        
           |  |  | 2416 |  * @param string $pagetype
 | 
        
           |  |  | 2417 |  * @param stdClass $parentcontext
 | 
        
           |  |  | 2418 |  * @param stdClass $currentcontext
 | 
        
           |  |  | 2419 |  * @return array
 | 
        
           |  |  | 2420 |  */
 | 
        
           |  |  | 2421 | function mod_page_type_list($pagetype, $parentcontext = null, $currentcontext = null) {
 | 
        
           |  |  | 2422 |     $patterns = plugin_page_type_list($pagetype, $parentcontext, $currentcontext);
 | 
        
           |  |  | 2423 |     if (empty($patterns)) {
 | 
        
           |  |  | 2424 |         // if modules don't have callbacks
 | 
        
           |  |  | 2425 |         // generate two default page type patterns for modules only
 | 
        
           |  |  | 2426 |         $bits = explode('-', $pagetype);
 | 
        
           |  |  | 2427 |         $patterns = array($pagetype => $pagetype);
 | 
        
           |  |  | 2428 |         if ($bits[2] == 'view') {
 | 
        
           |  |  | 2429 |             $patterns['mod-*-view'] = get_string('page-mod-x-view', 'pagetype');
 | 
        
           |  |  | 2430 |         } else if ($bits[2] == 'index') {
 | 
        
           |  |  | 2431 |             $patterns['mod-*-index'] = get_string('page-mod-x-index', 'pagetype');
 | 
        
           |  |  | 2432 |         }
 | 
        
           |  |  | 2433 |     }
 | 
        
           |  |  | 2434 |     return $patterns;
 | 
        
           |  |  | 2435 | }
 | 
        
           |  |  | 2436 | /// Functions update the blocks if required by the request parameters ==========
 | 
        
           |  |  | 2437 |   | 
        
           |  |  | 2438 | /**
 | 
        
           |  |  | 2439 |  * Return a {@link block_contents} representing the add a new block UI, if
 | 
        
           |  |  | 2440 |  * this user is allowed to see it.
 | 
        
           |  |  | 2441 |  *
 | 
        
           |  |  | 2442 |  * @return ?block_contents an appropriate block_contents, or null if the user
 | 
        
           |  |  | 2443 |  * cannot add any blocks here.
 | 
        
           |  |  | 2444 |  */
 | 
        
           |  |  | 2445 | function block_add_block_ui($page, $output) {
 | 
        
           |  |  | 2446 |     global $CFG, $OUTPUT;
 | 
        
           |  |  | 2447 |     if (!$page->user_is_editing() || !$page->user_can_edit_blocks()) {
 | 
        
           |  |  | 2448 |         return null;
 | 
        
           |  |  | 2449 |     }
 | 
        
           |  |  | 2450 |   | 
        
           |  |  | 2451 |     $bc = new block_contents();
 | 
        
           |  |  | 2452 |     $bc->title = get_string('addblock');
 | 
        
           |  |  | 2453 |     $bc->add_class('block_adminblock');
 | 
        
           |  |  | 2454 |     $bc->attributes['data-block'] = 'adminblock';
 | 
        
           |  |  | 2455 |   | 
        
           |  |  | 2456 |     $missingblocks = $page->blocks->get_addable_blocks();
 | 
        
           |  |  | 2457 |     if (empty($missingblocks)) {
 | 
        
           |  |  | 2458 |         $bc->content = get_string('noblockstoaddhere');
 | 
        
           |  |  | 2459 |         return $bc;
 | 
        
           |  |  | 2460 |     }
 | 
        
           |  |  | 2461 |   | 
        
           |  |  | 2462 |     $menu = array();
 | 
        
           |  |  | 2463 |     foreach ($missingblocks as $block) {
 | 
        
           |  |  | 2464 |         $menu[$block->name] = $block->title;
 | 
        
           |  |  | 2465 |     }
 | 
        
           |  |  | 2466 |   | 
        
           |  |  | 2467 |     $actionurl = new moodle_url($page->url, array('sesskey'=>sesskey()));
 | 
        
           |  |  | 2468 |     $select = new single_select($actionurl, 'bui_addblock', $menu, null, array(''=>get_string('adddots')), 'add_block');
 | 
        
           |  |  | 2469 |     $select->set_label(get_string('addblock'), array('class'=>'accesshide'));
 | 
        
           |  |  | 2470 |     $bc->content = $OUTPUT->render($select);
 | 
        
           |  |  | 2471 |     return $bc;
 | 
        
           |  |  | 2472 | }
 | 
        
           |  |  | 2473 |   | 
        
           |  |  | 2474 | /**
 | 
        
           |  |  | 2475 |  * Actually delete from the database any blocks that are currently on this page,
 | 
        
           |  |  | 2476 |  * but which should not be there according to blocks_name_allowed_in_format.
 | 
        
           |  |  | 2477 |  *
 | 
        
           |  |  | 2478 |  * @todo Write/Fix this function. Currently returns immediately
 | 
        
           |  |  | 2479 |  * @param $course
 | 
        
           |  |  | 2480 |  */
 | 
        
           |  |  | 2481 | function blocks_remove_inappropriate($course) {
 | 
        
           |  |  | 2482 |     // TODO
 | 
        
           |  |  | 2483 |     return;
 | 
        
           |  |  | 2484 |     /*
 | 
        
           |  |  | 2485 |     $blockmanager = blocks_get_by_page($page);
 | 
        
           |  |  | 2486 |   | 
        
           |  |  | 2487 |     if (empty($blockmanager)) {
 | 
        
           |  |  | 2488 |         return;
 | 
        
           |  |  | 2489 |     }
 | 
        
           |  |  | 2490 |   | 
        
           |  |  | 2491 |     if (($pageformat = $page->pagetype) == NULL) {
 | 
        
           |  |  | 2492 |         return;
 | 
        
           |  |  | 2493 |     }
 | 
        
           |  |  | 2494 |   | 
        
           |  |  | 2495 |     foreach($blockmanager as $region) {
 | 
        
           |  |  | 2496 |         foreach($region as $instance) {
 | 
        
           |  |  | 2497 |             $block = blocks_get_record($instance->blockid);
 | 
        
           |  |  | 2498 |             if(!blocks_name_allowed_in_format($block->name, $pageformat)) {
 | 
        
           |  |  | 2499 |                blocks_delete_instance($instance->instance);
 | 
        
           |  |  | 2500 |             }
 | 
        
           |  |  | 2501 |         }
 | 
        
           |  |  | 2502 |     }*/
 | 
        
           |  |  | 2503 | }
 | 
        
           |  |  | 2504 |   | 
        
           |  |  | 2505 | /**
 | 
        
           |  |  | 2506 |  * Check that a given name is in a permittable format
 | 
        
           |  |  | 2507 |  *
 | 
        
           |  |  | 2508 |  * @param string $name
 | 
        
           |  |  | 2509 |  * @param string $pageformat
 | 
        
           |  |  | 2510 |  * @return bool
 | 
        
           |  |  | 2511 |  */
 | 
        
           |  |  | 2512 | function blocks_name_allowed_in_format($name, $pageformat) {
 | 
        
           |  |  | 2513 |     $accept = NULL;
 | 
        
           |  |  | 2514 |     $maxdepth = -1;
 | 
        
           |  |  | 2515 |     if (!$bi = block_instance($name)) {
 | 
        
           |  |  | 2516 |         return false;
 | 
        
           |  |  | 2517 |     }
 | 
        
           |  |  | 2518 |   | 
        
           |  |  | 2519 |     $formats = $bi->applicable_formats();
 | 
        
           |  |  | 2520 |     if (!$formats) {
 | 
        
           |  |  | 2521 |         $formats = array();
 | 
        
           |  |  | 2522 |     }
 | 
        
           |  |  | 2523 |     foreach ($formats as $format => $allowed) {
 | 
        
           |  |  | 2524 |         $formatregex = '/^'.str_replace('*', '[^-]*', $format).'.*$/';
 | 
        
           |  |  | 2525 |         $depth = substr_count($format, '-');
 | 
        
           |  |  | 2526 |         if (preg_match($formatregex, $pageformat) && $depth > $maxdepth) {
 | 
        
           |  |  | 2527 |             $maxdepth = $depth;
 | 
        
           |  |  | 2528 |             $accept = $allowed;
 | 
        
           |  |  | 2529 |         }
 | 
        
           |  |  | 2530 |     }
 | 
        
           |  |  | 2531 |     if ($accept === NULL) {
 | 
        
           |  |  | 2532 |         $accept = !empty($formats['all']);
 | 
        
           |  |  | 2533 |     }
 | 
        
           |  |  | 2534 |     return $accept;
 | 
        
           |  |  | 2535 | }
 | 
        
           |  |  | 2536 |   | 
        
           |  |  | 2537 | /**
 | 
        
           |  |  | 2538 |  * Delete a block, and associated data.
 | 
        
           |  |  | 2539 |  *
 | 
        
           |  |  | 2540 |  * @param object $instance a row from the block_instances table
 | 
        
           |  |  | 2541 |  * @param bool $nolongerused legacy parameter. Not used, but kept for backwards compatibility.
 | 
        
           |  |  | 2542 |  * @param bool $skipblockstables for internal use only. Makes @see blocks_delete_all_for_context() more efficient.
 | 
        
           |  |  | 2543 |  */
 | 
        
           |  |  | 2544 | function blocks_delete_instance($instance, $nolongerused = false, $skipblockstables = false) {
 | 
        
           |  |  | 2545 |     global $DB;
 | 
        
           |  |  | 2546 |   | 
        
           |  |  | 2547 |     // Allow plugins to use this block before we completely delete it.
 | 
        
           |  |  | 2548 |     if ($pluginsfunction = get_plugins_with_function('pre_block_delete')) {
 | 
        
           |  |  | 2549 |         foreach ($pluginsfunction as $plugintype => $plugins) {
 | 
        
           |  |  | 2550 |             foreach ($plugins as $pluginfunction) {
 | 
        
           |  |  | 2551 |                 $pluginfunction($instance);
 | 
        
           |  |  | 2552 |             }
 | 
        
           |  |  | 2553 |         }
 | 
        
           |  |  | 2554 |     }
 | 
        
           |  |  | 2555 |   | 
        
           |  |  | 2556 |     if ($block = block_instance($instance->blockname, $instance)) {
 | 
        
           |  |  | 2557 |         $block->instance_delete();
 | 
        
           |  |  | 2558 |     }
 | 
        
           |  |  | 2559 |     context_helper::delete_instance(CONTEXT_BLOCK, $instance->id);
 | 
        
           |  |  | 2560 |   | 
        
           |  |  | 2561 |     if (!$skipblockstables) {
 | 
        
           |  |  | 2562 |         $DB->delete_records('block_positions', array('blockinstanceid' => $instance->id));
 | 
        
           |  |  | 2563 |         $DB->delete_records('block_instances', array('id' => $instance->id));
 | 
        
           |  |  | 2564 |         $DB->delete_records_list('user_preferences', 'name', array('block'.$instance->id.'hidden','docked_block_instance_'.$instance->id));
 | 
        
           |  |  | 2565 |     }
 | 
        
           |  |  | 2566 | }
 | 
        
           |  |  | 2567 |   | 
        
           |  |  | 2568 | /**
 | 
        
           |  |  | 2569 |  * Delete multiple blocks at once.
 | 
        
           |  |  | 2570 |  *
 | 
        
           |  |  | 2571 |  * @param array $instanceids A list of block instance ID.
 | 
        
           |  |  | 2572 |  */
 | 
        
           |  |  | 2573 | function blocks_delete_instances($instanceids) {
 | 
        
           |  |  | 2574 |     global $DB;
 | 
        
           |  |  | 2575 |   | 
        
           |  |  | 2576 |     $limit = 1000;
 | 
        
           |  |  | 2577 |     $count = count($instanceids);
 | 
        
           |  |  | 2578 |     $chunks = [$instanceids];
 | 
        
           |  |  | 2579 |     if ($count > $limit) {
 | 
        
           |  |  | 2580 |         $chunks = array_chunk($instanceids, $limit);
 | 
        
           |  |  | 2581 |     }
 | 
        
           |  |  | 2582 |   | 
        
           |  |  | 2583 |     // Perform deletion for each chunk.
 | 
        
           |  |  | 2584 |     foreach ($chunks as $chunk) {
 | 
        
           |  |  | 2585 |         $instances = $DB->get_recordset_list('block_instances', 'id', $chunk);
 | 
        
           |  |  | 2586 |         foreach ($instances as $instance) {
 | 
        
           |  |  | 2587 |             blocks_delete_instance($instance, false, true);
 | 
        
           |  |  | 2588 |         }
 | 
        
           |  |  | 2589 |         $instances->close();
 | 
        
           |  |  | 2590 |   | 
        
           |  |  | 2591 |         $DB->delete_records_list('block_positions', 'blockinstanceid', $chunk);
 | 
        
           |  |  | 2592 |         $DB->delete_records_list('block_instances', 'id', $chunk);
 | 
        
           |  |  | 2593 |   | 
        
           |  |  | 2594 |         $preferences = array();
 | 
        
           |  |  | 2595 |         foreach ($chunk as $instanceid) {
 | 
        
           |  |  | 2596 |             $preferences[] = 'block' . $instanceid . 'hidden';
 | 
        
           |  |  | 2597 |             $preferences[] = 'docked_block_instance_' . $instanceid;
 | 
        
           |  |  | 2598 |         }
 | 
        
           |  |  | 2599 |         $DB->delete_records_list('user_preferences', 'name', $preferences);
 | 
        
           |  |  | 2600 |     }
 | 
        
           |  |  | 2601 | }
 | 
        
           |  |  | 2602 |   | 
        
           |  |  | 2603 | /**
 | 
        
           |  |  | 2604 |  * Delete all the blocks that belong to a particular context.
 | 
        
           |  |  | 2605 |  *
 | 
        
           |  |  | 2606 |  * @param int $contextid the context id.
 | 
        
           |  |  | 2607 |  */
 | 
        
           |  |  | 2608 | function blocks_delete_all_for_context($contextid) {
 | 
        
           |  |  | 2609 |     global $DB;
 | 
        
           |  |  | 2610 |     $instances = $DB->get_recordset('block_instances', array('parentcontextid' => $contextid));
 | 
        
           |  |  | 2611 |     foreach ($instances as $instance) {
 | 
        
           |  |  | 2612 |         blocks_delete_instance($instance, true);
 | 
        
           |  |  | 2613 |     }
 | 
        
           |  |  | 2614 |     $instances->close();
 | 
        
           |  |  | 2615 |     $DB->delete_records('block_instances', array('parentcontextid' => $contextid));
 | 
        
           |  |  | 2616 |     $DB->delete_records('block_positions', array('contextid' => $contextid));
 | 
        
           |  |  | 2617 | }
 | 
        
           |  |  | 2618 |   | 
        
           |  |  | 2619 | /**
 | 
        
           |  |  | 2620 |  * Set a block to be visible or hidden on a particular page.
 | 
        
           |  |  | 2621 |  *
 | 
        
           |  |  | 2622 |  * @param object $instance a row from the block_instances, preferably LEFT JOINed with the
 | 
        
           |  |  | 2623 |  *      block_positions table as return by block_manager.
 | 
        
           |  |  | 2624 |  * @param moodle_page $page the back to set the visibility with respect to.
 | 
        
           |  |  | 2625 |  * @param integer $newvisibility 1 for visible, 0 for hidden.
 | 
        
           |  |  | 2626 |  */
 | 
        
           |  |  | 2627 | function blocks_set_visibility($instance, $page, $newvisibility) {
 | 
        
           |  |  | 2628 |     global $DB;
 | 
        
           |  |  | 2629 |     if (!empty($instance->blockpositionid)) {
 | 
        
           |  |  | 2630 |         // Already have local information on this page.
 | 
        
           |  |  | 2631 |         $DB->set_field('block_positions', 'visible', $newvisibility, array('id' => $instance->blockpositionid));
 | 
        
           |  |  | 2632 |         return;
 | 
        
           |  |  | 2633 |     }
 | 
        
           |  |  | 2634 |   | 
        
           |  |  | 2635 |     // Create a new block_positions record.
 | 
        
           |  |  | 2636 |     $bp = new stdClass;
 | 
        
           |  |  | 2637 |     $bp->blockinstanceid = $instance->id;
 | 
        
           |  |  | 2638 |     $bp->contextid = $page->context->id;
 | 
        
           |  |  | 2639 |     $bp->pagetype = $page->pagetype;
 | 
        
           |  |  | 2640 |     if ($page->subpage) {
 | 
        
           |  |  | 2641 |         $bp->subpage = $page->subpage;
 | 
        
           |  |  | 2642 |     }
 | 
        
           |  |  | 2643 |     $bp->visible = $newvisibility;
 | 
        
           |  |  | 2644 |     $bp->region = $instance->defaultregion;
 | 
        
           |  |  | 2645 |     $bp->weight = $instance->defaultweight;
 | 
        
           |  |  | 2646 |     $DB->insert_record('block_positions', $bp);
 | 
        
           |  |  | 2647 | }
 | 
        
           |  |  | 2648 |   | 
        
           |  |  | 2649 | /**
 | 
        
           |  |  | 2650 |  * Get the block record for a particular blockid - that is, a particular type os block.
 | 
        
           |  |  | 2651 |  *
 | 
        
           |  |  | 2652 |  * @param $int blockid block type id. If null, an array of all block types is returned.
 | 
        
           |  |  | 2653 |  * @param bool $notusedanymore No longer used.
 | 
        
           |  |  | 2654 |  * @return array|object|false row from block table, or all rows.
 | 
        
           |  |  | 2655 |  */
 | 
        
           |  |  | 2656 | function blocks_get_record($blockid = NULL, $notusedanymore = false) {
 | 
        
           |  |  | 2657 |     global $PAGE;
 | 
        
           |  |  | 2658 |     $blocks = $PAGE->blocks->get_installed_blocks();
 | 
        
           |  |  | 2659 |     if ($blockid === NULL) {
 | 
        
           |  |  | 2660 |         return $blocks;
 | 
        
           |  |  | 2661 |     } else if (isset($blocks[$blockid])) {
 | 
        
           |  |  | 2662 |         return $blocks[$blockid];
 | 
        
           |  |  | 2663 |     } else {
 | 
        
           |  |  | 2664 |         return false;
 | 
        
           |  |  | 2665 |     }
 | 
        
           |  |  | 2666 | }
 | 
        
           |  |  | 2667 |   | 
        
           |  |  | 2668 | /**
 | 
        
           |  |  | 2669 |  * Find a given block by its blockid within a provide array
 | 
        
           |  |  | 2670 |  *
 | 
        
           |  |  | 2671 |  * @param int $blockid
 | 
        
           |  |  | 2672 |  * @param array $blocksarray
 | 
        
           |  |  | 2673 |  * @return bool|object Instance if found else false
 | 
        
           |  |  | 2674 |  */
 | 
        
           |  |  | 2675 | function blocks_find_block($blockid, $blocksarray) {
 | 
        
           |  |  | 2676 |     if (empty($blocksarray)) {
 | 
        
           |  |  | 2677 |         return false;
 | 
        
           |  |  | 2678 |     }
 | 
        
           |  |  | 2679 |     foreach($blocksarray as $blockgroup) {
 | 
        
           |  |  | 2680 |         if (empty($blockgroup)) {
 | 
        
           |  |  | 2681 |             continue;
 | 
        
           |  |  | 2682 |         }
 | 
        
           |  |  | 2683 |         foreach($blockgroup as $instance) {
 | 
        
           |  |  | 2684 |             if($instance->blockid == $blockid) {
 | 
        
           |  |  | 2685 |                 return $instance;
 | 
        
           |  |  | 2686 |             }
 | 
        
           |  |  | 2687 |         }
 | 
        
           |  |  | 2688 |     }
 | 
        
           |  |  | 2689 |     return false;
 | 
        
           |  |  | 2690 | }
 | 
        
           |  |  | 2691 |   | 
        
           |  |  | 2692 | // Functions for programatically adding default blocks to pages ================
 | 
        
           |  |  | 2693 |   | 
        
           |  |  | 2694 |  /**
 | 
        
           |  |  | 2695 |   * Parse a list of default blocks. See config-dist for a description of the format.
 | 
        
           |  |  | 2696 |   *
 | 
        
           |  |  | 2697 |   * @param string $blocksstr Determines the starting point that the blocks are added in the region.
 | 
        
           |  |  | 2698 |   * @return array the parsed list of default blocks
 | 
        
           |  |  | 2699 |   */
 | 
        
           |  |  | 2700 | function blocks_parse_default_blocks_list($blocksstr) {
 | 
        
           |  |  | 2701 |     $blocks = array();
 | 
        
           |  |  | 2702 |     $bits = explode(':', $blocksstr);
 | 
        
           |  |  | 2703 |     if (!empty($bits)) {
 | 
        
           |  |  | 2704 |         $leftbits = trim(array_shift($bits));
 | 
        
           |  |  | 2705 |         if ($leftbits != '') {
 | 
        
           |  |  | 2706 |             $blocks[BLOCK_POS_LEFT] = explode(',', $leftbits);
 | 
        
           |  |  | 2707 |         }
 | 
        
           |  |  | 2708 |     }
 | 
        
           |  |  | 2709 |     if (!empty($bits)) {
 | 
        
           |  |  | 2710 |         $rightbits = trim(array_shift($bits));
 | 
        
           |  |  | 2711 |         if ($rightbits != '') {
 | 
        
           |  |  | 2712 |             $blocks[BLOCK_POS_RIGHT] = explode(',', $rightbits);
 | 
        
           |  |  | 2713 |         }
 | 
        
           |  |  | 2714 |     }
 | 
        
           |  |  | 2715 |     return $blocks;
 | 
        
           |  |  | 2716 | }
 | 
        
           |  |  | 2717 |   | 
        
           |  |  | 2718 | /**
 | 
        
           |  |  | 2719 |  * @return array the blocks that should be added to the site course by default.
 | 
        
           |  |  | 2720 |  */
 | 
        
           |  |  | 2721 | function blocks_get_default_site_course_blocks() {
 | 
        
           |  |  | 2722 |     global $CFG;
 | 
        
           |  |  | 2723 |   | 
        
           |  |  | 2724 |     if (isset($CFG->defaultblocks_site)) {
 | 
        
           |  |  | 2725 |         return blocks_parse_default_blocks_list($CFG->defaultblocks_site);
 | 
        
           |  |  | 2726 |     } else {
 | 
        
           |  |  | 2727 |         return array(
 | 
        
           |  |  | 2728 |             BLOCK_POS_LEFT => array(),
 | 
        
           |  |  | 2729 |             BLOCK_POS_RIGHT => array()
 | 
        
           |  |  | 2730 |         );
 | 
        
           |  |  | 2731 |     }
 | 
        
           |  |  | 2732 | }
 | 
        
           |  |  | 2733 |   | 
        
           |  |  | 2734 | /**
 | 
        
           |  |  | 2735 |  * Add the default blocks to a course.
 | 
        
           |  |  | 2736 |  *
 | 
        
           | 1441 | ariadna | 2737 |  * Because this function is used on install, we skip over any default blocks that do not exist
 | 
        
           |  |  | 2738 |  * so that install can complete successfully even if blocks are removed.
 | 
        
           |  |  | 2739 |  *
 | 
        
           | 1 | efrain | 2740 |  * @param object $course a course object.
 | 
        
           |  |  | 2741 |  */
 | 
        
           |  |  | 2742 | function blocks_add_default_course_blocks($course) {
 | 
        
           |  |  | 2743 |     global $CFG;
 | 
        
           |  |  | 2744 |   | 
        
           |  |  | 2745 |     if (isset($CFG->defaultblocks_override)) {
 | 
        
           |  |  | 2746 |         $blocknames = blocks_parse_default_blocks_list($CFG->defaultblocks_override);
 | 
        
           |  |  | 2747 |   | 
        
           |  |  | 2748 |     } else if ($course->id == SITEID) {
 | 
        
           |  |  | 2749 |         $blocknames = blocks_get_default_site_course_blocks();
 | 
        
           |  |  | 2750 |   | 
        
           |  |  | 2751 |     } else if (isset($CFG->{'defaultblocks_' . $course->format})) {
 | 
        
           |  |  | 2752 |         $blocknames = blocks_parse_default_blocks_list($CFG->{'defaultblocks_' . $course->format});
 | 
        
           |  |  | 2753 |   | 
        
           |  |  | 2754 |     } else {
 | 
        
           |  |  | 2755 |         require_once($CFG->dirroot. '/course/lib.php');
 | 
        
           |  |  | 2756 |         $blocknames = course_get_format($course)->get_default_blocks();
 | 
        
           |  |  | 2757 |   | 
        
           |  |  | 2758 |     }
 | 
        
           |  |  | 2759 |   | 
        
           |  |  | 2760 |     if ($course->id == SITEID) {
 | 
        
           |  |  | 2761 |         $pagetypepattern = 'site-index';
 | 
        
           |  |  | 2762 |     } else {
 | 
        
           |  |  | 2763 |         $pagetypepattern = 'course-view-*';
 | 
        
           |  |  | 2764 |     }
 | 
        
           |  |  | 2765 |     $page = new moodle_page();
 | 
        
           |  |  | 2766 |     $page->set_course($course);
 | 
        
           | 1441 | ariadna | 2767 |     $page->blocks->add_blocks(
 | 
        
           |  |  | 2768 |         $page->blocks->filter_nonexistent_blocks($blocknames),
 | 
        
           |  |  | 2769 |         $pagetypepattern,
 | 
        
           |  |  | 2770 |     );
 | 
        
           | 1 | efrain | 2771 | }
 | 
        
           |  |  | 2772 |   | 
        
           |  |  | 2773 | /**
 | 
        
           |  |  | 2774 |  * Add the default system-context blocks. E.g. the admin tree.
 | 
        
           | 1441 | ariadna | 2775 |  *
 | 
        
           |  |  | 2776 |  * Because this function is used on install, we skip over any default blocks that do not exist
 | 
        
           |  |  | 2777 |  * so that install can complete successfully even if blocks are removed.
 | 
        
           | 1 | efrain | 2778 |  */
 | 
        
           |  |  | 2779 | function blocks_add_default_system_blocks() {
 | 
        
           |  |  | 2780 |     global $DB;
 | 
        
           |  |  | 2781 |   | 
        
           |  |  | 2782 |     $page = new moodle_page();
 | 
        
           |  |  | 2783 |     $page->set_context(context_system::instance());
 | 
        
           |  |  | 2784 |     // We don't add blocks required by the theme, they will be auto-created.
 | 
        
           | 1441 | ariadna | 2785 |     $page->blocks->add_blocks(
 | 
        
           |  |  | 2786 |         $page->blocks->filter_nonexistent_blocks([
 | 
        
           |  |  | 2787 |             BLOCK_POS_LEFT => [
 | 
        
           |  |  | 2788 |                 'admin_bookmarks',
 | 
        
           |  |  | 2789 |             ],
 | 
        
           |  |  | 2790 |         ]),
 | 
        
           |  |  | 2791 |         'admin-*',
 | 
        
           |  |  | 2792 |         null,
 | 
        
           |  |  | 2793 |         false,
 | 
        
           |  |  | 2794 |         2,
 | 
        
           |  |  | 2795 |     );
 | 
        
           | 1 | efrain | 2796 |   | 
        
           |  |  | 2797 |     if ($defaultmypage = $DB->get_record('my_pages', array('userid' => null, 'name' => '__default', 'private' => 1))) {
 | 
        
           |  |  | 2798 |         $subpagepattern = $defaultmypage->id;
 | 
        
           |  |  | 2799 |     } else {
 | 
        
           |  |  | 2800 |         $subpagepattern = null;
 | 
        
           |  |  | 2801 |     }
 | 
        
           |  |  | 2802 |   | 
        
           |  |  | 2803 |     if ($defaultmycoursespage = $DB->get_record('my_pages', array('userid' => null, 'name' => '__courses', 'private' => 0))) {
 | 
        
           |  |  | 2804 |         $mycoursesubpagepattern = $defaultmycoursespage->id;
 | 
        
           |  |  | 2805 |     } else {
 | 
        
           |  |  | 2806 |         $mycoursesubpagepattern = null;
 | 
        
           |  |  | 2807 |     }
 | 
        
           |  |  | 2808 |   | 
        
           | 1441 | ariadna | 2809 |     $page->blocks->add_blocks($page->blocks->filter_nonexistent_blocks([
 | 
        
           | 1 | efrain | 2810 |         BLOCK_POS_RIGHT => [
 | 
        
           |  |  | 2811 |             'recentlyaccesseditems',
 | 
        
           |  |  | 2812 |         ],
 | 
        
           |  |  | 2813 |         'content' => [
 | 
        
           |  |  | 2814 |             'timeline',
 | 
        
           |  |  | 2815 |             'calendar_month',
 | 
        
           | 1441 | ariadna | 2816 |         ]]),
 | 
        
           | 1 | efrain | 2817 |         'my-index',
 | 
        
           |  |  | 2818 |         $subpagepattern
 | 
        
           |  |  | 2819 |     );
 | 
        
           |  |  | 2820 |   | 
        
           | 1441 | ariadna | 2821 |     $page->blocks->add_blocks($page->blocks->filter_nonexistent_blocks([
 | 
        
           | 1 | efrain | 2822 |         'content' => [
 | 
        
           |  |  | 2823 |             'myoverview'
 | 
        
           | 1441 | ariadna | 2824 |         ]]),
 | 
        
           | 1 | efrain | 2825 |         'my-index',
 | 
        
           |  |  | 2826 |         $mycoursesubpagepattern
 | 
        
           |  |  | 2827 |     );
 | 
        
           |  |  | 2828 | }
 |