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 10if(!defined('DOKU_INC')) die(); 11 12class 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