[-]
[+]
|
Added |
php-pecl-sphinx.changes
|
|
[-]
[+]
|
Deleted |
php5-sphinx.changes
^
|
@@ -1,10 +0,0 @@
--------------------------------------------------------------------
-Tue Aug 4 08:46:47 UTC 2015 - cs@linux-administrator.com
-
-- update to release 1.3.3
-
--------------------------------------------------------------------
-Tue May 13 18:50:53 UTC 2014 - cs@linux-administrator.com
-
-- update to release 1.3.2
-
|
[-]
[+]
|
Added |
php-pecl-sphinx.spec
^
|
|
[-]
[+]
|
Deleted |
php5-sphinx.spec
^
|
@@ -1,87 +0,0 @@
-# norootforbuild
-%define pkg_name sphinx
-%define pkg_version 1.3.3
-%define php_version %(php-config --version 2>/dev/null)
-#
-Name: php5-sphinx
-Version: %{pkg_version}
-Release: 1
-#
-License: PHP
-Group: Productivity/Networking/Web/Servers
-#
-BuildRoot: %{_tmppath}/%{pkg_name}-%{version}-build
-BuildRequires: php5-devel libsphinxclient-devel gcc gcc-c++
-Requires: php5 = %{php_version}
-#
-URL: http://pecl.php.net/
-Source: http://pecl.php.net/package/%{pkg_name}/%{pkg_name}-%{version}.tgz
-Summary: This extension provides bindings for libsphinxclient, client library for Sphinx
-
-%description
-This extension provides bindings for libsphinxclient, client library for Sphinx.
-
-Authors:
----------
-
- Antony Dovgal
-
-%debug_package
-
-%prep
-%setup -n %{pkg_name}-%{version}
-
-%{__mkdir} %{name}
-
-%build
-/usr/bin/phpize
-pushd %{name}
-
-CFLAGS="%{optflags} -fno-strict-aliasing"
-CXXFLAGS="%{optflags} -fno-strict-aliasing"
-%if 0%{?suse_version} > 1000
-CFLAGS="$CFLAGS -fstack-protector"
-CXXFLAGS="$CXXFLAGS -fstack-protector"
-%endif
-
-export CFLAGS
-export CXXFLAGS
-
-../configure --with-sphinx=%{_usr} --with-libdir=%{_lib}
-
-%{__make} %{?jobs:-j%jobs}
-popd
-
-%install
-%makeinstall -C %{name} INSTALL_ROOT=%{buildroot}
-%{__mkdir} -p %{buildroot}%{_sysconfdir}/php5/conf.d
-echo "; comment out next line to disable sphinx extension in php" > %{buildroot}%{_sysconfdir}/php5/conf.d/sphinx.ini
-echo "extension = sphinx.so" >> %{buildroot}%{_sysconfdir}/php5/conf.d/sphinx.ini
-
-
-%clean
-%{__rm} -rf %{buildroot}
-
-%files
-%defattr(-,root,root,-)
-%{_libdir}/php5/extensions/sphinx.so
-%config(noreplace) %{_sysconfdir}/php5/conf.d/sphinx.ini
-
-%doc CREDITS
-
-%changelog
-* Thu Apr 04 2013 Carsten Schoene <cs@linux-administrator.com> - 1.3.0-1
-- update to release 1.3.0
-
-* Sun Apr 09 2012 Carsten Schoene <cs@linux-administrator.com> - 1.2.0-1
-- update to release 1.2.0
-
-* Tue Jan 12 2010 Carsten Schoene <cs@linux-administrator.com> - 1.0.3-0
-- update to release 1.0.3
- - Added support for open(), close(), status() and setOverride() available in sphinx 0.9.9 new API
-
-* Sun Dec 20 2009 Carsten Schoene <cs@linux-administrator.com> - 1.0.2-0
-- update to release 1.0.2
-
-* Sat Jan 31 2009 Carsten Schoene <cs@linux-administrator.com>
-- initial build version 1.0.0
|
[-]
[+]
|
Added |
package.xml
^
|
@@ -0,0 +1,237 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<package packagerversion="1.9.5" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
+ <name>sphinx</name>
+ <channel>pecl.php.net</channel>
+ <summary>Client extension for Sphinx - opensource SQL full-text search engine</summary>
+ <description>This extension provides bindings for libsphinxclient, client library for Sphinx.</description>
+ <lead>
+ <name>Antony Dovgal</name>
+ <user>tony2001</user>
+ <email>tony2001@php.net</email>
+ <active>yes</active>
+ </lead>
+ <lead>
+ <name>Alexey Romanenko</name>
+ <user>santiago</user>
+ <email>santiago739@gmail.com</email>
+ <active>yes</active>
+ </lead>
+ <date>2015-05-21</date>
+ <time>15:33:48</time>
+ <version>
+ <release>1.3.99.1</release>
+ <api>1.3.99.1</api>
+ </version>
+ <stability>
+ <release>unstable</release>
+ <api>unstable</api>
+ </stability>
+ <license uri="http://www.php.net/license">PHP</license>
+ <notes>
+- PHP7 support
+ </notes>
+ <contents>
+ <dir name="/">
+ </dir>
+ </contents>
+ <dependencies>
+ <required>
+ <php>
+ <min>7.0.0</min>
+ <max>7.1.0</max>
+ <exclude>6.0.0</exclude>
+ </php>
+ <pearinstaller>
+ <min>1.4.0b1</min>
+ </pearinstaller>
+ </required>
+ </dependencies>
+ <providesextension>sphinx</providesextension>
+ <extsrcrelease>
+ <configureoption default="autodetect" name="with-sphinx" prompt="Please provide the installation prefix of libsphinxclient" />
+ </extsrcrelease>
+ <changelog>
+ <release>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <version>
+ <release>1.3.2</release>
+ <api>1.3.2</api>
+ </version>
+ <date>2014-05-06</date>
+ <notes>
+- Fixed build with older libsphinxclient versions (Dmitry Saprykin)
+- Added LICENSE to the package.
+ </notes>
+ </release>
+ <release>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <version>
+ <release>1.3.1</release>
+ <api>1.3.1</api>
+ </version>
+ <date>2014-05-06</date>
+ <notes>
+- Fixed bug #67216 (segfault on setGroupBy()) (Dmitry Saprykin)
+- Fixed bug #66272 (Some constants are not defined)
+ </notes>
+ </release>
+ <release>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <version>
+ <release>1.3.0</release>
+ <api>1.3.0</api>
+ </version>
+ <date>2013-04-04</date>
+ <notes>
+- Fixed setRankingMode's proto and add new ranking mode constants (patch by Michael Squires)
+- Fixed segfault when reading object properties.
+- Fixed bug #62026 (Second param in setRankingMode should be optional)
+ </notes>
+ </release>
+ <release>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <version>
+ <release>1.2.0</release>
+ <api>1.2.0</api>
+ </version>
+ <date>2012-04-03</date>
+ <notes>
+- Added mva support to updateAttributes().
+- Fixed build with 5_4.
+- Fixed bug #61392 (build failure with new version of libsphinxclient)
+ </notes>
+ </release>
+ <release>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <version>
+ <release>1.1.0</release>
+ <api>1.1.0</api>
+ </version>
+ <date>2010-09-17</date>
+ <notes>
+- Added support for new API in sphinx 1.10
+ - Fixed PECL bug #18325 (support 1.10-beta string attributes)
+ - Fixed PECL bug #17558 (time taken in search result was incorrect)
+ </notes>
+ </release>
+ <release>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <version>
+ <release>1.0.4</release>
+ <api>1.0.4</api>
+ </version>
+ <date>2010-02-26</date>
+ <notes>
+- Fixed PECL bug #17007 (incorrect query causes SEGFAULT)
+ </notes>
+ </release>
+ <release>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <version>
+ <release>1.0.3</release>
+ <api>1.0.3</api>
+ </version>
+ <date>2010-01-12</date>
+ <notes>
+- Added support for open(), close(), status() and setOverride() available in sphinx 0.9.9 new API
+ </notes>
+ </release>
+ <release>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <version>
+ <release>1.0.2</release>
+ <api>1.0.2</api>
+ </version>
+ <date>2009-12-03</date>
+ <notes>
+- Fixed crash when extending class doesn't call parent constructor.
+ </notes>
+ </release>
+ <release>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <version>
+ <release>1.0.1</release>
+ <api>1.0.1</api>
+ </version>
+ <date>2009-11-03</date>
+ <notes>
+- Fixed build failure with PHP 5.1.x.
+- Added support for setSelect(), available in sphinx 0.9.9 new API (patch by Olivier Poitrey)
+ </notes>
+ </release>
+ <release>
+ <stability>
+ <release>stable</release>
+ <api>stable</api>
+ </stability>
+ <version>
+ <release>1.0.0</release>
+ <api>1.0.0</api>
+ </version>
+ <date>2009-01-29</date>
+ <notes>
|
[-]
[+]
|
Deleted |
sphinx-1.0.0.tgz/sphinx-1.0.0/CREDITS
^
|
@@ -1,2 +0,0 @@
-Sphinx client extension for PHP
-Antony Dovgal
|
[-]
[+]
|
Deleted |
sphinx-1.0.0.tgz/sphinx-1.0.0/config.m4
^
|
@@ -1,50 +0,0 @@
-dnl $Id: config.m4,v 1.2 2008/10/31 14:04:51 tony2001 Exp $
-
-PHP_ARG_WITH(sphinx, for sphinx support,
-[ --with-sphinx Include sphinx support])
-
-if test "$PHP_SPHINX" != "no"; then
-
- SEARCH_PATH="/usr/local /usr /local /opt"
- SEARCH_FOR="/include/sphinxclient.h"
-
- if test "$PHP_SPHINX" = "yes"; then
- AC_MSG_CHECKING([for libsphinxclient headers in default path])
- for i in $SEARCH_PATH ; do
- if test -r $i/$SEARCH_FOR; then
- SPHINX_DIR=$i
- AC_MSG_RESULT(found in $i)
- fi
- done
- else
- AC_MSG_CHECKING([for libsphinxclient headers in $PHP_SPHINX])
- if test -r $PHP_SPHINX/$SEARCH_FOR; then
- SPHINX_DIR=$PHP_SPHINX
- AC_MSG_RESULT([found])
- fi
- fi
-
- if test -z "$SPHINX_DIR"; then
- AC_MSG_RESULT([not found])
- AC_MSG_ERROR([Cannot find libsphinxclient headers])
- fi
-
- PHP_ADD_INCLUDE($SPHINX_DIR/include)
-
- LIBNAME=sphinxclient
- LIBSYMBOL=sphinx_create
-
- PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
- [
- PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $SPHINX_DIR/$PHP_LIBDIR, SPHINX_SHARED_LIBADD)
- AC_DEFINE(HAVE_SPHINXLIB,1,[ ])
- ],[
- AC_MSG_ERROR([wrong libsphinxclient version or lib not found])
- ],[
- -L$SPHINX_DIR/$PHP_LIBDIR -lm
- ])
-
- PHP_SUBST(SPHINX_SHARED_LIBADD)
-
- PHP_NEW_EXTENSION(sphinx, sphinx.c, $ext_shared)
-fi
|
[-]
[+]
|
Deleted |
sphinx-1.0.0.tgz/sphinx-1.0.0/config.w32
^
|
@@ -1,13 +0,0 @@
-// $Id: config.w32,v 1.1 2008/07/16 07:32:49 tony2001 Exp $
-// vim:ft=javascript
-
-ARG_WITH("sphinx", "for sphinx support", "yes");
-
-if (PHP_SPHINX == "yes") {
- if (CHECK_LIB("libsphinxclient.lib", "sphinx_create") &&
- CHECK_HEADER_ADD_INCLUDE("sphinxclient.h", "CFLAGS_SPHINX")) {
-
- EXTENSION("sphinx", "sphinx.c");
- }
-}
-
|
[-]
[+]
|
Deleted |
sphinx-1.0.0.tgz/sphinx-1.0.0/php_sphinx.h
^
|
@@ -1,46 +0,0 @@
-/*
- +----------------------------------------------------------------------+
- | PHP Version 5 |
- +----------------------------------------------------------------------+
- | Copyright (c) 1997-2008 The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- | Author: Antony Dovgal <tony at daylessday.org> |
- | Based on Sphinx PHP API by Andrew Aksyonoff <shodan at shodan.ru> |
- +----------------------------------------------------------------------+
-*/
-
-/* $Id: php_sphinx.h,v 1.5 2009/01/28 17:11:02 tony2001 Exp $ */
-
-#ifndef PHP_SPHINX_H
-#define PHP_SPHINX_H
-
-extern zend_module_entry sphinx_module_entry;
-#define phpext_sphinx_ptr &sphinx_module_entry
-
-#ifdef ZTS
-#include "TSRM.h"
-#endif
-
-PHP_MINIT_FUNCTION(sphinx);
-PHP_MINFO_FUNCTION(sphinx);
-
-#define PHP_SPHINX_VERSION "1.0.0"
-
-#endif /* PHP_SPHINX_H */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
|
[-]
[+]
|
Deleted |
sphinx-1.0.0.tgz/sphinx-1.0.0/sphinx.c
^
|
@@ -1,1610 +0,0 @@
-/*
- +----------------------------------------------------------------------+
- | PHP Version 5 |
- +----------------------------------------------------------------------+
- | Copyright (c) 1997-2008 The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- | Author: Antony Dovgal <tony at daylessday.org> |
- | Based on Sphinx PHP API by Andrew Aksyonoff <shodan at shodan.ru> |
- +----------------------------------------------------------------------+
-*/
-
-/* $Id: sphinx.c,v 1.17 2008/11/21 15:23:05 tony2001 Exp $ */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "php.h"
-#include "php_ini.h"
-#include "ext/standard/info.h"
-#include "ext/standard/file.h"
-#include "zend_operators.h"
-#include "php_sphinx.h"
-
-#include <sphinxclient.h>
-
-static zend_class_entry *ce_sphinx_client;
-
-static zend_object_handlers php_sphinx_client_handlers;
-static zend_object_handlers cannot_be_cloned;
-
-typedef struct _php_sphinx_client {
- zend_object std;
- sphinx_client *sphinx;
- zend_bool array_result;
-} php_sphinx_client;
-
-#ifdef COMPILE_DL_SPHINX
-ZEND_GET_MODULE(sphinx)
-#endif
-
-#define SPHINX_CONST(name) REGISTER_LONG_CONSTANT(#name, name, CONST_CS | CONST_PERSISTENT)
-
-static void php_sphinx_client_obj_dtor(void *object TSRMLS_DC) /* {{{ */
-{
- php_sphinx_client *c = (php_sphinx_client *)object;
-
- sphinx_destroy(c->sphinx);
- zend_object_std_dtor(&c->std TSRMLS_CC);
- efree(c);
-}
-/* }}} */
-
-static zend_object_value php_sphinx_client_new(zend_class_entry *ce TSRMLS_DC) /* {{{ */
-{
- php_sphinx_client *c;
- zend_object_value retval;
-
- c = ecalloc(1, sizeof(*c));
- zend_object_std_init(&c->std, ce TSRMLS_CC);
-
- retval.handle = zend_objects_store_put(c, (zend_objects_store_dtor_t)zend_objects_destroy_object, php_sphinx_client_obj_dtor, NULL TSRMLS_CC);
- retval.handlers = &php_sphinx_client_handlers;
- return retval;
-}
-/* }}} */
-
-static zval *php_sphinx_client_read_property(zval *object, zval *member, int type TSRMLS_DC) /* {{{ */
-{
- php_sphinx_client *c;
- zval tmp_member;
- zval *retval;
- zend_object_handlers *std_hnd;
-
- c = (php_sphinx_client *)zend_object_store_get_object(object TSRMLS_CC);
-
- if (member->type != IS_STRING) {
- tmp_member = *member;
- zval_copy_ctor(&tmp_member);
- convert_to_string(&tmp_member);
- member = &tmp_member;
- }
-
- /* XXX we can either create retval ourselves (for custom properties) or use standard handlers */
-
- std_hnd = zend_get_std_object_handlers();
- retval = std_hnd->read_property(object, member, type TSRMLS_CC);
-
- if (member == &tmp_member) {
- zval_dtor(member);
- }
- return retval;
-}
-/* }}} */
-
-static HashTable *php_sphinx_client_get_properties(zval *object TSRMLS_DC) /* {{{ */
-{
- php_sphinx_client *c;
- const char *warning, *error;
- zval *tmp;
-
- c = (php_sphinx_client *)zend_objects_get_address(object TSRMLS_CC);
-
- error = sphinx_error(c->sphinx);
- MAKE_STD_ZVAL(tmp);
- ZVAL_STRING(tmp, (char *)error, 1);
- zend_hash_update(c->std.properties, "error", sizeof("error"), (void *)&tmp, sizeof(zval *), NULL);
-
- warning = sphinx_warning(c->sphinx);
- MAKE_STD_ZVAL(tmp);
- ZVAL_STRING(tmp, (char *)warning, 1);
- zend_hash_update(c->std.properties, "warning", sizeof("warning"), (void *)&tmp, sizeof(zval *), NULL);
- return c->std.properties;
-}
-/* }}} */
-
-#ifdef TONY_200807015
-static inline void php_sphinx_error(php_sphinx_client *c TSRMLS_DC) /* {{{ */
-{
- const char *err;
-
- err = sphinx_error(c->sphinx);
- if (!err || err[0] == '\0') {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "unknown error");
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", err);
- }
-}
-/* }}} */
-#endif
-
-static void php_sphinx_result_to_array(php_sphinx_client *c, sphinx_result *result, zval **array TSRMLS_DC) /* {{{ */
-{
- zval *tmp, *tmp_element, *sub_element, *sub_sub_element;
- int i, j;
-
- array_init(*array);
-
- /* error */
- if (!result->error) {
- add_assoc_string_ex(*array, "error", sizeof("error"), "", 1);
- } else {
- add_assoc_string_ex(*array, "error", sizeof("error"), (char *)(result->error), 1);
- }
-
- /* warning */
- if (!result->warning) {
- add_assoc_string_ex(*array, "warning", sizeof("warning"), "", 1);
- } else {
- add_assoc_string_ex(*array, "warning", sizeof("warning"), (char *)result->warning, 1);
- }
-
- /* status */
- add_assoc_long_ex(*array, "status", sizeof("status"), result->status);
-
- /* fields */
- MAKE_STD_ZVAL(tmp);
- array_init(tmp);
-
- for (i = 0; i < result->num_fields; i++) {
- add_next_index_string(tmp, result->fields[i], 1);
- }
- add_assoc_zval_ex(*array, "fields", sizeof("fields"), tmp);
-
- /* attrs */
- MAKE_STD_ZVAL(tmp);
- array_init(tmp);
-
- for (i = 0; i < result->num_attrs; i++) {
-#if SIZEOF_LONG == 8
- add_assoc_long_ex(tmp, result->attr_names[i], strlen(result->attr_names[i]) + 1, result->attr_types[i]);
-#else
- double float_value;
- char buf[128];
-
- float_value = (double)result->attr_types[i];
- slprintf(buf, sizeof(buf), "%.0f", float_value);
- add_assoc_string_ex(tmp, result->attr_names[i], strlen(result->attr_names[i]) + 1, buf, 1);
-#endif
- }
- add_assoc_zval_ex(*array, "attrs", sizeof("attrs"), tmp);
-
- /* matches */
- if (result->num_matches) {
- MAKE_STD_ZVAL(tmp);
- array_init(tmp);
-
- for (i = 0; i < result->num_matches; i++) {
- MAKE_STD_ZVAL(tmp_element);
- array_init(tmp_element);
-
- if (c->array_result) {
- /* id */
-#if SIZEOF_LONG == 8
- add_assoc_long_ex(tmp_element, "id", sizeof("id"), sphinx_get_id(result, i));
-#else
- double float_id;
- char buf[128];
-
- float_id = (double)sphinx_get_id(result, i);
- slprintf(buf, sizeof(buf), "%.0f", float_id);
- add_assoc_string_ex(tmp_element, "id", sizeof("id"), buf, 1);
-#endif
- }
-
- /* weight */
- add_assoc_long_ex(tmp_element, "weight", sizeof("weight"), sphinx_get_weight(result, i));
-
- /* attrs */
- MAKE_STD_ZVAL(sub_element);
- array_init(sub_element);
-
- for (j = 0; j < result->num_attrs; j++) {
- double float_value;
- char buf[128];
-
- MAKE_STD_ZVAL(sub_sub_element);
-
- switch(result->attr_types[j]) {
- case SPH_ATTR_MULTI | SPH_ATTR_INTEGER:
- {
- int k;
- unsigned int *mva = sphinx_get_mva(result, i, j);
- unsigned int tmp, num;
-
- array_init(sub_sub_element);
-
- if (!mva) {
- break;
- }
-
- memcpy(&num, mva, sizeof(unsigned int));
-
- for (k = 1; k <= num; k++) {
- mva++;
- memcpy(&tmp, mva, sizeof(unsigned int));
-#if SIZEOF_LONG == 8
- add_next_index_long(sub_sub_element, tmp);
-#else
- float_value = (double)tmp;
- slprintf(buf, sizeof(buf), "%.0f", float_value);
- add_next_index_string(sub_sub_element, buf, 1);
-#endif
- }
- } break;
-
- case SPH_ATTR_FLOAT:
- ZVAL_DOUBLE(sub_sub_element, sphinx_get_float(result, i, j));
- break;
- default:
-#if SIZEOF_LONG == 8
- ZVAL_LONG(sub_sub_element, sphinx_get_int(result, i, j));
-#else
- float_value = (double)sphinx_get_int(result, i, j);
- slprintf(buf, sizeof(buf), "%.0f", float_value);
- ZVAL_STRING(sub_sub_element, buf, 1);
-#endif
- break;
- }
-
- add_assoc_zval(sub_element, result->attr_names[j], sub_sub_element);
- }
-
- add_assoc_zval_ex(tmp_element, "attrs", sizeof("attrs"), sub_element);
-
- if (c->array_result) {
- add_next_index_zval(tmp, tmp_element);
- } else {
-#if SIZEOF_LONG == 8
- add_index_zval(tmp, sphinx_get_id(result, i), tmp_element);
-#else
- char buf[128];
- double float_id;
- int buf_len;
-
- float_id = (double)sphinx_get_id(result, i);
- buf_len = slprintf(buf, sizeof(buf), "%.0f", float_id);
- add_assoc_zval_ex(tmp, buf, buf_len + 1, tmp_element);
-#endif
- }
- }
-
- add_assoc_zval_ex(*array, "matches", sizeof("matches"), tmp);
- }
-
- /* total */
- add_assoc_long_ex(*array, "total", sizeof("total"), result->total);
-
- /* total_found */
- add_assoc_long_ex(*array, "total_found", sizeof("total_found"), result->total_found);
-
- /* time */
- add_assoc_double_ex(*array, "time", sizeof("time"), result->time_msec/1000);
-
- /* words */
- if (result->num_words) {
- MAKE_STD_ZVAL(tmp);
- array_init(tmp);
- for (i = 0; i < result->num_words; i++) {
- MAKE_STD_ZVAL(sub_element);
- array_init(sub_element);
-
- add_assoc_long_ex(sub_element, "docs", sizeof("docs"), result->words[i].docs);
- add_assoc_long_ex(sub_element, "hits", sizeof("hits"), result->words[i].hits);
- add_assoc_zval_ex(tmp, (char *)result->words[i].word, strlen(result->words[i].word) + 1, sub_element);
- }
- add_assoc_zval_ex(*array, "words", sizeof("words"), tmp);
- }
-}
-/* }}} */
-
-
-/* {{{ proto void SphinxClient::__construct() */
-static PHP_METHOD(SphinxClient, __construct)
-{
- php_sphinx_client *c;
-
- c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
-
- if (c->sphinx) {
- /* called __construct() twice, bail out */
- return;
- }
-
- c->sphinx = sphinx_create(1 /* copy string args */);
-
- sphinx_set_connect_timeout(c->sphinx, FG(default_socket_timeout));
-}
-/* }}} */
-
-/* {{{ proto bool SphinxClient::setServer(string server, int port) */
-static PHP_METHOD(SphinxClient, setServer)
-{
- php_sphinx_client *c;
- long port;
- char *server;
- int server_len, res;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &server, &server_len, &port) == FAILURE) {
- return;
- }
-
- c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
-
- res = sphinx_set_server(c->sphinx, server, (int)port);
- if (!res) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto bool SphinxClient::setLimits(int offset, int limit[, int max_matches[, int cutoff]]) */
-static PHP_METHOD(SphinxClient, setLimits)
-{
- php_sphinx_client *c;
- long offset, limit, max_matches = 0, cutoff = 0;
- int res;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll|ll", &offset, &limit, &max_matches, &cutoff) == FAILURE) {
- return;
- }
-
- c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
-
- res = sphinx_set_limits(c->sphinx, (int)offset, (int)limit, (int)max_matches, (int)cutoff);
- if (!res) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto bool SphinxClient::setMatchMode(int mode) */
-static PHP_METHOD(SphinxClient, setMatchMode)
-{
- php_sphinx_client *c;
- long mode;
- int res;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &mode) == FAILURE) {
- return;
- }
-
- c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
-
- res = sphinx_set_match_mode(c->sphinx, mode);
- if (!res) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto bool SphinxClient::setIndexWeights(array weights) */
-static PHP_METHOD(SphinxClient, setIndexWeights)
-{
- php_sphinx_client *c;
- zval *weights, **item;
- int num_weights, res = 0, i;
- int *index_weights;
- char **index_names;
- char *string_key;
- unsigned int string_key_len;
- unsigned long int num_key;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &weights) == FAILURE) {
- return;
- }
-
- c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
-
- num_weights = zend_hash_num_elements(Z_ARRVAL_P(weights));
- if (!num_weights) {
- /* check for empty array and return false right away */
- RETURN_FALSE;
- }
-
- index_names = safe_emalloc(num_weights, sizeof(char *), 0);
- index_weights = safe_emalloc(num_weights, sizeof(int), 0);
-
- /* reset num_weights, we'll reuse it count _real_ number of entries */
- num_weights = 0;
-
- for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(weights));
- zend_hash_get_current_data(Z_ARRVAL_P(weights), (void **)&item) != FAILURE;
- zend_hash_move_forward(Z_ARRVAL_P(weights))) {
-
- if (zend_hash_get_current_key_ex(Z_ARRVAL_P(weights), &string_key, &string_key_len, &num_key, 0, NULL) != HASH_KEY_IS_STRING) {
- /* if the key is not string.. well.. you're screwed */
- break;
- }
-
- convert_to_long_ex(item);
-
- index_names[num_weights] = estrndup(string_key, string_key_len);
- index_weights[num_weights] = Z_LVAL_PP(item);
-
- num_weights++;
- }
-
- if (num_weights) {
- res = sphinx_set_index_weights(c->sphinx, num_weights, (const char **)index_names, index_weights);
- }
-
- for (i = 0; i != num_weights; i++) {
- efree(index_names[i]);
- }
- efree(index_names);
- efree(index_weights);
-
- if (!res) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto bool SphinxClient::setIDRange(int min, int max) */
-static PHP_METHOD(SphinxClient, setIDRange)
-{
- php_sphinx_client *c;
- long min, max;
- int res;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ll", &min, &max) == FAILURE) {
- return;
- }
-
- c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
-
- res = sphinx_set_id_range(c->sphinx, (sphinx_uint64_t)min, (sphinx_uint64_t)max);
- if (!res) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto bool SphinxClient::setFilter(string attribute, array values[, bool exclude]) */
-static PHP_METHOD(SphinxClient, setFilter)
-{
- php_sphinx_client *c;
- zval *values, **item;
- char *attribute;
- int attribute_len, num_values, i = 0, res;
- zend_bool exclude = 0;
- sphinx_uint64_t *u_values;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sa|b", &attribute, &attribute_len, &values, &exclude) == FAILURE) {
- return;
- }
-
- c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
-
- num_values = zend_hash_num_elements(Z_ARRVAL_P(values));
- if (!num_values) {
- RETURN_FALSE;
- }
-
- u_values = safe_emalloc(num_values, sizeof(sphinx_uint64_t), 0);
-
- for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(values));
- zend_hash_get_current_data(Z_ARRVAL_P(values), (void **) &item) != FAILURE;
- zend_hash_move_forward(Z_ARRVAL_P(values))) {
-
- convert_to_double_ex(item);
- u_values[i] = (sphinx_uint64_t)Z_DVAL_PP(item);
- i++;
- }
-
- res = sphinx_add_filter(c->sphinx, attribute, num_values, u_values, exclude ? 1 : 0);
- efree(u_values);
-
- if (!res) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto bool SphinxClient::setFilterRange(string attribute, int min, int max[, bool exclude]) */
-static PHP_METHOD(SphinxClient, setFilterRange)
-{
- php_sphinx_client *c;
- char *attribute;
- int attribute_len, res;
- long min, max;
- zend_bool exclude = 0;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sll|b", &attribute, &attribute_len, &min, &max, &exclude ) == FAILURE) {
- return;
- }
-
- c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
-
- res = sphinx_add_filter_range(c->sphinx, attribute, min, max, exclude);
-
- if (!res) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto bool SphinxClient::setFilterFloatRange(string attribute, float min, float max[, bool exclude]) */
-static PHP_METHOD(SphinxClient, setFilterFloatRange)
-{
- php_sphinx_client *c;
- char *attribute;
- int attribute_len, res;
- double min, max;
- zend_bool exclude = 0;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sdd|b", &attribute, &attribute_len, &min, &max, &exclude) == FAILURE) {
- return;
- }
-
- c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
-
- res = sphinx_add_filter_float_range(c->sphinx, attribute, min, max, exclude);
-
- if (!res) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto bool SphinxClient::setGeoAnchor(string attrlat, string attrlong, float latitude, float longitude) */
-static PHP_METHOD(SphinxClient, setGeoAnchor)
-{
- php_sphinx_client *c;
- char *attrlat, *attrlong;
- int attrlat_len, attrlong_len, res;
- double latitude, longitude;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssdd", &attrlat, &attrlat_len, &attrlong, &attrlong_len, &latitude, &longitude) == FAILURE) {
- return;
- }
-
- c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
-
- res = sphinx_set_geoanchor(c->sphinx, attrlat, attrlong, latitude, longitude);
-
- if (!res) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto bool SphinxClient::setGroupBy(string attribute, int func[, string groupsort]) */
-static PHP_METHOD(SphinxClient, setGroupBy)
-{
- php_sphinx_client *c;
- char *attribute, *groupsort = NULL;
- int attribute_len, groupsort_len, func, res;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|s", &attribute, &attribute_len, &func, &groupsort, &groupsort_len) == FAILURE) {
- return;
- }
-
- if (groupsort == NULL) {
- groupsort = "@group desc";
- }
-
- c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
-
- res = sphinx_set_groupby(c->sphinx, attribute, func, groupsort);
-
- if (!res) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto bool SphinxClient::setGroupDistinct(string attribute) */
-static PHP_METHOD(SphinxClient, setGroupDistinct)
-{
- php_sphinx_client *c;
- char *attribute;
- int attribute_len, res;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &attribute, &attribute_len) == FAILURE) {
- return;
- }
-
- c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
-
- res = sphinx_set_groupby_distinct(c->sphinx, attribute);
-
- if (!res) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto bool SphinxClient::setRetries(int count[, int delay]) */
-static PHP_METHOD(SphinxClient, setRetries)
-{
- php_sphinx_client *c;
- long count, delay = 0;
- int res;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|l", &count, &delay) == FAILURE) {
- return;
- }
-
- c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
-
- res = sphinx_set_retries(c->sphinx, (int)count, (int)delay);
-
- if (!res) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto bool SphinxClient::setMaxQueryTime(int qtime) */
-static PHP_METHOD(SphinxClient, setMaxQueryTime)
-{
- php_sphinx_client *c;
- long qtime;
- int res;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &qtime) == FAILURE) {
- return;
- }
-
- c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
-
- res = sphinx_set_max_query_time(c->sphinx, (int)qtime);
-
- if (!res) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto bool SphinxClient::setRankingMode(int ranker) */
-static PHP_METHOD(SphinxClient, setRankingMode)
-{
- php_sphinx_client *c;
- long ranker;
- int res;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &ranker) == FAILURE) {
- return;
- }
-
- c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
-
- res = sphinx_set_ranking_mode(c->sphinx, (int)ranker);
-
- if (!res) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto bool SphinxClient::setFieldWeights(array weights) */
-static PHP_METHOD(SphinxClient, setFieldWeights)
-{
- php_sphinx_client *c;
- zval *weights, **item;
- int num_weights, res = 0, i;
- int *field_weights;
- char **field_names;
- char *string_key;
- unsigned int string_key_len;
- unsigned long int num_key;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &weights) == FAILURE) {
- return;
- }
-
- c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
-
- num_weights = zend_hash_num_elements(Z_ARRVAL_P(weights));
- if (!num_weights) {
- /* check for empty array and return false right away */
- RETURN_FALSE;
- }
-
- field_names = safe_emalloc(num_weights, sizeof(char *), 0);
- field_weights = safe_emalloc(num_weights, sizeof(int), 0);
-
- /* reset num_weights, we'll reuse it count _real_ number of entries */
- num_weights = 0;
-
- for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(weights));
- zend_hash_get_current_data(Z_ARRVAL_P(weights), (void **)&item) != FAILURE;
- zend_hash_move_forward(Z_ARRVAL_P(weights))) {
-
- if (zend_hash_get_current_key_ex(Z_ARRVAL_P(weights), &string_key, &string_key_len, &num_key, 0, NULL) != HASH_KEY_IS_STRING) {
- /* if the key is not string.. well.. you're screwed */
- break;
- }
-
- convert_to_long_ex(item);
-
- field_names[num_weights] = estrndup(string_key, string_key_len);
- field_weights[num_weights] = Z_LVAL_PP(item);
-
- num_weights++;
- }
-
- if (num_weights) {
- res = sphinx_set_field_weights(c->sphinx, num_weights, (const char **) field_names, field_weights);
- }
-
- for (i = 0; i != num_weights; i++) {
- efree(field_names[i]);
- }
- efree(field_names);
- efree(field_weights);
-
- if (!res) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto bool SphinxClient::setSortMode(int mode[, string sortby]) */
-static PHP_METHOD(SphinxClient, setSortMode)
-{
- php_sphinx_client *c;
- long mode;
- char *sortby = NULL;
- int sortby_len, res;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|s", &mode, &sortby, &sortby_len) == FAILURE) {
- return;
- }
-
- c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
-
- res = sphinx_set_sort_mode(c->sphinx, (int)mode, sortby);
-
- if (!res) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto bool SphinxClient::setConnectTimeout(float timeout) */
-static PHP_METHOD(SphinxClient, setConnectTimeout)
-{
- php_sphinx_client *c;
- double timeout;
- int res;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &timeout) == FAILURE) {
- return;
- }
-
- c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
-
- res = sphinx_set_connect_timeout(c->sphinx, timeout);
-
- if (!res) {
- RETURN_FALSE;
- }
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto bool SphinxClient::setArrayResult(bool array_result) */
-static PHP_METHOD(SphinxClient, setArrayResult)
-{
- php_sphinx_client *c;
- zend_bool array_result;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "b", &array_result) == FAILURE) {
- return;
- }
-
- c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
-
- c->array_result = array_result;
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto int SphinxClient::updateAttributes(string index, array attributes, array values) */
-static PHP_METHOD(SphinxClient, updateAttributes)
-{
- php_sphinx_client *c;
- zval *attributes, *values, **item;
- char *index;
- const char **attrs;
- int index_len, attrs_num, values_num, a = 0, i = 0, j = 0;
- int res;
- sphinx_uint64_t *docids = NULL, *vals = NULL;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "saa", &index, &index_len, &attributes, &values) == FAILURE) {
- return;
- }
-
- c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
-
- attrs_num = zend_hash_num_elements(Z_ARRVAL_P(attributes));
-
- if (!attrs_num) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "empty attributes array passed");
- RETURN_FALSE;
- }
-
- values_num = zend_hash_num_elements(Z_ARRVAL_P(values));
-
- if (!values_num) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "empty values array passed");
- RETURN_FALSE;
- }
-
- attrs = emalloc(sizeof(char *) * attrs_num);
- for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(attributes));
- zend_hash_get_current_data(Z_ARRVAL_P(attributes), (void **) &item) != FAILURE;
- zend_hash_move_forward(Z_ARRVAL_P(attributes))) {
- if (Z_TYPE_PP(item) != IS_STRING) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "non-string attributes are not allowed");
- break;
- }
- attrs[a] = Z_STRVAL_PP(item); /* no copying here! */
- a++;
- }
-
- /* cleanup on error */
- if (a != attrs_num) {
- RETVAL_FALSE;
- goto cleanup;
- }
-
- docids = emalloc(sizeof(sphinx_uint64_t) * values_num);
- vals = safe_emalloc(values_num * attrs_num, sizeof(sphinx_uint64_t), 0);
- for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(values));
- zend_hash_get_current_data(Z_ARRVAL_P(values), (void **) &item) != FAILURE;
- zend_hash_move_forward(Z_ARRVAL_P(values))) {
- char *str_id;
- ulong id;
- zval **attr_value;
- int failed = 0, key_type;
- uint str_id_len;
- double float_id = 0;
- unsigned char id_type;
-
- if (Z_TYPE_PP(item) != IS_ARRAY) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "value is not an array of attributes");
- break;
- }
-
- if (zend_hash_num_elements(Z_ARRVAL_PP(item)) != attrs_num) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "number of values is not equal to the number of attributes");
- break;
- }
-
- key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(values), &str_id, &str_id_len, &id, 0, NULL);
-
- if (key_type == HASH_KEY_IS_LONG) {
- /* ok */
- id_type = IS_LONG;
- } else if (key_type == HASH_KEY_IS_STRING) {
- id_type = is_numeric_string(str_id, str_id_len, (long *)&id, &float_id, 0);
- if (id_type == IS_LONG || id_type == IS_DOUBLE) {
- /* ok */
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "document ID must be numeric");
- break;
- }
- } else {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "document ID must be integer");
- break;
- }
-
- for (zend_hash_internal_pointer_reset(Z_ARRVAL_PP(item));
- zend_hash_get_current_data(Z_ARRVAL_PP(item), (void **) &attr_value) != FAILURE;
- zend_hash_move_forward(Z_ARRVAL_PP(item))) {
- if (Z_TYPE_PP(attr_value) != IS_LONG) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "attribute value must be integer");
- failed = 1;
- break;
- }
- vals[j] = (sphinx_uint64_t)Z_LVAL_PP(attr_value);
- j++;
- }
-
- if (failed) {
- break;
- }
-
- if (id_type == IS_LONG) {
- docids[i] = (sphinx_uint64_t)id;
- } else { /* IS_FLOAT */
- docids[i] = (sphinx_uint64_t)float_id;
- }
- i++;
- }
-
- if (i != values_num) {
- RETVAL_FALSE;
- goto cleanup;
- }
-
- res = sphinx_update_attributes(c->sphinx, index, (int)attrs_num, attrs, values_num, docids, vals);
-
- if (res < 0) {
- RETVAL_FALSE;
- } else {
- RETVAL_LONG(res);
- }
-
-cleanup:
- efree(attrs);
- if (docids) {
- efree(docids);
- }
- if (vals) {
- efree(vals);
- }
-}
-/* }}} */
-
-/* {{{ proto array SphinxClient::buildExcerpts(array docs, string index, string words[, array opts]) */
-static PHP_METHOD(SphinxClient, buildExcerpts)
-{
- php_sphinx_client *c;
- zval *docs_array, *opts_array = NULL, **item;
- char *index, *words;
- const char **docs;
- sphinx_excerpt_options opts;
- int index_len, words_len;
- int docs_num, i = 0;
- char **result;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ass|a", &docs_array, &index, &index_len, &words, &words_len, &opts_array) == FAILURE) {
- return;
- }
-
- c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
-
- docs_num = zend_hash_num_elements(Z_ARRVAL_P(docs_array));
-
- if (!docs_num) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "empty documents array passed");
- RETURN_FALSE;
- }
-
- docs = emalloc(sizeof(char *) * docs_num);
- for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(docs_array));
- zend_hash_get_current_data(Z_ARRVAL_P(docs_array), (void **) &item) != FAILURE;
- zend_hash_move_forward(Z_ARRVAL_P(docs_array))) {
- if (Z_TYPE_PP(item) != IS_STRING) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "non-string documents are not allowed");
- break;
- }
- docs[i] = Z_STRVAL_PP(item); /* no copying here! */
- i++;
- }
-
- if (i != docs_num) {
- RETVAL_FALSE;
- goto cleanup;
- }
-
-#define OPTS_EQUAL(str, str_len, txt) str_len == sizeof(txt) && memcmp(txt, str, sizeof(txt)) == 0
-
- if (opts_array) {
- char *string_key;
- unsigned int string_key_len;
- ulong dummy;
-
- /* nullify everything */
- memset(&opts, 0, sizeof(sphinx_excerpt_options));
- for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(opts_array));
- zend_hash_get_current_data(Z_ARRVAL_P(opts_array), (void **) &item) != FAILURE;
- zend_hash_move_forward(Z_ARRVAL_P(opts_array))) {
-
- switch (Z_TYPE_PP(item)) {
- case IS_STRING:
- case IS_LONG:
- case IS_BOOL:
- break;
- default:
- continue; /* ignore invalid options */
- }
-
- if (zend_hash_get_current_key_ex(Z_ARRVAL_P(opts_array), &string_key, &string_key_len, &dummy, 0, NULL) != HASH_KEY_IS_STRING) {
- continue; /* ignore invalid option names */
- }
-
- if (OPTS_EQUAL(string_key, string_key_len, "before_match")) {
- SEPARATE_ZVAL(item);
- convert_to_string_ex(item);
- opts.before_match = Z_STRVAL_PP(item);
- } else if (OPTS_EQUAL(string_key, string_key_len, "after_match")) {
- SEPARATE_ZVAL(item);
- convert_to_string_ex(item);
- opts.after_match = Z_STRVAL_PP(item);
- } else if (OPTS_EQUAL(string_key, string_key_len, "chunk_separator")) {
- SEPARATE_ZVAL(item);
- convert_to_string_ex(item);
- opts.chunk_separator = Z_STRVAL_PP(item);
- } else if (OPTS_EQUAL(string_key, string_key_len, "limit")) {
- SEPARATE_ZVAL(item);
- convert_to_long_ex(item);
- opts.limit = (int)Z_LVAL_PP(item);
- } else if (OPTS_EQUAL(string_key, string_key_len, "around")) {
- SEPARATE_ZVAL(item);
- convert_to_long_ex(item);
- opts.around = (int)Z_LVAL_PP(item);
- } else if (OPTS_EQUAL(string_key, string_key_len, "exact_phrase")) {
- SEPARATE_ZVAL(item);
- convert_to_boolean_ex(item);
- opts.exact_phrase = Z_LVAL_PP(item);
- } else if (OPTS_EQUAL(string_key, string_key_len, "single_passage")) {
- SEPARATE_ZVAL(item);
- convert_to_boolean_ex(item);
- opts.single_passage = Z_LVAL_PP(item);
- } else if (OPTS_EQUAL(string_key, string_key_len, "use_boundaries")) {
- SEPARATE_ZVAL(item);
- convert_to_boolean_ex(item);
- opts.use_boundaries = Z_LVAL_PP(item);
- } else if (OPTS_EQUAL(string_key, string_key_len, "weight_order")) {
- SEPARATE_ZVAL(item);
- convert_to_boolean_ex(item);
- opts.weight_order = Z_LVAL_PP(item);
- } else {
- /* ignore invalid option names */
- }
- }
- }
-
- if (opts_array) {
- result = sphinx_build_excerpts(c->sphinx, docs_num, docs, index, words, &opts);
- } else {
- result = sphinx_build_excerpts(c->sphinx, docs_num, docs, index, words, NULL);
- }
-
- if (!result) {
- RETVAL_FALSE;
- } else {
- array_init(return_value);
- for (i = 0; i < docs_num; i++) {
- if (result[i] && result[i][0] != '\0') {
- add_next_index_string(return_value, result[i], 1);
- } else {
- add_next_index_string(return_value, "", 1);
- }
- free(result[i]);
- }
- free(result);
- }
-
-cleanup:
- efree(docs);
-}
-/* }}} */
-
-/* {{{ proto array SphinxClient::buildKeywords(string query, string index, bool hits) */
-static PHP_METHOD(SphinxClient, buildKeywords)
-{
- php_sphinx_client *c;
- char *query, *index;
- int query_len, index_len;
- zend_bool hits;
- sphinx_keyword_info *result;
- int i, num_keywords;
- zval *tmp;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssb", &query, &query_len, &index, &index_len, &hits) == FAILURE) {
- return;
- }
-
- c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
-
- result = sphinx_build_keywords(c->sphinx, query, index, hits, &num_keywords);
- if (!result || num_keywords <= 0) {
- RETURN_FALSE;
- }
-
- array_init(return_value);
- for (i = 0; i < num_keywords; i++) {
- MAKE_STD_ZVAL(tmp);
- array_init(tmp);
-
- add_assoc_string_ex(tmp, "tokenized", sizeof("tokenized"), result[i].tokenized, 1);
- add_assoc_string_ex(tmp, "normalized", sizeof("normalized"), result[i].normalized, 1);
-
- if (hits) {
- add_assoc_long_ex(tmp, "docs", sizeof("docs"), result[i].num_docs);
- add_assoc_long_ex(tmp, "hits", sizeof("hits"), result[i].num_hits);
- }
-
- add_next_index_zval(return_value, tmp);
-
- free(result[i].tokenized);
- free(result[i].normalized);
- }
- free(result);
-}
-/* }}} */
-
-/* {{{ proto void SphinxClient::resetFilters() */
-static PHP_METHOD(SphinxClient, resetFilters)
-{
- php_sphinx_client *c;
-
- c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
-
- sphinx_reset_filters(c->sphinx);
-}
-/* }}} */
-
-/* {{{ proto void SphinxClient::resetGroupBy() */
-static PHP_METHOD(SphinxClient, resetGroupBy)
-{
- php_sphinx_client *c;
-
- c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
-
- sphinx_reset_groupby(c->sphinx);
-}
-/* }}} */
-
-/* {{{ proto string SphinxClient::getLastWarning() */
-static PHP_METHOD(SphinxClient, getLastWarning)
-{
- php_sphinx_client *c;
- const char *warning;
-
- c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
-
- warning = sphinx_warning(c->sphinx);
- if (!warning || !warning[0]) {
- RETURN_EMPTY_STRING();
- }
- RETURN_STRING((char *)warning, 1);
-}
-/* }}} */
-
-/* {{{ proto string SphinxClient::getLastError() */
-static PHP_METHOD(SphinxClient, getLastError)
-{
- php_sphinx_client *c;
- const char *error;
-
- c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
-
- error = sphinx_error(c->sphinx);
- if (!error || !error[0]) {
- RETURN_EMPTY_STRING();
- }
- RETURN_STRING((char *)error, 1);
-}
-/* }}} */
-
-/* {{{ proto array SphinxClient::query(string query[, string index[, string comment]]) */
-static PHP_METHOD(SphinxClient, query)
-{
- php_sphinx_client *c;
- char *query, *index = "*", *comment = "";
- int query_len, index_len, comment_len;
- sphinx_result *result;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ss", &query, &query_len, &index, &index_len, &comment, &comment_len) == FAILURE) {
- return;
- }
-
- c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
-
- result = sphinx_query(c->sphinx, query, index, comment);
-
- if (!result) {
- RETURN_FALSE;
- }
-
- php_sphinx_result_to_array(c, result, &return_value TSRMLS_CC);
-}
-
-/* }}} */
-
-/* {{{ proto int SphinxClient::addQuery(string query[, string index[, string comment]]) */
-static PHP_METHOD(SphinxClient, addQuery)
-{
- php_sphinx_client *c;
- char *query, *index = "*", *comment = "";
- int query_len, index_len, comment_len, res;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ss", &query, &query_len, &index, &index_len, &comment, &comment_len) == FAILURE) {
- return;
- }
-
- c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
-
- res = sphinx_add_query(c->sphinx, query, index, comment);
-
- if (res < 0) {
- RETURN_FALSE;
- }
- RETURN_LONG(res);
-}
-
-/* }}} */
-
-/* {{{ proto array SphinxClient::runQueries() */
-static PHP_METHOD(SphinxClient, runQueries)
-{
- php_sphinx_client *c;
- sphinx_result *results;
- int i, num_results;
- zval *single_result;
-
- c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
-
- results = sphinx_run_queries(c->sphinx);
-
- if (!results) {
- RETURN_FALSE;
- }
-
- num_results = sphinx_get_num_results(c->sphinx);
-
- array_init(return_value);
- for (i = 0; i < num_results; i++) {
- MAKE_STD_ZVAL(single_result);
- php_sphinx_result_to_array(c, &results[i], &single_result TSRMLS_CC);
- add_next_index_zval(return_value, single_result);
- }
-}
-/* }}} */
-
-/* {{{ proto string SphinxClient::escapeString(string data) */
-static PHP_METHOD(SphinxClient, escapeString)
-{
- char *str, *new_str, *source, *target;
- int str_len, new_str_len, i;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len) == FAILURE) {
- return;
- }
-
- if (!str_len) {
- RETURN_EMPTY_STRING();
- }
-
- new_str = safe_emalloc(2, str_len, 1);
- target = new_str;
- source = str;
- for (i = 0; i < str_len; i++) {
- switch (*source) {
- case '(':
- case ')':
- case '|':
- case '-':
- case '!':
- case '@':
- case '~':
- case '"':
- case '&':
- case '/':
- case '\\':
- *target++ = '\\';
- *target++ = *source;
- break;
- default:
- *target++ = *source;
- break;
- }
- source++;
- }
- *target = '\0';
-
- new_str_len = target - new_str;
- new_str = erealloc(new_str, new_str_len + 1);
- RETURN_STRINGL(new_str, new_str_len, 0);
-}
-/* }}} */
-
-/* {{{ proto int SphinxClient::__sleep() */
-static PHP_METHOD(SphinxClient, __sleep)
-{
- php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "SphinxClient instance cannot be (un)serialized");
-}
-/* }}} */
-
-/* {{{ proto int SphinxClient::__wakeup() */
-static PHP_METHOD(SphinxClient, __wakeup)
-{
- php_error_docref(NULL TSRMLS_CC, E_RECOVERABLE_ERROR, "SphinxClient instance cannot be (un)serialized");
-}
-/* }}} */
-
-/* {{{ arginfo */
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setserver, 0, 0, 2)
- ZEND_ARG_INFO(0, server)
- ZEND_ARG_INFO(0, port)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setlimits, 0, 0, 2)
- ZEND_ARG_INFO(0, offset)
- ZEND_ARG_INFO(0, limit)
- ZEND_ARG_INFO(0, max_matches)
- ZEND_ARG_INFO(0, cutoff)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setmatchmode, 0, 0, 1)
- ZEND_ARG_INFO(0, mode)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setindexweights, 0, 0, 1)
- ZEND_ARG_INFO(0, weights)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setidrange, 0, 0, 2)
- ZEND_ARG_INFO(0, min)
- ZEND_ARG_INFO(0, max)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setfilter, 0, 0, 2)
- ZEND_ARG_INFO(0, attribute)
- ZEND_ARG_INFO(0, values)
- ZEND_ARG_INFO(0, exclude)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setfilterrange, 0, 0, 3)
- ZEND_ARG_INFO(0, attribute)
- ZEND_ARG_INFO(0, min)
- ZEND_ARG_INFO(0, max)
- ZEND_ARG_INFO(0, exclude)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setgeoanchor, 0, 0, 4)
- ZEND_ARG_INFO(0, attrlat)
- ZEND_ARG_INFO(0, attrlong)
- ZEND_ARG_INFO(0, latitude)
- ZEND_ARG_INFO(0, longitude)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setgroupby, 0, 0, 2)
- ZEND_ARG_INFO(0, attribute)
- ZEND_ARG_INFO(0, func)
- ZEND_ARG_INFO(0, groupsort)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setgroupdistinct, 0, 0, 1)
- ZEND_ARG_INFO(0, attribute)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setretries, 0, 0, 1)
- ZEND_ARG_INFO(0, count)
- ZEND_ARG_INFO(0, delay)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setmaxquerytime, 0, 0, 1)
- ZEND_ARG_INFO(0, qtime)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setrankingmode, 0, 0, 1)
- ZEND_ARG_INFO(0, ranker)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setsortmode, 0, 0, 1)
- ZEND_ARG_INFO(0, mode)
- ZEND_ARG_INFO(0, sortby)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setconnecttimeout, 0, 0, 1)
- ZEND_ARG_INFO(0, timeout)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setarrayresult, 0, 0, 1)
- ZEND_ARG_INFO(0, array_result)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_updateattributes, 0, 0, 3)
- ZEND_ARG_INFO(0, index)
- ZEND_ARG_INFO(0, attributes)
- ZEND_ARG_INFO(0, values)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_buildexcerpts, 0, 0, 3)
- ZEND_ARG_INFO(0, docs)
- ZEND_ARG_INFO(0, index)
- ZEND_ARG_INFO(0, words)
- ZEND_ARG_INFO(0, opts)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_buildkeywords, 0, 0, 3)
- ZEND_ARG_INFO(0, query)
- ZEND_ARG_INFO(0, index)
- ZEND_ARG_INFO(0, hits)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_query, 0, 0, 1)
- ZEND_ARG_INFO(0, query)
- ZEND_ARG_INFO(0, index)
- ZEND_ARG_INFO(0, comment)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO(arginfo_sphinxclient__param_void, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_escapestring, 0, 0, 1)
- ZEND_ARG_INFO(0, data)
-ZEND_END_ARG_INFO()
-/* }}} */
-
-static zend_function_entry sphinx_client_methods[] = { /* {{{ */
- PHP_ME(SphinxClient, __construct, arginfo_sphinxclient__param_void, ZEND_ACC_PUBLIC)
- PHP_ME(SphinxClient, addQuery, arginfo_sphinxclient_query, ZEND_ACC_PUBLIC)
- PHP_ME(SphinxClient, buildExcerpts, arginfo_sphinxclient_buildexcerpts, ZEND_ACC_PUBLIC)
- PHP_ME(SphinxClient, buildKeywords, arginfo_sphinxclient_buildkeywords, ZEND_ACC_PUBLIC)
- PHP_ME(SphinxClient, getLastError, arginfo_sphinxclient__param_void, ZEND_ACC_PUBLIC)
- PHP_ME(SphinxClient, getLastWarning, arginfo_sphinxclient__param_void, ZEND_ACC_PUBLIC)
- PHP_ME(SphinxClient, escapeString, arginfo_sphinxclient_escapestring, ZEND_ACC_PUBLIC)
- PHP_ME(SphinxClient, query, arginfo_sphinxclient_query, ZEND_ACC_PUBLIC)
- PHP_ME(SphinxClient, resetFilters, arginfo_sphinxclient__param_void, ZEND_ACC_PUBLIC)
- PHP_ME(SphinxClient, resetGroupBy, arginfo_sphinxclient__param_void, ZEND_ACC_PUBLIC)
- PHP_ME(SphinxClient, runQueries, arginfo_sphinxclient__param_void, ZEND_ACC_PUBLIC)
- PHP_ME(SphinxClient, setArrayResult, arginfo_sphinxclient_setarrayresult, ZEND_ACC_PUBLIC)
- PHP_ME(SphinxClient, setConnectTimeout, arginfo_sphinxclient_setconnecttimeout, ZEND_ACC_PUBLIC)
- PHP_ME(SphinxClient, setFieldWeights, arginfo_sphinxclient_setindexweights, ZEND_ACC_PUBLIC)
- PHP_ME(SphinxClient, setFilter, arginfo_sphinxclient_setfilter, ZEND_ACC_PUBLIC)
- PHP_ME(SphinxClient, setFilterFloatRange, arginfo_sphinxclient_setfilterrange, ZEND_ACC_PUBLIC)
- PHP_ME(SphinxClient, setFilterRange, arginfo_sphinxclient_setfilterrange, ZEND_ACC_PUBLIC)
- PHP_ME(SphinxClient, setGeoAnchor, arginfo_sphinxclient_setgeoanchor, ZEND_ACC_PUBLIC)
- PHP_ME(SphinxClient, setGroupBy, arginfo_sphinxclient_setgroupby, ZEND_ACC_PUBLIC)
- PHP_ME(SphinxClient, setGroupDistinct, arginfo_sphinxclient_setgroupdistinct, ZEND_ACC_PUBLIC)
- PHP_ME(SphinxClient, setIndexWeights, arginfo_sphinxclient_setindexweights, ZEND_ACC_PUBLIC)
- PHP_ME(SphinxClient, setIDRange, arginfo_sphinxclient_setidrange, ZEND_ACC_PUBLIC)
- PHP_ME(SphinxClient, setLimits, arginfo_sphinxclient_setlimits, ZEND_ACC_PUBLIC)
- PHP_ME(SphinxClient, setMatchMode, arginfo_sphinxclient_setmatchmode, ZEND_ACC_PUBLIC)
- PHP_ME(SphinxClient, setMaxQueryTime, arginfo_sphinxclient_setmaxquerytime, ZEND_ACC_PUBLIC)
- PHP_ME(SphinxClient, setRankingMode, arginfo_sphinxclient_setrankingmode, ZEND_ACC_PUBLIC)
- PHP_ME(SphinxClient, setRetries, arginfo_sphinxclient_setretries, ZEND_ACC_PUBLIC)
- PHP_ME(SphinxClient, setServer, arginfo_sphinxclient_setserver, ZEND_ACC_PUBLIC)
- PHP_ME(SphinxClient, setSortMode, arginfo_sphinxclient_setsortmode, ZEND_ACC_PUBLIC)
- PHP_ME(SphinxClient, updateAttributes, arginfo_sphinxclient_updateattributes, ZEND_ACC_PUBLIC)
- PHP_ME(SphinxClient, __sleep, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
- PHP_ME(SphinxClient, __wakeup, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
- {NULL, NULL, NULL}
-};
-/* }}} */
-
-/* {{{ PHP_MINIT_FUNCTION
- */
-PHP_MINIT_FUNCTION(sphinx)
-{
- zend_class_entry ce;
-
- memcpy(&cannot_be_cloned, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
- cannot_be_cloned.clone_obj = NULL;
-
- memcpy(&php_sphinx_client_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
- php_sphinx_client_handlers.clone_obj = NULL;
- php_sphinx_client_handlers.read_property = php_sphinx_client_read_property;
- php_sphinx_client_handlers.get_properties = php_sphinx_client_get_properties;
-
- INIT_CLASS_ENTRY(ce, "SphinxClient", sphinx_client_methods);
- ce_sphinx_client = zend_register_internal_class(&ce TSRMLS_CC);
- ce_sphinx_client->create_object = php_sphinx_client_new;
-
- SPHINX_CONST(SEARCHD_OK);
- SPHINX_CONST(SEARCHD_ERROR);
- SPHINX_CONST(SEARCHD_RETRY);
- SPHINX_CONST(SEARCHD_WARNING);
-
- SPHINX_CONST(SPH_MATCH_ALL);
- SPHINX_CONST(SPH_MATCH_ANY);
- SPHINX_CONST(SPH_MATCH_PHRASE);
- SPHINX_CONST(SPH_MATCH_BOOLEAN);
- SPHINX_CONST(SPH_MATCH_EXTENDED);
- SPHINX_CONST(SPH_MATCH_FULLSCAN);
- SPHINX_CONST(SPH_MATCH_EXTENDED2);
-
- SPHINX_CONST(SPH_RANK_PROXIMITY_BM25);
- SPHINX_CONST(SPH_RANK_BM25);
- SPHINX_CONST(SPH_RANK_NONE);
- SPHINX_CONST(SPH_RANK_WORDCOUNT);
-
- SPHINX_CONST(SPH_SORT_RELEVANCE);
- SPHINX_CONST(SPH_SORT_ATTR_DESC);
- SPHINX_CONST(SPH_SORT_ATTR_ASC);
- SPHINX_CONST(SPH_SORT_TIME_SEGMENTS);
- SPHINX_CONST(SPH_SORT_EXTENDED);
- SPHINX_CONST(SPH_SORT_EXPR);
-
- SPHINX_CONST(SPH_FILTER_VALUES);
- SPHINX_CONST(SPH_FILTER_RANGE);
- SPHINX_CONST(SPH_FILTER_FLOATRANGE);
-
- SPHINX_CONST(SPH_ATTR_INTEGER);
- SPHINX_CONST(SPH_ATTR_TIMESTAMP);
- SPHINX_CONST(SPH_ATTR_ORDINAL);
- SPHINX_CONST(SPH_ATTR_BOOL);
- SPHINX_CONST(SPH_ATTR_FLOAT);
- SPHINX_CONST(SPH_ATTR_MULTI);
-
- SPHINX_CONST(SPH_GROUPBY_DAY);
- SPHINX_CONST(SPH_GROUPBY_WEEK);
- SPHINX_CONST(SPH_GROUPBY_MONTH);
- SPHINX_CONST(SPH_GROUPBY_YEAR);
- SPHINX_CONST(SPH_GROUPBY_ATTR);
- SPHINX_CONST(SPH_GROUPBY_ATTRPAIR);
-
- return SUCCESS;
-}
-/* }}} */
-
-/* {{{ PHP_MINFO_FUNCTION
- */
-PHP_MINFO_FUNCTION(sphinx)
-{
- php_info_print_table_start();
- php_info_print_table_header(2, "sphinx support", "enabled");
- php_info_print_table_header(2, "Version", PHP_SPHINX_VERSION);
- php_info_print_table_header(2, "Revision", "$Revision: 1.17 $");
- php_info_print_table_end();
-}
-/* }}} */
-
-static zend_function_entry sphinx_functions[] = { /* {{{ */
- {NULL, NULL, NULL}
-};
-/* }}} */
-
-/* {{{ sphinx_module_entry
- */
-zend_module_entry sphinx_module_entry = {
-#if ZEND_MODULE_API_NO >= 20010901
- STANDARD_MODULE_HEADER,
-#endif
- "sphinx",
- sphinx_functions,
- PHP_MINIT(sphinx),
- NULL,
- NULL,
- NULL,
- PHP_MINFO(sphinx),
-#if ZEND_MODULE_API_NO >= 20010901
- PHP_SPHINX_VERSION,
-#endif
- STANDARD_MODULE_PROPERTIES
-};
-/* }}} */
-
-/*
- * Local variables:
- * tab-width: 4
- * c-basic-offset: 4
- * End:
- * vim600: noet sw=4 ts=4 fdm=marker
- * vim<600: noet sw=4 ts=4
- */
|
|
Deleted |
sphinx-1.0.2.tgz
^
|
|
Deleted |
sphinx-1.0.3.tgz
^
|
|
Deleted |
sphinx-1.2.0.tgz
^
|
|
Deleted |
sphinx-1.3.0.tgz
^
|
|
Deleted |
sphinx-1.3.2.tgz
^
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git
^
|
+(directory)
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/HEAD
^
|
@@ -0,0 +1 @@
+ref: refs/heads/php7
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/branches
^
|
+(directory)
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/config
^
|
@@ -0,0 +1,11 @@
+[core]
+ repositoryformatversion = 0
+ filemode = true
+ bare = false
+ logallrefupdates = true
+[remote "origin"]
+ url = https://git.php.net/repository/pecl/search_engine/sphinx.git
+ fetch = +refs/heads/*:refs/remotes/origin/*
+[branch "php7"]
+ remote = origin
+ merge = refs/heads/php7
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/description
^
|
@@ -0,0 +1 @@
+Unnamed repository; edit this file 'description' to name the repository.
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/hooks
^
|
+(directory)
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/hooks/applypatch-msg.sample
^
|
@@ -0,0 +1,15 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message taken by
+# applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit. The hook is
+# allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "applypatch-msg".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/commit-msg" &&
+ exec "$GIT_DIR/hooks/commit-msg" ${1+"$@"}
+:
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/hooks/commit-msg.sample
^
|
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# An example hook script to check the commit log message.
+# Called by "git commit" with one argument, the name of the file
+# that has the commit message. The hook should exit with non-zero
+# status after issuing an appropriate message if it wants to stop the
+# commit. The hook is allowed to edit the commit message file.
+#
+# To enable this hook, rename this file to "commit-msg".
+
+# Uncomment the below to add a Signed-off-by line to the message.
+# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
+# hook is more suited to it.
+#
+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
+
+# This example catches duplicate Signed-off-by lines.
+
+test "" = "$(grep '^Signed-off-by: ' "$1" |
+ sort | uniq -c | sed -e '/^[ ]*1[ ]/d')" || {
+ echo >&2 Duplicate Signed-off-by lines.
+ exit 1
+}
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/hooks/post-update.sample
^
|
@@ -0,0 +1,8 @@
+#!/bin/sh
+#
+# An example hook script to prepare a packed repository for use over
+# dumb transports.
+#
+# To enable this hook, rename this file to "post-update".
+
+exec git update-server-info
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/hooks/pre-applypatch.sample
^
|
@@ -0,0 +1,14 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed
+# by applypatch from an e-mail message.
+#
+# The hook should exit with non-zero status after issuing an
+# appropriate message if it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-applypatch".
+
+. git-sh-setup
+test -x "$GIT_DIR/hooks/pre-commit" &&
+ exec "$GIT_DIR/hooks/pre-commit" ${1+"$@"}
+:
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/hooks/pre-commit.sample
^
|
@@ -0,0 +1,50 @@
+#!/bin/sh
+#
+# An example hook script to verify what is about to be committed.
+# Called by "git commit" with no arguments. The hook should
+# exit with non-zero status after issuing an appropriate message if
+# it wants to stop the commit.
+#
+# To enable this hook, rename this file to "pre-commit".
+
+if git rev-parse --verify HEAD >/dev/null 2>&1
+then
+ against=HEAD
+else
+ # Initial commit: diff against an empty tree object
+ against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
+fi
+
+# If you want to allow non-ascii filenames set this variable to true.
+allownonascii=$(git config hooks.allownonascii)
+
+# Redirect output to stderr.
+exec 1>&2
+
+# Cross platform projects tend to avoid non-ascii filenames; prevent
+# them from being added to the repository. We exploit the fact that the
+# printable range starts at the space character and ends with tilde.
+if [ "$allownonascii" != "true" ] &&
+ # Note that the use of brackets around a tr range is ok here, (it's
+ # even required, for portability to Solaris 10's /usr/bin/tr), since
+ # the square bracket bytes happen to fall in the designated range.
+ test $(git diff --cached --name-only --diff-filter=A -z $against |
+ LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
+then
+ echo "Error: Attempt to add a non-ascii file name."
+ echo
+ echo "This can cause problems if you want to work"
+ echo "with people on other platforms."
+ echo
+ echo "To be portable it is advisable to rename the file ..."
+ echo
+ echo "If you know what you are doing you can disable this"
+ echo "check using:"
+ echo
+ echo " git config hooks.allownonascii true"
+ echo
+ exit 1
+fi
+
+# If there are whitespace errors, print the offending file names and fail.
+exec git diff-index --check --cached $against --
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/hooks/pre-rebase.sample
^
|
@@ -0,0 +1,169 @@
+#!/bin/sh
+#
+# Copyright (c) 2006, 2008 Junio C Hamano
+#
+# The "pre-rebase" hook is run just before "git rebase" starts doing
+# its job, and can prevent the command from running by exiting with
+# non-zero status.
+#
+# The hook is called with the following parameters:
+#
+# $1 -- the upstream the series was forked from.
+# $2 -- the branch being rebased (or empty when rebasing the current branch).
+#
+# This sample shows how to prevent topic branches that are already
+# merged to 'next' branch from getting rebased, because allowing it
+# would result in rebasing already published history.
+
+publish=next
+basebranch="$1"
+if test "$#" = 2
+then
+ topic="refs/heads/$2"
+else
+ topic=`git symbolic-ref HEAD` ||
+ exit 0 ;# we do not interrupt rebasing detached HEAD
+fi
+
+case "$topic" in
+refs/heads/??/*)
+ ;;
+*)
+ exit 0 ;# we do not interrupt others.
+ ;;
+esac
+
+# Now we are dealing with a topic branch being rebased
+# on top of master. Is it OK to rebase it?
+
+# Does the topic really exist?
+git show-ref -q "$topic" || {
+ echo >&2 "No such branch $topic"
+ exit 1
+}
+
+# Is topic fully merged to master?
+not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
+if test -z "$not_in_master"
+then
+ echo >&2 "$topic is fully merged to master; better remove it."
+ exit 1 ;# we could allow it, but there is no point.
+fi
+
+# Is topic ever merged to next? If so you should not be rebasing it.
+only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
+only_next_2=`git rev-list ^master ${publish} | sort`
+if test "$only_next_1" = "$only_next_2"
+then
+ not_in_topic=`git rev-list "^$topic" master`
+ if test -z "$not_in_topic"
+ then
+ echo >&2 "$topic is already up-to-date with master"
+ exit 1 ;# we could allow it, but there is no point.
+ else
+ exit 0
+ fi
+else
+ not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
+ /usr/bin/perl -e '
+ my $topic = $ARGV[0];
+ my $msg = "* $topic has commits already merged to public branch:\n";
+ my (%not_in_next) = map {
+ /^([0-9a-f]+) /;
+ ($1 => 1);
+ } split(/\n/, $ARGV[1]);
+ for my $elem (map {
+ /^([0-9a-f]+) (.*)$/;
+ [$1 => $2];
+ } split(/\n/, $ARGV[2])) {
+ if (!exists $not_in_next{$elem->[0]}) {
+ if ($msg) {
+ print STDERR $msg;
+ undef $msg;
+ }
+ print STDERR " $elem->[1]\n";
+ }
+ }
+ ' "$topic" "$not_in_next" "$not_in_master"
+ exit 1
+fi
+
+exit 0
+
+################################################################
+
+This sample hook safeguards topic branches that have been
+published from being rewound.
+
+The workflow assumed here is:
+
+ * Once a topic branch forks from "master", "master" is never
+ merged into it again (either directly or indirectly).
+
+ * Once a topic branch is fully cooked and merged into "master",
+ it is deleted. If you need to build on top of it to correct
+ earlier mistakes, a new topic branch is created by forking at
+ the tip of the "master". This is not strictly necessary, but
+ it makes it easier to keep your history simple.
+
+ * Whenever you need to test or publish your changes to topic
+ branches, merge them into "next" branch.
+
+The script, being an example, hardcodes the publish branch name
+to be "next", but it is trivial to make it configurable via
+$GIT_DIR/config mechanism.
+
+With this workflow, you would want to know:
+
+(1) ... if a topic branch has ever been merged to "next". Young
+ topic branches can have stupid mistakes you would rather
+ clean up before publishing, and things that have not been
+ merged into other branches can be easily rebased without
+ affecting other people. But once it is published, you would
+ not want to rewind it.
+
+(2) ... if a topic branch has been fully merged to "master".
+ Then you can delete it. More importantly, you should not
+ build on top of it -- other people may already want to
+ change things related to the topic as patches against your
+ "master", so if you need further changes, it is better to
+ fork the topic (perhaps with the same name) afresh from the
+ tip of "master".
+
+Let's look at this example:
+
+ o---o---o---o---o---o---o---o---o---o "next"
+ / / / /
+ / a---a---b A / /
+ / / / /
+ / / c---c---c---c B /
+ / / / \ /
+ / / / b---b C \ /
+ / / / / \ /
+ ---o---o---o---o---o---o---o---o---o---o---o "master"
+
+
+A, B and C are topic branches.
+
+ * A has one fix since it was merged up to "next".
+
+ * B has finished. It has been fully merged up to "master" and "next",
+ and is ready to be deleted.
+
+ * C has not merged to "next" at all.
+
+We would want to allow C to be rebased, refuse A, and encourage
+B to be deleted.
+
+To compute (1):
+
+ git rev-list ^master ^topic next
+ git rev-list ^master next
+
+ if these match, topic has not merged in next at all.
+
+To compute (2):
+
+ git rev-list master..topic
+
+ if this is empty, it is fully merged to "master".
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/hooks/prepare-commit-msg.sample
^
|
@@ -0,0 +1,36 @@
+#!/bin/sh
+#
+# An example hook script to prepare the commit log message.
+# Called by "git commit" with the name of the file that has the
+# commit message, followed by the description of the commit
+# message's source. The hook's purpose is to edit the commit
+# message file. If the hook fails with a non-zero status,
+# the commit is aborted.
+#
+# To enable this hook, rename this file to "prepare-commit-msg".
+
+# This hook includes three examples. The first comments out the
+# "Conflicts:" part of a merge commit.
+#
+# The second includes the output of "git diff --name-status -r"
+# into the message, just before the "git status" output. It is
+# commented because it doesn't cope with --amend or with squashed
+# commits.
+#
+# The third example adds a Signed-off-by line to the message, that can
+# still be edited. This is rarely a good idea.
+
+case "$2,$3" in
+ merge,)
+ /usr/bin/perl -i.bak -ne 's/^/# /, s/^# #/#/ if /^Conflicts/ .. /#/; print' "$1" ;;
+
+# ,|template,)
+# /usr/bin/perl -i.bak -pe '
+# print "\n" . `git diff --cached --name-status -r`
+# if /^#/ && $first++ == 0' "$1" ;;
+
+ *) ;;
+esac
+
+# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
+# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/hooks/update.sample
^
|
@@ -0,0 +1,128 @@
+#!/bin/sh
+#
+# An example hook script to blocks unannotated tags from entering.
+# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
+#
+# To enable this hook, rename this file to "update".
+#
+# Config
+# ------
+# hooks.allowunannotated
+# This boolean sets whether unannotated tags will be allowed into the
+# repository. By default they won't be.
+# hooks.allowdeletetag
+# This boolean sets whether deleting tags will be allowed in the
+# repository. By default they won't be.
+# hooks.allowmodifytag
+# This boolean sets whether a tag may be modified after creation. By default
+# it won't be.
+# hooks.allowdeletebranch
+# This boolean sets whether deleting branches will be allowed in the
+# repository. By default they won't be.
+# hooks.denycreatebranch
+# This boolean sets whether remotely creating branches will be denied
+# in the repository. By default this is allowed.
+#
+
+# --- Command line
+refname="$1"
+oldrev="$2"
+newrev="$3"
+
+# --- Safety check
+if [ -z "$GIT_DIR" ]; then
+ echo "Don't run this script from the command line." >&2
+ echo " (if you want, you could supply GIT_DIR then run" >&2
+ echo " $0 <ref> <oldrev> <newrev>)" >&2
+ exit 1
+fi
+
+if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
+ echo "Usage: $0 <ref> <oldrev> <newrev>" >&2
+ exit 1
+fi
+
+# --- Config
+allowunannotated=$(git config --bool hooks.allowunannotated)
+allowdeletebranch=$(git config --bool hooks.allowdeletebranch)
+denycreatebranch=$(git config --bool hooks.denycreatebranch)
+allowdeletetag=$(git config --bool hooks.allowdeletetag)
+allowmodifytag=$(git config --bool hooks.allowmodifytag)
+
+# check for no description
+projectdesc=$(sed -e '1q' "$GIT_DIR/description")
+case "$projectdesc" in
+"Unnamed repository"* | "")
+ echo "*** Project description file hasn't been set" >&2
+ exit 1
+ ;;
+esac
+
+# --- Check types
+# if $newrev is 0000...0000, it's a commit to delete a ref.
+zero="0000000000000000000000000000000000000000"
+if [ "$newrev" = "$zero" ]; then
+ newrev_type=delete
+else
+ newrev_type=$(git cat-file -t $newrev)
+fi
+
+case "$refname","$newrev_type" in
+ refs/tags/*,commit)
+ # un-annotated tag
+ short_refname=${refname##refs/tags/}
+ if [ "$allowunannotated" != "true" ]; then
+ echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
+ echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
+ exit 1
+ fi
+ ;;
+ refs/tags/*,delete)
+ # delete tag
+ if [ "$allowdeletetag" != "true" ]; then
+ echo "*** Deleting a tag is not allowed in this repository" >&2
+ exit 1
+ fi
+ ;;
+ refs/tags/*,tag)
+ # annotated tag
+ if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
+ then
+ echo "*** Tag '$refname' already exists." >&2
+ echo "*** Modifying a tag is not allowed in this repository." >&2
+ exit 1
+ fi
+ ;;
+ refs/heads/*,commit)
+ # branch
+ if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
+ echo "*** Creating a branch is not allowed in this repository" >&2
+ exit 1
+ fi
+ ;;
+ refs/heads/*,delete)
+ # delete branch
+ if [ "$allowdeletebranch" != "true" ]; then
+ echo "*** Deleting a branch is not allowed in this repository" >&2
+ exit 1
+ fi
+ ;;
+ refs/remotes/*,commit)
+ # tracking branch
+ ;;
+ refs/remotes/*,delete)
+ # delete tracking branch
+ if [ "$allowdeletebranch" != "true" ]; then
+ echo "*** Deleting a tracking branch is not allowed in this repository" >&2
+ exit 1
+ fi
+ ;;
+ *)
+ # Anything else (is there anything else?)
+ echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
+ exit 1
+ ;;
+esac
+
+# --- Finished
+exit 0
|
|
Added |
sphinx-1.3.99.1.tgz/.git/index
^
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/info
^
|
+(directory)
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/info/exclude
^
|
@@ -0,0 +1,6 @@
+# git ls-files --others --exclude-from=.git/info/exclude
+# Lines that start with '#' are comments.
+# For a project mostly in C, the following would be a good set of
+# exclude patterns (uncomment them if you want to use them):
+# *.[oa]
+# *~
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/logs
^
|
+(directory)
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/logs/HEAD
^
|
@@ -0,0 +1 @@
+0000000000000000000000000000000000000000 9a3d08c67af0cad216aa0d38d39be71362667738 Local OBS User <obs@mgmt-desk.obs.j0ke.net> 1461308568 +0200 clone: from https://git.php.net/repository/pecl/search_engine/sphinx.git
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/logs/refs
^
|
+(directory)
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/logs/refs/heads
^
|
+(directory)
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/logs/refs/heads/php7
^
|
@@ -0,0 +1 @@
+0000000000000000000000000000000000000000 9a3d08c67af0cad216aa0d38d39be71362667738 Local OBS User <obs@mgmt-desk.obs.j0ke.net> 1461308568 +0200 clone: from https://git.php.net/repository/pecl/search_engine/sphinx.git
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/logs/refs/remotes
^
|
+(directory)
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/logs/refs/remotes/origin
^
|
+(directory)
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/logs/refs/remotes/origin/HEAD
^
|
@@ -0,0 +1 @@
+0000000000000000000000000000000000000000 7d9b13f64621bb0011743110b77e9f30c2f43b9b Local OBS User <obs@mgmt-desk.obs.j0ke.net> 1461308568 +0200 clone: from https://git.php.net/repository/pecl/search_engine/sphinx.git
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/objects
^
|
+(directory)
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/objects/info
^
|
+(directory)
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/objects/pack
^
|
+(directory)
|
|
Added |
sphinx-1.3.99.1.tgz/.git/objects/pack/pack-156141e462ea5d54d3ae9435f8efc82ad0ee5570.idx
^
|
|
Added |
sphinx-1.3.99.1.tgz/.git/objects/pack/pack-156141e462ea5d54d3ae9435f8efc82ad0ee5570.pack
^
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/packed-refs
^
|
@@ -0,0 +1,16 @@
+# pack-refs with: peeled
+7d9b13f64621bb0011743110b77e9f30c2f43b9b refs/remotes/origin/master
+9a3d08c67af0cad216aa0d38d39be71362667738 refs/remotes/origin/php7
+0a3df8dd793d4599487ffce2f3dc971e7ed8d917 refs/tags/RELEASE_0_1_0
+^3edc0ae37e1783da7ce766bf8341fad7ed92403b
+ef82e70ebab56ae8eaba1a943c4fa579458620df refs/tags/RELEASE_0_2_0
+^44dfdc1355ea1a3720f76e18e5c5215eb4e85e0f
+d215590113e406e07d432dc46ada12373fd852e3 refs/tags/RELEASE_1_0_0
+^34911f745b8e8f9bafb73e2f98f0d6315dfd09f0
+4cf83a9f4013306e7944a715460f1f1b038c04e7 refs/tags/RELEASE_1_0_3
+^320e62c30e405809e008cf3cb71e49dfc615f61e
+e044cf207038c972f7e0b7defc80d0a2eb96e379 refs/tags/RELEASE_1_0_4
+^190d6d1e5ab2a6ffc3b0414fd72b31b4e5bfa7ac
+54b3c387cbd24cb2ccb12a13fe4a2f70d72fff84 refs/tags/RELEASE_1_1_0
+^f24bbed1aff0d1bd6754c8b7eb9ed2b85ac79ca6
+2f40d68941ef245e0ee918e1a968be796128a666 refs/tags/RELEASE_1_3_3
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/refs
^
|
+(directory)
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/refs/heads
^
|
+(directory)
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/refs/heads/php7
^
|
@@ -0,0 +1 @@
+9a3d08c67af0cad216aa0d38d39be71362667738
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/refs/remotes
^
|
+(directory)
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/refs/remotes/origin
^
|
+(directory)
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/refs/remotes/origin/HEAD
^
|
@@ -0,0 +1 @@
+ref: refs/remotes/origin/master
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/.git/refs/tags
^
|
+(directory)
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/CREDITS
^
|
@@ -0,0 +1,3 @@
+Sphinx client extension for PHP
+Antony Dovgal (tony2001)
+Alexey Romanenko (santiago)
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/LICENSE
^
|
@@ -0,0 +1,68 @@
+--------------------------------------------------------------------
+ The PHP License, version 3.01
+Copyright (c) 1999 - 2010 The PHP Group. All rights reserved.
+--------------------------------------------------------------------
+
+Redistribution and use in source and binary forms, with or without
+modification, is permitted provided that the following conditions
+are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ 3. The name "PHP" must not be used to endorse or promote products
+ derived from this software without prior written permission. For
+ written permission, please contact group@php.net.
+
+ 4. Products derived from this software may not be called "PHP", nor
+ may "PHP" appear in their name, without prior written permission
+ from group@php.net. You may indicate that your software works in
+ conjunction with PHP by saying "Foo for PHP" instead of calling
+ it "PHP Foo" or "phpfoo"
+
+ 5. The PHP Group may publish revised and/or new versions of the
+ license from time to time. Each version will be given a
+ distinguishing version number.
+ Once covered code has been published under a particular version
+ of the license, you may always continue to use it under the terms
+ of that version. You may also choose to use such covered code
+ under the terms of any subsequent version of the license
+ published by the PHP Group. No one other than the PHP Group has
+ the right to modify the terms applicable to covered code created
+ under this License.
+
+ 6. Redistributions of any form whatsoever must retain the following
+ acknowledgment:
+ "This product includes PHP software, freely available from
+ <http://www.php.net/software/>".
+
+THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND
+ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP
+DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+OF THE POSSIBILITY OF SUCH DAMAGE.
+
+--------------------------------------------------------------------
+
+This software consists of voluntary contributions made by many
+individuals on behalf of the PHP Group.
+
+The PHP Group can be contacted via Email at group@php.net.
+
+For more information on the PHP Group and the PHP project,
+please see <http://www.php.net>.
+
+PHP includes the Zend Engine, freely available at
+<http://www.zend.com>.
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/config.m4
^
|
@@ -0,0 +1,114 @@
+dnl $Id$
+
+AC_DEFUN([SPHINX_CHECK_ENUM], [
+ AC_MSG_CHECKING([for $1 in sphinxclient.h])
+ AC_TRY_COMPILE([#include <sphinxclient.h>], [int i = $1],
+ [
+ AC_DEFINE([HAVE_]$1, [], [Define if $1 is available])
+ AC_MSG_RESULT([found])
+ ], [
+ AC_MSG_RESULT([not found])
+ ])
+])
+
+PHP_ARG_WITH(sphinx, for sphinx support,
+[ --with-sphinx Include sphinx support])
+
+if test "$PHP_SPHINX" != "no"; then
+
+ SEARCH_PATH="/usr/local /usr /local /opt"
+ SEARCH_FOR="/include/sphinxclient.h"
+
+ if test "$PHP_SPHINX" = "yes"; then
+ AC_MSG_CHECKING([for libsphinxclient headers in default path])
+ for i in $SEARCH_PATH ; do
+ if test -r $i/$SEARCH_FOR; then
+ SPHINX_DIR=$i
+ AC_MSG_RESULT(found in $i)
+ fi
+ done
+ else
+ AC_MSG_CHECKING([for libsphinxclient headers in $PHP_SPHINX])
+ if test -r $PHP_SPHINX/$SEARCH_FOR; then
+ SPHINX_DIR=$PHP_SPHINX
+ AC_MSG_RESULT([found])
+ fi
+ fi
+
+ if test -z "$SPHINX_DIR"; then
+ AC_MSG_RESULT([not found])
+ AC_MSG_ERROR([Cannot find libsphinxclient headers])
+ fi
+
+ PHP_ADD_INCLUDE($SPHINX_DIR/include)
+
+ LIBNAME=sphinxclient
+ LIBSYMBOL=sphinx_create
+
+ PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL,
+ [
+ PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $SPHINX_DIR/$PHP_LIBDIR, SPHINX_SHARED_LIBADD)
+ AC_DEFINE(HAVE_SPHINXLIB,1,[ ])
+ ],[
+ AC_MSG_ERROR([wrong libsphinxclient version or lib not found])
+ ],[
+ -L$SPHINX_DIR/$PHP_LIBDIR -lm
+ ])
+
+ PHP_CHECK_LIBRARY($LIBNAME,sphinx_get_string,
+ [
+ PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $SPHINX_DIR/$PHP_LIBDIR, SPHINX_SHARED_LIBADD)
+ AC_DEFINE(LIBSPHINX_VERSION_ID,110,[ ])
+ LIBSPHINX_VERSION_ID="110"
+ ],[],[
+ -L$SPHINX_DIR/$PHP_LIBDIR -lm
+ ])
+
+ if test "x$LIBSPHINX_VERSION_ID" = "x"; then
+ PHP_CHECK_LIBRARY($LIBNAME,sphinx_set_select,
+ [
+ PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $SPHINX_DIR/$PHP_LIBDIR, SPHINX_SHARED_LIBADD)
+ AC_DEFINE(LIBSPHINX_VERSION_ID,99,[ ])
+ LIBSPHINX_VERSION_ID="99"
+ ],[],[
+ -L$SPHINX_DIR/$PHP_LIBDIR -lm
+ ])
+ fi
+
+ if test "x$LIBSPHINX_VERSION_ID" = "x"; then
+ AC_DEFINE(LIBSPHINX_VERSION_ID,98,[ ])
+ fi
+
+ PHP_CHECK_LIBRARY($LIBNAME,sphinx_add_filter_string,
+ [
+ AC_DEFINE(HAVE_SPHINX_ADD_FILTER_STRING,1,[ ])
+ ],[],[
+ -L$SPHINX_DIR/$PHP_LIBDIR -lm
+ ])
+
+ _SAVE_CFLAGS=$CFLAGS
+ CFLAGS="$CFLAGS -I$SPHINX_DIR/include"
+ AC_CACHE_CHECK([for new sphinx_set_ranking_mode() signature], ac_cv_3arg_setrankingmode,
+ [AC_TRY_COMPILE([#include <sphinxclient.h>], [sphinx_set_ranking_mode(0, 0, 0)],
+ ac_cv_3arg_setrankingmode=yes, ac_cv_3arg_setrankingmode=no)])
+ if test "$ac_cv_3arg_setrankingmode" = yes; then
+ AC_DEFINE(HAVE_3ARG_SPHINX_SET_RANKING_MODE,1,[Whether we have 3 arg sphinx_set_ranking_mode()])
+ fi
+ CFLAGS=$_SAVE_CFLAGS
+
+ _SAVE_CPPFLAGS=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS -I$SPHINX_DIR/include"
+
+ SPHINX_CHECK_ENUM(SPH_RANK_PROXIMITY)
+ SPHINX_CHECK_ENUM(SPH_RANK_MATCHANY)
+ SPHINX_CHECK_ENUM(SPH_RANK_FIELDMASK)
+ SPHINX_CHECK_ENUM(SPH_RANK_SPH04)
+ SPHINX_CHECK_ENUM(SPH_RANK_EXPR)
+ SPHINX_CHECK_ENUM(SPH_RANK_TOTAL)
+
+ CPPFLAGS=$_SAVE_CPPFLAGS
+
+ PHP_SUBST(SPHINX_SHARED_LIBADD)
+
+ PHP_NEW_EXTENSION(sphinx, sphinx.c, $ext_shared)
+fi
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/config.w32
^
|
@@ -0,0 +1,15 @@
+// $Id$
+// vim:ft=javascript
+
+ARG_WITH("sphinx", "for sphinx support", "yes");
+
+if (PHP_SPHINX == "yes") {
+ if (CHECK_LIB("libsphinxclient.lib", "sphinx") &&
+ CHECK_HEADER_ADD_INCLUDE("sphinxclient.h", "CFLAGS_SPHINX")) {
+
+ ADD_FLAG("CFLAGS_SPHINX", "/D HAVE_3ARG_SPHINX_SET_RANKING_MODE=1");
+
+ EXTENSION("sphinx", "sphinx.c");
+ }
+}
+
|
[-]
[+]
|
Changed |
sphinx-1.3.99.1.tgz/package.xml
^
|
@@ -1,43 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
-<package packagerversion="1.7.2" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
+<package packagerversion="1.4.11" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0
+http://pear.php.net/dtd/tasks-1.0.xsd
+http://pear.php.net/dtd/package-2.0
+http://pear.php.net/dtd/package-2.0.xsd">
<name>sphinx</name>
<channel>pecl.php.net</channel>
<summary>Client extension for Sphinx - opensource SQL full-text search engine</summary>
- <description>This extension provides bindings for libsphinxclient, client library for Sphinx.</description>
+ <description>
+ This extension provides bindings for libsphinxclient, client library for Sphinx.
+ </description>
<lead>
<name>Antony Dovgal</name>
<user>tony2001</user>
<email>tony2001@php.net</email>
<active>yes</active>
</lead>
- <date>2009-01-29</date>
- <time>11:29:53</time>
+ <lead>
+ <name>Alexey Romanenko</name>
+ <user>santiago</user>
+ <email>santiago739@gmail.com</email>
+ <active>yes</active>
+ </lead>
+ <date>2014-07-06</date>
+ <time>19:00:00</time>
<version>
- <release>1.0.0</release>
- <api>1.0.0</api>
+ <release>1.3.3</release>
+ <api>1.3.3</api>
</version>
<stability>
<release>stable</release>
<api>stable</api>
</stability>
<license uri="http://www.php.net/license">PHP</license>
- <notes>- Added __sleep() and __wakeup() methods to prevent (un)serialization of SphinxClient instances.
-- Fixed PECL bug #15033 (segfaults on SPARC because of unaligned read).
-- Fixed PECL bug #14930 (configure fails on freebsd). (patch by nobleclem at fatalexception dot us)
-- Fixed PECL bug #14752 (32-bit Client does not work with 64-bit ids). (nobleclem at fatalexception dot us, Tony)</notes>
+ <notes>- Added setFilterString() method, available only when built with sphinxclient lib >= 2.2.3.
+- Fixed bug #67669 (SphinxClient::escapeString() is missing several symbols)
+ </notes>
<contents>
<dir name="/">
- <file md5sum="c664402670bd53a2ba39a1182f51259e" name="CREDITS" role="doc" />
- <file md5sum="2b6e68a834b9f76c2f0ebcd4d8f9ee71" name="config.m4" role="src" />
- <file md5sum="852a029f23080aa870633ce61e0fbe8e" name="config.w32" role="src" />
- <file md5sum="0b54a1196e704e90873ecabcdb73de67" name="sphinx.c" role="src" />
- <file md5sum="0427ae5fefdf1f2c007fbcec38d9900c" name="php_sphinx.h" role="src" />
- </dir>
+ <file name="CREDITS" role="doc" />
+ <file name="LICENSE" role="doc" />
+ <file name="config.m4" role="src" />
+ <file name="config.w32" role="src" />
+ <file name="sphinx.c" role="src" />
+ <file name="php_sphinx.h" role="src" />
+ </dir> <!-- / -->
</contents>
<dependencies>
<required>
<php>
- <min>5.1.3</min>
+ <min>5.2.2</min>
<max>6.0.0</max>
<exclude>6.0.0</exclude>
</php>
@@ -52,30 +63,99 @@
</extsrcrelease>
<changelog>
<release>
- <stability>
- <release>beta</release>
- <api>beta</api>
- </stability>
- <version>
- <release>0.2.0</release>
- <api>0.2.0</api>
- </version>
+ <stability><release>stable</release><api>stable</api></stability>
+ <version><release>1.3.2</release><api>1.3.2</api></version>
+ <date>2014-05-06</date>
+ <notes>- Fixed build with older libsphinxclient versions (Dmitry Saprykin)
+- Added LICENSE to the package.
+ </notes>
+ </release>
+ <release>
+ <stability><release>stable</release><api>stable</api></stability>
+ <version><release>1.3.1</release><api>1.3.1</api></version>
+ <date>2014-05-06</date>
+ <notes>- Fixed bug #67216 (segfault on setGroupBy()) (Dmitry Saprykin)
+- Fixed bug #66272 (Some constants are not defined)
+ </notes>
+ </release>
+ <release>
+ <stability><release>stable</release><api>stable</api></stability>
+ <version><release>1.3.0</release><api>1.3.0</api></version>
+ <date>2013-04-04</date>
+ <notes>- Fixed setRankingMode's proto and add new ranking mode constants (patch by Michael Squires)
+- Fixed segfault when reading object properties.
+- Fixed bug #62026 (Second param in setRankingMode should be optional)
+ </notes>
+ </release>
+ <release>
+ <stability><release>stable</release><api>stable</api></stability>
+ <version><release>1.2.0</release><api>1.2.0</api></version>
+ <date>2012-04-03</date>
+ <notes>- Added mva support to updateAttributes().
+- Fixed build with 5_4.
+- Fixed bug #61392 (build failure with new version of libsphinxclient)
+ </notes>
+ </release>
+ <release>
+ <stability><release>stable</release><api>stable</api></stability>
+ <version><release>1.1.0</release><api>1.1.0</api></version>
+ <date>2010-09-17</date>
+ <notes>- Added support for new API in sphinx 1.10
+ - Fixed PECL bug #18325 (support 1.10-beta string attributes)
+ - Fixed PECL bug #17558 (time taken in search result was incorrect)
+ </notes>
+ </release>
+ <release>
+ <stability><release>stable</release><api>stable</api></stability>
+ <version><release>1.0.4</release><api>1.0.4</api></version>
+ <date>2010-02-26</date>
+ <notes>- Fixed PECL bug #17007 (incorrect query causes SEGFAULT)</notes>
+ </release>
+ <release>
+ <stability><release>stable</release><api>stable</api></stability>
+ <version><release>1.0.3</release><api>1.0.3</api></version>
+ <date>2010-01-12</date>
+ <notes>- Added support for open(), close(), status() and setOverride() available in sphinx 0.9.9 new API</notes>
+ </release>
+ <release>
+ <stability><release>stable</release><api>stable</api></stability>
+ <version><release>1.0.2</release><api>1.0.2</api></version>
+ <date>2009-12-03</date>
+ <notes>- Fixed crash when extending class doesn't call parent constructor.</notes>
+ </release>
+ <release>
+ <stability><release>stable</release><api>stable</api></stability>
+ <version><release>1.0.1</release><api>1.0.1</api></version>
+ <date>2009-11-03</date>
+ <notes>- Fixed build failure with PHP 5.1.x.
+- Added support for setSelect(), available in sphinx 0.9.9 new API (patch by Olivier Poitrey)
+ </notes>
+ </release>
+ <release>
+ <stability><release>stable</release><api>stable</api></stability>
+ <version><release>1.0.0</release><api>1.0.0</api></version>
+ <date>2009-01-29</date>
+ <notes>- Added __sleep() and __wakeup() methods to prevent (un)serialization of SphinxClient instances.
+- Fixed PECL bug #15033 (segfaults on SPARC because of unaligned read).
+- Fixed PECL bug #14930 (configure fails on freebsd). (patch by nobleclem at fatalexception dot us)
+- Fixed PECL bug #14752 (32-bit Client does not work with 64-bit ids). (nobleclem at fatalexception dot us, Tony)
+ </notes>
+ </release>
+ <release>
+ <stability><release>beta</release><api>beta</api></stability>
+ <version><release>0.2.0</release><api>0.2.0</api></version>
<date>2008-07-31</date>
<notes>- Updated SphinxClient::updateAttributes() to return number of updated attributes on success.
- Updated SphinxClient::setIDRange() to accept integers, not floats.
-- Updated SphinxClient::addQuery() to return integer on success.</notes>
+- Updated SphinxClient::addQuery() to return integer on success.
+ </notes>
</release>
<release>
- <stability>
- <release>beta</release>
- <api>beta</api>
- </stability>
- <version>
- <release>0.1.0</release>
- <api>0.1.0</api>
- </version>
+ <stability><release>beta</release><api>beta</api></stability>
+ <version><release>0.1.0</release><api>0.1.0</api></version>
<date>2008-07-21</date>
- <notes>- Initial PECL release.</notes>
+ <notes>- Initial PECL release.
+ </notes>
</release>
</changelog>
</package>
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/php_sphinx.h
^
|
@@ -0,0 +1,46 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2008 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Antony Dovgal <tony at daylessday.org> |
+ | Based on Sphinx PHP API by Andrew Aksyonoff <shodan at shodan.ru> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifndef PHP_SPHINX_H
+#define PHP_SPHINX_H
+
+extern zend_module_entry sphinx_module_entry;
+#define phpext_sphinx_ptr &sphinx_module_entry
+
+#ifdef ZTS
+#include "TSRM.h"
+#endif
+
+PHP_MINIT_FUNCTION(sphinx);
+PHP_MINFO_FUNCTION(sphinx);
+
+#define PHP_SPHINX_VERSION "1.4.0-dev"
+
+#endif /* PHP_SPHINX_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/sphinx.c
^
|
@@ -0,0 +1,2035 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 5 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2008 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Antony Dovgal <tony at daylessday.org> |
+ | Based on Sphinx PHP API by Andrew Aksyonoff <shodan at shodan.ru> |
+ +----------------------------------------------------------------------+
+*/
+
+/* $Id$ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "php.h"
+#include "php_ini.h"
+#include "ext/standard/info.h"
+#include "ext/standard/file.h"
+#include "zend_operators.h"
+#include "php_sphinx.h"
+
+#include <sphinxclient.h>
+
+static zend_class_entry *ce_sphinx_client;
+
+static zend_object_handlers php_sphinx_client_handlers;
+static zend_object_handlers cannot_be_cloned;
+
+typedef struct _php_sphinx_client {
+ sphinx_client *sphinx;
+ zend_bool array_result;
+ zend_object std;
+} php_sphinx_client;
+
+#ifdef COMPILE_DL_SPHINX
+ZEND_GET_MODULE(sphinx)
+#endif
+
+#ifndef E_RECOVERABLE_ERROR
+#define E_RECOVERABLE_ERROR E_WARNING
+#endif
+
+#define SPHINX_CONST(name) REGISTER_LONG_CONSTANT(#name, name, CONST_CS | CONST_PERSISTENT)
+
+#define SPHINX_INITIALIZED(c) \
+ if (!(c) || !(c)->sphinx) { \
+ php_error_docref(NULL, E_WARNING, "using uninitialized SphinxClient object"); \
+ RETURN_FALSE; \
+ }
+
+static inline php_sphinx_client *php_sphinx_client_object(zend_object *obj) {
+ return (php_sphinx_client *)((char*)(obj) - XtOffsetOf(php_sphinx_client, std));
+}
+
+#define sphinx_client(zv) php_sphinx_client_object(Z_OBJ_P(zv))
+
+static void php_sphinx_client_obj_dtor(zend_object *object) /* {{{ */
+{
+ php_sphinx_client *c = php_sphinx_client_object(object);
+
+ sphinx_destroy(c->sphinx);
+ zend_object_std_dtor(&c->std);
+}
+/* }}} */
+
+static zend_object *php_sphinx_client_new(zend_class_entry *ce) /* {{{ */
+{
+ php_sphinx_client *c;
+
+ c = ecalloc(1, sizeof(*c) + zend_object_properties_size(ce));
+ zend_object_std_init(&c->std, ce);
+ object_properties_init(&c->std, ce);
+ c->std.handlers = &php_sphinx_client_handlers;
+ return &c->std;
+}
+/* }}} */
+
+static zval *php_sphinx_client_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv) /* {{{ */
+{
+ //php_sphinx_client *c;
+ zval tmp_member;
+ zval *retval;
+ zend_object_handlers *std_hnd;
+
+ //c = sphinx_client(object);
+
+ if (Z_TYPE_P(member) != IS_STRING) {
+ tmp_member = *member;
+ zval_copy_ctor(&tmp_member);
+ convert_to_string(&tmp_member);
+ member = &tmp_member;
+ }
+
+ /* XXX we can either create retval ourselves (for custom properties) or use standard handlers */
+
+ std_hnd = zend_get_std_object_handlers();
+ retval = std_hnd->read_property(object, member, type, cache_slot, rv);
+
+ if (member == &tmp_member) {
+ zval_dtor(member);
+ }
+ return retval;
+}
+/* }}} */
+
+static HashTable *php_sphinx_client_get_properties(zval *object) /* {{{ */
+{
+ php_sphinx_client *c;
+ const char *warning, *error;
+ zval tmp;
+ HashTable *props;
+
+ c = sphinx_client(object);
+ props = zend_std_get_properties(object);
+
+ error = sphinx_error(c->sphinx);
+ ZVAL_STRING(&tmp, (char *)error);
+ zend_hash_str_update(props, "error", strlen("error"), &tmp);
+
+ warning = sphinx_warning(c->sphinx);
+ ZVAL_STRING(&tmp, (char *)warning);
+ zend_hash_str_update(props, "warning", strlen("warning"), &tmp);
+ return c->std.properties;
+}
+/* }}} */
+
+static void php_sphinx_result_to_array(php_sphinx_client *c, sphinx_result *result, zval *array) /* {{{ */
+{
+ zval tmp;
+ int i, j;
+
+ array_init(array);
+
+ /* error */
+ if (!result->error) {
+ add_assoc_string(array, "error", "");
+ } else {
+ add_assoc_string(array, "error", (char *)(result->error));
+ }
+
+ /* warning */
+ if (!result->warning) {
+ add_assoc_string(array, "warning", "");
+ } else {
+ add_assoc_string(array, "warning", (char *)result->warning);
+ }
+
+ /* status */
+ add_assoc_long(array, "status", result->status);
+
+ switch(result->status) {
+ case SEARCHD_OK:
+ /* ok, continue reading data */
+ break;
+ case SEARCHD_WARNING:
+ /* this seems to be safe, too */
+ break;
+ default:
+ /* libsphinxclient doesn't nullify the data
+ in case of error, so it's not safe to continue. */
+ return;
+ }
+
+ /* fields */
+ array_init(&tmp);
+
+ for (i = 0; i < result->num_fields; i++) {
+ add_next_index_string(&tmp, result->fields[i]);
+ }
+ add_assoc_zval(array, "fields", &tmp);
+
+ /* attrs */
+ array_init(&tmp);
+
+ for (i = 0; i < result->num_attrs; i++) {
+#if SIZEOF_LONG == 8
+ add_assoc_long(&tmp, result->attr_names[i], result->attr_types[i]);
+#else
+ double float_value;
+ char buf[128];
+
+ float_value = (double)result->attr_types[i];
+ slprintf(buf, sizeof(buf), "%.0f", float_value);
+ add_assoc_string(&tmp, result->attr_names[i], buf);
+#endif
+ }
+ add_assoc_zval(array, "attrs", &tmp);
+
+ /* matches */
+ if (result->num_matches) {
+ array_init(&tmp);
+
+ for (i = 0; i < result->num_matches; i++) {
+ zval tmp_element, sub_element;
+
+ array_init(&tmp_element);
+
+ if (c->array_result) {
+ /* id */
+#if SIZEOF_LONG == 8
+ add_assoc_long(&tmp_element, "id", sphinx_get_id(result, i));
+#else
+ double float_id;
+ char buf[128];
+
+ float_id = (double)sphinx_get_id(result, i);
+ slprintf(buf, sizeof(buf), "%.0f", float_id);
+ add_assoc_string(&tmp_element, "id", buf);
+#endif
+ }
+
+ /* weight */
+ add_assoc_long(&tmp_element, "weight", sphinx_get_weight(result, i));
+
+ /* attrs */
+ array_init(&sub_element);
+
+ for (j = 0; j < result->num_attrs; j++) {
+ zval sub_sub_element;
+#if SIZEOF_LONG != 8
+ double float_value;
+ char buf[128];
+#endif
+
+ switch(result->attr_types[j]) {
+ case SPH_ATTR_MULTI | SPH_ATTR_INTEGER:
+ {
+ int k;
+ unsigned int *mva = sphinx_get_mva(result, i, j);
+ unsigned int tmp, num;
+
+ array_init(&sub_sub_element);
+
+ if (!mva) {
+ break;
+ }
+
+ memcpy(&num, mva, sizeof(unsigned int));
+
+ for (k = 1; k <= num; k++) {
+ mva++;
+ memcpy(&tmp, mva, sizeof(unsigned int));
+#if SIZEOF_LONG == 8
+ add_next_index_long(&sub_sub_element, tmp);
+#else
+ float_value = (double)tmp;
+ slprintf(buf, sizeof(buf), "%.0f", float_value);
+ add_next_index_string(&sub_sub_element, buf);
+#endif
+ }
+ } break;
+
+ case SPH_ATTR_FLOAT:
+ ZVAL_DOUBLE(&sub_sub_element, sphinx_get_float(result, i, j));
+ break;
+#if LIBSPHINX_VERSION_ID >= 110
+ case SPH_ATTR_STRING:
+ ZVAL_STRING(&sub_sub_element, sphinx_get_string(result, i, j));
+ break;
+#endif
+ default:
+#if SIZEOF_LONG == 8
+ ZVAL_LONG(&sub_sub_element, sphinx_get_int(result, i, j));
+#else
+ float_value = (double)sphinx_get_int(result, i, j);
+ slprintf(buf, sizeof(buf), "%.0f", float_value);
+ ZVAL_STRING(&sub_sub_element, buf);
+#endif
+ break;
+ }
+
+ add_assoc_zval(&sub_element, result->attr_names[j], &sub_sub_element);
+ }
+
+ add_assoc_zval(&tmp_element, "attrs", &sub_element);
+
+ if (c->array_result) {
+ add_next_index_zval(&tmp, &tmp_element);
+ } else {
+#if SIZEOF_LONG == 8
+ add_index_zval(&tmp, sphinx_get_id(result, i), &tmp_element);
+#else
+ char buf[128];
+ double float_id;
+ int buf_len;
+
+ float_id = (double)sphinx_get_id(result, i);
+ buf_len = slprintf(buf, sizeof(buf), "%.0f", float_id);
+ add_assoc_zval(tmp, buf, &tmp_element);
+#endif
+ }
+ }
+
+ add_assoc_zval(array, "matches", &tmp);
+ }
+
+ /* total */
+ add_assoc_long(array, "total", result->total);
+
+ /* total_found */
+ add_assoc_long(array, "total_found", result->total_found);
+
+ /* time */
+ add_assoc_double(array, "time", (double)result->time_msec/1000.0);
+
+ /* words */
+ if (result->num_words) {
+ zval tmp;
+
+ array_init(&tmp);
+ for (i = 0; i < result->num_words; i++) {
+ zval sub_element;
+
+ array_init(&sub_element);
+
+ add_assoc_long(&sub_element, "docs", result->words[i].docs);
+ add_assoc_long(&sub_element, "hits", result->words[i].hits);
+ add_assoc_zval(&tmp, (char *)result->words[i].word, &sub_element);
+ }
+ add_assoc_zval(array, "words", &tmp);
+ }
+}
+/* }}} */
+
+
+/* {{{ proto void SphinxClient::__construct() */
+static PHP_METHOD(SphinxClient, __construct)
+{
+ php_sphinx_client *c;
+
+ c = sphinx_client(getThis());
+
+ if (c->sphinx) {
+ /* called __construct() twice, bail out */
+ return;
+ }
+
+ c->sphinx = sphinx_create(1 /* copy string args */);
+
+ sphinx_set_connect_timeout(c->sphinx, FG(default_socket_timeout));
+}
+/* }}} */
+
+/* {{{ proto bool SphinxClient::setServer(string server, int port) */
+static PHP_METHOD(SphinxClient, setServer)
+{
+ php_sphinx_client *c;
+ zend_long port;
+ char *server;
+ int res;
+ size_t server_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl", &server, &server_len, &port) == FAILURE) {
+ return;
+ }
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ res = sphinx_set_server(c->sphinx, server, (int)port);
+ if (!res) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool SphinxClient::setLimits(int offset, int limit[, int max_matches[, int cutoff]]) */
+static PHP_METHOD(SphinxClient, setLimits)
+{
+ php_sphinx_client *c;
+ zend_long offset, limit, max_matches = 1000, cutoff = 0;
+ int res;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll|ll", &offset, &limit, &max_matches, &cutoff) == FAILURE) {
+ return;
+ }
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ res = sphinx_set_limits(c->sphinx, (int)offset, (int)limit, (int)max_matches, (int)cutoff);
+ if (!res) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool SphinxClient::setMatchMode(int mode) */
+static PHP_METHOD(SphinxClient, setMatchMode)
+{
+ php_sphinx_client *c;
+ zend_long mode;
+ int res;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &mode) == FAILURE) {
+ return;
+ }
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ res = sphinx_set_match_mode(c->sphinx, mode);
+ if (!res) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool SphinxClient::setIndexWeights(array weights) */
+static PHP_METHOD(SphinxClient, setIndexWeights)
+{
+ php_sphinx_client *c;
+ zval *weights, *item;
+ int num_weights, res = 0, i;
+ int *index_weights;
+ char **index_names;
+ zend_string *string_key;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &weights) == FAILURE) {
+ return;
+ }
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ num_weights = zend_hash_num_elements(Z_ARRVAL_P(weights));
+ if (!num_weights) {
+ /* check for empty array and return false right away */
+ RETURN_FALSE;
+ }
+
+ index_names = safe_emalloc(num_weights, sizeof(char *), 0);
+ index_weights = safe_emalloc(num_weights, sizeof(int), 0);
+
+ /* reset num_weights, we'll reuse it count _real_ number of entries */
+ num_weights = 0;
+
+ ZEND_HASH_FOREACH_STR_KEY_VAL_IND(Z_ARRVAL_P(weights), string_key, item) {
+ if (!string_key) {
+ /* if the key is not string.. well.. you're screwed */
+ break;
+ }
+
+ index_names[num_weights] = estrndup(string_key->val, string_key->len);
+ index_weights[num_weights] = zval_get_long(item);
+
+ num_weights++;
+ } ZEND_HASH_FOREACH_END();
+
+ if (num_weights) {
+ res = sphinx_set_index_weights(c->sphinx, num_weights, (const char **)index_names, index_weights);
+ }
+
+ for (i = 0; i != num_weights; i++) {
+ efree(index_names[i]);
+ }
+ efree(index_names);
+ efree(index_weights);
+
+ if (!res) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+#if LIBSPHINX_VERSION_ID >= 99
+/* {{{ proto bool SphinxClient::setSelect(string clause) */
+static PHP_METHOD(SphinxClient, setSelect)
+{
+ php_sphinx_client *c;
+ char *clause;
+ int res;
+ size_t clause_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &clause, &clause_len) == FAILURE) {
+ return;
+ }
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ res = sphinx_set_select(c->sphinx, clause);
+ if (!res) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+#endif
+
+/* {{{ proto bool SphinxClient::setIDRange(int min, int max) */
+static PHP_METHOD(SphinxClient, setIDRange)
+{
+ php_sphinx_client *c;
+ zend_long min, max;
+ int res;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "ll", &min, &max) == FAILURE) {
+ return;
+ }
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ res = sphinx_set_id_range(c->sphinx, (sphinx_uint64_t)min, (sphinx_uint64_t)max);
+ if (!res) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool SphinxClient::setFilter(string attribute, array values[, bool exclude]) */
+static PHP_METHOD(SphinxClient, setFilter)
+{
+ php_sphinx_client *c;
+ zval *values, *item;
+ char *attribute;
+ int num_values, i = 0, res;
+ zend_bool exclude = 0;
+ sphinx_int64_t *u_values;
+ size_t attribute_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "sa|b", &attribute, &attribute_len, &values, &exclude) == FAILURE) {
+ return;
+ }
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ num_values = zend_hash_num_elements(Z_ARRVAL_P(values));
+ if (!num_values) {
+ RETURN_FALSE;
+ }
+
+ u_values = safe_emalloc(num_values, sizeof(sphinx_int64_t), 0);
+
+ ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL_P(values), item) {
+ u_values[i] = (sphinx_int64_t)zval_get_double(item);
+ i++;
+ } ZEND_HASH_FOREACH_END();
+
+ res = sphinx_add_filter(c->sphinx, attribute, num_values, u_values, exclude ? 1 : 0);
+ efree(u_values);
+
+ if (!res) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+#ifdef HAVE_SPHINX_ADD_FILTER_STRING
+/* {{{ proto bool SphinxClient::setFilterString(string attribute, string value[, bool exclude]) */
+static PHP_METHOD(SphinxClient, setFilterString)
+{
+ php_sphinx_client *c;
+ char *attribute, *value;
+ int res;
+ zend_bool exclude = 0;
+ size_t attribute_len, value_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|b", &attribute, &attribute_len, &value, &value_len, &exclude) == FAILURE) {
+ return;
+ }
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ res = sphinx_add_filter_string(c->sphinx, attribute, value, exclude ? 1 : 0);
+ if (!res) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+#endif
+
+/* {{{ proto bool SphinxClient::setFilterRange(string attribute, int min, int max[, bool exclude]) */
+static PHP_METHOD(SphinxClient, setFilterRange)
+{
+ php_sphinx_client *c;
+ char *attribute;
+ int res;
+ zend_long min, max;
+ zend_bool exclude = 0;
+ size_t attribute_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "sll|b", &attribute, &attribute_len, &min, &max, &exclude ) == FAILURE) {
+ return;
+ }
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ res = sphinx_add_filter_range(c->sphinx, attribute, min, max, exclude);
+
+ if (!res) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool SphinxClient::setFilterFloatRange(string attribute, float min, float max[, bool exclude]) */
+static PHP_METHOD(SphinxClient, setFilterFloatRange)
+{
+ php_sphinx_client *c;
+ char *attribute;
+ int res;
+ double min, max;
+ zend_bool exclude = 0;
+ size_t attribute_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "sdd|b", &attribute, &attribute_len, &min, &max, &exclude) == FAILURE) {
+ return;
+ }
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ res = sphinx_add_filter_float_range(c->sphinx, attribute, min, max, exclude);
+
+ if (!res) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool SphinxClient::setGeoAnchor(string attrlat, string attrlong, float latitude, float longitude) */
+static PHP_METHOD(SphinxClient, setGeoAnchor)
+{
+ php_sphinx_client *c;
+ char *attrlat, *attrlong;
+ int res;
+ double latitude, longitude;
+ size_t attrlat_len, attrlong_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssdd", &attrlat, &attrlat_len, &attrlong, &attrlong_len, &latitude, &longitude) == FAILURE) {
+ return;
+ }
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ res = sphinx_set_geoanchor(c->sphinx, attrlat, attrlong, latitude, longitude);
+
+ if (!res) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool SphinxClient::setGroupBy(string attribute, int func[, string groupsort]) */
+static PHP_METHOD(SphinxClient, setGroupBy)
+{
+ php_sphinx_client *c;
+ char *attribute, *groupsort = NULL;
+ int res;
+ zend_long func;
+ size_t attribute_len, groupsort_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "sl|s", &attribute, &attribute_len, &func, &groupsort, &groupsort_len) == FAILURE) {
+ return;
+ }
+
+ if (groupsort == NULL) {
+ groupsort = "@group desc";
+ }
+
+ if (func < SPH_GROUPBY_DAY || func > SPH_GROUPBY_ATTRPAIR) {
+ php_error_docref(NULL, E_WARNING, "invalid group func specified (%ld)", func);
+ RETURN_FALSE;
+ }
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ res = sphinx_set_groupby(c->sphinx, attribute, func, groupsort);
+
+ if (!res) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool SphinxClient::setGroupDistinct(string attribute) */
+static PHP_METHOD(SphinxClient, setGroupDistinct)
+{
+ php_sphinx_client *c;
+ char *attribute;
+ int res;
+ size_t attribute_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &attribute, &attribute_len) == FAILURE) {
+ return;
+ }
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ res = sphinx_set_groupby_distinct(c->sphinx, attribute);
+
+ if (!res) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool SphinxClient::setRetries(int count[, int delay]) */
+static PHP_METHOD(SphinxClient, setRetries)
+{
+ php_sphinx_client *c;
+ zend_long count, delay = 0;
+ int res;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l", &count, &delay) == FAILURE) {
+ return;
+ }
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ res = sphinx_set_retries(c->sphinx, (int)count, (int)delay);
+
+ if (!res) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool SphinxClient::setMaxQueryTime(int qtime) */
+static PHP_METHOD(SphinxClient, setMaxQueryTime)
+{
+ php_sphinx_client *c;
+ zend_long qtime;
+ int res;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &qtime) == FAILURE) {
+ return;
+ }
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ res = sphinx_set_max_query_time(c->sphinx, (int)qtime);
+
+ if (!res) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+#ifdef HAVE_3ARG_SPHINX_SET_RANKING_MODE
+/* {{{ proto bool SphinxClient::setRankingMode(int ranker[, string ranking_expression]) */
+static PHP_METHOD(SphinxClient, setRankingMode)
+{
+ php_sphinx_client *c;
+ zend_long ranker;
+ int res;
+ char *rank_expr = NULL;
+ size_t rank_expr_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|s", &ranker, &rank_expr, &rank_expr_len) == FAILURE) {
+ return;
+ }
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ res = sphinx_set_ranking_mode(c->sphinx, (int)ranker, rank_expr);
+
+ if (!res) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+#else
+/* {{{ proto bool SphinxClient::setRankingMode(int ranker) */
+static PHP_METHOD(SphinxClient, setRankingMode)
+{
+ php_sphinx_client *c;
+ zend_long ranker;
+ int res;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &ranker) == FAILURE) {
+ return;
+ }
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ res = sphinx_set_ranking_mode(c->sphinx, (int)ranker);
+
+ if (!res) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+#endif
+
+/* {{{ proto bool SphinxClient::setFieldWeights(array weights) */
+static PHP_METHOD(SphinxClient, setFieldWeights)
+{
+ php_sphinx_client *c;
+ zval *weights, *item;
+ int num_weights, res = 0, i;
+ int *field_weights;
+ char **field_names;
+ zend_string *string_key;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "a", &weights) == FAILURE) {
+ return;
+ }
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ num_weights = zend_hash_num_elements(Z_ARRVAL_P(weights));
+ if (!num_weights) {
+ /* check for empty array and return false right away */
+ RETURN_FALSE;
+ }
+
+ field_names = safe_emalloc(num_weights, sizeof(char *), 0);
+ field_weights = safe_emalloc(num_weights, sizeof(int), 0);
+
+ /* reset num_weights, we'll reuse it count _real_ number of entries */
+ num_weights = 0;
+
+ ZEND_HASH_FOREACH_STR_KEY_VAL_IND(Z_ARRVAL_P(weights), string_key, item) {
+
+ if (!string_key) {
+ /* if the key is not string.. well.. you're screwed */
+ break;
+ }
+
+ field_names[num_weights] = estrndup(string_key->val, string_key->len);
+ field_weights[num_weights] = zval_get_long(item);
+
+ num_weights++;
+ } ZEND_HASH_FOREACH_END();
+
+ if (num_weights) {
+ res = sphinx_set_field_weights(c->sphinx, num_weights, (const char **) field_names, field_weights);
+ }
+
+ for (i = 0; i != num_weights; i++) {
+ efree(field_names[i]);
+ }
+ efree(field_names);
+ efree(field_weights);
+
+ if (!res) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool SphinxClient::setSortMode(int mode[, string sortby]) */
+static PHP_METHOD(SphinxClient, setSortMode)
+{
+ php_sphinx_client *c;
+ zend_long mode;
+ char *sortby = NULL;
+ int res;
+ size_t sortby_len;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|s", &mode, &sortby, &sortby_len) == FAILURE) {
+ return;
+ }
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ res = sphinx_set_sort_mode(c->sphinx, (int)mode, sortby);
+
+ if (!res) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool SphinxClient::setConnectTimeout(float timeout) */
+static PHP_METHOD(SphinxClient, setConnectTimeout)
+{
+ php_sphinx_client *c;
+ double timeout;
+ int res;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "d", &timeout) == FAILURE) {
+ return;
+ }
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ res = sphinx_set_connect_timeout(c->sphinx, timeout);
+
+ if (!res) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool SphinxClient::setArrayResult(bool array_result) */
+static PHP_METHOD(SphinxClient, setArrayResult)
+{
+ php_sphinx_client *c;
+ zend_bool array_result;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "b", &array_result) == FAILURE) {
+ return;
+ }
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ c->array_result = array_result;
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto int SphinxClient::updateAttributes(string index, array attributes, array values[, bool mva]) */
+static PHP_METHOD(SphinxClient, updateAttributes)
+{
+ php_sphinx_client *c;
+ zval *attributes, *values, *item;
+ char *index;
+ const char **attrs;
+ int attrs_num, values_num;
+ int res = 0;
+ sphinx_uint64_t *docids = NULL;
+ sphinx_int64_t *vals = NULL;
+ unsigned int *vals_mva = NULL;
+#if LIBSPHINX_VERSION_ID >= 110
+ int res_mva, values_mva_num, values_mva_size = 0;
+ zval *attr_value_mva;
+#endif
+ int a = 0, i = 0, j = 0;
+ zend_bool mva = 0;
+ size_t index_len;
+ ulong id;
+ zend_string *str_id;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "saa|b", &index, &index_len, &attributes, &values, &mva) == FAILURE) {
+ return;
+ }
+
+#if LIBSPHINX_VERSION_ID < 110
+ if (mva) {
+ php_error_docref(NULL, E_WARNING, "update mva attributes is not supported");
+ RETURN_FALSE;
+ }
+#endif
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ attrs_num = zend_hash_num_elements(Z_ARRVAL_P(attributes));
+
+ if (!attrs_num) {
+ php_error_docref(NULL, E_WARNING, "empty attributes array passed");
+ RETURN_FALSE;
+ }
+
+ values_num = zend_hash_num_elements(Z_ARRVAL_P(values));
+
+ if (!values_num) {
+ php_error_docref(NULL, E_WARNING, "empty values array passed");
+ RETURN_FALSE;
+ }
+
+ attrs = emalloc(sizeof(char *) * attrs_num);
+ ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL_P(attributes), item) {
+ if (Z_TYPE_P(item) != IS_STRING) {
+ php_error_docref(NULL, E_WARNING, "non-string attributes are not allowed");
+ break;
+ }
+ attrs[a] = Z_STRVAL_P(item); /* no copying here! */
+ a++;
+ } ZEND_HASH_FOREACH_END();
+
+ /* cleanup on error */
+ if (a != attrs_num) {
+ RETVAL_FALSE;
+ goto cleanup;
+ }
+
+ docids = emalloc(sizeof(sphinx_int64_t) * values_num);
+ if (!mva) {
+ vals = safe_emalloc(values_num * attrs_num, sizeof(sphinx_int64_t), 0);
+ }
+ ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(values), id, str_id, item) {
+ zval *attr_value;
+ int failed = 0;
+ double float_id = 0;
+ unsigned char id_type;
+
+ if (Z_TYPE_P(item) != IS_ARRAY) {
+ php_error_docref(NULL, E_WARNING, "value is not an array of attributes");
+ break;
+ }
+
+ if (zend_hash_num_elements(Z_ARRVAL_P(item)) != attrs_num) {
+ php_error_docref(NULL, E_WARNING, "number of values is not equal to the number of attributes");
+ break;
+ }
+
+ if (!str_id) {
+ /* ok */
+ id_type = IS_LONG;
+ } else {
+ id_type = is_numeric_string(str_id->val, str_id->len, (long *)&id, &float_id, 0);
+ if (id_type == IS_LONG || id_type == IS_DOUBLE) {
+ /* ok */
+ } else {
+ php_error_docref(NULL, E_WARNING, "document ID must be numeric");
+ break;
+ }
+ }
+
+ if (id_type == IS_LONG) {
+ docids[i] = (sphinx_uint64_t)id;
+ } else { /* IS_FLOAT */
+ docids[i] = (sphinx_uint64_t)float_id;
+ }
+
+ a = 0;
+ ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL_P(item), attr_value) {
+ if (mva) {
+#if LIBSPHINX_VERSION_ID >= 110
+ if (Z_TYPE_P(attr_value) != IS_ARRAY) {
+ php_error_docref(NULL, E_WARNING, "attribute value must be an array");
+ failed = 1;
+ break;
+ }
+ values_mva_num = zend_hash_num_elements(Z_ARRVAL_P(attr_value));
+ if (values_mva_num > values_mva_size) {
+ values_mva_size = values_mva_num;
+ vals_mva = safe_erealloc(vals_mva, values_mva_size, sizeof(unsigned int), 0);
+ }
+ if (vals_mva) {
+ memset(vals_mva, 0, values_mva_size * sizeof(unsigned int));
+ }
+
+ j = 0;
+ ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL_P(attr_value), attr_value_mva) {
+ if (Z_TYPE_P(attr_value_mva) != IS_LONG) {
+ php_error_docref(NULL, E_WARNING, "mva attribute value must be integer");
+ failed = 1;
+ break;
+ }
+ vals_mva[j] = (unsigned int)Z_LVAL_P(attr_value_mva);
+ j++;
+ } ZEND_HASH_FOREACH_END();
+
+ if (failed) {
+ break;
+ }
+
+ res_mva = sphinx_update_attributes_mva(c->sphinx, index, attrs[a], docids[i], values_mva_num, vals_mva);
+
+ if (res_mva < 0) {
+ failed = 1;
+ break;
+ }
+#endif
+ a++;
+ } else {
+ if (Z_TYPE_P(attr_value) != IS_LONG) {
+ php_error_docref(NULL, E_WARNING, "attribute value must be integer");
+ failed = 1;
+ break;
+ }
+ vals[j] = (sphinx_int64_t)Z_LVAL_P(attr_value);
+ j++;
+ }
+ } ZEND_HASH_FOREACH_END();
+
+ if (failed) {
+ break;
+ }
+
+ if (mva) {
+ res++;
+ }
+ i++;
+ } ZEND_HASH_FOREACH_END();
+
+ if (!mva && i != values_num) {
+ RETVAL_FALSE;
+ goto cleanup;
+ }
+
+ if (!mva) {
+ res = sphinx_update_attributes(c->sphinx, index, (int)attrs_num, attrs, values_num, docids, vals);
+ }
+
+ if (res < 0) {
+ RETVAL_FALSE;
+ } else {
+ RETVAL_LONG(res);
+ }
+
+cleanup:
+ efree(attrs);
+ if (docids) {
+ efree(docids);
+ }
+ if (vals) {
+ efree(vals);
+ }
+ if (vals_mva) {
+ efree(vals_mva);
+ }
+}
+/* }}} */
+
+/* {{{ proto array SphinxClient::buildExcerpts(array docs, string index, string words[, array opts]) */
+static PHP_METHOD(SphinxClient, buildExcerpts)
+{
+ php_sphinx_client *c;
+ zval *docs_array, *opts_array = NULL, *item;
+ char *index, *words;
+ const char **docs;
+ sphinx_excerpt_options opts;
+ size_t index_len, words_len;
+ int docs_num, i = 0;
+ char **result;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "ass|a", &docs_array, &index, &index_len, &words, &words_len, &opts_array) == FAILURE) {
+ return;
+ }
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ docs_num = zend_hash_num_elements(Z_ARRVAL_P(docs_array));
+
+ if (!docs_num) {
+ php_error_docref(NULL, E_WARNING, "empty documents array passed");
+ RETURN_FALSE;
+ }
+
+ docs = emalloc(sizeof(char *) * docs_num);
+ ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL_P(docs_array), item) {
+ if (Z_TYPE_P(item) != IS_STRING) {
+ php_error_docref(NULL, E_WARNING, "non-string documents are not allowed");
+ break;
+ }
+ docs[i] = Z_STRVAL_P(item); /* no copying here! */
+ i++;
+ } ZEND_HASH_FOREACH_END();
+
+ if (i != docs_num) {
+ RETVAL_FALSE;
+ goto cleanup;
+ }
+
+#define OPTS_EQUAL(str, txt) str->len == sizeof(txt) && memcmp(txt, str->val, sizeof(txt)) == 0
+
+ if (opts_array) {
+ zend_string *string_key;
+
+ /* nullify everything */
+ sphinx_init_excerpt_options(&opts);
+ ZEND_HASH_FOREACH_STR_KEY_VAL_IND(Z_ARRVAL_P(opts_array), string_key, item) {
+
+ switch (Z_TYPE_P(item)) {
+ case IS_STRING:
+ case IS_LONG:
+ case IS_TRUE:
+ case IS_FALSE:
+ break;
+ default:
+ continue; /* ignore invalid options */
+ }
+
+ if (!string_key) {
+ continue; /* ignore invalid option names */
+ }
+
+ if (OPTS_EQUAL(string_key, "before_match")) {
+ SEPARATE_ZVAL(item);
+ convert_to_string_ex(item);
+ opts.before_match = Z_STRVAL_P(item);
+ } else if (OPTS_EQUAL(string_key, "after_match")) {
+ SEPARATE_ZVAL(item);
+ convert_to_string_ex(item);
+ opts.after_match = Z_STRVAL_P(item);
+ } else if (OPTS_EQUAL(string_key, "chunk_separator")) {
+ SEPARATE_ZVAL(item);
+ convert_to_string_ex(item);
+ opts.chunk_separator = Z_STRVAL_P(item);
+ } else if (OPTS_EQUAL(string_key, "limit")) {
+ SEPARATE_ZVAL(item);
+ convert_to_long_ex(item);
+ opts.limit = (int)Z_LVAL_P(item);
+ } else if (OPTS_EQUAL(string_key, "around")) {
+ SEPARATE_ZVAL(item);
+ convert_to_long_ex(item);
+ opts.around = (int)Z_LVAL_P(item);
+ } else if (OPTS_EQUAL(string_key, "exact_phrase")) {
+ SEPARATE_ZVAL(item);
+ convert_to_boolean_ex(item);
+ opts.exact_phrase = Z_LVAL_P(item);
+ } else if (OPTS_EQUAL(string_key, "single_passage")) {
+ SEPARATE_ZVAL(item);
+ convert_to_boolean_ex(item);
+ opts.single_passage = Z_LVAL_P(item);
+ } else if (OPTS_EQUAL(string_key, "use_boundaries")) {
+ SEPARATE_ZVAL(item);
+ convert_to_boolean_ex(item);
+ opts.use_boundaries = Z_LVAL_P(item);
+ } else if (OPTS_EQUAL(string_key, "weight_order")) {
+ SEPARATE_ZVAL(item);
+ convert_to_boolean_ex(item);
+ opts.weight_order = Z_LVAL_P(item);
+#if LIBSPHINX_VERSION_ID >= 110
+ } else if (OPTS_EQUAL(string_key, "query_mode")) {
+ SEPARATE_ZVAL(item);
+ convert_to_boolean_ex(item);
+ opts.query_mode = Z_LVAL_P(item);
+ } else if (OPTS_EQUAL(string_key, "force_all_words")) {
+ SEPARATE_ZVAL(item);
+ convert_to_boolean_ex(item);
+ opts.force_all_words = Z_LVAL_P(item);
+ } else if (OPTS_EQUAL(string_key, "limit_passages")) {
+ SEPARATE_ZVAL(item);
+ convert_to_long_ex(item);
+ opts.limit_passages = (int)Z_LVAL_P(item);
+ } else if (OPTS_EQUAL(string_key, "limit_words")) {
+ SEPARATE_ZVAL(item);
+ convert_to_long_ex(item);
+ opts.limit_words = (int)Z_LVAL_P(item);
+ } else if (OPTS_EQUAL(string_key, "start_passage_id")) {
+ SEPARATE_ZVAL(item);
+ convert_to_long_ex(item);
+ opts.start_passage_id = (int)Z_LVAL_P(item);
+ } else if (OPTS_EQUAL(string_key, "load_files")) {
+ SEPARATE_ZVAL(item);
+ convert_to_boolean_ex(item);
+ opts.load_files = Z_LVAL_P(item);
+ } else if (OPTS_EQUAL(string_key, "html_strip_mode")) {
+ SEPARATE_ZVAL(item);
+ convert_to_string_ex(item);
+ opts.html_strip_mode = Z_STRVAL_P(item);
+ } else if (OPTS_EQUAL(string_key, "allow_empty")) {
+ SEPARATE_ZVAL(item);
+ convert_to_boolean_ex(item);
+ opts.allow_empty = Z_LVAL_P(item);
+#endif
+ } else {
+ /* ignore invalid option names */
+ }
+ } ZEND_HASH_FOREACH_END();
+ }
+
+ if (opts_array) {
+ result = sphinx_build_excerpts(c->sphinx, docs_num, docs, index, words, &opts);
+ } else {
+ result = sphinx_build_excerpts(c->sphinx, docs_num, docs, index, words, NULL);
+ }
+
+ if (!result) {
+ RETVAL_FALSE;
+ } else {
+ array_init(return_value);
+ for (i = 0; i < docs_num; i++) {
+ if (result[i] && result[i][0] != '\0') {
+ add_next_index_string(return_value, result[i]);
+ } else {
+ add_next_index_string(return_value, "");
+ }
+ free(result[i]);
+ }
+ free(result);
+ }
+
+cleanup:
+ efree(docs);
+}
+/* }}} */
+
+/* {{{ proto array SphinxClient::buildKeywords(string query, string index, bool hits) */
+static PHP_METHOD(SphinxClient, buildKeywords)
+{
+ php_sphinx_client *c;
+ char *query, *index;
+ size_t query_len, index_len;
+ zend_bool hits;
+ sphinx_keyword_info *result;
+ int i, num_keywords;
+ zval tmp;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "ssb", &query, &query_len, &index, &index_len, &hits) == FAILURE) {
+ return;
+ }
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ result = sphinx_build_keywords(c->sphinx, query, index, hits, &num_keywords);
+ if (!result || num_keywords <= 0) {
+ RETURN_FALSE;
+ }
+
+ array_init(return_value);
+ for (i = 0; i < num_keywords; i++) {
+ array_init(&tmp);
+
+ add_assoc_string(&tmp, "tokenized", result[i].tokenized);
+ add_assoc_string(&tmp, "normalized", result[i].normalized);
+
+ if (hits) {
+ add_assoc_long(&tmp, "docs", result[i].num_docs);
+ add_assoc_long(&tmp, "hits", result[i].num_hits);
+ }
+
+ add_next_index_zval(return_value, &tmp);
+
+ free(result[i].tokenized);
+ free(result[i].normalized);
+ }
+ free(result);
+}
+/* }}} */
+
+/* {{{ proto void SphinxClient::resetFilters() */
+static PHP_METHOD(SphinxClient, resetFilters)
+{
+ php_sphinx_client *c;
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ sphinx_reset_filters(c->sphinx);
+}
+/* }}} */
+
+/* {{{ proto void SphinxClient::resetGroupBy() */
+static PHP_METHOD(SphinxClient, resetGroupBy)
+{
+ php_sphinx_client *c;
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ sphinx_reset_groupby(c->sphinx);
+}
+/* }}} */
+
+/* {{{ proto string SphinxClient::getLastWarning() */
+static PHP_METHOD(SphinxClient, getLastWarning)
+{
+ php_sphinx_client *c;
+ const char *warning;
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ warning = sphinx_warning(c->sphinx);
+ if (!warning || !warning[0]) {
+ RETURN_EMPTY_STRING();
+ }
+ RETURN_STRING((char *)warning);
+}
+/* }}} */
+
+/* {{{ proto string SphinxClient::getLastError() */
+static PHP_METHOD(SphinxClient, getLastError)
+{
+ php_sphinx_client *c;
+ const char *error;
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ error = sphinx_error(c->sphinx);
+ if (!error || !error[0]) {
+ RETURN_EMPTY_STRING();
+ }
+ RETURN_STRING((char *)error);
+}
+/* }}} */
+
+/* {{{ proto array SphinxClient::query(string query[, string index[, string comment]]) */
+static PHP_METHOD(SphinxClient, query)
+{
+ php_sphinx_client *c;
+ char *query, *index = "*", *comment = "";
+ size_t query_len, index_len, comment_len;
+ sphinx_result *result;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|ss", &query, &query_len, &index, &index_len, &comment, &comment_len) == FAILURE) {
+ return;
+ }
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ result = sphinx_query(c->sphinx, query, index, comment);
+
+ if (!result) {
+ RETURN_FALSE;
+ }
+
+ php_sphinx_result_to_array(c, result, return_value);
+}
+
+/* }}} */
+
+/* {{{ proto int SphinxClient::addQuery(string query[, string index[, string comment]]) */
+static PHP_METHOD(SphinxClient, addQuery)
+{
+ php_sphinx_client *c;
+ char *query, *index = "*", *comment = "";
+ size_t query_len, index_len, comment_len, res;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|ss", &query, &query_len, &index, &index_len, &comment, &comment_len) == FAILURE) {
+ return;
+ }
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ res = sphinx_add_query(c->sphinx, query, index, comment);
+
+ if (res < 0) {
+ RETURN_FALSE;
+ }
+ RETURN_LONG(res);
+}
+
+/* }}} */
+
+/* {{{ proto array SphinxClient::runQueries() */
+static PHP_METHOD(SphinxClient, runQueries)
+{
+ php_sphinx_client *c;
+ sphinx_result *results;
+ int i, num_results;
+ zval single_result;
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ results = sphinx_run_queries(c->sphinx);
+
+ if (!results) {
+ RETURN_FALSE;
+ }
+
+ num_results = sphinx_get_num_results(c->sphinx);
+
+ array_init(return_value);
+ for (i = 0; i < num_results; i++) {
+ php_sphinx_result_to_array(c, &results[i], &single_result);
+ add_next_index_zval(return_value, &single_result);
+ }
+}
+/* }}} */
+
+/* {{{ proto string SphinxClient::escapeString(string data) */
+static PHP_METHOD(SphinxClient, escapeString)
+{
+ char *str, *new_str, *source, *target;
+ size_t str_len, new_str_len, i;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &str, &str_len) == FAILURE) {
+ return;
+ }
+
+ if (!str_len) {
+ RETURN_EMPTY_STRING();
+ }
+
+ new_str = safe_emalloc(2, str_len, 1);
+ target = new_str;
+ source = str;
+ for (i = 0; i < str_len; i++) {
+ switch (*source) {
+ case '(':
+ case ')':
+ case '|':
+ case '-':
+ case '!':
+ case '@':
+ case '~':
+ case '"':
+ case '&':
+ case '/':
+ case '\\':
+ case '^':
+ case '$':
+ case '=':
+ case '<':
+ *target++ = '\\';
+ *target++ = *source;
+ break;
+ default:
+ *target++ = *source;
+ break;
+ }
+ source++;
+ }
+ *target = '\0';
+
+ new_str_len = target - new_str;
+ new_str = erealloc(new_str, new_str_len + 1);
+ RETURN_STRINGL(new_str, new_str_len);
+ efree(new_str);
+}
+/* }}} */
+
+#if LIBSPHINX_VERSION_ID >= 99
+/* {{{ proto bool SphinxClient::open() */
+static PHP_METHOD(SphinxClient, open)
+{
+ php_sphinx_client *c;
+ int res;
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ res = sphinx_open(c->sphinx);
+ if (!res) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto bool SphinxClient::close() */
+static PHP_METHOD(SphinxClient, close)
+{
+ php_sphinx_client *c;
+ int res;
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ res = sphinx_close(c->sphinx);
+ if (!res) {
+ RETURN_FALSE;
+ }
+ RETURN_TRUE;
+}
+/* }}} */
+
+/* {{{ proto array SphinxClient::status() */
+static PHP_METHOD(SphinxClient, status)
+{
+ php_sphinx_client *c;
+ char **result;
+ int i, j, k, num_rows, num_cols;
+ zval tmp;
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ result = sphinx_status(c->sphinx, &num_rows, &num_cols);
+
+ if (!result || num_rows <= 0) {
+ RETURN_FALSE;
+ }
+
+ k = 0;
+ array_init(return_value);
+ for (i = 0; i < num_rows; i++) {
+ array_init(&tmp);
+
+ for (j = 0; j < num_cols; j++, k++) {
+ add_next_index_string(&tmp, result[k]);
+ }
+ add_next_index_zval(return_value, &tmp);
+ }
+ sphinx_status_destroy(result, num_rows, num_cols);
+}
+/* }}} */
+
+/* {{{ proto bool SphinxClient::setOverride(string attribute, int type, array values) */
+static PHP_METHOD(SphinxClient, setOverride)
+{
+ php_sphinx_client *c;
+ zval *values, *attr_value;
+ char *attribute;
+ zend_long type;
+ size_t attribute_len, values_num, i = 0;
+ int res;
+ sphinx_uint64_t *docids = NULL;
+ unsigned int *vals = NULL;
+ ulong id;
+ zend_string *str_id;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "sla", &attribute, &attribute_len, &type, &values) == FAILURE) {
+ return;
+ }
+
+ c = sphinx_client(getThis());
+ SPHINX_INITIALIZED(c)
+
+ if (type != SPH_ATTR_INTEGER && type != SPH_ATTR_TIMESTAMP
+ && type != SPH_ATTR_BOOL && type != SPH_ATTR_FLOAT) {
+ php_error_docref(NULL, E_WARNING, "type must be scalar");
+ RETURN_FALSE;
+ }
+
+ values_num = zend_hash_num_elements(Z_ARRVAL_P(values));
+ if (!values_num) {
+ php_error_docref(NULL, E_WARNING, "empty values array passed");
+ RETURN_FALSE;
+ }
+
+ docids = emalloc(sizeof(sphinx_uint64_t) * values_num);
+ vals = safe_emalloc(values_num, sizeof(unsigned int), 0);
+ ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(values), id, str_id, attr_value) {
+ double float_id = 0;
+ unsigned char id_type;
+
+ if (Z_TYPE_P(attr_value) != IS_LONG) {
+ php_error_docref(NULL, E_WARNING, "attribute value must be integer");
+ break;
+ }
+
+ if (!str_id) {
+ /* ok */
+ id_type = IS_LONG;
+ } else {
+ id_type = is_numeric_string(str_id->val, str_id->len, (long *)&id, &float_id, 0);
+ if (id_type == IS_LONG || id_type == IS_DOUBLE) {
+ /* ok */
+ } else {
+ php_error_docref(NULL, E_WARNING, "document ID must be numeric");
+ break;
+ }
+ }
+ vals[i] = (sphinx_uint64_t)Z_LVAL_P(attr_value);
+
+ if (id_type == IS_LONG) {
+ docids[i] = (sphinx_uint64_t)id;
+ } else { /* IS_FLOAT */
+ docids[i] = (sphinx_uint64_t)float_id;
+ }
+ i++;
+ } ZEND_HASH_FOREACH_END();
+
+ if (i != values_num) {
+ RETVAL_FALSE;
+ goto cleanup;
+ }
+
+ res = sphinx_add_override(c->sphinx, attribute, docids, values_num, vals);
+ if (!res) {
+ RETVAL_FALSE;
+ } else {
+ RETVAL_TRUE;
+ }
+
+cleanup:
+ if (docids) {
+ efree(docids);
+ }
+ if (vals) {
+ efree(vals);
+ }
+}
+/* }}} */
+#endif
+
+/* {{{ proto int SphinxClient::__sleep() */
+static PHP_METHOD(SphinxClient, __sleep)
+{
+ php_error_docref(NULL, E_RECOVERABLE_ERROR, "SphinxClient instance cannot be (un)serialized");
+}
+/* }}} */
+
+/* {{{ proto int SphinxClient::__wakeup() */
+static PHP_METHOD(SphinxClient, __wakeup)
+{
+ php_error_docref(NULL, E_RECOVERABLE_ERROR, "SphinxClient instance cannot be (un)serialized");
+}
+/* }}} */
+
+/* {{{ arginfo */
+ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setserver, 0, 0, 2)
+ ZEND_ARG_INFO(0, server)
+ ZEND_ARG_INFO(0, port)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setlimits, 0, 0, 2)
+ ZEND_ARG_INFO(0, offset)
+ ZEND_ARG_INFO(0, limit)
+ ZEND_ARG_INFO(0, max_matches)
+ ZEND_ARG_INFO(0, cutoff)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setmatchmode, 0, 0, 1)
+ ZEND_ARG_INFO(0, mode)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setindexweights, 0, 0, 1)
+ ZEND_ARG_INFO(0, weights)
+ZEND_END_ARG_INFO()
+
+#if LIBSPHINX_VERSION_ID >= 99
+ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setselect, 0, 0, 1)
+ ZEND_ARG_INFO(0, clause)
+ZEND_END_ARG_INFO()
+#endif
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setidrange, 0, 0, 2)
+ ZEND_ARG_INFO(0, min)
+ ZEND_ARG_INFO(0, max)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setfilter, 0, 0, 2)
+ ZEND_ARG_INFO(0, attribute)
+ ZEND_ARG_INFO(0, values)
+ ZEND_ARG_INFO(0, exclude)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setfilterstring, 0, 0, 2)
+ ZEND_ARG_INFO(0, attribute)
+ ZEND_ARG_INFO(0, value)
+ ZEND_ARG_INFO(0, exclude)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setfilterrange, 0, 0, 3)
+ ZEND_ARG_INFO(0, attribute)
+ ZEND_ARG_INFO(0, min)
+ ZEND_ARG_INFO(0, max)
+ ZEND_ARG_INFO(0, exclude)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setgeoanchor, 0, 0, 4)
+ ZEND_ARG_INFO(0, attrlat)
+ ZEND_ARG_INFO(0, attrlong)
+ ZEND_ARG_INFO(0, latitude)
+ ZEND_ARG_INFO(0, longitude)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setgroupby, 0, 0, 2)
+ ZEND_ARG_INFO(0, attribute)
+ ZEND_ARG_INFO(0, func)
+ ZEND_ARG_INFO(0, groupsort)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setgroupdistinct, 0, 0, 1)
+ ZEND_ARG_INFO(0, attribute)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setretries, 0, 0, 1)
+ ZEND_ARG_INFO(0, count)
+ ZEND_ARG_INFO(0, delay)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setmaxquerytime, 0, 0, 1)
+ ZEND_ARG_INFO(0, qtime)
+ZEND_END_ARG_INFO()
+
+#if LIBSPHINX_VERSION_ID >= 99
+ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setoverride, 0, 0, 3)
+ ZEND_ARG_INFO(0, attribute)
+ ZEND_ARG_INFO(0, type)
+ ZEND_ARG_INFO(0, values)
+ZEND_END_ARG_INFO()
+#endif
+
+#if HAVE_3ARG_SPHINX_SET_RANKING_MODE
+ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setrankingmode, 0, 0, 1)
+ ZEND_ARG_INFO(0, ranker)
+ ZEND_ARG_INFO(0, rank_expression)
+ZEND_END_ARG_INFO()
+#else
+ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setrankingmode, 0, 0, 1)
+ ZEND_ARG_INFO(0, ranker)
+ZEND_END_ARG_INFO()
+#endif
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setsortmode, 0, 0, 1)
+ ZEND_ARG_INFO(0, mode)
+ ZEND_ARG_INFO(0, sortby)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setconnecttimeout, 0, 0, 1)
+ ZEND_ARG_INFO(0, timeout)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_setarrayresult, 0, 0, 1)
+ ZEND_ARG_INFO(0, array_result)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_updateattributes, 0, 0, 3)
+ ZEND_ARG_INFO(0, index)
+ ZEND_ARG_INFO(0, attributes)
+ ZEND_ARG_INFO(0, values)
+ ZEND_ARG_INFO(0, mva)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_buildexcerpts, 0, 0, 3)
+ ZEND_ARG_INFO(0, docs)
+ ZEND_ARG_INFO(0, index)
+ ZEND_ARG_INFO(0, words)
+ ZEND_ARG_INFO(0, opts)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_buildkeywords, 0, 0, 3)
+ ZEND_ARG_INFO(0, query)
+ ZEND_ARG_INFO(0, index)
+ ZEND_ARG_INFO(0, hits)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_query, 0, 0, 1)
+ ZEND_ARG_INFO(0, query)
+ ZEND_ARG_INFO(0, index)
+ ZEND_ARG_INFO(0, comment)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO(arginfo_sphinxclient__param_void, 0)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_sphinxclient_escapestring, 0, 0, 1)
+ ZEND_ARG_INFO(0, data)
+ZEND_END_ARG_INFO()
+/* }}} */
+
+static zend_function_entry sphinx_client_methods[] = { /* {{{ */
+ PHP_ME(SphinxClient, __construct, arginfo_sphinxclient__param_void, ZEND_ACC_PUBLIC)
+ PHP_ME(SphinxClient, addQuery, arginfo_sphinxclient_query, ZEND_ACC_PUBLIC)
+ PHP_ME(SphinxClient, buildExcerpts, arginfo_sphinxclient_buildexcerpts, ZEND_ACC_PUBLIC)
+ PHP_ME(SphinxClient, buildKeywords, arginfo_sphinxclient_buildkeywords, ZEND_ACC_PUBLIC)
+#if LIBSPHINX_VERSION_ID >= 99
+ PHP_ME(SphinxClient, close, arginfo_sphinxclient__param_void, ZEND_ACC_PUBLIC)
+#endif
+ PHP_ME(SphinxClient, getLastError, arginfo_sphinxclient__param_void, ZEND_ACC_PUBLIC)
+ PHP_ME(SphinxClient, getLastWarning, arginfo_sphinxclient__param_void, ZEND_ACC_PUBLIC)
+ PHP_ME(SphinxClient, escapeString, arginfo_sphinxclient_escapestring, ZEND_ACC_PUBLIC)
+#if LIBSPHINX_VERSION_ID >= 99
+ PHP_ME(SphinxClient, open, arginfo_sphinxclient__param_void, ZEND_ACC_PUBLIC)
+#endif
+ PHP_ME(SphinxClient, query, arginfo_sphinxclient_query, ZEND_ACC_PUBLIC)
+ PHP_ME(SphinxClient, resetFilters, arginfo_sphinxclient__param_void, ZEND_ACC_PUBLIC)
+ PHP_ME(SphinxClient, resetGroupBy, arginfo_sphinxclient__param_void, ZEND_ACC_PUBLIC)
+ PHP_ME(SphinxClient, runQueries, arginfo_sphinxclient__param_void, ZEND_ACC_PUBLIC)
+ PHP_ME(SphinxClient, setArrayResult, arginfo_sphinxclient_setarrayresult, ZEND_ACC_PUBLIC)
+ PHP_ME(SphinxClient, setConnectTimeout, arginfo_sphinxclient_setconnecttimeout, ZEND_ACC_PUBLIC)
+ PHP_ME(SphinxClient, setFieldWeights, arginfo_sphinxclient_setindexweights, ZEND_ACC_PUBLIC)
+ PHP_ME(SphinxClient, setFilter, arginfo_sphinxclient_setfilter, ZEND_ACC_PUBLIC)
+#ifdef HAVE_SPHINX_ADD_FILTER_STRING
+ PHP_ME(SphinxClient, setFilterString, arginfo_sphinxclient_setfilterstring, ZEND_ACC_PUBLIC)
+#endif
+ PHP_ME(SphinxClient, setFilterFloatRange, arginfo_sphinxclient_setfilterrange, ZEND_ACC_PUBLIC)
+ PHP_ME(SphinxClient, setFilterRange, arginfo_sphinxclient_setfilterrange, ZEND_ACC_PUBLIC)
+ PHP_ME(SphinxClient, setGeoAnchor, arginfo_sphinxclient_setgeoanchor, ZEND_ACC_PUBLIC)
+ PHP_ME(SphinxClient, setGroupBy, arginfo_sphinxclient_setgroupby, ZEND_ACC_PUBLIC)
+ PHP_ME(SphinxClient, setGroupDistinct, arginfo_sphinxclient_setgroupdistinct, ZEND_ACC_PUBLIC)
+ PHP_ME(SphinxClient, setIndexWeights, arginfo_sphinxclient_setindexweights, ZEND_ACC_PUBLIC)
+ PHP_ME(SphinxClient, setIDRange, arginfo_sphinxclient_setidrange, ZEND_ACC_PUBLIC)
+#if LIBSPHINX_VERSION_ID >= 99
+ PHP_ME(SphinxClient, setSelect, arginfo_sphinxclient_setselect, ZEND_ACC_PUBLIC)
+#endif
+ PHP_ME(SphinxClient, setLimits, arginfo_sphinxclient_setlimits, ZEND_ACC_PUBLIC)
+ PHP_ME(SphinxClient, setMatchMode, arginfo_sphinxclient_setmatchmode, ZEND_ACC_PUBLIC)
+ PHP_ME(SphinxClient, setMaxQueryTime, arginfo_sphinxclient_setmaxquerytime, ZEND_ACC_PUBLIC)
+#if LIBSPHINX_VERSION_ID >= 99
+ PHP_ME(SphinxClient, setOverride, arginfo_sphinxclient_setoverride, ZEND_ACC_PUBLIC)
+#endif
+ PHP_ME(SphinxClient, setRankingMode, arginfo_sphinxclient_setrankingmode, ZEND_ACC_PUBLIC)
+ PHP_ME(SphinxClient, setRetries, arginfo_sphinxclient_setretries, ZEND_ACC_PUBLIC)
+ PHP_ME(SphinxClient, setServer, arginfo_sphinxclient_setserver, ZEND_ACC_PUBLIC)
+ PHP_ME(SphinxClient, setSortMode, arginfo_sphinxclient_setsortmode, ZEND_ACC_PUBLIC)
+#if LIBSPHINX_VERSION_ID >= 99
+ PHP_ME(SphinxClient, status, arginfo_sphinxclient__param_void, ZEND_ACC_PUBLIC)
+#endif
+ PHP_ME(SphinxClient, updateAttributes, arginfo_sphinxclient_updateattributes, ZEND_ACC_PUBLIC)
+ PHP_ME(SphinxClient, __sleep, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
+ PHP_ME(SphinxClient, __wakeup, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_FINAL)
+ {NULL, NULL, NULL}
+};
+/* }}} */
+
+/* {{{ PHP_MINIT_FUNCTION
+ */
+PHP_MINIT_FUNCTION(sphinx)
+{
+ zend_class_entry ce;
+
+ memcpy(&cannot_be_cloned, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
+ cannot_be_cloned.clone_obj = NULL;
+
+ memcpy(&php_sphinx_client_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
+ php_sphinx_client_handlers.clone_obj = NULL;
+ php_sphinx_client_handlers.read_property = php_sphinx_client_read_property;
+ php_sphinx_client_handlers.get_properties = php_sphinx_client_get_properties;
+ php_sphinx_client_handlers.free_obj = php_sphinx_client_obj_dtor;
+ php_sphinx_client_handlers.offset = XtOffsetOf(php_sphinx_client, std);
+
+ INIT_CLASS_ENTRY(ce, "SphinxClient", sphinx_client_methods);
+ ce_sphinx_client = zend_register_internal_class(&ce);
+ ce_sphinx_client->create_object = php_sphinx_client_new;
+
+ SPHINX_CONST(SEARCHD_OK);
+ SPHINX_CONST(SEARCHD_ERROR);
+ SPHINX_CONST(SEARCHD_RETRY);
+ SPHINX_CONST(SEARCHD_WARNING);
+
+ SPHINX_CONST(SPH_MATCH_ALL);
+ SPHINX_CONST(SPH_MATCH_ANY);
+ SPHINX_CONST(SPH_MATCH_PHRASE);
+ SPHINX_CONST(SPH_MATCH_BOOLEAN);
+ SPHINX_CONST(SPH_MATCH_EXTENDED);
+ SPHINX_CONST(SPH_MATCH_FULLSCAN);
+ SPHINX_CONST(SPH_MATCH_EXTENDED2);
+
+ SPHINX_CONST(SPH_RANK_PROXIMITY_BM25);
+ SPHINX_CONST(SPH_RANK_BM25);
+ SPHINX_CONST(SPH_RANK_NONE);
+ SPHINX_CONST(SPH_RANK_WORDCOUNT);
+#ifdef HAVE_SPH_RANK_PROXIMITY
+ SPHINX_CONST(SPH_RANK_PROXIMITY);
+#endif
+#ifdef HAVE_SPH_RANK_MATCHANY
+ SPHINX_CONST(SPH_RANK_MATCHANY);
+#endif
+#ifdef HAVE_SPH_RANK_FIELDMASK
+ SPHINX_CONST(SPH_RANK_FIELDMASK);
+#endif
+#ifdef HAVE_SPH_RANK_SPH04
+ SPHINX_CONST(SPH_RANK_SPH04);
+#endif
+#ifdef HAVE_SPH_RANK_EXPR
+ SPHINX_CONST(SPH_RANK_EXPR);
+#endif
+#ifdef HAVE_SPH_RANK_TOTAL
+ SPHINX_CONST(SPH_RANK_TOTAL);
+#endif
+
+ SPHINX_CONST(SPH_SORT_RELEVANCE);
+ SPHINX_CONST(SPH_SORT_ATTR_DESC);
+ SPHINX_CONST(SPH_SORT_ATTR_ASC);
+ SPHINX_CONST(SPH_SORT_TIME_SEGMENTS);
+ SPHINX_CONST(SPH_SORT_EXTENDED);
+ SPHINX_CONST(SPH_SORT_EXPR);
+
+ SPHINX_CONST(SPH_FILTER_VALUES);
+ SPHINX_CONST(SPH_FILTER_RANGE);
+ SPHINX_CONST(SPH_FILTER_FLOATRANGE);
+
+ SPHINX_CONST(SPH_ATTR_INTEGER);
+ SPHINX_CONST(SPH_ATTR_TIMESTAMP);
+ SPHINX_CONST(SPH_ATTR_ORDINAL);
+ SPHINX_CONST(SPH_ATTR_BOOL);
+ SPHINX_CONST(SPH_ATTR_FLOAT);
+ SPHINX_CONST(SPH_ATTR_MULTI);
+
+ SPHINX_CONST(SPH_GROUPBY_DAY);
+ SPHINX_CONST(SPH_GROUPBY_WEEK);
+ SPHINX_CONST(SPH_GROUPBY_MONTH);
+ SPHINX_CONST(SPH_GROUPBY_YEAR);
+ SPHINX_CONST(SPH_GROUPBY_ATTR);
+ SPHINX_CONST(SPH_GROUPBY_ATTRPAIR);
+
+ return SUCCESS;
+}
+/* }}} */
+
+/* {{{ PHP_MINFO_FUNCTION
+ */
+PHP_MINFO_FUNCTION(sphinx)
+{
+ php_info_print_table_start();
+ php_info_print_table_header(2, "sphinx support", "enabled");
+ php_info_print_table_header(2, "Version", PHP_SPHINX_VERSION);
+ php_info_print_table_header(2, "Revision", "$Revision$");
+ php_info_print_table_end();
+}
+/* }}} */
+
+static zend_function_entry sphinx_functions[] = { /* {{{ */
+ {NULL, NULL, NULL}
+};
+/* }}} */
+
+/* {{{ sphinx_module_entry
+ */
+zend_module_entry sphinx_module_entry = {
+ STANDARD_MODULE_HEADER,
+ "sphinx",
+ sphinx_functions,
+ PHP_MINIT(sphinx),
+ NULL,
+ NULL,
+ NULL,
+ PHP_MINFO(sphinx),
+ PHP_SPHINX_VERSION,
+ STANDARD_MODULE_PROPERTIES
+};
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/tests
^
|
+(directory)
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/tests/api
^
|
+(directory)
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/tests/api/sphinxapi-1.10.php
^
|
@@ -0,0 +1,1688 @@
+<?php
+
+//
+// $Id: sphinxapi.php 2376 2010-06-29 14:08:19Z shodan $
+//
+
+//
+// Copyright (c) 2001-2010, Andrew Aksyonoff
+// Copyright (c) 2008-2010, Sphinx Technologies Inc
+// All rights reserved
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License. You should have
+// received a copy of the GPL license along with this program; if you
+// did not, you can find it at http://www.gnu.org/
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// PHP version of Sphinx searchd client (PHP API)
+/////////////////////////////////////////////////////////////////////////////
+
+/// known searchd commands
+define ( "SEARCHD_COMMAND_SEARCH", 0 );
+define ( "SEARCHD_COMMAND_EXCERPT", 1 );
+define ( "SEARCHD_COMMAND_UPDATE", 2 );
+define ( "SEARCHD_COMMAND_KEYWORDS", 3 );
+define ( "SEARCHD_COMMAND_PERSIST", 4 );
+define ( "SEARCHD_COMMAND_STATUS", 5 );
+define ( "SEARCHD_COMMAND_QUERY", 6 );
+define ( "SEARCHD_COMMAND_FLUSHATTRS", 7 );
+
+/// current client-side command implementation versions
+define ( "VER_COMMAND_SEARCH", 0x117 );
+define ( "VER_COMMAND_EXCERPT", 0x102 );
+define ( "VER_COMMAND_UPDATE", 0x102 );
+define ( "VER_COMMAND_KEYWORDS", 0x100 );
+define ( "VER_COMMAND_STATUS", 0x100 );
+define ( "VER_COMMAND_QUERY", 0x100 );
+define ( "VER_COMMAND_FLUSHATTRS", 0x100 );
+
+/// known searchd status codes
+define ( "SEARCHD_OK", 0 );
+define ( "SEARCHD_ERROR", 1 );
+define ( "SEARCHD_RETRY", 2 );
+define ( "SEARCHD_WARNING", 3 );
+
+/// known match modes
+define ( "SPH_MATCH_ALL", 0 );
+define ( "SPH_MATCH_ANY", 1 );
+define ( "SPH_MATCH_PHRASE", 2 );
+define ( "SPH_MATCH_BOOLEAN", 3 );
+define ( "SPH_MATCH_EXTENDED", 4 );
+define ( "SPH_MATCH_FULLSCAN", 5 );
+define ( "SPH_MATCH_EXTENDED2", 6 ); // extended engine V2 (TEMPORARY, WILL BE REMOVED)
+
+/// known ranking modes (ext2 only)
+define ( "SPH_RANK_PROXIMITY_BM25", 0 ); ///< default mode, phrase proximity major factor and BM25 minor one
+define ( "SPH_RANK_BM25", 1 ); ///< statistical mode, BM25 ranking only (faster but worse quality)
+define ( "SPH_RANK_NONE", 2 ); ///< no ranking, all matches get a weight of 1
+define ( "SPH_RANK_WORDCOUNT", 3 ); ///< simple word-count weighting, rank is a weighted sum of per-field keyword occurence counts
+define ( "SPH_RANK_PROXIMITY", 4 );
+define ( "SPH_RANK_MATCHANY", 5 );
+define ( "SPH_RANK_FIELDMASK", 6 );
+define ( "SPH_RANK_SPH04", 7 );
+define ( "SPH_RANK_TOTAL", 8 );
+
+/// known sort modes
+define ( "SPH_SORT_RELEVANCE", 0 );
+define ( "SPH_SORT_ATTR_DESC", 1 );
+define ( "SPH_SORT_ATTR_ASC", 2 );
+define ( "SPH_SORT_TIME_SEGMENTS", 3 );
+define ( "SPH_SORT_EXTENDED", 4 );
+define ( "SPH_SORT_EXPR", 5 );
+
+/// known filter types
+define ( "SPH_FILTER_VALUES", 0 );
+define ( "SPH_FILTER_RANGE", 1 );
+define ( "SPH_FILTER_FLOATRANGE", 2 );
+
+/// known attribute types
+define ( "SPH_ATTR_INTEGER", 1 );
+define ( "SPH_ATTR_TIMESTAMP", 2 );
+define ( "SPH_ATTR_ORDINAL", 3 );
+define ( "SPH_ATTR_BOOL", 4 );
+define ( "SPH_ATTR_FLOAT", 5 );
+define ( "SPH_ATTR_BIGINT", 6 );
+define ( "SPH_ATTR_STRING", 7 );
+define ( "SPH_ATTR_MULTI", 0x40000000 );
+
+/// known grouping functions
+define ( "SPH_GROUPBY_DAY", 0 );
+define ( "SPH_GROUPBY_WEEK", 1 );
+define ( "SPH_GROUPBY_MONTH", 2 );
+define ( "SPH_GROUPBY_YEAR", 3 );
+define ( "SPH_GROUPBY_ATTR", 4 );
+define ( "SPH_GROUPBY_ATTRPAIR", 5 );
+
+// important properties of PHP's integers:
+// - always signed (one bit short of PHP_INT_SIZE)
+// - conversion from string to int is saturated
+// - float is double
+// - div converts arguments to floats
+// - mod converts arguments to ints
+
+// the packing code below works as follows:
+// - when we got an int, just pack it
+// if performance is a problem, this is the branch users should aim for
+//
+// - otherwise, we got a number in string form
+// this might be due to different reasons, but we assume that this is
+// because it didn't fit into PHP int
+//
+// - factor the string into high and low ints for packing
+// - if we have bcmath, then it is used
+// - if we don't, we have to do it manually (this is the fun part)
+//
+// - x64 branch does factoring using ints
+// - x32 (ab)uses floats, since we can't fit unsigned 32-bit number into an int
+//
+// unpacking routines are pretty much the same.
+// - return ints if we can
+// - otherwise format number into a string
+
+/// pack 64-bit signed
+function sphPackI64 ( $v )
+{
+ assert ( is_numeric($v) );
+
+ // x64
+ if ( PHP_INT_SIZE>=8 )
+ {
+ $v = (int)$v;
+ return pack ( "NN", $v>>32, $v&0xFFFFFFFF );
+ }
+
+ // x32, int
+ if ( is_int($v) )
+ return pack ( "NN", $v < 0 ? -1 : 0, $v );
+
+ // x32, bcmath
+ if ( function_exists("bcmul") )
+ {
+ if ( bccomp ( $v, 0 ) == -1 )
+ $v = bcadd ( "18446744073709551616", $v );
+ $h = bcdiv ( $v, "4294967296", 0 );
+ $l = bcmod ( $v, "4294967296" );
+ return pack ( "NN", (float)$h, (float)$l ); // conversion to float is intentional; int would lose 31st bit
+ }
+
+ // x32, no-bcmath
+ $p = max(0, strlen($v) - 13);
+ $lo = abs((float)substr($v, $p));
+ $hi = abs((float)substr($v, 0, $p));
+
+ $m = $lo + $hi*1316134912.0; // (10 ^ 13) % (1 << 32) = 1316134912
+ $q = floor($m/4294967296.0);
+ $l = $m - ($q*4294967296.0);
+ $h = $hi*2328.0 + $q; // (10 ^ 13) / (1 << 32) = 2328
+
+ if ( $v<0 )
+ {
+ if ( $l==0 )
+ $h = 4294967296.0 - $h;
+ else
+ {
+ $h = 4294967295.0 - $h;
+ $l = 4294967296.0 - $l;
+ }
+ }
+ return pack ( "NN", $h, $l );
+}
+
+/// pack 64-bit unsigned
+function sphPackU64 ( $v )
+{
+ assert ( is_numeric($v) );
+
+ // x64
+ if ( PHP_INT_SIZE>=8 )
+ {
+ assert ( $v>=0 );
+
+ // x64, int
+ if ( is_int($v) )
+ return pack ( "NN", $v>>32, $v&0xFFFFFFFF );
+
+ // x64, bcmath
+ if ( function_exists("bcmul") )
+ {
+ $h = bcdiv ( $v, 4294967296, 0 );
+ $l = bcmod ( $v, 4294967296 );
+ return pack ( "NN", $h, $l );
+ }
+
+ // x64, no-bcmath
+ $p = max ( 0, strlen($v) - 13 );
+ $lo = (int)substr ( $v, $p );
+ $hi = (int)substr ( $v, 0, $p );
+
+ $m = $lo + $hi*1316134912;
+ $l = $m % 4294967296;
+ $h = $hi*2328 + (int)($m/4294967296);
+
+ return pack ( "NN", $h, $l );
+ }
+
+ // x32, int
+ if ( is_int($v) )
+ return pack ( "NN", 0, $v );
+
+ // x32, bcmath
+ if ( function_exists("bcmul") )
+ {
+ $h = bcdiv ( $v, "4294967296", 0 );
+ $l = bcmod ( $v, "4294967296" );
+ return pack ( "NN", (float)$h, (float)$l ); // conversion to float is intentional; int would lose 31st bit
+ }
+
+ // x32, no-bcmath
+ $p = max(0, strlen($v) - 13);
+ $lo = (float)substr($v, $p);
+ $hi = (float)substr($v, 0, $p);
+
+ $m = $lo + $hi*1316134912.0;
+ $q = floor($m / 4294967296.0);
+ $l = $m - ($q * 4294967296.0);
+ $h = $hi*2328.0 + $q;
+
+ return pack ( "NN", $h, $l );
+}
+
+// unpack 64-bit unsigned
+function sphUnpackU64 ( $v )
+{
+ list ( $hi, $lo ) = array_values ( unpack ( "N*N*", $v ) );
+
+ if ( PHP_INT_SIZE>=8 )
+ {
+ if ( $hi<0 ) $hi += (1<<32); // because php 5.2.2 to 5.2.5 is totally fucked up again
+ if ( $lo<0 ) $lo += (1<<32);
+
+ // x64, int
+ if ( $hi<=2147483647 )
+ return ($hi<<32) + $lo;
+
+ // x64, bcmath
+ if ( function_exists("bcmul") )
+ return bcadd ( $lo, bcmul ( $hi, "4294967296" ) );
+
+ // x64, no-bcmath
+ $C = 100000;
+ $h = ((int)($hi / $C) << 32) + (int)($lo / $C);
+ $l = (($hi % $C) << 32) + ($lo % $C);
+ if ( $l>$C )
+ {
+ $h += (int)($l / $C);
+ $l = $l % $C;
+ }
+
+ if ( $h==0 )
+ return $l;
+ return sprintf ( "%d%05d", $h, $l );
+ }
+
+ // x32, int
+ if ( $hi==0 )
+ {
+ if ( $lo>0 )
+ return $lo;
+ return sprintf ( "%u", $lo );
+ }
+
+ $hi = sprintf ( "%u", $hi );
+ $lo = sprintf ( "%u", $lo );
+
+ // x32, bcmath
+ if ( function_exists("bcmul") )
+ return bcadd ( $lo, bcmul ( $hi, "4294967296" ) );
+
+ // x32, no-bcmath
+ $hi = (float)$hi;
+ $lo = (float)$lo;
+
+ $q = floor($hi/10000000.0);
+ $r = $hi - $q*10000000.0;
+ $m = $lo + $r*4967296.0;
+ $mq = floor($m/10000000.0);
+ $l = $m - $mq*10000000.0;
+ $h = $q*4294967296.0 + $r*429.0 + $mq;
+
+ $h = sprintf ( "%.0f", $h );
+ $l = sprintf ( "%07.0f", $l );
+ if ( $h=="0" )
+ return sprintf( "%.0f", (float)$l );
+ return $h . $l;
+}
+
+// unpack 64-bit signed
+function sphUnpackI64 ( $v )
+{
+ list ( $hi, $lo ) = array_values ( unpack ( "N*N*", $v ) );
+
+ // x64
+ if ( PHP_INT_SIZE>=8 )
+ {
+ if ( $hi<0 ) $hi += (1<<32); // because php 5.2.2 to 5.2.5 is totally fucked up again
+ if ( $lo<0 ) $lo += (1<<32);
+
+ return ($hi<<32) + $lo;
+ }
+
+ // x32, int
+ if ( $hi==0 )
+ {
+ if ( $lo>0 )
+ return $lo;
+ return sprintf ( "%u", $lo );
+ }
+ // x32, int
+ elseif ( $hi==-1 )
+ {
+ if ( $lo<0 )
+ return $lo;
+ return sprintf ( "%.0f", $lo - 4294967296.0 );
+ }
+
+ $neg = "";
+ $c = 0;
+ if ( $hi<0 )
+ {
+ $hi = ~$hi;
+ $lo = ~$lo;
+ $c = 1;
+ $neg = "-";
+ }
+
+ $hi = sprintf ( "%u", $hi );
+ $lo = sprintf ( "%u", $lo );
+
+ // x32, bcmath
+ if ( function_exists("bcmul") )
+ return $neg . bcadd ( bcadd ( $lo, bcmul ( $hi, "4294967296" ) ), $c );
+
+ // x32, no-bcmath
+ $hi = (float)$hi;
+ $lo = (float)$lo;
+
+ $q = floor($hi/10000000.0);
+ $r = $hi - $q*10000000.0;
+ $m = $lo + $r*4967296.0;
+ $mq = floor($m/10000000.0);
+ $l = $m - $mq*10000000.0 + $c;
+ $h = $q*4294967296.0 + $r*429.0 + $mq;
+ if ( $l==10000000 )
+ {
+ $l = 0;
+ $h += 1;
+ }
+
+ $h = sprintf ( "%.0f", $h );
+ $l = sprintf ( "%07.0f", $l );
+ if ( $h=="0" )
+ return $neg . sprintf( "%.0f", (float)$l );
+ return $neg . $h . $l;
+}
+
+
+function sphFixUint ( $value )
+{
+ if ( PHP_INT_SIZE>=8 )
+ {
+ // x64 route, workaround broken unpack() in 5.2.2+
+ if ( $value<0 ) $value += (1<<32);
+ return $value;
+ }
+ else
+ {
+ // x32 route, workaround php signed/unsigned braindamage
+ return sprintf ( "%u", $value );
+ }
+}
+
+
+/// sphinx searchd client class
+class SphinxClient
+{
+ var $_host; ///< searchd host (default is "localhost")
+ var $_port; ///< searchd port (default is 9312)
+ var $_offset; ///< how many records to seek from result-set start (default is 0)
+ var $_limit; ///< how many records to return from result-set starting at offset (default is 20)
+ var $_mode; ///< query matching mode (default is SPH_MATCH_ALL)
+ var $_weights; ///< per-field weights (default is 1 for all fields)
+ var $_sort; ///< match sorting mode (default is SPH_SORT_RELEVANCE)
+ var $_sortby; ///< attribute to sort by (defualt is "")
+ var $_min_id; ///< min ID to match (default is 0, which means no limit)
+ var $_max_id; ///< max ID to match (default is 0, which means no limit)
+ var $_filters; ///< search filters
+ var $_groupby; ///< group-by attribute name
+ var $_groupfunc; ///< group-by function (to pre-process group-by attribute value with)
+ var $_groupsort; ///< group-by sorting clause (to sort groups in result set with)
+ var $_groupdistinct;///< group-by count-distinct attribute
+ var $_maxmatches; ///< max matches to retrieve
+ var $_cutoff; ///< cutoff to stop searching at (default is 0)
+ var $_retrycount; ///< distributed retries count
+ var $_retrydelay; ///< distributed retries delay
+ var $_anchor; ///< geographical anchor point
+ var $_indexweights; ///< per-index weights
+ var $_ranker; ///< ranking mode (default is SPH_RANK_PROXIMITY_BM25)
+ var $_maxquerytime; ///< max query time, milliseconds (default is 0, do not limit)
+ var $_fieldweights; ///< per-field-name weights
+ var $_overrides; ///< per-query attribute values overrides
+ var $_select; ///< select-list (attributes or expressions, with optional aliases)
+
+ var $_error; ///< last error message
+ var $_warning; ///< last warning message
+ var $_connerror; ///< connection error vs remote error flag
+
+ var $_reqs; ///< requests array for multi-query
+ var $_mbenc; ///< stored mbstring encoding
+ var $_arrayresult; ///< whether $result["matches"] should be a hash or an array
+ var $_timeout; ///< connect timeout
+
+ /////////////////////////////////////////////////////////////////////////////
+ // common stuff
+ /////////////////////////////////////////////////////////////////////////////
+
+ /// create a new client object and fill defaults
+ function SphinxClient ()
+ {
+ // per-client-object settings
+ $this->_host = "localhost";
+ $this->_port = 9312;
+ $this->_path = false;
+ $this->_socket = false;
+
+ // per-query settings
+ $this->_offset = 0;
+ $this->_limit = 20;
+ $this->_mode = SPH_MATCH_ALL;
+ $this->_weights = array ();
+ $this->_sort = SPH_SORT_RELEVANCE;
+ $this->_sortby = "";
+ $this->_min_id = 0;
+ $this->_max_id = 0;
+ $this->_filters = array ();
+ $this->_groupby = "";
+ $this->_groupfunc = SPH_GROUPBY_DAY;
+ $this->_groupsort = "@group desc";
+ $this->_groupdistinct= "";
+ $this->_maxmatches = 1000;
+ $this->_cutoff = 0;
+ $this->_retrycount = 0;
+ $this->_retrydelay = 0;
+ $this->_anchor = array ();
+ $this->_indexweights= array ();
+ $this->_ranker = SPH_RANK_PROXIMITY_BM25;
+ $this->_maxquerytime= 0;
+ $this->_fieldweights= array();
+ $this->_overrides = array();
+ $this->_select = "*";
+
+ $this->_error = ""; // per-reply fields (for single-query case)
+ $this->_warning = "";
+ $this->_connerror = false;
+
+ $this->_reqs = array (); // requests storage (for multi-query case)
+ $this->_mbenc = "";
+ $this->_arrayresult = false;
+ $this->_timeout = 0;
+ }
+
+ function __destruct()
+ {
+ if ( $this->_socket !== false )
+ fclose ( $this->_socket );
+ }
+
+ /// get last error message (string)
+ function GetLastError ()
+ {
+ return $this->_error;
+ }
+
+ /// get last warning message (string)
+ function GetLastWarning ()
+ {
+ return $this->_warning;
+ }
+
+ /// get last error flag (to tell network connection errors from searchd errors or broken responses)
+ function IsConnectError()
+ {
+ return $this->_connerror;
+ }
+
+ /// set searchd host name (string) and port (integer)
+ function SetServer ( $host, $port = 0 )
+ {
+ assert ( is_string($host) );
+ if ( $host[0] == '/')
+ {
+ $this->_path = 'unix://' . $host;
+ return;
+ }
+ if ( substr ( $host, 0, 7 )=="unix://" )
+ {
+ $this->_path = $host;
+ return;
+ }
+
+ assert ( is_int($port) );
+ $this->_host = $host;
+ $this->_port = $port;
+ $this->_path = '';
+
+ }
+
+ /// set server connection timeout (0 to remove)
+ function SetConnectTimeout ( $timeout )
+ {
+ assert ( is_numeric($timeout) );
+ $this->_timeout = $timeout;
+ }
+
+
+ function _Send ( $handle, $data, $length )
+ {
+ if ( feof($handle) || fwrite ( $handle, $data, $length ) !== $length )
+ {
+ $this->_error = 'connection unexpectedly closed (timed out?)';
+ $this->_connerror = true;
+ return false;
+ }
+ return true;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+
+ /// enter mbstring workaround mode
+ function _MBPush ()
+ {
+ $this->_mbenc = "";
+ if ( ini_get ( "mbstring.func_overload" ) & 2 )
+ {
+ $this->_mbenc = mb_internal_encoding();
+ mb_internal_encoding ( "latin1" );
+ }
+ }
+
+ /// leave mbstring workaround mode
+ function _MBPop ()
+ {
+ if ( $this->_mbenc )
+ mb_internal_encoding ( $this->_mbenc );
+ }
+
+ /// connect to searchd server
+ function _Connect ()
+ {
+ if ( $this->_socket!==false )
+ {
+ // we are in persistent connection mode, so we have a socket
+ // however, need to check whether it's still alive
+ if ( !@feof ( $this->_socket ) )
+ return $this->_socket;
+
+ // force reopen
+ $this->_socket = false;
+ }
+
+ $errno = 0;
+ $errstr = "";
+ $this->_connerror = false;
+
+ if ( $this->_path )
+ {
+ $host = $this->_path;
+ $port = 0;
+ }
+ else
+ {
+ $host = $this->_host;
+ $port = $this->_port;
+ }
+
+ if ( $this->_timeout<=0 )
+ $fp = @fsockopen ( $host, $port, $errno, $errstr );
+ else
+ $fp = @fsockopen ( $host, $port, $errno, $errstr, $this->_timeout );
+
+ if ( !$fp )
+ {
+ if ( $this->_path )
+ $location = $this->_path;
+ else
+ $location = "{$this->_host}:{$this->_port}";
+
+ $errstr = trim ( $errstr );
+ $this->_error = "connection to $location failed (errno=$errno, msg=$errstr)";
+ $this->_connerror = true;
+ return false;
+ }
+
+ // send my version
+ // this is a subtle part. we must do it before (!) reading back from searchd.
+ // because otherwise under some conditions (reported on FreeBSD for instance)
+ // TCP stack could throttle write-write-read pattern because of Nagle.
+ if ( !$this->_Send ( $fp, pack ( "N", 1 ), 4 ) )
+ {
+ fclose ( $fp );
+ $this->_error = "failed to send client protocol version";
+ return false;
+ }
+
+ // check version
+ list(,$v) = unpack ( "N*", fread ( $fp, 4 ) );
+ $v = (int)$v;
+ if ( $v<1 )
+ {
+ fclose ( $fp );
+ $this->_error = "expected searchd protocol version 1+, got version '$v'";
+ return false;
+ }
+
+ return $fp;
+ }
+
+ /// get and check response packet from searchd server
+ function _GetResponse ( $fp, $client_ver )
+ {
+ $response = "";
+ $len = 0;
+
+ $header = fread ( $fp, 8 );
+ if ( strlen($header)==8 )
+ {
+ list ( $status, $ver, $len ) = array_values ( unpack ( "n2a/Nb", $header ) );
+ $left = $len;
+ while ( $left>0 && !feof($fp) )
+ {
+ $chunk = fread ( $fp, $left );
+ if ( $chunk )
+ {
+ $response .= $chunk;
+ $left -= strlen($chunk);
+ }
+ }
+ }
+ if ( $this->_socket === false )
+ fclose ( $fp );
+
+ // check response
+ $read = strlen ( $response );
+ if ( !$response || $read!=$len )
+ {
+ $this->_error = $len
+ ? "failed to read searchd response (status=$status, ver=$ver, len=$len, read=$read)"
+ : "received zero-sized searchd response";
+ return false;
+ }
+
+ // check status
+ if ( $status==SEARCHD_WARNING )
+ {
+ list(,$wlen) = unpack ( "N*", substr ( $response, 0, 4 ) );
+ $this->_warning = substr ( $response, 4, $wlen );
+ return substr ( $response, 4+$wlen );
+ }
+ if ( $status==SEARCHD_ERROR )
+ {
+ $this->_error = "searchd error: " . substr ( $response, 4 );
+ return false;
+ }
+ if ( $status==SEARCHD_RETRY )
+ {
+ $this->_error = "temporary searchd error: " . substr ( $response, 4 );
+ return false;
+ }
+ if ( $status!=SEARCHD_OK )
+ {
+ $this->_error = "unknown status code '$status'";
+ return false;
+ }
+
+ // check version
+ if ( $ver<$client_ver )
+ {
+ $this->_warning = sprintf ( "searchd command v.%d.%d older than client's v.%d.%d, some options might not work",
+ $ver>>8, $ver&0xff, $client_ver>>8, $client_ver&0xff );
+ }
+
+ return $response;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ // searching
+ /////////////////////////////////////////////////////////////////////////////
+
+ /// set offset and count into result set,
+ /// and optionally set max-matches and cutoff limits
+ function SetLimits ( $offset, $limit, $max=0, $cutoff=0 )
+ {
+ assert ( is_int($offset) );
+ assert ( is_int($limit) );
+ assert ( $offset>=0 );
+ assert ( $limit>0 );
+ assert ( $max>=0 );
+ $this->_offset = $offset;
+ $this->_limit = $limit;
+ if ( $max>0 )
+ $this->_maxmatches = $max;
+ if ( $cutoff>0 )
+ $this->_cutoff = $cutoff;
+ }
+
+ /// set maximum query time, in milliseconds, per-index
+ /// integer, 0 means "do not limit"
+ function SetMaxQueryTime ( $max )
+ {
+ assert ( is_int($max) );
+ assert ( $max>=0 );
+ $this->_maxquerytime = $max;
+ }
+
+ /// set matching mode
+ function SetMatchMode ( $mode )
+ {
+ assert ( $mode==SPH_MATCH_ALL
+ || $mode==SPH_MATCH_ANY
+ || $mode==SPH_MATCH_PHRASE
+ || $mode==SPH_MATCH_BOOLEAN
+ || $mode==SPH_MATCH_EXTENDED
+ || $mode==SPH_MATCH_FULLSCAN
+ || $mode==SPH_MATCH_EXTENDED2 );
+ $this->_mode = $mode;
+ }
+
+ /// set ranking mode
+ function SetRankingMode ( $ranker )
+ {
+ assert ( $ranker>=0 && $ranker<SPH_RANK_TOTAL );
+ $this->_ranker = $ranker;
+ }
+
+ /// set matches sorting mode
+ function SetSortMode ( $mode, $sortby="" )
+ {
+ assert (
+ $mode==SPH_SORT_RELEVANCE ||
+ $mode==SPH_SORT_ATTR_DESC ||
+ $mode==SPH_SORT_ATTR_ASC ||
+ $mode==SPH_SORT_TIME_SEGMENTS ||
+ $mode==SPH_SORT_EXTENDED ||
+ $mode==SPH_SORT_EXPR );
+ assert ( is_string($sortby) );
+ assert ( $mode==SPH_SORT_RELEVANCE || strlen($sortby)>0 );
+
+ $this->_sort = $mode;
+ $this->_sortby = $sortby;
+ }
+
+ /// bind per-field weights by order
+ /// DEPRECATED; use SetFieldWeights() instead
+ function SetWeights ( $weights )
+ {
+ assert ( is_array($weights) );
+ foreach ( $weights as $weight )
+ assert ( is_int($weight) );
+
+ $this->_weights = $weights;
+ }
+
+ /// bind per-field weights by name
+ function SetFieldWeights ( $weights )
+ {
+ assert ( is_array($weights) );
+ foreach ( $weights as $name=>$weight )
+ {
+ assert ( is_string($name) );
+ assert ( is_int($weight) );
+ }
+ $this->_fieldweights = $weights;
+ }
+
+ /// bind per-index weights by name
+ function SetIndexWeights ( $weights )
+ {
+ assert ( is_array($weights) );
+ foreach ( $weights as $index=>$weight )
+ {
+ assert ( is_string($index) );
+ assert ( is_int($weight) );
+ }
+ $this->_indexweights = $weights;
+ }
+
+ /// set IDs range to match
+ /// only match records if document ID is beetwen $min and $max (inclusive)
+ function SetIDRange ( $min, $max )
+ {
+ assert ( is_numeric($min) );
+ assert ( is_numeric($max) );
+ assert ( $min<=$max );
+ $this->_min_id = $min;
+ $this->_max_id = $max;
+ }
+
+ /// set values set filter
+ /// only match records where $attribute value is in given set
+ function SetFilter ( $attribute, $values, $exclude=false )
+ {
+ assert ( is_string($attribute) );
+ assert ( is_array($values) );
+ assert ( count($values) );
+
+ if ( is_array($values) && count($values) )
+ {
+ foreach ( $values as $value )
+ assert ( is_numeric($value) );
+
+ $this->_filters[] = array ( "type"=>SPH_FILTER_VALUES, "attr"=>$attribute, "exclude"=>$exclude, "values"=>$values );
+ }
+ }
+
+ /// set range filter
+ /// only match records if $attribute value is beetwen $min and $max (inclusive)
+ function SetFilterRange ( $attribute, $min, $max, $exclude=false )
+ {
+ assert ( is_string($attribute) );
+ assert ( is_numeric($min) );
+ assert ( is_numeric($max) );
+ assert ( $min<=$max );
+
+ $this->_filters[] = array ( "type"=>SPH_FILTER_RANGE, "attr"=>$attribute, "exclude"=>$exclude, "min"=>$min, "max"=>$max );
+ }
+
+ /// set float range filter
+ /// only match records if $attribute value is beetwen $min and $max (inclusive)
+ function SetFilterFloatRange ( $attribute, $min, $max, $exclude=false )
+ {
+ assert ( is_string($attribute) );
+ assert ( is_float($min) );
+ assert ( is_float($max) );
+ assert ( $min<=$max );
+
+ $this->_filters[] = array ( "type"=>SPH_FILTER_FLOATRANGE, "attr"=>$attribute, "exclude"=>$exclude, "min"=>$min, "max"=>$max );
+ }
+
+ /// setup anchor point for geosphere distance calculations
+ /// required to use @geodist in filters and sorting
+ /// latitude and longitude must be in radians
+ function SetGeoAnchor ( $attrlat, $attrlong, $lat, $long )
+ {
+ assert ( is_string($attrlat) );
+ assert ( is_string($attrlong) );
+ assert ( is_float($lat) );
+ assert ( is_float($long) );
+
+ $this->_anchor = array ( "attrlat"=>$attrlat, "attrlong"=>$attrlong, "lat"=>$lat, "long"=>$long );
+ }
+
+ /// set grouping attribute and function
+ function SetGroupBy ( $attribute, $func, $groupsort="@group desc" )
+ {
+ assert ( is_string($attribute) );
+ assert ( is_string($groupsort) );
+ assert ( $func==SPH_GROUPBY_DAY
+ || $func==SPH_GROUPBY_WEEK
+ || $func==SPH_GROUPBY_MONTH
+ || $func==SPH_GROUPBY_YEAR
+ || $func==SPH_GROUPBY_ATTR
+ || $func==SPH_GROUPBY_ATTRPAIR );
+
+ $this->_groupby = $attribute;
+ $this->_groupfunc = $func;
+ $this->_groupsort = $groupsort;
+ }
+
+ /// set count-distinct attribute for group-by queries
+ function SetGroupDistinct ( $attribute )
+ {
+ assert ( is_string($attribute) );
+ $this->_groupdistinct = $attribute;
+ }
+
+ /// set distributed retries count and delay
+ function SetRetries ( $count, $delay=0 )
+ {
+ assert ( is_int($count) && $count>=0 );
+ assert ( is_int($delay) && $delay>=0 );
+ $this->_retrycount = $count;
+ $this->_retrydelay = $delay;
+ }
+
+ /// set result set format (hash or array; hash by default)
+ /// PHP specific; needed for group-by-MVA result sets that may contain duplicate IDs
+ function SetArrayResult ( $arrayresult )
+ {
+ assert ( is_bool($arrayresult) );
+ $this->_arrayresult = $arrayresult;
+ }
+
+ /// set attribute values override
+ /// there can be only one override per attribute
+ /// $values must be a hash that maps document IDs to attribute values
+ function SetOverride ( $attrname, $attrtype, $values )
+ {
+ assert ( is_string ( $attrname ) );
+ assert ( in_array ( $attrtype, array ( SPH_ATTR_INTEGER, SPH_ATTR_TIMESTAMP, SPH_ATTR_BOOL, SPH_ATTR_FLOAT, SPH_ATTR_BIGINT ) ) );
+ assert ( is_array ( $values ) );
+
+ $this->_overrides[$attrname] = array ( "attr"=>$attrname, "type"=>$attrtype, "values"=>$values );
+ }
+
+ /// set select-list (attributes or expressions), SQL-like syntax
+ function SetSelect ( $select )
+ {
+ assert ( is_string ( $select ) );
+ $this->_select = $select;
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ /// clear all filters (for multi-queries)
+ function ResetFilters ()
+ {
+ $this->_filters = array();
+ $this->_anchor = array();
+ }
+
+ /// clear groupby settings (for multi-queries)
+ function ResetGroupBy ()
+ {
+ $this->_groupby = "";
+ $this->_groupfunc = SPH_GROUPBY_DAY;
+ $this->_groupsort = "@group desc";
+ $this->_groupdistinct= "";
+ }
+
+ /// clear all attribute value overrides (for multi-queries)
+ function ResetOverrides ()
+ {
+ $this->_overrides = array ();
+ }
+
+ //////////////////////////////////////////////////////////////////////////////
+
+ /// connect to searchd server, run given search query through given indexes,
+ /// and return the search results
+ function Query ( $query, $index="*", $comment="" )
+ {
+ assert ( empty($this->_reqs) );
+
+ $this->AddQuery ( $query, $index, $comment );
+ $results = $this->RunQueries ();
+ $this->_reqs = array (); // just in case it failed too early
+
+ if ( !is_array($results) )
+ return false; // probably network error; error message should be already filled
+
+ $this->_error = $results[0]["error"];
+ $this->_warning = $results[0]["warning"];
+ if ( $results[0]["status"]==SEARCHD_ERROR )
+ return false;
+ else
+ return $results[0];
+ }
+
+ /// helper to pack floats in network byte order
+ function _PackFloat ( $f )
+ {
+ $t1 = pack ( "f", $f ); // machine order
+ list(,$t2) = unpack ( "L*", $t1 ); // int in machine order
+ return pack ( "N", $t2 );
+ }
+
+ /// add query to multi-query batch
+ /// returns index into results array from RunQueries() call
+ function AddQuery ( $query, $index="*", $comment="" )
+ {
+ // mbstring workaround
+ $this->_MBPush ();
+
+ // build request
+ $req = pack ( "NNNNN", $this->_offset, $this->_limit, $this->_mode, $this->_ranker, $this->_sort ); // mode and limits
+ $req .= pack ( "N", strlen($this->_sortby) ) . $this->_sortby;
+ $req .= pack ( "N", strlen($query) ) . $query; // query itself
+ $req .= pack ( "N", count($this->_weights) ); // weights
+ foreach ( $this->_weights as $weight )
+ $req .= pack ( "N", (int)$weight );
+ $req .= pack ( "N", strlen($index) ) . $index; // indexes
+ $req .= pack ( "N", 1 ); // id64 range marker
+ $req .= sphPackU64 ( $this->_min_id ) . sphPackU64 ( $this->_max_id ); // id64 range
+
+ // filters
+ $req .= pack ( "N", count($this->_filters) );
+ foreach ( $this->_filters as $filter )
+ {
+ $req .= pack ( "N", strlen($filter["attr"]) ) . $filter["attr"];
+ $req .= pack ( "N", $filter["type"] );
+ switch ( $filter["type"] )
+ {
+ case SPH_FILTER_VALUES:
+ $req .= pack ( "N", count($filter["values"]) );
+ foreach ( $filter["values"] as $value )
+ $req .= sphPackI64 ( $value );
+ break;
+
+ case SPH_FILTER_RANGE:
+ $req .= sphPackI64 ( $filter["min"] ) . sphPackI64 ( $filter["max"] );
+ break;
+
+ case SPH_FILTER_FLOATRANGE:
+ $req .= $this->_PackFloat ( $filter["min"] ) . $this->_PackFloat ( $filter["max"] );
+ break;
+
+ default:
+ assert ( 0 && "internal error: unhandled filter type" );
+ }
+ $req .= pack ( "N", $filter["exclude"] );
+ }
+
+ // group-by clause, max-matches count, group-sort clause, cutoff count
+ $req .= pack ( "NN", $this->_groupfunc, strlen($this->_groupby) ) . $this->_groupby;
+ $req .= pack ( "N", $this->_maxmatches );
+ $req .= pack ( "N", strlen($this->_groupsort) ) . $this->_groupsort;
+ $req .= pack ( "NNN", $this->_cutoff, $this->_retrycount, $this->_retrydelay );
+ $req .= pack ( "N", strlen($this->_groupdistinct) ) . $this->_groupdistinct;
+
+ // anchor point
+ if ( empty($this->_anchor) )
+ {
+ $req .= pack ( "N", 0 );
+ } else
+ {
+ $a =& $this->_anchor;
+ $req .= pack ( "N", 1 );
+ $req .= pack ( "N", strlen($a["attrlat"]) ) . $a["attrlat"];
+ $req .= pack ( "N", strlen($a["attrlong"]) ) . $a["attrlong"];
+ $req .= $this->_PackFloat ( $a["lat"] ) . $this->_PackFloat ( $a["long"] );
+ }
+
+ // per-index weights
+ $req .= pack ( "N", count($this->_indexweights) );
+ foreach ( $this->_indexweights as $idx=>$weight )
+ $req .= pack ( "N", strlen($idx) ) . $idx . pack ( "N", $weight );
+
+ // max query time
+ $req .= pack ( "N", $this->_maxquerytime );
+
+ // per-field weights
+ $req .= pack ( "N", count($this->_fieldweights) );
+ foreach ( $this->_fieldweights as $field=>$weight )
+ $req .= pack ( "N", strlen($field) ) . $field . pack ( "N", $weight );
+
+ // comment
+ $req .= pack ( "N", strlen($comment) ) . $comment;
+
+ // attribute overrides
+ $req .= pack ( "N", count($this->_overrides) );
+ foreach ( $this->_overrides as $key => $entry )
+ {
+ $req .= pack ( "N", strlen($entry["attr"]) ) . $entry["attr"];
+ $req .= pack ( "NN", $entry["type"], count($entry["values"]) );
+ foreach ( $entry["values"] as $id=>$val )
+ {
+ assert ( is_numeric($id) );
+ assert ( is_numeric($val) );
+
+ $req .= sphPackU64 ( $id );
+ switch ( $entry["type"] )
+ {
+ case SPH_ATTR_FLOAT: $req .= $this->_PackFloat ( $val ); break;
+ case SPH_ATTR_BIGINT: $req .= sphPackI64 ( $val ); break;
+ default: $req .= pack ( "N", $val ); break;
+ }
+ }
+ }
+
+ // select-list
+ $req .= pack ( "N", strlen($this->_select) ) . $this->_select;
+
+ // mbstring workaround
+ $this->_MBPop ();
+
+ // store request to requests array
+ $this->_reqs[] = $req;
+ return count($this->_reqs)-1;
+ }
+
+ /// connect to searchd, run queries batch, and return an array of result sets
+ function RunQueries ()
+ {
+ if ( empty($this->_reqs) )
+ {
+ $this->_error = "no queries defined, issue AddQuery() first";
+ return false;
+ }
+
+ // mbstring workaround
+ $this->_MBPush ();
+
+ if (!( $fp = $this->_Connect() ))
+ {
+ $this->_MBPop ();
+ return false;
+ }
+
+ // send query, get response
+ $nreqs = count($this->_reqs);
+ $req = join ( "", $this->_reqs );
+ $len = 4+strlen($req);
+ $req = pack ( "nnNN", SEARCHD_COMMAND_SEARCH, VER_COMMAND_SEARCH, $len, $nreqs ) . $req; // add header
+
+ if ( !( $this->_Send ( $fp, $req, $len+8 ) ) ||
+ !( $response = $this->_GetResponse ( $fp, VER_COMMAND_SEARCH ) ) )
+ {
+ $this->_MBPop ();
+ return false;
+ }
+
+ // query sent ok; we can reset reqs now
+ $this->_reqs = array ();
+
+ // parse and return response
+ return $this->_ParseSearchResponse ( $response, $nreqs );
+ }
+
+ /// parse and return search query (or queries) response
+ function _ParseSearchResponse ( $response, $nreqs )
+ {
+ $p = 0; // current position
+ $max = strlen($response); // max position for checks, to protect against broken responses
+
+ $results = array ();
+ for ( $ires=0; $ires<$nreqs && $p<$max; $ires++ )
+ {
+ $results[] = array();
+ $result =& $results[$ires];
+
+ $result["error"] = "";
+ $result["warning"] = "";
+
+ // extract status
+ list(,$status) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
+ $result["status"] = $status;
+ if ( $status!=SEARCHD_OK )
+ {
+ list(,$len) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
+ $message = substr ( $response, $p, $len ); $p += $len;
+
+ if ( $status==SEARCHD_WARNING )
+ {
+ $result["warning"] = $message;
+ } else
+ {
+ $result["error"] = $message;
+ continue;
+ }
+ }
+
+ // read schema
+ $fields = array ();
+ $attrs = array ();
+
+ list(,$nfields) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
+ while ( $nfields-->0 && $p<$max )
+ {
+ list(,$len) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
+ $fields[] = substr ( $response, $p, $len ); $p += $len;
+ }
+ $result["fields"] = $fields;
+
+ list(,$nattrs) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
+ while ( $nattrs-->0 && $p<$max )
+ {
+ list(,$len) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
+ $attr = substr ( $response, $p, $len ); $p += $len;
+ list(,$type) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
+ $attrs[$attr] = $type;
+ }
+ $result["attrs"] = $attrs;
+
+ // read match count
+ list(,$count) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
+ list(,$id64) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
+
+ // read matches
+ $idx = -1;
+ while ( $count-->0 && $p<$max )
+ {
+ // index into result array
+ $idx++;
+
+ // parse document id and weight
+ if ( $id64 )
+ {
+ $doc = sphUnpackU64 ( substr ( $response, $p, 8 ) ); $p += 8;
+ list(,$weight) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
+ }
+ else
+ {
+ list ( $doc, $weight ) = array_values ( unpack ( "N*N*",
+ substr ( $response, $p, 8 ) ) );
+ $p += 8;
+ $doc = sphFixUint($doc);
+ }
+ $weight = sprintf ( "%u", $weight );
+
+ // create match entry
+ if ( $this->_arrayresult )
+ $result["matches"][$idx] = array ( "id"=>$doc, "weight"=>$weight );
+ else
+ $result["matches"][$doc]["weight"] = $weight;
+
+ // parse and create attributes
+ $attrvals = array ();
+ foreach ( $attrs as $attr=>$type )
+ {
+ // handle 64bit ints
+ if ( $type==SPH_ATTR_BIGINT )
+ {
+ $attrvals[$attr] = sphUnpackI64 ( substr ( $response, $p, 8 ) ); $p += 8;
+ continue;
+ }
+
+ // handle floats
+ if ( $type==SPH_ATTR_FLOAT )
+ {
+ list(,$uval) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
+ list(,$fval) = unpack ( "f*", pack ( "L", $uval ) );
+ $attrvals[$attr] = $fval;
+ continue;
+ }
+
+ // handle everything else as unsigned ints
+ list(,$val) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
+ if ( $type & SPH_ATTR_MULTI )
+ {
+ $attrvals[$attr] = array ();
+ $nvalues = $val;
+ while ( $nvalues-->0 && $p<$max )
+ {
+ list(,$val) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
+ $attrvals[$attr][] = sphFixUint($val);
+ }
+ } else if ( $type==SPH_ATTR_STRING )
+ {
+ $attrvals[$attr] = substr ( $response, $p, $val );
+ $p += $val;
+ } else
+ {
+ $attrvals[$attr] = sphFixUint($val);
+ }
+ }
+
+ if ( $this->_arrayresult )
+ $result["matches"][$idx]["attrs"] = $attrvals;
+ else
+ $result["matches"][$doc]["attrs"] = $attrvals;
+ }
+
+ list ( $total, $total_found, $msecs, $words ) =
+ array_values ( unpack ( "N*N*N*N*", substr ( $response, $p, 16 ) ) );
+ $result["total"] = sprintf ( "%u", $total );
+ $result["total_found"] = sprintf ( "%u", $total_found );
+ $result["time"] = sprintf ( "%.3f", $msecs/1000 );
+ $p += 16;
+
+ while ( $words-->0 && $p<$max )
+ {
+ list(,$len) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
+ $word = substr ( $response, $p, $len ); $p += $len;
+ list ( $docs, $hits ) = array_values ( unpack ( "N*N*", substr ( $response, $p, 8 ) ) ); $p += 8;
+ $result["words"][$word] = array (
+ "docs"=>sprintf ( "%u", $docs ),
+ "hits"=>sprintf ( "%u", $hits ) );
+ }
+ }
+
+ $this->_MBPop ();
+ return $results;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ // excerpts generation
+ /////////////////////////////////////////////////////////////////////////////
+
+ /// connect to searchd server, and generate exceprts (snippets)
+ /// of given documents for given query. returns false on failure,
+ /// an array of snippets on success
+ function BuildExcerpts ( $docs, $index, $words, $opts=array() )
+ {
+ assert ( is_array($docs) );
+ assert ( is_string($index) );
+ assert ( is_string($words) );
+ assert ( is_array($opts) );
+
+ $this->_MBPush ();
+
+ if (!( $fp = $this->_Connect() ))
+ {
+ $this->_MBPop();
+ return false;
+ }
+
+ /////////////////
+ // fixup options
+ /////////////////
+
+ if ( !isset($opts["before_match"]) ) $opts["before_match"] = "<b>";
+ if ( !isset($opts["after_match"]) ) $opts["after_match"] = "</b>";
+ if ( !isset($opts["chunk_separator"]) ) $opts["chunk_separator"] = " ... ";
+ if ( !isset($opts["limit"]) ) $opts["limit"] = 256;
+ if ( !isset($opts["limit_passages"]) ) $opts["limit_passages"] = 0;
+ if ( !isset($opts["limit_words"]) ) $opts["limit_words"] = 0;
+ if ( !isset($opts["around"]) ) $opts["around"] = 5;
+ if ( !isset($opts["exact_phrase"]) ) $opts["exact_phrase"] = false;
+ if ( !isset($opts["single_passage"]) ) $opts["single_passage"] = false;
+ if ( !isset($opts["use_boundaries"]) ) $opts["use_boundaries"] = false;
+ if ( !isset($opts["weight_order"]) ) $opts["weight_order"] = false;
+ if ( !isset($opts["query_mode"]) ) $opts["query_mode"] = false;
+ if ( !isset($opts["force_all_words"]) ) $opts["force_all_words"] = false;
+ if ( !isset($opts["start_passage_id"]) ) $opts["start_passage_id"] = 1;
+ if ( !isset($opts["load_files"]) ) $opts["load_files"] = false;
+ if ( !isset($opts["html_strip_mode"]) ) $opts["html_strip_mode"] = "index";
+ if ( !isset($opts["allow_empty"]) ) $opts["allow_empty"] = false;
+
+ /////////////////
+ // build request
+ /////////////////
+
+ // v.1.2 req
+ $flags = 1; // remove spaces
+ if ( $opts["exact_phrase"] ) $flags |= 2;
+ if ( $opts["single_passage"] ) $flags |= 4;
+ if ( $opts["use_boundaries"] ) $flags |= 8;
+ if ( $opts["weight_order"] ) $flags |= 16;
+ if ( $opts["query_mode"] ) $flags |= 32;
+ if ( $opts["force_all_words"] ) $flags |= 64;
+ if ( $opts["load_files"] ) $flags |= 128;
+ if ( $opts["allow_empty"] ) $flags |= 256;
+ $req = pack ( "NN", 0, $flags ); // mode=0, flags=$flags
+ $req .= pack ( "N", strlen($index) ) . $index; // req index
+ $req .= pack ( "N", strlen($words) ) . $words; // req words
+
+ // options
+ $req .= pack ( "N", strlen($opts["before_match"]) ) . $opts["before_match"];
+ $req .= pack ( "N", strlen($opts["after_match"]) ) . $opts["after_match"];
+ $req .= pack ( "N", strlen($opts["chunk_separator"]) ) . $opts["chunk_separator"];
+ $req .= pack ( "NN", (int)$opts["limit"], (int)$opts["around"] );
+ $req .= pack ( "NNN", (int)$opts["limit_passages"], (int)$opts["limit_words"], (int)$opts["start_passage_id"] ); // v.1.2
+ $req .= pack ( "N", strlen($opts["html_strip_mode"]) ) . $opts["html_strip_mode"];
+
+ // documents
+ $req .= pack ( "N", count($docs) );
+ foreach ( $docs as $doc )
+ {
+ assert ( is_string($doc) );
+ $req .= pack ( "N", strlen($doc) ) . $doc;
+ }
+
+ ////////////////////////////
+ // send query, get response
+ ////////////////////////////
+
+ $len = strlen($req);
+ $req = pack ( "nnN", SEARCHD_COMMAND_EXCERPT, VER_COMMAND_EXCERPT, $len ) . $req; // add header
+ if ( !( $this->_Send ( $fp, $req, $len+8 ) ) ||
+ !( $response = $this->_GetResponse ( $fp, VER_COMMAND_EXCERPT ) ) )
+ {
+ $this->_MBPop ();
+ return false;
+ }
+
+ //////////////////
+ // parse response
+ //////////////////
+
+ $pos = 0;
+ $res = array ();
+ $rlen = strlen($response);
+ for ( $i=0; $i<count($docs); $i++ )
+ {
+ list(,$len) = unpack ( "N*", substr ( $response, $pos, 4 ) );
+ $pos += 4;
+
+ if ( $pos+$len > $rlen )
+ {
+ $this->_error = "incomplete reply";
+ $this->_MBPop ();
+ return false;
+ }
+ $res[] = $len ? substr ( $response, $pos, $len ) : "";
+ $pos += $len;
+ }
+
+ $this->_MBPop ();
+ return $res;
+ }
+
+
+ /////////////////////////////////////////////////////////////////////////////
+ // keyword generation
+ /////////////////////////////////////////////////////////////////////////////
+
+ /// connect to searchd server, and generate keyword list for a given query
+ /// returns false on failure,
+ /// an array of words on success
+ function BuildKeywords ( $query, $index, $hits )
+ {
+ assert ( is_string($query) );
+ assert ( is_string($index) );
+ assert ( is_bool($hits) );
+
+ $this->_MBPush ();
+
+ if (!( $fp = $this->_Connect() ))
+ {
+ $this->_MBPop();
+ return false;
+ }
+
+ /////////////////
+ // build request
+ /////////////////
+
+ // v.1.0 req
+ $req = pack ( "N", strlen($query) ) . $query; // req query
+ $req .= pack ( "N", strlen($index) ) . $index; // req index
+ $req .= pack ( "N", (int)$hits );
+
+ ////////////////////////////
+ // send query, get response
+ ////////////////////////////
+
+ $len = strlen($req);
+ $req = pack ( "nnN", SEARCHD_COMMAND_KEYWORDS, VER_COMMAND_KEYWORDS, $len ) . $req; // add header
+ if ( !( $this->_Send ( $fp, $req, $len+8 ) ) ||
+ !( $response = $this->_GetResponse ( $fp, VER_COMMAND_KEYWORDS ) ) )
+ {
+ $this->_MBPop ();
+ return false;
+ }
+
+ //////////////////
+ // parse response
+ //////////////////
+
+ $pos = 0;
+ $res = array ();
+ $rlen = strlen($response);
+ list(,$nwords) = unpack ( "N*", substr ( $response, $pos, 4 ) );
+ $pos += 4;
+ for ( $i=0; $i<$nwords; $i++ )
+ {
+ list(,$len) = unpack ( "N*", substr ( $response, $pos, 4 ) ); $pos += 4;
+ $tokenized = $len ? substr ( $response, $pos, $len ) : "";
+ $pos += $len;
+
+ list(,$len) = unpack ( "N*", substr ( $response, $pos, 4 ) ); $pos += 4;
+ $normalized = $len ? substr ( $response, $pos, $len ) : "";
+ $pos += $len;
+
+ $res[] = array ( "tokenized"=>$tokenized, "normalized"=>$normalized );
+
+ if ( $hits )
+ {
+ list($ndocs,$nhits) = array_values ( unpack ( "N*N*", substr ( $response, $pos, 8 ) ) );
+ $pos += 8;
+ $res [$i]["docs"] = $ndocs;
+ $res [$i]["hits"] = $nhits;
+ }
+
+ if ( $pos > $rlen )
+ {
+ $this->_error = "incomplete reply";
+ $this->_MBPop ();
+ return false;
+ }
+ }
+
+ $this->_MBPop ();
+ return $res;
+ }
+
+ function EscapeString ( $string )
+ {
+ $from = array ( '\\', '(',')','|','-','!','@','~','"','&', '/', '^', '$', '=' );
+ $to = array ( '\\\\', '\(','\)','\|','\-','\!','\@','\~','\"', '\&', '\/', '\^', '\$', '\=' );
+
+ return str_replace ( $from, $to, $string );
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ // attribute updates
+ /////////////////////////////////////////////////////////////////////////////
+
+ /// batch update given attributes in given rows in given indexes
+ /// returns amount of updated documents (0 or more) on success, or -1 on failure
+ function UpdateAttributes ( $index, $attrs, $values, $mva=false )
+ {
+ // verify everything
+ assert ( is_string($index) );
+ assert ( is_bool($mva) );
+
+ assert ( is_array($attrs) );
+ foreach ( $attrs as $attr )
+ assert ( is_string($attr) );
+
+ assert ( is_array($values) );
+ foreach ( $values as $id=>$entry )
+ {
+ assert ( is_numeric($id) );
+ assert ( is_array($entry) );
+ assert ( count($entry)==count($attrs) );
+ foreach ( $entry as $v )
+ {
+ if ( $mva )
+ {
+ assert ( is_array($v) );
+ foreach ( $v as $vv )
+ assert ( is_int($vv) );
+ } else
+ assert ( is_int($v) );
+ }
+ }
+
+ // build request
+ $this->_MBPush ();
+ $req = pack ( "N", strlen($index) ) . $index;
+
+ $req .= pack ( "N", count($attrs) );
+ foreach ( $attrs as $attr )
+ {
+ $req .= pack ( "N", strlen($attr) ) . $attr;
+ $req .= pack ( "N", $mva ? 1 : 0 );
+ }
+
+ $req .= pack ( "N", count($values) );
+ foreach ( $values as $id=>$entry )
+ {
+ $req .= sphPackU64 ( $id );
+ foreach ( $entry as $v )
+ {
+ $req .= pack ( "N", $mva ? count($v) : $v );
+ if ( $mva )
+ foreach ( $v as $vv )
+ $req .= pack ( "N", $vv );
+ }
+ }
+
+ // connect, send query, get response
+ if (!( $fp = $this->_Connect() ))
+ {
+ $this->_MBPop ();
+ return -1;
+ }
+
+ $len = strlen($req);
+ $req = pack ( "nnN", SEARCHD_COMMAND_UPDATE, VER_COMMAND_UPDATE, $len ) . $req; // add header
+ if ( !$this->_Send ( $fp, $req, $len+8 ) )
+ {
+ $this->_MBPop ();
+ return -1;
+ }
+
+ if (!( $response = $this->_GetResponse ( $fp, VER_COMMAND_UPDATE ) ))
+ {
+ $this->_MBPop ();
+ return -1;
+ }
+
+ // parse response
+ list(,$updated) = unpack ( "N*", substr ( $response, 0, 4 ) );
+ $this->_MBPop ();
+ return $updated;
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ // persistent connections
+ /////////////////////////////////////////////////////////////////////////////
+
+ function Open()
+ {
+ if ( $this->_socket !== false )
+ {
+ $this->_error = 'already connected';
+ return false;
+ }
+ if ( !$fp = $this->_Connect() )
+ return false;
+
+ // command, command version = 0, body length = 4, body = 1
+ $req = pack ( "nnNN", SEARCHD_COMMAND_PERSIST, 0, 4, 1 );
+ if ( !$this->_Send ( $fp, $req, 12 ) )
+ return false;
+
+ $this->_socket = $fp;
+ return true;
+ }
+
+ function Close()
+ {
+ if ( $this->_socket === false )
+ {
+ $this->_error = 'not connected';
+ return false;
+ }
+
+ fclose ( $this->_socket );
+ $this->_socket = false;
+
+ return true;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // status
+ //////////////////////////////////////////////////////////////////////////
+
+ function Status ()
+ {
+ $this->_MBPush ();
+ if (!( $fp = $this->_Connect() ))
+ {
+ $this->_MBPop();
+ return false;
+ }
+
+ $req = pack ( "nnNN", SEARCHD_COMMAND_STATUS, VER_COMMAND_STATUS, 4, 1 ); // len=4, body=1
+ if ( !( $this->_Send ( $fp, $req, 12 ) ) ||
+ !( $response = $this->_GetResponse ( $fp, VER_COMMAND_STATUS ) ) )
+ {
+ $this->_MBPop ();
+ return false;
+ }
+
+ $res = substr ( $response, 4 ); // just ignore length, error handling, etc
+ $p = 0;
+ list ( $rows, $cols ) = array_values ( unpack ( "N*N*", substr ( $response, $p, 8 ) ) ); $p += 8;
+
+ $res = array();
+ for ( $i=0; $i<$rows; $i++ )
+ for ( $j=0; $j<$cols; $j++ )
+ {
+ list(,$len) = unpack ( "N*", substr ( $response, $p, 4 ) ); $p += 4;
+ $res[$i][] = substr ( $response, $p, $len ); $p += $len;
+ }
+
+ $this->_MBPop ();
+ return $res;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // flush
+ //////////////////////////////////////////////////////////////////////////
+
+ function FlushAttributes ()
+ {
+ $this->_MBPush ();
+ if (!( $fp = $this->_Connect() ))
+ {
+ $this->_MBPop();
+ return -1;
+ }
+
+ $req = pack ( "nnN", SEARCHD_COMMAND_FLUSHATTRS, VER_COMMAND_FLUSHATTRS, 0 ); // len=0
+ if ( !( $this->_Send ( $fp, $req, 8 ) ) ||
+ !( $response = $this->_GetResponse ( $fp, VER_COMMAND_FLUSHATTRS ) ) )
+ {
+ $this->_MBPop ();
+ return -1;
+ }
+
+ $tag = -1;
+ if ( strlen($response)==4 )
+ list(,$tag) = unpack ( "N*", $response );
+ else
+ $this->_error = "unexpected response length";
+
+ $this->_MBPop ();
+ return $tag;
+ }
+}
+
+//
+// $Id: sphinxapi.php 2376 2010-06-29 14:08:19Z shodan $
+//
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/tests/api_0.9.8.php
^
|
@@ -0,0 +1,88 @@
+<?php
+
+date_default_timezone_set('Europe/Moscow');
+
+$cl = new SphinxClient ();
+
+$q = "test";
+$sql = "";
+$mode = SPH_MATCH_ALL;
+$host = "localhost";
+$port = 9312;
+$index = "test1";
+$groupby = "";
+$groupsort = "@group desc";
+$filter = "group_id";
+$filtervals = array();
+$distinct = "";
+$sortby = "";
+$limit = 20;
+$ranker = SPH_RANK_PROXIMITY_BM25;
+
+////////////
+// do query
+////////////
+
+$cl->SetServer ( $host, $port );
+$cl->SetConnectTimeout ( 1 );
+$cl->SetArrayResult ( true );
+$cl->SetFieldWeights ( array ( 100, 1 ) );
+$cl->SetMatchMode ( $mode );
+if ( count($filtervals) ) $cl->SetFilter ( $filter, $filtervals );
+if ( $groupby ) $cl->SetGroupBy ( $groupby, SPH_GROUPBY_ATTR, $groupsort );
+if ( $sortby ) $cl->SetSortMode ( SPH_SORT_EXTENDED, $sortby );
+if ( $sortexpr ) $cl->SetSortMode ( SPH_SORT_EXPR, $sortexpr );
+if ( $distinct ) $cl->SetGroupDistinct ( $distinct );
+if ( $limit ) $cl->SetLimits ( 0, $limit, ( $limit>1000 ) ? $limit : 1000 );
+$cl->SetRankingMode ( $ranker );
+$res = $cl->Query ( $q, $index );
+
+///////////////////////
+// print query results
+///////////////////////
+
+//print_r($res);
+
+if ( $res===false )
+{
+ print "Query failed: " . $cl->GetLastError() . ".\n";
+
+} else
+{
+ if ( $cl->GetLastWarning() )
+ print "WARNING: " . $cl->GetLastWarning() . "\n\n";
+
+ print "Query '$q' retrieved $res[total] of $res[total_found] matches in $res[time] sec.\n";
+ print "Query stats:\n";
+ if ( is_array($res["words"]) )
+ foreach ( $res["words"] as $word => $info )
+ print " '$word' found $info[hits] times in $info[docs] documents\n";
+ print "\n";
+
+ if ( is_array($res["matches"]) )
+ {
+ $n = 1;
+ print "Matches:\n";
+ foreach ( $res["matches"] as $docinfo )
+ {
+ print "$n. doc_id=$docinfo[id], weight=$docinfo[weight]";
+ foreach ( $res["attrs"] as $attrname => $attrtype )
+ {
+ $value = $docinfo["attrs"][$attrname];
+ if ( $attrtype & SPH_ATTR_MULTI )
+ {
+ $value = "(" . join ( ",", $value ) .")";
+ } else
+ {
+ if ( $attrtype==SPH_ATTR_TIMESTAMP )
+ $value = date ( "Y-m-d H:i:s", $value );
+ }
+ print ", $attrname=$value";
+ }
+ print "\n";
+ $n++;
+ }
+ }
+}
+
+
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/tests/api_0.9.9.php
^
|
@@ -0,0 +1,98 @@
+<?php
+
+date_default_timezone_set('Europe/Moscow');
+
+$cl = new SphinxClient ();
+
+$q = "test";
+$sql = "";
+$mode = SPH_MATCH_ALL;
+$host = "localhost";
+$port = 9312;
+$index = "test1";
+$groupby = "";
+$groupsort = "@group desc";
+$filter = "group_id";
+$filtervals = array();
+$distinct = "";
+$sortby = "";
+$limit = 20;
+$ranker = SPH_RANK_PROXIMITY_BM25;
+$select = "group_id,title";
+
+////////////
+// do query
+////////////
+
+/*
+$cl->SetServer ( $host, $port );
+$cl->SetConnectTimeout ( 1 );
+$cl->Open();
+*/
+$cl->SetArrayResult ( true );
+$cl->SetFieldWeights ( array ( 100, 1 ) );
+$cl->SetMatchMode ( $mode );
+
+if ( count($filtervals) ) $cl->SetFilter ( $filter, $filtervals );
+if ( $groupby ) $cl->SetGroupBy ( $groupby, SPH_GROUPBY_ATTR, $groupsort );
+if ( $sortby ) $cl->SetSortMode ( SPH_SORT_EXTENDED, $sortby );
+if ( $sortexpr ) $cl->SetSortMode ( SPH_SORT_EXPR, $sortexpr );
+if ( $distinct ) $cl->SetGroupDistinct ( $distinct );
+if ( $select ) $cl->SetSelect ( $select );
+if ( $limit ) $cl->SetLimits ( 0, $limit, ( $limit>1000 ) ? $limit : 1000 );
+$cl->SetRankingMode ( $ranker );
+$res = $cl->Query ( $q, $index );
+
+///////////////////////
+// print query results
+///////////////////////
+
+//print_r($res);
+
+if ( $res===false )
+{
+ print "Query failed: " . $cl->GetLastError() . ".\n";
+
+} else
+{
+ if ( $cl->GetLastWarning() )
+ print "WARNING: " . $cl->GetLastWarning() . "\n\n";
+
+ print "Query '$q' retrieved $res[total] of $res[total_found] matches in $res[time] sec.\n";
+ print "Query stats:\n";
+ if ( is_array($res["words"]) )
+ foreach ( $res["words"] as $word => $info )
+ print " '$word' found $info[hits] times in $info[docs] documents\n";
+ print "\n";
+
+ if ( is_array($res["matches"]) )
+ {
+ $n = 1;
+ print "Matches:\n";
+ foreach ( $res["matches"] as $docinfo )
+ {
+ print "$n. doc_id=$docinfo[id], weight=$docinfo[weight]";
+ foreach ( $res["attrs"] as $attrname => $attrtype )
+ {
+ $value = $docinfo["attrs"][$attrname];
+ if ( $attrtype & SPH_ATTR_MULTI )
+ {
+ $value = "(" . join ( ",", $value ) .")";
+ } else
+ {
+ if ( $attrtype==SPH_ATTR_TIMESTAMP )
+ $value = date ( "Y-m-d H:i:s", $value );
+ }
+ print ", $attrname=$value";
+ }
+ print "\n";
+ $n++;
+ }
+ }
+}
+$cl->Close();
+print "\n";
+
+
+
+
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/tests/example.sql
^
|
@@ -0,0 +1,30 @@
+DROP TABLE IF EXISTS test.documents;
+CREATE TABLE test.documents
+(
+ id INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT,
+ group_id INTEGER NOT NULL,
+ group_id2 INTEGER NOT NULL,
+ date_added DATETIME NOT NULL,
+ title VARCHAR(255) NOT NULL,
+ content TEXT NOT NULL
+);
+
+REPLACE INTO test.documents ( id, group_id, group_id2, date_added, title, content ) VALUES
+ ( 1, 1, 5, NOW(), 'test one', 'this is my test document number one. also checking search within phrases.' ),
+ ( 2, 1, 6, NOW(), 'test two', 'this is my test document number two' ),
+ ( 3, 2, 7, NOW(), 'another doc', 'this is another group' ),
+ ( 4, 2, 8, NOW(), 'doc number four', 'this is to test groups' );
+
+DROP TABLE IF EXISTS test.tags;
+CREATE TABLE test.tags
+(
+ docid INTEGER NOT NULL,
+ tagid INTEGER NOT NULL,
+ UNIQUE(docid,tagid)
+);
+
+INSERT INTO test.tags VALUES
+ (1,1), (1,3), (1,5), (1,7),
+ (2,6), (2,4), (2,2),
+ (3,15),
+ (4,7), (4,40);
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/tests/pecl_17007.php
^
|
@@ -0,0 +1,7 @@
+<?php
+$sphinx = new SphinxClient();
+$sphinx->setServer('localhost', 3312);
+$sphinx->setMatchMode(SPH_MATCH_EXTENDED2);
+$sphinx->addQuery('test)');
+$results = $sphinx->runQueries();
+var_dump($results);
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/tests/pecl_18635.php
^
|
@@ -0,0 +1,14 @@
+<?php
+$s = new SphinxClient;
+$s->setServer('localhost',9312);
+$s->setMatchMode(SPH_MATCH_ANY);
+$s->setMaxQueryTime(3);
+
+
+$result = $s->query('test');
+var_dump($result);
+
+if ($result === false)
+{
+ print "Query failed: " . $s->GetLastError() . ".\n";
+}
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/tests/sphinx-0.9.9.conf
^
|
@@ -0,0 +1,53 @@
+
+source src1
+{
+ type = mysql
+
+ sql_host = localhost
+ sql_user = test
+ sql_pass =
+ sql_db = test
+ sql_port = 3306 # optional, default is 3306
+
+ sql_query = SELECT id, group_id, group_id2, UNIX_TIMESTAMP(date_added) AS date_added, title, content \
+ FROM documents
+
+ sql_attr_uint = group_id
+ sql_attr_uint = group_id2
+ sql_attr_timestamp = date_added
+ sql_attr_multi = uint mva from query; SELECT docid, tagid FROM tags
+ sql_attr_multi = uint mva2 from query; SELECT docid, tagid FROM tags
+
+ sql_query_info = SELECT * FROM documents WHERE id=$id
+}
+
+
+index test1
+{
+ source = src1
+ path = /tmp/sphinx-0.9.9/var/data/test1
+ docinfo = extern
+ charset_type = sbcs
+}
+
+
+indexer
+{
+ mem_limit = 32M
+}
+
+
+searchd
+{
+ listen = 9312
+ listen = 9306:mysql41
+ log = /tmp/sphinx-0.9.9/var/log/searchd.log
+ query_log = /tmp/sphinx-0.9.9/var/log/query.log
+ read_timeout = 5
+ max_children = 30
+ pid_file = /tmp/sphinx-0.9.9/var/log/searchd.pid
+ max_matches = 1000
+ seamless_rotate = 1
+ preopen_indexes = 0
+ unlink_old = 1
+}
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/tests/sphinx-1.10.conf
^
|
@@ -0,0 +1,69 @@
+
+source src1
+{
+ type = mysql
+
+ sql_host = localhost
+ sql_user = test
+ sql_pass =
+ sql_db = test
+ sql_port = 3306 # optional, default is 3306
+
+ sql_query = SELECT id, group_id, group_id2, UNIX_TIMESTAMP(date_added) AS date_added, title, content \
+ FROM documents
+
+ sql_attr_uint = group_id
+ sql_attr_uint = group_id2
+ sql_attr_timestamp = date_added
+ sql_attr_string = title
+ sql_attr_multi = uint mva from query; SELECT docid, tagid FROM tags
+ sql_attr_multi = uint mva2 from query; SELECT docid, tagid FROM tags
+
+ sql_query_info = SELECT * FROM documents WHERE id=$id
+}
+
+
+index test1
+{
+ source = src1
+ path = /tmp/sphinx-1.10/var/data/test1
+ docinfo = extern
+ charset_type = sbcs
+}
+
+
+index testrt
+{
+ type = rt
+ rt_mem_limit = 32M
+
+ path = /tmp/sphinx-1.10/var/data/testrt
+ charset_type = utf-8
+
+ rt_field = title
+ rt_field = content
+ rt_attr_uint = gid
+}
+
+
+indexer
+{
+ mem_limit = 32M
+}
+
+
+searchd
+{
+ listen = 9312
+ listen = 9306:mysql41
+ log = /tmp/sphinx-1.10/var/log/searchd.log
+ query_log = /tmp/sphinx-1.10/var/log/query.log
+ read_timeout = 5
+ max_children = 30
+ pid_file = /tmp/sphinx-1.10/var/log/searchd.pid
+ max_matches = 1000
+ seamless_rotate = 1
+ preopen_indexes = 0
+ unlink_old = 1
+ workers = threads # for RT to work
+}
|
[-]
[+]
|
Added |
sphinx-1.3.99.1.tgz/tests/test_1.10.php
^
|
@@ -0,0 +1,202 @@
+<?php
+
+require ( "api/sphinxapi-1.10.php" );
+
+function test_query ( $client, $test_extras )
+{
+ $override_docid = 4;
+ $override_value = 456;
+ $query = "test";
+ $index = "test1";
+
+ $client->SetFieldWeights ( array ( 'title' => 100, 'content' => 1 ) );
+
+ if ( $test_extras )
+ {
+ $client->SetOverride ( "group_id", SPH_ATTR_INTEGER, array ( $override_docid => $override_value) );
+ $client->SetSelect ( "*, group_id*1000+@id*10 AS q" );
+ }
+
+ $client->SetArrayResult(true);
+ $res = $client->Query ( $query, $index );
+ if ( $res === false )
+ {
+ print "Query failed: " . $client->GetLastError() . ".\n";
+ }
+ else
+ {
+ if ( $client->GetLastWarning() )
+ print "WARNING: " . $client->GetLastWarning() . "\n\n";
+
+ print "Query '$query' retrieved $res[total] of $res[total_found] matches in $res[time] sec.\n";
+ print "Query stats:\n";
+ if ( is_array($res["words"]) )
+ foreach ( $res["words"] as $word => $info )
+ print " '$word' found $info[hits] times in $info[docs] documents\n";
+ print "\n";
+
+ if ( is_array($res["matches"]) )
+ {
+ $n = 1;
+ print "Matches:\n";
+ foreach ( $res["matches"] as $docinfo )
+ {
+ print "$n. doc_id=$docinfo[id], weight=$docinfo[weight]";
+ foreach ( $res["attrs"] as $attrname => $attrtype )
+ {
+ $value = $docinfo["attrs"][$attrname];
+ if ( $attrtype & SPH_ATTR_MULTI )
+ {
+ $value = "(" . join ( ",", $value ) .")";
+ }
+ else
+ {
+ if ( $attrtype==SPH_ATTR_TIMESTAMP )
+ $value = date ( "Y-m-d H:i:s", $value );
+ }
+ print ", $attrname=$value";
+ }
+ print "\n";
+ $n++;
+ }
+ }
+ }
+ print "\n";
+}
+
+function test_excerpt ( $client )
+{
+ $docs = array
+ (
+ "this is my test text to be highlighted, and for the sake of the testing we need to pump its length somewhat",
+ "another test text to be highlighted, below limit",
+ "test number three, without phrase match",
+ "final test, not only without phrase match, but also above limit and with swapped phrase text test as well"
+ );
+ $words = "test text";
+ $index = "test1";
+ $opts = array
+ (
+ "chunk_separator" => " ... ",
+ "limit" => 60,
+ "around" => 3,
+ );
+
+ for ( $j=0; $j<2; $j++ )
+ {
+ $opts["exact_phrase"] = $j;
+ print "exact_phrase=$j\n" ;
+
+ $res = $client->BuildExcerpts ( $docs, $index, $words, $opts );
+ if ( !$res )
+ {
+ print "query failed: " . $client->GetLastError() . ".\n" ;
+ }
+ else
+ {
+ $n = 0;
+ foreach ( $res as $entry )
+ {
+ $n++;
+ print "n=$n, res=$entry\n";
+ }
+ }
+ print "\n";
+ }
+}
+
+function test_update ( $client )
+{
+ $attrs = array( "group_id" , "group_id2" );
+ $vals = array( 2 => array ( 22, 33 ) , 4 => array ( 444, 555 ) );
+
+ $res = $client->UpdateAttributes( "test1", $attrs, $vals);
+ if ( $res < 0 )
+ print "query failed: " . $client->GetLastError() . ".\n\n";
+ else
+ print "update success, $res rows updated\n\n";
+}
+
+function test_update_mva ( $client )
+{
+ $attrs = array ( "mva" , "mva2" );
+ $vals = array (
+ 1 => array( array ( 123, 456 ) , array ( 321 ) ) ,
+ 2 => array( array ( 78, 910, 11 ) , array ( 87, 12 ) ),
+ 4 => array( array ( 55 ) , array ( 66 , 77 ) )
+ );
+
+ $res = $client->UpdateAttributes( "test1", $attrs, $vals, true );
+ if ( $res === false || $res < 0 )
+ print "query mva failed: " . $client->GetLastError() . ".\n\n";
+ else
+ print "update mva success, $res rows updated\n\n";
+}
+
+function test_keywords ( $client )
+{
+ $words = $client->BuildKeywords("hello test one", "test1", true);
+
+ if ( !$words )
+ {
+ print "build_keywords failed: " . $client->GetLastError() . "\n\n" ;
+ }
+ else
+ {
+ print "build_keywords result:\n";
+
+ $n = 0;
+ foreach ( $words as $entry )
+ {
+ $n++;
+ printf ( "%d. tokenized=%s, normalized=%s, docs=%d, hits=%d\n", $n,
+ $entry['tokenized'], $entry['normalized'],
+ $entry['docs'], $entry['hits'] );
+ }
+ print "\n";
+ }
+}
+
+function test_status ( $client )
+{
+ $status = $client->Status();
+ if ( !$status )
+ {
+ print "status failed: " . $client->GetLastError() . "\n\n";
+ }
+
+ foreach ( $status as $item )
+ {
+ print "$item[0]: $item[1]\n";
+ }
+ print "\n";
+}
+
+date_default_timezone_set('Europe/Moscow');
+
+$host = "localhost";
+$port = 9312;
+
+$client = new SphinxClient ();
+$client->SetServer ( $host, $port );
+
+test_query ( $client, false );
+test_excerpt ( $client );
+test_update ( $client );
+test_update_mva ( $client );
+test_query ( $client, false );
+
+test_keywords ( $client );
+test_query ( $client, true );
+
+$client->Open();
+test_update ( $client );
+test_update ( $client );
+test_query ( $client, false );
+test_query ( $client, false );
+$client->Close();
+
+test_status ( $client );
+
+
+
|