[ Index ]
 

Code source de eGroupWare 1.2.106-2

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/wiki/inc/ -> class.sowiki.inc.php (source)

   1  <?php
   2  /**************************************************************************\
   3  * eGroupWare - Wiki DB-Layer                                               *
   4  * http://www.egroupware.org                                                *
   5  * Written by Ralf Becker <RalfBecker@outdoor-training.de>                  *
   6  * originaly based on WikkiTikkiTavi tavi.sf.net and www.axisgroupware.org: *
   7  * former files lib/pagestore.php + lib/page.php                            *
   8  * --------------------------------------------                             *
   9  *  This program is free software; you can redistribute it and/or modify it *
  10  *  under the terms of the GNU General Public License as published by the   *
  11  *  Free Software Foundation; either version 2 of the License, or (at your  *
  12  *  option) any later version.                                              *
  13  \**************************************************************************/
  14  
  15  /* $Id: class.sowiki.inc.php 21443 2006-04-25 05:51:38Z ralfbecker $ */
  16  
  17  define ('WIKI_ACL_ALL',0);        // everyone incl. anonymous
  18  define ('WIKI_ACL_USER',1);        // everyone BUT anonymous
  19  define ('WIKI_ACL_ADMIN',2);    // only admins (access to the admin app !)
  20  
  21  /**
  22   * Class representing a wiki-page, usualy gets instanciated via sowiki::page()
  23   * @class soWikiPage
  24   * @author RalfBecker-AT-outdoor-training.de
  25   * @license GPL
  26   */
  27  class soWikiPage
  28  {
  29      var $name = '';                       // Name of page.
  30      var $title = '';                      // Title of page.
  31      var $text = '';                       // Page's text in wiki markup form.
  32      var $time = '';                       // Page's modification time.
  33      var $hostname = '';                   // Hostname of last editor.
  34      var $username = '';                   // Username of last editor.
  35      var $comment  = '';                   // Description of last edit.
  36      var $version = -1;                    // Version number of page.
  37      var $mutable = 1;                     // Whether page may be edited (depricated !)
  38      var $readable = WIKI_ACL_ALL;         // who can read the page
  39      var $writable = WIKI_ACL_ALL;         // who can write the page
  40      var $exists = 0;                      // Whether page already exists.
  41      var $db; /* @var $db db */            // Database object.
  42      var $PgTbl;
  43      var $colNames = array(                // column-name - class-var-name pairs
  44          'wiki_id'        => 'wiki_id',
  45          'wiki_name'      => 'name',
  46          'wiki_lang'      => 'lang',
  47          'wiki_version'   => 'version',
  48          'wiki_time'      => 'time',
  49          'wiki_supercede' => 'supercede',
  50          'wiki_readable'  => 'readable',
  51          'wiki_writable'  => 'writable',
  52          'wiki_hostname'  => 'hostname',
  53          'wiki_username'  => 'username',
  54          'wiki_comment'   => 'comment',
  55          'wiki_title'     => 'title',
  56          'wiki_body'      => 'text',
  57      );
  58      var $debug = 0;    // overwritten by constructor, set it in the sowiki class, not here
  59  
  60      /**
  61       * Constructor of the soWikiPage class, gets instanciated via the soWiki::page function
  62       *
  63       *  @param object $db db-object
  64       *  @param string $PgTbl name of pages-table
  65       *  @param string $name name of the wiki-page
  66       *  @param string/boolean $lang requested language or False
  67       *  @param int $wiki_id which wiki to use
  68       *  @param int $debug debug-value
  69       */
  70  	function soWikiPage($db,$PgTbl,$name = '',$lang=False,$wiki_id=0,$debug=0)
  71      {
  72          $this->db = $db;        // to have an independent result-pointer
  73          $this->db->set_app('wiki');
  74          $this->PgTbl = $PgTbl;
  75  
  76          $this->name = $name;
  77          $this->lang = $lang;
  78          $this->wiki_id = (int) $wiki_id;
  79          $this->memberships = $GLOBALS['egw']->accounts->membership();
  80          foreach($this->memberships as $n => $data)
  81          {
  82              $this->memberships[$n] = (int) $data['account_id'];
  83          }
  84          $this->user_lang = $GLOBALS['egw_info']['user']['preferences']['common']['lang'];
  85          $this->use_langs = array($this->user_lang,'');
  86          // english as fallback, should be configurable or a pref
  87          if ($this->user_lang != 'en') $this->use_langs[] = 'en';
  88          $this->lang_priority_sql  = "CASE WHEN wiki_body IS NULL THEN ".(count($this->use_langs)+1).' ELSE (CASE wiki_lang';
  89  
  90          foreach($this->use_langs as $order => $lang)
  91          {
  92              $this->lang_priority_sql .= ' WHEN '.$this->db->quote($lang)." THEN $order";
  93          }
  94          $this->lang_priority_sql  .= ' ELSE '.count($this->use_langs).' END) END AS lang_priority';
  95  
  96          // $GLOBALS['config'] is set by lib/init
  97          if (!is_array($GLOBALS['config']))
  98          {
  99              $c =& CreateObject('phpgwapi.config','wiki');
 100              $c->read_repository();
 101              $GLOBALS['config'] = $c->config_data;
 102              unset($c);
 103          }
 104          $this->config = &$GLOBALS['config'];
 105      }
 106  
 107      /**
 108       * filter to and into query to get only readable / writeable page of current user
 109       *
 110       * @param boolean $readable generate SQL for readable or writable filter, default True == readable
 111       * @param boolean $add_wiki_id add code to filter only the actual wiki
 112       * @return string SQL to AND into the query
 113       */
 114  	function acl_filter($readable = True,$add_wiki_id=True)
 115      {
 116          static $filters = array();
 117  
 118          $filter_id = "$readable-$add_wiki_id";
 119          if (isset($filters[$filter_id]))
 120          {
 121              return $filters[$filter_id];
 122          }
 123          $user = $GLOBALS['egw_info']['user']['account_id'];
 124  
 125          $filters[] = WIKI_ACL_ALL;
 126  
 127          if ($GLOBALS['egw_info']['user']['account_lid'] !=  $GLOBALS['config']['AnonymousUser'])
 128          {
 129              $filters[] = WIKI_ACL_USER;
 130          }
 131          if (@$GLOBALS['egw_info']['user']['apps']['admin'])
 132          {
 133              $filters[] = WIKI_ACL_ADMIN;
 134          }
 135          $filters = array_merge($filters,$this->memberships);
 136  
 137          $sql = '('.($add_wiki_id ? " wiki_id=$this->wiki_id AND " : '').
 138              ($readable ? 'wiki_readable' : 'wiki_writable').' IN ('.implode(',',$filters).'))';
 139          
 140          if ($this->debug) echo "<p>sowiki::acl_filter($readable,$add_wiki_id) = '$sql'</p>\n";
 141  
 142          return $filters[$filter_id] = $sql;
 143      }
 144  
 145      /**
 146       * check if page is readable or writeable by the current user
 147       *
 148       * If we have an anonymous session and the anonymous session-type is NOT editable,
 149       * all pages are readonly (even if their own setting is editable by all) !!!
 150       *
 151       *  * @paramboolean $readable check if page is readable or writable, default False == writeable
 152       * @return boolean true if check was successful, false otherwise
 153       */
 154  	function acl_check($readable = False)
 155      {
 156          if (!$readable && $this->config['Anonymous_Session_Type'] != 'editable' &&
 157              $GLOBALS['egw_info']['user']['account_lid'] == $this->config['anonymous_username'])
 158          {
 159              return False;    // Global config overrides page-specific setting
 160          }
 161          switch ($acl = $readable ? $this->readable : $this->writable)
 162          {
 163              case WIKI_ACL_ALL:
 164                  return True;
 165  
 166              case WIKI_ACL_USER:
 167                  return $GLOBALS['egw_info']['user']['account_lid'] !=  $this->config['anonymous_username'];
 168  
 169              case WIKI_ACL_ADMIN:
 170                  return  isset($GLOBALS['egw_info']['user']['apps']['admin']);
 171  
 172              default:
 173                  return in_array($acl,$this->memberships);
 174          }
 175          return False;
 176      }
 177  
 178      /**
 179       * Returns the class-vars belonging direct to the wiki-page as an array
 180       *
 181       * @return array
 182       */
 183  	function as_array()
 184      {
 185          $arr = array();
 186          foreach($this->colNames as $name)
 187          {
 188              $arr[$name] = $this->$name;
 189          }
 190          return $arr;
 191      }
 192  
 193      /**
 194       * Check if the page, which name, lang was set in the constructor, exists.
 195       *
 196       * @return boolean true if page exists in database, false otherwise
 197       */
 198  	function exists()
 199      {
 200          $this->db->select($this->PgTbl,'wiki_lang',array(
 201                  'wiki_name'    => $this->name,
 202                  'wiki_lang' => $this->use_langs,
 203                  $this->acl_filter(),
 204              ),__LINE__,__FILE__);
 205          
 206          return $this->db->next_record() ? ($this->db->f(0) ? $this->db->f(0) : 'default')  : False;
 207      }
 208  
 209      /**
 210       * Read in a page contents, name and lang was set in the constructor
 211       *
 212       * @return array/boolean contents of the page or False.
 213       */
 214  	function read()
 215      {
 216          $where = array(
 217              'wiki_name'    => $this->name,
 218              'wiki_lang' => !empty($this->lang) ? $this->lang : $this->use_langs,
 219              $this->acl_filter(),
 220          );
 221          if($this->version != -1)
 222          {
 223              $where['wiki_version'] = $this->version;
 224          }
 225          else
 226          {
 227              $where[] = 'wiki_supercede=wiki_time';    // gives the up-to-date version only
 228          }
 229          $this->db->select($this->PgTbl,"*,$this->lang_priority_sql",$where,__LINE__,__FILE__,false,'ORDER BY lang_priority');
 230  
 231          if (!$this->db->next_record())
 232          {
 233              return False;
 234          }
 235          foreach($this->colNames as $dbname => $name)
 236          {
 237              $this->$name     = $this->db->f($dbname);
 238          }
 239          $this->exists   = 1;
 240          $this->mutable  = $this->acl_check();
 241  
 242          return $this->text;
 243      }
 244  
 245      /**
 246       * Write the a page's contents to the db and sets the supercede-time of the prev. version
 247       *
 248       * The caller is responsible for performing locking.
 249       */
 250  	function write()
 251      {
 252          $this->time = $this->supercede = time();
 253          foreach($this->colNames as $dbname => $name)
 254          {
 255              $arr[$dbname] = $this->$name;
 256          }
 257          if (is_null($arr['wiki_comment'])) $arr['wiki_comment'] = '';    // can not be null
 258  
 259          if (empty($this->text))    unset($arr['wiki_body']);    // deleted / empty pages are written as SQL NULL
 260  
 261          $this->db->insert($this->PgTbl,$arr,false,__LINE__,__FILE__);
 262  
 263          if($this->version > 1)    // set supercede-time of prev. version
 264          {
 265              $this->db->update($this->PgTbl,array(
 266                      'wiki_supercede' => $this->supercede
 267                  ),array(
 268                      'wiki_id' => $this->wiki_id,
 269                      'wiki_name' => $this->name,
 270                      'wiki_lang' => $this->lang,
 271                      'wiki_version' => $this->version-1
 272                  ),__LINE__,__FILE__);
 273          }
 274      }
 275  
 276      /**
 277       * Renames a page to a new name and/or lang
 278       *
 279       * The caller is responsible for performing locking.
 280       * @param string/boolean $new_name to rename to or false if only a new language, default false
 281       * @param string/boolean $new_lang to rename to or false if only a new name, default false
 282       * @return int affected rows, 1=success, 0=not found
 283       */
 284  	function rename($new_name=False,$new_lang=False)
 285      {
 286          if ($new_name === False && $new_lang === False || !$this->acl_check())
 287          {
 288              if ($this->debug) echo "soWikiPage::rename('$new_name','$new_lang') returning False this=<pre>".print_r($this->as_array(),True)."</pre>";
 289              return False;    // nothing to do or no permission
 290          }
 291          $new = array(
 292              'wiki_id' => $this->wiki_id,
 293              'wiki_name'    => $new_name === False ? $this->name : $new_name,
 294              'wiki_lang'    => $new_lang === False ? $this->lang : $new_lang,
 295          );
 296          // delete (evtl.) existing target
 297          $this->db->delete($this->PgTbl,$new,__LINE__,__FILE__);
 298  
 299          $this->db->update($this->PgTbl,$new,array(
 300                  'wiki_id' => $this->wiki_id,
 301                  'wiki_name' => $this->name,
 302                  'wiki_lang' => $this->lang,
 303              ),__LINE__,__FILE__);
 304  
 305          if ($this->debug) echo "<p>soWikiPage::rename('$new_name','$new_lang') old='$this->name:$this->lang', sql='$sql', sql2='$sql2'</p>";
 306  
 307          if ($new_name !== False) $this->name = $new_name;
 308          if ($new_lang !== False) $this->lang = $new_lang;
 309  
 310          return $this->db->affected_rows();
 311      }
 312      
 313      /**
 314       * Returns colNames array, which translates column-names to internal names
 315       *
 316       * @return array with column-names as keys
 317       */
 318  	function column2names()
 319      {
 320          return $this->colNames;
 321      }     
 322  }
 323  
 324  /**
 325   * Wiki's storage-object was former called pageStore in WikiTikiTavi
 326   * @class sowiki
 327   * @author RalfBecker-AT-outdoor-training.de
 328   * @license GPL
 329   */
 330  class sowiki    // DB-Layer
 331  {
 332      var $db; /* @var $db db */
 333      var $LkTbl = 'egw_wiki_links';
 334      var $PgTbl = 'egw_wiki_pages';
 335      var $RtTbl = 'egw_wiki_rate';
 336      var $IwTbl = 'egw_wiki_interwiki';
 337      var $SwTbl = 'egw_wiki_sisterwiki';
 338      var $RemTbl= 'egw_wiki_remote_pages';
 339      var $ExpireLen,$Admin;
 340      var $RatePeriod,$RateView,$RateSearch,$RateEdit;
 341      var $wiki_id = 0;
 342      var $colNames=false;    // array converting column-names to internal names, set on the first call to sowiki::page
 343      var $debug = 0;
 344  
 345      /**
 346       * Constructor of the PageStrore class sowiki
 347       *
 348       * @param int $wikid_id which wiki to use, default 0
 349       */
 350  	function sowiki($wiki_id=0)
 351      {
 352          $this->wiki_id = (int) $wiki_id;
 353          $this->user_lang = $GLOBALS['egw_info']['user']['preferences']['common']['lang'];
 354  
 355          $this->db = clone($GLOBALS['egw']->db);
 356          $this->db->set_app('wiki');
 357          
 358          global $ExpireLen,$Admin;        // this should come from the app-config later
 359          global $RatePeriod, $RateView, $RateSearch, $RateEdit;
 360          $this->ExpireLen  = $ExpireLen;
 361          $this->Admin      = $Admin;
 362          $this->RatePeriod = $RatePeriod;
 363          $this->RateView   = $RateView;
 364          $this->RateSearch = $RateSearch;
 365          $this->RateEdit   = $RateEdit;
 366      }
 367  
 368      /**
 369       * Create a page object / instanciate the soWikiPage class.
 370       * @param string $name name of the page
 371       * @param string/boolean $lang language or false for the users default language-order
 372       * @return object soWikiPage class of the page
 373      */
 374      function &page($name = '',$lang=False)
 375      {
 376          if ($this->debug) echo "<p>sowiki::page(".print_r($name,True).",'$lang')</p>";
 377  
 378          if (is_array($name))
 379          {
 380              $lang = $lang ? $lang : @$name['lang'];
 381              $name = @$name['name'] ? $name['name'] : @$name['title'];
 382          }
 383          $page =& new soWikiPage($this->db,$this->PgTbl,$name,$lang,$this->wiki_id,$this->debug);
 384          
 385          if (!$this->colNames) $this->colNames = $page->column2names();
 386          
 387          return $page;
 388      }
 389  
 390          
 391      /**
 392       * Returns the SQL to retrive the length of the body-column
 393       *
 394       * MaxDB cant calculate the length of the content of a LONG column, we set it to 1,
 395       * we could retrive the complete column and use strlen on it, I dont do it as the length is only for sorting 
 396       * via a macro and that macro retrives all pages(!) - never used that macro ;-)
 397       *
 398       * @param string $table table-name of join alias incl. '.', or '' (default)
 399       * @return string the SQL
 400       */
 401  	function length_sql($table)
 402      {
 403          if ($this->db->Type == 'maxdb' || $this->db->Type == 'sapdb')
 404          {
 405              return '1';
 406          }
 407          return 'LENGTH('.$table.'wiki_body)';
 408      }
 409          
 410      /**
 411       * Find $text in the database, searches title and body.
 412       *
 413       * @param string $text pattern to search
 414       * @param string/boolean $search_in comma-separated string with columns to search (name,title,body) or false to search all three for "%text%" (!)
 415       * @return array of wiki-pages (array with column-name / value pairs)
 416       */
 417  	function find($text,$search_in=False)
 418      {
 419          $sql="SELECT t1.wiki_name,t1.wiki_lang,t1.wiki_version,MAX(t2.wiki_version) as wiki_max,t1.wiki_title,t1.wiki_body".
 420              " FROM $this->PgTbl AS t1,$this->PgTbl AS t2".
 421              " WHERE t1.wiki_name=t2.wiki_name AND t1.wiki_lang=t2.wiki_lang AND t1.wiki_id=$this->wiki_id AND t2.wiki_id=$this->wiki_id".
 422              " GROUP BY t1.wiki_name,t1.wiki_lang,t1.wiki_version,t1.wiki_title,t1.wiki_body".
 423              " HAVING t1.wiki_version=MAX(t2.wiki_version) AND (";
 424  
 425          // fix for case-insensitiv search on pgsql for lowercase searchwords
 426          $op_text = $this->db->type == 'pgsql' && !preg_match('/[A-Z]/') ? 'ILIKE' : 'LIKE';
 427          $op_text .= ' '.$this->db->quote($search_in ? $text : "%$text%");
 428  
 429          $search_in = $search_in ? explode(',',$search_in) : array('wiki_name','wiki_title','wiki_body');
 430          
 431          if ($this->db->Type == 'sapdb' || $this->db->Type == 'maxdb') 
 432          {
 433              $search_in = array_intersect($search_in,array('wiki_name','wiki_title'));
 434          }
 435          foreach($search_in as $n => $name)
 436          {
 437              $sql .= ($n ? ' OR ' : '') . "t1.$name $op_text";
 438          }
 439          $sql .= ')';
 440  
 441          $this->db->query($sql,__LINE__,__FILE__);
 442          
 443          return $this->_return_pages("find('$text','".implode(',',$search_in)."'");
 444      }
 445  
 446      /**
 447       * Retrieve a page's edit history.
 448       *
 449       * @param string/array $page name of the page or array with values for keys 'name' and 'lang' 
 450       * @param string/boolean $lang language to use or false if given via array in $name, default false 
 451       * @return an array of the different versions 
 452       */
 453  	function history($page,$lang=False)
 454      {
 455          $name = $this->db->db_addslashes(is_array($page) ? $page['name'] : $page);
 456          $lang = $this->db->db_addslashes(is_array($page) && !$lang ? $page['lang'] : $lang);
 457  
 458          $this->db->select($this->PgTbl,'wiki_time,wiki_hostname,wiki_version,wiki_username,wiki_comment',array(
 459                  'wiki_name'    => is_array($page) ? $page['name'] : $page,
 460                  'wiki_lang'    => is_array($page) && !$lang ? $page['lang'] : $lang,
 461                  'wiki_id'    => $this->wiki_id,
 462              ),__LINE__,__FILE__,False,'ORDER BY wiki_version DESC');
 463          
 464          return $this->_return_pages('history('.print_r($page,True).",'$lang')");
 465      }
 466  
 467      /**
 468       * Look up an interwiki prefix
 469       *
 470       * @param string $name name-prefix of an interwiki
 471       * @return string/boolean the url of False 
 472       */
 473  	function interwiki($name)
 474      {
 475          $this->db->select($this->IwTbl,'interwiki_url',array(
 476                  'wiki_id' => $this->wiki_id,
 477                  'interwiki_prefix'  => $name,
 478              ),__LINE__,__FILE__);
 479          
 480          return $this->db->next_record() ? $this->db->f('url') : False;
 481      }
 482  
 483      /**
 484       * Clear all the links cached for a particular page.
 485       *
 486       * @param string/array $page page-name or array with values for wiki_id, name and lang keys
 487       */
 488  	function clear_link($page)
 489      {
 490          if ($this->debug) echo "<p>sowiki::clear_link(".print_r($page,true)."</p>\n";
 491  
 492          $this->db->delete($this->LkTbl,array(
 493              'wiki_id' => is_array($page) && isset($page['wiki_id']) ? $page['wiki_id'] : $this->wiki_id,
 494              'wiki_name'    => is_array($page) ? $page['name'] : $page,
 495              'wiki_lang'    => $page['lang'],
 496          ),__LINE__,__FILE__);
 497      }
 498  
 499      /**
 500       * Clear all the interwiki definitions for a particular page.
 501       *
 502       * @param string/array $page page-name or array with values for wiki_id, name and lang keys
 503       */
 504  	function clear_interwiki($page)
 505      {
 506          if ($this->debug) echo "<p>sowiki::clear_interwiki(".print_r($page,true)."</p>\n";
 507  
 508          $this->db->delete($this->IwTbl,array(
 509              'wiki_id' => is_array($page) && isset($page['wiki_id']) ? $page['wiki_id'] : $this->wiki_id,
 510              'wiki_name'    => is_array($page) ? $page['name'] : $page,
 511              'wiki_lang'    => $page['lang'],
 512          ),__LINE__,__FILE__);
 513      }
 514  
 515      /**
 516       * Clear all the sisterwiki definitions for a particular page.
 517       *
 518       * @param string/array $page page-name or array with values for wiki_id, name and lang keys
 519       */
 520  	function clear_sisterwiki($page)
 521      {
 522          if ($this->debug) echo "<p>sowiki::clear_sisterwiki(".print_r($page,true)."</p>\n";
 523  
 524          $this->db->delete($this->SwTbl,array(
 525              'wiki_id' => is_array($page) && isset($page['wiki_id']) ? $page['wiki_id'] : $this->wiki_id,
 526              'wiki_name'    => is_array($page) ? $page['name'] : $page,
 527              'wiki_lang'    => $page['lang'],
 528          ),__LINE__,__FILE__);
 529      }
 530  
 531      /**
 532       * Add a link for a given page to the link table.
 533       *
 534       * @param string/array $page page-name or array with values for wiki_id, name and lang keys
 535       * @param string $link the link to add
 536       */
 537  	function new_link($page, $link)
 538      {
 539          static $links = array();
 540  
 541          $where = array(
 542              'wiki_id' => is_array($page) && isset($page['wiki_id']) ? $page['wiki_id'] : $this->wiki_id,
 543              'wiki_name'    => trim(is_array($page) ? $page['name'] : $page),
 544              'wiki_lang'    => $page['lang'],
 545              'wiki_link'    => trim($link),
 546          );
 547          // $links need to be 2-dimensional as rename, can cause new_link to be called for different pages
 548          $page_uid = strtolower($where['wiki_id'].':'.$where['page'].':'.$where['lang']);
 549          $link = strtolower(trim($link));
 550          
 551          $data = array('wiki_count' => ++$links[$page_uid][$link]);
 552  
 553          if ($this->debug) echo "<p>sowiki::new_link('$where[wiki_id]:$where[wiki_name]:$where[wiki_lang]','$link') = $data[wiki_count]</p>";
 554  
 555          if ($where['wiki_count'] == 1)
 556          {
 557              $this->db->insert($this->LkTbl,array_merge($data,$where),False,__LINE__,__FILE__);
 558          }
 559          else
 560          {
 561              $this->db->update($this->LkTbl,$data,$where,__LINE__,__FILE__);
 562          }
 563      }
 564  
 565      /**
 566       * Retrives all links on all pages and all languages
 567       *
 568       * @param string $link if none-empty, only these links are retrived
 569       * @return array 2-dim. array with linking pages and languages, eg. $arr[$page][$lang] = $link
 570       */
 571  	function get_links($link='')
 572      {
 573          $where = array('wiki_id' => $this->wiki_id);
 574          if ($link)
 575          {
 576              $where['wiki_link'] = $link;
 577          }
 578          $this->db->select($this->LkTbl,'wiki_name,wiki_lang,wiki_link',$where,__LINE__,__FILE__,false,
 579              'ORDER BY wiki_name,wiki_lang');
 580  
 581          $result = array();
 582          while ($row = $this->db->row(True))
 583          {
 584              $result[$row['wiki_name']][$row['wiki_lang']][] = $row['wiki_link'];
 585          }
 586          return $result;
 587      }
 588  
 589      /**
 590       * Add an interwiki definition for a particular page.
 591       *
 592       * @param string/array $page page-name or array with values for name, lang and evtl. wiki_id (this->wiki_id is used if not)
 593       * @param string $prefix Prefix of the new interwiki
 594       * @param string $url URL of the new interwiki
 595       */
 596  	function new_interwiki($page, $prefix, $url)
 597      {
 598          $this->db->insert($this->IwTbl,array(
 599                  'wiki_name'        => is_array($page) ? $page['name'] : $page,
 600                  'wiki_lang'        => $page['lang'],
 601                  'interwiki_url'    => str_replace('&amp;','&',$url),
 602              ),array(
 603                  'wiki_id'          => is_array($page) && isset($page['wiki_id']) ? $page['wiki_id'] : $this->wiki_id,
 604                  'interwiki_prefix' => $prefix,
 605              ),__LINE__,__FILE__);
 606      }
 607  
 608      /**
 609       * Add an sisterwiki definition for a particular page.
 610       *
 611       * @param string/array $page page-name or array with values for name, lang and evtl. wiki_id (this->wiki_id is used if not)
 612       * @param string $prefix Prefix of the new interwiki
 613       * @param string $url URL of the new interwiki
 614       */
 615  	function new_sisterwiki($page, $prefix, $url)
 616      {
 617          $this->db->insert($this->SwTbl,array(
 618                  'wiki_name'        => is_array($page) ? $page['name'] : $page,
 619                  'wiki_lang'        => $page['lang'],
 620                  'interwiki_url'    => str_replace('&amp;','&',$url),
 621              ),array(
 622                  'wiki_id'          => is_array($page) && isset($page['wiki_id']) ? $page['wiki_id'] : $this->wiki_id,
 623                  'interwiki_prefix' => $prefix,
 624              ),__LINE__,__FILE__);
 625      }
 626  
 627      /**
 628       * Find all twins of a page at sisterwiki sites.
 629       *
 630       * @param string/array $page page-name or array with values for name
 631       * @return array list of array(site,page)
 632       */
 633  	function twinpages($page)
 634      {
 635          $this->db->query("SELECT wiki_remote_site, wiki_remote_page FROM $this->RemTbl WHERE wiki_remote_page=".
 636              $this->db->quote(is_array($page) ? $page['name'] : $page),__LINE__,__FILE__);
 637  
 638          $list = array();
 639          while($this->db->next_record())
 640          { 
 641              $list[] = array(
 642                  'site' => $this->db->f('wiki_remote_site'),
 643                  'page' => $this->db->f('wiki_remote_page'),
 644              );
 645          }
 646          return $list;
 647      }
 648  
 649      /*
 650       * Lock all wiki database tables.
 651       */
 652  	function lock()
 653      {
 654          $this->db->lock(array($this->PgTbl,$this->IwTbl,$this->SwTbl,$this->LkTbl),'write');
 655      }
 656  
 657      /*
 658       * Unlock all database tables.
 659       */
 660  	function unlock()
 661      {
 662          $this->db->unlock();
 663      }
 664  
 665      /*
 666       * Retrieve a list of all of the pages in the wiki.
 667       *
 668       * @return array of all pages
 669       */
 670  	function allpages()
 671      {
 672          $qid = $this->db->query("SELECT t1.wiki_time,t1.wiki_name,t1.wiki_lang,t1.wiki_hostname,t1.wiki_username,t1.wiki_title,".$this->length_sql('t1.').
 673                                                          " AS wiki_length,t1.wiki_comment,t1.wiki_version,MAX(t2.wiki_version)" .
 674                                                          " FROM $this->PgTbl AS t1, $this->PgTbl AS t2" .
 675                                                          " WHERE t1.wiki_name = t2.wiki_name AND t1.wiki_lang=t2.wiki_lang AND t1.wiki_id=t2.wiki_id AND t1.wiki_id=".(int)$this->wiki_id.
 676                                                          " GROUP BY t1.wiki_name,t1.wiki_lang,t1.wiki_version,t1.wiki_time,t1.wiki_hostname,t1.wiki_username,t1.wiki_body,t1.wiki_comment,t1.wiki_title" .
 677                                                          " HAVING t1.wiki_version = MAX(t2.wiki_version)",__LINE__,__FILE__);
 678  
 679          return $this->_return_pages('allpages()');
 680      }
 681      
 682      /**
 683       * Create array of page-arrays from the returned rows of a query
 684       *
 685       * @internal
 686       * @param string $func calling function incl. parameters for debug-message
 687       */
 688  	function _return_pages($func)
 689      {
 690          if (!$this->colNames)
 691          {
 692              $page =& new soWikiPage($this->db,$this->PgTbl);
 693              $this->colNames = $page->column2names();
 694              unset($page);
 695          }
 696          $list = array();
 697          while($this->db->next_record())
 698          {
 699              $page = array();
 700              foreach($this->db->Record as $col => $val)
 701              {
 702                  $name = isset($this->colNames[$col]) ? $this->colNames[$col] : ($name == 'wiki_length' ? 'length' : $col);
 703                  $page[$name] = $val;
 704              }    
 705              $list[] = $page;
 706          }
 707          if ($this->debug) echo "<p>sowiki::$func<pre>".print_r($list,true)."</pre>\n";
 708  
 709          return $list;
 710      }
 711  
 712      /*
 713       * Retrieve a list of the new pages in the wiki.
 714       *
 715       * @return array of pages
 716       */
 717  	function newpages()
 718      {
 719          $this->db->select($this->PgTbl,'wiki_time,wiki_name,wiki_lang,wiki_hostname,wiki_username,'.$this->length_sql().' AS wiki_length,wiki_comment,wiki_title',
 720              array(
 721                  'wiki_id' => $this->wiki_id,
 722                  'wiki_version=1',
 723              ),__LINE__,__FILE__);
 724  
 725          return $this->_return_pages('newpages()');
 726      }
 727  
 728      /*
 729       * Retrieve a list of all empty (deleted) pages in the wiki.
 730       *
 731       * @return array of pages
 732       */
 733  	function emptypages()
 734      {
 735          $this->db->query("SELECT t1.wiki_time,t1.wiki_name,t1.wiki_lang,t1.wiki_hostname,t1.wiki_username,0,t1.wiki_comment,t1.wiki_version,MAX(t2.wiki_version),t1.wiki_title " .
 736                                           " FROM $this->PgTbl AS t1,$this->PgTbl AS t2" .
 737                                           " WHERE t1.wiki_name=t2.wiki_name AND t1.wiki_lang=t2.wiki_lang AND t1.wiki_id=t2.wiki_id AND t1.wiki_id=".(int)$this->wiki_id.
 738                                           " GROUP BY t1.wiki_name,t1.wiki_lang,t1.wiki_version,t1.wiki_time,t1.wiki_hostname,t1.wiki_username,t1.wiki_comment".
 739                                           " HAVING t1.wiki_version = MAX(t2.wiki_version) AND t1.wiki_body IS NULL",__LINE__,__FILE__);
 740  
 741          return $this->_return_pages('emptypages()');
 742      }
 743  
 744      /*
 745       * Retrieve a list of information about a particular set of pages
 746       *
 747       * @param array $names array of page-names
 748       * @return array of pages
 749       */
 750  	function givenpages($names)
 751      {
 752          $list = array();
 753          foreach($names as $page)
 754          {
 755              $this->db->select($this->PgTbl,'wiki_time,wiki_name,wiki_hostname,wiki_username,'.$this->length_sql().' AS wiki_length,wiki_comment,wiki_title',array(
 756                  'wiki_name' => $page,
 757                  'wiki_id'    => $this->wiki_id,
 758                  ),__LINE__,__FILE__,False,'ORDER BY wiki_version DESC');
 759  
 760              $list = array_merge($list,$this->_return_pages('givenpages('.@print_r($names,true).')'));
 761          }
 762          return $list;
 763      }
 764  
 765      /**
 766       * Expire old versions of pages.
 767       */
 768  	function maintain()
 769      {
 770          $this->db->delete($this->PgTbl,"(wiki_time!=wiki_supercede OR wiki_body IS NULL) AND ".
 771              "wiki_supercede<".(time()-86400*$this->ExpireLen),__LINE__,__FILE__);
 772  
 773          if($this->RatePeriod)
 774          {
 775              $this->db->delete($this->RtTbl,"wiki_rate_ip NOT LIKE '%.*' AND " .
 776                  intval(time()/86400)." > wiki_rate_time/86400",__LINE__,__FILE__);
 777          }
 778      }
 779  
 780      /**
 781       * Perform a lookup on an IP addresses edit-rate.
 782       *
 783       * @param string $type 'view',' search' or 'edit'
 784       * @param string $remote_addr eg. $_SERVER['REMOTE_ADDR']
 785       */
 786  	function rateCheck($type,$remote_addr)
 787      {
 788          if(!$this->RatePeriod)
 789          { 
 790              return;
 791          }
 792  
 793          $this->db->lock($this->RtTbl,'WRITE');
 794  
 795          // Make sure this IP address hasn't been excluded.
 796  
 797          $fields = explode(".", $remote_addr);
 798          $this->db->select($this->RtTbl,'*',"wiki_rate_ip='$fields[0].*'".
 799              " OR wiki_rate_ip='$fields[0].$fields[1].*'".
 800              " OR wiki_rate_ip='$fields[0].$fields[1].$fields[2].*'",__LINE__,__FILE__);
 801          
 802          if ($this->db->next_record())
 803          {
 804              global $ErrorDeniedAccess;
 805              die($ErrorDeniedAccess);
 806          }
 807  
 808          // Now check how many more actions we can perform.
 809  
 810          $this->db->select($this->RtTbl,'wiki_rate_time,wiki_rate_viewLimit,wiki_rate_searchLimit,wiki_rate_editLimit',array(
 811                  'wiki_rate_ip' => $remote_addr
 812              ),__LINE__,__FILE__);
 813  
 814          if(!$this->db->next_record())
 815          { 
 816              $result = array(-1, $this->RateView, $this->RateSearch, $this->RateEdit); 
 817          }
 818          else
 819          {
 820              $result = $this->db->Record;
 821  
 822              $result[0] = time()-$result[0];
 823              if ($result[0]  < 0)
 824              { 
 825                  $result[0] = $this->RatePeriod; 
 826              }
 827              $result[1] = min($result[1] + $result[0] * $this->RateView / $this->RatePeriod,$this->RateView);
 828              $result[2] = min($result[2] + $result[0] * $this->RateSearch / $this->RatePeriod,$this->RateSearch);
 829              $result[3] = min($result[3] + $result[0] * $this->RateEdit / $this->RatePeriod,$this->RateEdit);
 830          }
 831  
 832          switch($type)
 833          {
 834              case 'view':    $result[1]--; break;
 835              case 'search':    $result[2]--; break;
 836              case 'edit':    $result[3]--; break;
 837          }
 838          if($result[1] < 0 || $result[2] < 0 || $result[3] < 0)
 839          {
 840              global $ErrorRateExceeded;
 841              die($ErrorRateExceeded);
 842          }
 843  
 844          // Record this action.
 845  
 846          $this->db->insert($this->RtTbl,array(
 847                  'wiki_rate_viewLimit'    => $result[1],
 848                  'wiki_rate_searchLimit'    => $result[2],
 849                  'wiki_rate_editLimit'    => $result[3],
 850                  'wiki_rate_time'        => time(),
 851              ),array(
 852                  'wiki_rate_ip' => $remote_addr
 853              ),__LINE__,__FILE__);
 854  
 855          $this->db->unlock();
 856      }
 857  
 858      /**
 859       * Return a list of blocked address ranges.
 860       *
 861       * @return array of blocked address-ranges
 862       */
 863  	function rateBlockList()
 864      {
 865          $list = array();
 866  
 867          if(!$this->RatePeriod)
 868          { 
 869              return $list; 
 870          }
 871          $this->db->select($this->RtTbl,'wiki_rate_ip',false,__LINE__,__FILE__);
 872          
 873          while($this->db->next_record())
 874          {
 875              if(preg_match('/^\\d+\\.(\\d+\\.(\\d+\\.)?)?\\*$/',$this->db->f('wiki_rate_ip')))
 876              { 
 877                  $list[] = $this->db->f('wiki_rate_ip');
 878              }
 879          }
 880          return $list;
 881      }
 882  
 883      /**
 884       * Block an address range.
 885       *
 886       * @param string $address ip-addr. or addr-range
 887       */
 888  	function rateBlockAdd($address)
 889      {
 890          if(preg_match('/^\\d+\\.(\\d+\\.(\\d+\\.)?)?\\*$/', $address))
 891          {
 892              $this->db->select($this->RtTbl,'*',array(
 893                      'wiki_rate_ip' => $address
 894                  ),__LINE__,__FILE__);
 895  
 896              if(!$this->db->next_record())
 897              {
 898                  $this->db->insert($this->RtTbl,array(
 899                          'wiki_rate_ip'    => $address,
 900                          'wiki_rate_time'=> time(),
 901                      ),__LINE__,__FILE__);
 902              }
 903          }
 904      }
 905  
 906      /**
 907       * Remove an address-range block.
 908       *
 909       * @param string $address ip-addr. or addr-range
 910       */
 911  	function rateBlockRemove($address)
 912      {
 913          $this->db->delete($this->RtTbl,array('wiki_rate_ip' => $address),__LINE__,__FILE__);
 914      }
 915  }
 916  ?>


Généré le : Sun Feb 25 17:20:01 2007 par Balluche grâce à PHPXref 0.7