Moodle  2.2.1
http://www.collinsharper.com
C:/xampp/htdocs/moodle/lib/blocklib.php
Go to the documentation of this file.
00001 <?php
00002 
00003 // This file is part of Moodle - http://moodle.org/
00004 //
00005 // Moodle is free software: you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation, either version 3 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // Moodle is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
00017 
00029 defined('MOODLE_INTERNAL') || die();
00030 
00034 define('BLOCK_MOVE_LEFT',   0x01);
00035 define('BLOCK_MOVE_RIGHT',  0x02);
00036 define('BLOCK_MOVE_UP',     0x04);
00037 define('BLOCK_MOVE_DOWN',   0x08);
00038 define('BLOCK_CONFIGURE',   0x10);
00044 define('BLOCK_POS_LEFT',  'side-pre');
00045 define('BLOCK_POS_RIGHT', 'side-post');
00051 define('BLOCKS_PINNED_TRUE',0);
00052 define('BLOCKS_PINNED_FALSE',1);
00053 define('BLOCKS_PINNED_BOTH',2);
00056 define('BUI_CONTEXTS_FRONTPAGE_ONLY', 0);
00057 define('BUI_CONTEXTS_FRONTPAGE_SUBS', 1);
00058 define('BUI_CONTEXTS_ENTIRE_SITE', 2);
00059 
00060 define('BUI_CONTEXTS_CURRENT', 0);
00061 define('BUI_CONTEXTS_CURRENT_SUBS', 1);
00062 
00071 class block_not_on_page_exception extends moodle_exception {
00077     public function __construct($instanceid, $page) {
00078         $a = new stdClass;
00079         $a->instanceid = $instanceid;
00080         $a->url = $page->url->out();
00081         parent::__construct('blockdoesnotexistonpage', '', $page->url->out(), $a);
00082     }
00083 }
00084 
00094 class block_manager {
00099     const MAX_WEIGHT = 10;
00100 
00102 
00107     protected $page;
00108 
00110     protected $regions = array();
00111 
00113     protected $defaultregion = null;
00114 
00116     protected $allblocks = null;
00117 
00123     protected $addableblocks = null;
00124 
00129     protected $birecordsbyregion = null;
00130 
00136     protected $blockinstances = array();
00137 
00143     protected $visibleblockcontent = array();
00144 
00150     protected $extracontent = array();
00151 
00161     protected $movingblock = null;
00162 
00166     protected $fakeblocksonly = false;
00167 
00169 
00176     public function __construct($page) {
00177         $this->page = $page;
00178     }
00179 
00181 
00187     public function get_regions() {
00188         if (is_null($this->defaultregion)) {
00189             $this->page->initialise_theme_and_output();
00190         }
00191         return array_keys($this->regions);
00192     }
00193 
00202     public function get_default_region() {
00203         $this->page->initialise_theme_and_output();
00204         return $this->defaultregion;
00205     }
00206 
00212     public function get_addable_blocks() {
00213         $this->check_is_loaded();
00214 
00215         if (!is_null($this->addableblocks)) {
00216             return $this->addableblocks;
00217         }
00218 
00219         // Lazy load.
00220         $this->addableblocks = array();
00221 
00222         $allblocks = blocks_get_record();
00223         if (empty($allblocks)) {
00224             return $this->addableblocks;
00225         }
00226 
00227         $pageformat = $this->page->pagetype;
00228         foreach($allblocks as $block) {
00229             if ($block->visible &&
00230                     (block_method_result($block->name, 'instance_allow_multiple') || !$this->is_block_present($block->name)) &&
00231                     blocks_name_allowed_in_format($block->name, $pageformat) &&
00232                     block_method_result($block->name, 'user_can_addto', $this->page)) {
00233                 $this->addableblocks[$block->name] = $block;
00234             }
00235         }
00236 
00237         return $this->addableblocks;
00238     }
00239 
00246     public function is_block_present($blockname) {
00247         if (empty($this->blockinstances)) {
00248             return false;
00249         }
00250 
00251         foreach ($this->blockinstances as $region) {
00252             foreach ($region as $instance) {
00253                 if (empty($instance->instance->blockname)) {
00254                     continue;
00255                 }
00256                 if ($instance->instance->blockname == $blockname) {
00257                     return true;
00258                 }
00259             }
00260         }
00261         return false;
00262     }
00263 
00271     public function is_known_block_type($blockname, $includeinvisible = false) {
00272         $blocks = $this->get_installed_blocks();
00273         foreach ($blocks as $block) {
00274             if ($block->name == $blockname && ($includeinvisible || $block->visible)) {
00275                 return true;
00276             }
00277         }
00278         return false;
00279     }
00280 
00287     public function is_known_region($region) {
00288         return array_key_exists($region, $this->regions);
00289     }
00290 
00297     public function get_blocks_for_region($region) {
00298         $this->check_is_loaded();
00299         $this->ensure_instances_exist($region);
00300         return $this->blockinstances[$region];
00301     }
00302 
00309     public function get_content_for_region($region, $output) {
00310         $this->check_is_loaded();
00311         $this->ensure_content_created($region, $output);
00312         return $this->visibleblockcontent[$region];
00313     }
00314 
00322     protected function get_move_target_url($region, $weight) {
00323         return new moodle_url($this->page->url, array('bui_moveid' => $this->movingblock,
00324                 'bui_newregion' => $region, 'bui_newweight' => $weight, 'sesskey' => sesskey()));
00325     }
00326 
00343     public function region_has_content($region, $output) {
00344 
00345         if (!$this->is_known_region($region)) {
00346             return false;
00347         }
00348         $this->check_is_loaded();
00349         $this->ensure_content_created($region, $output);
00350         // if ($this->page->user_is_editing() && $this->page->user_can_edit_blocks()) {
00351         // Mark Nielsen's patch - part 1
00352         if ($this->page->user_is_editing() && $this->page->user_can_edit_blocks() && $this->movingblock) {
00353             // If editing is on, we need all the block regions visible, for the
00354             // move blocks UI.
00355             return true;
00356         }
00357         return !empty($this->visibleblockcontent[$region]) || !empty($this->extracontent[$region]);
00358     }
00359 
00365     public function get_installed_blocks() {
00366         global $DB;
00367         if (is_null($this->allblocks)) {
00368             $this->allblocks = $DB->get_records('block');
00369         }
00370         return $this->allblocks;
00371     }
00372 
00374 
00382     public function add_region($region) {
00383         $this->check_not_yet_loaded();
00384         $this->regions[$region] = 1;
00385     }
00386 
00393     public function add_regions($regions) {
00394         foreach ($regions as $region) {
00395             $this->add_region($region);
00396         }
00397     }
00398 
00406     public function set_default_region($defaultregion) {
00407         $this->check_not_yet_loaded();
00408         if ($defaultregion) {
00409             $this->check_region_is_known($defaultregion);
00410         }
00411         $this->defaultregion = $defaultregion;
00412     }
00413 
00421     public function add_fake_block($bc, $region) {
00422         $this->page->initialise_theme_and_output();
00423         if (!$this->is_known_region($region)) {
00424             $region = $this->get_default_region();
00425         }
00426         if (array_key_exists($region, $this->visibleblockcontent)) {
00427             throw new coding_exception('block_manager has already prepared the blocks in region ' .
00428                     $region . 'for output. It is too late to add a fake block.');
00429         }
00430         $this->extracontent[$region][] = $bc;
00431     }
00432 
00441     public function add_pretend_block($bc, $region) {
00442         debugging(DEBUG_DEVELOPER, 'add_pretend_block has been renamed to add_fake_block. Please rename the method call in your code.');
00443         $this->add_fake_block($bc, $region);
00444     }
00445 
00453     public function region_completely_docked($region, $output) {
00454         if (!$this->page->theme->enable_dock) {
00455             return false;
00456         }
00457         $this->check_is_loaded();
00458         $this->ensure_content_created($region, $output);
00459         foreach($this->visibleblockcontent[$region] as $instance) {
00460             if (!empty($instance->content) && !get_user_preferences('docked_block_instance_'.$instance->blockinstanceid, 0)) {
00461                 return false;
00462             }
00463         }
00464         return true;
00465     }
00466 
00474     public function region_uses_dock($regions, $output) {
00475         if (!$this->page->theme->enable_dock) {
00476             return false;
00477         }
00478         $this->check_is_loaded();
00479         foreach((array)$regions as $region) {
00480             $this->ensure_content_created($region, $output);
00481             foreach($this->visibleblockcontent[$region] as $instance) {
00482                 if(!empty($instance->content) && get_user_preferences('docked_block_instance_'.$instance->blockinstanceid, 0)) {
00483                     return true;
00484                 }
00485             }
00486         }
00487         return false;
00488     }
00489 
00491 
00500     public function load_blocks($includeinvisible = null) {
00501         global $DB, $CFG;
00502 
00503         if (!is_null($this->birecordsbyregion)) {
00504             // Already done.
00505             return;
00506         }
00507 
00508         if ($CFG->version < 2009050619) {
00509             // Upgrade/install not complete. Don't try too show any blocks.
00510             $this->birecordsbyregion = array();
00511             return;
00512         }
00513 
00514         // Ensure we have been initialised.
00515         if (is_null($this->defaultregion)) {
00516             $this->page->initialise_theme_and_output();
00517             // If there are still no block regions, then there are no blocks on this page.
00518             if (empty($this->regions)) {
00519                 $this->birecordsbyregion = array();
00520                 return;
00521             }
00522         }
00523 
00524         // Check if we need to load normal blocks
00525         if ($this->fakeblocksonly) {
00526             $this->birecordsbyregion = $this->prepare_per_region_arrays();
00527             return;
00528         }
00529 
00530         if (is_null($includeinvisible)) {
00531             $includeinvisible = $this->page->user_is_editing();
00532         }
00533         if ($includeinvisible) {
00534             $visiblecheck = '';
00535         } else {
00536             $visiblecheck = 'AND (bp.visible = 1 OR bp.visible IS NULL)';
00537         }
00538 
00539         $context = $this->page->context;
00540         $contexttest = 'bi.parentcontextid = :contextid2';
00541         $parentcontextparams = array();
00542         $parentcontextids = get_parent_contexts($context);
00543         if ($parentcontextids) {
00544             list($parentcontexttest, $parentcontextparams) =
00545                     $DB->get_in_or_equal($parentcontextids, SQL_PARAMS_NAMED, 'parentcontext');
00546             $contexttest = "($contexttest OR (bi.showinsubcontexts = 1 AND bi.parentcontextid $parentcontexttest))";
00547         }
00548 
00549         $pagetypepatterns = matching_page_type_patterns($this->page->pagetype);
00550         list($pagetypepatterntest, $pagetypepatternparams) =
00551                 $DB->get_in_or_equal($pagetypepatterns, SQL_PARAMS_NAMED, 'pagetypepatterntest');
00552 
00553         list($ccselect, $ccjoin) = context_instance_preload_sql('bi.id', CONTEXT_BLOCK, 'ctx');
00554 
00555         $params = array(
00556             'subpage1' => $this->page->subpage,
00557             'subpage2' => $this->page->subpage,
00558             'contextid1' => $context->id,
00559             'contextid2' => $context->id,
00560             'pagetype' => $this->page->pagetype,
00561         );
00562         if ($this->page->subpage === '') {
00563             $params['subpage1'] = $DB->sql_empty();
00564             $params['subpage2'] = $DB->sql_empty();
00565         }
00566         $sql = "SELECT
00567                     bi.id,
00568                     bp.id AS blockpositionid,
00569                     bi.blockname,
00570                     bi.parentcontextid,
00571                     bi.showinsubcontexts,
00572                     bi.pagetypepattern,
00573                     bi.subpagepattern,
00574                     bi.defaultregion,
00575                     bi.defaultweight,
00576                     COALESCE(bp.visible, 1) AS visible,
00577                     COALESCE(bp.region, bi.defaultregion) AS region,
00578                     COALESCE(bp.weight, bi.defaultweight) AS weight,
00579                     bi.configdata
00580                     $ccselect
00581 
00582                 FROM {block_instances} bi
00583                 JOIN {block} b ON bi.blockname = b.name
00584                 LEFT JOIN {block_positions} bp ON bp.blockinstanceid = bi.id
00585                                                   AND bp.contextid = :contextid1
00586                                                   AND bp.pagetype = :pagetype
00587                                                   AND bp.subpage = :subpage1
00588                 $ccjoin
00589 
00590                 WHERE
00591                 $contexttest
00592                 AND bi.pagetypepattern $pagetypepatterntest
00593                 AND (bi.subpagepattern IS NULL OR bi.subpagepattern = :subpage2)
00594                 $visiblecheck
00595                 AND b.visible = 1
00596 
00597                 ORDER BY
00598                     COALESCE(bp.region, bi.defaultregion),
00599                     COALESCE(bp.weight, bi.defaultweight),
00600                     bi.id";
00601         $blockinstances = $DB->get_recordset_sql($sql, $params + $parentcontextparams + $pagetypepatternparams);
00602 
00603         $this->birecordsbyregion = $this->prepare_per_region_arrays();
00604         $unknown = array();
00605         foreach ($blockinstances as $bi) {
00606             context_instance_preload($bi);
00607             if ($this->is_known_region($bi->region)) {
00608                 $this->birecordsbyregion[$bi->region][] = $bi;
00609             } else {
00610                 $unknown[] = $bi;
00611             }
00612         }
00613 
00614         // Pages don't necessarily have a defaultregion. The  one time this can
00615         // happen is when there are no theme block regions, but the script itself
00616         // has a block region in the main content area.
00617         if (!empty($this->defaultregion)) {
00618             $this->birecordsbyregion[$this->defaultregion] =
00619                     array_merge($this->birecordsbyregion[$this->defaultregion], $unknown);
00620         }
00621     }
00622 
00634     public function add_block($blockname, $region, $weight, $showinsubcontexts, $pagetypepattern = NULL, $subpagepattern = NULL) {
00635         global $DB;
00636         // Allow invisible blocks because this is used when adding default page blocks, which
00637         // might include invisible ones if the user makes some default blocks invisible
00638         $this->check_known_block_type($blockname, true);
00639         $this->check_region_is_known($region);
00640 
00641         if (empty($pagetypepattern)) {
00642             $pagetypepattern = $this->page->pagetype;
00643         }
00644 
00645         $blockinstance = new stdClass;
00646         $blockinstance->blockname = $blockname;
00647         $blockinstance->parentcontextid = $this->page->context->id;
00648         $blockinstance->showinsubcontexts = !empty($showinsubcontexts);
00649         $blockinstance->pagetypepattern = $pagetypepattern;
00650         $blockinstance->subpagepattern = $subpagepattern;
00651         $blockinstance->defaultregion = $region;
00652         $blockinstance->defaultweight = $weight;
00653         $blockinstance->configdata = '';
00654         $blockinstance->id = $DB->insert_record('block_instances', $blockinstance);
00655 
00656         // Ensure the block context is created.
00657         get_context_instance(CONTEXT_BLOCK, $blockinstance->id);
00658 
00659         // If the new instance was created, allow it to do additional setup
00660         if ($block = block_instance($blockname, $blockinstance)) {
00661             $block->instance_create();
00662         }
00663     }
00664 
00665     public function add_block_at_end_of_default_region($blockname) {
00666         $defaulregion = $this->get_default_region();
00667 
00668         $lastcurrentblock = end($this->birecordsbyregion[$defaulregion]);
00669         if ($lastcurrentblock) {
00670             $weight = $lastcurrentblock->weight + 1;
00671         } else {
00672             $weight = 0;
00673         }
00674 
00675         if ($this->page->subpage) {
00676             $subpage = $this->page->subpage;
00677         } else {
00678             $subpage = null;
00679         }
00680 
00681         // Special case. Course view page type include the course format, but we
00682         // want to add the block non-format-specifically.
00683         $pagetypepattern = $this->page->pagetype;
00684         if (strpos($pagetypepattern, 'course-view') === 0) {
00685             $pagetypepattern = 'course-view-*';
00686         }
00687 
00688         // We should end using this for ALL the blocks, making always the 1st option
00689         // the default one to be used. Until then, this is one hack to avoid the
00690         // 'pagetypewarning' message on blocks initial edition (MDL-27829) caused by
00691         // non-existing $pagetypepattern set. This way at least we guarantee one "valid"
00692         // (the FIRST $pagetypepattern will be set)
00693 
00694         // We are applying it to all blocks created in mod pages for now and only if the
00695         // default pagetype is not one of the available options
00696         if (preg_match('/^mod-.*-/', $pagetypepattern)) {
00697             $pagetypelist = generate_page_type_patterns($this->page->pagetype, null, $this->page->context);
00698             // Only go for the first if the pagetype is not a valid option
00699             if (is_array($pagetypelist) && !array_key_exists($pagetypepattern, $pagetypelist)) {
00700                 $pagetypepattern = key($pagetypelist);
00701             }
00702         }
00703         // Surely other pages like course-report will need this too, they just are not important
00704         // enough now. This will be decided in the coming days. (MDL-27829, MDL-28150)
00705 
00706         $this->add_block($blockname, $defaulregion, $weight, false, $pagetypepattern, $subpage);
00707     }
00708 
00716     public function add_blocks($blocks, $pagetypepattern = NULL, $subpagepattern = NULL, $showinsubcontexts=false, $weight=0) {
00717         $this->add_regions(array_keys($blocks));
00718         foreach ($blocks as $region => $regionblocks) {
00719             $weight = 0;
00720             foreach ($regionblocks as $blockname) {
00721                 $this->add_block($blockname, $region, $weight, $showinsubcontexts, $pagetypepattern, $subpagepattern);
00722                 $weight += 1;
00723             }
00724         }
00725     }
00726 
00737     public function reposition_block($blockinstanceid, $newregion, $newweight) {
00738         global $DB;
00739 
00740         $this->check_region_is_known($newregion);
00741         $inst = $this->find_instance($blockinstanceid);
00742 
00743         $bi = $inst->instance;
00744         if ($bi->weight == $bi->defaultweight && $bi->region == $bi->defaultregion &&
00745                 !$bi->showinsubcontexts && strpos($bi->pagetypepattern, '*') === false &&
00746                 (!$this->page->subpage || $bi->subpagepattern)) {
00747 
00748             // Set default position
00749             $newbi = new stdClass;
00750             $newbi->id = $bi->id;
00751             $newbi->defaultregion = $newregion;
00752             $newbi->defaultweight = $newweight;
00753             $DB->update_record('block_instances', $newbi);
00754 
00755             if ($bi->blockpositionid) {
00756                 $bp = new stdClass;
00757                 $bp->id = $bi->blockpositionid;
00758                 $bp->region = $newregion;
00759                 $bp->weight = $newweight;
00760                 $DB->update_record('block_positions', $bp);
00761             }
00762 
00763         } else {
00764             // Just set position on this page.
00765             $bp = new stdClass;
00766             $bp->region = $newregion;
00767             $bp->weight = $newweight;
00768 
00769             if ($bi->blockpositionid) {
00770                 $bp->id = $bi->blockpositionid;
00771                 $DB->update_record('block_positions', $bp);
00772 
00773             } else {
00774                 $bp->blockinstanceid = $bi->id;
00775                 $bp->contextid = $this->page->context->id;
00776                 $bp->pagetype = $this->page->pagetype;
00777                 if ($this->page->subpage) {
00778                     $bp->subpage = $this->page->subpage;
00779                 } else {
00780                     $bp->subpage = '';
00781                 }
00782                 $bp->visible = $bi->visible;
00783                 $DB->insert_record('block_positions', $bp);
00784             }
00785         }
00786     }
00787 
00794     public function find_instance($instanceid) {
00795         foreach ($this->regions as $region => $notused) {
00796             $this->ensure_instances_exist($region);
00797             foreach($this->blockinstances[$region] as $instance) {
00798                 if ($instance->instance->id == $instanceid) {
00799                     return $instance;
00800                 }
00801             }
00802         }
00803         throw new block_not_on_page_exception($instanceid, $this->page);
00804     }
00805 
00807 
00813     protected function check_not_yet_loaded() {
00814         if (!is_null($this->birecordsbyregion)) {
00815             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.');
00816         }
00817     }
00818 
00826     protected function check_is_loaded() {
00827         if (is_null($this->birecordsbyregion)) {
00828             throw new coding_exception('block_manager has not yet loaded the blocks, to it is too soon to request the information you asked for.');
00829         }
00830     }
00831 
00839     protected function check_known_block_type($blockname, $includeinvisible = false) {
00840         if (!$this->is_known_block_type($blockname, $includeinvisible)) {
00841             if ($this->is_known_block_type($blockname, true)) {
00842                 throw new coding_exception('Unknown block type ' . $blockname);
00843             } else {
00844                 throw new coding_exception('Block type ' . $blockname . ' has been disabled by the administrator.');
00845             }
00846         }
00847     }
00848 
00855     protected function check_region_is_known($region) {
00856         if (!$this->is_known_region($region)) {
00857             throw new coding_exception('Trying to reference an unknown block region ' . $region);
00858         }
00859     }
00860 
00867     protected function prepare_per_region_arrays() {
00868         $result = array();
00869         foreach ($this->regions as $region => $notused) {
00870             $result[$region] = array();
00871         }
00872         return $result;
00873     }
00874 
00881     protected function create_block_instances($birecords) {
00882         $results = array();
00883         foreach ($birecords as $record) {
00884             if ($blockobject = block_instance($record->blockname, $record, $this->page)) {
00885                 $results[] = $blockobject;
00886             }
00887         }
00888         return $results;
00889     }
00890 
00897     public function create_all_block_instances() {
00898         foreach ($this->get_regions() as $region) {
00899             $this->ensure_instances_exist($region);
00900         }
00901     }
00902 
00911     protected function create_block_contents($instances, $output, $region) {
00912         $results = array();
00913 
00914         $lastweight = 0;
00915         $lastblock = 0;
00916         if ($this->movingblock) {
00917             $first = reset($instances);
00918             if ($first) {
00919                 $lastweight = $first->instance->weight - 2;
00920             }
00921 
00922             $strmoveblockhere = get_string('moveblockhere', 'block');
00923         }
00924 
00925         foreach ($instances as $instance) {
00926             $content = $instance->get_content_for_output($output);
00927             if (empty($content)) {
00928                 continue;
00929             }
00930 
00931             if ($this->movingblock && $lastweight != $instance->instance->weight &&
00932                     $content->blockinstanceid != $this->movingblock && $lastblock != $this->movingblock) {
00933                 $results[] = new block_move_target($strmoveblockhere, $this->get_move_target_url($region, ($lastweight + $instance->instance->weight)/2));
00934             }
00935 
00936             if ($content->blockinstanceid == $this->movingblock) {
00937                 $content->add_class('beingmoved');
00938                 $content->annotation .= get_string('movingthisblockcancel', 'block',
00939                         html_writer::link($this->page->url, get_string('cancel')));
00940             }
00941 
00942             $results[] = $content;
00943             $lastweight = $instance->instance->weight;
00944             $lastblock = $instance->instance->id;
00945         }
00946 
00947         if ($this->movingblock && $lastblock != $this->movingblock) {
00948             $results[] = new block_move_target($strmoveblockhere, $this->get_move_target_url($region, $lastweight + 1));
00949         }
00950         return $results;
00951     }
00952 
00958     protected function ensure_instances_exist($region) {
00959         $this->check_region_is_known($region);
00960         if (!array_key_exists($region, $this->blockinstances)) {
00961             $this->blockinstances[$region] =
00962                     $this->create_block_instances($this->birecordsbyregion[$region]);
00963         }
00964     }
00965 
00971     protected function ensure_content_created($region, $output) {
00972         $this->ensure_instances_exist($region);
00973         if (!array_key_exists($region, $this->visibleblockcontent)) {
00974             $contents = array();
00975             if (array_key_exists($region, $this->extracontent)) {
00976                 $contents = $this->extracontent[$region];
00977             }
00978             $contents = array_merge($contents, $this->create_block_contents($this->blockinstances[$region], $output, $region));
00979             if ($region == $this->defaultregion) {
00980                 $addblockui = block_add_block_ui($this->page, $output);
00981                 if ($addblockui) {
00982                     $contents[] = $addblockui;
00983                 }
00984             }
00985             $this->visibleblockcontent[$region] = $contents;
00986         }
00987     }
00988 
00990 
00998     public function edit_controls($block) {
00999         global $CFG;
01000 
01001         if (!isset($CFG->undeletableblocktypes) || (!is_array($CFG->undeletableblocktypes) && !is_string($CFG->undeletableblocktypes))) {
01002             $undeletableblocktypes = array('navigation','settings');
01003         } else if (is_string($CFG->undeletableblocktypes)) {
01004             $undeletableblocktypes = explode(',', $CFG->undeletableblocktypes);
01005         } else {
01006             $undeletableblocktypes = $CFG->undeletableblocktypes;
01007         }
01008 
01009         $controls = array();
01010         $actionurl = $this->page->url->out(false, array('sesskey'=> sesskey()));
01011 
01012         if ($this->page->user_can_edit_blocks()) {
01013             // Move icon.
01014             $controls[] = array('url' => $actionurl . '&bui_moveid=' . $block->instance->id,
01015                     'icon' => 't/move', 'caption' => get_string('move'));
01016         }
01017 
01018         if ($this->page->user_can_edit_blocks() || $block->user_can_edit()) {
01019             // Edit config icon - always show - needed for positioning UI.
01020             $controls[] = array('url' => $actionurl . '&bui_editid=' . $block->instance->id,
01021                     'icon' => 't/edit', 'caption' => get_string('configuration'));
01022         }
01023 
01024         if ($this->page->user_can_edit_blocks() && $block->user_can_edit() && $block->user_can_addto($this->page)) {
01025             if (!in_array($block->instance->blockname, $undeletableblocktypes)
01026                     || !in_array($block->instance->pagetypepattern, array('*', 'site-index'))
01027                     || $block->instance->parentcontextid != SITEID) {
01028                 // Delete icon.
01029                 $controls[] = array('url' => $actionurl . '&bui_deleteid=' . $block->instance->id,
01030                         'icon' => 't/delete', 'caption' => get_string('delete'));
01031             }
01032         }
01033 
01034         if ($this->page->user_can_edit_blocks() && $block->instance_can_be_hidden()) {
01035             // Show/hide icon.
01036             if ($block->instance->visible) {
01037                 $controls[] = array('url' => $actionurl . '&bui_hideid=' . $block->instance->id,
01038                         'icon' => 't/hide', 'caption' => get_string('hide'));
01039             } else {
01040                 $controls[] = array('url' => $actionurl . '&bui_showid=' . $block->instance->id,
01041                         'icon' => 't/show', 'caption' => get_string('show'));
01042             }
01043         }
01044 
01045         // Assign roles icon.
01046         if (has_capability('moodle/role:assign', $block->context)) {
01047             //TODO: please note it is sloppy to pass urls through page parameters!!
01048             //      it is shortened because some web servers (e.g. IIS by default) give
01049             //      a 'security' error if you try to pass a full URL as a GET parameter in another URL.
01050             $return = $this->page->url->out(false);
01051             $return = str_replace($CFG->wwwroot . '/', '', $return);
01052 
01053             $controls[] = array('url' => $CFG->wwwroot . '/' . $CFG->admin .
01054                     '/roles/assign.php?contextid=' . $block->context->id . '&returnurl=' . urlencode($return),
01055                     'icon' => 'i/roles', 'caption' => get_string('assignroles', 'role'));
01056         }
01057 
01058         return $controls;
01059     }
01060 
01066     public function process_url_actions() {
01067         if (!$this->page->user_is_editing()) {
01068             return false;
01069         }
01070         return $this->process_url_add() || $this->process_url_delete() ||
01071             $this->process_url_show_hide() || $this->process_url_edit() ||
01072             $this->process_url_move();
01073     }
01074 
01079     public function process_url_add() {
01080         $blocktype = optional_param('bui_addblock', null, PARAM_PLUGIN);
01081         if (!$blocktype) {
01082             return false;
01083         }
01084 
01085         require_sesskey();
01086 
01087         if (!$this->page->user_can_edit_blocks()) {
01088             throw new moodle_exception('nopermissions', '', $this->page->url->out(), get_string('addblock'));
01089         }
01090 
01091         if (!array_key_exists($blocktype, $this->get_addable_blocks())) {
01092             throw new moodle_exception('cannotaddthisblocktype', '', $this->page->url->out(), $blocktype);
01093         }
01094 
01095         $this->add_block_at_end_of_default_region($blocktype);
01096 
01097         // If the page URL was a guess, it will contain the bui_... param, so we must make sure it is not there.
01098         $this->page->ensure_param_not_in_url('bui_addblock');
01099 
01100         return true;
01101     }
01102 
01107     public function process_url_delete() {
01108         $blockid = optional_param('bui_deleteid', null, PARAM_INTEGER);
01109         if (!$blockid) {
01110             return false;
01111         }
01112 
01113         require_sesskey();
01114 
01115         $block = $this->page->blocks->find_instance($blockid);
01116 
01117         if (!$block->user_can_edit() || !$this->page->user_can_edit_blocks() || !$block->user_can_addto($this->page)) {
01118             throw new moodle_exception('nopermissions', '', $this->page->url->out(), get_string('deleteablock'));
01119         }
01120 
01121         blocks_delete_instance($block->instance);
01122 
01123         // If the page URL was a guess, it will contain the bui_... param, so we must make sure it is not there.
01124         $this->page->ensure_param_not_in_url('bui_deleteid');
01125 
01126         return true;
01127     }
01128 
01133     public function process_url_show_hide() {
01134         if ($blockid = optional_param('bui_hideid', null, PARAM_INTEGER)) {
01135             $newvisibility = 0;
01136         } else if ($blockid = optional_param('bui_showid', null, PARAM_INTEGER)) {
01137             $newvisibility = 1;
01138         } else {
01139             return false;
01140         }
01141 
01142         require_sesskey();
01143 
01144         $block = $this->page->blocks->find_instance($blockid);
01145 
01146         if (!$this->page->user_can_edit_blocks()) {
01147             throw new moodle_exception('nopermissions', '', $this->page->url->out(), get_string('hideshowblocks'));
01148         } else if (!$block->instance_can_be_hidden()) {
01149             return false;
01150         }
01151 
01152         blocks_set_visibility($block->instance, $this->page, $newvisibility);
01153 
01154         // If the page URL was a guses, it will contain the bui_... param, so we must make sure it is not there.
01155         $this->page->ensure_param_not_in_url('bui_hideid');
01156         $this->page->ensure_param_not_in_url('bui_showid');
01157 
01158         return true;
01159     }
01160 
01166     public function process_url_edit() {
01167         global $CFG, $DB, $PAGE, $OUTPUT;
01168 
01169         $blockid = optional_param('bui_editid', null, PARAM_INTEGER);
01170         if (!$blockid) {
01171             return false;
01172         }
01173 
01174         require_sesskey();
01175         require_once($CFG->dirroot . '/blocks/edit_form.php');
01176 
01177         $block = $this->find_instance($blockid);
01178 
01179         if (!$block->user_can_edit() && !$this->page->user_can_edit_blocks()) {
01180             throw new moodle_exception('nopermissions', '', $this->page->url->out(), get_string('editblock'));
01181         }
01182 
01183         $editpage = new moodle_page();
01184         $editpage->set_pagelayout('admin');
01185         $editpage->set_course($this->page->course);
01186         //$editpage->set_context($block->context);
01187         $editpage->set_context($this->page->context);
01188         if ($this->page->cm) {
01189             $editpage->set_cm($this->page->cm);
01190         }
01191         $editurlbase = str_replace($CFG->wwwroot . '/', '/', $this->page->url->out_omit_querystring());
01192         $editurlparams = $this->page->url->params();
01193         $editurlparams['bui_editid'] = $blockid;
01194         $editpage->set_url($editurlbase, $editurlparams);
01195         $editpage->set_block_actions_done();
01196         // At this point we are either going to redirect, or display the form, so
01197         // overwrite global $PAGE ready for this. (Formslib refers to it.)
01198         $PAGE = $editpage;
01199         //some functions like MoodleQuickForm::addHelpButton use $OUTPUT so we need to replace that to
01200         $output = $editpage->get_renderer('core');
01201         $OUTPUT = $output;
01202 
01203         $formfile = $CFG->dirroot . '/blocks/' . $block->name() . '/edit_form.php';
01204         if (is_readable($formfile)) {
01205             require_once($formfile);
01206             $classname = 'block_' . $block->name() . '_edit_form';
01207             if (!class_exists($classname)) {
01208                 $classname = 'block_edit_form';
01209             }
01210         } else {
01211             $classname = 'block_edit_form';
01212         }
01213 
01214         $mform = new $classname($editpage->url, $block, $this->page);
01215         $mform->set_data($block->instance);
01216 
01217         if ($mform->is_cancelled()) {
01218             redirect($this->page->url);
01219 
01220         } else if ($data = $mform->get_data()) {
01221             $bi = new stdClass;
01222             $bi->id = $block->instance->id;
01223             $bi->pagetypepattern = $data->bui_pagetypepattern;
01224             if (empty($data->bui_subpagepattern) || $data->bui_subpagepattern == '%@NULL@%') {
01225                 $bi->subpagepattern = null;
01226             } else {
01227                 $bi->subpagepattern = $data->bui_subpagepattern;
01228             }
01229 
01230             $systemcontext = get_context_instance(CONTEXT_SYSTEM);
01231             $frontpagecontext = get_context_instance(CONTEXT_COURSE, SITEID);
01232             $parentcontext = get_context_instance_by_id($data->bui_parentcontextid);
01233 
01234             // Updating stickiness and contexts.  See MDL-21375 for details.
01235             if (has_capability('moodle/site:manageblocks', $parentcontext)) { // Check permissions in destination
01236 
01237                 // Explicitly set the default context
01238                 $bi->parentcontextid = $parentcontext->id;
01239 
01240                 if ($data->bui_editingatfrontpage) {   // The block is being edited on the front page
01241 
01242                     // The interface here is a special case because the pagetype pattern is
01243                     // totally derived from the context menu.  Here are the excpetions.   MDL-30340
01244 
01245                     switch ($data->bui_contexts) {
01246                         case BUI_CONTEXTS_ENTIRE_SITE:
01247                             // The user wants to show the block across the entire site
01248                             $bi->parentcontextid = $systemcontext->id;
01249                             $bi->showinsubcontexts = true;
01250                             $bi->pagetypepattern  = '*';
01251                             break;
01252                         case BUI_CONTEXTS_FRONTPAGE_SUBS:
01253                             // The user wants the block shown on the front page and all subcontexts
01254                             $bi->parentcontextid = $frontpagecontext->id;
01255                             $bi->showinsubcontexts = true;
01256                             $bi->pagetypepattern  = '*';
01257                             break;
01258                         case BUI_CONTEXTS_FRONTPAGE_ONLY:
01259                             // The user want to show the front page on the frontpage only
01260                             $bi->parentcontextid = $frontpagecontext->id;
01261                             $bi->showinsubcontexts = false;
01262                             $bi->pagetypepattern  = 'site-index';
01263                             // This is the only relevant page type anyway but we'll set it explicitly just
01264                             // in case the front page grows site-index-* subpages of its own later
01265                             break;
01266                     }
01267                 }
01268             }
01269 
01270             $bits = explode('-', $bi->pagetypepattern);
01271             // hacks for some contexts
01272             if (($parentcontext->contextlevel == CONTEXT_COURSE) && ($parentcontext->instanceid != SITEID)) {
01273                 // For course context
01274                 // is page type pattern is mod-*, change showinsubcontext to 1
01275                 if ($bits[0] == 'mod' || $bi->pagetypepattern == '*') {
01276                     $bi->showinsubcontexts = 1;
01277                 } else {
01278                     $bi->showinsubcontexts = 0;
01279                 }
01280             } else  if ($parentcontext->contextlevel == CONTEXT_USER) {
01281                 // for user context
01282                 // subpagepattern should be null
01283                 if ($bits[0] == 'user' or $bits[0] == 'my') {
01284                     // we don't need subpagepattern in usercontext
01285                     $bi->subpagepattern = null;
01286                 }
01287             }
01288 
01289             $bi->defaultregion = $data->bui_defaultregion;
01290             $bi->defaultweight = $data->bui_defaultweight;
01291             $DB->update_record('block_instances', $bi);
01292 
01293             if (!empty($block->config)) {
01294                 $config = clone($block->config);
01295             } else {
01296                 $config = new stdClass;
01297             }
01298             foreach ($data as $configfield => $value) {
01299                 if (strpos($configfield, 'config_') !== 0) {
01300                     continue;
01301                 }
01302                 $field = substr($configfield, 7);
01303                 $config->$field = $value;
01304             }
01305             $block->instance_config_save($config);
01306 
01307             $bp = new stdClass;
01308             $bp->visible = $data->bui_visible;
01309             $bp->region = $data->bui_region;
01310             $bp->weight = $data->bui_weight;
01311             $needbprecord = !$data->bui_visible || $data->bui_region != $data->bui_defaultregion ||
01312                     $data->bui_weight != $data->bui_defaultweight;
01313 
01314             if ($block->instance->blockpositionid && !$needbprecord) {
01315                 $DB->delete_records('block_positions', array('id' => $block->instance->blockpositionid));
01316 
01317             } else if ($block->instance->blockpositionid && $needbprecord) {
01318                 $bp->id = $block->instance->blockpositionid;
01319                 $DB->update_record('block_positions', $bp);
01320 
01321             } else if ($needbprecord) {
01322                 $bp->blockinstanceid = $block->instance->id;
01323                 $bp->contextid = $this->page->context->id;
01324                 $bp->pagetype = $this->page->pagetype;
01325                 if ($this->page->subpage) {
01326                     $bp->subpage = $this->page->subpage;
01327                 } else {
01328                     $bp->subpage = '';
01329                 }
01330                 $DB->insert_record('block_positions', $bp);
01331             }
01332 
01333             redirect($this->page->url);
01334 
01335         } else {
01336             $strheading = get_string('blockconfiga', 'moodle', $block->get_title());
01337             $editpage->set_title($strheading);
01338             $editpage->set_heading($strheading);
01339             $bits = explode('-', $this->page->pagetype);
01340             if ($bits[0] == 'tag' && !empty($this->page->subpage)) {
01341                 // better navbar for tag pages
01342                 $editpage->navbar->add(get_string('tags'), new moodle_url('/tag/'));
01343                 $tag = tag_get('id', $this->page->subpage, '*');
01344                 // tag search page doesn't have subpageid
01345                 if ($tag) {
01346                     $editpage->navbar->add($tag->name, new moodle_url('/tag/index.php', array('id'=>$tag->id)));
01347                 }
01348             }
01349             $editpage->navbar->add($block->get_title());
01350             $editpage->navbar->add(get_string('configuration'));
01351             echo $output->header();
01352             echo $output->heading($strheading, 2);
01353             $mform->display();
01354             echo $output->footer();
01355             exit;
01356         }
01357     }
01358 
01364     public function process_url_move() {
01365         global $CFG, $DB, $PAGE;
01366 
01367         $blockid = optional_param('bui_moveid', null, PARAM_INTEGER);
01368         if (!$blockid) {
01369             return false;
01370         }
01371 
01372         require_sesskey();
01373 
01374         $block = $this->find_instance($blockid);
01375 
01376         if (!$this->page->user_can_edit_blocks()) {
01377             throw new moodle_exception('nopermissions', '', $this->page->url->out(), get_string('editblock'));
01378         }
01379 
01380         $newregion = optional_param('bui_newregion', '', PARAM_ALPHANUMEXT);
01381         $newweight = optional_param('bui_newweight', null, PARAM_FLOAT);
01382         if (!$newregion || is_null($newweight)) {
01383             // Don't have a valid target position yet, must be just starting the move.
01384             $this->movingblock = $blockid;
01385             $this->page->ensure_param_not_in_url('bui_moveid');
01386             return false;
01387         }
01388 
01389         if (!$this->is_known_region($newregion)) {
01390             throw new moodle_exception('unknownblockregion', '', $this->page->url, $newregion);
01391         }
01392 
01393         // Move this block. This may involve moving other nearby blocks.
01394         $blocks = $this->birecordsbyregion[$newregion];
01395 
01396         $maxweight = self::MAX_WEIGHT;
01397         $minweight = -self::MAX_WEIGHT;
01398 
01399         // Initialise the used weights and spareweights array with the default values
01400         $spareweights = array();
01401         $usedweights = array();
01402         for ($i = $minweight; $i <= $maxweight; $i++) {
01403             $spareweights[$i] = $i;
01404             $usedweights[$i] = array();
01405         }
01406 
01407         // Check each block and sort out where we have used weights
01408         foreach ($blocks as $bi) {
01409             if ($bi->weight > $maxweight) {
01410                 // If this statement is true then the blocks weight is more than the
01411                 // current maximum. To ensure that we can get the best block position
01412                 // we will initialise elements within the usedweights and spareweights
01413                 // arrays between the blocks weight (which will then be the new max) and
01414                 // the current max
01415                 $parseweight = $bi->weight;
01416                 while (!array_key_exists($parseweight, $usedweights)) {
01417                     $usedweights[$parseweight] = array();
01418                     $spareweights[$parseweight] = $parseweight;
01419                     $parseweight--;
01420                 }
01421                 $maxweight = $bi->weight;
01422             } else if ($bi->weight < $minweight) {
01423                 // As above except this time the blocks weight is LESS than the
01424                 // the current minimum, so we will initialise the array from the
01425                 // blocks weight (new minimum) to the current minimum
01426                 $parseweight = $bi->weight;
01427                 while (!array_key_exists($parseweight, $usedweights)) {
01428                     $usedweights[$parseweight] = array();
01429                     $spareweights[$parseweight] = $parseweight;
01430                     $parseweight++;
01431                 }
01432                 $minweight = $bi->weight;
01433             }
01434             if ($bi->id != $block->instance->id) {
01435                 unset($spareweights[$bi->weight]);
01436                 $usedweights[$bi->weight][] = $bi->id;
01437             }
01438         }
01439 
01440         // First we find the nearest gap in the list of weights.
01441         $bestdistance = max(abs($newweight - self::MAX_WEIGHT), abs($newweight + self::MAX_WEIGHT)) + 1;
01442         $bestgap = null;
01443         foreach ($spareweights as $spareweight) {
01444             if (abs($newweight - $spareweight) < $bestdistance) {
01445                 $bestdistance = abs($newweight - $spareweight);
01446                 $bestgap = $spareweight;
01447             }
01448         }
01449 
01450         // If there is no gap, we have to go outside -self::MAX_WEIGHT .. self::MAX_WEIGHT.
01451         if (is_null($bestgap)) {
01452             $bestgap = self::MAX_WEIGHT + 1;
01453             while (!empty($usedweights[$bestgap])) {
01454                 $bestgap++;
01455             }
01456         }
01457 
01458         // Now we know the gap we are aiming for, so move all the blocks along.
01459         if ($bestgap < $newweight) {
01460             $newweight = floor($newweight);
01461             for ($weight = $bestgap + 1; $weight <= $newweight; $weight++) {
01462                 foreach ($usedweights[$weight] as $biid) {
01463                     $this->reposition_block($biid, $newregion, $weight - 1);
01464                 }
01465             }
01466             $this->reposition_block($block->instance->id, $newregion, $newweight);
01467         } else {
01468             $newweight = ceil($newweight);
01469             for ($weight = $bestgap - 1; $weight >= $newweight; $weight--) {
01470                 if (array_key_exists($weight, $usedweights)) {
01471                     foreach ($usedweights[$weight] as $biid) {
01472                         $this->reposition_block($biid, $newregion, $weight + 1);
01473                     }
01474                 }
01475             }
01476             $this->reposition_block($block->instance->id, $newregion, $newweight);
01477         }
01478 
01479         $this->page->ensure_param_not_in_url('bui_moveid');
01480         $this->page->ensure_param_not_in_url('bui_newregion');
01481         $this->page->ensure_param_not_in_url('bui_newweight');
01482         return true;
01483     }
01484 
01490     public function show_only_fake_blocks($setting = true) {
01491         $this->fakeblocksonly = $setting;
01492     }
01493 }
01494 
01496 
01505 function block_method_result($blockname, $method, $param = NULL) {
01506     if(!block_load_class($blockname)) {
01507         return NULL;
01508     }
01509     return call_user_func(array('block_'.$blockname, $method), $param);
01510 }
01511 
01520 function block_instance($blockname, $instance = NULL, $page = NULL) {
01521     if(!block_load_class($blockname)) {
01522         return false;
01523     }
01524     $classname = 'block_'.$blockname;
01525     $retval = new $classname;
01526     if($instance !== NULL) {
01527         if (is_null($page)) {
01528             global $PAGE;
01529             $page = $PAGE;
01530         }
01531         $retval->_load_instance($instance, $page);
01532     }
01533     return $retval;
01534 }
01535 
01542 function block_load_class($blockname) {
01543     global $CFG;
01544 
01545     if(empty($blockname)) {
01546         return false;
01547     }
01548 
01549     $classname = 'block_'.$blockname;
01550 
01551     if(class_exists($classname)) {
01552         return true;
01553     }
01554 
01555     $blockpath = $CFG->dirroot.'/blocks/'.$blockname.'/block_'.$blockname.'.php';
01556 
01557     if (file_exists($blockpath)) {
01558         require_once($CFG->dirroot.'/blocks/moodleblock.class.php');
01559         include_once($blockpath);
01560     }else{
01561         //debugging("$blockname code does not exist in $blockpath", DEBUG_DEVELOPER);
01562         return false;
01563     }
01564 
01565     return class_exists($classname);
01566 }
01567 
01575 function matching_page_type_patterns($pagetype) {
01576     $patterns = array($pagetype);
01577     $bits = explode('-', $pagetype);
01578     if (count($bits) == 3 && $bits[0] == 'mod') {
01579         if ($bits[2] == 'view') {
01580             $patterns[] = 'mod-*-view';
01581         } else if ($bits[2] == 'index') {
01582             $patterns[] = 'mod-*-index';
01583         }
01584     }
01585     while (count($bits) > 0) {
01586         $patterns[] = implode('-', $bits) . '-*';
01587         array_pop($bits);
01588     }
01589     $patterns[] = '*';
01590     return $patterns;
01591 }
01592 
01602 function generate_page_type_patterns($pagetype, $parentcontext = null, $currentcontext = null) {
01603     global $CFG;
01604 
01605     $bits = explode('-', $pagetype);
01606 
01607     $core = get_core_subsystems();
01608     $plugins = get_plugin_types();
01609 
01610     //progressively strip pieces off the page type looking for a match
01611     $componentarray = null;
01612     for ($i = count($bits); $i > 0; $i--) {
01613         $possiblecomponentarray = array_slice($bits, 0, $i);
01614         $possiblecomponent = implode('', $possiblecomponentarray);
01615 
01616         // Check to see if the component is a core component
01617         if (array_key_exists($possiblecomponent, $core) && !empty($core[$possiblecomponent])) {
01618             $libfile = $CFG->dirroot.'/'.$core[$possiblecomponent].'/lib.php';
01619             if (file_exists($libfile)) {
01620                 require_once($libfile);
01621                 $function = $possiblecomponent.'_page_type_list';
01622                 if (function_exists($function)) {
01623                     if ($patterns = $function($pagetype, $parentcontext, $currentcontext)) {
01624                         break;
01625                     }
01626                 }
01627             }
01628         }
01629 
01630         //check the plugin directory and look for a callback
01631         if (array_key_exists($possiblecomponent, $plugins) && !empty($plugins[$possiblecomponent])) {
01632 
01633             //We've found a plugin type. Look for a plugin name by getting the next section of page type
01634             if (count($bits) > $i) {
01635                 $pluginname = $bits[$i];
01636                 $directory = get_plugin_directory($possiblecomponent, $pluginname);
01637                 if (!empty($directory)){
01638                     $libfile = $directory.'/lib.php';
01639                     if (file_exists($libfile)) {
01640                         require_once($libfile);
01641                         $function = $possiblecomponent.'_'.$pluginname.'_page_type_list';
01642                         if (!function_exists($function)) {
01643                             $function = $pluginname.'_page_type_list';
01644                         }
01645                         if (function_exists($function)) {
01646                             if ($patterns = $function($pagetype, $parentcontext, $currentcontext)) {
01647                                 break;
01648                             }
01649                         }
01650                     }
01651                 }
01652             }
01653 
01654             //we'll only get to here if we still don't have any patterns
01655             //the plugin type may have a callback
01656             $directory = get_plugin_directory($possiblecomponent, null);
01657             if (!empty($directory)){
01658                 $libfile = $directory.'/lib.php';
01659                 if (file_exists($libfile)) {
01660                     require_once($libfile);
01661                     $function = $possiblecomponent.'_page_type_list';
01662                     if (function_exists($function)) {
01663                         if ($patterns = $function($pagetype, $parentcontext, $currentcontext)) {
01664                             break;
01665                         }
01666                     }
01667                 }
01668             }
01669         }
01670     }
01671 
01672     if (empty($patterns)) {
01673         $patterns = default_page_type_list($pagetype, $parentcontext, $currentcontext);
01674     }
01675 
01676     // Ensure that the * pattern is always available if editing block 'at distance', so
01677     // we always can 'bring back' it to the original context. MDL-30340
01678     if ((!isset($currentcontext) or !isset($parentcontext) or $currentcontext->id != $parentcontext->id) && !isset($patterns['*'])) {
01679         // TODO: We could change the string here, showing its 'bring back' meaning
01680         $patterns['*'] = get_string('page-x', 'pagetype');
01681     }
01682 
01683     return $patterns;
01684 }
01685 
01694 function default_page_type_list($pagetype, $parentcontext = null, $currentcontext = null) {
01695     // Generate page type patterns based on current page type if
01696     // callbacks haven't been defined
01697     $patterns = array($pagetype => $pagetype);
01698     $bits = explode('-', $pagetype);
01699     while (count($bits) > 0) {
01700         $pattern = implode('-', $bits) . '-*';
01701         $pagetypestringname = 'page-'.str_replace('*', 'x', $pattern);
01702         // guessing page type description
01703         if (get_string_manager()->string_exists($pagetypestringname, 'pagetype')) {
01704             $patterns[$pattern] = get_string($pagetypestringname, 'pagetype');
01705         } else {
01706             $patterns[$pattern] = $pattern;
01707         }
01708         array_pop($bits);
01709     }
01710     $patterns['*'] = get_string('page-x', 'pagetype');
01711     return $patterns;
01712 }
01713 
01722 function my_page_type_list($pagetype, $parentcontext = null, $currentcontext = null) {
01723     return array('my-index' => get_string('page-my-index', 'pagetype'));
01724 }
01725 
01735 function mod_page_type_list($pagetype, $parentcontext = null, $currentcontext = null) {
01736     $patterns = plugin_page_type_list($pagetype, $parentcontext, $currentcontext);
01737     if (empty($patterns)) {
01738         // if modules don't have callbacks
01739         // generate two default page type patterns for modules only
01740         $bits = explode('-', $pagetype);
01741         $patterns = array($pagetype => $pagetype);
01742         if ($bits[2] == 'view') {
01743             $patterns['mod-*-view'] = get_string('page-mod-x-view', 'pagetype');
01744         } else if ($bits[2] == 'index') {
01745             $patterns['mod-*-index'] = get_string('page-mod-x-index', 'pagetype');
01746         }
01747     }
01748     return $patterns;
01749 }
01751 
01759 function block_add_block_ui($page, $output) {
01760     global $CFG, $OUTPUT;
01761     if (!$page->user_is_editing() || !$page->user_can_edit_blocks()) {
01762         return null;
01763     }
01764 
01765     $bc = new block_contents();
01766     $bc->title = get_string('addblock');
01767     $bc->add_class('block_adminblock');
01768 
01769     $missingblocks = $page->blocks->get_addable_blocks();
01770     if (empty($missingblocks)) {
01771         $bc->content = get_string('noblockstoaddhere');
01772         return $bc;
01773     }
01774 
01775     $menu = array();
01776     foreach ($missingblocks as $block) {
01777         $blockobject = block_instance($block->name);
01778         if ($blockobject !== false && $blockobject->user_can_addto($page)) {
01779             $menu[$block->name] = $blockobject->get_title();
01780         }
01781     }
01782     collatorlib::asort($menu);
01783 
01784     $actionurl = new moodle_url($page->url, array('sesskey'=>sesskey()));
01785     $select = new single_select($actionurl, 'bui_addblock', $menu, null, array(''=>get_string('adddots')), 'add_block');
01786     $bc->content = $OUTPUT->render($select);
01787     return $bc;
01788 }
01789 
01790 // Functions that have been deprecated by block_manager =======================
01791 
01802 function blocks_get_missing(&$page, &$blockmanager) {
01803     debugging('blocks_get_missing is deprecated. Please use $page->blocks->get_addable_blocks() instead.', DEBUG_DEVELOPER);
01804     $blocks = $page->blocks->get_addable_blocks();
01805     $ids = array();
01806     foreach ($blocks as $block) {
01807         $ids[] = $block->id;
01808     }
01809     return $ids;
01810 }
01811 
01819 function blocks_remove_inappropriate($course) {
01820     // TODO
01821     return;
01822     /*
01823     $blockmanager = blocks_get_by_page($page);
01824 
01825     if (empty($blockmanager)) {
01826         return;
01827     }
01828 
01829     if (($pageformat = $page->pagetype) == NULL) {
01830         return;
01831     }
01832 
01833     foreach($blockmanager as $region) {
01834         foreach($region as $instance) {
01835             $block = blocks_get_record($instance->blockid);
01836             if(!blocks_name_allowed_in_format($block->name, $pageformat)) {
01837                blocks_delete_instance($instance->instance);
01838             }
01839         }
01840     }*/
01841 }
01842 
01850 function blocks_name_allowed_in_format($name, $pageformat) {
01851     $accept = NULL;
01852     $maxdepth = -1;
01853     $formats = block_method_result($name, 'applicable_formats');
01854     if (!$formats) {
01855         $formats = array();
01856     }
01857     foreach ($formats as $format => $allowed) {
01858         $formatregex = '/^'.str_replace('*', '[^-]*', $format).'.*$/';
01859         $depth = substr_count($format, '-');
01860         if (preg_match($formatregex, $pageformat) && $depth > $maxdepth) {
01861             $maxdepth = $depth;
01862             $accept = $allowed;
01863         }
01864     }
01865     if ($accept === NULL) {
01866         $accept = !empty($formats['all']);
01867     }
01868     return $accept;
01869 }
01870 
01878 function blocks_delete_instance($instance, $nolongerused = false, $skipblockstables = false) {
01879     global $DB;
01880 
01881     if ($block = block_instance($instance->blockname, $instance)) {
01882         $block->instance_delete();
01883     }
01884     delete_context(CONTEXT_BLOCK, $instance->id);
01885 
01886     if (!$skipblockstables) {
01887         $DB->delete_records('block_positions', array('blockinstanceid' => $instance->id));
01888         $DB->delete_records('block_instances', array('id' => $instance->id));
01889         $DB->delete_records_list('user_preferences', 'name', array('block'.$instance->id.'hidden','docked_block_instance_'.$instance->id));
01890     }
01891 }
01892 
01898 function blocks_delete_all_for_context($contextid) {
01899     global $DB;
01900     $instances = $DB->get_recordset('block_instances', array('parentcontextid' => $contextid));
01901     foreach ($instances as $instance) {
01902         blocks_delete_instance($instance, true);
01903     }
01904     $instances->close();
01905     $DB->delete_records('block_instances', array('parentcontextid' => $contextid));
01906     $DB->delete_records('block_positions', array('contextid' => $contextid));
01907 }
01908 
01917 function blocks_set_visibility($instance, $page, $newvisibility) {
01918     global $DB;
01919     if (!empty($instance->blockpositionid)) {
01920         // Already have local information on this page.
01921         $DB->set_field('block_positions', 'visible', $newvisibility, array('id' => $instance->blockpositionid));
01922         return;
01923     }
01924 
01925     // Create a new block_positions record.
01926     $bp = new stdClass;
01927     $bp->blockinstanceid = $instance->id;
01928     $bp->contextid = $page->context->id;
01929     $bp->pagetype = $page->pagetype;
01930     if ($page->subpage) {
01931         $bp->subpage = $page->subpage;
01932     }
01933     $bp->visible = $newvisibility;
01934     $bp->region = $instance->defaultregion;
01935     $bp->weight = $instance->defaultweight;
01936     $DB->insert_record('block_positions', $bp);
01937 }
01938 
01947 function blocks_delete_all_on_page($pagetype, $pageid) {
01948     global $DB;
01949 
01950     debugging('Call to deprecated function blocks_delete_all_on_page. ' .
01951             'This function cannot work any more. Doing nothing. ' .
01952             'Please update your code to use a block_manager method $PAGE->blocks->....', DEBUG_DEVELOPER);
01953     return false;
01954 }
01955 
01965 function blocks_repopulate_page($page) {
01966     global $CFG;
01967 
01968     debugging('Call to deprecated function blocks_repopulate_page. ' .
01969             'Use a more specific method like blocks_add_default_course_blocks, ' .
01970             'or just call $PAGE->blocks->add_blocks()', DEBUG_DEVELOPER);
01971 
01973     if (!empty($CFG->defaultblocks_override)) {
01974         $blocknames = $CFG->defaultblocks_override;
01975     } else {
01976         $blocknames = $page->blocks_get_default();
01977     }
01978 
01979     $blocks = blocks_parse_default_blocks_list($blocknames);
01980     $page->blocks->add_blocks($blocks);
01981 
01982     return true;
01983 }
01984 
01992 function blocks_get_record($blockid = NULL, $notusedanymore = false) {
01993     global $PAGE;
01994     $blocks = $PAGE->blocks->get_installed_blocks();
01995     if ($blockid === NULL) {
01996         return $blocks;
01997     } else if (isset($blocks[$blockid])) {
01998         return $blocks[$blockid];
01999     } else {
02000         return false;
02001     }
02002 }
02003 
02011 function blocks_find_block($blockid, $blocksarray) {
02012     if (empty($blocksarray)) {
02013         return false;
02014     }
02015     foreach($blocksarray as $blockgroup) {
02016         if (empty($blockgroup)) {
02017             continue;
02018         }
02019         foreach($blockgroup as $instance) {
02020             if($instance->blockid == $blockid) {
02021                 return $instance;
02022             }
02023         }
02024     }
02025     return false;
02026 }
02027 
02028 // Functions for programatically adding default blocks to pages ================
02029 
02036 function blocks_parse_default_blocks_list($blocksstr) {
02037     $blocks = array();
02038     $bits = explode(':', $blocksstr);
02039     if (!empty($bits)) {
02040         $leftbits = trim(array_shift($bits));
02041         if ($leftbits != '') {
02042             $blocks[BLOCK_POS_LEFT] = explode(',', $leftbits);
02043         }
02044     }
02045     if (!empty($bits)) {
02046         $rightbits =trim(array_shift($bits));
02047         if ($rightbits != '') {
02048             $blocks[BLOCK_POS_RIGHT] = explode(',', $rightbits);
02049         }
02050     }
02051     return $blocks;
02052 }
02053 
02057 function blocks_get_default_site_course_blocks() {
02058     global $CFG;
02059 
02060     if (!empty($CFG->defaultblocks_site)) {
02061         return blocks_parse_default_blocks_list($CFG->defaultblocks_site);
02062     } else {
02063         return array(
02064             BLOCK_POS_LEFT => array('site_main_menu'),
02065             BLOCK_POS_RIGHT => array('course_summary', 'calendar_month')
02066         );
02067     }
02068 }
02069 
02075 function blocks_add_default_course_blocks($course) {
02076     global $CFG;
02077 
02078     if (!empty($CFG->defaultblocks_override)) {
02079         $blocknames = blocks_parse_default_blocks_list($CFG->defaultblocks_override);
02080 
02081     } else if ($course->id == SITEID) {
02082         $blocknames = blocks_get_default_site_course_blocks();
02083 
02084     } else {
02085         $defaultblocks = 'defaultblocks_' . $course->format;
02086         if (!empty($CFG->$defaultblocks)) {
02087             $blocknames = blocks_parse_default_blocks_list($CFG->$defaultblocks);
02088 
02089         } else {
02090             $formatconfig = $CFG->dirroot.'/course/format/'.$course->format.'/config.php';
02091             $format = array(); // initialize array in external file
02092             if (is_readable($formatconfig)) {
02093                 include($formatconfig);
02094             }
02095             if (!empty($format['defaultblocks'])) {
02096                 $blocknames = blocks_parse_default_blocks_list($format['defaultblocks']);
02097 
02098             } else if (!empty($CFG->defaultblocks)){
02099                 $blocknames = blocks_parse_default_blocks_list($CFG->defaultblocks);
02100 
02101             } else {
02102                 $blocknames = array(
02103                     BLOCK_POS_LEFT => array(),
02104                     BLOCK_POS_RIGHT => array('search_forums', 'news_items', 'calendar_upcoming', 'recent_activity')
02105                 );
02106             }
02107         }
02108     }
02109 
02110     if ($course->id == SITEID) {
02111         $pagetypepattern = 'site-index';
02112     } else {
02113         $pagetypepattern = 'course-view-*';
02114     }
02115     $page = new moodle_page();
02116     $page->set_course($course);
02117     $page->blocks->add_blocks($blocknames, $pagetypepattern);
02118 }
02119 
02123 function blocks_add_default_system_blocks() {
02124     global $DB;
02125 
02126     $page = new moodle_page();
02127     $page->set_context(get_context_instance(CONTEXT_SYSTEM));
02128     $page->blocks->add_blocks(array(BLOCK_POS_LEFT => array('navigation', 'settings')), '*', null, true);
02129     $page->blocks->add_blocks(array(BLOCK_POS_LEFT => array('admin_bookmarks')), 'admin-*', null, null, 2);
02130 
02131     if ($defaultmypage = $DB->get_record('my_pages', array('userid'=>null, 'name'=>'__default', 'private'=>1))) {
02132         $subpagepattern = $defaultmypage->id;
02133     } else {
02134         $subpagepattern = null;
02135     }
02136 
02137     $page->blocks->add_blocks(array(BLOCK_POS_RIGHT => array('private_files', 'online_users'), 'content' => array('course_overview')), 'my-index', $subpagepattern, false);
02138 }
 All Data Structures Namespaces Files Functions Variables Enumerations