1<?php 2/** 3 * Archive Plugin: displays links to all wiki pages from a given month 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author Esther Brunner <wikidesign@gmail.com> 7 */ 8 9/** 10 * All DokuWiki plugins to extend the parser/rendering mechanism 11 * need to inherit from this class 12 */ 13class syntax_plugin_blog_archive extends DokuWiki_Syntax_Plugin { 14 15 function getType() { return 'substition'; } 16 function getPType() { return 'block'; } 17 function getSort() { return 309; } 18 19 function connectTo($mode) { 20 $this->Lexer->addSpecialPattern('\{\{archive>.*?\}\}', $mode, 'plugin_blog_archive'); 21 } 22 23 function handle($match, $state, $pos, Doku_Handler $handler) { 24 global $ID; 25 26 $match = substr($match, 10, -2); // strip {{archive> from start and }} from end 27 list($match, $flags) = explode('&', $match, 2); 28 $flags = explode('&', $flags); 29 list($match, $refine) = explode(' ', $match, 2); 30 list($ns, $rest) = explode('?', $match, 2); 31 32 $author = NULL; 33 foreach($flags as $i=>$flag) { 34 if(preg_match('/(\w+)\s*=(.+)/', $flag, $temp) == 1) { 35 if ($temp[1] == 'author') { 36 $author = trim($temp[2]); 37 unset($flags[$i]); 38 } 39 } 40 } 41 42 if (!$rest) { 43 $rest = $ns; 44 $ns = ''; 45 } 46 47 if ($ns == '') $ns = cleanID($this->getConf('namespace')); 48 elseif (($ns == '*') || ($ns == ':')) $ns = ''; 49 elseif ($ns == '.') $ns = getNS($ID); 50 else $ns = cleanID($ns); 51 52 // daily archive 53 if (preg_match("/\d{4}-\d{2}-\d{2}/", $rest)) { 54 list($year, $month, $day) = explode('-', $rest, 3); 55 56 $start = mktime(0, 0, 0, $month, $day, $year); 57 $end = $start + 24*60*60; 58 59 // monthly archive 60 } elseif (preg_match("/\d{4}-\d{2}/", $rest)) { 61 list($year, $month) = explode('-', $rest, 2); 62 63 // calculate start and end times 64 $nextmonth = $month + 1; 65 $year2 = $year; 66 if ($nextmonth > 12) { 67 $nextmonth = 1; 68 $year2 = $year + 1; 69 } 70 71 $start = mktime(0, 0, 0, $month, 1, $year); 72 $end = mktime(0, 0, 0, $nextmonth, 1, $year2); 73 74 // a whole year 75 } elseif (preg_match("/\d{4}/", $rest)) { 76 $start = mktime(0, 0, 0, 1, 1, $rest); 77 $end = mktime(0, 0, 0, 1, 1, $rest + 1); 78 79 // all entries from that namespace up to now 80 } elseif ($rest == '*') { 81 $start = 0; 82 $end = PHP_INT_MAX; 83 84 // unknown format 85 } else { 86 return false; 87 } 88 89 return array($ns, $start, $end, $flags, $refine, $author); 90 } 91 92 function render($mode, Doku_Renderer $renderer, $data) { 93 list($ns, $start, $end, $flags, $refine, $author) = $data; 94 95 // get the blog entries for our namespace 96 /** @var helper_plugin_blog $my */ 97 if ($my = plugin_load('helper', 'blog')) $entries = $my->getBlog($ns, NULL, $author); 98 else return false; 99 100 // use tag refinements? 101 if ($refine) { 102 /** @var helper_plugin_tag $tag */ 103 if (plugin_isdisabled('tag') || (!$tag = plugin_load('helper', 'tag'))) { 104 msg($this->getLang('missing_tagplugin'), -1); 105 } else { 106 $entries = $tag->tagRefine($entries, $refine); 107 } 108 } 109 110 if (!$entries) return true; // nothing to display 111 112 if ($mode == 'xhtml') { 113 if ($this->getConf('showhistogram')) { 114 $alt_list = $this->_build_alternative_list($start, $end, $entries); 115 116 // Add histogram and posts list 117 $renderer->doc .= '<div class="level1">'; 118 $renderer->doc .= '<h1>' . $this->getLang('archive_title') . '</h1>'; 119 $renderer->doc .= $alt_list; 120 $renderer->doc .= '</div>' . DOKU_LF; 121 } else { 122 // let Pagelist Plugin do the work for us 123 if (plugin_isdisabled('pagelist') 124 || (!$pagelist = plugin_load('helper', 'pagelist'))) { 125 msg($this->getLang('missing_pagelistplugin'), -1); 126 return false; 127 } 128 /** @var helper_plugin_pagelist $pagelist */ 129 $pagelist->setFlags($flags); 130 $pagelist->startList(); 131 foreach ($entries as $entry) { 132 133 // entry in the right date range? 134 if (($start > $entry['date']) || ($entry['date'] >= $end)) continue; 135 136 $pagelist->addPage($entry); 137 } 138 $renderer->doc .= $pagelist->finishList(); 139 } 140 return true; 141 142 // for metadata renderer 143 } elseif ($mode == 'metadata') { 144 /** @var Doku_Renderer_metadata $renderer */ 145 // use the blog plugin cache handler in order to ensure that the cache is expired whenever a page, comment 146 // or linkback is added 147 if (time() < $end) $renderer->meta['plugin_blog']['purgefile_cache'] = true; 148 149 foreach ($entries as $entry) { 150 151 // entry in the right date range? 152 if (($start > $entry['date']) || ($entry['date'] >= $end)) continue; 153 154 $renderer->meta['relation']['references'][$entry['id']] = true; 155 $renderer->meta['plugin_blog']['archive_pages'][] = $entry['id']; 156 } 157 158 return true; 159 } 160 return false; 161 } 162 163 // Generate alternative posts list 164 function _build_alternative_list($start, $end, $entries) { 165 $current_year =''; 166 $current_month =''; 167 $ul_open = false; 168 169 $histogram_count = array(); 170 $histogram_higher = 0; 171 172 $list = ''; 173 foreach ($entries as $entry) { 174 // entry in the right date range? 175 if (($start > $entry['date']) || ($entry['date'] >= $end)) continue; 176 177 if ($current_year != date('o',$entry['date'])) { 178 if ($ul_open) { 179 $list .= '</ul>' . DOKU_LF; 180 $ul_open = false; 181 } 182 $current_year = date('o',$entry['date']); 183 $list .= '<h2>' . $current_year . '</h2>' . DOKU_LF; 184 $current_month = ''; 185 } 186 if ($current_month != date('m',$entry['date'])) { 187 if ($ul_open) { 188 $list .= '</ul>' . DOKU_LF; 189 } 190 $current_month = date('m',$entry['date']); 191 $list .= '<h3 id="m' . date('o-m',$entry['date']) . '">' . $this->getLang('month_' . $current_month) . '</h3><ul>' . DOKU_LF; 192 $ul_open = true; 193 } 194 $histogram_count[date('o-m',$entry['date'])] += 1; 195 if ($histogram_higher < $histogram_count[date('o-m',$entry['date'])]) { 196 $histogram_higher = $histogram_count[date('o-m',$entry['date'])]; 197 } 198 $list .= '<li>' . date('d',$entry['date']) . ' - <a href="' . wl($entry['id']) . '" title="' . $entry['id'] . '">' . $entry['title'] . '</a></li>' . DOKU_LF; 199 } 200 $list .= '</ul>' . DOKU_LF; 201 202 $histogram = $this->_build_histogram($histogram_count, $histogram_higher); 203 204 return $histogram . $list; 205 } 206 207 // Generate histogram 208 function _build_histogram($histogram_count, $histogram_higher) { 209 if (empty($histogram_count)) return ''; 210 211 $histogram = '<p>'; 212 $max_months = $this->getConf('max_months'); 213 $histogram_height = $this->getConf('histogram_height'); 214 $histogram_count = array_reverse($histogram_count); 215 $month_count = 0; 216 foreach ($histogram_count as $key => $month_reference) { 217 // Check the max_months parameter 218 if ($month_count >= $max_months) { 219 break; 220 } 221 if ($month_reference > 0) { 222 // Height in "px" 223 $current_height = $histogram_height / $histogram_higher * $month_reference; 224 } else { 225 // Height in "px" 226 $current_height = 1; 227 } 228 // Generate the alt attribute 229 $alt = $key.': '.$month_reference.' '; 230 if ($month_reference > 1) { 231 $alt .= $this->getLang('entries'); 232 } else { 233 $alt .= $this->getLang('entry'); 234 } 235 $histogram .= '<a href="#m' . $key . '" title="' . $alt . '">'; 236 $histogram .= '<img class="blog_archive_bar" alt="' . $alt . '" style="height: ' . $current_height . 'px;" src="'.DOKU_BASE.'lib/images/blank.gif"/></a>' . DOKU_LF; 237 $month_count += 1; 238 } 239 $histogram .= '</p>'; 240 241 return $histogram; 242 } 243 244} 245// vim:ts=4:sw=4:et:enc=utf-8: 246