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 queries fields explicitly indexed as boolean.
19  */
20 #include "couchbase.h"
21 
22 typedef struct {
23     PCBC_ZEND_OBJECT_PRE
24     double boost;
25     char *field;
26     zend_bool value;
27     PCBC_ZEND_OBJECT_POST
28 } pcbc_boolean_field_search_query_t;
29 
30 #if PHP_VERSION_ID >= 70000
pcbc_boolean_field_search_query_fetch_object(zend_object * obj)31 static inline pcbc_boolean_field_search_query_t *pcbc_boolean_field_search_query_fetch_object(zend_object *obj)
32 {
33     return (pcbc_boolean_field_search_query_t *)((char *)obj - XtOffsetOf(pcbc_boolean_field_search_query_t, std));
34 }
35 #define Z_BOOLEAN_FIELD_SEARCH_QUERY_OBJ(zo) (pcbc_boolean_field_search_query_fetch_object(zo))
36 #define Z_BOOLEAN_FIELD_SEARCH_QUERY_OBJ_P(zv) (pcbc_boolean_field_search_query_fetch_object(Z_OBJ_P(zv)))
37 #else
38 #define Z_BOOLEAN_FIELD_SEARCH_QUERY_OBJ(zo) ((pcbc_boolean_field_search_query_t *)zo)
39 #define Z_BOOLEAN_FIELD_SEARCH_QUERY_OBJ_P(zv)                                                                         \
40     ((pcbc_boolean_field_search_query_t *)zend_object_store_get_object(zv TSRMLS_CC))
41 #endif
42 
43 #define LOGARGS(lvl) LCB_LOG_##lvl, NULL, "pcbc/boolean_field_search_query", __FILE__, __LINE__
44 
45 zend_class_entry *pcbc_boolean_field_search_query_ce;
46 
47 /* {{{ proto void BooleanFieldSearchQuery::__construct() */
PHP_METHOD(BooleanFieldSearchQuery,__construct)48 PHP_METHOD(BooleanFieldSearchQuery, __construct)
49 {
50     throw_pcbc_exception("Accessing private constructor.", LCB_EINVAL);
51 }
52 /* }}} */
53 
54 /* {{{ proto \Couchbase\BooleanFieldSearchQuery BooleanFieldSearchQuery::field(string $field)
55  */
PHP_METHOD(BooleanFieldSearchQuery,field)56 PHP_METHOD(BooleanFieldSearchQuery, field)
57 {
58     pcbc_boolean_field_search_query_t *obj;
59     char *field = NULL;
60     int rv;
61     pcbc_str_arg_size field_len;
62 
63     rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &field, &field_len);
64     if (rv == FAILURE) {
65         RETURN_NULL();
66     }
67 
68     obj = Z_BOOLEAN_FIELD_SEARCH_QUERY_OBJ_P(getThis());
69     if (obj->field) {
70         efree(obj->field);
71     }
72     obj->field = estrndup(field, field_len);
73 
74     RETURN_ZVAL(getThis(), 1, 0);
75 } /* }}} */
76 
77 /* {{{ proto \Couchbase\BooleanFieldSearchQuery BooleanFieldSearchQuery::boost(double $boost)
78  */
PHP_METHOD(BooleanFieldSearchQuery,boost)79 PHP_METHOD(BooleanFieldSearchQuery, boost)
80 {
81     pcbc_boolean_field_search_query_t *obj;
82     double boost = 0;
83     int rv;
84 
85     rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "d", &boost);
86     if (rv == FAILURE) {
87         RETURN_NULL();
88     }
89 
90     obj = Z_BOOLEAN_FIELD_SEARCH_QUERY_OBJ_P(getThis());
91     obj->boost = boost;
92 
93     RETURN_ZVAL(getThis(), 1, 0);
94 } /* }}} */
95 
96 /* {{{ proto array BooleanFieldSearchQuery::jsonSerialize()
97  */
PHP_METHOD(BooleanFieldSearchQuery,jsonSerialize)98 PHP_METHOD(BooleanFieldSearchQuery, jsonSerialize)
99 {
100     pcbc_boolean_field_search_query_t *obj;
101     int rv;
102 
103     rv = zend_parse_parameters_none();
104     if (rv == FAILURE) {
105         RETURN_NULL();
106     }
107 
108     obj = Z_BOOLEAN_FIELD_SEARCH_QUERY_OBJ_P(getThis());
109     array_init(return_value);
110     ADD_ASSOC_BOOL_EX(return_value, "bool", obj->value);
111     if (obj->field) {
112         ADD_ASSOC_STRING(return_value, "field", obj->field);
113     }
114     if (obj->boost >= 0) {
115         ADD_ASSOC_DOUBLE_EX(return_value, "boost", obj->boost);
116     }
117 } /* }}} */
118 
119 ZEND_BEGIN_ARG_INFO_EX(ai_BooleanFieldSearchQuery_none, 0, 0, 0)
120 ZEND_END_ARG_INFO()
121 
122 ZEND_BEGIN_ARG_INFO_EX(ai_BooleanFieldSearchQuery_field, 0, 0, 1)
123 ZEND_ARG_INFO(0, field)
124 ZEND_END_ARG_INFO()
125 
126 ZEND_BEGIN_ARG_INFO_EX(ai_BooleanFieldSearchQuery_boost, 0, 0, 1)
127 ZEND_ARG_INFO(0, boost)
128 ZEND_END_ARG_INFO()
129 
130 // clang-format off
131 zend_function_entry boolean_field_search_query_methods[] = {
132     PHP_ME(BooleanFieldSearchQuery, __construct, ai_BooleanFieldSearchQuery_none, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL | ZEND_ACC_CTOR)
133     PHP_ME(BooleanFieldSearchQuery, jsonSerialize, ai_BooleanFieldSearchQuery_none, ZEND_ACC_PUBLIC)
134     PHP_ME(BooleanFieldSearchQuery, boost, ai_BooleanFieldSearchQuery_boost, ZEND_ACC_PUBLIC)
135     PHP_ME(BooleanFieldSearchQuery, field, ai_BooleanFieldSearchQuery_field, ZEND_ACC_PUBLIC)
136     PHP_FE_END
137 };
138 // clang-format on
139 
pcbc_boolean_field_search_query_init(zval * return_value,zend_bool value TSRMLS_DC)140 void pcbc_boolean_field_search_query_init(zval *return_value, zend_bool value TSRMLS_DC)
141 {
142     pcbc_boolean_field_search_query_t *obj;
143 
144     object_init_ex(return_value, pcbc_boolean_field_search_query_ce);
145     obj = Z_BOOLEAN_FIELD_SEARCH_QUERY_OBJ_P(return_value);
146     obj->boost = -1;
147     obj->value = value;
148     obj->field = NULL;
149 }
150 
151 zend_object_handlers boolean_field_search_query_handlers;
152 
boolean_field_search_query_free_object(pcbc_free_object_arg * object TSRMLS_DC)153 static void boolean_field_search_query_free_object(pcbc_free_object_arg *object TSRMLS_DC) /* {{{ */
154 {
155     pcbc_boolean_field_search_query_t *obj = Z_BOOLEAN_FIELD_SEARCH_QUERY_OBJ(object);
156 
157     if (obj->field != NULL) {
158         efree(obj->field);
159     }
160 
161     zend_object_std_dtor(&obj->std TSRMLS_CC);
162 #if PHP_VERSION_ID < 70000
163     efree(obj);
164 #endif
165 } /* }}} */
166 
boolean_field_search_query_create_object(zend_class_entry * class_type TSRMLS_DC)167 static pcbc_create_object_retval boolean_field_search_query_create_object(zend_class_entry *class_type TSRMLS_DC)
168 {
169     pcbc_boolean_field_search_query_t *obj = NULL;
170 
171     obj = PCBC_ALLOC_OBJECT_T(pcbc_boolean_field_search_query_t, class_type);
172 
173     zend_object_std_init(&obj->std, class_type TSRMLS_CC);
174     object_properties_init(&obj->std, class_type);
175 
176 #if PHP_VERSION_ID >= 70000
177     obj->std.handlers = &boolean_field_search_query_handlers;
178     return &obj->std;
179 #else
180     {
181         zend_object_value ret;
182         ret.handle = zend_objects_store_put(obj, (zend_objects_store_dtor_t)zend_objects_destroy_object,
183                                             boolean_field_search_query_free_object, NULL TSRMLS_CC);
184         ret.handlers = &boolean_field_search_query_handlers;
185         return ret;
186     }
187 #endif
188 }
189 
pcbc_boolean_field_search_query_get_debug_info(zval * object,int * is_temp TSRMLS_DC)190 static HashTable *pcbc_boolean_field_search_query_get_debug_info(zval *object, int *is_temp TSRMLS_DC) /* {{{ */
191 {
192     pcbc_boolean_field_search_query_t *obj = NULL;
193 #if PHP_VERSION_ID >= 70000
194     zval retval;
195 #else
196     zval retval = zval_used_for_init;
197 #endif
198 
199     *is_temp = 1;
200     obj = Z_BOOLEAN_FIELD_SEARCH_QUERY_OBJ_P(object);
201 
202     array_init(&retval);
203     ADD_ASSOC_BOOL_EX(&retval, "bool", obj->value);
204     if (obj->field) {
205         ADD_ASSOC_STRING(&retval, "field", obj->field);
206     }
207     if (obj->boost >= 0) {
208         ADD_ASSOC_DOUBLE_EX(&retval, "boost", obj->boost);
209     }
210     return Z_ARRVAL(retval);
211 } /* }}} */
212 
PHP_MINIT_FUNCTION(BooleanFieldSearchQuery)213 PHP_MINIT_FUNCTION(BooleanFieldSearchQuery)
214 {
215     zend_class_entry ce;
216 
217     INIT_NS_CLASS_ENTRY(ce, "Couchbase", "BooleanFieldSearchQuery", boolean_field_search_query_methods);
218     pcbc_boolean_field_search_query_ce = zend_register_internal_class(&ce TSRMLS_CC);
219     pcbc_boolean_field_search_query_ce->create_object = boolean_field_search_query_create_object;
220     PCBC_CE_DISABLE_SERIALIZATION(pcbc_boolean_field_search_query_ce);
221 
222     zend_class_implements(pcbc_boolean_field_search_query_ce TSRMLS_CC, 1, pcbc_json_serializable_ce);
223     zend_class_implements(pcbc_boolean_field_search_query_ce TSRMLS_CC, 1, pcbc_search_query_part_ce);
224 
225     memcpy(&boolean_field_search_query_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
226     boolean_field_search_query_handlers.get_debug_info = pcbc_boolean_field_search_query_get_debug_info;
227 #if PHP_VERSION_ID >= 70000
228     boolean_field_search_query_handlers.free_obj = boolean_field_search_query_free_object;
229     boolean_field_search_query_handlers.offset = XtOffsetOf(pcbc_boolean_field_search_query_t, std);
230 #endif
231 
232     zend_register_class_alias("\\CouchbaseBooleanFieldSearchQuery", pcbc_boolean_field_search_query_ce);
233     return SUCCESS;
234 }
235