mirror of
https://github.com/php/pecl-search_engine-sphinx.git
synced 2026-03-24 01:02:13 +01:00
2105 lines
56 KiB
C
2105 lines
56 KiB
C
/*
|
|
+----------------------------------------------------------------------+
|
|
| 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 {
|
|
zend_object std;
|
|
sphinx_client *sphinx;
|
|
zend_bool array_result;
|
|
} 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 TSRMLS_CC, E_WARNING, "using uninitialized SphinxClient object"); \
|
|
RETURN_FALSE; \
|
|
}
|
|
|
|
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;
|
|
#if PHP_VERSION_ID < 50399
|
|
zval *tmp;
|
|
#endif
|
|
|
|
c = ecalloc(1, sizeof(*c));
|
|
zend_object_std_init(&c->std, ce TSRMLS_CC);
|
|
|
|
#if PHP_VERSION_ID < 50399
|
|
ALLOC_HASHTABLE(c->std.properties);
|
|
zend_hash_init(c->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
|
|
zend_hash_copy(c->std.properties, &ce->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
|
|
#else
|
|
object_properties_init(&c->std, ce);
|
|
#endif
|
|
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;
|
|
}
|
|
/* }}} */
|
|
|
|
#if PHP_MAJOR_VERSION >= 5 && PHP_MINOR_VERSION >= 4
|
|
static zval *php_sphinx_client_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC)
|
|
#else
|
|
static zval *php_sphinx_client_read_property(zval *object, zval *member, int type TSRMLS_DC) /* {{{ */
|
|
#endif
|
|
{
|
|
zval tmp_member;
|
|
zval *retval;
|
|
zend_object_handlers *std_hnd;
|
|
|
|
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();
|
|
#if PHP_MAJOR_VERSION >= 5 && PHP_MINOR_VERSION >= 4
|
|
retval = std_hnd->read_property(object, member, type, key TSRMLS_CC);
|
|
#else
|
|
retval = std_hnd->read_property(object, member, type TSRMLS_CC);
|
|
#endif
|
|
|
|
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;
|
|
HashTable *props;
|
|
|
|
c = (php_sphinx_client *)zend_objects_get_address(object TSRMLS_CC);
|
|
|
|
props = zend_std_get_properties(object TSRMLS_CC);
|
|
|
|
error = sphinx_error(c->sphinx);
|
|
MAKE_STD_ZVAL(tmp);
|
|
ZVAL_STRING(tmp, (char *)error, 1);
|
|
zend_hash_update(props, "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(props, "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);
|
|
|
|
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 */
|
|
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++) {
|
|
#if SIZEOF_LONG != 8
|
|
double float_value;
|
|
char buf[128];
|
|
#endif
|
|
|
|
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;
|
|
#if LIBSPHINX_VERSION_ID >= 110
|
|
case SPH_ATTR_STRING:
|
|
ZVAL_STRING(sub_sub_element, sphinx_get_string(result, i, j), 1);
|
|
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, 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"), (double)result->time_msec/1000.0);
|
|
|
|
/* 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);
|
|
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;
|
|
long offset, limit, max_matches = 1000, 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);
|
|
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;
|
|
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);
|
|
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;
|
|
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);
|
|
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;
|
|
|
|
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;
|
|
}
|
|
/* }}} */
|
|
|
|
#if LIBSPHINX_VERSION_ID >= 99
|
|
/* {{{ proto bool SphinxClient::setSelect(string clause) */
|
|
static PHP_METHOD(SphinxClient, setSelect)
|
|
{
|
|
php_sphinx_client *c;
|
|
char *clause;
|
|
int clause_len, res;
|
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &clause, &clause_len) == FAILURE) {
|
|
return;
|
|
}
|
|
|
|
c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
|
|
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;
|
|
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);
|
|
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 attribute_len, num_values, i = 0, res;
|
|
zend_bool exclude = 0;
|
|
sphinx_int64_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);
|
|
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);
|
|
|
|
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_int64_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;
|
|
}
|
|
/* }}} */
|
|
|
|
#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 attribute_len, value_len, res;
|
|
zend_bool exclude = 0;
|
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|b", &attribute, &attribute_len, &value, &value_len, &exclude) == FAILURE) {
|
|
return;
|
|
}
|
|
|
|
c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
|
|
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 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);
|
|
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 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);
|
|
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 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);
|
|
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 attribute_len, groupsort_len, res;
|
|
long func;
|
|
|
|
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";
|
|
}
|
|
|
|
if (func < SPH_GROUPBY_DAY || func > SPH_GROUPBY_ATTRPAIR) {
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid group func specified (%ld)", func);
|
|
RETURN_FALSE;
|
|
}
|
|
|
|
c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
|
|
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 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);
|
|
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;
|
|
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);
|
|
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;
|
|
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);
|
|
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;
|
|
long ranker;
|
|
int res, rank_expr_len;
|
|
char *rank_expr = NULL;
|
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|s", &ranker, &rank_expr, &rank_expr_len) == FAILURE) {
|
|
return;
|
|
}
|
|
|
|
c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
|
|
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;
|
|
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);
|
|
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;
|
|
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);
|
|
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;
|
|
|
|
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);
|
|
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() TSRMLS_CC, "d", &timeout) == FAILURE) {
|
|
return;
|
|
}
|
|
|
|
c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
|
|
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() TSRMLS_CC, "b", &array_result) == FAILURE) {
|
|
return;
|
|
}
|
|
|
|
c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
|
|
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 index_len, 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;
|
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "saa|b", &index, &index_len, &attributes, &values, &mva) == FAILURE) {
|
|
return;
|
|
}
|
|
|
|
#if LIBSPHINX_VERSION_ID < 110
|
|
if (mva) {
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "update mva attributes is not supported");
|
|
RETURN_FALSE;
|
|
}
|
|
#endif
|
|
|
|
c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
|
|
SPHINX_INITIALIZED(c)
|
|
|
|
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_int64_t) * values_num);
|
|
if (!mva) {
|
|
vals = safe_emalloc(values_num * attrs_num, sizeof(sphinx_int64_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;
|
|
}
|
|
|
|
if (id_type == IS_LONG) {
|
|
docids[i] = (sphinx_uint64_t)id;
|
|
} else { /* IS_FLOAT */
|
|
docids[i] = (sphinx_uint64_t)float_id;
|
|
}
|
|
|
|
a = 0;
|
|
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 (mva) {
|
|
#if LIBSPHINX_VERSION_ID >= 110
|
|
if (Z_TYPE_PP(attr_value) != IS_ARRAY) {
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "attribute value must be an array");
|
|
failed = 1;
|
|
break;
|
|
}
|
|
values_mva_num = zend_hash_num_elements(Z_ARRVAL_PP(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;
|
|
for (zend_hash_internal_pointer_reset(Z_ARRVAL_PP(attr_value));
|
|
zend_hash_get_current_data(Z_ARRVAL_PP(attr_value), (void **) &attr_value_mva) != FAILURE;
|
|
zend_hash_move_forward(Z_ARRVAL_PP(attr_value))) {
|
|
if (Z_TYPE_PP(attr_value_mva) != IS_LONG) {
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "mva attribute value must be integer");
|
|
failed = 1;
|
|
break;
|
|
}
|
|
vals_mva[j] = (unsigned int)Z_LVAL_PP(attr_value_mva);
|
|
j++;
|
|
}
|
|
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_PP(attr_value) != IS_LONG) {
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "attribute value must be integer");
|
|
failed = 1;
|
|
break;
|
|
}
|
|
vals[j] = (sphinx_int64_t)Z_LVAL_PP(attr_value);
|
|
j++;
|
|
}
|
|
}
|
|
|
|
if (failed) {
|
|
break;
|
|
}
|
|
|
|
if (mva) {
|
|
res++;
|
|
}
|
|
i++;
|
|
}
|
|
|
|
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;
|
|
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);
|
|
SPHINX_INITIALIZED(c)
|
|
|
|
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 */
|
|
sphinx_init_excerpt_options(&opts);
|
|
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);
|
|
#if LIBSPHINX_VERSION_ID >= 110
|
|
} else if (OPTS_EQUAL(string_key, string_key_len, "query_mode")) {
|
|
SEPARATE_ZVAL(item);
|
|
convert_to_boolean_ex(item);
|
|
opts.query_mode = Z_LVAL_PP(item);
|
|
} else if (OPTS_EQUAL(string_key, string_key_len, "force_all_words")) {
|
|
SEPARATE_ZVAL(item);
|
|
convert_to_boolean_ex(item);
|
|
opts.force_all_words = Z_LVAL_PP(item);
|
|
} else if (OPTS_EQUAL(string_key, string_key_len, "limit_passages")) {
|
|
SEPARATE_ZVAL(item);
|
|
convert_to_long_ex(item);
|
|
opts.limit_passages = (int)Z_LVAL_PP(item);
|
|
} else if (OPTS_EQUAL(string_key, string_key_len, "limit_words")) {
|
|
SEPARATE_ZVAL(item);
|
|
convert_to_long_ex(item);
|
|
opts.limit_words = (int)Z_LVAL_PP(item);
|
|
} else if (OPTS_EQUAL(string_key, string_key_len, "start_passage_id")) {
|
|
SEPARATE_ZVAL(item);
|
|
convert_to_long_ex(item);
|
|
opts.start_passage_id = (int)Z_LVAL_PP(item);
|
|
} else if (OPTS_EQUAL(string_key, string_key_len, "load_files")) {
|
|
SEPARATE_ZVAL(item);
|
|
convert_to_boolean_ex(item);
|
|
opts.load_files = Z_LVAL_PP(item);
|
|
} else if (OPTS_EQUAL(string_key, string_key_len, "html_strip_mode")) {
|
|
SEPARATE_ZVAL(item);
|
|
convert_to_string_ex(item);
|
|
opts.html_strip_mode = Z_STRVAL_PP(item);
|
|
} else if (OPTS_EQUAL(string_key, string_key_len, "allow_empty")) {
|
|
SEPARATE_ZVAL(item);
|
|
convert_to_boolean_ex(item);
|
|
opts.allow_empty = Z_LVAL_PP(item);
|
|
#endif
|
|
} 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);
|
|
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++) {
|
|
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_INITIALIZED(c)
|
|
|
|
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_INITIALIZED(c)
|
|
|
|
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);
|
|
SPHINX_INITIALIZED(c)
|
|
|
|
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);
|
|
SPHINX_INITIALIZED(c)
|
|
|
|
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);
|
|
SPHINX_INITIALIZED(c)
|
|
|
|
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);
|
|
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 = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
|
|
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++) {
|
|
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 '\\':
|
|
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);
|
|
}
|
|
/* }}} */
|
|
|
|
#if LIBSPHINX_VERSION_ID >= 99
|
|
/* {{{ proto bool SphinxClient::open() */
|
|
static PHP_METHOD(SphinxClient, open)
|
|
{
|
|
php_sphinx_client *c;
|
|
int res;
|
|
|
|
c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
|
|
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 = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
|
|
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 = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
|
|
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++) {
|
|
MAKE_STD_ZVAL(tmp);
|
|
array_init(tmp);
|
|
|
|
for (j = 0; j < num_cols; j++, k++) {
|
|
add_next_index_string(tmp, result[k], 1);
|
|
}
|
|
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;
|
|
long type;
|
|
int attribute_len, values_num, i = 0;
|
|
int res;
|
|
sphinx_uint64_t *docids = NULL;
|
|
unsigned int *vals = NULL;
|
|
|
|
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sla", &attribute, &attribute_len, &type, &values) == FAILURE) {
|
|
return;
|
|
}
|
|
|
|
c = (php_sphinx_client *)zend_object_store_get_object(getThis() TSRMLS_CC);
|
|
SPHINX_INITIALIZED(c)
|
|
|
|
if (type != SPH_ATTR_INTEGER && type != SPH_ATTR_TIMESTAMP
|
|
&& type != SPH_ATTR_BOOL && type != SPH_ATTR_FLOAT) {
|
|
php_error_docref(NULL TSRMLS_CC, 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 TSRMLS_CC, 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);
|
|
for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(values));
|
|
zend_hash_get_current_data(Z_ARRVAL_P(values), (void **) &attr_value) != FAILURE;
|
|
zend_hash_move_forward(Z_ARRVAL_P(values)))
|
|
{
|
|
char *str_id;
|
|
ulong id;
|
|
int key_type;
|
|
uint str_id_len;
|
|
double float_id = 0;
|
|
unsigned char id_type;
|
|
|
|
if (Z_TYPE_PP(attr_value) != IS_LONG) {
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "attribute value must be integer");
|
|
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;
|
|
}
|
|
vals[i] = (sphinx_uint64_t)Z_LVAL_PP(attr_value);
|
|
|
|
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_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 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()
|
|
|
|
#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;
|
|
|
|
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);
|
|
#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 = {
|
|
#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
|
|
*/
|