Commit | Line | Data |
---|---|---|
7d2a0492 | 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 | * This file contains classes used to manage the navigation structures in Moodle | |
20 | * and was introduced as part of the changes occuring in Moodle 2.0 | |
21 | * | |
22 | * @since 2.0 | |
23 | * @package blocks | |
24 | * @copyright 2009 Sam Hemelryk | |
25 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
26 | */ | |
27 | ||
28 | /** | |
29 | * The global navigation tree block class | |
30 | * | |
31 | * Used to produce the global navigation block new to Moodle 2.0 | |
32 | * | |
33 | * @package blocks | |
34 | * @copyright 2009 Sam Hemelryk | |
35 | * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later | |
36 | */ | |
3406acde | 37 | class block_navigation extends block_base { |
7d2a0492 | 38 | |
39 | /** @var int */ | |
40 | public static $navcount; | |
41 | /** @var string */ | |
42 | public $blockname = null; | |
d7319652 | 43 | /** @var bool */ |
7d2a0492 | 44 | protected $contentgenerated = false; |
d7319652 | 45 | /** @var bool|null */ |
46 | protected $docked = null; | |
7d2a0492 | 47 | |
48 | /** | |
49 | * Set the initial properties for the block | |
50 | */ | |
51 | function init() { | |
52 | global $CFG; | |
53 | $this->blockname = get_class($this); | |
621f2f28 | 54 | $this->title = get_string('pluginname', $this->blockname); |
7d2a0492 | 55 | $this->version = 2009082800; |
56 | } | |
57 | ||
58 | /** | |
59 | * All multiple instances of this block | |
60 | * @return bool Returns true | |
61 | */ | |
62 | function instance_allow_multiple() { | |
63 | return false; | |
64 | } | |
65 | ||
66 | /** | |
67 | * Set the applicable formats for this block to all | |
68 | * @return array | |
69 | */ | |
70 | function applicable_formats() { | |
71 | return array('all' => true); | |
72 | } | |
73 | ||
74 | /** | |
75 | * Allow the user to configure a block instance | |
76 | * @return bool Returns true | |
77 | */ | |
78 | function instance_allow_config() { | |
79 | return true; | |
80 | } | |
81 | ||
3406acde SH |
82 | function instance_can_be_docked() { |
83 | return (parent::instance_can_be_docked() && (empty($this->config->enabledock) || $this->config->enabledock=='yes')); | |
84 | } | |
85 | ||
9d897331 | 86 | function get_required_javascript() { |
1ce15fda | 87 | global $CFG; |
7c964cdf | 88 | $this->page->requires->js_module(array('name'=>'core_dock', 'fullpath'=>'/blocks/dock.js', 'requires'=>array('base', 'cookie', 'dom', 'io', 'node', 'event-custom', 'event-mouseenter', 'yui2-container'))); |
3406acde | 89 | $this->page->requires->js_module(array('name'=>'block_navigation', 'fullpath'=>'/blocks/navigation/navigation.js', 'requires'=>array('core_dock', 'io', 'node', 'dom', 'event-custom', 'json-parse'))); |
9d897331 SH |
90 | user_preference_allow_ajax_update('docked_block_instance_'.$this->instance->id, PARAM_INT); |
91 | } | |
92 | ||
7d2a0492 | 93 | /** |
94 | * Gets the content for this block by grabbing it from $this->page | |
95 | */ | |
96 | function get_content() { | |
97 | global $CFG, $OUTPUT; | |
98 | // First check if we have already generated, don't waste cycles | |
99 | if ($this->contentgenerated === true) { | |
4f0c2d00 | 100 | return $this->content; |
7d2a0492 | 101 | } |
f44b10ed | 102 | $this->page->requires->yui2_lib('dom'); |
2574fae6 | 103 | // JS for navigation moved to the standard theme, the code will probably have to depend on the actual page structure |
9dec75db | 104 | // $this->page->requires->js('/lib/javascript-navigation.js'); |
7d2a0492 | 105 | // Navcount is used to allow us to have multiple trees although I dont' know why |
106 | // you would want to trees the same | |
c1c0cecf | 107 | |
3406acde | 108 | block_navigation::$navcount++; |
c1c0cecf | 109 | |
d7319652 | 110 | // Check if this block has been docked |
111 | if ($this->docked === null) { | |
3406acde | 112 | $this->docked = get_user_preferences('nav_in_tab_panel_globalnav'.block_navigation::$navcount, 0); |
d7319652 | 113 | } |
114 | ||
115 | // Check if there is a param to change the docked state | |
116 | if ($this->docked && optional_param('undock', null, PARAM_INT)==$this->instance->id) { | |
3406acde | 117 | unset_user_preference('nav_in_tab_panel_globalnav'.block_navigation::$navcount); |
d7319652 | 118 | $url = $this->page->url; |
119 | $url->remove_params(array('undock')); | |
120 | redirect($url); | |
121 | } else if (!$this->docked && optional_param('dock', null, PARAM_INT)==$this->instance->id) { | |
3406acde | 122 | set_user_preferences(array('nav_in_tab_panel_globalnav'.block_navigation::$navcount=>1)); |
d7319652 | 123 | $url = $this->page->url; |
124 | $url->remove_params(array('dock')); | |
125 | redirect($url); | |
126 | } | |
127 | ||
7d2a0492 | 128 | // Initialise (only actually happens if it hasn't already been done yet |
129 | $this->page->navigation->initialise(); | |
130 | ||
7d2a0492 | 131 | if (!empty($this->config->showmyhistory) && $this->config->showmyhistory=='yes') { |
132 | $this->showmyhistory(); | |
133 | } | |
134 | ||
7d2a0492 | 135 | // Get the expandable items so we can pass them to JS |
136 | $expandable = array(); | |
137 | $this->page->navigation->find_expandable($expandable); | |
d2c394f3 | 138 | |
7d2a0492 | 139 | // Initialise the JS tree object |
3406acde | 140 | $module = array('name'=>'block_navigation', 'fullpath'=>'/blocks/navigation/navigation.js', 'requires'=>array('core_dock', 'io', 'node', 'dom', 'event-custom', 'json-parse')); |
781bd8ae PS |
141 | $arguments = array($this->instance->id, array('expansions'=>$expandable, 'instance'=>$this->instance->id, 'candock'=>$this->instance_can_be_docked())); |
142 | $this->page->requires->js_init_call('M.block_navigation.init_add_tree', $arguments, false, $module); | |
4f0c2d00 | 143 | |
7d2a0492 | 144 | // Grab the items to display |
3406acde SH |
145 | $renderer = $this->page->get_renderer('block_navigation'); |
146 | $this->content->text = $renderer->navigation_tree($this->page->navigation); | |
4ca6cfbf | 147 | |
3ea5951e | 148 | $reloadlink = new moodle_url($this->page->url, array('regenerate'=>'navigation')); |
17390771 | 149 | |
3406acde | 150 | $this->content->footer .= $OUTPUT->action_icon($reloadlink, new pix_icon('t/reload', get_string('reload')), null, array('class'=>'customcommand reloadnavigation')); |
4ca6cfbf | 151 | |
7d2a0492 | 152 | // Set content generated to true so that we know it has been done |
153 | $this->contentgenerated = true; | |
4f0c2d00 PS |
154 | |
155 | return $this->content; | |
7d2a0492 | 156 | } |
157 | ||
158 | /** | |
159 | * Returns the attributes to set for this block | |
160 | * | |
161 | * This function returns an array of HTML attributes for this block including | |
162 | * the defaults | |
163 | * {@link block_tree->html_attributes()} is used to get the default arguments | |
164 | * and then we check whether the user has enabled hover expansion and add the | |
165 | * appropriate hover class if it has | |
166 | * | |
167 | * @return array An array of HTML attributes | |
168 | */ | |
169 | public function html_attributes() { | |
170 | $attributes = parent::html_attributes(); | |
171 | if (!empty($this->config->enablehoverexpansion) && $this->config->enablehoverexpansion == 'yes') { | |
9d897331 | 172 | $attributes['class'] .= ' block_js_expansion'; |
7d2a0492 | 173 | } |
7d2a0492 | 174 | return $attributes; |
175 | } | |
176 | ||
177 | /** | |
178 | * This function maintains a history of the active pages that a user has visited | |
179 | * and displays it back to the user as part of the navigation structure | |
180 | * | |
181 | * @return bool | |
182 | */ | |
183 | protected function showmyhistory() { | |
a6855934 | 184 | global $USER, $PAGE; |
7d2a0492 | 185 | |
186 | // Create a navigation cache so that we can store the history | |
187 | $cache = new navigation_cache('navigationhistory', 60*60); | |
188 | ||
189 | // If the user isn't logged in or is a guest we don't want to display anything | |
4cdb8d70 | 190 | if (!isloggedin() || isguestuser()) { |
7d2a0492 | 191 | return false; |
192 | } | |
193 | ||
194 | // Check the cache to see if we have loaded my courses already | |
195 | // there is a very good chance that we have | |
196 | if (!$cache->cached('history')) { | |
197 | $cache->history = array(); | |
198 | } | |
199 | $history = $cache->history; | |
200 | $historycount = count($history); | |
201 | ||
202 | // Find the initial active node | |
203 | $child = false; | |
204 | if ($PAGE->navigation->contains_active_node()) { | |
205 | $child = $PAGE->navigation->find_active_node(); | |
206 | } else if ($PAGE->settingsnav->contains_active_node()) { | |
207 | $child = $PAGE->settingsnav->find_active_node(); | |
208 | } | |
209 | // Check that we found an active child node | |
210 | if ($child!==false) { | |
211 | $properties = array(); | |
212 | // Check whether this child contains another active child node | |
213 | // this can happen if we are looking at a module | |
214 | if ($child->contains_active_node()) { | |
215 | $titlebits = array(); | |
216 | // Loop while the child contains active nodes and in each iteration | |
217 | // find the next node in the correct direction | |
218 | while ($child!==null && $child->contains_active_node()) { | |
219 | if (!empty($child->shorttext)) { | |
220 | $titlebits[] = $child->shorttext; | |
221 | } else { | |
222 | $titlebits[] = $child->text; | |
223 | } | |
224 | foreach ($child->children as $child) { | |
225 | if ($child->contains_active_node() || $child->isactive) { | |
226 | // We have found the active child or one of its parents | |
227 | // so break the foreach so we can proceed in the while | |
228 | break; | |
229 | } | |
230 | } | |
231 | } | |
232 | if (!empty($child->shorttext)) { | |
233 | $titlebits[] = $child->shorttext; | |
234 | } else { | |
235 | $titlebits[] = $child->text; | |
236 | } | |
237 | $properties['text'] = join(' - ', $titlebits); | |
238 | $properties['shorttext'] = join(' - ', $titlebits); | |
239 | } else { | |
240 | $properties['text'] = $child->text; | |
241 | $properties['shorttext'] = $child->shorttext; | |
242 | } | |
243 | $properties['action'] = $child->action; | |
244 | $properties['key'] = $child->key; | |
245 | $properties['type'] = $child->type; | |
246 | $properties['icon'] = $child->icon; | |
247 | ||
248 | // Create a new navigation node object free of the main structure | |
249 | // so that it is easily storeable and customised | |
250 | $child = new navigation_node($properties); | |
251 | ||
252 | // Check that this page isn't already in the history array. If it is | |
253 | // we will remove it so that it gets added at the top and we dont get | |
254 | // duplicate entries | |
255 | foreach ($history as $key=>$node) { | |
256 | if ($node->key == $child->key && $node->type == $child->type) { | |
257 | if ($node->action instanceof moodle_url && $child->action instanceof moodle_url && $node->action->compare($child->action)) { | |
258 | unset($history[$key]); | |
eb788065 | 259 | } else if ($child->action instanceof moodle_url && $child->action->out_omit_querystring() == $node->action) { |
7d2a0492 | 260 | unset($history[$key]); |
261 | } else if ($child->action == $node->action) { | |
262 | unset($history[$key]); | |
263 | } | |
264 | } | |
265 | } | |
266 | // If there is more than 5 elements in the array remove the first one | |
267 | // We want a fifo array | |
268 | if (count($history) > 5) { | |
269 | array_shift($history); | |
270 | } | |
271 | $child->nodetype = navigation_node::NODETYPE_LEAF; | |
272 | $child->children = array(); | |
273 | // Add the child to the history array | |
274 | array_push($history,$child); | |
275 | } | |
276 | ||
277 | // If we have `more than nothing` in the history display it :D | |
278 | if ($historycount > 0) { | |
279 | // Add a branch to hold the users history | |
3406acde | 280 | $mymoodle = $PAGE->navigation->get('profile', navigation_node::TYPE_USER); |
7a7e209d | 281 | $myhistorybranch = $mymoodle->add(get_string('showmyhistorytitle', $this->blockname), null, navigation_node::TYPE_CUSTOM, null, 'myhistory'); |
3406acde SH |
282 | foreach (array_reverse($history) as $node) { |
283 | $myhistorybranch->children->add($node); | |
284 | } | |
7d2a0492 | 285 | } |
286 | ||
287 | // Cache the history (or update the cached history as it is) | |
288 | $cache->history = $history; | |
289 | ||
290 | return true; | |
291 | } | |
c1c0cecf | 292 | } |