├── EXPERIMENTAL ├── CREDITS ├── tests ├── index.swish-e ├── index.swish-e.prop ├── skipif.inc ├── 016.phpt ├── 015.phpt ├── 010.phpt ├── 008.phpt ├── 018.phpt ├── 013.phpt ├── 006.phpt ├── 012.phpt ├── 019.phpt ├── 011.phpt ├── 017.phpt ├── 020.phpt ├── 009.phpt ├── 005.phpt ├── 014.phpt ├── 001.phpt ├── 007.phpt ├── 004.phpt ├── 003.phpt └── 002.phpt ├── config.w32 ├── swish.php ├── config.m4 ├── php_swish.h ├── README ├── package.xml └── swish.c /EXPERIMENTAL: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /CREDITS: -------------------------------------------------------------------------------- 1 | swish-e 2 | Wez Furlong 3 | Antony Dovgal 4 | -------------------------------------------------------------------------------- /tests/index.swish-e: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/php/pecl-search_engine-swish/master/tests/index.swish-e -------------------------------------------------------------------------------- /tests/index.swish-e.prop: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/php/pecl-search_engine-swish/master/tests/index.swish-e.prop -------------------------------------------------------------------------------- /config.w32: -------------------------------------------------------------------------------- 1 | // $Id$ 2 | // vim:ft=javascript 3 | 4 | ARG_WITH("swish", "Swish-e support", "no"); 5 | 6 | if (PHP_SWISH == "yes") { 7 | if (CHECK_LIB("libswish-e.lib", "swish") && 8 | CHECK_HEADER_ADD_INCLUDE("swish-e.h", "CFLAGS_SWISH")) { 9 | 10 | EXTENSION("swish", "swish.c"); 11 | } 12 | } 13 | 14 | 15 | -------------------------------------------------------------------------------- /tests/skipif.inc: -------------------------------------------------------------------------------- 1 | 14 | -------------------------------------------------------------------------------- /swish.php: -------------------------------------------------------------------------------- 1 | prepare(); 6 | $s->setSort('swishrank desc'); 7 | 8 | $results = $s->execute("for"); 9 | 10 | echo "There are ", $results->hits, " hits\n"; 11 | while ($r = $results->nextResult()) { 12 | printf("%s %d %s\n", 13 | $r->swishdocpath, 14 | $r->swishrank, 15 | $r->name 16 | ); 17 | }; 18 | 19 | echo "Done\n"; 20 | 21 | ?> 22 | -------------------------------------------------------------------------------- /tests/016.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | SwishResults::nextResult() and SwishResults::seekResult() basic tests 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | query("test"); 11 | 12 | var_dump($results->seekResult(0)); 13 | var_dump($results->seekResult(2)); 14 | try { 15 | var_dump($results->seekResult(1000)); 16 | } catch (SwishException $e) { 17 | var_dump($e->getMessage()); 18 | } 19 | echo "Done\n"; 20 | ?> 21 | --EXPECTF-- 22 | int(0) 23 | int(2) 24 | string(15) "No more results" 25 | Done 26 | -------------------------------------------------------------------------------- /tests/015.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | SwishResult::getMetaList() tests 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | query("test"); 11 | 12 | $r = $rs->nextResult(); 13 | 14 | var_dump($r->getMetaList("test")); 15 | var_dump($r->getMetaList()); 16 | 17 | echo "Done\n"; 18 | ?> 19 | --EXPECTF-- 20 | Warning: SwishResult::getMetaList() expects exactly 0 parameters, 1 given in %s on line %d 21 | NULL 22 | array(1) { 23 | [0]=> 24 | array(3) { 25 | ["Name"]=> 26 | string(12) "swishdefault" 27 | ["Type"]=> 28 | int(0) 29 | ["ID"]=> 30 | int(1) 31 | } 32 | } 33 | Done 34 | -------------------------------------------------------------------------------- /tests/010.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | SwishSearch::resetLimit() tests 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | prepare("test"); 11 | 12 | $search->resetLimit(); 13 | $search->resetLimit(1); 14 | $rs = $search->execute(); 15 | var_dump($rs->hits); 16 | 17 | var_dump($search->setLimit("swishdocsize", 0, 5000)); 18 | $rs = $search->execute(); 19 | var_dump($rs->hits); 20 | 21 | $search->resetLimit(); 22 | $rs = $search->execute(); 23 | var_dump($rs->hits); 24 | 25 | echo "Done\n"; 26 | ?> 27 | --EXPECTF-- 28 | Warning: SwishSearch::resetLimit() expects exactly 0 parameters, 1 given in %s on line %d 29 | int(9) 30 | NULL 31 | int(5) 32 | int(9) 33 | Done 34 | -------------------------------------------------------------------------------- /tests/008.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | SwishSearch::setLimit() more sophisticated tests 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | prepare("test"); 11 | try { 12 | $search->setLimit("swishdocsize", 0, 5000); 13 | } catch (SwishException $e) { 14 | var_dump($e->getMessage()); 15 | } 16 | 17 | $rs = $search->execute(); 18 | var_dump($rs->hits); 19 | 20 | $search = $h->prepare("test"); 21 | try { 22 | $search->setLimit("swishdocsize", 4000, 10000); 23 | } catch (SwishException $e) { 24 | var_dump($e->getMessage()); 25 | } 26 | 27 | $rs = $search->execute(); 28 | var_dump($rs->hits); 29 | 30 | echo "Done\n"; 31 | ?> 32 | --EXPECTF-- 33 | int(5) 34 | int(8) 35 | Done 36 | -------------------------------------------------------------------------------- /tests/018.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | SwishSearch::setStructure() tests 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | prepare("test"); 11 | $s->setStructure(Swish::IN_FILE); //the default one 12 | $rs = $s->execute("", ""); 13 | $rs = $s->execute(); 14 | 15 | var_dump($rs->hits); 16 | 17 | $s = $h->prepare("test"); 18 | $s->setStructure(Swish::IN_TITLE); 19 | $rs = $s->execute(); 20 | 21 | var_dump($rs->hits); 22 | 23 | $s->setStructure(Swish::IN_TITLE,1); 24 | 25 | echo "Done\n"; 26 | ?> 27 | --EXPECTF-- 28 | Warning: SwishSearch::execute() expects at most 1 parameter, 2 given in %s on line %d 29 | int(9) 30 | int(0) 31 | 32 | Warning: SwishSearch::setStructure() expects exactly 1 parameter, 2 given in %s on line %d 33 | Done 34 | -------------------------------------------------------------------------------- /tests/013.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | SwishResult properties 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | query("test"); 11 | 12 | $result = $results->nextResult(); 13 | var_dump($result); 14 | var_dump($result->test); 15 | $a = array(); 16 | var_dump($result->$a); 17 | 18 | echo "Done\n"; 19 | ?> 20 | --EXPECTF-- 21 | object(SwishResult)#%d (8) { 22 | ["swishreccount"]=> 23 | int(1) 24 | ["swishrank"]=> 25 | int(1000) 26 | ["swishfilenum"]=> 27 | int(11) 28 | ["swishdbfile"]=> 29 | string(%d) "%sindex.swish-e" 30 | ["swishdocpath"]=> 31 | string(%d) "%sREADME.TESTING" 32 | ["swishtitle"]=> 33 | NULL 34 | ["swishdocsize"]=> 35 | int(6508) 36 | ["swishlastmodified"]=> 37 | int(1082042828) 38 | } 39 | 40 | Notice: Undefined property: SwishResult::$test in %s on line %d 41 | NULL 42 | 43 | Notice: Array to string conversion in %s on line %d 44 | 45 | Notice: Undefined property: SwishResult::$Array in %s on line %d 46 | NULL 47 | Done 48 | -------------------------------------------------------------------------------- /tests/006.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | SwishSearch::setLimit() tests 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | prepare("test"); 11 | try { 12 | var_dump($search->setLimit("swishdocsize", 0, 10000)); 13 | } catch (SwishException $e) { 14 | var_dump($e->getMessage()); 15 | } 16 | try { 17 | var_dump($search->setLimit("swishdocsize", -1, -1000000)); 18 | } catch (SwishException $e) { 19 | var_dump($e->getMessage()); 20 | } 21 | try { 22 | var_dump($search->setLimit("swishrank", -1, -1000000)); 23 | } catch (SwishException $e) { 24 | var_dump($e->getMessage()); 25 | } 26 | try { 27 | var_dump($search->setLimit("swishdocsiz", 0, 10000)); 28 | } catch (SwishException $e) { 29 | var_dump($e->getMessage()); 30 | } 31 | var_dump($search->setLimit()); 32 | 33 | echo "Done\n"; 34 | ?> 35 | --EXPECTF-- 36 | NULL 37 | string(42) "Property 'swishdocsize' is already limited" 38 | NULL 39 | NULL 40 | 41 | Warning: SwishSearch::setLimit() expects exactly 3 parameters, 0 given in %s on line %d 42 | NULL 43 | Done 44 | -------------------------------------------------------------------------------- /tests/012.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | SwishResults::getRemovedStopwords() tests 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | query("test"); 11 | var_dump($results->getRemovedStopwords(dirname(__FILE__)."/index.swish-e")); 12 | 13 | $results = $h->query("test AND hello"); 14 | var_dump($results->getRemovedStopwords(dirname(__FILE__)."/index.swish-e")); 15 | 16 | $results = $h->query("test or hello"); 17 | var_dump($results->getRemovedStopwords(dirname(__FILE__)."/index.swish-e")); 18 | var_dump($results->getRemovedStopwords(dirname(__FILE__)."/index")); 19 | var_dump($results->getRemovedStopwords(dirname(__FILE__)."/")); 20 | var_dump($results->getRemovedStopwords("")); 21 | var_dump($results->getRemovedStopwords()); 22 | 23 | echo "Done\n"; 24 | ?> 25 | --EXPECTF-- 26 | array(0) { 27 | } 28 | array(0) { 29 | } 30 | array(0) { 31 | } 32 | bool(false) 33 | bool(false) 34 | bool(false) 35 | 36 | Warning: SwishResults::getRemovedStopwords() expects exactly 1 parameter, 0 given in %s on line %d 37 | NULL 38 | Done 39 | -------------------------------------------------------------------------------- /tests/019.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | swish constants 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | 33 | --EXPECTF-- 34 | int(0) 35 | int(4) 36 | int(8) 37 | int(16) 38 | int(0) 39 | int(1) 40 | int(2) 41 | int(3) 42 | int(4) 43 | int(5) 44 | int(6) 45 | int(7) 46 | int(1) 47 | int(2) 48 | int(4) 49 | int(8) 50 | int(16) 51 | int(32) 52 | int(64) 53 | int(128) 54 | Done 55 | -------------------------------------------------------------------------------- /tests/011.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | SwishResults::getParsedWords() tests 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | query("test"); 11 | var_dump($results->getParsedWords(dirname(__FILE__)."/index.swish-e")); 12 | 13 | $results = $h->query("test AND hello"); 14 | var_dump($results->getParsedWords(dirname(__FILE__)."/index.swish-e")); 15 | 16 | $results = $h->query("test or hello"); 17 | var_dump($results->getParsedWords(dirname(__FILE__)."/index.swish-e")); 18 | 19 | $results = $h->query("test or hello"); 20 | var_dump($results->getParsedWords(dirname(__FILE__)."/test")); 21 | var_dump($results->getParsedWords(dirname(__FILE__)."/")); 22 | 23 | $results = $h->query("test or hello a b c d e f g"); 24 | var_dump($results->getParsedWords(dirname(__FILE__)."/index.swish-e")); 25 | 26 | echo "Done\n"; 27 | ?> 28 | --EXPECTF-- 29 | array(1) { 30 | [0]=> 31 | string(4) "test" 32 | } 33 | array(3) { 34 | [0]=> 35 | string(4) "test" 36 | [1]=> 37 | string(3) "and" 38 | [2]=> 39 | string(5) "hello" 40 | } 41 | array(3) { 42 | [0]=> 43 | string(4) "test" 44 | [1]=> 45 | string(2) "or" 46 | [2]=> 47 | string(5) "hello" 48 | } 49 | bool(false) 50 | bool(false) 51 | array(10) { 52 | [0]=> 53 | string(4) "test" 54 | [1]=> 55 | string(2) "or" 56 | [2]=> 57 | string(5) "hello" 58 | [3]=> 59 | string(1) "a" 60 | [4]=> 61 | string(1) "b" 62 | [5]=> 63 | string(1) "c" 64 | [6]=> 65 | string(1) "d" 66 | [7]=> 67 | string(1) "e" 68 | [8]=> 69 | string(1) "f" 70 | [9]=> 71 | string(1) "g" 72 | } 73 | Done 74 | -------------------------------------------------------------------------------- /tests/017.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | SwishSearch::setPhraseDelimiter() tests 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | prepare("test_and_test"); 11 | $s->setPhraseDelimiter("_"); 12 | $rs = $s->execute(); 13 | 14 | var_dump($rs->getParsedWords(dirname(__FILE__)."/index.swish-e")); 15 | 16 | $s = $h->prepare("test_and_test"); 17 | $rs = $s->execute(); 18 | 19 | var_dump($rs->getParsedWords(dirname(__FILE__)."/index.swish-e")); 20 | 21 | $s = $h->prepare("test_and_test"); 22 | $s->setPhraseDelimiter(); 23 | $s->setPhraseDelimiter(""); 24 | $rs = $s->execute(); 25 | 26 | var_dump($rs->getParsedWords(dirname(__FILE__)."/index.swish-e")); 27 | 28 | $s = $h->prepare("test_and_test"); 29 | $s->setPhraseDelimiter("t"); 30 | $rs = $s->execute(); 31 | 32 | var_dump($rs->getParsedWords(dirname(__FILE__)."/index.swish-e")); 33 | 34 | echo "Done\n"; 35 | ?> 36 | --EXPECTF-- 37 | array(5) { 38 | [0]=> 39 | string(4) "test" 40 | [1]=> 41 | string(1) "_" 42 | [2]=> 43 | string(3) "and" 44 | [3]=> 45 | string(1) "_" 46 | [4]=> 47 | string(4) "test" 48 | } 49 | array(3) { 50 | [0]=> 51 | string(4) "test" 52 | [1]=> 53 | string(3) "and" 54 | [2]=> 55 | string(4) "test" 56 | } 57 | 58 | Warning: SwishSearch::setPhraseDelimiter() expects exactly 1 parameter, 0 given in %s on line %d 59 | array(3) { 60 | [0]=> 61 | string(4) "test" 62 | [1]=> 63 | string(3) "and" 64 | [2]=> 65 | string(4) "test" 66 | } 67 | array(7) { 68 | [0]=> 69 | string(1) "t" 70 | [1]=> 71 | string(1) "e" 72 | [2]=> 73 | string(1) "t" 74 | [3]=> 75 | string(3) "and" 76 | [4]=> 77 | string(1) "t" 78 | [5]=> 79 | string(1) "e" 80 | [6]=> 81 | string(1) "t" 82 | } 83 | Done 84 | -------------------------------------------------------------------------------- /config.m4: -------------------------------------------------------------------------------- 1 | dnl $Id$ 2 | dnl vim:ts=2:sw=2:et: 3 | 4 | PHP_ARG_WITH(swish, for Swish-e support, 5 | [ --with-swish=PATH Include Swish-e support. PATH is path to swish-config]) 6 | 7 | if test "$PHP_SWISH" != "no"; then 8 | 9 | if test "$PHP_SWISH" = "yes"; then 10 | SWISH_CONFIG=`$php_shtool path swish_config` 11 | 12 | if test -z "$SWISH_CONFIG"; then 13 | for i in /usr/local /usr; do 14 | if test -f $i/bin/swish-config; then 15 | PHP_SWISH=$i; 16 | SWISH_CONFIG=$i/bin/swish-config; 17 | break; 18 | fi 19 | done 20 | fi 21 | 22 | else 23 | 24 | for i in "$PHP_SWISH" "$PHP_SWISH/swish-config" "$PHP_SWISH/bin/swish-config" ; do 25 | if test -f "$i" && test -x "$i"; then 26 | SWISH_CONFIG="$i" 27 | break; 28 | fi 29 | done 30 | fi 31 | 32 | if test -z "$SWISH_CONFIG" || ! test -f "$SWISH_CONFIG" || ! test -x "$SWISH_CONFIG"; then 33 | AC_MSG_ERROR([swish-config not found]) 34 | fi 35 | 36 | SWISH_INC=`"$SWISH_CONFIG" --cflags` 37 | PHP_EVAL_INCLINE($SWISH_INC) 38 | 39 | SWISH_LIBS=`"$SWISH_CONFIG" --libs` 40 | PHP_EVAL_LIBLINE($SWISH_LIBS, SWISH_SHARED_LIBADD) 41 | 42 | old_CFLAGS=$CFLAGS 43 | CFLAGS="$SWISH_INC" 44 | AC_CACHE_CHECK(for stemmer constants, ac_cv_stemmer_constants, 45 | AC_TRY_COMPILE([ 46 | #include 47 | #include 48 | ],[ 49 | int i = STEM_OK; 50 | ],[ 51 | ac_cv_stemmer_constants=yes 52 | ],[ 53 | ac_cv_stemmer_constants=no 54 | ]) 55 | ) 56 | CFLAGS=$old_CFLAGS 57 | 58 | if test "$ac_cv_stemmer_constants" = "yes"; then 59 | AC_DEFINE(HAVE_STEMMER_CONSTANTS, 1, [Whether stemmer constants are exported]) 60 | fi 61 | 62 | PHP_SUBST(SWISH_SHARED_LIBADD) 63 | PHP_NEW_EXTENSION(swish, swish.c, $ext_shared) 64 | fi 65 | -------------------------------------------------------------------------------- /php_swish.h: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 5 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2007 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | This source file is subject to version 3.01 of the PHP license, | 8 | | that is bundled with this package in the file LICENSE, and is | 9 | | available through the world-wide-web at the following url: | 10 | | http://www.php.net/license/3_01.txt | 11 | | If you did not receive a copy of the PHP license and are unable to | 12 | | obtain it through the world-wide-web, please send a note to | 13 | | license@php.net so we can mail you a copy immediately. | 14 | +----------------------------------------------------------------------+ 15 | | Authors: Wez Furlong | 16 | | Antony Dovgal | 17 | +----------------------------------------------------------------------+ 18 | */ 19 | 20 | /* $Id$ */ 21 | 22 | #ifndef PHP_SWISH_H 23 | #define PHP_SWISH_H 24 | 25 | extern zend_module_entry swish_module_entry; 26 | #define phpext_swish_ptr &swish_module_entry 27 | 28 | #define PHP_SWISH_VERSION "0.5.0" 29 | 30 | #ifdef PHP_WIN32 31 | #define PHP_SWISH_API __declspec(dllexport) 32 | #else 33 | #define PHP_SWISH_API 34 | #endif 35 | 36 | #ifdef ZTS 37 | #include "TSRM.h" 38 | #endif 39 | 40 | #endif /* PHP_SWISH_H */ 41 | 42 | 43 | /* 44 | * Local variables: 45 | * tab-width: 4 46 | * c-basic-offset: 4 47 | * End: 48 | * vim600: noet sw=4 ts=4 fdm=marker 49 | * vim<600: noet sw=4 ts=4 50 | */ 51 | -------------------------------------------------------------------------------- /tests/020.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | SwishResult::stem() tests 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | query(); 10 | $rs = $h->query("test"); 11 | 12 | $r = $rs->nextResult(); 13 | var_dump($r->stem("developing")); 14 | var_dump($r->stem("testing")); 15 | var_dump($r->stem("tests")); 16 | var_dump($r->stem("c")); 17 | var_dump($r->stem("security")); 18 | var_dump($r->stem("secure")); 19 | var_dump($r->stem()); 20 | 21 | try { 22 | var_dump($r->stem("")); 23 | } catch (SwishException $e) { 24 | var_dump($e->getMessage()); 25 | } 26 | 27 | try { 28 | var_dump($r->stem(str_repeat("test", 100))); 29 | } catch (SwishException $e) { 30 | var_dump($e->getMessage()); 31 | } 32 | 33 | try { 34 | var_dump($r->stem("1234567890")); 35 | } catch (SwishException $e) { 36 | var_dump($e->getMessage()); 37 | } 38 | 39 | echo "Done\n"; 40 | ?> 41 | --EXPECTF-- 42 | Warning: Swish::query() expects exactly 1 parameter, 0 given in %s on line %d 43 | array(1) { 44 | [0]=> 45 | string(7) "develop" 46 | } 47 | array(1) { 48 | [0]=> 49 | string(4) "test" 50 | } 51 | array(1) { 52 | [0]=> 53 | string(4) "test" 54 | } 55 | array(1) { 56 | [0]=> 57 | string(1) "c" 58 | } 59 | array(1) { 60 | [0]=> 61 | string(5) "secur" 62 | } 63 | array(1) { 64 | [0]=> 65 | string(5) "secur" 66 | } 67 | 68 | Warning: SwishResult::stem() expects exactly 1 parameter, 0 given in %s on line %d 69 | NULL 70 | string(36) "The word was stemmed to empty string" 71 | array(1) { 72 | [0]=> 73 | string(400) "testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest" 74 | } 75 | array(1) { 76 | [0]=> 77 | string(10) "1234567890" 78 | } 79 | Done 80 | -------------------------------------------------------------------------------- /tests/009.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | SwishSearch::setSort() tests 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | prepare("test"); 11 | 12 | $search->setSort("swishrank desc"); 13 | $rs = $search->execute(); 14 | 15 | while ($rs && $r = $rs->nextResult()) { 16 | var_dump($r->swishrank); 17 | var_dump($r->swishdocpath); 18 | } 19 | 20 | echo "=================\n"; 21 | 22 | $search->setSort("swishrank asc"); 23 | $rs = $search->execute(); 24 | 25 | while ($rs && $r = $rs->nextResult()) { 26 | var_dump($r->swishrank); 27 | var_dump($r->swishdocpath); 28 | } 29 | 30 | echo "=================\n"; 31 | 32 | $search->setSort("blah asc"); 33 | 34 | try { 35 | $rs = $search->execute(); 36 | } catch (SwishException $e) { 37 | var_dump($e->getMessage()); 38 | } 39 | 40 | $search->setSort(); 41 | 42 | echo "Done\n"; 43 | ?> 44 | --EXPECTF-- 45 | int(1000) 46 | string(%d) "%sREADME.TESTING" 47 | int(899) 48 | string(%d) "%sREADME.TESTING2" 49 | int(610) 50 | string(%d) "%sREADME.SUBMITTING_PATCH" 51 | int(604) 52 | string(%d) "%sREADME.QNX" 53 | int(530) 54 | string(%d) "%sREADME.WIN32-BUILD-SYSTEM" 55 | int(308) 56 | string(%d) "%sREADME.EXT_SKEL" 57 | int(248) 58 | string(%d) "%sREADME.CVS-RULES" 59 | int(161) 60 | string(%d) "%sREADME.Zeus" 61 | int(161) 62 | string(%d) "%sREADME.SELF-CONTAINED-EXTENSIONS" 63 | ================= 64 | int(161) 65 | string(%d) "%sREADME.Zeus" 66 | int(161) 67 | string(%d) "%sREADME.SELF-CONTAINED-EXTENSIONS" 68 | int(248) 69 | string(%d) "%sREADME.CVS-RULES" 70 | int(308) 71 | string(%d) "%sREADME.EXT_SKEL" 72 | int(530) 73 | string(%d) "%sREADME.WIN32-BUILD-SYSTEM" 74 | int(604) 75 | string(%d) "%sREADME.QNX" 76 | int(610) 77 | string(%d) "%sREADME.SUBMITTING_PATCH" 78 | int(899) 79 | string(%d) "%sREADME.TESTING2" 80 | int(1000) 81 | string(%d) "%sREADME.TESTING" 82 | ================= 83 | string(%d) "Property 'blah' is not defined in index '%sindex.swish-e'" 84 | 85 | Warning: SwishSearch::setSort() expects exactly 1 parameter, 0 given in %s on line %d 86 | Done 87 | -------------------------------------------------------------------------------- /tests/005.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | SwishResults::nextResult() and SwishResults::seekResult() basic tests 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | query("I_really_doubt_this_can_be_found"); 11 | var_dump($results); 12 | 13 | try { 14 | var_dump($results->seekResult()); 15 | } catch (SwishException $e) { 16 | var_dump($e->getMessage()); 17 | } 18 | try { 19 | var_dump($results->seekResult(-1)); 20 | } catch (SwishException $e) { 21 | var_dump($e->getMessage()); 22 | } 23 | try { 24 | var_dump($results->seekResult(0)); 25 | } catch (SwishException $e) { 26 | var_dump($e->getMessage()); 27 | } 28 | try { 29 | var_dump($results->seekResult(1000)); 30 | } catch (SwishException $e) { 31 | var_dump($e->getMessage()); 32 | } 33 | try { 34 | var_dump($results->nextResult(1000)); 35 | } catch (SwishException $e) { 36 | var_dump($e->getMessage()); 37 | } 38 | try { 39 | var_dump($results->nextResult()); 40 | } catch (SwishException $e) { 41 | var_dump($e->getMessage()); 42 | } 43 | 44 | echo "Done\n"; 45 | ?> 46 | --EXPECTF-- 47 | object(SwishResults)#%d (2) { 48 | ["hits"]=> 49 | int(0) 50 | ["indexes"]=> 51 | array(1) { 52 | [0]=> 53 | array(3) { 54 | ["name"]=> 55 | string(%d) "%sindex.swish-e" 56 | ["parsed_words"]=> 57 | array(7) { 58 | [0]=> 59 | string(1) "i" 60 | [1]=> 61 | string(6) "realli" 62 | [2]=> 63 | string(5) "doubt" 64 | [3]=> 65 | string(3) "thi" 66 | [4]=> 67 | string(3) "can" 68 | [5]=> 69 | string(2) "be" 70 | [6]=> 71 | string(5) "found" 72 | } 73 | ["removed_stop_words"]=> 74 | array(0) { 75 | } 76 | } 77 | } 78 | } 79 | 80 | Warning: SwishResults::seekResult() expects exactly 1 parameter, 0 given in %s on line %d 81 | NULL 82 | string(33) "position cannot be less than zero" 83 | string(15) "No more results" 84 | string(15) "No more results" 85 | 86 | Warning: SwishResults::nextResult() expects exactly 0 parameters, 1 given in %s on line %d 87 | NULL 88 | bool(false) 89 | Done 90 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | README for PHP Swish-e bindings 2 | =============================== 3 | $Id$ 4 | 5 | This extension provides bindings to the swish-e API. 6 | 7 | Swish-e is a GPL licensed search engine, with a clause that allows applications 8 | to link against the libswish-e library to use the published API to do so 9 | without invoking the viral portion of the GPL. This is subject to returning a 10 | link back to the swish-e source code. 11 | 12 | Here it is: 13 | http://swish-e.org/index.html 14 | 15 | How do I use this? 16 | ================== 17 | 18 | First you need to have built a swish index. Consult the swish docs for details 19 | on that: http://swish-e.org/docs/index.html 20 | 21 | % swish-e -i /path/to/stuff/to/index 22 | 23 | Now build this PHP module: 24 | 25 | % phpize 26 | % configure --with-swish=/usr/local 27 | % make 28 | % su - 29 | # make install 30 | # echo 'extension=swish.so' >> /usr/local/lib/php.ini 31 | 32 | 33 | Then you can code up an interface to the index using PHP: 34 | 35 | query("lemons"); 38 | echo "There are ", $results->hits, " lemons\n"; 39 | while ($r = $results->nextResult()) { 40 | printf("in file %s, relevance %d\n", 41 | $r->swishdocpath, 42 | $r->swishrank 43 | ); 44 | } 45 | ?> 46 | 47 | Brief API reference: 48 | ==================== 49 | See http://swish-e.org/docs/swish-library.html for more background. 50 | 51 | /* major handle class */ 52 | 53 | class Swish { 54 | public indexes = array(); //indexes and their properties 55 | 56 | SwishSearch prepare([string query]); 57 | SwishResult query(string query); 58 | 59 | array getMetaList(string indexname); 60 | array getPropertyList(string indexname); 61 | } 62 | 63 | /* search handle class */ 64 | 65 | class SwishSearch { 66 | void setStructure(int structure); 67 | void setPhraseDelimiter(string delimiter_char); 68 | void setSort(string sort_string); 69 | void setLimit(string property, string low, string high); 70 | void resetLimit(); 71 | SwishResults execute([string query]); 72 | } 73 | 74 | /* search results class */ 75 | 76 | class SwishResults { 77 | public hits = 0; 78 | public indexes = array(); 79 | 80 | SwishResult nextResult(); 81 | int seekResult(int position); 82 | array getParsedWords(string indexname); 83 | array getRemovedStopWords(string indexname); 84 | } 85 | 86 | /* search result class */ 87 | 88 | class SwishResult { 89 | /* 90 | properties defined by Swish, 91 | automatically "converted" to object properties 92 | */ 93 | 94 | array getMetaList(); 95 | array stem(string word); 96 | } 97 | 98 | vim:ts=2:sw=2:et: 99 | -------------------------------------------------------------------------------- /tests/014.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Swish::getMetaList() and Swish::getPropertyList() tests 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | getMetaList(dirname(__FILE__)."/index.swish-e")); 11 | var_dump($h->getPropertyList(dirname(__FILE__)."/index.swish-e")); 12 | 13 | var_dump($h->getMetaList(dirname(__FILE__)."/index.swish-e", 1)); 14 | var_dump($h->getPropertyList(dirname(__FILE__)."/index.swish-e", 1)); 15 | 16 | var_dump($h->getMetaList()); 17 | var_dump($h->getPropertyList()); 18 | 19 | echo "Done\n"; 20 | ?> 21 | --EXPECTF-- 22 | array(1) { 23 | [0]=> 24 | array(3) { 25 | ["Name"]=> 26 | string(12) "swishdefault" 27 | ["Type"]=> 28 | int(0) 29 | ["ID"]=> 30 | int(1) 31 | } 32 | } 33 | array(8) { 34 | [0]=> 35 | array(3) { 36 | ["Name"]=> 37 | string(13) "swishreccount" 38 | ["Type"]=> 39 | int(8) 40 | ["ID"]=> 41 | int(2) 42 | } 43 | [1]=> 44 | array(3) { 45 | ["Name"]=> 46 | string(9) "swishrank" 47 | ["Type"]=> 48 | int(8) 49 | ["ID"]=> 50 | int(3) 51 | } 52 | [2]=> 53 | array(3) { 54 | ["Name"]=> 55 | string(12) "swishfilenum" 56 | ["Type"]=> 57 | int(8) 58 | ["ID"]=> 59 | int(4) 60 | } 61 | [3]=> 62 | array(3) { 63 | ["Name"]=> 64 | string(11) "swishdbfile" 65 | ["Type"]=> 66 | int(4) 67 | ["ID"]=> 68 | int(5) 69 | } 70 | [4]=> 71 | array(3) { 72 | ["Name"]=> 73 | string(12) "swishdocpath" 74 | ["Type"]=> 75 | int(4) 76 | ["ID"]=> 77 | int(6) 78 | } 79 | [5]=> 80 | array(3) { 81 | ["Name"]=> 82 | string(10) "swishtitle" 83 | ["Type"]=> 84 | int(4) 85 | ["ID"]=> 86 | int(7) 87 | } 88 | [6]=> 89 | array(3) { 90 | ["Name"]=> 91 | string(12) "swishdocsize" 92 | ["Type"]=> 93 | int(8) 94 | ["ID"]=> 95 | int(8) 96 | } 97 | [7]=> 98 | array(3) { 99 | ["Name"]=> 100 | string(17) "swishlastmodified" 101 | ["Type"]=> 102 | int(16) 103 | ["ID"]=> 104 | int(9) 105 | } 106 | } 107 | 108 | Warning: Swish::getMetaList() expects exactly 1 parameter, 2 given in %s on line %d 109 | NULL 110 | 111 | Warning: Swish::getPropertyList() expects exactly 1 parameter, 2 given in %s on line %d 112 | NULL 113 | 114 | Warning: Swish::getMetaList() expects exactly 1 parameter, 0 given in %s on line %d 115 | NULL 116 | 117 | Warning: Swish::getPropertyList() expects exactly 1 parameter, 0 given in %s on line %d 118 | NULL 119 | Done 120 | -------------------------------------------------------------------------------- /tests/001.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Swish::__construct() tests 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | getMessage()); 25 | } 26 | } 27 | 28 | unlink($tmp_file); 29 | 30 | try { 31 | $h = new Swish(); 32 | } catch (SwishException $e) { 33 | var_dump($e->getMessage()); 34 | } 35 | 36 | try { 37 | $h = new Swish("a", "b"); 38 | } catch (SwishException $e) { 39 | var_dump($e->getMessage()); 40 | } 41 | 42 | echo "Done\n"; 43 | ?> 44 | --EXPECTF-- 45 | string(%d) "File "%s001.php" has an unknown format." 46 | string(%d) "Couldn't open the property file "%s001.phpt.prop": No such file or directory" 47 | object(Swish)#%d (1) { 48 | ["indexes"]=> 49 | array(1) { 50 | [0]=> 51 | array(2) { 52 | ["name"]=> 53 | string(%d) "%sindex.swish-e" 54 | ["headers"]=> 55 | array(24) { 56 | ["Name"]=> 57 | string(0) "" 58 | ["Saved as"]=> 59 | string(13) "index.swish-e" 60 | ["Total Words"]=> 61 | int(1888) 62 | ["Total Files"]=> 63 | int(16) 64 | ["Removed Files"]=> 65 | int(0) 66 | ["Total Word Pos"]=> 67 | int(17662) 68 | ["Removed Word Pos"]=> 69 | int(0) 70 | ["Indexed on"]=> 71 | string(%d) "%s" 72 | ["Description"]=> 73 | string(0) "" 74 | ["Pointer"]=> 75 | string(0) "" 76 | ["Maintained by"]=> 77 | string(0) "" 78 | ["MinWordLimit"]=> 79 | int(1) 80 | ["MaxWordLimit"]=> 81 | int(40) 82 | ["WordCharacters"]=> 83 | string(101) "0123456789abcdefghijklmnopqrstuvwxyz%s" 84 | ["BeginCharacters"]=> 85 | string(101) "0123456789abcdefghijklmnopqrstuvwxyz%s" 86 | ["EndCharacters"]=> 87 | string(101) "0123456789abcdefghijklmnopqrstuvwxyz%s" 88 | ["IgnoreFirstChar"]=> 89 | string(0) "" 90 | ["IgnoreLastChar"]=> 91 | string(0) "" 92 | ["StopWords"]=> 93 | array(0) { 94 | } 95 | ["BuzzWords"]=> 96 | array(0) { 97 | } 98 | ["Stemming Applied"]=> 99 | bool(true) 100 | ["Soundex Applied"]=> 101 | bool(false) 102 | ["Fuzzy Mode"]=> 103 | string(%d) "%s" 104 | ["IgnoreTotalWordCountWhenRanking"]=> 105 | bool(false) 106 | } 107 | } 108 | } 109 | } 110 | string(22) "No index file supplied" 111 | string(75) "Could not open the index file 'nonexistent_file': No such file or directory" 112 | 113 | Warning: Swish::__construct() expects exactly 1 parameter, 0 given in %s on line %d 114 | 115 | Warning: Swish::__construct() expects exactly 1 parameter, 2 given in %s on line %d 116 | Done 117 | -------------------------------------------------------------------------------- /tests/007.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Swish handle properties test 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | indexes); 12 | var_dump($h->test); 13 | $a = array(); 14 | var_dump($h->$a); 15 | 16 | echo "Done\n"; 17 | ?> 18 | --EXPECTF-- 19 | object(Swish)#%d (1) { 20 | ["indexes"]=> 21 | array(1) { 22 | [0]=> 23 | array(2) { 24 | ["name"]=> 25 | string(%d) "%sindex.swish-e" 26 | ["headers"]=> 27 | array(24) { 28 | ["Name"]=> 29 | string(0) "" 30 | ["Saved as"]=> 31 | string(13) "index.swish-e" 32 | ["Total Words"]=> 33 | int(1888) 34 | ["Total Files"]=> 35 | int(16) 36 | ["Removed Files"]=> 37 | int(0) 38 | ["Total Word Pos"]=> 39 | int(17662) 40 | ["Removed Word Pos"]=> 41 | int(0) 42 | ["Indexed on"]=> 43 | string(%d) "%s" 44 | ["Description"]=> 45 | string(0) "" 46 | ["Pointer"]=> 47 | string(0) "" 48 | ["Maintained by"]=> 49 | string(0) "" 50 | ["MinWordLimit"]=> 51 | int(1) 52 | ["MaxWordLimit"]=> 53 | int(40) 54 | ["WordCharacters"]=> 55 | string(101) "0123456789abcdefghijklmnopqrstuvwxyz%s" 56 | ["BeginCharacters"]=> 57 | string(101) "0123456789abcdefghijklmnopqrstuvwxyz%s" 58 | ["EndCharacters"]=> 59 | string(101) "0123456789abcdefghijklmnopqrstuvwxyz%s" 60 | ["IgnoreFirstChar"]=> 61 | string(0) "" 62 | ["IgnoreLastChar"]=> 63 | string(0) "" 64 | ["StopWords"]=> 65 | array(0) { 66 | } 67 | ["BuzzWords"]=> 68 | array(0) { 69 | } 70 | ["Stemming Applied"]=> 71 | bool(true) 72 | ["Soundex Applied"]=> 73 | bool(false) 74 | ["Fuzzy Mode"]=> 75 | string(%d) "%s" 76 | ["IgnoreTotalWordCountWhenRanking"]=> 77 | bool(false) 78 | } 79 | } 80 | } 81 | } 82 | array(1) { 83 | [0]=> 84 | array(2) { 85 | ["name"]=> 86 | string(%d) "%sindex.swish-e" 87 | ["headers"]=> 88 | array(24) { 89 | ["Name"]=> 90 | string(0) "" 91 | ["Saved as"]=> 92 | string(13) "index.swish-e" 93 | ["Total Words"]=> 94 | int(1888) 95 | ["Total Files"]=> 96 | int(16) 97 | ["Removed Files"]=> 98 | int(0) 99 | ["Total Word Pos"]=> 100 | int(17662) 101 | ["Removed Word Pos"]=> 102 | int(0) 103 | ["Indexed on"]=> 104 | string(%d) "%s" 105 | ["Description"]=> 106 | string(0) "" 107 | ["Pointer"]=> 108 | string(0) "" 109 | ["Maintained by"]=> 110 | string(0) "" 111 | ["MinWordLimit"]=> 112 | int(1) 113 | ["MaxWordLimit"]=> 114 | int(40) 115 | ["WordCharacters"]=> 116 | string(101) "0123456789abcdefghijklmnopqrstuvwxyz%s" 117 | ["BeginCharacters"]=> 118 | string(101) "0123456789abcdefghijklmnopqrstuvwxyz%s" 119 | ["EndCharacters"]=> 120 | string(101) "0123456789abcdefghijklmnopqrstuvwxyz%s" 121 | ["IgnoreFirstChar"]=> 122 | string(0) "" 123 | ["IgnoreLastChar"]=> 124 | string(0) "" 125 | ["StopWords"]=> 126 | array(0) { 127 | } 128 | ["BuzzWords"]=> 129 | array(0) { 130 | } 131 | ["Stemming Applied"]=> 132 | bool(true) 133 | ["Soundex Applied"]=> 134 | bool(false) 135 | ["Fuzzy Mode"]=> 136 | string(%d) "%s" 137 | ["IgnoreTotalWordCountWhenRanking"]=> 138 | bool(false) 139 | } 140 | } 141 | } 142 | 143 | Notice: Undefined property: Swish::$test in %s on line %d 144 | NULL 145 | 146 | Notice: Array to string conversion in %s on line %d 147 | 148 | Notice: Undefined property: Swish::$Array in %s on line %d 149 | NULL 150 | Done 151 | -------------------------------------------------------------------------------- /tests/004.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | SwishResults and SwishResult basic tests 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | query("test"); 11 | 12 | while ($results && $result = $results->nextResult()) { 13 | var_dump($result); 14 | var_dump($result->test); 15 | } 16 | 17 | 18 | echo "Done\n"; 19 | ?> 20 | --EXPECTF-- 21 | object(SwishResult)#%d (8) { 22 | ["swishreccount"]=> 23 | int(1) 24 | ["swishrank"]=> 25 | int(1000) 26 | ["swishfilenum"]=> 27 | int(11) 28 | ["swishdbfile"]=> 29 | string(%d) "%sindex.swish-e" 30 | ["swishdocpath"]=> 31 | string(%d) "%sREADME.TESTING" 32 | ["swishtitle"]=> 33 | NULL 34 | ["swishdocsize"]=> 35 | int(6508) 36 | ["swishlastmodified"]=> 37 | int(1082042828) 38 | } 39 | 40 | Notice: Undefined property: SwishResult::$test in %s on line %d 41 | NULL 42 | object(SwishResult)#%d (8) { 43 | ["swishreccount"]=> 44 | int(2) 45 | ["swishrank"]=> 46 | int(899) 47 | ["swishfilenum"]=> 48 | int(12) 49 | ["swishdbfile"]=> 50 | string(%d) "%sindex.swish-e" 51 | ["swishdocpath"]=> 52 | string(%d) "%sREADME.TESTING2" 53 | ["swishtitle"]=> 54 | NULL 55 | ["swishdocsize"]=> 56 | int(4922) 57 | ["swishlastmodified"]=> 58 | int(1048578318) 59 | } 60 | 61 | Notice: Undefined property: SwishResult::$test in %s on line %d 62 | NULL 63 | object(SwishResult)#%d (8) { 64 | ["swishreccount"]=> 65 | int(3) 66 | ["swishrank"]=> 67 | int(610) 68 | ["swishfilenum"]=> 69 | int(10) 70 | ["swishdbfile"]=> 71 | string(%d) "%sindex.swish-e" 72 | ["swishdocpath"]=> 73 | string(%d) "%sREADME.SUBMITTING_PATCH" 74 | ["swishtitle"]=> 75 | NULL 76 | ["swishdocsize"]=> 77 | int(4557) 78 | ["swishlastmodified"]=> 79 | int(1072136752) 80 | } 81 | 82 | Notice: Undefined property: SwishResult::$test in %s on line %d 83 | NULL 84 | object(SwishResult)#%d (8) { 85 | ["swishreccount"]=> 86 | int(4) 87 | ["swishrank"]=> 88 | int(604) 89 | ["swishfilenum"]=> 90 | int(7) 91 | ["swishdbfile"]=> 92 | string(%d) "%sindex.swish-e" 93 | ["swishdocpath"]=> 94 | string(%d) "%sREADME.QNX" 95 | ["swishtitle"]=> 96 | NULL 97 | ["swishdocsize"]=> 98 | int(2112) 99 | ["swishlastmodified"]=> 100 | int(923518833) 101 | } 102 | 103 | Notice: Undefined property: SwishResult::$test in %s on line %d 104 | NULL 105 | object(SwishResult)#%d (8) { 106 | ["swishreccount"]=> 107 | int(5) 108 | ["swishrank"]=> 109 | int(530) 110 | ["swishfilenum"]=> 111 | int(15) 112 | ["swishdbfile"]=> 113 | string(%d) "%sindex.swish-e" 114 | ["swishdocpath"]=> 115 | string(%d) "%sREADME.WIN32-BUILD-SYSTEM" 116 | ["swishtitle"]=> 117 | NULL 118 | ["swishdocsize"]=> 119 | int(6290) 120 | ["swishlastmodified"]=> 121 | int(1072147878) 122 | } 123 | 124 | Notice: Undefined property: SwishResult::$test in %s on line %d 125 | NULL 126 | object(SwishResult)#%d (8) { 127 | ["swishreccount"]=> 128 | int(6) 129 | ["swishrank"]=> 130 | int(308) 131 | ["swishfilenum"]=> 132 | int(3) 133 | ["swishdbfile"]=> 134 | string(%d) "%sindex.swish-e" 135 | ["swishdocpath"]=> 136 | string(%d) "%sREADME.EXT_SKEL" 137 | ["swishtitle"]=> 138 | NULL 139 | ["swishdocsize"]=> 140 | int(7126) 141 | ["swishlastmodified"]=> 142 | int(1056902837) 143 | } 144 | 145 | Notice: Undefined property: SwishResult::$test in %s on line %d 146 | NULL 147 | object(SwishResult)#%d (8) { 148 | ["swishreccount"]=> 149 | int(7) 150 | ["swishrank"]=> 151 | int(248) 152 | ["swishfilenum"]=> 153 | int(1) 154 | ["swishdbfile"]=> 155 | string(%d) "%sindex.swish-e" 156 | ["swishdocpath"]=> 157 | string(%d) "%sREADME.CVS-RULES" 158 | ["swishtitle"]=> 159 | NULL 160 | ["swishdocsize"]=> 161 | int(5183) 162 | ["swishlastmodified"]=> 163 | int(1151000661) 164 | } 165 | 166 | Notice: Undefined property: SwishResult::$test in %s on line %d 167 | NULL 168 | object(SwishResult)#%d (8) { 169 | ["swishreccount"]=> 170 | int(8) 171 | ["swishrank"]=> 172 | int(161) 173 | ["swishfilenum"]=> 174 | int(16) 175 | ["swishdbfile"]=> 176 | string(%d) "%sindex.swish-e" 177 | ["swishdocpath"]=> 178 | string(%d) "%sREADME.Zeus" 179 | ["swishtitle"]=> 180 | NULL 181 | ["swishdocsize"]=> 182 | int(4289) 183 | ["swishlastmodified"]=> 184 | int(1076280587) 185 | } 186 | 187 | Notice: Undefined property: SwishResult::$test in %s on line %d 188 | NULL 189 | object(SwishResult)#%d (8) { 190 | ["swishreccount"]=> 191 | int(9) 192 | ["swishrank"]=> 193 | int(161) 194 | ["swishfilenum"]=> 195 | int(8) 196 | ["swishdbfile"]=> 197 | string(%d) "%sindex.swish-e" 198 | ["swishdocpath"]=> 199 | string(%d) "%sREADME.SELF-CONTAINED-EXTENSIONS" 200 | ["swishtitle"]=> 201 | NULL 202 | ["swishdocsize"]=> 203 | int(4768) 204 | ["swishlastmodified"]=> 205 | int(1035408917) 206 | } 207 | 208 | Notice: Undefined property: SwishResult::$test in %s on line %d 209 | NULL 210 | Done 211 | -------------------------------------------------------------------------------- /tests/003.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Swish::query() tests 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | query($query)); 22 | var_dump($r->hits); 23 | var_dump($r->indexes); 24 | $a = array(); 25 | var_dump($r->$a); 26 | } catch (SwishException $e) { 27 | var_dump($e->getMessage()); 28 | } 29 | } 30 | 31 | echo "Done\n"; 32 | ?> 33 | --EXPECTF-- 34 | string(25) "No search words specified" 35 | object(SwishResults)#%d (2) { 36 | ["hits"]=> 37 | int(9) 38 | ["indexes"]=> 39 | array(1) { 40 | [0]=> 41 | array(3) { 42 | ["name"]=> 43 | string(%d) "%sindex.swish-e" 44 | ["parsed_words"]=> 45 | array(1) { 46 | [0]=> 47 | string(4) "test" 48 | } 49 | ["removed_stop_words"]=> 50 | array(0) { 51 | } 52 | } 53 | } 54 | } 55 | int(9) 56 | array(1) { 57 | [0]=> 58 | array(3) { 59 | ["name"]=> 60 | string(%d) "%sindex.swish-e" 61 | ["parsed_words"]=> 62 | array(1) { 63 | [0]=> 64 | string(4) "test" 65 | } 66 | ["removed_stop_words"]=> 67 | array(0) { 68 | } 69 | } 70 | } 71 | 72 | Notice: Array to string conversion in %s on line %d 73 | 74 | Notice: Undefined property: SwishResults::$Array in %s on line %d 75 | NULL 76 | object(SwishResults)#%d (2) { 77 | ["hits"]=> 78 | int(5) 79 | ["indexes"]=> 80 | array(1) { 81 | [0]=> 82 | array(3) { 83 | ["name"]=> 84 | string(%d) "%sindex.swish-e" 85 | ["parsed_words"]=> 86 | array(1) { 87 | [0]=> 88 | string(4) "data" 89 | } 90 | ["removed_stop_words"]=> 91 | array(0) { 92 | } 93 | } 94 | } 95 | } 96 | int(5) 97 | array(1) { 98 | [0]=> 99 | array(3) { 100 | ["name"]=> 101 | string(%d) "%sindex.swish-e" 102 | ["parsed_words"]=> 103 | array(1) { 104 | [0]=> 105 | string(4) "data" 106 | } 107 | ["removed_stop_words"]=> 108 | array(0) { 109 | } 110 | } 111 | } 112 | 113 | Notice: Array to string conversion in %s on line %d 114 | 115 | Notice: Undefined property: SwishResults::$Array in %s on line %d 116 | NULL 117 | object(SwishResults)#%d (2) { 118 | ["hits"]=> 119 | int(9) 120 | ["indexes"]=> 121 | array(1) { 122 | [0]=> 123 | array(3) { 124 | ["name"]=> 125 | string(%d) "%sindex.swish-e" 126 | ["parsed_words"]=> 127 | array(1) { 128 | [0]=> 129 | string(7) "paramet" 130 | } 131 | ["removed_stop_words"]=> 132 | array(0) { 133 | } 134 | } 135 | } 136 | } 137 | int(9) 138 | array(1) { 139 | [0]=> 140 | array(3) { 141 | ["name"]=> 142 | string(%d) "%sindex.swish-e" 143 | ["parsed_words"]=> 144 | array(1) { 145 | [0]=> 146 | string(7) "paramet" 147 | } 148 | ["removed_stop_words"]=> 149 | array(0) { 150 | } 151 | } 152 | } 153 | 154 | Notice: Array to string conversion in %s on line %d 155 | 156 | Notice: Undefined property: SwishResults::$Array in %s on line %d 157 | NULL 158 | object(SwishResults)#%d (2) { 159 | ["hits"]=> 160 | int(0) 161 | ["indexes"]=> 162 | array(1) { 163 | [0]=> 164 | array(3) { 165 | ["name"]=> 166 | string(%d) "%sindex.swish-e" 167 | ["parsed_words"]=> 168 | array(1) { 169 | [0]=> 170 | string(4) "ouch" 171 | } 172 | ["removed_stop_words"]=> 173 | array(0) { 174 | } 175 | } 176 | } 177 | } 178 | int(0) 179 | array(1) { 180 | [0]=> 181 | array(3) { 182 | ["name"]=> 183 | string(%d) "%sindex.swish-e" 184 | ["parsed_words"]=> 185 | array(1) { 186 | [0]=> 187 | string(4) "ouch" 188 | } 189 | ["removed_stop_words"]=> 190 | array(0) { 191 | } 192 | } 193 | } 194 | 195 | Notice: Array to string conversion in %s on line %d 196 | 197 | Notice: Undefined property: SwishResults::$Array in %s on line %d 198 | NULL 199 | object(SwishResults)#%d (2) { 200 | ["hits"]=> 201 | int(0) 202 | ["indexes"]=> 203 | array(1) { 204 | [0]=> 205 | array(3) { 206 | ["name"]=> 207 | string(%d) "%sindex.swish-e" 208 | ["parsed_words"]=> 209 | array(1) { 210 | [0]=> 211 | string(4) "blah" 212 | } 213 | ["removed_stop_words"]=> 214 | array(0) { 215 | } 216 | } 217 | } 218 | } 219 | int(0) 220 | array(1) { 221 | [0]=> 222 | array(3) { 223 | ["name"]=> 224 | string(%d) "%sindex.swish-e" 225 | ["parsed_words"]=> 226 | array(1) { 227 | [0]=> 228 | string(4) "blah" 229 | } 230 | ["removed_stop_words"]=> 231 | array(0) { 232 | } 233 | } 234 | } 235 | 236 | Notice: Array to string conversion in %s on line %d 237 | 238 | Notice: Undefined property: SwishResults::$Array in %s on line %d 239 | NULL 240 | Done 241 | -------------------------------------------------------------------------------- /package.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | swish 7 | pecl.php.net 8 | Swish-e bindings 9 | 10 | This extension provides bindings to the Swish-e API. 11 | 12 | Swish-e is a GPL licensed search engine, with a clause that allows applications 13 | to link against the libswish-e library to use the published API to do so 14 | without invoking the viral portion of the GPL. This is subject to returning a 15 | link back to the swish-e source code. 16 | 17 | Here it is: 18 | http://swish-e.org 19 | 20 | 21 | Antony Dovgal 22 | tony2001 23 | tony2001@php.net 24 | yes 25 | 26 | 27 | Wez Furlong 28 | wez 29 | wez@php.net 30 | yes 31 | 32 | 2012-05-06 33 | 34 | 35 | 0.5.0 36 | 0.5.0 37 | 38 | 39 | beta 40 | beta 41 | 42 | PHP 43 | - Fixed 5.4.x build. (patch by oeriksson at mandriva dot com) 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 5.1.3 85 | 6.0.0 86 | 6.0.0 87 | 88 | 89 | 1.4.0b1 90 | 91 | 92 | 93 | swish 94 | 95 | 96 | 97 | 98 | 99 | 2009-10-05 100 | 101 | 102 | 0.4.0 103 | 0.4.0 104 | 105 | 106 | beta 107 | beta 108 | 109 | PHP 110 | - Added PHP 5.3.x support. 111 | 112 | 113 | 114 | 2007-05-17 115 | 116 | 117 | 0.3.0 118 | 0.3.0 119 | 120 | 121 | beta 122 | beta 123 | 124 | PHP 125 | - Improved swish-config autodetection. 126 | - Fixed shared build. 127 | 128 | 129 | 130 | 2007-02-21 131 | 132 | 133 | 0.2.0 134 | 0.2.0 135 | 136 | 137 | beta 138 | beta 139 | 140 | PHP 141 | 142 | - Added missing IN_ALL constant. 143 | - Changed constants to be class constants. 144 | - Fixed Swish::__construct() to prevent calling it twice. 145 | 146 | 147 | 148 | PHP 149 | 2007-02-08 150 | 151 | 0.1 152 | 0.1 153 | 154 | 155 | beta 156 | beta 157 | 158 | 159 | Initial PECL release. 160 | 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /tests/002.phpt: -------------------------------------------------------------------------------- 1 | --TEST-- 2 | Swish::prepare() tests 3 | --SKIPIF-- 4 | 5 | --FILE-- 6 | prepare($query)); 22 | var_dump($r = $s->execute()); 23 | var_dump($r->hits); 24 | var_dump($r = $s->execute()); 25 | var_dump($r->hits); 26 | var_dump($r = $s->execute($query." OR php")); 27 | var_dump($r->hits); 28 | } catch (SwishException $e) { 29 | var_dump($e->getMessage()); 30 | } 31 | } 32 | 33 | var_dump($s = $h->prepare()); 34 | var_dump($s = $h->prepare("a", "b")); 35 | 36 | echo "Done\n"; 37 | ?> 38 | --EXPECTF-- 39 | object(SwishSearch)#%d (0) { 40 | } 41 | string(25) "No search words specified" 42 | object(SwishSearch)#%d (0) { 43 | } 44 | object(SwishResults)#%d (2) { 45 | ["hits"]=> 46 | int(9) 47 | ["indexes"]=> 48 | array(1) { 49 | [0]=> 50 | array(3) { 51 | ["name"]=> 52 | string(%d) "%sindex.swish-e" 53 | ["parsed_words"]=> 54 | array(1) { 55 | [0]=> 56 | string(4) "test" 57 | } 58 | ["removed_stop_words"]=> 59 | array(0) { 60 | } 61 | } 62 | } 63 | } 64 | int(9) 65 | object(SwishResults)#%d (2) { 66 | ["hits"]=> 67 | int(9) 68 | ["indexes"]=> 69 | array(1) { 70 | [0]=> 71 | array(3) { 72 | ["name"]=> 73 | string(%d) "%sindex.swish-e" 74 | ["parsed_words"]=> 75 | array(1) { 76 | [0]=> 77 | string(4) "test" 78 | } 79 | ["removed_stop_words"]=> 80 | array(0) { 81 | } 82 | } 83 | } 84 | } 85 | int(9) 86 | object(SwishResults)#%d (2) { 87 | ["hits"]=> 88 | int(16) 89 | ["indexes"]=> 90 | array(1) { 91 | [0]=> 92 | array(3) { 93 | ["name"]=> 94 | string(%d) "%sindex.swish-e" 95 | ["parsed_words"]=> 96 | array(3) { 97 | [0]=> 98 | string(4) "test" 99 | [1]=> 100 | string(2) "or" 101 | [2]=> 102 | string(3) "php" 103 | } 104 | ["removed_stop_words"]=> 105 | array(0) { 106 | } 107 | } 108 | } 109 | } 110 | int(16) 111 | object(SwishSearch)#%d (0) { 112 | } 113 | object(SwishResults)#%d (2) { 114 | ["hits"]=> 115 | int(5) 116 | ["indexes"]=> 117 | array(1) { 118 | [0]=> 119 | array(3) { 120 | ["name"]=> 121 | string(%d) "%sindex.swish-e" 122 | ["parsed_words"]=> 123 | array(1) { 124 | [0]=> 125 | string(4) "data" 126 | } 127 | ["removed_stop_words"]=> 128 | array(0) { 129 | } 130 | } 131 | } 132 | } 133 | int(5) 134 | object(SwishResults)#%d (2) { 135 | ["hits"]=> 136 | int(5) 137 | ["indexes"]=> 138 | array(1) { 139 | [0]=> 140 | array(3) { 141 | ["name"]=> 142 | string(%d) "%sindex.swish-e" 143 | ["parsed_words"]=> 144 | array(1) { 145 | [0]=> 146 | string(4) "data" 147 | } 148 | ["removed_stop_words"]=> 149 | array(0) { 150 | } 151 | } 152 | } 153 | } 154 | int(5) 155 | object(SwishResults)#%d (2) { 156 | ["hits"]=> 157 | int(16) 158 | ["indexes"]=> 159 | array(1) { 160 | [0]=> 161 | array(3) { 162 | ["name"]=> 163 | string(%d) "%sindex.swish-e" 164 | ["parsed_words"]=> 165 | array(3) { 166 | [0]=> 167 | string(4) "data" 168 | [1]=> 169 | string(2) "or" 170 | [2]=> 171 | string(3) "php" 172 | } 173 | ["removed_stop_words"]=> 174 | array(0) { 175 | } 176 | } 177 | } 178 | } 179 | int(16) 180 | object(SwishSearch)#%d (0) { 181 | } 182 | object(SwishResults)#%d (2) { 183 | ["hits"]=> 184 | int(9) 185 | ["indexes"]=> 186 | array(1) { 187 | [0]=> 188 | array(3) { 189 | ["name"]=> 190 | string(%d) "%sindex.swish-e" 191 | ["parsed_words"]=> 192 | array(1) { 193 | [0]=> 194 | string(7) "paramet" 195 | } 196 | ["removed_stop_words"]=> 197 | array(0) { 198 | } 199 | } 200 | } 201 | } 202 | int(9) 203 | object(SwishResults)#%d (2) { 204 | ["hits"]=> 205 | int(9) 206 | ["indexes"]=> 207 | array(1) { 208 | [0]=> 209 | array(3) { 210 | ["name"]=> 211 | string(%d) "%sindex.swish-e" 212 | ["parsed_words"]=> 213 | array(1) { 214 | [0]=> 215 | string(7) "paramet" 216 | } 217 | ["removed_stop_words"]=> 218 | array(0) { 219 | } 220 | } 221 | } 222 | } 223 | int(9) 224 | object(SwishResults)#%d (2) { 225 | ["hits"]=> 226 | int(16) 227 | ["indexes"]=> 228 | array(1) { 229 | [0]=> 230 | array(3) { 231 | ["name"]=> 232 | string(%d) "%sindex.swish-e" 233 | ["parsed_words"]=> 234 | array(3) { 235 | [0]=> 236 | string(7) "paramet" 237 | [1]=> 238 | string(2) "or" 239 | [2]=> 240 | string(3) "php" 241 | } 242 | ["removed_stop_words"]=> 243 | array(0) { 244 | } 245 | } 246 | } 247 | } 248 | int(16) 249 | object(SwishSearch)#%d (0) { 250 | } 251 | object(SwishResults)#%d (2) { 252 | ["hits"]=> 253 | int(0) 254 | ["indexes"]=> 255 | array(1) { 256 | [0]=> 257 | array(3) { 258 | ["name"]=> 259 | string(%d) "%sindex.swish-e" 260 | ["parsed_words"]=> 261 | array(1) { 262 | [0]=> 263 | string(4) "ouch" 264 | } 265 | ["removed_stop_words"]=> 266 | array(0) { 267 | } 268 | } 269 | } 270 | } 271 | int(0) 272 | object(SwishResults)#%d (2) { 273 | ["hits"]=> 274 | int(0) 275 | ["indexes"]=> 276 | array(1) { 277 | [0]=> 278 | array(3) { 279 | ["name"]=> 280 | string(%d) "%sindex.swish-e" 281 | ["parsed_words"]=> 282 | array(1) { 283 | [0]=> 284 | string(4) "ouch" 285 | } 286 | ["removed_stop_words"]=> 287 | array(0) { 288 | } 289 | } 290 | } 291 | } 292 | int(0) 293 | object(SwishResults)#%d (2) { 294 | ["hits"]=> 295 | int(16) 296 | ["indexes"]=> 297 | array(1) { 298 | [0]=> 299 | array(3) { 300 | ["name"]=> 301 | string(%d) "%sindex.swish-e" 302 | ["parsed_words"]=> 303 | array(3) { 304 | [0]=> 305 | string(4) "ouch" 306 | [1]=> 307 | string(2) "or" 308 | [2]=> 309 | string(3) "php" 310 | } 311 | ["removed_stop_words"]=> 312 | array(0) { 313 | } 314 | } 315 | } 316 | } 317 | int(16) 318 | object(SwishSearch)#%d (0) { 319 | } 320 | object(SwishResults)#%d (2) { 321 | ["hits"]=> 322 | int(0) 323 | ["indexes"]=> 324 | array(1) { 325 | [0]=> 326 | array(3) { 327 | ["name"]=> 328 | string(%d) "%sindex.swish-e" 329 | ["parsed_words"]=> 330 | array(1) { 331 | [0]=> 332 | string(4) "blah" 333 | } 334 | ["removed_stop_words"]=> 335 | array(0) { 336 | } 337 | } 338 | } 339 | } 340 | int(0) 341 | object(SwishResults)#%d (2) { 342 | ["hits"]=> 343 | int(0) 344 | ["indexes"]=> 345 | array(1) { 346 | [0]=> 347 | array(3) { 348 | ["name"]=> 349 | string(%d) "%sindex.swish-e" 350 | ["parsed_words"]=> 351 | array(1) { 352 | [0]=> 353 | string(4) "blah" 354 | } 355 | ["removed_stop_words"]=> 356 | array(0) { 357 | } 358 | } 359 | } 360 | } 361 | int(0) 362 | object(SwishResults)#%d (2) { 363 | ["hits"]=> 364 | int(16) 365 | ["indexes"]=> 366 | array(1) { 367 | [0]=> 368 | array(3) { 369 | ["name"]=> 370 | string(%d) "%sindex.swish-e" 371 | ["parsed_words"]=> 372 | array(3) { 373 | [0]=> 374 | string(4) "blah" 375 | [1]=> 376 | string(2) "or" 377 | [2]=> 378 | string(3) "php" 379 | } 380 | ["removed_stop_words"]=> 381 | array(0) { 382 | } 383 | } 384 | } 385 | } 386 | int(16) 387 | object(SwishSearch)#%d (0) { 388 | } 389 | 390 | Warning: Swish::prepare() expects at most 1 parameter, 2 given in %s on line %d 391 | NULL 392 | Done 393 | -------------------------------------------------------------------------------- /swish.c: -------------------------------------------------------------------------------- 1 | /* 2 | +----------------------------------------------------------------------+ 3 | | PHP Version 5 | 4 | +----------------------------------------------------------------------+ 5 | | Copyright (c) 1997-2007 The PHP Group | 6 | +----------------------------------------------------------------------+ 7 | | This source file is subject to version 3.01 of the PHP license, | 8 | | that is bundled with this package in the file LICENSE, and is | 9 | | available through the world-wide-web at the following url: | 10 | | http://www.php.net/license/3_01.txt | 11 | | If you did not receive a copy of the PHP license and are unable to | 12 | | obtain it through the world-wide-web, please send a note to | 13 | | license@php.net so we can mail you a copy immediately. | 14 | +----------------------------------------------------------------------+ 15 | | Authors: Wez Furlong | 16 | | Antony Dovgal | 17 | +----------------------------------------------------------------------+ 18 | */ 19 | 20 | /* $Id$ */ 21 | 22 | #ifdef HAVE_CONFIG_H 23 | #include "config.h" 24 | #endif 25 | 26 | #include "php.h" 27 | #include "php_ini.h" 28 | #include "ext/standard/info.h" 29 | #include "php_swish.h" 30 | #include "zend_exceptions.h" 31 | #include "swish-e.h" 32 | 33 | /* {{{ internal structs */ 34 | static zend_class_entry *ce_sw_exception; 35 | static zend_class_entry *ce_sw_handle; 36 | static zend_class_entry *ce_sw_search; 37 | static zend_class_entry *ce_sw_result; 38 | static zend_class_entry *ce_sw_results; 39 | 40 | static zend_object_handlers php_sw_results_obj_handlers; 41 | static zend_object_handlers php_sw_result_obj_handlers; 42 | static zend_object_handlers php_sw_handle_obj_handlers; 43 | static zend_object_handlers cannot_be_cloned; 44 | 45 | struct php_sw_handle { 46 | zend_object std; 47 | SW_HANDLE h; 48 | }; 49 | 50 | struct php_sw_search { 51 | zend_object std; 52 | zval refhandle; 53 | struct php_sw_handle *h; 54 | SW_SEARCH s; 55 | }; 56 | 57 | struct php_sw_results { 58 | zend_object std; 59 | zval refhandle; 60 | struct php_sw_handle *h; 61 | SW_RESULTS r; 62 | }; 63 | 64 | struct php_sw_result { 65 | zend_object std; 66 | zval refhandle; 67 | struct php_sw_handle *h; 68 | SW_RESULT r; 69 | }; 70 | /* }}} */ 71 | 72 | #if PHP_VERSION_ID < 50300 73 | # define Z_SET_REFCOUNT_P(pz, rc) pz->refcount = rc 74 | # define Z_SET_ISREF_P(pz) pz->is_ref = 1 75 | # define Z_UNSET_ISREF_P(pz) pz->is_ref = 0 76 | #endif 77 | 78 | /* {{{ internal functions */ 79 | static int sw_throw_exception(struct php_sw_handle *h TSRMLS_DC) /* {{{ */ 80 | { 81 | if (SwishError(h->h)) { 82 | char *msg = SwishLastErrorMsg(h->h); 83 | if (!msg || *msg == 0 ) { 84 | msg = SwishErrorString(h->h); 85 | } 86 | if (!msg || *msg == 0) { 87 | /* this usually should not happen */ 88 | msg = "Unknown error occured. Please report"; 89 | } 90 | zend_throw_exception_ex(ce_sw_exception, 0 TSRMLS_CC, msg); 91 | return 1; 92 | } 93 | return 0; 94 | } 95 | /* }}} */ 96 | 97 | #ifndef HAVE_STEMMER_CONSTANTS /* {{{ */ 98 | /* if these constants were not exported, define them */ 99 | enum { 100 | STEM_OK, 101 | STEM_NOT_ALPHA, 102 | STEM_TOO_SMALL, 103 | STEM_WORD_TOO_BIG, 104 | STEM_TO_NOTHING 105 | }; 106 | #endif 107 | /* }}} */ 108 | 109 | static int sw_stemmer_error_to_exception(int error TSRMLS_DC) /* {{{ */ 110 | { 111 | if (error != STEM_OK) { 112 | char *msg; 113 | switch(error) { 114 | case STEM_NOT_ALPHA: 115 | msg = "Not all letters are alpha"; 116 | break; 117 | case STEM_TOO_SMALL: 118 | msg = "The word is too small to be stemmed"; 119 | break; 120 | case STEM_WORD_TOO_BIG: 121 | msg = "The word is too big to be stemmed"; 122 | break; 123 | case STEM_TO_NOTHING: 124 | msg = "The word was stemmed to empty string"; 125 | break; 126 | default: 127 | msg = "Unknown stemming error"; 128 | break; 129 | } 130 | zend_throw_exception_ex(ce_sw_exception, 0 TSRMLS_CC, msg); 131 | return 1; 132 | } 133 | return 0; 134 | } 135 | /* }}} */ 136 | 137 | static void php_sw_header_to_zval(SWISH_HEADER_VALUE value, SWISH_HEADER_TYPE type, zval** retval, zend_bool alloc_zval TSRMLS_DC) /* {{{ */ 138 | { 139 | if (alloc_zval) { 140 | MAKE_STD_ZVAL(*retval); 141 | } 142 | 143 | switch (type) { 144 | case SWISH_STRING: 145 | ZVAL_STRING(*retval, (char *)value.string, 1); 146 | break; 147 | 148 | case SWISH_NUMBER: 149 | ZVAL_LONG(*retval, value.number); 150 | break; 151 | 152 | case SWISH_BOOL: 153 | ZVAL_BOOL(*retval, value.boolean); 154 | return; 155 | 156 | case SWISH_LIST: 157 | { 158 | const char **string_list; 159 | string_list = value.string_list; 160 | array_init(*retval); 161 | 162 | while ( string_list && *string_list ) 163 | { 164 | add_next_index_string(*retval, (char *)(*string_list), 1); 165 | string_list++; 166 | } 167 | } 168 | break; 169 | 170 | case SWISH_HEADER_ERROR: 171 | ZVAL_NULL(*retval); 172 | break; 173 | 174 | default: 175 | ZVAL_NULL(*retval); 176 | break; 177 | } 178 | } 179 | /* }}} */ 180 | 181 | static void sw_handle_dtor(void *object TSRMLS_DC) /* {{{ */ 182 | { 183 | struct php_sw_handle *h = (struct php_sw_handle*)object; 184 | 185 | if (h->h) { 186 | SwishClose(h->h); 187 | h->h = NULL; 188 | } 189 | 190 | zend_object_std_dtor(&h->std TSRMLS_CC); 191 | efree(h); 192 | } 193 | /* }}} */ 194 | 195 | static void sw_search_dtor(void *object TSRMLS_DC) /* {{{ */ 196 | { 197 | struct php_sw_search *s = (struct php_sw_search*)object; 198 | 199 | if (s->s) { 200 | Free_Search_Object(s->s); 201 | s->s = NULL; 202 | } 203 | 204 | zend_objects_store_del_ref(&s->refhandle TSRMLS_CC); 205 | 206 | zend_object_std_dtor(&s->std TSRMLS_CC); 207 | efree(s); 208 | } 209 | /* }}} */ 210 | 211 | static void sw_results_dtor(void *object TSRMLS_DC) /* {{{ */ 212 | { 213 | struct php_sw_results *r = (struct php_sw_results*)object; 214 | 215 | if (r->r) { 216 | Free_Results_Object(r->r); 217 | r->r = NULL; 218 | } 219 | 220 | zend_objects_store_del_ref(&r->refhandle TSRMLS_CC); 221 | 222 | zend_object_std_dtor(&r->std TSRMLS_CC); 223 | efree(r); 224 | } 225 | /* }}} */ 226 | 227 | static void sw_result_dtor(void *object TSRMLS_DC) /* {{{ */ 228 | { 229 | struct php_sw_result *r = (struct php_sw_result*)object; 230 | 231 | zend_objects_store_del_ref(&r->refhandle TSRMLS_CC); 232 | 233 | zend_object_std_dtor(&r->std TSRMLS_CC); 234 | efree(r); 235 | } 236 | /* }}} */ 237 | 238 | static zend_object_value sw_handle_new(zend_class_entry *ce TSRMLS_DC) /* {{{ */ 239 | { 240 | struct php_sw_handle *h; 241 | zend_object_value retval; 242 | 243 | h = ecalloc(1, sizeof(*h)); 244 | zend_object_std_init(&h->std, ce TSRMLS_CC); 245 | 246 | retval.handle = zend_objects_store_put(h, 247 | (zend_objects_store_dtor_t)zend_objects_destroy_object, 248 | sw_handle_dtor, 249 | NULL TSRMLS_CC); 250 | retval.handlers = &php_sw_handle_obj_handlers; 251 | return retval; 252 | } 253 | /* }}} */ 254 | 255 | static zend_object_value sw_search_new(zend_class_entry *ce TSRMLS_DC) /* {{{ */ 256 | { 257 | struct php_sw_search *s; 258 | zend_object_value retval; 259 | 260 | s = ecalloc(1, sizeof(*s)); 261 | zend_object_std_init(&s->std, ce TSRMLS_CC); 262 | 263 | retval.handle = zend_objects_store_put(s, 264 | (zend_objects_store_dtor_t)zend_objects_destroy_object, 265 | sw_search_dtor, 266 | NULL TSRMLS_CC); 267 | retval.handlers = &cannot_be_cloned; 268 | return retval; 269 | } 270 | /* }}} */ 271 | 272 | static zend_object_value sw_results_new(zend_class_entry *ce TSRMLS_DC) /* {{{ */ 273 | { 274 | struct php_sw_results *r; 275 | zend_object_value retval; 276 | 277 | r = ecalloc(1, sizeof(*r)); 278 | zend_object_std_init(&r->std, ce TSRMLS_CC); 279 | 280 | retval.handle = zend_objects_store_put(r, 281 | (zend_objects_store_dtor_t)zend_objects_destroy_object, 282 | sw_results_dtor, 283 | NULL TSRMLS_CC); 284 | retval.handlers = &php_sw_results_obj_handlers; 285 | return retval; 286 | } 287 | /* }}} */ 288 | 289 | static zend_object_value sw_result_new(zend_class_entry *ce TSRMLS_DC) /* {{{ */ 290 | { 291 | struct php_sw_result *r; 292 | zend_object_value retval; 293 | 294 | r = ecalloc(1, sizeof(*r)); 295 | zend_object_std_init(&r->std, ce TSRMLS_CC); 296 | 297 | retval.handle = zend_objects_store_put(r, 298 | (zend_objects_store_dtor_t)zend_objects_destroy_object, 299 | sw_result_dtor, 300 | NULL TSRMLS_CC); 301 | retval.handlers = &php_sw_result_obj_handlers; 302 | return retval; 303 | } 304 | /* }}} */ 305 | 306 | static void php_sw_results_indexes_to_array(struct php_sw_results *r, zval **z_indexes TSRMLS_DC) /* {{{ */ 307 | { 308 | zval *index, *ztmp, *element; 309 | const char **index_names; 310 | SWISH_HEADER_VALUE header_value; 311 | SWISH_HEADER_TYPE header_type; 312 | 313 | index_names = SwishIndexNames(r->h->h); 314 | 315 | MAKE_STD_ZVAL(*z_indexes); 316 | array_init(*z_indexes); 317 | 318 | while (index_names && *index_names) { 319 | MAKE_STD_ZVAL(index); 320 | array_init(index); 321 | 322 | MAKE_STD_ZVAL(ztmp); 323 | ZVAL_STRING(ztmp, (char *)(*index_names), 1); 324 | 325 | add_assoc_zval(index, "name", ztmp); 326 | 327 | header_type = SWISH_LIST; 328 | header_value = SwishParsedWords(r->r, *index_names); 329 | php_sw_header_to_zval(header_value, header_type, &element, 1 TSRMLS_CC); 330 | add_assoc_zval(index, "parsed_words", element); 331 | 332 | header_type = SWISH_LIST; 333 | header_value = SwishRemovedStopwords(r->r, *index_names); 334 | php_sw_header_to_zval(header_value, header_type, &element, 1 TSRMLS_CC); 335 | add_assoc_zval(index, "removed_stop_words", element); 336 | 337 | add_next_index_zval(*z_indexes, index); 338 | index_names++; 339 | } 340 | } 341 | /* }}} */ 342 | 343 | #if PHP_VERSION_ID >= 50400 344 | static zval *php_sw_results_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */ 345 | #else 346 | static zval *php_sw_results_read_property(zval *object, zval *member, int type TSRMLS_DC) 347 | #endif 348 | { 349 | struct php_sw_results *r; 350 | zval tmp_member; 351 | zval *retval; 352 | zend_object_handlers *std_hnd; 353 | 354 | r = (struct php_sw_results*)zend_object_store_get_object(object TSRMLS_CC); 355 | 356 | if (member->type != IS_STRING) { 357 | tmp_member = *member; 358 | zval_copy_ctor(&tmp_member); 359 | convert_to_string(&tmp_member); 360 | member = &tmp_member; 361 | } 362 | 363 | if (Z_STRLEN_P(member) == (sizeof("hits") - 1) && !memcmp(Z_STRVAL_P(member), "hits", Z_STRLEN_P(member))){ 364 | MAKE_STD_ZVAL(retval); 365 | ZVAL_LONG(retval, SwishHits(r->r)); 366 | Z_SET_REFCOUNT_P(retval, 0); 367 | } else if (Z_STRLEN_P(member) == (sizeof("indexes") - 1) && !memcmp(Z_STRVAL_P(member), "indexes", Z_STRLEN_P(member))) { 368 | php_sw_results_indexes_to_array(r, &retval TSRMLS_CC); 369 | Z_SET_REFCOUNT_P(retval, 0); 370 | } else { 371 | std_hnd = zend_get_std_object_handlers(); 372 | #if PHP_VERSION_ID >= 50400 373 | retval = std_hnd->read_property(object, member, type, key TSRMLS_CC); 374 | #else 375 | retval = std_hnd->read_property(object, member, type TSRMLS_CC); 376 | #endif 377 | 378 | } 379 | 380 | if (member == &tmp_member) { 381 | zval_dtor(member); 382 | } 383 | return(retval); 384 | } 385 | /* }}} */ 386 | 387 | static HashTable *php_sw_results_get_properties(zval *object TSRMLS_DC) /* {{{ */ 388 | { 389 | struct php_sw_results *r; 390 | zval *tmp; 391 | 392 | r = (struct php_sw_results*)zend_objects_get_address(object TSRMLS_CC); 393 | 394 | MAKE_STD_ZVAL(tmp); 395 | ZVAL_LONG(tmp, SwishHits(r->r)); 396 | 397 | zend_hash_update(r->std.properties, "hits", sizeof("hits"), (void *)&tmp, sizeof(zval *), NULL); 398 | 399 | php_sw_results_indexes_to_array(r, &tmp TSRMLS_CC); 400 | zend_hash_update(r->std.properties, "indexes", sizeof("indexes"), (void *)&tmp, sizeof(zval *), NULL); 401 | return r->std.properties; 402 | } 403 | /* }}} */ 404 | 405 | static void php_sw_prop_to_zval(struct php_sw_result *r, char *name , zval **prop TSRMLS_DC) /* {{{ */ 406 | { 407 | PropValue *v; 408 | 409 | MAKE_STD_ZVAL(*prop); 410 | 411 | v = getResultPropValue(r->r, name, 0); 412 | if (!v) { 413 | ZVAL_NULL(*prop); 414 | } else { 415 | switch(v->datatype) { 416 | case PROP_STRING: 417 | ZVAL_STRING(*prop, v->value.v_str, 1); 418 | break; 419 | case PROP_INTEGER: 420 | ZVAL_LONG(*prop, v->value.v_int); 421 | break; 422 | case PROP_DATE: 423 | ZVAL_LONG(*prop, v->value.v_date); 424 | break; 425 | case PROP_FLOAT: 426 | ZVAL_DOUBLE(*prop, v->value.v_float); 427 | break; 428 | case PROP_ULONG: 429 | ZVAL_LONG(*prop, v->value.v_ulong); 430 | break; 431 | default: 432 | ZVAL_NULL(*prop); 433 | break; 434 | } 435 | freeResultPropValue(v); 436 | } 437 | } 438 | /* }}} */ 439 | 440 | #if PHP_VERSION_ID >= 50400 441 | static zval *php_sw_result_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */ 442 | #else 443 | static zval *php_sw_result_read_property(zval *object, zval *member, int type TSRMLS_DC) 444 | #endif 445 | { 446 | struct php_sw_result *r; 447 | zval tmp_member; 448 | zval *retval; 449 | zend_object_handlers *std_hnd; 450 | 451 | r = (struct php_sw_result*)zend_object_store_get_object(object TSRMLS_CC); 452 | 453 | if (member->type != IS_STRING) { 454 | tmp_member = *member; 455 | zval_copy_ctor(&tmp_member); 456 | convert_to_string(&tmp_member); 457 | member = &tmp_member; 458 | } 459 | 460 | php_sw_prop_to_zval(r, Z_STRVAL_P(member), &retval TSRMLS_CC); 461 | 462 | if (Z_TYPE_P(retval) == IS_NULL) { 463 | /* not found */ 464 | zval_ptr_dtor(&retval); 465 | std_hnd = zend_get_std_object_handlers(); 466 | #if PHP_VERSION_ID >= 50400 467 | retval = std_hnd->read_property(object, member, type, key TSRMLS_CC); 468 | #else 469 | retval = std_hnd->read_property(object, member, type TSRMLS_CC); 470 | #endif 471 | } else { 472 | Z_SET_REFCOUNT_P(retval, 0); 473 | } 474 | 475 | if (member == &tmp_member) { 476 | zval_dtor(member); 477 | } 478 | return(retval); 479 | } 480 | /* }}} */ 481 | 482 | static HashTable *php_sw_result_get_properties(zval *object TSRMLS_DC) /* {{{ */ 483 | { 484 | struct php_sw_result *r; 485 | zval *prop; 486 | SWISH_META_LIST meta; 487 | char *name; 488 | 489 | r = (struct php_sw_result*)zend_objects_get_address(object TSRMLS_CC); 490 | 491 | meta = SwishResultPropertyList(r->r); 492 | 493 | while (meta && *meta) { 494 | name = (char*)SwishMetaName(*meta); 495 | php_sw_prop_to_zval(r, name, &prop TSRMLS_CC); 496 | zend_hash_update(r->std.properties, name, strlen(name)+1, (void *)&prop, sizeof(zval *), NULL); 497 | meta++; 498 | } 499 | 500 | return r->std.properties; 501 | } 502 | /* }}} */ 503 | 504 | static void php_sw_handle_indexes_to_array(struct php_sw_handle *h, zval **z_indexes TSRMLS_DC) /* {{{ */ 505 | { 506 | zval *index, *ztmp, *header; 507 | const char **index_names, **header_names, **curr_header; 508 | SWISH_HEADER_VALUE header_value; 509 | SWISH_HEADER_TYPE header_type; 510 | 511 | index_names = SwishIndexNames(h->h); 512 | header_names = SwishHeaderNames(h->h); 513 | 514 | MAKE_STD_ZVAL(*z_indexes); 515 | array_init(*z_indexes); 516 | 517 | while (index_names && *index_names) { 518 | MAKE_STD_ZVAL(index); 519 | array_init(index); 520 | 521 | MAKE_STD_ZVAL(ztmp); 522 | ZVAL_STRING(ztmp, (char *)(*index_names), 1); 523 | 524 | add_assoc_zval(index, "name", ztmp); 525 | 526 | MAKE_STD_ZVAL(ztmp); 527 | array_init(ztmp); 528 | 529 | curr_header = header_names; 530 | while (curr_header && *curr_header) { 531 | header_value = SwishHeaderValue(h->h, *index_names, *curr_header, &header_type); 532 | php_sw_header_to_zval(header_value, header_type, &header, 1 TSRMLS_CC); 533 | add_assoc_zval(ztmp, (char *)(*curr_header), header); 534 | 535 | curr_header++; 536 | } 537 | 538 | add_assoc_zval(index, "headers", ztmp); 539 | add_next_index_zval(*z_indexes, index); 540 | index_names++; 541 | } 542 | } 543 | /* }}} */ 544 | 545 | #if PHP_VERSION_ID >= 50400 546 | static zval *php_sw_handle_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */ 547 | #else 548 | static zval *php_sw_handle_read_property(zval *object, zval *member, int type TSRMLS_DC) 549 | #endif 550 | { 551 | struct php_sw_handle *h; 552 | zval tmp_member; 553 | zval *retval; 554 | zend_object_handlers *std_hnd; 555 | 556 | h = (struct php_sw_handle*)zend_object_store_get_object(object TSRMLS_CC); 557 | 558 | if (member->type != IS_STRING) { 559 | tmp_member = *member; 560 | zval_copy_ctor(&tmp_member); 561 | convert_to_string(&tmp_member); 562 | member = &tmp_member; 563 | } 564 | 565 | if (Z_STRLEN_P(member) == (sizeof("indexes") - 1) && !memcmp(Z_STRVAL_P(member), "indexes", Z_STRLEN_P(member))){ 566 | php_sw_handle_indexes_to_array(h, &retval TSRMLS_CC); 567 | Z_SET_REFCOUNT_P(retval, 0); 568 | } else { 569 | std_hnd = zend_get_std_object_handlers(); 570 | #if PHP_VERSION_ID >= 50400 571 | retval = std_hnd->read_property(object, member, type, key TSRMLS_CC); 572 | #else 573 | retval = std_hnd->read_property(object, member, type TSRMLS_CC); 574 | #endif 575 | } 576 | 577 | if (member == &tmp_member) { 578 | zval_dtor(member); 579 | } 580 | return retval; 581 | } 582 | /* }}} */ 583 | 584 | static HashTable *php_sw_handle_get_properties(zval *object TSRMLS_DC) /* {{{ */ 585 | { 586 | struct php_sw_handle *h; 587 | zval *z_indexes; 588 | 589 | h = (struct php_sw_handle*)zend_objects_get_address(object TSRMLS_CC); 590 | 591 | php_sw_handle_indexes_to_array(h, &z_indexes TSRMLS_CC); 592 | zend_hash_update(h->std.properties, "indexes", sizeof("indexes"), (void *)&z_indexes, sizeof(zval *), NULL); 593 | 594 | return h->std.properties; 595 | } 596 | /* }}} */ 597 | 598 | static void fill_property_list(zval *return_value, SWISH_META_LIST meta TSRMLS_DC) /* {{{ */ 599 | { 600 | zval *prop; 601 | 602 | array_init(return_value); 603 | 604 | while (meta && *meta) { 605 | MAKE_STD_ZVAL(prop); 606 | array_init(prop); 607 | 608 | add_assoc_string(prop, "Name", (char*)SwishMetaName(*meta), 1); 609 | add_assoc_long(prop, "Type", SwishMetaType(*meta)); 610 | add_assoc_long(prop, "ID", SwishMetaID(*meta)); 611 | 612 | add_next_index_zval(return_value, prop); 613 | meta++; 614 | } 615 | } 616 | /* }}} */ 617 | 618 | /* }}} */ 619 | 620 | /* {{{ proto void Swish::__construct(string indices) 621 | Open a swish index */ 622 | static PHP_METHOD(Swish, __construct) 623 | { 624 | zval *object = getThis(); 625 | struct php_sw_handle *h; 626 | char *indices; 627 | int indices_len; 628 | 629 | if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &indices, &indices_len)) { 630 | return; 631 | } 632 | 633 | h = (struct php_sw_handle*)zend_object_store_get_object(object TSRMLS_CC); 634 | 635 | if (h->h) { 636 | /* called __construct() twice, bail out */ 637 | return; 638 | } 639 | 640 | h->h = SwishInit(indices); 641 | 642 | if (sw_throw_exception(h TSRMLS_CC)) { 643 | return; 644 | } 645 | } 646 | /* }}} */ 647 | 648 | /* {{{ proto object Swish::prepare([string query]) 649 | Returns a new search object */ 650 | static PHP_METHOD(Swish, prepare) 651 | { 652 | struct php_sw_handle *h; 653 | char *query = NULL; 654 | int qlen; 655 | struct php_sw_search *s; 656 | SW_SEARCH search; 657 | 658 | if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &query, &qlen)) { 659 | return; 660 | } 661 | 662 | h = (struct php_sw_handle*)zend_object_store_get_object(getThis() TSRMLS_CC); 663 | 664 | search = New_Search_Object(h->h, query); 665 | 666 | if (sw_throw_exception(h TSRMLS_CC)) { 667 | if (search) { 668 | Free_Search_Object(search); 669 | } 670 | return; 671 | } 672 | 673 | object_init_ex(return_value, ce_sw_search); 674 | Z_SET_REFCOUNT_P(return_value, 1); 675 | Z_SET_ISREF_P(return_value); 676 | 677 | s = zend_object_store_get_object(return_value TSRMLS_CC); 678 | s->s = search; 679 | 680 | s->refhandle = *getThis(); 681 | zend_objects_store_add_ref(getThis() TSRMLS_CC); 682 | s->h = h; 683 | } 684 | /* }}} */ 685 | 686 | /* {{{ proto object Swish::query(string query) 687 | Executes a search, returning the result object */ 688 | static PHP_METHOD(Swish, query) 689 | { 690 | char *query = NULL; 691 | int qlen; 692 | struct php_sw_handle *h; 693 | struct php_sw_results *r; 694 | SW_RESULTS results; 695 | 696 | if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &query, &qlen)) { 697 | return; 698 | } 699 | 700 | h = (struct php_sw_handle*)zend_object_store_get_object(getThis() TSRMLS_CC); 701 | 702 | results = SwishQuery(h->h, query); 703 | 704 | if (sw_throw_exception(h TSRMLS_CC)) { 705 | if (results) { 706 | Free_Results_Object(results); 707 | } 708 | return; 709 | } 710 | 711 | object_init_ex(return_value, ce_sw_results); 712 | Z_SET_REFCOUNT_P(return_value, 1); 713 | Z_SET_ISREF_P(return_value); 714 | r = zend_object_store_get_object(return_value TSRMLS_CC); 715 | r->r = results; 716 | r->h = h; 717 | 718 | r->refhandle = *getThis(); 719 | zend_objects_store_add_ref(&r->refhandle TSRMLS_CC); 720 | } 721 | /* }}} */ 722 | 723 | /* {{{ proto array Swish::getMetaList(string indexname) 724 | Returns an array of meta information for a named index */ 725 | static PHP_METHOD(Swish, getMetaList) 726 | { 727 | struct php_sw_handle *h; 728 | char *index_name; 729 | int len; 730 | SWISH_META_LIST meta; 731 | 732 | if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &index_name, &len)) { 733 | return; 734 | } 735 | 736 | h = (struct php_sw_handle*)zend_object_store_get_object(getThis() TSRMLS_CC); 737 | 738 | meta = SwishMetaList(h->h, index_name); 739 | fill_property_list(return_value, meta TSRMLS_CC); 740 | } 741 | /* }}} */ 742 | 743 | /* {{{ proto array Swish::getPropertyList(string indexname) 744 | Returns an array of property information for a named index */ 745 | static PHP_METHOD(Swish, getPropertyList) 746 | { 747 | struct php_sw_handle *h; 748 | char *index_name; 749 | int len; 750 | SWISH_META_LIST meta; 751 | 752 | if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &index_name, &len)) { 753 | return; 754 | } 755 | 756 | h = (struct php_sw_handle*)zend_object_store_get_object(getThis() TSRMLS_CC); 757 | 758 | meta = SwishPropertyList(h->h, index_name); 759 | fill_property_list(return_value, meta TSRMLS_CC); 760 | } 761 | /* }}} */ 762 | 763 | /* {{{ proto void SwishSearch::setStructure(int structure) 764 | Sets the "structure" flag in the search object */ 765 | static PHP_METHOD(SwishSearch, setStructure) 766 | { 767 | struct php_sw_search *s; 768 | long l; 769 | 770 | if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &l)) { 771 | return; 772 | } 773 | 774 | s = (struct php_sw_search*)zend_object_store_get_object(getThis() TSRMLS_CC); 775 | SwishSetStructure(s->s, l); 776 | } 777 | /* }}} */ 778 | 779 | /* {{{ proto void SwishSearch::setPhraseDelimiter(string delim) 780 | Sets the phrase delimiter character, the default is double-quotes */ 781 | static PHP_METHOD(SwishSearch, setPhraseDelimiter) 782 | { 783 | struct php_sw_search *s; 784 | char *str; 785 | int str_len; 786 | 787 | if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len)) { 788 | return; 789 | } 790 | 791 | s = (struct php_sw_search*)zend_object_store_get_object(getThis() TSRMLS_CC); 792 | SwishPhraseDelimiter(s->s, *str); 793 | } 794 | /* }}} */ 795 | 796 | /* {{{ proto void SwishSearch::setSort(string sort) 797 | Sets the sort order of the results */ 798 | static PHP_METHOD(SwishSearch, setSort) 799 | { 800 | struct php_sw_search *s; 801 | char *str; 802 | int str_len; 803 | 804 | if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len)) { 805 | return; 806 | } 807 | 808 | s = (struct php_sw_search*)zend_object_store_get_object(getThis() TSRMLS_CC); 809 | 810 | SwishSetSort(s->s, str); 811 | } 812 | /* }}} */ 813 | 814 | /* {{{ proto void SwishSearch::setLimit(string prop, string low, string hi) 815 | Sets the limit parameters for a search */ 816 | static PHP_METHOD(SwishSearch, setLimit) 817 | { 818 | struct php_sw_search *s; 819 | char *prop, *low, *hi; 820 | int pl, ll, hl; 821 | 822 | if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss", &prop, &pl, &low, &ll, &hi, &hl)) { 823 | return; 824 | } 825 | 826 | s = (struct php_sw_search*)zend_object_store_get_object(getThis() TSRMLS_CC); 827 | if (SwishSetSearchLimit(s->s, prop, low, hi) == 0) { 828 | if (sw_throw_exception(s->h TSRMLS_CC)) { 829 | return; 830 | } 831 | } 832 | } 833 | /* }}} */ 834 | 835 | /* {{{ proto void SwishSearch::resetLimit() 836 | Resets the limit parameters for a search */ 837 | static PHP_METHOD(SwishSearch, resetLimit) 838 | { 839 | struct php_sw_search *s; 840 | 841 | if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "")) { 842 | return; 843 | } 844 | 845 | s = (struct php_sw_search*)zend_object_store_get_object(getThis() TSRMLS_CC); 846 | SwishResetSearchLimit(s->s); 847 | } 848 | /* }}} */ 849 | 850 | /* {{{ proto object SwishSearch::execute([string query]) 851 | Returns a new results object */ 852 | static PHP_METHOD(SwishSearch, execute) 853 | { 854 | char *query = NULL; 855 | int qlen; 856 | struct php_sw_search *s; 857 | struct php_sw_results *r; 858 | SW_RESULTS results; 859 | 860 | if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &query, &qlen)) { 861 | return; 862 | } 863 | 864 | s = (struct php_sw_search*)zend_object_store_get_object(getThis() TSRMLS_CC); 865 | 866 | results = SwishExecute(s->s, query); 867 | 868 | if (sw_throw_exception(s->h TSRMLS_CC)) { 869 | if (results) { 870 | Free_Results_Object(results); 871 | } 872 | return; 873 | } 874 | 875 | object_init_ex(return_value, ce_sw_results); 876 | Z_SET_REFCOUNT_P(return_value, 1); 877 | Z_SET_ISREF_P(return_value); 878 | r = zend_object_store_get_object(return_value TSRMLS_CC); 879 | r->r = results; 880 | r->h = s->h; 881 | 882 | r->refhandle = s->refhandle; 883 | zend_objects_store_add_ref(&s->refhandle TSRMLS_CC); 884 | } 885 | /* }}} */ 886 | 887 | /* {{{ proto long SwishResults::seekResult(int position) 888 | Sets the current seek position in the list of results. 0 is the first. */ 889 | static PHP_METHOD(SwishResults, seekResult) 890 | { 891 | struct php_sw_results *r; 892 | long l; 893 | int retval; 894 | 895 | if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &l)) { 896 | return; 897 | } 898 | 899 | if (l < 0) { 900 | zend_throw_exception_ex(ce_sw_exception, 0 TSRMLS_CC, "position cannot be less than zero"); 901 | return; 902 | } 903 | 904 | r = (struct php_sw_results*)zend_object_store_get_object(getThis() TSRMLS_CC); 905 | if (!r->r) { 906 | zend_throw_exception_ex(ce_sw_exception, 0 TSRMLS_CC, "no more results"); 907 | return; 908 | } 909 | 910 | retval = SwishSeekResult(r->r, l); 911 | if (sw_throw_exception(r->h TSRMLS_CC)) { 912 | return; 913 | } 914 | RETURN_LONG(retval); 915 | } 916 | /* }}} */ 917 | 918 | /* {{{ proto object SwishResults::nextResult() 919 | Advances to the next result. Returns false when there are no more results. */ 920 | static PHP_METHOD(SwishResults, nextResult) 921 | { 922 | struct php_sw_results *r; 923 | struct php_sw_result *result; 924 | SW_RESULT res; 925 | 926 | if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "")) { 927 | return; 928 | } 929 | 930 | r = (struct php_sw_results*)zend_object_store_get_object(getThis() TSRMLS_CC); 931 | if (!r->r) { 932 | RETURN_FALSE; 933 | } 934 | res = SwishNextResult(r->r); 935 | if (!res) { 936 | RETURN_FALSE; 937 | } 938 | 939 | object_init_ex(return_value, ce_sw_result); 940 | Z_SET_REFCOUNT_P(return_value, 1); 941 | Z_SET_ISREF_P(return_value); 942 | result = zend_object_store_get_object(return_value TSRMLS_CC); 943 | result->r = res; 944 | result->h = r->h; 945 | 946 | result->refhandle = r->refhandle; 947 | zend_objects_store_add_ref(&r->refhandle TSRMLS_CC); 948 | } 949 | /* }}} */ 950 | 951 | /* {{{ proto array SwishResults::getParsedWords(string indexname) 952 | Returns the tokenized query */ 953 | static PHP_METHOD(SwishResults, getParsedWords) 954 | { 955 | struct php_sw_results *r; 956 | SWISH_HEADER_VALUE value; 957 | char *index; 958 | int index_len; 959 | 960 | if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &index, &index_len)) { 961 | return; 962 | } 963 | 964 | r = (struct php_sw_results*)zend_object_store_get_object(getThis() TSRMLS_CC); 965 | if (!r->r) { 966 | RETURN_FALSE; 967 | } 968 | 969 | value = SwishParsedWords(r->r, index); 970 | if (!value.string_list) { 971 | RETURN_FALSE; 972 | } 973 | 974 | php_sw_header_to_zval(value, SWISH_LIST, &return_value, 0 TSRMLS_CC); 975 | } 976 | /* }}} */ 977 | 978 | /* {{{ proto array SwishResults::getRemovedStopwords(string indexname) 979 | Returns a list of stopwords removed from the query */ 980 | static PHP_METHOD(SwishResults, getRemovedStopwords) 981 | { 982 | struct php_sw_results *r; 983 | SWISH_HEADER_VALUE value; 984 | char *index; 985 | int index_len; 986 | 987 | if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &index, &index_len)) { 988 | return; 989 | } 990 | 991 | r = (struct php_sw_results*)zend_object_store_get_object(getThis() TSRMLS_CC); 992 | if (!r->r) { 993 | RETURN_FALSE; 994 | } 995 | 996 | value = SwishRemovedStopwords(r->r, index); 997 | if (!value.string_list) { 998 | RETURN_FALSE; 999 | } 1000 | 1001 | php_sw_header_to_zval(value, SWISH_LIST, &return_value, 0 TSRMLS_CC); 1002 | } 1003 | /* }}} */ 1004 | 1005 | /* {{{ proto array SwishResult::getMetaList() 1006 | Returns an array of meta information for the result */ 1007 | static PHP_METHOD(SwishResult, getMetaList) 1008 | { 1009 | struct php_sw_result *r; 1010 | SWISH_META_LIST meta; 1011 | 1012 | if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "")) { 1013 | return; 1014 | } 1015 | 1016 | r = (struct php_sw_result*)zend_object_store_get_object(getThis() TSRMLS_CC); 1017 | 1018 | meta = SwishResultMetaList(r->r); 1019 | fill_property_list(return_value, meta TSRMLS_CC); 1020 | } 1021 | /* }}} */ 1022 | 1023 | /* {{{ proto array SwishResult::stem(string word) 1024 | Stems the word and returns result as an array */ 1025 | static PHP_METHOD(SwishResult, stem) 1026 | { 1027 | struct php_sw_result *r; 1028 | SW_FUZZYWORD fuzzy_word; 1029 | const char** word_list; 1030 | char *word; 1031 | int word_len; 1032 | zval *tmp; 1033 | int error; 1034 | 1035 | if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &word, &word_len)) { 1036 | return; 1037 | } 1038 | 1039 | r = (struct php_sw_result*)zend_object_store_get_object(getThis() TSRMLS_CC); 1040 | 1041 | fuzzy_word = SwishFuzzyWord(r->r, word); 1042 | if (sw_throw_exception(r->h TSRMLS_CC)) { 1043 | return; 1044 | } 1045 | 1046 | if (!fuzzy_word) { 1047 | RETURN_FALSE; 1048 | } 1049 | 1050 | word_list = SwishFuzzyWordList(fuzzy_word); 1051 | error = SwishFuzzyWordError(fuzzy_word); 1052 | if (error) { 1053 | sw_stemmer_error_to_exception(error TSRMLS_CC); 1054 | SwishFuzzyWordFree(fuzzy_word); 1055 | RETURN_FALSE; 1056 | } 1057 | 1058 | array_init(return_value); 1059 | while (word_list && *word_list) { 1060 | MAKE_STD_ZVAL(tmp); 1061 | ZVAL_STRING(tmp, (char *)(*word_list), 1); 1062 | add_next_index_zval(return_value, tmp); 1063 | 1064 | word_list++; 1065 | } 1066 | SwishFuzzyWordFree(fuzzy_word); 1067 | } 1068 | /* }}} */ 1069 | 1070 | /* {{{ class method tables */ 1071 | static zend_function_entry sw_handle_methods[] = { 1072 | PHP_ME(Swish, __construct, NULL, ZEND_ACC_PUBLIC) 1073 | PHP_ME(Swish, prepare, NULL, ZEND_ACC_PUBLIC) 1074 | PHP_ME(Swish, query, NULL, ZEND_ACC_PUBLIC) 1075 | PHP_ME(Swish, getMetaList, NULL, ZEND_ACC_PUBLIC) 1076 | PHP_ME(Swish, getPropertyList, NULL, ZEND_ACC_PUBLIC) 1077 | {NULL, NULL, NULL} 1078 | }; 1079 | 1080 | static zend_function_entry sw_search_methods[] = { 1081 | PHP_ME(SwishSearch, execute, NULL, ZEND_ACC_PUBLIC) 1082 | PHP_ME(SwishSearch, setStructure, NULL, ZEND_ACC_PUBLIC) 1083 | PHP_ME(SwishSearch, setPhraseDelimiter, NULL, ZEND_ACC_PUBLIC) 1084 | PHP_ME(SwishSearch, setSort, NULL, ZEND_ACC_PUBLIC) 1085 | PHP_ME(SwishSearch, setLimit, NULL, ZEND_ACC_PUBLIC) 1086 | PHP_ME(SwishSearch, resetLimit, NULL, ZEND_ACC_PUBLIC) 1087 | {NULL, NULL, NULL} 1088 | }; 1089 | 1090 | static zend_function_entry sw_results_methods[] = { 1091 | PHP_ME(SwishResults, seekResult, NULL, ZEND_ACC_PUBLIC) 1092 | PHP_ME(SwishResults, nextResult, NULL, ZEND_ACC_PUBLIC) 1093 | PHP_ME(SwishResults, getParsedWords, NULL, ZEND_ACC_PUBLIC) 1094 | PHP_ME(SwishResults, getRemovedStopwords, NULL, ZEND_ACC_PUBLIC) 1095 | {NULL, NULL, NULL} 1096 | }; 1097 | 1098 | static zend_function_entry sw_result_methods[] = { 1099 | PHP_ME(SwishResult, getMetaList, NULL, ZEND_ACC_PUBLIC) 1100 | PHP_ME(SwishResult, stem, NULL, ZEND_ACC_PUBLIC) 1101 | {NULL, NULL, NULL} 1102 | }; 1103 | /* }}} */ 1104 | 1105 | /* {{{ swish_functions[] */ 1106 | static zend_function_entry swish_functions[] = { 1107 | {NULL, NULL, NULL} 1108 | }; 1109 | /* }}} */ 1110 | 1111 | #ifdef COMPILE_DL_SWISH 1112 | ZEND_GET_MODULE(swish) 1113 | #endif 1114 | 1115 | #define PHP_SWISH_CLASS_CONST(name, value) \ 1116 | zend_declare_class_constant_long(ce_sw_handle, name, sizeof(name)-1, (long)value TSRMLS_CC); 1117 | 1118 | /* {{{ PHP_MINIT_FUNCTION */ 1119 | PHP_MINIT_FUNCTION(swish) 1120 | { 1121 | zend_class_entry ce; 1122 | 1123 | memcpy(&cannot_be_cloned, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); 1124 | cannot_be_cloned.clone_obj = NULL; 1125 | 1126 | memcpy(&php_sw_result_obj_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); 1127 | php_sw_result_obj_handlers.clone_obj = NULL; 1128 | php_sw_result_obj_handlers.read_property = php_sw_result_read_property; 1129 | php_sw_result_obj_handlers.get_properties = php_sw_result_get_properties; 1130 | 1131 | memcpy(&php_sw_handle_obj_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); 1132 | php_sw_handle_obj_handlers.clone_obj = NULL; 1133 | php_sw_handle_obj_handlers.read_property = php_sw_handle_read_property; 1134 | php_sw_handle_obj_handlers.get_properties = php_sw_handle_get_properties; 1135 | 1136 | memcpy(&php_sw_results_obj_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); 1137 | php_sw_results_obj_handlers.clone_obj = NULL; 1138 | php_sw_results_obj_handlers.read_property = php_sw_results_read_property; 1139 | php_sw_results_obj_handlers.get_properties = php_sw_results_get_properties; 1140 | 1141 | 1142 | INIT_CLASS_ENTRY(ce, "SwishException", NULL); 1143 | ce_sw_exception = zend_register_internal_class_ex(&ce, 1144 | zend_exception_get_default(TSRMLS_C), NULL TSRMLS_CC); 1145 | 1146 | INIT_CLASS_ENTRY(ce, "Swish", sw_handle_methods); 1147 | ce_sw_handle = zend_register_internal_class(&ce TSRMLS_CC); 1148 | ce_sw_handle->create_object = sw_handle_new; 1149 | 1150 | INIT_CLASS_ENTRY(ce, "SwishSearch", sw_search_methods); 1151 | ce_sw_search = zend_register_internal_class(&ce TSRMLS_CC); 1152 | ce_sw_search->create_object = sw_search_new; 1153 | 1154 | INIT_CLASS_ENTRY(ce, "SwishResults", sw_results_methods); 1155 | ce_sw_results = zend_register_internal_class(&ce TSRMLS_CC); 1156 | ce_sw_results->create_object = sw_results_new; 1157 | 1158 | INIT_CLASS_ENTRY(ce, "SwishResult", sw_result_methods); 1159 | ce_sw_result = zend_register_internal_class(&ce TSRMLS_CC); 1160 | ce_sw_result->create_object = sw_result_new; 1161 | 1162 | PHP_SWISH_CLASS_CONST("META_TYPE_UNDEF", SW_META_TYPE_UNDEF); 1163 | PHP_SWISH_CLASS_CONST("META_TYPE_STRING", SW_META_TYPE_STRING); 1164 | PHP_SWISH_CLASS_CONST("META_TYPE_ULONG", SW_META_TYPE_ULONG); 1165 | PHP_SWISH_CLASS_CONST("META_TYPE_DATE", SW_META_TYPE_DATE); 1166 | 1167 | PHP_SWISH_CLASS_CONST("IN_FILE_BIT", IN_FILE_BIT); 1168 | PHP_SWISH_CLASS_CONST("IN_TITLE_BIT", IN_TITLE_BIT); 1169 | PHP_SWISH_CLASS_CONST("IN_HEAD_BIT", IN_HEAD_BIT); 1170 | PHP_SWISH_CLASS_CONST("IN_BODY_BIT", IN_BODY_BIT); 1171 | PHP_SWISH_CLASS_CONST("IN_COMMENTS_BIT", IN_COMMENTS_BIT); 1172 | PHP_SWISH_CLASS_CONST("IN_HEADER_BIT", IN_HEADER_BIT); 1173 | PHP_SWISH_CLASS_CONST("IN_EMPHASIZED_BIT", IN_EMPHASIZED_BIT); 1174 | PHP_SWISH_CLASS_CONST("IN_META_BIT", IN_META_BIT); 1175 | 1176 | PHP_SWISH_CLASS_CONST("IN_FILE", IN_FILE); 1177 | PHP_SWISH_CLASS_CONST("IN_TITLE", IN_TITLE); 1178 | PHP_SWISH_CLASS_CONST("IN_HEAD", IN_HEAD); 1179 | PHP_SWISH_CLASS_CONST("IN_BODY", IN_BODY); 1180 | PHP_SWISH_CLASS_CONST("IN_COMMENTS", IN_COMMENTS); 1181 | PHP_SWISH_CLASS_CONST("IN_HEADER", IN_HEADER); 1182 | PHP_SWISH_CLASS_CONST("IN_EMPHASIZED", IN_EMPHASIZED); 1183 | PHP_SWISH_CLASS_CONST("IN_META", IN_META); 1184 | PHP_SWISH_CLASS_CONST("IN_ALL", IN_ALL); 1185 | 1186 | return SUCCESS; 1187 | } 1188 | /* }}} */ 1189 | 1190 | /* {{{ PHP_MINFO_FUNCTION */ 1191 | PHP_MINFO_FUNCTION(swish) 1192 | { 1193 | php_info_print_table_start(); 1194 | php_info_print_table_header(2, "swish support", "enabled"); 1195 | php_info_print_table_row(2, "extension version", PHP_SWISH_VERSION); 1196 | /* DO NOT REMOVE THIS URL! 1197 | * It is here for license compliance */ 1198 | php_info_print_table_row(2, "source available from", "http://swish-e.org"); 1199 | php_info_print_table_end(); 1200 | } 1201 | /* }}} */ 1202 | 1203 | /* {{{ swish_module_entry */ 1204 | zend_module_entry swish_module_entry = { 1205 | #if ZEND_MODULE_API_NO >= 20010901 1206 | STANDARD_MODULE_HEADER, 1207 | #endif 1208 | "swish", 1209 | swish_functions, 1210 | PHP_MINIT(swish), 1211 | NULL, 1212 | NULL, 1213 | NULL, 1214 | PHP_MINFO(swish), 1215 | #if ZEND_MODULE_API_NO >= 20010901 1216 | PHP_SWISH_VERSION, 1217 | #endif 1218 | STANDARD_MODULE_PROPERTIES 1219 | }; 1220 | /* }}} */ 1221 | 1222 | /* 1223 | * Local variables: 1224 | * tab-width: 4 1225 | * c-basic-offset: 4 1226 | * End: 1227 | * vim600: noet sw=4 ts=4 fdm=marker 1228 | * vim<600: noet sw=4 ts=4 1229 | */ 1230 | --------------------------------------------------------------------------------