1<?php
2/**
3 * Songlist Plugin: Extract and generate a list of songs from a given page, the songs are indexed by IDs.
4 *
5 * Syntax:     <songlist {src=]page>
6 *   src    the page that contains the lines of the form
7 *          text to be inserted on a line|ID
8 *
9 * @license    GPL v2+ (http://www.gnu.org/licenses/gpl.html)
10 * @author     Reinhold Kainhofer <reinhold@kainhofer.com>
11 */
12
13if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../../').'/');
14if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
15require_once(DOKU_PLUGIN.'syntax.php');
16
17/**
18 * All DokuWiki plugins to extend the parser/rendering mechanism
19 * need to inherit from this class
20 */
21class syntax_plugin_songlist extends DokuWiki_Syntax_Plugin {
22    /**
23     * return some info
24     */
25    function getInfo(){
26      return array(
27        'author' => 'Reinhold Kainhofer',
28        'email'  => 'reinhold@kainhofer.com',
29        'date'   => '2008-09-03',
30        'name'   => 'Songlist Plugin',
31        'desc'   => 'Automatically generate a list with lines taken from a master page. Each song is identified by an ID.
32                     Syntax: <songlist src=pagename>',
33        'url'    => 'http://wiki.splitbrain.org/plugin:songlist',
34      );
35    }
36
37    function getType(){ return 'substition';}
38    function getAllowedTypes() { return array('container','substition','protected','disabled','formatting','paragraphs'); }
39    function getPType(){ return 'block';}
40
41    function getSort(){ return 999; }
42
43    /** Connect pattern to lexer */
44    function connectTo($mode) {
45        $this->Lexer->addSpecialPattern('<songlist\s*.*?>.*?</songlist.*?>',$mode,'plugin_songlist');
46    }
47
48    function normalize_id($id) {
49      return preg_replace("/[,'!?.\ ]/", "", strtolower ($id) );
50    }
51
52    /**
53     * Handle the match
54     */
55    function handle($match, $state, $pos, &$handler){
56        //
57        global $entrymap;
58        //
59        switch ($state) {
60            case DOKU_LEXER_SPECIAL:
61                if ( preg_match( "/^<songlist\s*(?:src=|)\"?([^ ]*?)\"?\s*>/", $match, $matches ) ) {
62                  $filename=$matches[1];
63                  $entrymap = $this->readPatternFile( $filename, $entrymap );
64                }
65                $data = $match;
66                $data = preg_replace( ":\</?songlist.*?\>:", "", $data );
67                $line = strtok( $data, "\n" );
68                while ($line !== false ) {
69                  $id = $this->normalize_id ($line);
70                  if ( $entrymap[$id] ) {
71                    $result .= $entrymap[$id]."\n";
72                  } else {
73                    $result .= $line."\n";
74                  }
75                  $line = strtok( "\n" );
76                }
77                return array( $state, $result );
78                break;
79        }
80        return false;
81    }
82
83    /**
84     * Create output
85     */
86    function render($mode, &$renderer, $indata) {
87      //
88      if($mode == 'xhtml'){
89          list($instr, $data) = $indata;
90          switch ($instr) {
91          case DOKU_LEXER_SPECIAL:
92              $renderer->doc .= p_render( 'xhtml', p_get_instructions($data), $info );
93              break;
94        }
95        return true;
96      }
97      return false;
98    }
99
100    function readPatternFile( $pagename, $tmp )
101    {
102      $replacements = $tmp;
103      $pages = array( $pagename );
104      $loadedPages = array();
105      foreach( $pages as $page )
106      {
107        $page = cleanID( $page );
108        //
109        // don't read in pages that were already read
110        if( in_array( $page, $loadedPages ) ) continue;
111        $loadedPages[] = $page;
112        //
113        // Only use pages that the user is allowed to read
114        if ( auth_quickaclcheck( $page ) < AUTH_READ ) continue;
115        //
116        // get the actual filename and load it into the array
117        $filename = wikiFN( $page );
118        if( !file_exists( $filename ) ) continue;
119        //
120        // Read all lines from the file and parse them
121        $handle = fopen ( $filename, "r" );
122        while ( !feof($handle) ) {
123          $buffer = fgets( $handle, 4096 );
124          if ( preg_match( "/^(.*)\|([-a-zA-Z0-9_ ,!?ßäöüÄÖÜ']+)\n?$/", $buffer, $matches ) ) {
125            $id = $this->normalize_id ($matches[2]);
126            $replacements[$id] = $matches[1];
127          }
128        }
129      }
130      return $replacements;
131    }
132}
133