diff --git a/action.php b/action.php
index 8e66a27..9578a55 100644
--- a/action.php
+++ b/action.php
@@ -33,7 +33,20 @@ function register(&$controller) {
$controller->register_hook('HTML_EDIT_FORMSELECTION', 'BEFORE', $this, '_editform');
$controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, '_handle_edit_post');
$controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, '_handle_ajax');
- }
+ $controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE', $this, '_handle_refresh_data');
+ }
+
+ function _handle_refresh_data(&$event, $param) {
+
+ if ($_REQUEST['cmd'] === null) return;
+
+ // verify valid values
+ switch (key($_REQUEST['cmd'])) {
+ case 'refresh_data' :
+ $this->dthlp->rebuild_data();
+ break;
+ }
+ }
/**
* Handles the page write event and removes the database info
diff --git a/admin/rebuild.php b/admin/rebuild.php
new file mode 100644
index 0000000..08aeb73
--- /dev/null
+++ b/admin/rebuild.php
@@ -0,0 +1,41 @@
+getLang('menu_rebuild');
+ }
+
+ function handle() {
+
+ }
+
+ function html() {
+
+ echo '
Short:
This page allows you to refreshes all Data-Plugin data. You can refresh as often as you like!
';
+
+ echo '
';
+
+ }
+
+}
+
+// vim:ts=4:sw=4:et:
diff --git a/helper.php b/helper.php
index 03dbea3..a403b97 100644
--- a/helper.php
+++ b/helper.php
@@ -1,505 +1,575 @@
-
- */
-// must be run within Dokuwiki
-if(!defined('DOKU_INC')) die();
-
-if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
-require_once(DOKU_PLUGIN.'syntax.php');
-require_once(DOKU_INC.'inc/infoutils.php');
-
-
-/**
- * This is the base class for all syntax classes, providing some general stuff
- */
-class helper_plugin_data extends DokuWiki_Plugin {
-
- /**
- * @var helper_plugin_sqlite initialized via _getDb()
- */
- protected $db = null;
-
- /**
- * @var array stores the alias definitions
- */
- protected $aliases = null;
-
- /**
- * @var array stores custom key localizations
- */
- protected $locs = array();
-
- /**
- * Constructor
- *
- * Loads custom translations
- */
- public function __construct(){
- global $conf;
-
- $lang = array();
- $path = DOKU_CONF.'/lang/en/data-plugin.php';
- if(file_exists($path)) include($path);
- $path = DOKU_CONF.'/lang/'.$this->determineLang().'/data-plugin.php';
- if(file_exists($path)) include($path);
- $this->locs = $lang;
- }
-
- protected function determineLang() {
- global $ID;
- $trans = plugin_load('helper','translation');
- if ($trans) {
- $values['__trans__'] = $trans->getLangPart($ID);
- }
- global $conf;
- return $conf['lang'];
- }
-
- /**
- * Simple function to check if the database is ready to use
- */
- public function ready(){
- return (bool) $this->_getDB();
- }
-
- /**
- * @return helper_plugin_sqlite load the sqlite helper
- */
- function _getDB(){
- if ($this->db === null) {
- $this->db =& plugin_load('helper', 'sqlite');
- if ($this->db === null) {
- msg('The data plugin needs the sqlite plugin', -1);
- return false;
- }
- if(!$this->db->init('data',dirname(__FILE__).'/db/')){
- $db = null;
- return false;
- }
- $this->db->create_function('DATARESOLVE',array($this,'_resolveData'),2);
- }
- return $this->db;
- }
-
- /**
- * Makes sure the given data fits with the given type
- */
- function _cleanData($value, $type){
- $value = trim($value);
- if(!$value AND $value!=='0') return '';
- if (is_array($type)) {
- if (isset($type['enum']) &&
- !preg_match('/(^|,\s*)' . preg_quote_cb($value) . '($|\s*,)/', $type['enum'])) {
- return '';
- }
- $type = $type['type'];
- }
- switch($type){
- case 'dt':
- if(preg_match('/^(\d\d\d\d)-(\d\d?)-(\d\d?)$/',$value,$m)){
- return sprintf('%d-%02d-%02d',$m[1],$m[2],$m[3]);
- }
- return '';
- case 'url':
- if(!preg_match('!^[a-z]+://!i',$value)) $value='http://'.$value;
- return $value;
- case 'mail':
- $email = '';
- $name = '';
- $part = '';
- $parts = preg_split('/\s+/',$value);
- do{
- $part = array_shift($parts);
- if(!$email && mail_isvalid($part)){
- $email = strtolower($part);
- continue;
- }
- $name .= $part.' ';
- }while($part);
- return trim($email.' '.$name);
- case 'page': case 'nspage':
- return cleanID($value);
- default:
- return $value;
- }
- }
-
- /**
- * Add pre and postfixs to the given value
- *
- * $type may be an column array with pre and postfixes
- */
- function _addPrePostFixes($type, $val, $pre='', $post='') {
- if (is_array($type)) {
- if (isset($type['prefix'])) $pre = $type['prefix'];
- if (isset($type['postfix'])) $post = $type['postfix'];
- }
- $val = $pre.$val.$post;
- $val = $this->replacePlaceholders($val);
- return $val;
- }
-
- /**
- * Resolve a value according to its column settings
- *
- * This function is registered as a SQL function named DATARESOLVE
- */
- function _resolveData($value, $colname){
- // resolve pre and postfixes
- $column = $this->_column($colname);
- $value = $this->_addPrePostFixes($column['type'], $value);
-
- // for pages, resolve title
- $type = $column['type'];
- if(is_array($type)) $type = $type['type'];
- if($type == 'title' || ($type == 'page' && useHeading('content'))){
- $id = $value;
- if($type == 'title'){
- list($id,) = explode('|',$value,2);
- }
- //DATARESOLVE is only used with the 'LIKE' comparator, so concatenate the different strings is fine.
- $value .= ' ' . p_get_first_heading($id);
- }
- return $value;
- }
-
- /**
- * Return XHTML formated data, depending on column type
- *
- * @param $column
- * @param $value
- * @param $R Doku_Renderer_xhtml
- * @return string
- */
- function _formatData($column, $value, &$R){
- global $conf;
- $vals = explode("\n",$value);
- $outs = array();
- foreach($vals as $val){
- $val = trim($val);
- if($val=='') continue;
- $type = $column['type'];
- if (is_array($type)) $type = $type['type'];
- switch($type){
- case 'page':
- $val = $this->_addPrePostFixes($column['type'], $val);
- $outs[] = $R->internallink($val,null,null,true);
- break;
- case 'title':
- case 'pageid':
- list($id,$title) = explode('|',$val,2);
- $id = $this->_addPrePostFixes($column['type'], $id);
- $outs[] = $R->internallink($id,$title,null,true);
- break;
- case 'nspage':
- // no prefix/postfix here
- $val = ':'.$column['key'].":$val";
-
- $outs[] = $R->internallink($val,null,null,true);
- break;
- case 'mail':
- list($id,$title) = explode(' ',$val,2);
- $id = $this->_addPrePostFixes($column['type'], $id);
- $id = obfuscate(hsc($id));
- if(!$title){
- $title = $id;
- }else{
- $title = hsc($title);
- }
- if($conf['mailguard'] == 'visible') $id = rawurlencode($id);
- $outs[] = ''.$title.'';
- break;
- case 'url':
- $val = $this->_addPrePostFixes($column['type'], $val);
- $outs[] = $this->external_link($val,false,'urlextern');
- break;
- case 'tag':
- // per default use keyname as target page, but prefix on aliases
- if(!is_array($column['type'])){
- $target = $column['key'].':';
- }else{
- $target = $this->_addPrePostFixes($column['type'],'');
- }
-
- $outs[] = ''.hsc($val).'';
- break;
- case 'timestamp':
- $outs[] = dformat($val);
- break;
- case 'wiki':
- global $ID;
- $oldid = $ID;
- list($ID,$data) = explode('|',$val,2);
- $data = $this->_addPrePostFixes($column['type'], $data);
- // Trim document_{start,end}, p_{open,close}
- $ins = array_slice(p_get_instructions($data), 2, -2);
- $outs[] = p_render('xhtml', $ins, $byref_ignore);
- $ID = $oldid;
- break;
- default:
- $val = $this->_addPrePostFixes($column['type'], $val);
- if(substr($type,0,3) == 'img'){
- $sz = (int) substr($type,3);
- if(!$sz) $sz = 40;
- $title = $column['key'].': '.basename(str_replace(':','/',$val));
- $outs[] = '
';
- }else{
- $outs[] = hsc($val);
- }
- }
- }
- return join(', ',$outs);
- }
-
- /**
- * Split a column name into its parts
- *
- * @returns array with key, type, ismulti, title, opt
- */
- function _column($col){
- preg_match('/^([^_]*)(?:_(.*))?((? $col,
- 'multi' => ($matches[3] === 's'),
- 'key' => utf8_strtolower($matches[1]),
- 'title' => $matches[1],
- 'type' => utf8_strtolower($matches[2])
- );
-
- // fix title for special columns
- static $specials = array('%title%' => array('page', 'title'),
- '%pageid%' => array('title', 'page'),
- '%class%' => array('class'),
- '%lastmod%' => array('lastmod','timestamp'));
- if (isset($specials[$column['title']])) {
- $s = $specials[$column['title']];
- $column['title'] = $this->getLang($s[0]);
- if($column['type'] === '' && isset($s[1])) {
- $column['type'] = $s[1];
- }
- }
-
- // check if the type is some alias
- $aliases = $this->_aliases();
- if(isset($aliases[$column['type']])){
- $column['origtype'] = $column['type'];
- $column['type'] = $aliases[$column['type']];
- }
-
- // use custom localization for keys
- if(isset($this->locs[$column['key']])){
- $column['title'] = $this->locs[$column['key']];
- }
-
- return $column;
- }
-
- /**
- * Load defined type aliases
- */
- function _aliases(){
- if(!is_null($this->aliases)) return $this->aliases;
-
- $sqlite = $this->_getDB();
- if(!$sqlite) return array();
-
- $this->aliases = array();
- $res = $sqlite->query("SELECT * FROM aliases");
- $rows = $sqlite->res2arr($res);
- foreach($rows as $row){
- $name = $row['name'];
- unset($row['name']);
- $this->aliases[$name] = array_filter(array_map('trim', $row));
- if (!isset($this->aliases[$name]['type'])) $this->aliases[$name]['type'] = '';
- }
- return $this->aliases;
- }
-
- /**
- * Parse a filter line into an array
- *
- * @param $filterline
- * @return mixed - array on success, false on error
- */
- function _parse_filter($filterline){
- //split filterline on comparator
- if(preg_match('/^(.*?)([\*=<>!~]{1,2})(.*)$/',$filterline,$matches)){
- $column = $this->_column(trim($matches[1]));
-
- $com = $matches[2];
- $aliasses = array('<>' => '!=', '=!' => '!=', '~!' => '!~',
- '==' => '=', '~=' => '~', '=~' => '~');
-
- if (isset($aliasses[$com])) {
- $com = $aliasses[$com];
- } elseif (!preg_match('/(!?[=~])|([<>]=?)|(\*~)/', $com)) {
- msg('Failed to parse comparison "'.hsc($com).'"',-1);
- return false;
- }
-
- $val = trim($matches[3]);
-
- if(strpos($com, '~') !== false) {
- if ($com === '*~') {
- $val = '*' . $val . '*';
- $com = '~';
- }
- $val = str_replace('*','%',$val);
- if ($com == '!~'){
- $com = 'NOT LIKE';
- } else {
- $com = 'LIKE';
- }
- } else {
- // Clean if there are no asterisks I could kill
- $val = $this->_cleanData($val, $column['type']);
- }
- $sqlite = $this->_getDB();
- if(!$sqlite) return false;
- $val = $sqlite->escape_string($val); //pre escape
-
- return array('key' => $column['key'],
- 'value' => $val,
- 'compare' => $com,
- 'colname' => $column['colname'],
- 'type' => $column['type']
- );
- }
- msg('Failed to parse filter "'.hsc($filterline).'"',-1);
- return false;
- }
-
- /**
- * Replace placeholders in sql
- */
- function _replacePlaceholdersInSQL(&$data){
- // allow current user name in filter:
- $data['sql'] = str_replace('%user%', $_SERVER['REMOTE_USER'], $data['sql']);
- // allow current date in filter:
- $data['sql'] = str_replace('%now%', dformat(null, '%Y-%m-%d'),$data['sql']);
-
- // language filter
- $data['sql'] = $this->makeTranslationReplacement($data['sql']);
- }
-
- public function makeTranslationReplacement($data) {
- global $conf;
- global $ID;
-
- $patterns[] = '%lang%';
- $values[] = $conf['lang'];
-
- // if translation plugin available, get current translation (empty for default lang)
- $patterns[] = '%trans%';
- $trans = plugin_load('helper','translation');
- if($trans) $values[] = $trans->getLangPart($ID);
- else $values[] = '';
-
- return str_replace($patterns, $values, $data);
- }
-
- /**
- * Get filters given in the request via GET or POST
- */
- function _get_filters(){
- $flt = array();
- $filters = array();
-
- if(!isset($_REQUEST['dataflt'])){
- $flt = array();
- }elseif(!is_array($_REQUEST['dataflt'])){
- $flt = (array) $_REQUEST['dataflt'];
- }else{
- $flt = $_REQUEST['dataflt'];
- }
- foreach($flt as $key => $line){
- // we also take the column and filtertype in the key:
- if(!is_numeric($key)) $line = $key.$line;
- $f = $this->_parse_filter($line);
- if(is_array($f)){
- $f['logic'] = 'AND';
- $filters[] = $f;
- }
- }
- return $filters;
- }
-
- /**
- * prepare an array to be passed through buildURLparams()
- */
- function _a2ua($name,$array){
- $urlarray = array();
- foreach((array) $array as $key => $val){
- $urlarray[$name.'['.$key.']'] = $val;
- }
- return $urlarray;
- }
-
- /**
- * get current URL parameters
- */
- function _get_current_param($returnURLparams=true){
- $cur_params = array();
- if(isset($_REQUEST['dataflt'])){
- $cur_params = $this->_a2ua('dataflt', $_REQUEST['dataflt']);
- }
- if (isset($_REQUEST['datasrt'])) {
- $cur_params['datasrt'] = $_REQUEST['datasrt'];
- }
- if (isset($_REQUEST['dataofs'])) {
- $cur_params['dataofs'] = $_REQUEST['dataofs'];
- }
-
- //combine key and value
- if(!$returnURLparams){
- $flat_param=array();
- foreach($cur_params as $key => $val){
- $flat_param[]=$key.$val;
- }
- $cur_params=$flat_param;
- }
- return $cur_params;
- }
-
- /**
- * Get url parameters, remove all filters for given column and add filter for desired tag
- * @param array $column
- * @param string $tag
- * @return array of url parameters
- */
- function _getTagUrlparam($column, $tag) {
- $param = array();
-
- if(isset($_REQUEST['dataflt'])) {
- $param = (array) $_REQUEST['dataflt'];
-
- //remove all filters equal to column
- foreach($param as $key => $flt) {
- if(!is_numeric($key)) $flt = $key.$flt;
- $filter = $this->_parse_filter($flt);
- if($filter['key'] == $column['key']) {
- unset($param[$key]);
- }
- }
- }
- $param[] = $column['key']."_=$tag";
- $param = $this->_a2ua('dataflt', $param);
-
- if(isset($_REQUEST['datasrt'])) {
- $param['datasrt'] = $_REQUEST['datasrt'];
- }
- if(isset($_REQUEST['dataofs'])) {
- $param['dataofs'] = $_REQUEST['dataofs'];
- }
-
- return $param;
- }
-
- private function replacePlaceholders($value) {
- return $this->makeTranslationReplacement($value);
- }
-}
+
+ */
+// must be run within Dokuwiki
+if(!defined('DOKU_INC')) die();
+
+if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/');
+require_once(DOKU_PLUGIN.'syntax.php');
+require_once(DOKU_INC.'inc/infoutils.php');
+require_once(DOKU_INC.'inc/search.php');
+require_once(DOKU_INC.'/inc/DifferenceEngine.php');
+
+function data_callback_search_wanted(&$data,$base,$file,$type,$lvl,$opts) {
+ global $conf;
+
+ if($type == 'd'){
+ return true; // recurse all directories, but we don't store namespaces
+ }
+
+ if(!preg_match("/.*\.txt$/", $file)) { // Ignore everything but TXT
+ return true;
+ }
+
+ // get id of this file
+ $id = pathID($file);
+
+ $item = &$data["$id"];
+ if(! isset($item)) {
+ $data["$id"]= array('id' => $id,
+ 'file' => $file);
+ }
+}
+
+/**
+ * This is the base class for all syntax classes, providing some general stuff
+ */
+class helper_plugin_data extends DokuWiki_Plugin {
+
+ /**
+ * @var helper_plugin_sqlite initialized via _getDb()
+ */
+ protected $db = null;
+
+ /**
+ * @var array stores the alias definitions
+ */
+ protected $aliases = null;
+
+ /**
+ * @var array stores custom key localizations
+ */
+ protected $locs = array();
+
+ /**
+ * Constructor
+ *
+ * Loads custom translations
+ */
+ public function __construct(){
+ global $conf;
+
+ $lang = array();
+ $path = DOKU_CONF.'/lang/en/data-plugin.php';
+ if(file_exists($path)) include($path);
+ $path = DOKU_CONF.'/lang/'.$this->determineLang().'/data-plugin.php';
+ if(file_exists($path)) include($path);
+ $this->locs = $lang;
+ }
+
+ function rebuild_data() {
+
+ // Load the data plugin only if we need to
+ $data_entry = null;
+ $data_entry =& plugin_load('syntax', 'data_entry');
+ if(!$data_entry)
+ {
+ msg('Error loading the data entry class from data Helper. stopping current action.',-1);
+ return;
+ }
+
+ global $conf;
+ $result = '';
+ $data = array();
+ search($data,$conf['datadir'],'data_callback_search_wanted',array('ns' => $ns));
+
+ $output = array();
+ foreach($data as $entry) {
+
+ // Get the content of the file
+ $filename = $conf['datadir'].$entry['file'];
+ if (strpos($filename, 'syntax') > 0) continue; // Skip instructional pages
+ $body = @file_get_contents($filename);
+
+ // Run the regular expression to get the dataentry section
+ $pattern = '/----.*dataentry.*\R----/s';
+ if (preg_match($pattern, $body, $matches) === false) {
+ continue;
+ }
+
+ foreach ($matches as $match) {
+
+ // Re-use the handle method to get the formatted data
+ $cleanedMatch = htmlspecialchars($match);
+ $dummy = "";
+ $formatted = $data_entry->handle($cleanedMatch, null, null, $dummy);
+ $output['id'.count($output)] = $formatted;
+
+ // Re-use the save_data method to .... (drum roll) save the data.
+ // Ignore the returned html, just move on to the next file
+ $html = $data_entry->_saveData($formatted, $entry['id'], 'Title'.count($output));
+ }
+ }
+
+ msg('Data entry plugin found and refreshed all '.count($output).' entries.');
+ }
+
+
+ protected function determineLang() {
+ global $ID;
+ $trans = plugin_load('helper','translation');
+ if ($trans) {
+ $values['__trans__'] = $trans->getLangPart($ID);
+ }
+ global $conf;
+ return $conf['lang'];
+ }
+
+ /**
+ * Simple function to check if the database is ready to use
+ */
+ public function ready(){
+ return (bool) $this->_getDB();
+ }
+
+ /**
+ * @return helper_plugin_sqlite load the sqlite helper
+ */
+ function _getDB(){
+ if ($this->db === null) {
+ $this->db =& plugin_load('helper', 'sqlite');
+ if ($this->db === null) {
+ msg('The data plugin needs the sqlite plugin', -1);
+ return false;
+ }
+ if(!$this->db->init('data',dirname(__FILE__).'/db/')){
+ $db = null;
+ return false;
+ }
+ $this->db->create_function('DATARESOLVE',array($this,'_resolveData'),2);
+ }
+ return $this->db;
+ }
+
+ /**
+ * Makes sure the given data fits with the given type
+ */
+ function _cleanData($value, $type){
+ $value = trim($value);
+ if(!$value AND $value!=='0') return '';
+ if (is_array($type)) {
+ if (isset($type['enum']) &&
+ !preg_match('/(^|,\s*)' . preg_quote_cb($value) . '($|\s*,)/', $type['enum'])) {
+ return '';
+ }
+ $type = $type['type'];
+ }
+ switch($type){
+ case 'dt':
+ if(preg_match('/^(\d\d\d\d)-(\d\d?)-(\d\d?)$/',$value,$m)){
+ return sprintf('%d-%02d-%02d',$m[1],$m[2],$m[3]);
+ }
+ return '';
+ case 'url':
+ if(!preg_match('!^[a-z]+://!i',$value)) $value='http://'.$value;
+ return $value;
+ case 'mail':
+ $email = '';
+ $name = '';
+ $part = '';
+ $parts = preg_split('/\s+/',$value);
+ do{
+ $part = array_shift($parts);
+ if(!$email && mail_isvalid($part)){
+ $email = strtolower($part);
+ continue;
+ }
+ $name .= $part.' ';
+ }while($part);
+ return trim($email.' '.$name);
+ case 'page': case 'nspage':
+ return cleanID($value);
+ default:
+ return $value;
+ }
+ }
+
+ /**
+ * Add pre and postfixs to the given value
+ *
+ * $type may be an column array with pre and postfixes
+ */
+ function _addPrePostFixes($type, $val, $pre='', $post='') {
+ if (is_array($type)) {
+ if (isset($type['prefix'])) $pre = $type['prefix'];
+ if (isset($type['postfix'])) $post = $type['postfix'];
+ }
+ $val = $pre.$val.$post;
+ $val = $this->replacePlaceholders($val);
+ return $val;
+ }
+
+ /**
+ * Resolve a value according to its column settings
+ *
+ * This function is registered as a SQL function named DATARESOLVE
+ */
+ function _resolveData($value, $colname){
+ // resolve pre and postfixes
+ $column = $this->_column($colname);
+ $value = $this->_addPrePostFixes($column['type'], $value);
+
+ // for pages, resolve title
+ $type = $column['type'];
+ if(is_array($type)) $type = $type['type'];
+ if($type == 'title' || ($type == 'page' && useHeading('content'))){
+ $id = $value;
+ if($type == 'title'){
+ list($id,) = explode('|',$value,2);
+ }
+ //DATARESOLVE is only used with the 'LIKE' comparator, so concatenate the different strings is fine.
+ $value .= ' ' . p_get_first_heading($id);
+ }
+ return $value;
+ }
+
+ /**
+ * Return XHTML formated data, depending on column type
+ *
+ * @param $column
+ * @param $value
+ * @param $R Doku_Renderer_xhtml
+ * @return string
+ */
+ function _formatData($column, $value, &$R){
+ global $conf;
+ $vals = explode("\n",$value);
+ $outs = array();
+ foreach($vals as $val){
+ $val = trim($val);
+ if($val=='') continue;
+ $type = $column['type'];
+ if (is_array($type)) $type = $type['type'];
+ switch($type){
+ case 'page':
+ $val = $this->_addPrePostFixes($column['type'], $val);
+ $outs[] = $R->internallink($val,null,null,true);
+ break;
+ case 'title':
+ case 'pageid':
+ list($id,$title) = explode('|',$val,2);
+ $id = $this->_addPrePostFixes($column['type'], $id);
+ $outs[] = $R->internallink($id,$title,null,true);
+ break;
+ case 'nspage':
+ // no prefix/postfix here
+ $val = ':'.$column['key'].":$val";
+
+ $outs[] = $R->internallink($val,null,null,true);
+ break;
+ case 'mail':
+ list($id,$title) = explode(' ',$val,2);
+ $id = $this->_addPrePostFixes($column['type'], $id);
+ $id = obfuscate(hsc($id));
+ if(!$title){
+ $title = $id;
+ }else{
+ $title = hsc($title);
+ }
+ if($conf['mailguard'] == 'visible') $id = rawurlencode($id);
+ $outs[] = ''.$title.'';
+ break;
+ case 'url':
+ $val = $this->_addPrePostFixes($column['type'], $val);
+ $outs[] = $this->external_link($val,false,'urlextern');
+ break;
+ case 'tag':
+ // per default use keyname as target page, but prefix on aliases
+ if(!is_array($column['type'])){
+ $target = $column['key'].':';
+ }else{
+ $target = $this->_addPrePostFixes($column['type'],'');
+ }
+
+ $outs[] = ''.hsc($val).'';
+ break;
+ case 'timestamp':
+ $outs[] = dformat($val);
+ break;
+ case 'wiki':
+ global $ID;
+ $oldid = $ID;
+ list($ID,$data) = explode('|',$val,2);
+ $data = $this->_addPrePostFixes($column['type'], $data);
+ // Trim document_{start,end}, p_{open,close}
+ $ins = array_slice(p_get_instructions($data), 2, -2);
+ $outs[] = p_render('xhtml', $ins, $byref_ignore);
+ $ID = $oldid;
+ break;
+ default:
+ $val = $this->_addPrePostFixes($column['type'], $val);
+ if(substr($type,0,3) == 'img'){
+ $sz = (int) substr($type,3);
+ if(!$sz) $sz = 40;
+ $title = $column['key'].': '.basename(str_replace(':','/',$val));
+ $outs[] = '
';
+ }else{
+ $outs[] = hsc($val);
+ }
+ }
+ }
+ return join(', ',$outs);
+ }
+
+ /**
+ * Split a column name into its parts
+ *
+ * @returns array with key, type, ismulti, title, opt
+ */
+ function _column($col){
+ preg_match('/^([^_]*)(?:_(.*))?((? $col,
+ 'multi' => ($matches[3] === 's'),
+ 'key' => utf8_strtolower($matches[1]),
+ 'title' => $matches[1],
+ 'type' => utf8_strtolower($matches[2])
+ );
+
+ // fix title for special columns
+ static $specials = array('%title%' => array('page', 'title'),
+ '%pageid%' => array('title', 'page'),
+ '%class%' => array('class'),
+ '%lastmod%' => array('lastmod','timestamp'));
+ if (isset($specials[$column['title']])) {
+ $s = $specials[$column['title']];
+ $column['title'] = $this->getLang($s[0]);
+ if($column['type'] === '' && isset($s[1])) {
+ $column['type'] = $s[1];
+ }
+ }
+
+ // check if the type is some alias
+ $aliases = $this->_aliases();
+ if(isset($aliases[$column['type']])){
+ $column['origtype'] = $column['type'];
+ $column['type'] = $aliases[$column['type']];
+ }
+
+ // use custom localization for keys
+ if(isset($this->locs[$column['key']])){
+ $column['title'] = $this->locs[$column['key']];
+ }
+
+ return $column;
+ }
+
+ /**
+ * Load defined type aliases
+ */
+ function _aliases(){
+ if(!is_null($this->aliases)) return $this->aliases;
+
+ $sqlite = $this->_getDB();
+ if(!$sqlite) return array();
+
+ $this->aliases = array();
+ $res = $sqlite->query("SELECT * FROM aliases");
+ $rows = $sqlite->res2arr($res);
+ foreach($rows as $row){
+ $name = $row['name'];
+ unset($row['name']);
+ $this->aliases[$name] = array_filter(array_map('trim', $row));
+ if (!isset($this->aliases[$name]['type'])) $this->aliases[$name]['type'] = '';
+ }
+ return $this->aliases;
+ }
+
+ /**
+ * Parse a filter line into an array
+ *
+ * @param $filterline
+ * @return mixed - array on success, false on error
+ */
+ function _parse_filter($filterline){
+ //split filterline on comparator
+ if(preg_match('/^(.*?)([\*=<>!~]{1,2})(.*)$/',$filterline,$matches)){
+ $column = $this->_column(trim($matches[1]));
+
+ $com = $matches[2];
+ $aliasses = array('<>' => '!=', '=!' => '!=', '~!' => '!~',
+ '==' => '=', '~=' => '~', '=~' => '~');
+
+ if (isset($aliasses[$com])) {
+ $com = $aliasses[$com];
+ } elseif (!preg_match('/(!?[=~])|([<>]=?)|(\*~)/', $com)) {
+ msg('Failed to parse comparison "'.hsc($com).'"',-1);
+ return false;
+ }
+
+ $val = trim($matches[3]);
+
+ if(strpos($com, '~') !== false) {
+ if ($com === '*~') {
+ $val = '*' . $val . '*';
+ $com = '~';
+ }
+ $val = str_replace('*','%',$val);
+ if ($com == '!~'){
+ $com = 'NOT LIKE';
+ } else {
+ $com = 'LIKE';
+ }
+ } else {
+ // Clean if there are no asterisks I could kill
+ $val = $this->_cleanData($val, $column['type']);
+ }
+ $sqlite = $this->_getDB();
+ if(!$sqlite) return false;
+ $val = $sqlite->escape_string($val); //pre escape
+
+ return array('key' => $column['key'],
+ 'value' => $val,
+ 'compare' => $com,
+ 'colname' => $column['colname'],
+ 'type' => $column['type']
+ );
+ }
+ msg('Failed to parse filter "'.hsc($filterline).'"',-1);
+ return false;
+ }
+
+ /**
+ * Replace placeholders in sql
+ */
+ function _replacePlaceholdersInSQL(&$data){
+ // allow current user name in filter:
+ $data['sql'] = str_replace('%user%', $_SERVER['REMOTE_USER'], $data['sql']);
+ // allow current date in filter:
+ $data['sql'] = str_replace('%now%', dformat(null, '%Y-%m-%d'),$data['sql']);
+
+ // language filter
+ $data['sql'] = $this->makeTranslationReplacement($data['sql']);
+ }
+
+ public function makeTranslationReplacement($data) {
+ global $conf;
+ global $ID;
+
+ $patterns[] = '%lang%';
+ $values[] = $conf['lang'];
+
+ // if translation plugin available, get current translation (empty for default lang)
+ $patterns[] = '%trans%';
+ $trans = plugin_load('helper','translation');
+ if($trans) $values[] = $trans->getLangPart($ID);
+ else $values[] = '';
+
+ return str_replace($patterns, $values, $data);
+ }
+
+ /**
+ * Get filters given in the request via GET or POST
+ */
+ function _get_filters(){
+ $flt = array();
+ $filters = array();
+
+ if(!isset($_REQUEST['dataflt'])){
+ $flt = array();
+ }elseif(!is_array($_REQUEST['dataflt'])){
+ $flt = (array) $_REQUEST['dataflt'];
+ }else{
+ $flt = $_REQUEST['dataflt'];
+ }
+ foreach($flt as $key => $line){
+ // we also take the column and filtertype in the key:
+ if(!is_numeric($key)) $line = $key.$line;
+ $f = $this->_parse_filter($line);
+ if(is_array($f)){
+ $f['logic'] = 'AND';
+ $filters[] = $f;
+ }
+ }
+ return $filters;
+ }
+
+ /**
+ * prepare an array to be passed through buildURLparams()
+ */
+ function _a2ua($name,$array){
+ $urlarray = array();
+ foreach((array) $array as $key => $val){
+ $urlarray[$name.'['.$key.']'] = $val;
+ }
+ return $urlarray;
+ }
+
+ /**
+ * get current URL parameters
+ */
+ function _get_current_param($returnURLparams=true){
+ $cur_params = array();
+ if(isset($_REQUEST['dataflt'])){
+ $cur_params = $this->_a2ua('dataflt', $_REQUEST['dataflt']);
+ }
+ if (isset($_REQUEST['datasrt'])) {
+ $cur_params['datasrt'] = $_REQUEST['datasrt'];
+ }
+ if (isset($_REQUEST['dataofs'])) {
+ $cur_params['dataofs'] = $_REQUEST['dataofs'];
+ }
+
+ //combine key and value
+ if(!$returnURLparams){
+ $flat_param=array();
+ foreach($cur_params as $key => $val){
+ $flat_param[]=$key.$val;
+ }
+ $cur_params=$flat_param;
+ }
+ return $cur_params;
+ }
+
+ /**
+ * Get url parameters, remove all filters for given column and add filter for desired tag
+ * @param array $column
+ * @param string $tag
+ * @return array of url parameters
+ */
+ function _getTagUrlparam($column, $tag) {
+ $param = array();
+
+ if(isset($_REQUEST['dataflt'])) {
+ $param = (array) $_REQUEST['dataflt'];
+
+ //remove all filters equal to column
+ foreach($param as $key => $flt) {
+ if(!is_numeric($key)) $flt = $key.$flt;
+ $filter = $this->_parse_filter($flt);
+ if($filter['key'] == $column['key']) {
+ unset($param[$key]);
+ }
+ }
+ }
+ $param[] = $column['key']."_=$tag";
+ $param = $this->_a2ua('dataflt', $param);
+
+ if(isset($_REQUEST['datasrt'])) {
+ $param['datasrt'] = $_REQUEST['datasrt'];
+ }
+ if(isset($_REQUEST['dataofs'])) {
+ $param['dataofs'] = $_REQUEST['dataofs'];
+ }
+
+ return $param;
+ }
+
+ private function replacePlaceholders($value) {
+ return $this->makeTranslationReplacement($value);
+ }
+}
diff --git a/lang/en/lang.php b/lang/en/lang.php
index 960d07b..7a4bdfb 100644
--- a/lang/en/lang.php
+++ b/lang/en/lang.php
@@ -2,6 +2,7 @@
$lang['menu_alias'] = 'Data Plugin: Field Aliases';
$lang['menu_clean'] = 'Data Plugin: Clean up database';
+$lang['menu_rebuild'] = 'Data Plugin: Rebuild database';
$lang['pages_del'] = '%d entries removed.';
$lang['submit_clean'] = 'Clean database!';
diff --git a/lang/nl/lang.php b/lang/nl/lang.php
index 0c6f183..953f307 100644
--- a/lang/nl/lang.php
+++ b/lang/nl/lang.php
@@ -2,6 +2,7 @@
$lang['menu_alias'] = 'Data Plugin: Veldaliases';
$lang['menu_clean'] = 'Data Plugin: Schoon de database op';
+$lang['menu_rebuild'] = 'Data Plugin: Bouw de database opnieuw op';
$lang['pages_del'] = '%d blokken verwijderd.';
$lang['submit_clean'] = 'Database opschonen!';