1<?php
2/*
3description : Provide caching mechanism for plugins
4author      : Ikuo Obataya
5email       : I.Obataya@gmail.com
6lastupdate  : 2008-11-26
7license     : GPL 2 (http://www.gnu.org/licenses/gpl.html)
8*/
9if(!defined('DOKU_INC')) die();
10class plugin_cache{
11  var $namespace  ='';
12  var $mediaDir   ='';
13  var $mediaFormat='';
14  var $linkFormat ='';
15  var $prefix     ='';
16  var $extension  ='';
17  var $tmpdir     ='';
18  function plugin_cache($_name='plugin_cache',$_prefix='noname',$_ext='txt'){
19    global $conf;
20    $this->namespace = strtolower($_name);
21    $this->prefix    = strtolower($_prefix);
22    $this->extension = strtolower($_ext);
23    if (empty($_prefix)){
24      $this->prefix = $_prefix;
25    }else{
26      $this->prefix = $_prefix.'_';
27    }
28    $delimiter = ($conf['useslash'])?'/':':';
29    $this->mediaDir    = $conf['mediadir'].'/'.$this->namespace;
30    $this->mediaFormat = $this->mediaDir.'/'.$this->prefix.'%s.'.$this->extension;
31    $this->linkFormat  = $this->namespace.$delimiter.$this->prefix.'%s.'.$this->extension;
32
33    $this->useTmpDir   = false;
34    $this->tmpDir      = '/var/tmp';
35    $this->tmpFormat   = $this->tmpDir.'/'.$this->namespace.'_'.$this->prefix.'%s.'.$this->extension;
36
37    $this->CheckDir();
38  }
39
40 /**
41  * Get media file path
42  */
43  function GetMediaPath($id){
44    $id = strtolower($id);
45    if($this->useTmpDir===false){
46      return sprintf($this->mediaFormat,$id);
47    }else{
48      return sprintf($this->tmpFormat,$id);
49    }
50  }
51
52 /**
53  * Get all media file paths array
54  * array(ID,filepath)
55  */
56  function GetAllMediaPaths(){
57    $dir = $this->mediaDir;
58    $dirhandle = opendir($dir);
59    $files = array();
60
61    $patten = array($this->prefix,'.'.$this->extension);
62    $replace = array('','');
63    while($name = readdir($dirhandle)){
64      if (strpos($name,$this->extension)!==false){
65        $path = $dir.'/'.$name;
66        $id = str_replace($patten,$replace,$name);
67        $files[$id] = $path;
68      }
69    }
70    closedir();
71    return $files;
72  }
73
74 /**
75  * Get media link
76  */
77  function GetMediaLink($id){
78    return ml(sprintf($this->linkFormat,$id),'',true,'',true);
79  }
80
81 /**
82  * Get text from cache. If none, return false
83  *
84  * Uses gzip if extension is .gz
85  * and bz2 if extension is .bz2
86  */
87  function GetMediaText($id){
88    $filepath = $this->GetMediaPath($id);
89    if (@file_exists($filepath)){
90      @touch($filepath);
91      return io_readFile($filepath);
92    }
93    return false;
94  }
95 /**
96  * Save string to cache with a permission of $conf['fmode'].
97  *
98  * Uses gzip if extension is .gz
99  * and bz2 if extension is .bz2
100  */
101  function PutMediaText($id,$text){
102    global $conf;
103    $path = $this->GetMediaPath($id);
104    if(io_saveFile($path,$text)){
105        @chmod($path,$conf['fmode']);
106        return true;
107    }
108    return false;
109  }
110 /**
111  * Check cache directories
112  */
113  function CheckDir(){
114    global $conf;
115    $dummyFN=mediaFN($this->namespace.':_dummy');
116    $tmp = dirname($dummyFN);
117    if (!@is_dir($tmp)){
118      io_makeFileDir($dummyFN);
119      @chmod($tmp,$conf['dmode']);
120    }
121    if (auth_aclcheck($this->namespace.":*","","@ALL")==0){
122       global $AUTH_ACL;
123       $acl = join("",file(DOKU_CONF.'acl.auth.php'));
124       $p_acl = $this->namespace.":*\t@ALL\t1\n";
125       $new_acl = $acl.$p_acl;
126       io_saveFile(DOKU_CONF.'acl.auth.php', $new_acl);
127       $AUTH_ACL = file(DOKU_CONF.'acl.auth.php'); // Reload ACL
128    }
129  }
130 /**
131  * Return true if the file exists
132  */
133  function Exists($id){
134    $path = $this->GetMediaPath($id);
135    if(@file_exists($path)!==false){
136      @touch($path);
137      return true;
138    }
139    return false;
140  }
141
142 /**
143  * Clear all media files in a plugin's media directory
144  */
145  function ClearCache(){
146    global $conf;
147    $handle = @opendir($this->mediaDir);
148    if ($handle === false)
149      return;
150    while (($entry = readdir($handle))){
151      $path = $this->mediaDir.'/'.$entry;
152      if(is_file($path))
153          @unlink($path);
154    }
155    closedir($handle);
156  }
157 /**
158  * Remove cache and directory
159  */
160  function RemoveDir(){
161    $this->ClearCache();
162    @rmdir($this->mediaDir);
163  }
164 /**
165  * save array as tab-text
166  */
167  function _save_array($id,$ar=''){
168    $_st = _microtime();
169    if(empty($id)) return false;
170    global $conf;
171    if (empty($ar)){
172    }else{
173      $rep_pair = array("\n"=>"","\t"=>"");
174      $values = array_values($ar);
175      $keys = array_keys($ar);
176      $sz = count($values);
177      for($i=0;$i<$sz;$i++){
178        $k = $keys[$i];
179        if(empty($k)) $k=$i;
180        $v=strtr($ar[$k],$rep_pair);
181        $file.= $k."\t".$v."\n";
182      }
183    }
184    if (empty($file)){$file='#not found';}
185    $path = $this->GetMediaPath($id);
186    if(io_saveFile($path,$file)){
187      @chmod($path,$conf['fmode']);
188      _stopwatch('save_array',$_st);
189      return true;
190    }else{
191      _stopwatch('save_array',$_st);
192    return false;
193    }
194  }
195
196 /**
197  * read array from tab-text
198  */
199  function _read_array($id){
200    $_st = _microtime();
201    if (empty($id) || !$this->Exists($id)) return NULL;
202    $path = $this->GetMediaPath($id);
203    $lines = split("\n",io_readFile($path));
204    $a = array();
205    $sz = count($lines);
206    for($i=0;$i<$sz;$i++){
207      if ($line=='#not found') return null;
208      $line = chop($lines[$i]);
209      if (empty($line)) continue;
210      $items = explode("\t",$line);
211      if (count($items)!=2)continue;
212      $a[$items[0]] = $items[1];
213    }
214      _stopwatch('read_array',$_st);
215    @touch($path);
216    return $a;
217  }
218
219}
220