view.php 16.1 KB
Newer Older
1
2
3
4
5
<?php
/**
 *
 * @package    mahara
 * @subpackage core
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.
9
10
11
12
 *
 */

define('INTERNAL', 1);
13
define('PUBLIC', 1);
14
15
16
17
define('SECTION_PLUGINTYPE', 'core');
define('SECTION_PLUGINNAME', 'view');
define('SECTION_PAGE', 'view');

18
require(dirname(dirname(__FILE__)) . '/init.php');
19

20
require_once(get_config('libroot') . 'view.php');
21
require_once(get_config('libroot') . 'collection.php');
22
require_once(get_config('libroot') . 'objectionable.php');
23
require_once('institution.php');
24
require_once('group.php');
25
safe_require('artefact', 'comment');
26
safe_require('artefact', 'file');
27

28
29
30
31
32
33
34
35
36
37
38
39
40
// Used by the Mahara assignment submission plugin for Moodle, to indicate that a user
// coming over from mnet should be able to view a certain page (i.e. a teacher viewing
// an assignmnet submission)
$mnetviewid = param_integer('mnetviewid', false);
$mnetcollid = param_integer('mnetcollid', false);
if (
        ($mnetviewid || $mnetcollid)
        && $SESSION->get('mnetuser')
        && safe_require_plugin('auth', 'xmlrpc')
) {
    auth_xmlrpc_mnet_view_access($mnetviewid, $mnetcollid);
}

41
// access key for roaming teachers
42
43
// TODO: The mt token is used by the old token-based Mahara assignment submission
// access system, which is now deprecated. Remove eventually.
44
45
46
47
48
49
50
51
52
53
54
55
56
$mnettoken = $SESSION->get('mnetuser') ? param_alphanum('mt', null) : null;

// access key for logged out users
$usertoken = (is_null($mnettoken) && get_config('allowpublicviews')) ? param_alphanum('t', null) : null;

if ($mnettoken) {
    if (!$viewid = get_view_from_token($mnettoken, false)) {
        throw new AccessDeniedException(get_string('accessdenied', 'error'));
    }
}
else if ($usertoken) {
    if (!$viewid = get_view_from_token($usertoken, true)) {
        throw new AccessDeniedException(get_string('accessdenied', 'error'));
Richard Mansfield's avatar
Richard Mansfield committed
57
58
    }
}
59
60
61
62
63
64
65
66
67
68
69
70
else if ($pageurl = param_alphanumext('page', null)) {
    if ($profile = param_alphanumext('profile', null)) {
        $view = new View(array('urlid' => $pageurl, 'ownerurlid' => $profile));
    }
    else if ($homepage = param_alphanumext('homepage', null)) {
        $view = new View(array('urlid' => $pageurl, 'groupurlid' => $homepage));
    }
    else {
        throw new ViewNotFoundException(get_string('viewnotfoundexceptiontitle', 'error'));
    }
    $viewid = $view->get('id');
}
Richard Mansfield's avatar
Richard Mansfield committed
71
72
73
else {
    $viewid = param_integer('id');
}
74

75
$new = param_boolean('new');
76
77
78
79
$showmore = param_boolean('showmore');
if (!$showmore) {
    $showmore = 0;
}
80

81
82
83
84
85
if (!isset($view)) {
    $view = new View($viewid);
}

if (!can_view_view($view)) {
86
87
    $errorstr = (param_integer('objection', null)) ? get_string('accessdeniedobjection', 'error') : get_string('accessdenied', 'error');
    throw new AccessDeniedException($errorstr);
88
}
89
90
91
92
93
94
95
96
97
else {
    // To save the atime in the db - make it a millisecond in the past
    // so it differs from the atime in the View constructor and so triggers
    // the saving of the atime change. Can't use $view->set('dirty', true)
    // as that will also get the view object to update the mtime which is not
    // what we want.
    $view->set('atime', (time()) - 1);
    $view->commit();
}
98

99
// Comment list pagination requires limit/offset params
100
101
102
$limit       = param_integer('limit', 10);
$offset      = param_integer('offset', 0);
$showcomment = param_integer('showcomment', null);
103

104
// Create the "make comment private form" now if it's been submitted
105
106
if (param_variable('make_public_submit', null)) {
    pieform(ArtefactTypeComment::make_public_form(param_integer('comment')));
107
}
108
else if (param_exists('delete_comment_submit')) {
Richard Mansfield's avatar
Richard Mansfield committed
109
    pieform(ArtefactTypeComment::delete_comment_form(param_integer('comment')));
110
111
}

112
113
$owner    = $view->get('owner');
$viewtype = $view->get('type');
114

115
116
if ($viewtype == 'profile' || $viewtype == 'dashboard' || $viewtype == 'grouphomepage') {
    redirect($view->get_url());
117
}
118

119
120
define('TITLE', $view->get('title'));

121
$collection = $view->get('collection');
122
$submittedgroup = (int)$view->get('submittedgroup');
123
if ($USER->is_logged_in() && $submittedgroup && group_user_can_assess_submitted_views($submittedgroup, $USER->get('id'))) {
124
    // The user is a tutor of the group that this view has
125
    // been submitted to, and is entitled to release the view
126
    $submittedgroup = get_record('group', 'id', $submittedgroup);
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
    // If the view is part of a submitted collection, the whole
    // collection must be released at once.
    $releasecollection = !empty($collection) && $collection->get('submittedgroup') == $submittedgroup->id;
    if ($releasecollection) {
        if ($ctime = $collection->get('submittedtime')) {
            $text = get_string(
                'collectionsubmittedtogroupon', 'view', group_homepage_url($submittedgroup), hsc($submittedgroup->name),
                format_date(strtotime($ctime))
            );
        }
        else {
            $text = get_string('collectionsubmittedtogroup', 'view', group_homepage_url($submittedgroup), hsc($submittedgroup->name));
        }
    }
    else if ($view->get('submittedtime')) {
142
        $text = get_string('viewsubmittedtogroupon', 'view', group_homepage_url($submittedgroup), hsc($submittedgroup->name), format_date(strtotime($view->get('submittedtime'))));
143
144
    }
    else {
145
        $text = get_string('viewsubmittedtogroup', 'view', group_homepage_url($submittedgroup), hsc($submittedgroup->name));
146
    }
147
148
149
150
    if (($releasecollection && $collection->get('submittedstatus') == Collection::SUBMITTED) || $view->get('submittedstatus') == View::SUBMITTED) {
        $releaseform = pieform(array(
            'name'     => 'releaseview',
            'method'   => 'post',
Pat Kira's avatar
Pat Kira committed
151
            'class' => 'form-inline',
152
153
154
155
156
157
158
159
160
            'plugintype' => 'core',
            'pluginname' => 'view',
            'autofocus' => false,
            'elements' => array(
                'submittedview' => array(
                    'type'  => 'html',
                    'value' => $text,
                ),
                'submit' => array(
Pat Kira's avatar
Pat Kira committed
161
162
                    'type'  => 'button',
                    'usebuttontag' => true,
163
                    'class' => 'btn-default pull-right',
164
                    'value' => $releasecollection ? '<span class="icon icon-unlock left" role="presentation" aria-hidden="true"></span>' . get_string('releasecollection', 'group') : '<span class="icon icon-unlock left" role="presentation" aria-hidden="true"></span>' . get_string('releaseview', 'group'),
165
                ),
166
            ),
167
168
169
170
171
        ));
    }
    else {
        $releaseform = $text . ' ' . get_string('submittedpendingrelease', 'view');
    }
172
}
173
174
175
176
177
else {
    $releaseform = '';
}

function releaseview_submit() {
178
    global $USER, $SESSION, $view, $collection, $submittedgroup, $releasecollection;
179

180
    if ($releasecollection) {
181
182
183
184
185
186
187
188
        if (is_object($submittedgroup) && $submittedgroup->allowarchives) {
            $collection->pendingrelease($USER);
            $SESSION->add_ok_msg(get_string('collectionreleasedpending', 'group'));
        }
        else {
            $collection->release($USER);
            $SESSION->add_ok_msg(get_string('collectionreleasedsuccess', 'group'));
        }
189
190
    }
    else {
191
192
193
194
195
196
197
198
        if (is_object($submittedgroup) && $submittedgroup->allowarchives) {
            $view->pendingrelease($USER);
            $SESSION->add_ok_msg(get_string('viewreleasedpending', 'group'));
        }
        else {
            $view->release($USER);
            $SESSION->add_ok_msg(get_string('viewreleasedsuccess', 'group'));
        }
199
    }
200
    if ($submittedgroup) {
201
202
        // The tutor might not have access to the view any more; send
        // them back to the group page.
203
        redirect(group_homepage_url($submittedgroup));
204
    }
205
    redirect($view->get_url());
206
}
207

208
$javascript = array('paginator', 'viewmenu', 'js/collection-navigation.js');
209
210
$blocktype_js = $view->get_all_blocktype_javascript();
$javascript = array_merge($javascript, $blocktype_js['jsfiles']);
211
if (is_plugin_active('externalvideo', 'blocktype')) {
212
213
    $javascript = array_merge($javascript, array((is_https() ? 'https:' : 'http:') . '//cdn.embedly.com/widgets/platform.js'));
}
214
$inlinejs = "addLoadEvent( function() {\n" . join("\n", $blocktype_js['initjs']) . "\n});";
215

216
217
// If the view has comments turned off, tutors can still leave
// comments if the view is submitted to their group.
218
if (!empty($releaseform) || ($commenttype = $view->user_comments_allowed($USER))) {
219
    $defaultprivate = !empty($releaseform);
220
221
    $moderate = isset($commenttype) && $commenttype === 'private';
    $addfeedbackform = pieform(ArtefactTypeComment::add_comment_form($defaultprivate, $moderate));
222
223
224
}
if ($USER->is_logged_in()) {
    $objectionform = pieform(objection_form());
225
    if ($notrudeform = notrude_form()) {
226
227
        $notrudeform = pieform($notrudeform);
    }
228
229
}

230
$viewbeingwatched = (int)record_exists('usr_watchlist_view', 'usr', $USER->get('id'), 'view', $viewid);
231
232
233
234
235
236
$commentoptions = ArtefactTypeComment::get_comment_options();
$commentoptions->limit = $limit;
$commentoptions->offset = $offset;
$commentoptions->showcomment = $showcomment;
$commentoptions->view = $view;
$feedback = ArtefactTypeComment::get_comments($commentoptions);
237

238
// Set up theme
239
240
$viewtheme = $view->get('theme');
if ($viewtheme && $THEME->basename != $viewtheme) {
241
    $THEME = new Theme($view);
242
}
Naomi Guyer's avatar
Naomi Guyer committed
243
$headers = array();
244
$headers[] = '<link rel="stylesheet" type="text/css" href="' . append_version_number(get_config('wwwroot') . 'js/jquery/jquery-ui/css/smoothness/jquery-ui.min.css') . '">';
245
$headers = array_merge($headers, $view->get_all_blocktype_css());
246
247
// Set up skin, if the page has one
$viewskin = $view->get('skin');
248
249
$issiteview = $view->get('institution') == 'mahara';
if ($viewskin && get_config('skins') && can_use_skins($owner, false, $issiteview) && (!isset($THEME->skins) || $THEME->skins !== false)) {
250
    $skin = array('skinid' => $viewskin, 'viewid' => $view->get('id'));
251
252
253
254
255
}
else {
    $skin = false;
}

256
257
258
if (!$view->is_public()) {
    $headers[] = '<meta name="robots" content="noindex">';  // Tell search engines not to index non-public views
}
259

260
261
262
263
// include slimbox2 js and css files, if it is enabled...
if (get_config_plugin('blocktype', 'gallery', 'useslimbox2')) {
    $langdir = (get_string('thisdirection', 'langconfig') == 'rtl' ? '-rtl' : '');
    $headers = array_merge($headers, array(
264
        '<script type="application/javascript" src="' . append_version_number(get_config('wwwroot') . 'lib/slimbox2/js/slimbox2.js') . '"></script>',
265
        '<link rel="stylesheet" type="text/css" href="' . append_version_number(get_config('wwwroot') . 'lib/slimbox2/css/slimbox2' . $langdir . '.css') . '">'
266
267
268
    ));
}

269
$can_edit = $USER->can_edit_view($view) && !$submittedgroup && !$view->is_submitted();
270
$can_copy = $view->is_copyable($view);
271

272
273
274
275
276
277
278
279
280
$viewgroupform = false;
if ($owner && $owner == $USER->get('id')) {
    if ($tutorgroupdata = group_get_user_course_groups()) {
        if (!$view->is_submitted()) {
            $viewgroupform = view_group_submission_form($view, $tutorgroupdata, 'view');
        }
    }
}

281
282
$viewcontent = $view->build_rows(); // Build content before initialising smarty in case pieform elements define headers.

283
$smarty = smarty(
284
    $javascript,
285
    $headers,
286
287
288
289
    array('confirmcopytitle' => 'view',
          'confirmcopydesc' => 'view',
          'View' => 'view',
          'Collection' => 'collection'),
290
291
    array(
        'sidebars' => false,
292
        'skin' => $skin
293
    )
294
);
295

296
297
$javascript = <<<EOF
var viewid = {$viewid};
298
var showmore = {$showmore};
299
300
301
addLoadEvent(function () {
    paginator = {$feedback->pagination_js}
});
302

303
304
305
jQuery(function($) {
    $('#column-container .blockinstance-content .commentlink').each(function() {
        var blockid = $(this).attr('id').match(/\d+/);
306
        // only use comments expander if there are comments on the artefact
307
308
        $(this).on('click', function(e) {
            var commentlink = $(this);
309
310
            var chtml = commentlink.parent().parent().find('#feedbacktable_' + blockid).parent();
            // add a 'close' link at the bottom of the list for convenience
311
312
313
            if ($('#closer_' + blockid).length == 0) {
                var closer = $('<a id="closer_' + blockid + '" href="#" class="close-link">Close</a>').click(function(e) {
                    $(this).parent().toggle(400, function() {
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
                        commentlink.focus();
                    });
                    e.preventDefault();
                });
                chtml.append(closer);
            }
            chtml.toggle(400, function() {
                if (chtml.is(':visible')) {
                    chtml.find('a').first().focus();
                }
                else {
                    commentlink.focus();
                }
            });
            e.preventDefault();
        });
    });
});

333
334
EOF;

335
// collection top navigation
336
if ($collection) {
337
338
    $shownav = $collection->get('navigation');
    if ($shownav) {
339
        if ($views = $collection->get('views')) {
340
341
342
343
344
            $viewnav = $views['views'];
            if ($collection->has_framework()) {
                array_unshift($viewnav, $collection->collection_nav_framework_option());
            }
            $smarty->assign('collection', $viewnav);
345
        }
346
    }
347
348
}

349
$smarty->assign('INLINEJAVASCRIPT', $javascript . $inlinejs);
350
$smarty->assign('new', $new);
351
$smarty->assign('viewid', $viewid);
352
$smarty->assign('viewtype', $viewtype);
353
$smarty->assign('feedback', $feedback);
Richard Mansfield's avatar
Richard Mansfield committed
354
355
$smarty->assign('owner', $owner);
$smarty->assign('tags', $view->get('tags'));
356
$smarty->assign('PAGEHEADING', null);
357
358
359
360
361
362
363
364
365
366
367
368
369
if ($view->is_anonymous()) {
  $smarty->assign('PAGEAUTHOR', get_string('anonymoususer'));
  $smarty->assign('author', get_string('anonymoususer'));
  if ($view->is_staff_or_admin_for_page()) {
    $smarty->assign('realauthor', $view->display_author());
  }
  $smarty->assign('anonymous', TRUE);
} else {
  $smarty->assign('PAGEAUTHOR', $view->formatted_owner());
  $smarty->assign('author', $view->display_author());
  $smarty->assign('anonymous', FALSE);
}

370

371
$titletext = ($collection && $shownav) ? hsc($collection->get('name')) : $view->display_title(true, false, false);
372
$smarty->assign('lastupdatedstr', $view->lastchanged_message());
373
$smarty->assign('visitstring', $view->visit_message());
374
375
if ($can_edit) {
    $smarty->assign('editurl', get_config('wwwroot') . 'view/blocks.php?id=' . $viewid . ($new ? '&new=1' : ''));
376
}
377
378
if ($can_copy) {
    $smarty->assign('copyurl', get_config('wwwroot') . 'view/copy.php?id=' . $viewid . (!empty($collection) ? '&collection=' . $collection->get('id') : ''));
379
}
380

381
382
$title = hsc(TITLE);

383
$smarty->assign('maintitle', $titletext);
384

385
// Provide a link for roaming teachers to return
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
$showmnetlink = false;
// Old token-based access list
if (
    $mnetviewlist = $SESSION->get('mnetviewaccess')
    && isset($mnetviewlist[$view->get('id')])
) {
    $showmnetlink = true;
}

// New mnet-based access list
if (
    $SESSION->get('mnetviews')
    && in_array($view->get('id'), $SESSION->get('mnetviews'))
) {
    $showmnetlink = true;
}


if ($showmnetlink) {
    $returnurl = $SESSION->get('mnetuserfrom');
    require_once(get_config('docroot') . 'api/xmlrpc/lib.php');
    if ($peer = get_peer_from_instanceid($SESSION->get('authinstance'))) {
        $smarty->assign('mnethost', array(
            'name'      => $peer->name,
            'url'       => $returnurl ? $returnurl : $peer->wwwroot,
        ));
412
413
    }
}
414

415
$smarty->assign('viewdescription', ArtefactTypeFolder::append_view_url($view->get('description'), $view->get('id')));
416
$smarty->assign('viewcontent', $viewcontent);
417
$smarty->assign('releaseform', $releaseform);
418
if (isset($addfeedbackform)) {
419
    $smarty->assign('enablecomments', 1);
420
    $smarty->assign('addfeedbackform', $addfeedbackform);
421
}
422
423
if (isset($objectionform)) {
    $smarty->assign('objectionform', $objectionform);
424
    $smarty->assign('notrudeform', $notrudeform);
425
}
426
$smarty->assign('viewbeingwatched', $viewbeingwatched);
427

428
429
if ($viewgroupform) {
    $smarty->assign('view_group_submission_form', $viewgroupform);
430
431
}

432
433
434
435
if ($titletext !== $title) {
    $smarty->assign('title', $title);
}

436
437
$smarty->assign('userisowner', ($owner && $owner == $USER->get('id')));

438
439
$smarty->display('view/view.tpl');

440
mahara_log('views', "$viewid"); // Log view visits