1<?php 2/** 3 * Download Counter Action Plugin 4 * 5 * @license GPLv3 (http://www.gnu.org/licenses/gpl.html) 6 * @link http://www.dokuwiki.org/plugin:dlcount 7 * @author Markus Birth <markus@birth-online.de> 8 */ 9 10if(!defined('DOKU_INC')) die(); 11if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 12require_once(DOKU_PLUGIN.'admin.php'); 13 14class admin_plugin_dlcount extends DokuWiki_Admin_Plugin { 15 16 const DATADIR = '_media'; // below $conf['metadir'], no trailing slash 17 const SUFFIX = '.meta'; 18 19 /** 20 * return some info 21 */ 22 function getInfo(){ 23 return confToHash(dirname(__FILE__).'/INFO.txt'); 24 } 25 26 /** 27 * return true if the plugin should only be accessed by wiki admins (default: true) 28 */ 29// function forAdminOnly() { 30// return true; 31// } 32 33 /** 34 * return the menu string to be displayed in the main admin menu 35 */ 36// function getMenuText($language) { 37// return 'dlcount'; 38// } 39 40 /** 41 * return sort order for position in admin menu 42 */ 43// function getMenuSort() { 44// return 999; 45// } 46 47 function glob_recursive($mask) { 48 $result = glob($mask); 49 if ($result === false) return array(); 50 $dirs = explode(DIRECTORY_SEPARATOR, $mask); 51 $dirmask = array_pop($dirs); 52 $dirs = glob(implode(DIRECTORY_SEPARATOR, $dirs) . '/*', GLOB_ONLYDIR); 53 if ($dirs === false) return $result; 54 foreach ($dirs as $dir) { 55 $partresult = $this->glob_recursive($dir . '/' . $dirmask); 56 $result = array_merge($result, $partresult); 57 } 58 return $result; 59 } 60 61 /** 62 * handle user request 63 */ 64 function handle() { 65 global $conf; 66 $mediametadir = $conf['metadir'] . '/' . self::DATADIR; 67 $this->mediafiles = $this->glob_recursive($conf['mediadir'] . '/*.*'); 68 $this->dlcount = array(); 69 $this->lastdl = array(); 70 foreach ($this->mediafiles as $idx=>$mediafile) { 71 list ($ext, $mime, $dl) = mimetype($mediafile); 72 // skip images as their downloads are NOT counted 73 if (substr($mime, 0, 5) == 'image') { 74 unset($this->mediafiles[$idx]); 75 continue; 76 } 77 $mediaWN = $this->getWNfromMediaFN($mediafile); 78 $metaFN = $mediametadir . '/' . str_replace(':', DIRECTORY_SEPARATOR, $mediaWN) . self::SUFFIX; 79 if (!file_exists($metaFN)) { 80 $this->dlcount[$mediaWN] = 0; 81 $this->lastdl[$mediaWN] = -1; 82 } else { 83 $meta = unserialize(io_readFile($metaFN, false)); 84 $this->dlcount[$mediaWN] = $meta['dlcount']; 85 $this->lastdl[$mediaWN] = $meta['lastdl']; 86 } 87 } 88 arsort($this->dlcount); 89 arsort($this->lastdl); 90 } 91 92 /** 93 * output appropriate html 94 */ 95 function html() { 96 ptln(sprintf($this->getLang('mediafiles_found'), count($this->mediafiles)) . '<br /><br />'); 97 ptln('<strong>' . $this->getLang('top_dl_files') . ':</strong><br />'); 98 ptln('<table class="inline"><tr><th>#</th><th>' . $this->getLang('filename') . '</th><th>' . $this->getLang('downloads') . '</th><th>' . $this->getLang('last_download') . '</th></tr>'); 99 $top = 1; 100 foreach ($this->dlcount as $fn=>$dlc) { 101 $lastdl = $this->getLang('never'); 102 $lastdltime = $this->time_translate(time() - $this->lastdl[$fn]); 103 if ($this->lastdl[$fn] > 0) $lastdl = sprintf($this->getLang('ago'), $lastdltime); 104 ptln('<tr><th class="rightalign">' . $top++ . '</th><td>' . $fn . '</td><td class="rightalign">' . $dlc . '</td><td class="rightalign">' . $lastdl . '</td></tr>'); 105 if ($top > $this->getConf('top_n_statistics')) break; 106 } 107 ptln('</table><br /><br />'); 108 109 ptln('<strong>' . $this->getLang('most_recent_dl_files') . ':</strong><br />'); 110 ptln('<table class="inline"><tr><th>#</th><th>' . $this->getLang('filename') . '</th><th>' . $this->getLang('downloads') . '</th><th>' . $this->getLang('last_download') . '</th></tr>'); 111 $top = 1; 112 foreach ($this->lastdl as $fn=>$dlt) { 113 $lastdl = $this->getLang('never'); 114 $lastdltime = $this->time_translate(time() - $dlt); 115 if ($dlt > 0) $lastdl = sprintf($this->getLang('ago'), $lastdltime); 116 ptln('<tr><th class="rightalign">' . $top++ . '</th><td>' . $fn . '</td><td class="rightalign">' . $this->dlcount[$fn] . '</td><td class="rightalign">' . $lastdl . '</td></tr>'); 117 if ($top > $this->getConf('top_n_statistics')) break; 118 } 119 ptln('</table><br /><br />'); 120 121 ptln('<strong>' . $this->getLang('least_recent_dl_files') . ':</strong><br />'); 122 ptln('<table class="inline"><tr><th>#</th><th>' . $this->getLang('filename') . '</th><th>' . $this->getLang('downloads') . '</th><th>' . $this->getLang('last_download') . '</th></tr>'); 123 $top = count($this->lastdl); 124 foreach (array_reverse($this->lastdl) as $fn=>$dlt) { 125 $lastdl = $this->getLang('never'); 126 $lastdltime = $this->time_translate(time() - $dlt); 127 if ($dlt > 0) $lastdl = sprintf($this->getLang('ago'), $lastdltime); 128 ptln('<tr><th class="rightalign">' . $top-- . '</th><td>' . $fn . '</td><td class="rightalign">' . $this->dlcount[$fn] . '</td><td class="rightalign">' . $lastdl . '</td></tr>'); 129 if ($top <= count($this->lastdl)-$this->getConf('top_n_statistics')) break; 130 } 131 ptln('</table><br /><br />'); 132 } 133 134 function getWNfromMetaFN($metafn) { 135 $fixedpos = strpos($metafn, '/'.self::DATADIR.'/')+strlen('/'.self::DATADIR); 136 $wn = substr($metafn, $fixedpos); 137 $wn = str_replace(DIRECTORY_SEPARATOR, ':', $wn); 138 return $wn; 139 } 140 141 function getWNfromMediaFN($mediafn) { 142 global $conf; 143 $fixedpos = strpos($mediafn, '/'.$conf['mediadir'].'/') + strlen('/'.$conf['mediadir']); 144 $wn = substr($mediafn, $fixedpos); 145 $wn = str_replace(DIRECTORY_SEPARATOR, ':', $wn); 146 return $wn; 147 } 148 149 // BEGIN: borrowed and modified from http://de3.php.net/manual/en/function.filesize.php 150 function size_translate($filesize) { 151 $array = array( 152 'TiB' => 1024 * 1024 * 1024 * 1024, 153 'GiB' => 1024 * 1024 * 1024, 154 'MiB' => 1024 * 1024, 155 'KiB' => 1024, 156 ); 157 if($filesize <= 1024) { 158 return $filesize . ' B'; 159 } 160 foreach ($array as $name=>$size) { 161 if($filesize >= $size) { 162 return round((round($filesize / $size * 100) / 100), 2) . ' ' . $name; 163 } 164 } 165 return $filesize; 166 } 167 // END: borrowed and modified from http://de3.php.net/manual/en/function.filesize.php 168 169 170 // BEGIN: borrowed and modified from http://de3.php.net/manual/en/function.filesize.php 171 function time_translate($seconds) { 172 $array = array( 173 'y' => 60 * 60 * 24 * 365.25, 174 'M' => 60 * 60 * 24 * 30.5, 175 'w' => 60 * 60 * 24 * 7, 176 'd' => 60 * 60 * 24, 177 'h' => 60 * 60, 178 'm' => 60, 179 's' => 1, 180 ); 181 foreach ($array as $name=>$secs) { 182 if ($seconds < $secs && $secs != end($array)) continue; 183 $resv = floor($seconds / $secs); 184 $res .= ' ' . $resv . $name; 185 $seconds -= $resv*$secs; 186 } 187 return trim($res); 188 } 189 // END: borrowed and modified from http://de3.php.net/manual/en/function.filesize.php 190 191}