1 <?php
2 /**
3  * DokuWiki Plugin snippets (Helper Component)
4  *
5  * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6  * @author  Myron Turner <turnermm02@shaw.ca>
7  */
8 
9 // must be run within Dokuwiki
10 if(!defined('DOKU_INC')) die();
11 
12 class helper_plugin_snippets extends DokuWiki_Plugin {
13 
14     private $metafn;
15 
16     function __construct() {
17         $this->metafn = metaFN('snippets_upd','.ser');
18         if(!file_exists($this->metafn)) {
19             $ar = array('snip'=>array(), 'doc'=>array());
20             io_saveFile($this->metafn,serialize($ar));
21         }
22     }
23 
24     /**
25      * Return info about supported methods in this Helper Plugin
26      *
27      * @return array of public methods
28      */
29     public function getMethods() {
30         return array(
31             array(
32                 'name'   => 'mostRecentVersion',
33                 'desc'   => 'checks metadata for most recent version of  $id',
34                 'params' => array(
35                     'id'         => 'string'
36                 ),
37                 'return' => array('timestamp' => 'integer')
38             ),
39             array(
40                 'name' => 'snippetWasUpdated',
41                 'desc' => 'check if snippet inserted in a page was updated to most recent version',
42                 'params' => array( 'id'=>'string', 'snippet'=>'string'),
43                 'return' =>array('timstamp'=>'boolean')
44             ),
45            array(
46                 'name' => 'updateMetaTime',
47                 'desc' => 'sets and updates timestamp of snippet in metafile of page where snippet is inserted',
48                 'params' => array(
49                     'id' => 'string',
50                     'snippet' => 'string',
51                     'set_time' => 'int'
52                 ),
53                 'return' =>array()
54             ),
55            array(
56                 'name' => 'insertSnippet',
57                 'desc' => 'inserts updated snippet into page',
58                 'params' => array(
59                   'result (reference)' => 'string',
60                   'page_id' => 'string'
61                 ),
62                 'return' =>array()
63             ),
64         );
65     }
66 
67     /**
68      *  If the metadata shows that the (snippet) file has been restored from an earlier version, that is the most recent
69      *  version; otherwise the last modified date is the most recent version
70      *  @param string  $id  id of page to be checked for most recent version
71      *  @modified int  timestamp
72      *  @return int timestamp
73     */
74     function mostRecentVersion($id, &$modified) {
75         $modified = p_get_metadata($id, 'date modified');
76         $sum = p_get_metadata($id, 'last_change sum');
77         if($sum && preg_match('#restored\s+(\(.*?\))#',$sum,$matches)){
78             return  strtotime(trim($matches[1],'()'));
79         }
80         return $modified;
81   }
82     /**
83       *  Checks the most recent version of  snippet against the timestamp for snippet
84       *  stored in the meta file for page into which the snippet has been inserted
85       *  If the timestamps are the same then the snippet has been updated
86       *  @param $id string  id of page where snippet was inserted
87       *  @param snippet string  page id of snippet
88     */
89    function snippetWasUpdated($id, $snippet) {
90        $isref = p_get_metadata($id, 'relation isreferencedby' );
91        $snip_time = $isref['snippets'][$snippet] ;
92        if(empty($snip_time)) {
93           $this->updateMetaTime($id,$snippet);
94        }
95        $time_stamp = $this->mostRecentVersion($snippet, $modified);
96 
97         return $snip_time  ==  $time_stamp;
98    }
99 
100     /**
101       *  Updates time stamp of snippet in metafile of page where snippet is inserted
102     */
103     function updateMetaTime($id,$snippet) {
104     global $ID;
105     if(empty($ID)) $ID = $id;
106         if(!$snippet) return;
107     $isref = p_get_metadata($id, 'relation isreferencedby');
108         $time =  $this->mostRecentVersion($snippet, $modified) ;
109 
110     $data = array();
111 
112     if(!is_array($isref)) {
113        $is_array= array();
114     }
115     $isref['snippets'][$snippet] = $time;
116 
117     $data['relation']['isreferencedby']=$isref;
118      p_set_metadata($id, $data);
119 }
120 
121     /**
122       * Inserts updated snippets in page after checking to see if snippets have been updated
123       * @param result:   reference to string that holds the page contents
124       * @param page_id  string
125       * @ param $force boolean: if true, latest snippet will be inserted into Old Revisions
126     */
127     function insertSnippet(&$result, $page_id,$force) {
128          if(!file_exists(wikiFN($page_id))) return;
129          $snip_data=unserialize(io_readFile($this->metafn,false));
130          if(!array_key_exists($page_id,$snip_data['doc'])) return; //Check if page contains snippet
131 
132          global $replacement;  // will hold new version of snippet
133 
134          $snippets = $snip_data['doc'][$page_id];
135          $page_t = filemtime(wikiFN($page_id));
136 
137          foreach ($snippets as $snip) {
138              $snip_file = wikiFN($snip);
139              if(!file_exists($snip_file)) continue;
140              $snip_t = filemtime($snip_file);
141 
142              if($snip_t < $page_t && $this->snippetWasUpdated($page_id,$snip) && !$force) {
143                    continue;
144              }
145 
146              $replacement =  trim(preg_replace('/<snippet>.*?<\/snippet>/s', '', io_readFile($snip_file)));
147              $snip_id = preg_quote($snip);
148              $result = preg_replace_callback(
149                 "|(?<=~~SNIPPET_O)\d*(~~$snip_id~~).*?(?=~~SNIPPET_C~~$snip_id~~)|ms",
150                      function($matches){
151                          global $replacement;
152                          return  time()  . $matches[1]. "\n" .$replacement  . "\n";  // time() makes each update unique for renderer
153                   },
154                   $result
155                 );
156           }
157 
158     }
159 
160     /*
161       *    create new page array for a snippet entry in the database
162       *
163       *    @ $pages  array   page ids currently held for snippet
164       *    @ $id  string        id of current page
165     */
166     function getPageArray($pages, $id) {
167         $id_array = array();
168         foreach($pages as $page_id) {
169             if($id != $page_id) {  // remove current page from array of pages held by the snippet
170                 $id_array[] = $page_id;
171             }
172         }
173         return $id_array;
174     }
175 
176    function getMetaFileName() {
177        return $this->metafn;
178    }
179 
180 }
181 // vim:ts=4:sw=4:et:
182