web.php 93.7 KB
Newer Older
1
2
<?php
/**
Francois Marier's avatar
Francois Marier committed
3
 * Mahara: Electronic portfolio, weblog, resume builder and social networking
4
5
 * Copyright (C) 2006-2009 Catalyst IT Ltd and others; see:
 *                         http://wiki.mahara.org/Contributors
6
 *
Francois Marier's avatar
Francois Marier committed
7
8
9
10
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
11
 *
Francois Marier's avatar
Francois Marier committed
12
13
14
15
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
16
 *
Francois Marier's avatar
Francois Marier committed
17
18
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20
21
 *
 * @package    mahara
 * @subpackage core
22
 * @author     Catalyst IT Ltd
23
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL
24
 * @copyright  (C) 2006-2009 Catalyst IT Ltd http://catalyst.net.nz
25
26
27
28
29
30
 * @copyright  (C) portions from Moodle, (C) Martin Dougiamas http://dougiamas.com
 */

defined('INTERNAL') || die();


31
32
33
function smarty_core() {
    require_once 'dwoo/dwoo/dwooAutoload.php';
    require_once 'dwoo/mahara/Dwoo_Mahara.php';
34

35
    return new Dwoo_Mahara();
36
37
38
}


39
40
41
42
43
44
/**
 * This function creates a Smarty object and sets it up for use within our
 * podclass app, setting up some variables.
 *
 * The variables that it sets up are:
 *
45
 * - WWWROOT: The base url for the Mahara system
46
47
48
49
50
 * - USER: The user object
 * - JAVASCRIPT: A list of javascript files to include in the header.  This
 *   list is passed into this function (see below).
 * - HEADERS: An array of any further headers to set.  Each header is just
 *   straight HTML (see below).
51
52
 * - PUBLIC: Set true if this page is a public page
 * - MAINNAV: Array defining the main navigation
53
 *
54
 * @param $javascript A list of javascript includes.  Each include should be just
55
 *                    the name of a file, and reside in js/{filename}
56
57
58
 * @param $headers    A list of additional headers.  These are to be specified as
 *                    actual HTML.
 * @param $strings    A list of language strings required by the javascript code.
59
60
 * @return Smarty
 */
61

62
function smarty($javascript = array(), $headers = array(), $pagestrings = array(), $extraconfig = array()) {
63
    global $USER, $SESSION, $THEME;
64
65
66
67
68
69
70
71
72
73
74

    if (!is_array($headers)) {
        $headers = array();
    }
    if (!is_array($pagestrings)) {
        $pagestrings = array();
    }
    if (!is_array($extraconfig)) {
        $extraconfig = array();
    }

Martyn Smith's avatar
Martyn Smith committed
75
    $SIDEBLOCKS = array();
76

77
78
    $smarty = smarty_core();

79
    $wwwroot = get_config('wwwroot');
80
    // NOTE: not using jswwwroot - it seems to wreck image paths if you 
81
    // drag them around the wysiwyg editor
82
    $jswwwroot = json_encode($wwwroot);
Martyn Smith's avatar
Martyn Smith committed
83
84

    $theme_list = array();
85
86
87
88
    
    if (function_exists('pieform_get_headdata')) {
        $headers = array_merge($headers, pieform_get_headdata());
    }
89

90
    // Insert the appropriate javascript tags 
91
    $javascript_array = array();
92
    $jsroot = $wwwroot . 'js/';
93

94
95
    $langdirection = get_string('thisdirection', 'langconfig');

Richard Mansfield's avatar
Richard Mansfield committed
96
    // TinyMCE must be included first for some reason we're not sure about
97
    $checkarray = array(&$javascript, &$headers);
98
    $found_tinymce = false;
99
    foreach ($checkarray as &$check) {
100
101
102
103
        if (($key = array_search('tinymce', $check)) !== false || ($key = array_search('tinytinymce', $check)) !== false) {
            if (!$found_tinymce) {
                $found_tinymce = $check[$key];
                $javascript_array[] = $jsroot . 'tinymce/tiny_mce.js';
104
                $content_css = json_encode($THEME->get_url('style/tinymce.css'));
105
106
                $language = substr(current_language(), 0, 2);
                $execcommand = '';
107
108
                if (isset($extraconfig['tinymcesetup'])) {
                    $execcommand = 'setup: ' . $extraconfig['tinymcesetup'] . ',';
109
                }
110

111
112
113
114
115
116
117
118
                $adv_buttons = array(
                    "bold,italic,underline,separator,justifyleft,justifycenter,justifyright,justifyfull,separator,bullist,numlist,separator,link,unlink,separator,code,fullscreen",
                    "bold,italic,underline,strikethrough,separator,forecolor,backcolor,separator,justifyleft,justifycenter,justifyright,justifyfull,separator,hr,emotions,image,iespell,cleanup,separator,link,unlink,separator,code",
                    "bullist,numlist,separator,tablecontrols,separator,cut,copy,paste,pasteword",
                    "fontselect,separator,fontsizeselect,separator,formatselect",
                );

                // For right-to-left langs, reverse button order & align controls right.
119
120
                $tinymce_langdir = $langdirection == 'rtl' ? 'rtl' : 'ltr';
                $toolbar_align = 'left';
121
122
123

                if ($check[$key] == 'tinymce') {
                    $tinymce_config = <<<EOF
124
    mode: "none",
125
    theme: "advanced",
126
    plugins: "table,emotions,iespell,inlinepopups,paste",
127
128
129
    theme_advanced_buttons1 : "{$adv_buttons[1]}",
    theme_advanced_buttons2 : "{$adv_buttons[2]}",
    theme_advanced_buttons3 : "{$adv_buttons[3]}",
130
    theme_advanced_toolbar_location : "top",
131
    theme_advanced_toolbar_align : "{$toolbar_align}",
132
    //width: '512',
133
EOF;
134
135
136
                }
                else {
                    $tinymce_config = <<<EOF
137
    mode: "textareas",
138
139
    editor_selector: 'tinywysiwyg',
    theme: "advanced",
140
    plugins: "fullscreen,inlinepopups",
141
    theme_advanced_buttons1 : "{$adv_buttons[0]}",
142
    theme_advanced_buttons2 : "",
143
144
    theme_advanced_buttons3 : "",
    theme_advanced_toolbar_location : "top",
145
    theme_advanced_toolbar_align : "{$toolbar_align}",
146
147
148
149
    fullscreen_new_window: true,
    fullscreen_settings: {
        theme: "advanced",
        plugins: "table,emotions,iespell,inlinepopups,paste",
150
151
152
        theme_advanced_buttons1 : "{$adv_buttons[1]}",
        theme_advanced_buttons2 : "{$adv_buttons[2]}",
        theme_advanced_buttons3 : "{$adv_buttons[3]}"
153
    },
154
EOF;
155
                }
156

157
                $headers[] = <<<EOF
158
159
160
161
<script type="text/javascript">
tinyMCE.init({
    button_tile_map: true,
    {$tinymce_config}
162
    {$execcommand}
163
    extended_valid_elements : "object[width|height|classid|codebase],param[name|value],embed[src|type|width|height|flashvars|wmode],script[src,type,language],+ul[id|type|compact]",
164
    urlconverter_callback : "custom_urlconvert",
165
    language: '{$language}',
166
    directionality: "{$tinymce_langdir}",
167
    content_css : {$content_css},
168
    //document_base_url: {$jswwwroot},
169
    remove_script_host: false,
170
    relative_urls: false
171
});
172
function custom_urlconvert (u, n, e) {
173
  // Don't convert the url on the skype status buttons.
174
175
  if (u.indexOf('skype:') == 0) {
      return u;
176
  }
177
178
179
180
181
182
183
184
185
186
187
188
189
190
  var t = tinyMCE.activeEditor, s = t.settings;

  // Don't convert link href since thats the CSS files that gets loaded into the editor also skip local file URLs
  if (!s.convert_urls || (e && e.nodeName == 'LINK') || u.indexOf('file:') === 0)
      return u;

  // Convert to relative
  if (s.relative_urls)
      return t.documentBaseURI.toRelative(u);

  // Convert to absolute
  u = t.documentBaseURI.toAbsolute(u, s.remove_script_host);

  return u;
191
}
192
193
194
</script>

EOF;
195
196
197
198
199
200
201
                unset($check[$key]);
            }
            else {
                if ($check[$key] != $found_tinymce) {
                    log_warn('Two differently configured tinyMCE instances have been asked for on this page! This is not possible');
                }
                unset($check[$key]);
202
            }
203
        }
204
205
    }

206
    if (get_config('developermode') & DEVMODE_UNPACKEDJS) {
207
        $javascript_array[] = $jsroot . 'MochiKit/MochiKit.js';
208
209
210
211
        $javascript_array[] = $jsroot . 'MochiKit/Position.js';
        $javascript_array[] = $jsroot . 'MochiKit/Color.js';
        $javascript_array[] = $jsroot . 'MochiKit/Visual.js';
        $javascript_array[] = $jsroot . 'MochiKit/DragAndDrop.js';
212
        $javascript_array[] = $jsroot . 'MochiKit/Format.js';
213
214
215
216
    }
    else {
        $javascript_array[] = $jsroot . 'MochiKit/Packed.js';
    }
Martyn Smith's avatar
Martyn Smith committed
217
    $javascript_array[] = $jsroot . 'keyboardNavigation.js';
218

219
    $strings = array();
220
221
222
223
224
225
226
227
228
    foreach ($pagestrings as $k => $v) {
        if (is_array($v)) {
            foreach ($v as $tag) {
                $strings[$tag] = get_raw_string($tag, $k);
            }
        }
        else {
            $strings[$k] = get_raw_string($k, $v);
        }
229
230
    }

231
    $jsstrings = jsstrings();
Martyn Smith's avatar
Martyn Smith committed
232
    $themepaths = themepaths();
233

Richard Mansfield's avatar
Richard Mansfield committed
234
    foreach ($javascript as $jsfile) {
235
236
237
238
        // For now, if there's no path in the js file, assume it's in
        // $jsroot and append '.js' to the name.  Later we may want to
        // ensure all smarty() calls include the full path to the js
        // file, with the proper extension.
239
        if (strpos($jsfile, '/') === false) {
240
            $javascript_array[] = $jsroot . $jsfile . '.js';
241
            if (isset($jsstrings[$jsfile])) {
242
243
244
                foreach ($jsstrings[$jsfile] as $section => $tags) {
                    foreach ($tags as $tag) {
                        $strings[$tag] = get_raw_string($tag, $section);
245
246
247
                    }
                }
            }
Martyn Smith's avatar
Martyn Smith committed
248
249
            if (isset($themepaths[$jsfile])) {
                foreach ($themepaths[$jsfile] as $themepath) {
Nigel McNie's avatar
Nigel McNie committed
250
                    $theme_list[$themepath] = $THEME->get_url($themepath);
Martyn Smith's avatar
Martyn Smith committed
251
252
                }
            }
253
254
        }
        else {
255
            // A .js file with a fully specified path
256
            $javascript_array[] = $wwwroot . $jsfile;
257
258
259
260
261
262
            // If $jsfile is from a plugin (i.e. plugintype/pluginname/js/foo.js)
            // Then get js strings from static function jsstrings in plugintype/pluginname/lib.php 
            $bits = explode('/', $jsfile);
            if (count($bits) == 4) {
                safe_require($bits[0], $bits[1]);
                $pluginclass = generate_class_name($bits[0], $bits[1]);
263
                $name = substr($bits[3], 0, strpos($bits[3], '.js'));
264
265
                if (is_callable(array($pluginclass, 'jsstrings'))) {
                    $tempstrings = call_static_method($pluginclass, 'jsstrings', $name);
266
267
268
                    foreach ($tempstrings as $section => $tags) {
                        foreach ($tags as $tag) {
                            $strings[$tag] = get_raw_string($tag, $section);
269
270
                        }
                    }
Richard Mansfield's avatar
Richard Mansfield committed
271
                }
272
273
274
275
276
277
278
279
280
                if (is_callable(array($pluginclass, 'jshelp'))) {
                    $tempstrings = call_static_method($pluginclass, 'jshelp', $name);
                    foreach ($tempstrings as $section => $tags) {
                        foreach ($tags as $tag) {
                            $strings[$tag . '.help'] = get_help_icon($bits[0], $bits[1], null, null,
                                                                     null, $tag);
                        }
                    }
                }
Martyn Smith's avatar
Martyn Smith committed
281
282
283
                if (is_callable(array($pluginclass, 'themepaths'))) {
                    $tmpthemepaths = call_static_method($pluginclass, 'themepaths', $name);
                    foreach ($tmpthemepaths as $themepath) {
Nigel McNie's avatar
Nigel McNie committed
284
                        $theme_list[$themepath] = $THEME->get_url($themepath);
Martyn Smith's avatar
Martyn Smith committed
285
286
                    }
                }
Martyn Smith's avatar
Martyn Smith committed
287
            }
Martyn Smith's avatar
Martyn Smith committed
288
        }
289
    }
290
291

    $javascript_array[] = $jsroot . 'mahara.js';
292
    if (get_config('developermode') & DEVMODE_DEBUGJS) {
293
        $javascript_array[] = $jsroot . 'debug.js';
294
295
296
297
    }
    if ((get_config('developermode') & DEVMODE_FIREBUGLITE)
        && isset($_SERVER['HTTP_USER_AGENT']) && false === stripos($_SERVER['HTTP_USER_AGENT'], 'gecko')) {
        $javascript_array[] = $jsroot . 'firebug/firebug.js';
298
    }
299

300
301
302
    foreach ($jsstrings['mahara'] as $section => $tags) {
        foreach ($tags as $tag) {
            $strings[$tag] = get_raw_string($tag, $section);
303
304
        }
    }
305
306
    if (isset($extraconfig['themepaths']) && is_array($extraconfig['themepaths'])) {
        foreach ($extraconfig['themepaths'] as $themepath) {
Nigel McNie's avatar
Nigel McNie committed
307
            $theme_list[$themepath] = $THEME->get_url($themepath);
308
309
        }
    }
310

311
    $stringjs = '<script type="text/javascript">';
312
    $stringjs .= 'var strings = ' . json_encode($strings) . ';';
313
314
    $stringjs .= '</script>';

315
    // stylesheet set up - if we're in a plugin also get its stylesheet
Nigel McNie's avatar
Nigel McNie committed
316
    $stylesheets = array_reverse(array_values($THEME->get_url('style/style.css', true)));
317
    if (defined('SECTION_PLUGINTYPE') && defined('SECTION_PLUGINNAME') && SECTION_PLUGINTYPE != 'core') {
Nigel McNie's avatar
Nigel McNie committed
318
        if ($pluginsheets = $THEME->get_url('style/style.css', true, SECTION_PLUGINTYPE . '/' . SECTION_PLUGINNAME)) {
319
320
321
            $stylesheets = array_merge($stylesheets, array_reverse($pluginsheets));
        }
    }
322
    if (defined('ADMIN') || defined('INSTITUTIONALADMIN')) {
323
324
325
        if ($adminsheets = $THEME->get_url('style/admin.css', true)) {
            $stylesheets = array_merge($stylesheets, array_reverse($adminsheets));
        }
326
    }
327
    if (get_config('developermode') & DEVMODE_DEBUGCSS) {
328
329
        $stylesheets[] = get_config('wwwroot') . 'theme/debug.css';
    }
330

331
332
333
    // look for extra stylesheets
    if (isset($extraconfig['stylesheets']) && is_array($extraconfig['stylesheets'])) {
        foreach ($extraconfig['stylesheets'] as $extrasheet) {
334
            if ($sheets = $THEME->get_url($extrasheet, true)) {
Nigel McNie's avatar
Nigel McNie committed
335
                $stylesheets = array_merge($stylesheets, array_reverse(array_values($sheets)));
336
337
338
339
            }
        }
    }

340
    // Include rtl.css for right-to-left langs
341
    if ($langdirection == 'rtl') {
342
        $smarty->assign('LANGDIRECTION', 'rtl');
343
344
345
346
347
        if ($rtlsheets = $THEME->get_url('style/rtl.css', true)) {
            $stylesheets = array_merge($stylesheets, array_reverse($rtlsheets));
        }
    }

348
    $smarty->assign('STRINGJS', $stringjs);
349

350
    $smarty->assign('STYLESHEETLIST', $stylesheets);
351
352
353
354
    if (!empty($theme_list)) {
        // this gets assigned in smarty_core, but do it again here if it's changed locally
        $smarty->assign('THEMELIST', json_encode(array_merge((array)json_decode($smarty->get_template_vars('THEMELIST')),  $theme_list))); 
    }
355

356

357
358
359
360
    $sitename = get_config('sitename');
    if (!$sitename) {
       $sitename = 'Mahara';
    }
361
    $smarty->assign('sitename', $sitename);
362

Martyn Smith's avatar
Martyn Smith committed
363
    if (defined('TITLE')) {
364
        $smarty->assign('PAGETITLE', TITLE . ' - ' . $sitename);
365
        $smarty->assign('heading', TITLE);
Martyn Smith's avatar
Martyn Smith committed
366
367
    }
    else {
368
        $smarty->assign('PAGETITLE', $sitename);
Martyn Smith's avatar
Martyn Smith committed
369
370
    }

371
372
373
    if (defined('PUBLIC')) {
        $smarty->assign('PUBLIC', true);
    }
374
375
376
    if (defined('ADMIN')) {
        $smarty->assign('ADMIN', true);
    }
377
378
379
    if (defined('INSTITUTIONALADMIN')) {
        $smarty->assign('INSTITUTIONALADMIN', true);
    }
380

381
382
    $smarty->assign('LOGGEDIN', $USER->is_logged_in());
    if ($USER->is_logged_in()) {
383
        $smarty->assign('MAINNAV', main_nav());
384
        $smarty->assign('RIGHTNAV', right_nav());
385
    }
386
387
    else {
        $smarty->assign('sitedefaultlang', get_string('sitedefault', 'admin') . ' (' . 
388
                        get_string_from_language(get_config('lang'), 'thislanguage') . ')');
389
390
        $smarty->assign('LANGUAGES', get_languages());
    }
391

392
    $smarty->assign_by_ref('USER', $USER);
393
    $smarty->assign('SESSKEY', $USER->get('sesskey'));
394
    $smarty->assign_by_ref('JAVASCRIPT', $javascript_array);
395
    $smarty->assign_by_ref('HEADERS', $headers);
396
397
398
399
400
401
    $siteclosedforupgrade = get_config('siteclosed');
    if ($siteclosedforupgrade && get_config('disablelogin')) {
        $smarty->assign('SITECLOSED', get_string('siteclosedlogindisabled', 'mahara', get_config('wwwroot') . 'admin/upgrade.php'));
    }
    else if ($siteclosedforupgrade || get_config('siteclosedbyadmin')) {
        $smarty->assign('SITECLOSED', get_string('siteclosed'));
402
    }
403

404
405
    if ((!isset($extraconfig['pagehelp']) || $extraconfig['pagehelp'] !== false)
        and $help = has_page_help()) {
406
407
408
        $smarty->assign('PAGEHELPNAME', $help[0]);
        $smarty->assign('PAGEHELPICON', $help[1]);
    }
409
    if (defined('GROUP')) {
410
        require_once('group.php');
411
412
        $group = group_current_group();
        $smarty->assign('GROUP', $group);
413
        $smarty->assign('GROUPNAV', group_get_menu_tabs());
414
        $smarty->assign('PAGEHEADING', hsc($group->name));
415
    }
416

Martyn Smith's avatar
Martyn Smith committed
417
    // ---------- sideblock stuff ----------
418
419
    $sidebars = !isset($extraconfig['sidebars']) || $extraconfig['sidebars'] !== false;
    if ($sidebars && !defined('INSTALLER') && (!defined('MENUITEM') || substr(MENUITEM, 0, 5) != 'admin')) {
Richard Mansfield's avatar
Richard Mansfield committed
420
        if (get_config('installed') && !defined('ADMIN') && !defined('INSTITUTIONALADMIN')) {
421
422
423
424
            $data = site_menu();
            if (!empty($data)) {
                $smarty->assign('SITEMENU', site_menu());
                $SIDEBLOCKS[] = array(
425
                    'name'   => 'linksandresources',
426
427
428
429
430
431
432
                    'weight' => 10,
                    'data'   => $data,
                );
            }
        }

        if ($USER->is_logged_in() && defined('MENUITEM') && substr(MENUITEM, 0, 11) == 'myportfolio') {
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
            if (get_config('showselfsearchsideblock')) {
                $SIDEBLOCKS[] = array(
                    'name'   => 'selfsearch',
                    'weight' => 0,
                    'data'   => array(),
                );
            }
            if (get_config('showtagssideblock')) {
                $SIDEBLOCKS[] = array(
                    'name'   => 'tags',
                    'id'     => 'sb-tags',
                    'weight' => 0,
                    'data'   => tags_sideblock(),
                );
            }
Clare Lenihan's avatar
Clare Lenihan committed
448
        }
Clare Lenihan's avatar
Clare Lenihan committed
449

Richard Mansfield's avatar
Richard Mansfield committed
450
        if($USER->is_logged_in() && !defined('ADMIN') && !defined('INSTITUTIONALADMIN')) {
451
452
            $SIDEBLOCKS[] = array(
                'name'   => 'profile',
453
                'id'     => 'sb-profile',
454
455
456
                'weight' => -20,
                'data'   => profile_sideblock()
            );
457
458
459
            if (get_config('showonlineuserssideblock')) {
                $SIDEBLOCKS[] = array(
                    'name'   => 'onlineusers',
460
                    'id'     => 'sb-onlineusers',
461
462
463
464
                    'weight' => -10,
                    'data'   => onlineusers_sideblock(),
                );
            }
465
        }
Martyn Smith's avatar
Martyn Smith committed
466

Richard Mansfield's avatar
Richard Mansfield committed
467
468
469
        if(defined('GROUP')) {
            $SIDEBLOCKS[] = array(
                'name'   => 'group',
470
                'id'     => 'sb-groupnav',
Richard Mansfield's avatar
Richard Mansfield committed
471
472
473
474
475
                'weight' => -10,
                'data'   => group_sideblock()
            );
        }

476
        if (!$USER->is_logged_in() && !(get_config('siteclosed') && get_config('disablelogin'))) {
477
            $SIDEBLOCKS[] = array(
478
479
                'name'   => 'login',
                'weight' => -10,
480
                'id'     => 'sb-loginbox',
481
482
483
                'data'   => array(
                    'loginform' => auth_generate_login_form(),
                ),
484
485
            );
        }
486

487
488
489
490
491
492
493
494
495
        if (get_config('enablenetworking')) {
            require_once(get_config('docroot') .'api/xmlrpc/lib.php');
            if ($USER->is_logged_in() && $ssopeers = get_service_providers($USER->authinstance)) {
                $SIDEBLOCKS[] = array(
                    'name'   => 'ssopeers',
                    'weight' => 1,
                    'data'   => $ssopeers,
                );
            }
Martyn Smith's avatar
Martyn Smith committed
496
497
        }

498
499
500
501
502
        if (isset($extraconfig['sideblocks']) && is_array($extraconfig['sideblocks'])) {
            foreach ($extraconfig['sideblocks'] as $sideblock) {
                $SIDEBLOCKS[] = $sideblock;
            }
        }
Martyn Smith's avatar
Martyn Smith committed
503

504
505
        usort($SIDEBLOCKS, create_function('$a,$b', 'if ($a["weight"] == $b["weight"]) return 0; return ($a["weight"] < $b["weight"]) ? -1 : 1;'));

506
507
508
        // Place all sideblocks on the right. If this structure is munged 
        // appropriately, you can put blocks on the left. In future versions of 
        // Mahara, we'll make it easy to do this.
509
        $SIDEBLOCKS = array('left' => array(), 'right' => $SIDEBLOCKS);
510

511
        $smarty->assign('userauthinstance', $SESSION->get('authinstance'));
512
        $smarty->assign('MNETUSER', $SESSION->get('mnetuser'));
513
        $smarty->assign('SIDEBLOCKS', $SIDEBLOCKS);
514
        $smarty->assign('SIDEBARS', $sidebars);
515

516
517
518
519
520
521
522
523
524
    }

    if ($USER->get('parentuser')) {
        $smarty->assign('USERMASQUERADING', true);
        $smarty->assign('masqueradedetails', get_string('youaremasqueradingas', 'mahara', hsc(display_name($USER))));
        $smarty->assign('becomeyouagain',
            ' <a href="' . hsc($wwwroot) . 'admin/users/changeuser.php?restore=1">'
            . get_string('becomeadminagain', 'admin', $USER->get('parentuser')->name)
            . '</a>');
525
    }
Martyn Smith's avatar
Martyn Smith committed
526

527
528
529
    return $smarty;
}

530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553

/**
 * Manages theme configuration.
 *
 * Does its best to give the user _a_ theme, even if it's not the theme they 
 * want to use (e.g. the theme they want has been uninstalled)
 */
class Theme {

    /**
     * The base name of the theme (the name of the directory in which it lives)
     */
    public $basename = '';

    /**
     * A human-readable version of the theme name
     */
    public $displayname = '';

    /**
     * Which pieform renderer to use by default for all forms
     */
    public $formrenderer = '';

554
555
556
557
558
559
560
561
562
563
    /**
     * Directories where to look for templates by default
     */
    public $templatedirs = array();

    /**
     * Theme inheritance path from this theme to 'raw'
     */
    public $inheritance = array();

564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
    /**
     * What unit the left/center/right column widths are in. 'pixels' or 'percent'
     */
    public $columnwidthunits    = '';

    /**
     * Width of the left column. Integer - see $columnwidthunits
     */
    public $leftcolumnwidth     = 256;

    /**
     * Background colour for the left column
     */
    public $leftcolumnbgcolor   = '#fff';

    /**
     * Background colour for the center column
     */
    public $centercolumnbgcolor = '#fff';

    /**
     * Width of the right column. Integer - see $columnwidthunits
     */
    public $rightcolumnwidth    = 256;

    /**
     * Background colour for the right column
     */
    public $rightcolumnbgcolor  = '#fff';


    /**
     * Initialises a theme object based on the theme 'hint' passed.
     *
     * If arg is a string, it's taken to be a theme name. If it's a user 
     * object, we ask it for a theme name. If it's an integer, we pretend 
     * that's a user ID and ask for the theme for that user.
     *
     * If the theme they want doesn't exist, the object is initialised for the 
     * default theme. This means you can initialise one of these for a user
     * and then use it without worrying if the theme exists.
     *
     * @param mixed $arg Theme name, user object or user ID
     */
    public function __construct($arg) {
        if (is_string($arg)) {
            $themename = $arg;
        }
        else if ($arg instanceof User) {
            $themename = $arg->get('theme');
        }
        else if (is_int($arg)) {
            $user = new User();
            $user->find_by_id($arg);
            $themename = $user->get('theme');
        }
        else {
            throw new SystemException("Argument to Theme::__construct was not a theme name, user object or user ID");
        }

        if (!$themename) {
            // Theme to show to when no theme has been suggested
626
627
628
            if (!$themename = get_config('theme')) {
                $themename = 'raw';
            }
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
        }
        $this->init_theme($themename);
    }

    /**
     * Given a theme name, reads in all config and sets fields on this object
     */
    private function init_theme($themename) {
        if (!preg_match('/^[a-zA-Z0-9_-]+$/', $themename)) {
            throw new SystemException("Theme name is in invalid form: '$themename'");
        }

        $this->basename = $themename;

        $themeconfigfile = get_config('docroot') . 'theme/' . $this->basename . '/themeconfig.php';
        if (!is_readable($themeconfigfile)) {
            // We can safely assume that the default theme is installed, users 
            // should never be able to remove it
            $this->basename = 'default';
            $themeconfigfile = get_config('docroot') . 'theme/default/themeconfig.php';
        }

        require($themeconfigfile);

        foreach (get_object_vars($theme) as $key => $value) {
            $this->$key = $value;
        }

        if (!isset($this->displayname)) {
658
            $this->displayname = $this->basename;
659
660
661
662
663
        }
        if (!isset($theme->parent) || !$theme->parent) {
            $theme->parent = 'raw';
        }

664
665
666
        $this->templatedirs[] = get_config('docroot') . 'theme/' . $this->basename . '/templates/';
        $this->inheritance[]  = $this->basename;

667
668
669
670
671
672
673
674
        // Now go through the theme hierarchy assigning variables from the 
        // parent themes
        $currenttheme = $this->basename;
        while ($currenttheme != 'raw') {
            $currenttheme = isset($theme->parent) ? $theme->parent : 'raw';
            $parentconfigfile = get_config('docroot') . 'theme/' . $currenttheme . '/themeconfig.php';
            require($parentconfigfile);
            foreach (get_object_vars($theme) as $key => $value) {
675
                if (!isset($this->$key) || !$this->$key) {
676
677
678
                    $this->$key = $value;
                }
            }
679
680
            $this->templatedirs[] = get_config('docroot') . 'theme/' . $currenttheme . '/templates/';
            $this->inheritance[]  = $currenttheme;
681
682
683
        }
    }

684
685
686
    /**
     * stuff
     */
687
688
    public function get_url($filename, $all=false, $plugindirectory='') {
        return $this->_get_path($filename, $all, $plugindirectory, get_config('wwwroot'));
689
690
    }

691
692
    public function get_path($filename, $all=false, $plugindirectory='') {
        return $this->_get_path($filename, $all, $plugindirectory, get_config('docroot'));
693
694
    }

695
    private function _get_path($filename, $all, $plugindirectory, $returnprefix) {
696
        $list = array();
697
        $plugindirectory = ($plugindirectory && substr($plugindirectory, -1) != DIRECTORY_SEPARATOR) ? $plugindirectory . DIRECTORY_SEPARATOR : $plugindirectory;
698
699

        foreach ($this->inheritance as $themedir) {
700
            if (is_readable(get_config('docroot') . $plugindirectory . 'theme/' . $themedir . '/static/' . $filename)) {
701
                if ($all) {
702
                    $list[$themedir] = $returnprefix . $plugindirectory . 'theme/' . $themedir . '/static/' . $filename;
703
704
                }
                else {
705
                    return $returnprefix . $plugindirectory . 'theme/' . $themedir . '/static/' . $filename;
706
707
708
709
710
711
712
713
                }
            }
        }
        if ($all) {
            return $list;
        }

        $extra = '';
714
715
        if ($plugindirectory) {
            $extra = ", plugindir $plugindirectory";
716
717
        }
        log_debug("Missing file in theme {$this->basename}{$extra}: $filename");
718
        return $returnprefix . $plugindirectory . 'theme/' . $themedir . '/static/' . $filename;
719
720
    }

721
722
723
}


724
725
/** 
 * Returns the lists of strings used in the .js files
726
 * @return array                   
727
728
 */

729
function jsstrings() {
Martyn Smith's avatar
Martyn Smith committed
730
    return array(
731
732
733
       'mahara' => array(                        // js file
            'mahara' => array(                   // section
                'namedfieldempty',               // string name
734
                'processing',
735
736
737
                'requiredfieldempty',
                'unknownerror',
                'loading',
Martyn Smith's avatar
Martyn Smith committed
738
                'showtags',
739
740
                'unreadmessages',
                'unreadmessage',
741
742
                'pendingfriend',
                'pendingfriends',
743
                'couldnotgethelp',
744
745
746
747
748
749
                'password',
                'username',
                'login',
                'sessiontimedout',
                'loginfailed',
                'home',
750
                'youhavenottaggedanythingyet',
751
            ),
752
753
        ),
        'tablerenderer' => array(
754
755
756
757
758
759
            'mahara' => array(
                'firstpage',
                'nextpage',
                'prevpage',
                'lastpage',
            )
760
        ),
761
        'friends' => array(
762
            'group' => array(
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
                'confirmremovefriend',
                'seeallviews',
                'noviewstosee',
                'sendmessage',
                'whymakemeyourfriend',
                'approverequest',
                'denyrequest',
                'pending',
                'removefromfriendslist',
                'views',
                'trysearchingforfriends',
                'nobodyawaitsfriendapproval',
                'sendfriendrequest',
                'addtomyfriends',
                'friendshiprequested',
                'userdoesntwantfriends',
                'existingfriend',
                'nosearchresultsfound',
781
                'reason',
782
                'requestfriendship',
783
                'cancel',
784
785
            ),
        ),
786
787
788
        'views' => array(
            'view' => array(
                'confirmdeleteblockinstance',
789
                'blocksinstructionajax',
790
                'Configure',
791
792
            ),
        ),
793
794
795
796
797
798
799
800
801
        'adminusersearch' => array(
            'admin' => array(
                'suspenduser',
                'suspensionreason',
            ),
            'mahara' => array(
                'cancel',
            ),
        ),
Martyn Smith's avatar
Martyn Smith committed
802
803
804
    );
}

Martyn Smith's avatar
Martyn Smith committed
805
function themepaths() {
806
807
808
809
810
811
812
813
814

    static $paths;
    if (empty($paths)) {
        $paths = array(
            'mahara' => array(
                'images/icon_close.gif',
                'images/failure.gif',
                'images/loading.gif',
                'images/success.gif',
815
                'images/icon_problem.gif',
816
                'images/icon_help.gif',
817
                'style/js.css',
818
819
820
821
            ),
        );
    }
    return $paths;
Martyn Smith's avatar
Martyn Smith committed
822
823
}

824
825
826
827
828
829
/** 
 * Takes an array of string identifiers and returns an array of the
 * corresponding strings, quoted for use in inline javascript here
 * docs.
 */

830
831
832
833
function quotestrings($strings) {
    $qstrings = array();
    foreach ($strings as $section => $tags) {
        foreach ($tags as $tag) {
834
            $qstrings[$tag] = json_encode(get_string($tag, $section));
835
        }
836
    }
837
    return $qstrings;
838
839
}

840
841
842
843
844
845
846
/** 
 * This function sets up and caches info about the current selected theme
 * contains inheritance path (used for locating images) and template dirs
 * and potentially more stuff later ( like mime header to send (html vs xhtml))
 * @return object
 */
function theme_setup() {
847
848
849
    global $THEME;
    log_warn("theme_setup() is deprecated - please use the global \$THEME object instead");
    return $THEME;
850
851
852
853
854
855
856
857
}

/** 
 * This function returns the full url to an image
 * Always use it to get image urls
 * @param $imagelocation path to image relative to theme/$theme/static/
 * @param $pluginlocation path to plugin relative to docroot
 */
858
function theme_get_url($location, $pluginlocation='', $all = false) {
859
860
861
862
863
864
    global $THEME;
    log_warn("theme_get_url() is deprecated: Use \$THEME->get_url() instead");
    $plugintype = $pluginname = '';
    if ($pluginlocation) {
        list($plugintype, $pluginname) = explode('/', $pluginlocation);
        $pluginname = substr($pluginname, 0, -1);
865
    }
866
    return $THEME->get_url($location, $all, $plugintype, $pluginname);
867
868
}

869
870
871
872
873
874
/** 
 * This function returns the full path to an image
 * Always use it to get image paths
 * @param $imagelocation path to image relative to theme/$theme/static/
 * @param $pluginlocation path to plugin relative to docroot
 */
875
function theme_get_path($location, $pluginlocation='', $all=false) {
876
877
878
879
880
881
    global $THEME;
    log_warn("theme_get_path() is deprecated: Use \$THEME->get_path() instead");
    $plugintype = $pluginname = '';
    if ($pluginlocation) {
        list($plugintype, $pluginname) = explode('/', $pluginlocation);
        $pluginname = substr($pluginname, 0, -1);
882
    }
883
    return $THEME->get_path($location, $all, $plugintype, $pluginname);
884
885
}

886
887
888
889
890
/**
 * This function sends headers suitable for all JSON returning scripts.
 *
 */
function json_headers() {
891
    // @todo Catalyst IT Ltd
892
893
    // header('Content-type: text/x-json');
    header('Content-type: text/plain');
Martyn Smith's avatar
Martyn Smith committed
894
    header('Pragma: no-cache');
895
896
}

Richard Mansfield's avatar
Richard Mansfield committed
897
/**
898
 * This function sends a JSON message, and ends the script.
Richard Mansfield's avatar
Richard Mansfield committed
899
 *
900
901
902
903
904
905
906
907
 * Scripts receiving replies will recieve a JSON array with two fields:
 *
 *  - error: True or false depending on whether the request was successful
 *  - message: JSON data representing a message sent back from the script
 *
 * @param boolean $error   Whether the script ended in an error or not
 * @param string  $message A message to pass back to the user, can be an
 *                         array of JSON data
Richard Mansfield's avatar
Richard Mansfield committed
908
 */
909
function json_reply($error, $message, $returncode=0) {
Richard Mansfield's avatar
Richard Mansfield committed
910
    json_headers();
911
    echo json_encode(array('error' => $error, 'message' => $message, 'returnCode' => $returncode));
912
    perf_to_log();
Richard Mansfield's avatar
Richard Mansfield committed
913
914
915
    exit;
}

916
function _param_retrieve($name) {
917
918
919
920
921
922
923
    // prefer post
    if (isset($_POST[$name])) {
        $value = $_POST[$name];
    } 
    else if (isset($_GET[$name])) {
        $value = $_GET[$name];
    }
924
    else if (func_num_args() == 2) {
925
926
927
        $php_work_around = func_get_arg(1);
        return array($php_work_around, true);
    }
928
    else {
929
930
931
        throw new ParameterException("Missing parameter '$name' and no default supplied");
    }

932
    return array($value, false);
933
934
}

Martyn Smith's avatar
Martyn Smith committed
935
936
937
938
939
940
941
942
943
944
945
/**
 * This function returns a GET or POST parameter with optional default.  If the
 * default isn't specified and the parameter hasn't been sent, a
 * ParameterException exception is thrown
 *
 * @param string The GET or POST parameter you want returned
 * @param mixed [optional] the default value for this parameter
 *
 * @return string The value of the parameter
 *
 */
Martyn Smith's avatar
Martyn Smith committed
946
function param_variable($name) {
947
948
949
    $args = func_get_args();
    list ($value) = call_user_func_array('_param_retrieve', $args);
    return $value;
Martyn Smith's avatar
Martyn Smith committed
950
951
952
953
954
955
956
957
958
959
960
}

/**
 * This function returns a GET or POST parameter as an integer with optional
 * default.  If the default isn't specified and the parameter hasn't been sent,
 * a ParameterException exception is thrown. Likewise, if the parameter isn't a
 * valid integer, a ParameterException exception is thrown
 *
 * @param string The GET or POST parameter you want returned
 * @param mixed [optional] the default value for this parameter
 *
Nigel McNie's avatar
Nigel McNie committed
961
 * @return int The value of the parameter
Martyn Smith's avatar
Martyn Smith committed
962
963
 *
 */
Martyn Smith's avatar
Martyn Smith committed
964
function param_integer($name) {
965
966
967
968
969
970
    $args = func_get_args();

    list ($value, $defaultused) = call_user_func_array('_param_retrieve', $args);

    if ($defaultused) {
        return $value;
Martyn Smith's avatar
Martyn Smith committed
971
972
973
974
975
    }

    if (preg_match('/^\d+$/',$value)) {
        return (int)$value;
    }
976
977
978
    else if ($value == '' && isset($args[1])) {
        return $args[1];
    }
Martyn Smith's avatar
Martyn Smith committed
979

980
    throw new ParameterException("The '$name' parameter is not an integer");
Martyn Smith's avatar
Martyn Smith committed
981
982
}

Martyn Smith's avatar
Martyn Smith committed
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
/**
 * This function returns a GET or POST parameter as an alpha string with optional
 * default.  If the default isn't specified and the parameter hasn't been sent,
 * a ParameterException exception is thrown. Likewise, if the parameter isn't a
 * valid alpha string, a ParameterException exception is thrown
 *
 * Valid characters are a-z and A-Z
 *
 * @param string The GET or POST parameter you want returned
 * @param mixed [optional] the default value for this parameter
 *
 * @return string The value of the parameter
 *
 */
function param_alpha($name) {
998
999
1000
    $args = func_get_args();

    list ($value, $defaultused) = call_user_func_array('_param_retrieve', $args);
For faster browsing, not all history is shown. View entire blame