1<?php
2/**
3 * DokuWiki Plugin currentlyreading (Syntax Component)
4 *
5 * Displays a "Currently Reading" box with an image of the book cover and a link to the page.
6 * The image is pulled from the first image of the page and it is assumed that the page is about the story.
7 *
8 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
9 * @author  Charles Fewlass <fewlass@suddenlink.net>
10 */
11
12// must be run within DokuWiki
13if(!defined('DOKU_INC')) die();
14
15/**
16 * Class syntax_plugin_currentlyreading
17 */
18class syntax_plugin_currentlyreading extends \dokuwiki\Extension\SyntaxPlugin {
19    public function getType() { return 'substition'; }
20    public function getSort() { return 302; }
21    public function getPType(){ return 'block'; }
22
23    /**
24     * regex pattern for lexer to seek
25     */
26    public function connectTo($mode) {
27        // Looking to match {{reading>[pageid]}}
28        $pattern = '\{\{reading\b>[[:blank:]]??[[:alnum:]]{1}(?:[[:alnum:]]|[[:blank:]]|\.|,|-|_|:)+?[[:alnum:]]{1}(?:\?[0-9]+?)*?[[:blank:]]??\}\}';
29        $this->Lexer->addSpecialPattern($pattern, $mode, 'plugin_currentlyreading');
30    }
31
32    /**
33     * handle matches from lexer
34     *
35     * @param   string  $match  Match from lexer
36     * @return  string  $html   HTML string to render
37     */
38    public function handle($match, $state, $pos, Doku_Handler $handler) {
39        // Let's get the $pagename through its first phase.
40        $pagename = substr($match, 10, -2); // Remove the markup to reveal the pagename.
41        $pagename = hsc($pagename); // Clean up html entities.
42        $pagename = preg_replace('/\s\s+/', ' ', $pagename); // Eliminate excessive spaces to single space, but keep leading and trailing.
43
44        // What is the float?
45        $left = $right = $center = false;
46        if (substr($pagename, 0, 1) == ' ') $left = true;
47        if (substr($pagename, -1, 1) == ' ') $right = true;
48        if (($left == false) && ($right == false)) {
49            $float = '';
50        } elseif ($left && $right) {
51            $float = ' mediacenter';
52        } else {
53            if ($left) $float = ' mediaright';
54            if ($right) $float = ' medialeft';
55        }
56
57        // What will be the width?
58        $width = null;
59        if ($spos = strpos($pagename, '?')) {
60            $width = intval(substr($pagename, $spos+1)); // The user specified a width in the markup.
61            $pagename = substr($pagename, 0, -(strlen($pagename)-$spos)); // Strip the width declaration off of the $pagename.
62        } else {
63            $width = $this->getConf('width'); // Get the width from the configuration settings.
64        }
65
66        // $pagename's second phase: create a pagename ID that we can look up.
67        $title = trim($pagename); // Save the original for a possible $title.
68        $pagename = trim($pagename);
69        $pagename = strtolower($pagename);
70        $pagename = strtr($pagename, ' ', '');
71
72        // Enquiring minds want to know: does the page exist?
73        $pageexists = false;
74        if (page_exists($pagename)) $pageexists = true;
75
76        // Is there a preferred title from a wiki page or do we use the input.
77        if ($pageexists) {
78            $title = p_get_metadata($pagename, 'title', METADATA_DONT_RENDER);
79        } else {
80            $title = strtr(noNS($title), '_', ' ');
81        }
82
83        // Create the link.
84        $link = wl($pagename);
85
86        // Get the image if it exists and create the image tag.
87        $image = (p_get_metadata($pagename, 'relation firstimage', METADATA_DONT_RENDER));
88
89        if ($image) {
90            $imagetag = '<img class="plugin_currentlyreading" style="max-width: '.$width.'px;" src="'.ml($image).'" alt="'.$title.'" />';
91        } else {
92            $imagetag = null;
93        }
94
95        // What heading to use?
96        if ($this->getConf('alternative')) { // Use an alternative heading from the config settings or from the language files.
97            $heading = hsc($this->getConf('alternative'));
98        } else $heading = $this->getLang('currentlyreading');
99
100        // Putting HTML altogether.
101        $html = '<div class="plugin_currentlyreading'.$float.'" style="max-width: '.$width.'px;"><span class="plugin_currentlyreading">'.$heading.'</span><br />'.
102                '<a class="plugin_currentlyreading" href="'.$link.'">'.$title.'</a><br />'.
103                $imagetag.'</div>';
104
105        return $html;
106    }
107
108    /**
109     * Renders $html
110     *
111     * @param   string   $html   HTML to render
112     * @return  boolean
113     */
114    public function render($mode, Doku_Renderer $renderer, $html) {
115        if ($html === false) return false;
116        if ($mode !== 'xhtml') return false;
117
118        $renderer->doc .= $html;
119
120        return true;
121    }
122}
123