]> CyberLeo.Net >> Repos - SourceForge/phpwiki.git/blob - lib/WikiDB/backend.php
Activated Id substitution for Subversion
[SourceForge/phpwiki.git] / lib / WikiDB / backend.php
1 <?php // -*-php-*-
2 rcs_id('$Id$');
3
4 /*
5   Pagedata
6
7    maintained by WikiPage 
8     //:latestversion
9     //:deleted (*)     (Set if latest content is empty.)
10     //:pagename (*)
11
12     hits
13     is_locked
14
15   Versiondata
16
17     %content (?should this be here?)
18     _supplanted : Time version ceased to be the current version
19
20     mtime (*)   : Time of version edit.
21     orig_mtime
22     is_minor_edit (*)
23     author      : nominal author
24     author_id   : authenticated author
25     summary
26
27     //version
28     //created (*)
29     //%superceded
30         
31     //:serial
32
33      (types are scalars: strings, ints, bools)
34 */     
35
36 /**
37  * A WikiDB_backend handles the storage and retrieval of data for a WikiDB.
38  *
39  * It does not have to be this way, of course, but the standard WikiDB uses
40  * a WikiDB_backend.  (Other WikiDB's could be written which use some other
41  * method to access their underlying data store.)
42  *
43  * The interface outlined here seems to work well with both RDBM based
44  * and flat DBM/hash based methods of data storage.
45  *
46  * Though it contains some default implementation of certain methods,
47  * this is an abstract base class.  It is expected that most efficient
48  * backends will override nearly all the methods in this class.
49  *
50  * @access protected
51  * @see WikiDB
52  */
53 class WikiDB_backend
54 {
55     /**
56      * Get page meta-data from database.
57      *
58      * @param $pagename string Page name.
59      * @return hash
60      * Returns a hash containing the page meta-data.
61      * Returns an empty array if there is no meta-data for the requested page.
62      * Keys which might be present in the hash are:
63      * <dl>
64      *  <dt> locked  <dd> If the page is locked.
65      *  <dt> hits    <dd> The page hit count.
66      *  <dt> created <dd> Unix time of page creation. (FIXME: Deprecated: I
67      *                    don't think we need this...) 
68      * </dl>
69      */
70     function get_pagedata($pagename) {
71         trigger_error("virtual", E_USER_ERROR);
72     }
73
74     /**
75      * Update the page meta-data.
76      *
77      * Set page meta-data.
78      *
79      * Only meta-data whose keys are preset in $newdata is affected.
80      *
81      * For example:
82      * <pre>
83      *   $backend->update_pagedata($pagename, array('locked' => 1)); 
84      * </pre>
85      * will set the value of 'locked' to 1 for the specified page, but it
86      * will not affect the value of 'hits' (or whatever other meta-data
87      * may have been stored for the page.)
88      *
89      * To delete a particular piece of meta-data, set its value to false.
90      * <pre>
91      *   $backend->update_pagedata($pagename, array('locked' => false)); 
92      * </pre>
93      *
94      * @param $pagename string Page name.
95      * @param $newdata hash New meta-data.
96      */
97     function update_pagedata($pagename, $newdata) {
98         trigger_error("virtual", E_USER_ERROR);
99     }
100     
101
102     /**
103      * Get the current version number for a page.
104      *
105      * @param $pagename string Page name.
106      * @return int The latest version number for the page.  Returns zero if
107      *  no versions of a page exist.
108      */
109     function get_latest_version($pagename) {
110         trigger_error("virtual", E_USER_ERROR);
111     }
112     
113     /**
114      * Get preceding version number.
115      *
116      * @param $pagename string Page name.
117      * @param $version int Find version before this one.
118      * @return int The version number of the version in the database which
119      *  immediately preceeds $version.
120      */
121     function get_previous_version($pagename, $version) {
122         trigger_error("virtual", E_USER_ERROR);
123     }
124     
125     /**
126      * Get revision meta-data and content.
127      *
128      * @param $pagename string Page name.
129      * @param $version integer Which version to get.
130      * @param $want_content boolean
131      *  Indicates the caller really wants the page content.  If this
132      *  flag is not set, the backend is free to skip fetching of the
133      *  page content (as that may be expensive).  If the backend omits
134      *  the content, the backend might still want to set the value of
135      *  '%content' to the empty string if it knows there's no content.
136      *
137      * @return hash The version data, or false if specified version does not
138      *    exist.
139      *
140      * Some keys which might be present in the $versiondata hash are:
141      * <dl>
142      * <dt> %content
143      *  <dd> This is a pseudo-meta-data element (since it's actually
144      *       the page data, get it?) containing the page content.
145      *       If the content was not fetched, this key may not be present.
146      * </dl>
147      * For description of other version meta-data see WikiDB_PageRevision::get().
148      * @see WikiDB_PageRevision::get
149      */
150     function get_versiondata($pagename, $version, $want_content = false) {
151         trigger_error("virtual", E_USER_ERROR);
152     }
153
154     /**
155      * Delete page from the database with backup possibility.
156      * This should remove all links (from the named page) from
157      * the link database.
158      *
159      * @param $pagename string Page name.
160      * i.e save_page('') and DELETE nonempty id
161      * Can be undone and is seen in RecentChanges.
162      */
163     function delete_page($pagename) {
164         $mtime = time();
165         $user =& $GLOBALS['request']->_user;
166         $vdata = array('author' => $user->getId(),
167                        'author_id' => $user->getAuthenticatedId(),
168                        'mtime' => $mtime);
169
170         $this->lock(); // critical section:
171         $version = $this->get_latest_version($pagename);
172         $this->set_versiondata($pagename, $version+1, $vdata);
173         $this->set_links($pagename, false); // links are purged.
174         // SQL needs to invalidate the non_empty id
175         if (! WIKIDB_NOCACHE_MARKUP) {
176             // need the hits, perms and LOCKED, otherwise you can reset the perm 
177             // by action=remove and re-create it with default perms
178             $pagedata = $this->get_pagedata($pagename); 
179             unset($pagedata['_cached_html']);
180             $this->update_pagedata($pagename, $pagedata);
181         }
182         $this->unlock();
183     }
184
185     /**
186      * Delete page (and all it's revisions) from the database.
187      *
188      */
189     function purge_page($pagename) {
190         trigger_error("virtual", E_USER_ERROR);
191     }
192
193     /**
194      * Delete an old revision of a page.
195      *
196      * Note that one is never allowed to delete the most recent version,
197      * but that this requirement is enforced by WikiDB not by the backend.
198      *
199      * In fact, to be safe, backends should probably allow the deletion of
200      * the most recent version.
201      *
202      * @param $pagename string Page name.
203      * @param $version integer Version to delete.
204      */
205     function delete_versiondata($pagename, $version) {
206         trigger_error("virtual", E_USER_ERROR);
207     }
208
209     /**
210      * Create a new page revision.
211      *
212      * If the given ($pagename,$version) is already in the database,
213      * this method completely overwrites any stored data for that version.
214      *
215      * @param $pagename string Page name.
216      * @param $version int New revisions content.
217      * @param $data hash New revision metadata.
218      *
219      * @see get_versiondata
220      */
221     function set_versiondata($pagename, $version, $data) {
222         trigger_error("virtual", E_USER_ERROR);
223     }
224
225     /**
226      * Update page version meta-data.
227      *
228      * If the given ($pagename,$version) is already in the database,
229      * this method only changes those meta-data values whose keys are
230      * explicity listed in $newdata.
231      *
232      * @param $pagename string Page name.
233      * @param $version int New revisions content.
234      * @param $newdata hash New revision metadata.
235      * @see set_versiondata, get_versiondata
236      */
237     function update_versiondata($pagename, $version, $newdata) {
238         $data = $this->get_versiondata($pagename, $version, true);
239         if (!$data) {
240             assert($data);
241             return;
242         }
243         foreach ($newdata as $key => $val) {
244             if (empty($val))
245                 unset($data[$key]);
246             else
247                 $data[$key] = $val;
248         }
249         $this->set_versiondata($pagename, $version, $data);
250     }
251     
252     /**
253      * Set links for page.
254      *
255      * @param $pagename string Page name.
256      *
257      * @param $links array List of page(names) which page links to.
258      */
259     function set_links($pagename, $links) {
260         trigger_error("virtual", E_USER_ERROR);
261     }
262         
263     /**
264      * Find pages which link to or are linked from a page.
265      *
266      * @param $pagename string Page name.
267      * @param $reversed boolean True to get backlinks.
268      *
269      * FIXME: array or iterator?
270      * @return object A WikiDB_backend_iterator.
271      */
272     function get_links($pagename, $reversed, $include_empty=false,
273                        $sortby='', $limit='', $exclude='') {
274         //FIXME: implement simple (but slow) link finder.
275         die("FIXME get_links");
276     }
277
278     /**
279      * Get all revisions of a page.
280      *
281      * @param $pagename string The page name.
282      * @return object A WikiDB_backend_iterator.
283      */
284     function get_all_revisions($pagename) {
285         include_once('lib/WikiDB/backend/dumb/AllRevisionsIter.php');
286         return new WikiDB_backend_dumb_AllRevisionsIter($this, $pagename);
287     }
288     
289     /**
290      * Get all pages in the database.
291      *
292      * Pages should be returned in alphabetical order if that is
293      * feasable.
294      *
295      * @access protected
296      *
297      * @param $include_defaulted boolean
298      * If set, even pages with no content will be returned
299      * --- but still only if they have at least one revision (not
300      * counting the default revision 0) entered in the database.
301      *
302      * Normally pages whose current revision has empty content
303      * are not returned as these pages are considered to be
304      * non-existing.
305      *
306      * @return object A WikiDB_backend_iterator.
307      */
308     function get_all_pages($include_defaulted, $orderby=false, $limit='', $exclude='') {
309         trigger_error("virtual", E_USER_ERROR);
310     }
311         
312     /**
313      * Title or full text search.
314      *
315      * Pages should be returned in alphabetical order if that is
316      * feasable.
317      *
318      * @access protected
319      *
320      * @param $search object A TextSearchQuery object describing the parsed query string, 
321      *                       with efficient methods for SQL and PCRE match.
322      *
323      * @param $fullsearch boolean If true, a full text search is performed,
324      *  otherwise a title search is performed.
325      *
326      * @return object A WikiDB_backend_iterator.
327      *
328      * @see WikiDB::titleSearch
329      */
330     function text_search($search, $fulltext=false, $sortby='', 
331                          $limit='', $exclude='') 
332     {
333         // This method implements a simple linear search
334         // through all the pages in the database.
335         //
336         // It is expected that most backends will overload
337         // this method with something more efficient.
338         include_once('lib/WikiDB/backend/dumb/TextSearchIter.php');
339         // ignore $limit
340         $pages = $this->get_all_pages(false, $sortby, false, $exclude);
341         return new WikiDB_backend_dumb_TextSearchIter($this, $pages, $search, $fulltext, 
342                                                       array('limit'   => $limit, 
343                                                             'exclude' => $exclude));
344     }
345
346
347     /**
348      *
349      * @access protected
350      * @param $pages     object A TextSearchQuery object.
351      * @param $linkvalue object A TextSearchQuery object for the linkvalues 
352      *                          (linkto, relation or backlinks or attribute values).
353      * @param $linktype  string One of the 4 linktypes.
354      * @param $relation  object A TextSearchQuery object or false.
355      * @param $options   array Currently ignored. hash of sortby, limit, exclude.
356      * @return object A WikiDB_backend_iterator.
357      * @see WikiDB::linkSearch
358      */
359     function link_search( $pages, $linkvalue, $linktype, $relation=false, $options=array() ) {
360         include_once('lib/WikiDB/backend/dumb/LinkSearchIter.php');
361         $pageiter = $this->text_search($pages);
362         return new WikiDB_backend_dumb_LinkSearchIter($this, $pageiter, $linkvalue, $linktype, $relation, $options);
363     }
364
365     /**
366      * Find pages with highest hit counts.
367      *
368      * Find the pages with the highest hit counts.  The pages should
369      * be returned in reverse order by hit count.
370      *
371      * @access protected
372      * @param integer $limit No more than this many pages
373      * @return object A WikiDB_backend_iterator.
374      */
375     function most_popular($limit, $sortby='-hits') {
376         // This is method fetches all pages, then
377         // sorts them by hit count.
378         // (Not very efficient.)
379         //
380         // It is expected that most backends will overload
381         // method with something more efficient.
382         include_once('lib/WikiDB/backend/dumb/MostPopularIter.php');
383         $pages = $this->get_all_pages(false, $sortby, false);
384         return new WikiDB_backend_dumb_MostPopularIter($this, $pages, $limit);
385     }
386
387     /**
388      * Find recent changes.
389      *
390      * @access protected
391      * @param $params hash See WikiDB::mostRecent for a description
392      *  of parameters which can be included in this hash.
393      * @return object A WikiDB_backend_iterator.
394      * @see WikiDB::mostRecent
395      */
396     function most_recent($params) {
397         // This method is very inefficient and searches through
398         // all pages for the most recent changes.
399         //
400         // It is expected that most backends will overload
401         // method with something more efficient.
402         include_once('lib/WikiDB/backend/dumb/MostRecentIter.php');
403         $pages = $this->get_all_pages(true, '-mtime');
404         return new WikiDB_backend_dumb_MostRecentIter($this, $pages, $params);
405     }
406
407     function wanted_pages($exclude_from='', $exclude='', $sortby='', $limit='') {
408         include_once('lib/WikiDB/backend/dumb/WantedPagesIter.php');
409         $allpages = $this->get_all_pages(true,false,false,$exclude_from);
410         return new WikiDB_backend_dumb_WantedPagesIter($this, $allpages, $exclude, $sortby, $limit);
411     }
412
413     /**
414      * Lock backend database.
415      *
416      * Calls may be nested.
417      *
418      * @param $write_lock boolean Unless this is set to false, a write lock
419      *     is acquired, otherwise a read lock.  If the backend doesn't support
420      *     read locking, then it should make a write lock no matter which type
421      *     of lock was requested.
422      *
423      *     All backends <em>should</em> support write locking.
424      */
425     function lock($write_lock = true) {
426     }
427
428     /**
429      * Unlock backend database.
430      *
431      * @param $force boolean Normally, the database is not unlocked until
432      *  unlock() is called as many times as lock() has been.  If $force is
433      *  set to true, the the database is unconditionally unlocked.
434      */
435     function unlock($force = false) {
436     }
437
438
439     /**
440      * Close database.
441      */
442     function close () {
443     }
444
445     /**
446      * Synchronize with filesystem.
447      *
448      * This should flush all unwritten data to the filesystem.
449      */
450     function sync() {
451     }
452
453     /**
454      * Optimize the database.
455      */
456     function optimize() {
457     }
458
459     /**
460      * Check database integrity.
461      *
462      * This should check the validity of the internal structure of the database.
463      * Errors should be reported via:
464      * <pre>
465      *   trigger_error("Message goes here.", E_USER_WARNING);
466      * </pre>
467      *
468      * @return boolean True iff database is in a consistent state.
469      */
470     function check($args=false) {
471     }
472
473     /**
474      * Put the database into a consistent state 
475      * by reparsing and restoring all pages.
476      *
477      * This should put the database into a consistent state.
478      * (I.e. rebuild indexes, etc...)
479      *
480      * @return boolean True iff successful.
481      */
482     function rebuild($args=false) {
483         global $request;
484         $dbh = $request->getDbh();
485         $iter = $dbh->getAllPages(false);
486         while ($page = $iter->next()) {
487             $current = $page->getCurrentRevision(true);
488             $pagename = $page->getName();
489             $meta = $current->_data;
490             $version = $current->getVersion();
491             $content =& $meta['%content'];
492             $formatted = new TransformedText($page, $content, $current->getMetaData());
493             $type = $formatted->getType();
494             $meta['pagetype'] = $type->getName();
495             $links = $formatted->getWikiPageLinks(); // linkto => relation
496             $this->lock(array('version','page','recent','link','nonempty'));
497             $this->set_versiondata($pagename, $version, $meta);
498             $this->set_links($pagename, $links);
499             $this->unlock(array('version','page','recent','link','nonempty'));
500         }
501     }
502
503     function _parse_searchwords($search) {
504         $search = strtolower(trim($search));
505         if (!$search)
506             return array(array(),array());
507         
508         $words = preg_split('/\s+/', $search);
509         $exclude = array();
510         foreach ($words as $key => $word) {
511             if ($word[0] == '-' && $word != '-') {
512                 $word = substr($word, 1);
513                 $exclude[] = preg_quote($word);
514                 unset($words[$key]);
515             }
516         }
517         return array($words, $exclude);
518     }
519
520     /** 
521      * Split the given limit parameter into offset,limit. (offset is optional. default: 0)
522      * Duplicate the PageList function here to avoid loading the whole PageList.php 
523      * Usage: 
524      *   list($offset,$count) = $this->limit($args['limit']);
525      */
526     function limit($limit) {
527         if (strstr($limit, ','))
528             return split(',', $limit);
529         else
530             return array(0, $limit);
531     }
532     
533     /** 
534      * Handle sortby requests for the DB iterator and table header links.
535      * Prefix the column with + or - like "+pagename","-mtime", ...
536      * supported actions: 'flip_order' "mtime" => "+mtime" => "-mtime" ...
537      *                    'db'         "-pagename" => "pagename DESC"
538      * In PageList all columns are sortable. (patch by DanFr)
539      * Here with the backend only some, the rest is delayed to PageList.
540      * (some kind of DumbIter)
541      * Duplicate the PageList function here to avoid loading the whole 
542      * PageList.php, and it forces the backend specific sortable_columns()
543      */
544     function sortby ($column, $action, $sortable_columns=false) {
545         if (empty($column)) return '';
546         //support multiple comma-delimited sortby args: "+hits,+pagename"
547         if (strstr($column, ',')) {
548             $result = array();
549             foreach (explode(',', $column) as $col) {
550                 if (empty($this))
551                     $result[] = WikiDB_backend::sortby($col, $action);
552                 else
553                     $result[] = $this->sortby($col, $action);
554             }
555             return join(",",$result);
556         }
557         if (substr($column,0,1) == '+') {
558             $order = '+'; $column = substr($column,1);
559         } elseif (substr($column,0,1) == '-') {
560             $order = '-'; $column = substr($column,1);
561         }
562         // default order: +pagename, -mtime, -hits
563         if (empty($order))
564             if (in_array($column,array('mtime','hits')))
565                 $order = '-';
566             else
567                 $order = '+';
568         if ($action == 'flip_order') {
569             return ($order == '+' ? '-' : '+') . $column;
570         } elseif ($action == 'init') {
571             $this->_sortby[$column] = $order;
572             return $order . $column;
573         } elseif ($action == 'check') {
574             return (!empty($this->_sortby[$column]) or 
575                     ($GLOBALS['request']->getArg('sortby') and 
576                      strstr($GLOBALS['request']->getArg('sortby'),$column)));
577         } elseif ($action == 'db') {
578             // native sort possible?
579             if (!empty($this) and !$sortable_columns)
580                 $sortable_columns = $this->sortable_columns();
581             if (in_array($column, $sortable_columns))
582                 // asc or desc: +pagename, -pagename
583                 return $column . ($order == '+' ? ' ASC' : ' DESC');
584             else 
585                 return '';
586         }
587         return '';
588     }
589
590     function sortable_columns() {
591         return array('pagename'/*,'mtime','author_id','author'*/);
592     }
593
594     // adds surrounding quotes 
595     function quote ($s) { return "'".$s."'"; }
596     // no surrounding quotes because we know it's a string
597     function qstr ($s)  { return $s; }
598
599     function isSQL () {
600         return in_array(DATABASE_TYPE, array('SQL','ADODB','PDO'));
601     }
602
603     function backendType() {
604         return DATABASE_TYPE;
605     }
606
607     function write_accesslog(&$entry) {
608         global $request;
609         if (!$this->isSQL()) return;
610         $dbh = &$this->_dbh;
611         $log_tbl = $entry->_accesslog->logtable;
612         // duration problem: sprintf "%f" might use comma e.g. "100,201" in european locales
613         $dbh->query("INSERT INTO $log_tbl"
614                     . " (time_stamp,remote_host,remote_user,request_method,request_line,request_args,"
615                     .   "request_uri,request_time,status,bytes_sent,referer,agent,request_duration)"
616                     . " VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)",
617                     array(
618                           // Problem: date formats are backend specific. Either use unixtime as %d (long),
619                           // or the native timestamp format.
620                           $entry->time,
621                           $entry->host, 
622                           $entry->user,
623                           $entry->request_method,
624                           $entry->request,
625                           $entry->request_args,
626                           $entry->request_uri,
627                           $entry->_ncsa_time($entry->time), 
628                           $entry->status, 
629                           (int)$entry->size,
630                           $entry->referer,
631                           $entry->user_agent,
632                           $entry->duration));
633     }
634 };
635
636 /**
637  * Iterator returned by backend methods which (possibly) return
638  * multiple records.
639  *
640  * FIXME: This might be two seperate classes: page_iter and version_iter.
641  * For the versions we have WikiDB_backend_dumb_AllRevisionsIter.
642  */
643 class WikiDB_backend_iterator
644 {
645     /**
646      * Get the next record in the iterator set.
647      *
648      * This returns a hash. The hash may contain the following keys:
649      * <dl>
650      * <dt> pagename <dt> (string) the page name or linked page name on link iterators
651      * <dt> version  <dt> (int) the version number
652      * <dt> pagedata <dt> (hash) page meta-data (as returned from backend::get_pagedata().)
653      * <dt> versiondata <dt> (hash) page meta-data (as returned from backend::get_versiondata().)
654      * <dt> linkrelation <dt> (string) the page naming the relation (e.g. isa:=page <=> isa)
655      *
656      * If this is a page iterator, it must contain the 'pagename' entry --- the others
657      * are optional.
658      *
659      * If this is a version iterator, the 'pagename', 'version', <strong>and</strong> 'versiondata'
660      * entries are mandatory.  ('pagedata' is optional.)
661      *
662      * If this is a link iterator, the 'pagename' is mandatory, 'linkrelation' is optional.
663      */
664     function next() {
665         trigger_error("virtual", E_USER_ERROR);
666     }
667
668     function count() {
669         if (!empty($this->_pages))
670             return count($this->_pages);
671         else
672             return 0;    
673     }
674
675     function asArray() {
676         if (!empty($this->_pages)) {
677             reset($this->_pages);
678             return $this->_pages;
679         } else {
680             $result = array();
681             while ($page = $this->next())
682                 $result[] = $page;
683             return $result;
684         }
685     }
686
687     /**
688      * Release resources held by this iterator.
689      */
690     function free() {
691     }
692 };
693
694 /**
695  * search baseclass, pcre-specific
696  */
697 class WikiDB_backend_search
698 {
699     function WikiDB_backend_search($search, &$dbh) {
700         $this->_dbh = $dbh;
701         $this->_case_exact = $search->_case_exact;
702         $this->_stoplist   =& $search->_stoplist;
703         $this->stoplisted = array();
704     }
705     function _quote($word) {
706         return preg_quote($word, "/");
707     }
708     //TODO: use word anchors
709     function EXACT($word) { return "^".$this->_quote($word)."$"; }
710     function STARTS_WITH($word) { return "^".$this->_quote($word); }
711     function ENDS_WITH($word) { return $this->_quote($word)."$"; }
712     function WORD($word) { return $this->_quote($word); }
713     function REGEX($word) { return $word; }
714     //TESTME
715     function _pagename_match_clause($node) {
716         $method = $node->op;
717         $word = $this->$method($node->word);
718         return "preg_match(\"/\".$word.\"/\"".($this->_case_exact ? "i":"").")";
719     }
720     /* Eliminate stoplist words.
721      *  Keep a list of Stoplisted words to inform the poor user. 
722      */
723     function isStoplisted ($node) {
724         // check only on WORD or EXACT fulltext search
725         if ($node->op != 'WORD' and $node->op != 'EXACT')
726             return false;
727         if (preg_match("/^".$this->_stoplist."$/i", $node->word)) {
728             array_push($this->stoplisted, $node->word);
729             return true;
730         }
731         return false;
732     }
733     function getStoplisted($word) {
734         return $this->stoplisted;
735     }
736 }
737
738 /**
739  * search baseclass, sql-specific
740  */
741 class WikiDB_backend_search_sql extends WikiDB_backend_search
742 {
743     function _pagename_match_clause($node) {
744         // word already quoted by TextSearchQuery_node_word::_sql_quote()
745         $word = $node->sql();
746         if ($word == '%') // ALL shortcut
747             return "1=1";
748         else
749             return ($this->_case_exact 
750                     ? "pagename LIKE '$word'"
751                     : "LOWER(pagename) LIKE '$word'");
752     }
753     function _fulltext_match_clause($node) {
754         // force word-style %word% for fulltext search
755         $word = '%' . $node->_sql_quote($node->word) . '%';
756         // eliminate stoplist words
757         if ($this->isStoplisted($node))
758             return "1=1";  // and (pagename or 1) => and 1
759         else
760             return $this->_pagename_match_clause($node)
761                 // probably convert this MATCH AGAINST or SUBSTR/POSITION without wildcards
762                 . ($this->_case_exact ? " OR content LIKE '$word'" 
763                                       : " OR LOWER(content) LIKE '$word'");
764     }
765 }
766
767 // $Log: not supported by cvs2svn $
768 // Revision 1.36  2008/03/17 19:13:22  rurban
769 // define default $backend_type
770 //
771 // Revision 1.35  2007/08/25 18:17:46  rurban
772 // rearrange access_log columns into natural order: request_args
773 //
774 // Revision 1.34  2007/07/14 12:03:51  rurban
775 // just typo
776 //
777 // Revision 1.33  2007/06/07 21:35:04  rurban
778 // fixed backend asArray access to iterators (DebugInfo with SQL)
779 //
780 // Revision 1.32  2007/02/17 14:14:41  rurban
781 // enforce accesslog types
782 //
783 // Revision 1.31  2007/01/28 22:49:55  rurban
784 // use backend specific SQL write_accesslog
785 //
786 // Revision 1.30  2007/01/02 13:20:26  rurban
787 // added link_search. Clarify API: sortby,limit and exclude are strings.
788 //
789
790 // For emacs users
791 // Local Variables:
792 // mode: php
793 // tab-width: 8
794 // c-basic-offset: 4
795 // c-hanging-comment-ender-p: nil
796 // indent-tabs-mode: nil
797 // End:
798 ?>