1 /**
2 * Copyright 2016-2017 Couchbase, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 /**
18 * A FTS query that matches terms (without further analysis). Usually for debugging purposes, prefer using MatchQuery.
19 */
20 #include "couchbase.h"
21
22 typedef struct {
23 PCBC_ZEND_OBJECT_PRE
24 double boost;
25 char *field;
26 char *term;
27 int prefix_length;
28 int fuzziness;
29 PCBC_ZEND_OBJECT_POST
30 } pcbc_term_search_query_t;
31
32 #if PHP_VERSION_ID >= 70000
pcbc_term_search_query_fetch_object(zend_object * obj)33 static inline pcbc_term_search_query_t *pcbc_term_search_query_fetch_object(zend_object *obj)
34 {
35 return (pcbc_term_search_query_t *)((char *)obj - XtOffsetOf(pcbc_term_search_query_t, std));
36 }
37 #define Z_TERM_SEARCH_QUERY_OBJ(zo) (pcbc_term_search_query_fetch_object(zo))
38 #define Z_TERM_SEARCH_QUERY_OBJ_P(zv) (pcbc_term_search_query_fetch_object(Z_OBJ_P(zv)))
39 #else
40 #define Z_TERM_SEARCH_QUERY_OBJ(zo) ((pcbc_term_search_query_t *)zo)
41 #define Z_TERM_SEARCH_QUERY_OBJ_P(zv) ((pcbc_term_search_query_t *)zend_object_store_get_object(zv TSRMLS_CC))
42 #endif
43
44 #define LOGARGS(lvl) LCB_LOG_##lvl, NULL, "pcbc/term_search_query", __FILE__, __LINE__
45
46 zend_class_entry *pcbc_term_search_query_ce;
47
48 /* {{{ proto void TermSearchQuery::__construct() */
PHP_METHOD(TermSearchQuery,__construct)49 PHP_METHOD(TermSearchQuery, __construct)
50 {
51 throw_pcbc_exception("Accessing private constructor.", LCB_EINVAL);
52 }
53 /* }}} */
54
55 /* {{{ proto \Couchbase\TermSearchQuery TermSearchQuery::field(string $field)
56 */
PHP_METHOD(TermSearchQuery,field)57 PHP_METHOD(TermSearchQuery, field)
58 {
59 pcbc_term_search_query_t *obj;
60 char *field = NULL;
61 int rv;
62 pcbc_str_arg_size field_len;
63
64 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &field, &field_len);
65 if (rv == FAILURE) {
66 RETURN_NULL();
67 }
68
69 obj = Z_TERM_SEARCH_QUERY_OBJ_P(getThis());
70 if (obj->field) {
71 efree(obj->field);
72 }
73 obj->field = estrndup(field, field_len);
74
75 RETURN_ZVAL(getThis(), 1, 0);
76 } /* }}} */
77
78 /* {{{ proto \Couchbase\TermSearchQuery TermSearchQuery::prefixLength(int $prefixLength)
79 */
PHP_METHOD(TermSearchQuery,prefixLength)80 PHP_METHOD(TermSearchQuery, prefixLength)
81 {
82 pcbc_term_search_query_t *obj;
83 long prefix_length = 0;
84 int rv;
85
86 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &prefix_length);
87 if (rv == FAILURE) {
88 RETURN_NULL();
89 }
90
91 obj = Z_TERM_SEARCH_QUERY_OBJ_P(getThis());
92 obj->prefix_length = prefix_length;
93
94 RETURN_ZVAL(getThis(), 1, 0);
95 } /* }}} */
96
97 /* {{{ proto \Couchbase\TermSearchQuery TermSearchQuery::fuzziness(int $fuzziness)
98 */
PHP_METHOD(TermSearchQuery,fuzziness)99 PHP_METHOD(TermSearchQuery, fuzziness)
100 {
101 pcbc_term_search_query_t *obj;
102 long fuzziness = 0;
103 int rv;
104
105 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &fuzziness);
106 if (rv == FAILURE) {
107 RETURN_NULL();
108 }
109
110 obj = Z_TERM_SEARCH_QUERY_OBJ_P(getThis());
111 obj->fuzziness = fuzziness;
112
113 RETURN_ZVAL(getThis(), 1, 0);
114 } /* }}} */
115
116 /* {{{ proto \Couchbase\TermSearchQuery TermSearchQuery::boost(double $boost)
117 */
PHP_METHOD(TermSearchQuery,boost)118 PHP_METHOD(TermSearchQuery, boost)
119 {
120 pcbc_term_search_query_t *obj;
121 double boost = 0;
122 int rv;
123
124 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &boost);
125 if (rv == FAILURE) {
126 RETURN_NULL();
127 }
128
129 obj = Z_TERM_SEARCH_QUERY_OBJ_P(getThis());
130 obj->boost = boost;
131
132 RETURN_ZVAL(getThis(), 1, 0);
133 } /* }}} */
134
135 /* {{{ proto array TermSearchQuery::jsonSerialize()
136 */
PHP_METHOD(TermSearchQuery,jsonSerialize)137 PHP_METHOD(TermSearchQuery, jsonSerialize)
138 {
139 pcbc_term_search_query_t *obj;
140 int rv;
141
142 rv = zend_parse_parameters_none();
143 if (rv == FAILURE) {
144 RETURN_NULL();
145 }
146
147 obj = Z_TERM_SEARCH_QUERY_OBJ_P(getThis());
148 array_init(return_value);
149 ADD_ASSOC_STRING(return_value, "term", obj->term);
150 if (obj->field) {
151 ADD_ASSOC_STRING(return_value, "field", obj->field);
152 }
153 if (obj->prefix_length >= 0) {
154 ADD_ASSOC_LONG_EX(return_value, "prefix_length", obj->prefix_length);
155 }
156 if (obj->fuzziness >= 0) {
157 ADD_ASSOC_LONG_EX(return_value, "fuzziness", obj->fuzziness);
158 }
159 if (obj->boost >= 0) {
160 ADD_ASSOC_DOUBLE_EX(return_value, "boost", obj->boost);
161 }
162 } /* }}} */
163
164 ZEND_BEGIN_ARG_INFO_EX(ai_TermSearchQuery_none, 0, 0, 0)
165 ZEND_END_ARG_INFO()
166
167 ZEND_BEGIN_ARG_INFO_EX(ai_TermSearchQuery_field, 0, 0, 1)
168 ZEND_ARG_INFO(0, field)
169 ZEND_END_ARG_INFO()
170
171 ZEND_BEGIN_ARG_INFO_EX(ai_TermSearchQuery_prefixLength, 0, 0, 1)
172 ZEND_ARG_INFO(0, prefixLength)
173 ZEND_END_ARG_INFO()
174
175 ZEND_BEGIN_ARG_INFO_EX(ai_TermSearchQuery_fuzziness, 0, 0, 1)
176 ZEND_ARG_INFO(0, fuzziness)
177 ZEND_END_ARG_INFO()
178
179 ZEND_BEGIN_ARG_INFO_EX(ai_TermSearchQuery_boost, 0, 0, 1)
180 ZEND_ARG_INFO(0, boost)
181 ZEND_END_ARG_INFO()
182
183 // clang-format off
184 zend_function_entry term_search_query_methods[] = {
185 PHP_ME(TermSearchQuery, __construct, ai_TermSearchQuery_none, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL | ZEND_ACC_CTOR)
186 PHP_ME(TermSearchQuery, jsonSerialize, ai_TermSearchQuery_none, ZEND_ACC_PUBLIC)
187 PHP_ME(TermSearchQuery, boost, ai_TermSearchQuery_boost, ZEND_ACC_PUBLIC)
188 PHP_ME(TermSearchQuery, field, ai_TermSearchQuery_field, ZEND_ACC_PUBLIC)
189 PHP_ME(TermSearchQuery, prefixLength, ai_TermSearchQuery_prefixLength, ZEND_ACC_PUBLIC)
190 PHP_ME(TermSearchQuery, fuzziness, ai_TermSearchQuery_fuzziness, ZEND_ACC_PUBLIC)
191 PHP_FE_END
192 };
193 // clang-format on
194
pcbc_term_search_query_init(zval * return_value,char * term,int term_len TSRMLS_DC)195 void pcbc_term_search_query_init(zval *return_value, char *term, int term_len TSRMLS_DC)
196 {
197 pcbc_term_search_query_t *obj;
198
199 object_init_ex(return_value, pcbc_term_search_query_ce);
200 obj = Z_TERM_SEARCH_QUERY_OBJ_P(return_value);
201 obj->boost = -1;
202 obj->term = estrndup(term, term_len);
203 obj->field = NULL;
204 obj->prefix_length = -1;
205 obj->fuzziness = -1;
206 }
207
208 zend_object_handlers term_search_query_handlers;
209
term_search_query_free_object(pcbc_free_object_arg * object TSRMLS_DC)210 static void term_search_query_free_object(pcbc_free_object_arg *object TSRMLS_DC) /* {{{ */
211 {
212 pcbc_term_search_query_t *obj = Z_TERM_SEARCH_QUERY_OBJ(object);
213
214 if (obj->term != NULL) {
215 efree(obj->term);
216 }
217 if (obj->field != NULL) {
218 efree(obj->field);
219 }
220
221 zend_object_std_dtor(&obj->std TSRMLS_CC);
222 #if PHP_VERSION_ID < 70000
223 efree(obj);
224 #endif
225 } /* }}} */
226
term_search_query_create_object(zend_class_entry * class_type TSRMLS_DC)227 static pcbc_create_object_retval term_search_query_create_object(zend_class_entry *class_type TSRMLS_DC)
228 {
229 pcbc_term_search_query_t *obj = NULL;
230
231 obj = PCBC_ALLOC_OBJECT_T(pcbc_term_search_query_t, class_type);
232
233 zend_object_std_init(&obj->std, class_type TSRMLS_CC);
234 object_properties_init(&obj->std, class_type);
235
236 #if PHP_VERSION_ID >= 70000
237 obj->std.handlers = &term_search_query_handlers;
238 return &obj->std;
239 #else
240 {
241 zend_object_value ret;
242 ret.handle = zend_objects_store_put(obj, (zend_objects_store_dtor_t)zend_objects_destroy_object,
243 term_search_query_free_object, NULL TSRMLS_CC);
244 ret.handlers = &term_search_query_handlers;
245 return ret;
246 }
247 #endif
248 }
249
pcbc_term_search_query_get_debug_info(zval * object,int * is_temp TSRMLS_DC)250 static HashTable *pcbc_term_search_query_get_debug_info(zval *object, int *is_temp TSRMLS_DC) /* {{{ */
251 {
252 pcbc_term_search_query_t *obj = NULL;
253 #if PHP_VERSION_ID >= 70000
254 zval retval;
255 #else
256 zval retval = zval_used_for_init;
257 #endif
258
259 *is_temp = 1;
260 obj = Z_TERM_SEARCH_QUERY_OBJ_P(object);
261
262 array_init(&retval);
263 ADD_ASSOC_STRING(&retval, "term", obj->term);
264 if (obj->field) {
265 ADD_ASSOC_STRING(&retval, "field", obj->field);
266 }
267 if (obj->prefix_length >= 0) {
268 ADD_ASSOC_LONG_EX(&retval, "prefix_length", obj->prefix_length);
269 }
270 if (obj->fuzziness >= 0) {
271 ADD_ASSOC_LONG_EX(&retval, "fuzziness", obj->fuzziness);
272 }
273 if (obj->boost >= 0) {
274 ADD_ASSOC_DOUBLE_EX(&retval, "boost", obj->boost);
275 }
276 return Z_ARRVAL(retval);
277 } /* }}} */
278
PHP_MINIT_FUNCTION(TermSearchQuery)279 PHP_MINIT_FUNCTION(TermSearchQuery)
280 {
281 zend_class_entry ce;
282
283 INIT_NS_CLASS_ENTRY(ce, "Couchbase", "TermSearchQuery", term_search_query_methods);
284 pcbc_term_search_query_ce = zend_register_internal_class(&ce TSRMLS_CC);
285 pcbc_term_search_query_ce->create_object = term_search_query_create_object;
286 PCBC_CE_DISABLE_SERIALIZATION(pcbc_term_search_query_ce);
287
288 zend_class_implements(pcbc_term_search_query_ce TSRMLS_CC, 1, pcbc_json_serializable_ce);
289 zend_class_implements(pcbc_term_search_query_ce TSRMLS_CC, 1, pcbc_search_query_part_ce);
290
291 memcpy(&term_search_query_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
292 term_search_query_handlers.get_debug_info = pcbc_term_search_query_get_debug_info;
293 #if PHP_VERSION_ID >= 70000
294 term_search_query_handlers.free_obj = term_search_query_free_object;
295 term_search_query_handlers.offset = XtOffsetOf(pcbc_term_search_query_t, std);
296 #endif
297
298 zend_register_class_alias("\\CouchbaseTermSearchQuery", pcbc_term_search_query_ce);
299 return SUCCESS;
300 }
301