menu.php 13 KB
Newer Older
Richard Mansfield's avatar
Richard Mansfield committed
1 2 3 4 5
<?php
/**
 *
 * @package    mahara
 * @subpackage admin
6
 * @author     Catalyst IT Ltd
7 8
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL version 3 or later
 * @copyright  For copyright information on Mahara, please see the README file distributed with this software.
Richard Mansfield's avatar
Richard Mansfield committed
9 10 11
 *
 */

12
define('INTERNAL', 1);
Richard Mansfield's avatar
Richard Mansfield committed
13
define('ADMIN', 1);
14
define('MENUITEM', 'configsite/sitemenu');
Penny Leach's avatar
Penny Leach committed
15 16 17 18
define('SECTION_PLUGINTYPE', 'core');
define('SECTION_PLUGINNAME', 'admin');
define('SECTION_PAGE', 'sitemenu');

19
require(dirname(dirname(dirname(__FILE__))) . '/init.php');
20 21
require_once('pieforms/pieform.php');
define('TITLE', get_string('menus', 'admin'));
Richard Mansfield's avatar
Richard Mansfield committed
22

23
$strings = array('edit','delete','update','cancel','add','name','unknownerror');
24
$adminstrings = array('confirmdeletemenuitem', 'deletefailed','deletingmenuitem','savingmenuitem',
25 26
                      'nositefiles','loggedinmenu','loggedoutmenu','linkedto','externallink','sitefile',
                      'loadingmenuitems','menuitemsloaded','failedloadingsitefiles',
27
                      'failedloadingmenuitems');
28
foreach ($strings as $string) {
29
    $getstring[$string] = json_encode(get_string($string));
30 31
}
foreach ($adminstrings as $string) {
32
    $getstring[$string] = json_encode(get_string($string, 'admin'));
33 34
}

35 36 37
$thead = array(json_encode(get_string('type', 'admin')), json_encode(get_string('name', 'admin')), json_encode(get_string('linkedto', 'admin')), '""');
$ijs = "var thead = TR(null,map(partial(TH,null),[" . implode($thead,",") . "]));\n";
$ijs .= "var externallink = " . json_encode(get_string('externallink', 'admin')) . ";\n";
38
$ijs .= "var sitefile = " . json_encode(get_string('sitefile','admin')) . ";\n";
39 40
$namelabel = json_encode(get_string('name', 'admin'));
$linkedtolabel = json_encode(get_string('linkedto', 'admin'));
Richard Mansfield's avatar
Richard Mansfield committed
41 42
$ijs .= <<< EOJS
// Request a list of menu items from the server
Richard Mansfield's avatar
Richard Mansfield committed
43
function getitems() {
44
    sendjsonrequest('getmenuitems.json.php', {'public':selectedmenu == 'loggedoutmenu'}, 'GET',
45
                    function(data) { displaymenuitems(data.menuitems); });
Richard Mansfield's avatar
Richard Mansfield committed
46
}
47 48
// Get a list of the available admin files
function getadminfiles() {
Aaron Wells's avatar
Aaron Wells committed
49 50
    sendjsonrequest('getadminfiles.json.php', {'public':selectedmenu == 'loggedoutmenu'},
                    'GET',
51 52 53 54 55 56 57 58
                    function (data) {
                        if (!data.error) {
                            adminfiles = data.adminfiles;
                        }
                        else {
                            adminfiles = null;
                        }
                    });
59 60
}

Richard Mansfield's avatar
Richard Mansfield committed
61 62 63
// Puts the list of menu items into the empty table.
function displaymenuitems(itemlist) {
    var rows = map(formatrow,itemlist);
64
    var form = FORM({'id':'form','method':'post','enctype':'multipart/form-data',
Naomi Guyer's avatar
Naomi Guyer committed
65 66
                         'encoding':'multipart/form-data', 'name':'linksandresourcesform'},
                    TABLE({'class':'nohead table table-striped'},THEAD(null,[thead]), TBODY(null,[rows,addform()])));
67
    replaceChildNodes($('menuitemlist'),form);
Richard Mansfield's avatar
Richard Mansfield committed
68 69 70 71 72 73
}

// Creates one table row
function formatrow (item) {
    // item has id, type, name, link, linkedto
    var type = eval(item.type);
74
    var linkedto = A({'href':item.linkedto},item.linktext);
Naomi Guyer's avatar
Naomi Guyer committed
75
    var edit = BUTTON({'type':'button','class':'button btn btn-default btn-sm'}, SPAN({'class':'icon icon-lg icon-pencil prs'}), {$getstring['edit']});
76
    connect(edit, 'onclick', function () { edititem(item); });
Naomi Guyer's avatar
Naomi Guyer committed
77
    var del = BUTTON({'type':'button','class':'button btn btn-default btn-sm'}, SPAN({'class':'icon icon-lg icon-times text-danger prs'}), {$getstring['delete']});
78
    connect(del, 'onclick', function () { delitem(item.id); });
Naomi Guyer's avatar
Naomi Guyer committed
79
    var buttonGroup = SPAN({'class':'btn-group'}, edit, del);
Penny Leach's avatar
Penny Leach committed
80 81 82 83 84 85
    var cells = map(
        partial(TD,null),
        [
            type,
            item.name,
            linkedto,
Naomi Guyer's avatar
Naomi Guyer committed
86
            [buttonGroup,contextualHelpIcon('linksandresourcesform', null, 'core', 'admin', null, 'adminmenuedit')]
Penny Leach's avatar
Penny Leach committed
87 88
        ]
    );
Richard Mansfield's avatar
Richard Mansfield committed
89
    return TR({'id':'menuitem_'+item.id},cells);
Richard Mansfield's avatar
Richard Mansfield committed
90 91 92 93 94 95
}

// Returns the form which adds a new menu item
function addform(type) {
    var item = {'id':'new'};
    item.type = type ? type : 'externallist';
96
    return editform(item);
Richard Mansfield's avatar
Richard Mansfield committed
97 98 99 100 101 102 103
}

// Creates the contents of a menu item edit form
// This is formatted as a table within the form (which is within a row of the table).
function editform(item) {
    // item has id, type, name, link, linkedto
    // The form has two radio buttons to select the type, external link or admin file
Naomi Guyer's avatar
Naomi Guyer committed
104 105
    var elink = INPUT({'type':'radio','class':'radio with-label','name':'type'+item.id,'id':'type_'+item.id+'_externallink','value':'externallink'});
    var afile = INPUT({'type':'radio','class':'radio with-label','name':'type'+item.id,'id':'type_'+item.id+'_sitefile','value':'sitefile'});
Richard Mansfield's avatar
Richard Mansfield committed
106 107 108

    // Either a save, a cancel button, or both.
    var savecancel = [];
109
    var save = BUTTON({'type':'button','class':'button btn btn-default btn-sm'}, SPAN({'class':'icon icon-plus-circle icon-lg'}));
110
    connect(save, 'onclick', function () { saveitem(item.id); });
Richard Mansfield's avatar
Richard Mansfield committed
111 112 113 114

    // The link field will be a text box or a select in the case of an admin file.
    var linkedto = null;

115
    var rowtype = 'add';
Richard Mansfield's avatar
Richard Mansfield committed
116 117 118 119 120 121 122 123
    if (!item) {
        // This is the 'add' form rather than the edit form
        // Set defaults.
        item = {'type':'externallist'};
    }
    if (!item.linkedto) {
        item.linkedto = '';
        item.name = '';
124
        connect(elink, 'onclick', function () { changeaddform('externallink'); });
125
        connect(afile, 'onclick', function () { changeaddform('sitefile'); });
Richard Mansfield's avatar
Richard Mansfield committed
126
        // The save button says 'add', and there's no cancel button.
127
        setNodeAttribute(save,'value',{$getstring['add']});
Richard Mansfield's avatar
Richard Mansfield committed
128 129 130 131
        savecancel = [save];
    }
    else { // Editing an existing menu item.
        // The save button says 'update' and there's a cancel button.
132
        var rowtype = 'edit';
133
        setNodeAttribute(save,'value',{$getstring['update']});
Naomi Guyer's avatar
Naomi Guyer committed
134
        var cancel = BUTTON({'type':'button','class':'button btn-sm btn btn-link'}, {$getstring['cancel']});
135
        connect(cancel, 'onclick', closeopenedits);
Richard Mansfield's avatar
Richard Mansfield committed
136
        savecancel = [save,cancel];
137
        connect(elink, 'onclick', function () { changeeditform(item,'externallink'); });
138
        connect(afile, 'onclick', function () { changeeditform(item,'sitefile'); });
Richard Mansfield's avatar
Richard Mansfield committed
139 140 141
    }

    // A text field for the name
Naomi Guyer's avatar
Naomi Guyer committed
142
    var name = SPAN(null,LABEL({'for':'name'+item.id,'class':'sr-only'},$namelabel),INPUT({'type':'text','class':'text form-control input-sm','id':'name'+item.id,'value':item.name}));
Richard Mansfield's avatar
Richard Mansfield committed
143

144
    if (item.type == 'sitefile') {
Richard Mansfield's avatar
Richard Mansfield committed
145 146
        if (adminfiles == null) {
            // There are no admin files, we don't need the select or save button
147
            linkedto = {$getstring['nositefiles']};
Richard Mansfield's avatar
Richard Mansfield committed
148 149 150 151
            savecancel = [cancel];
        }
        else {
            // Select the currently selected file.
152
            linkedtoselect = SELECT({'id':'linkedto'+item.id});
Naomi Guyer's avatar
Naomi Guyer committed
153
            linkedto = SPAN(null,LABEL({'for':'linkedto'+item.id,'class':'sr-only'},$linkedtolabel), linkedtoselect);
154 155
            for (var i = 0; i < adminfiles.length; i++) {
                if (item.file == adminfiles[i].id) {
156
                    appendChildNodes(linkedtoselect, OPTION({'value':adminfiles[i].id, 'selected':true}, adminfiles[i].name));
157 158
                }
                else {
159
                    appendChildNodes(linkedtoselect, OPTION({'value':adminfiles[i].id}, adminfiles[i].name));
160 161
                }
            }
Richard Mansfield's avatar
Richard Mansfield committed
162 163 164 165
        }
        setNodeAttribute(afile,'checked',true);
    }
    else { // type = externallist
Naomi Guyer's avatar
Naomi Guyer committed
166 167
        linkedto =  SPAN(null,LABEL({'for':'linkedto'+item.id,'class':'sr-only'},$linkedtolabel),
                         INPUT({'type':'text','class':'text form-control input-sm','id':'linkedto'+item.id,'value':item.linkedto}));
Richard Mansfield's avatar
Richard Mansfield committed
168 169
        setNodeAttribute(elink,'checked',true);
    }
Naomi Guyer's avatar
Naomi Guyer committed
170 171
    var radios = [DIV({'class' : 'radio'}, elink, LABEL({'for':'type_'+item.id+'_externallink'}, {$getstring['externallink']}), contextualHelpIcon('linksandresourcesform', 'elink', 'core', 'admin', null, 'adminexternallink')),
                  DIV({'class' : 'radio'}, afile, LABEL({'for':'type_'+item.id+'_sitefile'}, {$getstring['sitefile']}),contextualHelpIcon('linksandresourcesform', 'afile', 'core', 'admin', null, 'adminsitefile'))];
Richard Mansfield's avatar
Richard Mansfield committed
172
    var row = TR({'id':'row'+item.id, 'class':rowtype},
173 174
                 map(partial(TD,null),[radios,name,linkedto,savecancel]));
    return row;
Richard Mansfield's avatar
Richard Mansfield committed
175 176 177 178 179 180
}

// Close all open edit forms
function closeopenedits() {
    var rows = getElementsByTagAndClassName('tr',null,$('menuitemlist'));
    for (var i=0; i<rows.length; i++) {
181
        if (hasElementClass(rows[i],'edit')) {
Richard Mansfield's avatar
Richard Mansfield committed
182 183
            removeElement(rows[i]);
        }
184 185
        else if (hasElementClass(rows[i],'hidden')) {
            removeElementClass(rows[i],'hidden');
Richard Mansfield's avatar
Richard Mansfield committed
186 187 188 189 190 191 192 193 194 195 196 197
        }
    }
}

// Change the type of an edit form
function changeeditform(item, type) {
    item.type = type;
    edititem(item);
}

// Change the type of the add form
function changeaddform(type) {
198 199
    var newrow = addform(type);
    swapDOM($('rownew'),newrow);
Richard Mansfield's avatar
Richard Mansfield committed
200 201 202 203 204 205
}

// Open a new edit form
function edititem(item) {
    closeopenedits();
    var menuitem = $('menuitem_'+item.id);
206
    addElementClass(menuitem,'hidden');
207
    var newrow = editform(item);
208
    insertSiblingNodesBefore(menuitem, newrow);
Richard Mansfield's avatar
Richard Mansfield committed
209 210
}

Richard Mansfield's avatar
Richard Mansfield committed
211
// Receive standard json error message
Richard Mansfield's avatar
Richard Mansfield committed
212 213
// Request deletion of a menu item from the db
function delitem(itemid) {
214
    if (confirm({$getstring['confirmdeletemenuitem']})) {
215
        sendjsonrequest('deletemenuitem.json.php',{'itemid':itemid}, 'POST', getitems);
216
    }
Richard Mansfield's avatar
Richard Mansfield committed
217 218 219
}

// Send the menu item in the form to the database.
220 221 222 223
function saveitem(itemid) {
    var f = $('form');
    var name = $('name'+itemid).value;
    var linkedto = $('linkedto'+itemid).value;
Richard Mansfield's avatar
Richard Mansfield committed
224
    if (name == '') {
225
        displayMessage(get_string('namedfieldempty',{$getstring['name']}),'error');
Richard Mansfield's avatar
Richard Mansfield committed
226 227 228
        return false;
    }
    if (linkedto == '') {
229
        displayMessage(get_string('namedfieldempty',{$getstring['linkedto']}),'error');
Richard Mansfield's avatar
Richard Mansfield committed
230 231
        return false;
    }
232

233
    var data = {'type':eval('f.type'+itemid+'[0].checked') ? 'externallink' : 'sitefile',
Richard Mansfield's avatar
Richard Mansfield committed
234 235
                'name':name,
                'linkedto':linkedto,
236
                'itemid':itemid,
237
                'public':selectedmenu == 'loggedoutmenu'};
238
    sendjsonrequest('updatemenu.json.php', data, 'POST', getitems);
Richard Mansfield's avatar
Richard Mansfield committed
239 240 241
    return false;
}

242 243
function changemenu() {
    selectedmenu = $('menuselect').value;
Richard Mansfield's avatar
Richard Mansfield committed
244
    getitems();
245
    getadminfiles();
Richard Mansfield's avatar
Richard Mansfield committed
246 247
}

248
var selectedmenu = 'loggedoutmenu';
249
var adminfiles = null;
250 251 252 253 254
addLoadEvent(function () {
    $('menuselect').value = selectedmenu;
    $('menuselect').onchange = changemenu;
    changemenu();
});
Richard Mansfield's avatar
Richard Mansfield committed
255 256
EOJS;

257 258 259
$menulist = array('loggedinmenu', 'loggedoutmenu');
foreach ($menulist as &$menu) {
    $menu = array('value' => $menu,
260
                  'name' => get_string($menu,'admin'));
261 262
}

263 264 265 266 267

// Edit form for footer links
$all = footer_menu(true);
$active = get_config('footerlinks');
$active = $active ? unserialize($active) : array_keys($all);
268 269
$activeurls = get_config('footercustomlinks');
$activeurls = $activeurls ? unserialize($activeurls) : null;
270 271 272
$footerelements = array();
foreach ($all as $k => $v) {
    $footerelements[$k] = array(
273
        'type' => 'switchbox',
274
        'class' => 'last pb0',
275 276
        'title' => $v['title'],
        'defaultvalue' => in_array($k, $active),
277 278 279 280 281 282 283 284
        'onclick' => "getElement('footerlinks_{$k}_link').disabled = !this.checked;",
    );
    $footerelements[$k . '_link'] = array(
        'type' => 'text',
        'size' => 60,
        'description' => get_string('footercustomlink', 'admin', $v['url']),
        'defaultvalue' => isset($activeurls[$k]) ? $activeurls[$k] : '',
        'disabled' => !in_array($k, $active),
285 286 287
    );
}
$footerelements['submit'] = array(
288
    'class' => 'btn-primary',
289 290 291 292 293 294 295 296 297
    'type'  => 'submit',
    'value' => get_string('savechanges', 'admin')
);
$footerform = pieform(array(
    'name'              => 'footerlinks',
    'elements'          => $footerelements,
));

function footerlinks_submit(Pieform $form, $values) {
298
    global $active, $activeurls, $all, $SESSION;
299
    $new = array();
300
    $newurls = array();
301 302 303 304
    foreach (array_keys($all) as $k) {
        if (!empty($values[$k])) {
            $new[] = $k;
        }
305 306 307 308
        if (!empty($values[$k.'_link']) &&
            ($values[$k.'_link'] != $all[$k]['url'])) {
                $newurls[$k] = $values[$k.'_link'];
        }
309 310 311 312 313
    }
    if ($new != $active) {
        set_config('footerlinks', serialize($new));
        $SESSION->add_ok_msg(get_string('footerupdated', 'admin'));
    }
314 315 316 317 318 319 320
    if ($newurls != $activeurls) {
        set_config('footercustomlinks', serialize($newurls));
        if ($new == $active) {
            // record message in session only if we haven't done so yet.
            $SESSION->add_ok_msg(get_string('footerupdated', 'admin'));
        }
    }
321 322 323 324
    redirect(get_config('wwwroot') . 'admin/site/menu.php');
}


325
$smarty = smarty();
326 327
setpageicon($smarty, 'icon-bars');

328 329
$smarty->assign('INLINEJAVASCRIPT', $ijs);
$smarty->assign('MENUS', $menulist);
330
$smarty->assign('descriptionstrargs', array('<a href="' . get_config('wwwroot') . 'artefact/file/sitefiles.php">', '</a>'));
331
$smarty->assign('PAGEHEADING', TITLE);
332
$smarty->assign('footerform', $footerform);
333
$smarty->display('admin/site/menu.tpl');