PAGE::stripe_start()   A
last analyzed

Complexity

Conditions 5
Paths 8

Size

Total Lines 29
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 11
nc 8
nop 3
dl 0
loc 29
rs 9.6111
c 1
b 0
f 0
ccs 0
cts 6
cp 0
crap 30
1
<?php
2
3
include_once INCLUDESPATH . '../../commonlib/phplib/gaze.php';
4
include_once INCLUDESPATH . 'easyparliament/member.php';
5
6
class PAGE {
7
    // So we can tell from other places whether we need to output the page_start or not.
8
    // Use the page_started() function to do this.
9
    public $page_start_done = false;
10
    public $supress_heading = false;
11
    public $heading_displayed = false;
12
13
    // We want to know where we are with the stripes, the main structural elements
14
    // of most pages, so that if we output an error message we can wrap it in HTML
15
    // that won't break the rest of the page.
16
    // Changed in $this->stripe_start().
17
    public $within_stripe_main = false;
18
    public $within_stripe_sidebar = false;
19
20
    public function page_start() {
21
        if (!$this->page_started()) {
22
            $this->checkForAdmin();
23
            $this->displayHeader();
24
        }
25
    }
26
27
    private function displayHeader() {
28
        global $page_errors;
29
        $h = new MySociety\TheyWorkForYou\Renderer\Header();
30
        $u = new MySociety\TheyWorkForYou\Renderer\User();
31
32
        $data = $h->data;
33
        $data = array_merge($u->data, $data);
34
        if (isset($page_errors)) {
35
            $data['page_errors'] = $page_errors;
36
        }
37
        $data['banner_text'] = '';
38
        extract($data);
39
        require_once INCLUDESPATH . 'easyparliament/templates/html/header.php';
40
41
        echo '<div class="full-page legacy-page static-page"> <div class="full-page__row"> <div class="panel">';
42
43
        $this->page_start_done = true;
44
    }
45
46
    private function checkForAdmin() {
47
        global $DATA, $this_page, $THEUSER;
48
        $parent = $DATA->page_metadata($this_page, "parent");
49
        if ($parent == 'admin' && (!$THEUSER->isloggedin() || !$THEUSER->is_able_to('viewadminsection'))) {
50
            if (!$THEUSER->isloggedin()) {
51
                $THISPAGE = new \MySociety\TheyWorkForYou\Url($this_page);
52
53
                $LOGINURL = new \MySociety\TheyWorkForYou\Url('userlogin');
54
                $LOGINURL->insert(['ret' => $THISPAGE->generate('none') ]);
55
56
                $text = "<a href=\"" . $LOGINURL->generate() . '">' . gettext('You’d better sign in!') . '</a>';
57
            } else {
58
                $text = "That's all folks!";
59
            }
60
            $this_page = 'home';
61
            $this->displayHeader();
62
            echo $text;
63
            $this->page_end();
64
            exit();
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
65
        }
66
    }
67
68
    public function page_end() {
69
        if (!$this->page_started()) {
70
            $this->page_start();
71
        }
72
73
        echo '</div></div></div>';
74
        $footer = new MySociety\TheyWorkForYou\Renderer\Footer();
75
        $footer_links = $footer->data;
0 ignored issues
show
Unused Code introduced by
The assignment to $footer_links is dead and can be removed.
Loading history...
76
        require_once INCLUDESPATH . 'easyparliament/templates/html/footer.php';
77
    }
78
79
    public function page_started() {
80
        return $this->page_start_done == true ? true : false;
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
81
    }
82
83
    public function heading_displayed() {
84
        return $this->heading_displayed == true ? true : false;
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
85
    }
86
87
    public function within_stripe() {
88
        if ($this->within_stripe_main == true || $this->within_stripe_sidebar == true) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
89
            return true;
90
        } else {
91
            return false;
92
        }
93
    }
94
95
    public function within_stripe_sidebar() {
96
        if ($this->within_stripe_sidebar == true) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison === instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
97
            return true;
98
        } else {
99
            return false;
100
        }
101
    }
102
103
    public function stripe_start($type = 'side', $id = '', $extra_class = '') {
104
        // $type is one of:
105
        //  'full' - a full width div
106
        //  'side' - a white stripe with a coloured sidebar.
107
        //           (Has extra padding at the bottom, often used for whole pages.)
108
        //  'head-1' - used for the page title headings in hansard.
109
        //  'head-2' - used for section/subsection titles in hansard.
110
        //  '1', '2' - For alternating stripes in listings.
111
        //  'time-1', 'time-2' - For displaying the times in hansard listings.
112
        //  'procedural-1', 'procedural-2' - For the proecdures in hansard listings.
113
        //  'foot' - For the bottom stripe on hansard debates/wrans listings.
114
        // $id is the value of an id for this div (if blank, not used).
115
        ?>
116
        <div class="stripe-<?php echo $type; ?><?php if ($extra_class != '') {
117
            echo ' ' . $extra_class;
118
        }
119
        ?>"<?php
120
                if ($id != '') {
121
                    print ' id="' . $id . '"';
122
                }
123
        ?>>
124
            <div class="main">
125
<?php
126
        $this->within_stripe_main = true;
127
        // On most, uncomplicated pages, the first stripe on a page will include
128
        // the page heading. So, if we haven't already printed a heading on this
129
        // page, we do it now...
130
        if (!$this->heading_displayed() && $this->supress_heading != true) {
0 ignored issues
show
Coding Style Best Practice introduced by
It seems like you are loosely comparing two booleans. Considering using the strict comparison !== instead.

When comparing two booleans, it is generally considered safer to use the strict comparison operator.

Loading history...
131
            $this->heading();
132
        }
133
    }
134
135
136
    public function stripe_end($contents = [], $extra = '') {
0 ignored issues
show
Unused Code introduced by
The parameter $extra is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

136
    public function stripe_end($contents = [], /** @scrutinizer ignore-unused */ $extra = '') {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
137
        // $contents is an array containing 0 or more hashes.
138
        // Each hash has two values, 'type' and 'content'.
139
        // 'Type' could be one of these:
140
        //  'include' - will include a sidebar named after the value of 'content'.php.
141
        //  'nextprev' - $this->nextprevlinks() is called ('content' currently ignored).
142
        //  'html' - The value of the 'content' is simply displayed.
143
        //  'extrahtml' - The value of the 'content' is displayed after the sidebar has
144
        //                  closed, but within this stripe.
145
146
        // If $contents is empty then '&nbsp;' will be output.
147
148
        /* eg, take this hypothetical array:
149
            $contents = array(
150
                array (
151
                    'type'  => 'include',
152
                    'content'   => 'mp'
153
                ),
154
                array (
155
                    'type'  => 'html',
156
                    'content'   => "<p>This is your MP</p>\n"
157
                ),
158
                array (
159
                    'type'  => 'nextprev'
160
                ),
161
                array (
162
                    'type'  => 'none'
163
                ),
164
                array (
165
                    'extrahtml' => '<a href="blah">Source</a>'
166
                )
167
            );
168
169
            The sidebar div would be opened.
170
            This would first include /includes/easyparliament/templates/sidebars/mp.php.
171
            Then display "<p>This is your MP</p>\n".
172
            Then call $this->nextprevlinks().
173
            The sidebar div would be closed.
174
            '<a href="blah">Source</a>' is displayed.
175
            The stripe div is closed.
176
177
            But in most cases we only have 0 or 1 hashes in $contents.
178
179
        */
180
181
        // $extra is html that will go after the sidebar has closed, but within
182
        // this stripe.
183
        // eg, the 'Source' bit on Hansard pages.
184
        global $DATA, $this_page;
185
186
        $this->within_stripe_main = false;
187
        ?>
188
            </div> <!-- end .main -->
189
            <div class="sidebar">
190
191
        <?php
192
        $this->within_stripe_sidebar = true;
193
        $extrahtml = '';
194
195
        if (count($contents) == 0) {
196
            print "\t\t\t&nbsp;\n";
197
        } else {
198
            #print '<div class="sidebar">';
199
            foreach ($contents as $hash) {
200
                if (isset($hash['type'])) {
201
                    if ($hash['type'] == 'include') {
202
                        $this->include_sidebar_template($hash['content']);
203
204
                    } elseif ($hash['type'] == 'nextprev') {
205
                        $this->nextprevlinks();
206
207
                    } elseif ($hash['type'] == 'html') {
208
                        print $hash['content'];
209
210
                    } elseif ($hash['type'] == 'extrahtml') {
211
                        $extrahtml .= $hash['content'];
212
                    }
213
                }
214
215
            }
216
        }
217
218
        $this->within_stripe_sidebar = false;
219
        ?>
220
            </div> <!-- end .sidebar -->
221
            <div class="break"></div>
222
<?php
223
        if ($extrahtml != '') {
224
            ?>
225
            <div class="extra"><?php echo $extrahtml; ?></div>
226
<?php
227
        }
228
        ?>
229
        </div> <!-- end .stripe-* -->
230
231
<?php
232
    }
233
234
235
236
    public function include_sidebar_template($sidebarname) {
237
        global $this_page, $DATA;
238
239
        $sidebarpath = INCLUDESPATH . 'easyparliament/sidebars/' . $sidebarname . '.php';
240
241
        if (file_exists($sidebarpath)) {
242
            include $sidebarpath;
243
        }
244
    }
245
246
247
    public function block_start($data = []) {
248
        // Starts a 'block' div, used mostly on the home page,
249
        // on the MP page, and in the sidebars.
250
        // $data is a hash like this:
251
        //  'id'    => 'help',
252
        //  'title' => 'What are debates?'
253
        //  'url'   => '/help/#debates'     [if present, will be wrapped round 'title']
254
        //  'body'  => false    [If not present, assumed true. If false, no 'blockbody' div]
255
        // Both items are optional (although it'll look odd without a title).
256
257
        $this->blockbody_open = false;
0 ignored issues
show
Bug Best Practice introduced by
The property blockbody_open does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
258
259
        if (isset($data['id']) && $data['id'] != '') {
260
            $id = ' id="' . $data['id'] . '"';
261
        } else {
262
            $id = '';
263
        }
264
265
        $title = $data['title'] ?? '';
266
267
        if (isset($data['url'])) {
268
            $title = '<a href="' . $data['url'] . '">' . $title . '</a>';
269
        }
270
        ?>
271
                <div class="block"<?php echo $id; ?>>
272
                    <h4><?php echo $title; ?></h4>
273
<?php
274
        if (!isset($data['body']) || $data['body'] == true) {
275
            ?>
276
                    <div class="blockbody">
277
<?php
278
            $this->blockbody_open = true;
279
        }
280
    }
281
282
    public function block_end() {
283
        if ($this->blockbody_open) {
284
            ?>
285
                    </div>
286
<?php
287
        }
288
        ?>
289
                </div> <!-- end .block -->
290
291
<?php
292
    }
293
294
    public function heading() {
295
        global $this_page, $DATA;
296
297
        // As well as a page's title, we may display that of its parent.
298
        // A page's parent can have a 'title' and a 'heading'.
299
        // The 'title' is always used to create the <title></title>.
300
        // If we have a 'heading' however, we'll use that here, on the page, instead.
301
302
        $parent_page = $DATA->page_metadata($this_page, 'parent');
303
304
        if ($parent_page != '') {
305
            // Not a top-level page, so it has a section heading.
306
            // This is the page title of the parent.
307
            $section_text = $DATA->page_metadata($parent_page, 'title');
308
309
        } else {
310
            // Top level page - no parent, hence no parental title.
311
            $section_text = '';
312
        }
313
314
315
        // A page can have a 'title' and a 'heading'.
316
        // The 'title' is always used to create the <title></title>.
317
        // If we have a 'heading' however, we'll use that here, on the page, instead.
318
319
        $page_text = $DATA->page_metadata($this_page, "heading");
320
321
        if ($page_text == '' && !is_bool($page_text)) {
322
            // If the metadata 'heading' is set, but empty, we display nothing.
323
        } elseif ($page_text == false) {
324
            // But if it just hasn't been set, we use the 'title'.
325
            $page_text = $DATA->page_metadata($this_page, "title");
326
        }
327
328
        if ($page_text == $section_text) {
329
            // We don't want to print both.
330
            $section_text = '';
331
        } elseif (!$page_text && $section_text) {
332
            // Bodge for if we have a section_text but no page_text.
333
            $page_text = $section_text;
334
            $section_text = '';
335
        }
336
337
        # XXX Yucky
338
        if ($this_page != 'home' && $this_page != 'contact') {
339
            if ($section_text && $parent_page != 'help_us_out' && $parent_page != 'home' && $this_page != 'campaign') {
340
                print "\t\t\t\t<h1>$section_text";
341
                if ($page_text) {
342
                    print "\n\t\t\t\t<br><span>$page_text</span>\n";
343
                }
344
                print "</h1>\n";
345
            } elseif ($page_text) {
346
                print "\t\t\t\t<h1>$page_text</h1>\n";
347
            }
348
        }
349
350
        // So we don't print the heading twice by accident from $this->stripe_start().
351
        $this->heading_displayed = true;
352
    }
353
354
    public function postcode_form() {
355
        // Used on the mp (and yourmp) pages.
356
        // And the userchangepc page.
357
        global $THEUSER;
358
359
        echo '<br>';
360
        $this->block_start(['id' => 'mp', 'title' => 'Find out about your MP/MSPs/MLAs']);
361
        echo '<form action="/postcode/" method="get">';
362
        if ($THEUSER->postcode_is_set()) {
363
            $FORGETURL = new \MySociety\TheyWorkForYou\Url('userchangepc');
364
            $FORGETURL->insert(['forget' => 't']);
365
            ?>
366
                        <p><?= gettext('Your current postcode:') ?> <strong><?php echo $THEUSER->postcode(); ?></strong> &nbsp; <small>(<a href="<?php echo $FORGETURL->generate(); ?>" title="<?= gettext('The cookie storing your postcode will be erased') ?>"><?= gettext('Forget this postcode') ?></a>)</small></p>
367
<?php
368
        }
369
        ?>
370
                        <p><strong><?= gettext('Enter your UK postcode:') ?> </strong>
371
372
                        <input type="text" name="pc" value="<?php echo _htmlentities(get_http_var('pc')); ?>" maxlength="10" size="10"> <input type="submit" value="<?= gettext('GO') ?>" class="submit"> <small><?= gettext('(e.g. BS3 1QP)') ?></small>
373
                        </p>
374
                        </form>
375
<?php
376
        $this->block_end();
377
    }
378
379
    public function error_message($message, $fatal = false, $status = 500) {
380
        // If $fatal is true, we exit the page right here.
381
        // $message is like the array used in $this->message()
382
        global $page_errors;
383
384
        // if possible send a 500 error so that google or whatever doesn't
385
        // cache the page. Rely on the fact that an inpage errors will be
386
        // sent after a page_start and hence the headers have been sent
387
        if (!headers_sent()) {
388
            header("HTTP/1.0 $status Internal Server Error");
389
        }
390
391
        if (is_string($message)) {
392
            // Sometimes we're just sending a single line to this function
393
            // rather like the bigger array...
394
            $message =  [
395
                'text' => $message,
396
            ];
397
        }
398
399
        // if the page has started then we're most likely in an old school page
400
        // so we should just print out the error, otherwise stick it in the error
401
        // global which will then be displayed by the header template
402
        if ($this->page_started()) {
403
            $this->message($message, 'error');
404
        } else {
405
            if (!isset($page_errors)) {
406
                $page_errors = [];
407
            }
408
            $page_errors[]  = $message;
409
        }
410
411
        if ($fatal) {
412
            if (!$this->page_started()) {
413
                $this->page_start();
414
            }
415
416
            if ($this->within_stripe()) {
417
                $this->stripe_end();
418
            }
419
            $this->page_end();
420
        }
421
422
    }
423
424
425
    public function message($message, $class = '') {
426
        // Generates a very simple but common page content.
427
        // Used for when a user logs out, or votes, or any simple thing
428
        // where there's a little message and probably a link elsewhere.
429
        // $message is an array like:
430
        //      'title' => 'You are now logged out'.
431
        //      'text'  => 'Some more text here',
432
        //      'linkurl' => '/debates/',
433
        //      'linktext' => 'Back to previous page'
434
        // All fields optional.
435
        // 'linkurl' should already have htmlentities done on it.
436
        // $class is a class name that will be applied to the message's HTML elements.
437
438
        if ($class != '') {
439
            $class = ' class="' . $class . '"';
440
        }
441
442
        $need_to_close_stripe = false;
443
444
        if (!$this->within_stripe()) {
445
            $this->stripe_start();
446
            $need_to_close_stripe = true;
447
        }
448
449
        if (isset($message['title'])) {
450
            ?>
451
            <h3<?php echo $class; ?>><?php echo $message['title']; ?></h3>
452
<?php
453
        }
454
455
        if (isset($message['text'])) {
456
            ?>
457
            <p<?php echo $class; ?>><?php echo $message['text']; ?></p>
458
<?php
459
        }
460
461
        $linkurl = $message['linkurl'] ?? "";
462
        if (!preg_match('#^/[^/]#', $linkurl)) {
463
            $linkurl = null;
464
        }
465
        if (isset($linkurl) && isset($message['linktext'])) {
466
            ?>
467
            <p><a href="<?php echo _htmlspecialchars($linkurl); ?>"><?php echo _htmlspecialchars($message['linktext']); ?></a></p>
468
<?php
469
        }
470
471
        if ($need_to_close_stripe) {
472
            $this->stripe_end();
473
        }
474
    }
475
476
    public function informational($text) {
477
        print '<div class="informational left">' . $text . '</div>';
478
    }
479
480
    public function set_hansard_headings($info) {
481
        // Called from HANSARDLIST->display().
482
        // $info is the $data['info'] array passed to the template.
483
        // If the page's HTML hasn't already been started, it sets the page
484
        // headings that will be needed later in the page.
485
486
        global $DATA, $this_page;
487
488
        if ($this->page_started()) {
489
            return;
490
        }
491
        // The page's HTML hasn't been started yet, so we'd better do it.
492
493
        // Set the page title (in the <title></title>).
494
        $page_title = '';
495
496
        if (isset($info['text_heading'])) {
497
            $page_title = $info['text_heading'];
498
        } elseif (isset($info['text'])) {
499
            // Use a truncated version of the page's main item's body text.
500
            // trim_words() is in utility.php. Trim to 40 chars.
501
            $page_title = trim_characters($info['text'], 0, 40);
502
        }
503
504
        if ($page_title != '') {
505
            // If page title has been set by now, it is good enough to display
506
            // in the open graph title tag, without the extra date info etc.
507
            $DATA->set_page_metadata($this_page, 'og_title', $page_title);
508
        }
509
510
        if (isset($info['date'])) {
511
            // debatesday and wransday pages.
512
            if ($page_title != '') {
513
                $page_title .= ': ';
514
            }
515
            $page_title .= format_date($info['date'], SHORTDATEFORMAT);
516
        }
517
518
        if ($page_title != '') {
519
            $DATA->set_page_metadata($this_page, 'title', $page_title);
520
        }
521
522
        if (isset($info['date'])) {
523
            // Set the page heading (displayed on the page).
524
            $page_heading = format_date($info['date'], LONGERDATEFORMAT);
525
            $DATA->set_page_metadata($this_page, 'heading', $page_heading);
526
        }
527
528
    }
529
530
    public function nextprevlinks() {
531
532
        // Generally called from $this->stripe_end();
533
534
        global $DATA, $this_page;
535
536
        // We'll put the html in these and print them out at the end of the function...
537
        $prevlink = '';
538
        $uplink = '';
539
        $nextlink = '';
540
541
        // This data is put in the metadata in hansardlist.php
542
        $nextprev = $DATA->page_metadata($this_page, 'nextprev');
543
        // $nextprev will have three arrays: 'prev', 'up' and 'next'.
544
        // Each should have a 'body', 'title' and 'url' element.
545
546
547
        // PREVIOUS ////////////////////////////////////////////////
548
549
        if (isset($nextprev['prev'])) {
550
551
            $prev = $nextprev['prev'];
552
553
            if (isset($prev['url'])) {
554
                $prevlink = '<a href="' . $prev['url'] . '" title="' . $prev['title'] . '" class="linkbutton">&laquo; ' . $prev['body'] . '</a>';
555
556
            } else {
557
                $prevlink = '&laquo; ' . $prev['body'];
558
            }
559
        }
560
561
        if ($prevlink != '') {
562
            $prevlink = '<span class="prev">' . $prevlink . '</span>';
563
        }
564
565
566
        // UP ////////////////////////////////////////////////
567
568
        if (isset($nextprev['up'])) {
569
570
            $uplink = '<span class="up"><a href="' . $nextprev['up']['url'] . '" title="' . $nextprev['up']['title'] . '">' . $nextprev['up']['body'] . '</a>';
571
            if (get_http_var('s')) {
572
                $URL = new \MySociety\TheyWorkForYou\Url($this_page);
573
                $uplink .= '<br><a href="' . $URL->generate() . '">' . gettext('Remove highlighting') . '</a>';
574
            }
575
            $uplink .= '</span>';
576
        }
577
578
579
        // NEXT ////////////////////////////////////////////////
580
581
        if (isset($nextprev['next'])) {
582
            $next = $nextprev['next'];
583
584
            if (isset($next['url'])) {
585
                $nextlink = '<a href="' . $next['url'] . '" title="' . $next['title'] . '" class="linkbutton">' . $next['body'] . ' &raquo;</a>';
586
            } else {
587
                $nextlink = $next['body'] . ' &raquo;';
588
            }
589
        }
590
591
        if ($nextlink != '') {
592
            $nextlink = '<span class="next">' . $nextlink . '</span>';
593
        }
594
595
596
        if ($uplink || $prevlink || $nextlink) {
597
            echo "<p class='nextprev'>$nextlink $prevlink $uplink</p><br class='clear'>";
598
        }
599
    }
600
601
602
    public function search_form($value = '') {
603
        global $SEARCHENGINE;
604
        // Search box on the search page.
605
        // If $value is set then it will be displayed in the form.
606
        // Otherwise the value of 's' in the URL will be displayed.
607
608
        $wtt = get_http_var('wtt');
609
610
        $URL = new \MySociety\TheyWorkForYou\Url('search');
611
        $URL->reset(); // no need to pass any query params as a form action. They are not used.
612
613
        if ($value == '') {
614
            if (get_http_var('q') !== '') {
615
                $value = get_http_var('q');
616
            } else {
617
                $value = get_http_var('s');
618
            }
619
        }
620
621
        $person_name = '';
622
        if (preg_match_all('#speaker:(\d+)#', $value, $m) == 1) {
623
            $person_id = $m[1][0];
624
            $member = new MEMBER(['person_id' => $person_id]);
625
            if ($member->valid) {
626
                $value = str_replace("speaker:$person_id", '', $value);
627
                $person_name = $member->full_name();
628
            }
629
        }
630
631
        echo '<div class="mainsearchbox">';
632
        if ($wtt < 2) {
633
            echo '<form action="', $URL->generate(), '" method="get">';
634
            if (get_http_var('o')) {
635
                echo '<input type="hidden" name="o" value="', _htmlentities(get_http_var('o')), '">';
636
            }
637
            if (get_http_var('house')) {
638
                echo '<input type="hidden" name="house" value="', _htmlentities(get_http_var('house')), '">';
639
            }
640
            echo '<input type="text" name="q" value="', _htmlentities($value), '" size="50"> ';
641
            echo '<input type="submit" value=" ', ($wtt ? gettext('Modify search') : gettext('Search')), ' ">';
642
            $URL = new \MySociety\TheyWorkForYou\Url('search');
643
            $URL->insert(['adv' => 1]);
644
            echo '&nbsp;&nbsp; <a href="' . $URL->generate() . '">' . gettext('More&nbsp;options') . '</a>';
645
            echo '<br>';
646
            if ($wtt) {
647
                print '<input type="hidden" name="wtt" value="1">';
648
            }
649
        } else { ?>
650
    <form action="https://www.writetothem.com/lords" method="get">
651
    <input type="hidden" name="pid" value="<?=_htmlentities(get_http_var('pid')) ?>">
652
    <input type="submit" style="font-size: 150%" value=" I want to write to this Lord "><br>
653
<?php
654
        }
655
656
        if (!$wtt && ($value || $person_name)) {
657
            echo '<div style="margin-top: 5px">';
658
            $orderUrl = new \MySociety\TheyWorkForYou\Url('search');
659
            $orderUrl->insert(['s' => $value]); # Need the parsed value
660
            $ordering = get_http_var('o');
661
            if ($ordering != 'r' && $ordering != 'd' && $ordering != 'p' && $ordering != 'o') {
662
                $ordering = 'd';
663
            }
664
665
            if ($ordering == 'r') {
666
                print '<strong>' . gettext('Sorted by relevance') . '</strong>';
667
            } else {
668
                printf(gettext("<a href='%s'>Sort by relevance</a>"), $orderUrl->generate('html', ['o' => 'r']));
669
            }
670
671
            print "&nbsp;|&nbsp;";
672
            if ($ordering == 'd') {
673
                print '<strong>' . gettext('Sorted by date:') . ' ' . gettext('newest') . '</strong> / <a href="' . $orderUrl->generate('html', ['o' => 'o']) . '">' . gettext('oldest') . '</a>';
674
            } elseif ($ordering == 'o') {
675
                print '<strong>' . gettext('Sorted by date:') . '</strong> <a href="' . $orderUrl->generate('html', ['o' => 'd']) . '">' . gettext('newest') . '</a> / <strong>' . gettext('oldest') . '</strong>';
676
            } else {
677
                print gettext("Sort by date:") . ' ';
678
                printf("<a href='%s'>", $orderUrl->generate('html', ['o' => 'd']));
679
                print gettext("newest");
680
                print '</a> / ';
681
                printf("<a href='%s'>", $orderUrl->generate('html', ['o' => 'o']));
682
                print gettext('oldest');
683
                print '</a>';
684
            }
685
686
            print "&nbsp;|&nbsp;";
687
            if ($ordering == 'p') {
688
                print '<strong>' . gettext('Use by person') . '</strong>';
689
            } else {
690
                printf('<a href="%s">', $orderUrl->generate('html', ['o' => 'p']));
691
                print gettext('Show use by person') . '</a>';
692
            }
693
            echo '</div>';
694
695
            if ($person_name) {
696
                ?>
697
                    <p>
698
                    <input type="radio" name="pid" value="<?php echo _htmlentities($person_id) ?>" checked><?= sprintf(gettext('Search only %s'), _htmlentities($person_name)) ?>
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $person_id does not seem to be defined for all execution paths leading up to this point.
Loading history...
699
                    <input type="radio" name="pid" value=""><?= gettext('Search all speeches') ?>
700
                    </p>
701
                <?php
702
            }
703
        }
704
705
        echo '</form> </div>';
706
    }
707
708
    public function login_form($errors = []) {
709
        // Used for /user/login/ and /user/prompt/
710
        // $errors is a hash of potential errors from a previous log in attempt.
711
        ?>
712
        <form method="post" action="<?php $URL = new \MySociety\TheyWorkForYou\Url('userlogin');
713
        $URL->reset();
714
        echo $URL->generate(); ?>" class="login-form">
715
716
<?php
717
        if (isset($errors["email"])) {
718
            $this->error_message($errors['email']);
719
        }
720
        if (isset($errors["invalidemail"])) {
721
            $this->error_message($errors['invalidemail']);
722
        }
723
        ?>
724
            <p>
725
                <label for="email"><?= gettext('Email address:') ?></label></span>
726
                <input type="text" name="email" id="email" value="<?php echo _htmlentities(get_http_var("email")); ?>" maxlength="100" class="form-control"></span>
727
            </p>
728
729
<?php
730
                if (isset($errors["password"])) {
731
                    $this->error_message($errors['password']);
732
                }
733
        if (isset($errors["invalidpassword"])) {
734
            $this->error_message($errors['invalidpassword']);
735
        }
736
        ?>
737
            <p>
738
                <label for="password"><?= gettext('Password:') ?></label>
739
                <input type="password" name="password" id="password" maxlength="30" class="form-control">
740
            </p>
741
742
            <p>
743
                <input type="checkbox" name="remember" id="remember" value="true"<?php
744
                $remember = get_http_var("remember");
745
        if (get_http_var("submitted") != "true" || $remember == "true") {
746
            print " checked";
747
        }
748
        ?>>
749
                <label for="remember" class="remember-label"><?= gettext('Keep me signed in on this device') ?></label>
750
            </p>
751
752
            <p>
753
                <input type="submit" value="<?= gettext('Sign in') ?>" class="button">
754
            </p>
755
756
            <input type="hidden" name="submitted" value="true">
757
<?php
758
        // I had to havk about with this a bit to cover glossary login.
759
        // Glossary returl can't be properly formatted until the "add" form
760
        // has been submitted, so we have to do this rubbish:
761
        global $glossary_returl;
762
        if ((get_http_var("ret") != "") || ($glossary_returl != "")) {
763
            // The return url for after the user has logged in.
764
            if (get_http_var("ret") != "") {
765
                $returl = get_http_var("ret");
766
            } else {
767
                $returl = $glossary_returl;
768
            }
769
            ?>
770
            <input type="hidden" name="ret" value="<?php echo _htmlentities($returl); ?>">
771
<?php
772
        }
773
        ?>
774
775
            <p>
776
                <?= gettext('Forgotten your password?') ?>
777
                <a href="<?php
778
                    $URL = new \MySociety\TheyWorkForYou\Url("userpassword");
779
        $URL->insert(["email" => get_http_var("email")]);
780
        echo $URL->generate();
781
        ?>"><?= gettext('Set a new one!') ?></a>
782
            </p>
783
784
            <p>
785
                <?= gettext('Not yet a member?') ?>
786
                <a href="<?php $URL = new \MySociety\TheyWorkForYou\Url("userjoin");
787
        echo $URL->generate(); ?>"><?= gettext('Join now!') ?></a>
788
            </p>
789
790
        </form>
791
<?php
792
    }
793
794
    public function mp_search_form($person_id) {
795
        // Search box on the MP page.
796
797
        $URL = new \MySociety\TheyWorkForYou\Url('search');
798
        $URL->remove(['s', 'q']);
799
        ?>
800
                <div class="mpsearchbox">
801
                    <form action="<?php echo $URL->generate(); ?>" method="get">
802
                    <p>
803
                    <input name="q" size="12">
804
                    <input type="hidden" name="pid" value="<?=$person_id ?>">
805
                    <input type="submit" class="submit" value="<?= gettext('GO') ?>"></p>
806
                    </form>
807
                </div>
808
<?php
809
    }
810
811
    public function glossary_atoz(&$GLOSSARY) {
812
        // Print out a nice list of lettered links to glossary pages
813
814
        $letters =  [];
815
816
        foreach ($GLOSSARY->alphabet as $letter => $eps) {
817
            // if we're writing out the current letter (list or item)
818
            if ($letter == $GLOSSARY->current_letter) {
819
                // if we're in item view - show the letter as "on" but make it a link
820
                if ($GLOSSARY->current_term != '') {
821
                    $URL = new \MySociety\TheyWorkForYou\Url('glossary');
822
                    $URL->insert(['az' => $letter]);
823
                    $letter_link = $URL->generate('url');
824
825
                    $letters[] = "<li class=\"on\"><a href=\"" . $letter_link . "\">" . $letter . "</a></li>";
826
                }
827
                // otherwise in list view show no link
828
                else {
829
                    $letters[] = "<li class=\"on\">" . $letter . "</li>";
830
                }
831
            } elseif (!empty($GLOSSARY->alphabet[$letter])) {
832
                $URL = new \MySociety\TheyWorkForYou\Url('glossary');
833
                $URL->insert(['az' => $letter]);
834
                $letter_link = $URL->generate('url');
835
836
                $letters[] = "<li><a href=\"" . $letter_link . "\">" . $letter . "</a></li>";
837
            } else {
838
                $letters[] = '<li>' . $letter . '</li>';
839
            }
840
        }
841
        ?>
842
                    <div class="letters">
843
                        <ul>
844
    <?php
845
        for ($n = 0; $n < 13; $n++) {
846
            print $letters[$n];
847
        }
848
        ?>
849
                        </ul>
850
                        <ul>
851
    <?php
852
        for ($n = 13; $n < 26; $n++) {
853
            print $letters[$n];
854
        }
855
        ?>
856
                        </ul>
857
                    </div>
858
        <?php
859
    }
860
861
    public function glossary_display_term(&$GLOSSARY) {
862
        // Display a single glossary term
863
        global $this_page;
864
865
        $term = $GLOSSARY->current_term;
866
867
        $term['body'] = $GLOSSARY->glossarise($term['body'], 0, 1);
868
869
        // add some extra controls for the administrators
870
        if ($this_page == "admin_glossary") {
871
            print "<a id=\"gl" . $term['glossary_id'] . "\"></a>";
872
            print "<h3>" . $term['title'] . "</h3>";
873
            $URL = new \MySociety\TheyWorkForYou\Url('admin_glossary');
874
            $URL->insert(["delete_confirm" => $term['glossary_id']]);
875
            $delete_url = $URL->generate();
876
            $admin_links = "<br><small><a href=\"" . $delete_url . "\">delete</a></small>";
877
        } else {
878
            $admin_links = "";
879
        }
880
881
        if (isset($term['user_id'])) {
882
            $URL = new \MySociety\TheyWorkForYou\Url('userview');
883
            $URL->insert(['u' => $term['user_id']]);
884
            $user_link = $URL->generate('url');
885
886
            $user_details = "\t\t\t\t<p><small>contributed by user <a href=\"" . $user_link . "\">" . $term['firstname'] . " " . $term['lastname'] . "</a></small>" . $admin_links . "</p>\n";
887
        } else {
888
            $user_details = "";
889
        }
890
891
        print "\t\t\t\t<p class=\"glossary-body\">" . $term['body'] . "</p>\n" . $user_details;
892
893
        if ($this_page == "glossary_item") {
894
            // Add a direct search link for current glossary item
895
            $URL = new \MySociety\TheyWorkForYou\Url('search');
896
            // remember to quote the term for phrase matching in search
897
            $URL->insert(['s' => '"' . $term['title'] . '"']);
898
            $search_url = $URL->generate();
899
            printf("\t\t\t\t<p>Search hansard for \"<a href=\"%s\" title=\"View search results for this glossary item\">%s</a>\"</p>", $search_url, $term['title']);
900
        }
901
    }
902
903
    public function glossary_display_match_list(&$GLOSSARY) {
904
        if ($GLOSSARY->num_search_matches > 1) {
905
            $plural = "them";
906
            $definition = "some definitions";
907
        } else {
908
            $plural = "it";
909
            $definition = "a definition";
910
        }
911
        ?>
912
            <h4>Found <?php echo $GLOSSARY->num_search_matches; ?> matches for <em><?php echo $GLOSSARY->query; ?></em></h4>
913
            <p>It seems we already have <?php echo $definition; ?> for that. Would you care to see <?php echo $plural; ?>?</p>
914
            <ul class="glossary"><?php
915
        foreach ($GLOSSARY->search_matches as $match) {
916
            $URL = new \MySociety\TheyWorkForYou\Url('glossary');
917
            $URL->insert(['gl' => $match['glossary_id']]);
918
            $URL->remove(['g']);
919
            $term_link = $URL->generate('url');
920
            ?><li><a href="<?php echo $term_link ?>"><?php echo $match['title']?></a></li><?php
921
        }
922
        ?></ul>
923
<?php
924
    }
925
926
    public function glossary_link() {
927
        // link to the glossary with no epobject_id - i.e. show all entries
928
        $URL = new \MySociety\TheyWorkForYou\Url('glossary');
929
        $URL->remove(["g"]);
930
        $glossary_link = $URL->generate('url');
931
        print "<small><a href=\"" . $glossary_link . "\">Browse the glossary</a></small>";
932
    }
933
934
    public function glossary_links() {
935
        print "<div>";
936
        $this->glossary_link();
937
        print "</div>";
938
    }
939
940
    public function page_links($pagedata) {
941
        // The next/prev and page links for the search page.
942
        global $this_page;
943
944
        // $pagedata has...
945
        $total_results      = $pagedata['total_results'];
946
        $results_per_page   = $pagedata['results_per_page'];
947
        $page               = $pagedata['page'];
948
949
        if ($total_results > $results_per_page) {
950
951
            $numpages = ceil($total_results / $results_per_page);
952
953
            $pagelinks = [];
954
955
            // How many links are we going to display on the page - don't want to
956
            // display all of them if we have 100s...
957
            if ($page < 10) {
958
                $firstpage = 1;
959
                $lastpage = 10;
960
            } else {
961
                $firstpage = $page - 10;
962
                $lastpage = $page + 9;
963
            }
964
965
            if ($firstpage < 1) {
966
                $firstpage = 1;
967
            }
968
            if ($lastpage > $numpages) {
969
                $lastpage = $numpages;
970
            }
971
972
            // Generate all the page links.
973
            $URL = new \MySociety\TheyWorkForYou\Url($this_page);
974
            $URL->insert(['wtt' => get_http_var('wtt')]);
975
            if (isset($pagedata['s'])) {
976
                # XXX: Should be taken out in *one* place, not here + search_form etc.
977
                $value = $pagedata['s'];
978
                if (preg_match_all('#speaker:(\d+)#', $value, $m) == 1) {
979
                    $person_id = $m[1][0];
980
                    $value = str_replace('speaker:' . $person_id, '', $value);
981
                    $URL->insert(['pid' => $person_id]);
982
                }
983
                $URL->insert(['s' => $value]);
984
            }
985
986
            for ($n = $firstpage; $n <= $lastpage; $n++) {
987
988
                if ($n > 1) {
989
                    $URL->insert(['p' => $n]);
990
                } else {
991
                    // No page number for the first page.
992
                    $URL->remove(['p']);
993
                }
994
                if (isset($pagedata['pid'])) {
995
                    $URL->insert(['pid' => $pagedata['pid']]);
996
                }
997
998
                if ($n != $page) {
999
                    $pagelinks[] = '<a href="' . $URL->generate() . '">' . $n . '</a>';
1000
                } else {
1001
                    $pagelinks[] = "<strong>$n</strong>";
1002
                }
1003
            }
1004
1005
            // Display everything.
1006
1007
            ?>
1008
                <div class="pagelinks">
1009
                    <?= gettext('Result page:') ?>
1010
<?php
1011
1012
            if ($page != 1) {
1013
                $prevpage = $page - 1;
1014
                $URL->insert(['p' => $prevpage]);
1015
                ?>
1016
                    <big><strong><a href="<?php echo $URL->generate(); ?>"><big>&laquo;</big> <?=gettext('Previous') ?></a></strong></big>
1017
<?php
1018
            }
1019
1020
            echo "\t\t\t\t" . implode(' ', $pagelinks);
1021
1022
            if ($page != $numpages) {
1023
                $nextpage = $page + 1;
1024
                $URL->insert(['p' => $nextpage]);
1025
                ?>
1026
1027
                    <big><strong><a href="<?php echo $URL->generate(); ?>"><?= gettext('Next') ?> <big>&raquo;</big></a></strong></big> <?php
1028
            }
1029
1030
            ?>
1031
1032
                </div>
1033
<?php
1034
1035
        }
1036
1037
    }
1038
1039
    public function display_commentreport($data) {
1040
        // $data has key value pairs.
1041
        // Called from $COMMENT->display_report().
1042
1043
        if ($data['user_id'] > 0) {
1044
            $USERURL = new \MySociety\TheyWorkForYou\Url('userview');
1045
            $USERURL->insert(['id' => $data['user_id']]);
1046
            $username = '<a href="' . $USERURL->generate() . '">' . _htmlentities($data['user_name']) . '</a>';
1047
        } else {
1048
            $username = _htmlentities($data['user_name']);
1049
        }
1050
        ?>
1051
                <div class="comment">
1052
                    <p class="credit"><strong>Annotation report</strong><br>
1053
                    <small>Reported by <?php echo $username; ?> on <?php echo $data['reported']; ?></small></p>
1054
1055
                    <p><?php echo _htmlentities($data['body']); ?></p>
1056
                </div>
1057
<?php
1058
        if ($data['resolved'] != 'NULL') {
1059
            ?>
1060
                <p>&nbsp;<br><em>This report has not been resolved.</em></p>
1061
<?php
1062
        } else {
1063
            ?>
1064
                <p><em>This report was resolved on <?php echo $data['resolved']; ?></em></p>
1065
<?php
1066
            // We could link to the person who resolved it with $data['resolvedby'],
1067
            // a user_id. But we don't have their name at the moment.
1068
        }
1069
1070
    }
1071
1072
1073
    public function display_commentreportlist($data) {
1074
        // For the admin section.
1075
        // Gets an array of data from COMMENTLIST->render().
1076
        // Passes it on to $this->display_table().
1077
1078
        if (count($data) > 0) {
1079
1080
            ?>
1081
            <h3>Reported annotations</h3>
1082
<?php
1083
            // Put the data in an array which we then display using $PAGE->display_table().
1084
            $tabledata['header'] = [
0 ignored issues
show
Comprehensibility Best Practice introduced by
$tabledata was never initialized. Although not strictly required by PHP, it is generally a good practice to add $tabledata = array(); before regardless.
Loading history...
1085
                'Reported by',
1086
                'Begins...',
1087
                'Reported on',
1088
                '',
1089
            ];
1090
1091
            $tabledata['rows'] = [];
1092
1093
            $EDITURL = new \MySociety\TheyWorkForYou\Url('admin_commentreport');
1094
1095
            foreach ($data as $n => $report) {
1096
1097
                if (!$report['locked']) {
1098
                    // Yes, we could probably cope if we just passed the report_id
1099
                    // through, but this isn't a public-facing page and life's
1100
                    // easier if we have the comment_id too.
1101
                    $EDITURL->insert([
1102
                        'rid' => $report['report_id'],
1103
                        'cid' => $report['comment_id'],
1104
                    ]);
1105
                    $editlink = '<a href="' . $EDITURL->generate() . '">View</a>';
1106
                } else {
1107
                    $editlink = 'Locked';
1108
                }
1109
1110
                $body = trim_characters($report['body'], 0, 40);
1111
1112
                $tabledata['rows'][] =  [
1113
                    _htmlentities($report['firstname'] . ' ' . $report['lastname']),
1114
                    _htmlentities($body),
1115
                    $report['reported'],
1116
                    $editlink,
1117
                ];
1118
1119
            }
1120
1121
            $this->display_table($tabledata);
1122
1123
        } else {
1124
1125
            print "<p>There are no outstanding annotation reports.</p>\n";
1126
        }
1127
1128
    }
1129
1130
    public function display_table($data) {
1131
        /* Pass it data to be displayed in a <table> and it renders it
1132
            with stripes.
1133
1134
        $data is like (for example):
1135
        array (
1136
            'header' => array (
1137
                'ID',
1138
                'name'
1139
            ),
1140
            'rows' => array (
1141
                array (
1142
                    '37',
1143
                    'Guy Fawkes'
1144
                ),
1145
                etc...
1146
            )
1147
        )
1148
        */
1149
1150
        ?>
1151
    <table border="1" cellpadding="3" cellspacing="0" width="90%">
1152
<?php
1153
        if (isset($data['header']) && count($data['header'])) {
1154
            ?>
1155
    <thead>
1156
    <tr><?php
1157
            foreach ($data['header'] as $text) {
1158
                ?><th><?php echo $text; ?></th><?php
1159
            }
1160
            ?></tr>
1161
    </thead>
1162
<?php
1163
        }
1164
1165
        if (isset($data['rows']) && count($data['rows'])) {
1166
            ?>
1167
    <tbody>
1168
<?php
1169
            foreach ($data['rows'] as $row) {
1170
                ?>
1171
    <tr><?php
1172
                foreach ($row as $text) {
1173
                    ?><td><?php echo $text; ?></td><?php
1174
                }
1175
                ?></tr>
1176
<?php
1177
            }
1178
            ?>
1179
    </tbody>
1180
<?php
1181
        }
1182
        ?>
1183
    </table>
1184
<?php
1185
1186
    }
1187
1188
1189
1190
    public function admin_menu() {
1191
        // Returns HTML suitable for putting in the sidebar on Admin pages.
1192
        global $this_page, $DATA;
1193
1194
        $pages =  ['admin_home',
1195
            'admin_comments', 'admin_searchlogs', 'admin_popularsearches', 'admin_failedsearches',
1196
            'alert_stats', 'admin_statistics', 'admin_reportstats',
1197
            'admin_commentreports', 'admin_glossary', 'admin_glossary_pending', 'admin_badusers',
1198
            'admin_profile_message', 'admin_photos', 'admin_mpurls', 'admin_policies', 'admin_banner', 'admin_announcement','admin_featured', 'admin_topics',
1199
            'admin_wikipedia',
1200
        ];
1201
1202
        $links = [];
1203
1204
        foreach ($pages as $page) {
1205
            $title = $DATA->page_metadata($page, 'title');
1206
1207
            if ($page != $this_page) {
1208
                $URL = new \MySociety\TheyWorkForYou\Url($page);
1209
                $title = '<a href="' . $URL->generate() . '">' . $title . '</a>';
1210
            } else {
1211
                $title = '<strong>' . $title . '</strong>';
1212
            }
1213
1214
            $links[] = $title;
1215
        }
1216
1217
        $html = "<ul>\n";
1218
1219
        $html .= "<li>" . implode("</li>\n<li>", $links) . "</li>\n";
1220
1221
        $html .= "</ul>\n";
1222
1223
        return $html;
1224
    }
1225
}
1226
1227
$PAGE = new PAGE();
1228