1 /**
2 * Copyright 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 #include "couchbase.h"
18 #include <Zend/zend_alloc.h>
19
20 #define LOGARGS(lvl) LCB_LOG_##lvl, NULL, "pcbc/analytics_query", __FILE__, __LINE__
21
22 zend_class_entry *pcbc_analytics_query_ce;
23
24 /* {{{ proto void AnalyticsQuery::__construct() Should not be called directly */
PHP_METHOD(AnalyticsQuery,__construct)25 PHP_METHOD(AnalyticsQuery, __construct)
26 {
27 throw_pcbc_exception("Accessing private constructor.", LCB_EINVAL);
28 }
29 /* }}} */
30
31 /* {{{ proto \Couchbase\AnalyticsQuery AnalyticsQuery::fromString(string $statement) */
PHP_METHOD(AnalyticsQuery,fromString)32 PHP_METHOD(AnalyticsQuery, fromString)
33 {
34 char *statement = NULL;
35 pcbc_str_arg_size statement_len = 0;
36 int rv;
37
38 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &statement, &statement_len);
39 if (rv == FAILURE) {
40 RETURN_NULL();
41 }
42
43 pcbc_analytics_query_init(return_value, statement, statement_len TSRMLS_CC);
44 } /* }}} */
45
PHP_METHOD(AnalyticsQuery,rawParam)46 PHP_METHOD(AnalyticsQuery, rawParam)
47 {
48 zval *value;
49 zval *options;
50 char *name = NULL;
51 pcbc_str_arg_size name_len = 0;
52 int rv;
53
54 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz", &name, &name_len, &value);
55 if (rv == FAILURE) {
56 RETURN_NULL();
57 }
58
59 PCBC_READ_PROPERTY(options, pcbc_analytics_query_ce, getThis(), "options", 0);
60 PCBC_ADDREF_P(value);
61 add_assoc_zval_ex(options, name, name_len, value);
62
63 RETURN_ZVAL(getThis(), 1, 0);
64 }
65
PHP_METHOD(AnalyticsQuery,positionalParams)66 PHP_METHOD(AnalyticsQuery, positionalParams)
67 {
68 zval *params;
69 zval *options;
70 int rv;
71
72 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", ¶ms);
73 if (rv == FAILURE) {
74 RETURN_NULL();
75 }
76
77 PCBC_READ_PROPERTY(options, pcbc_analytics_query_ce, getThis(), "options", 0);
78 PCBC_ADDREF_P(params);
79 add_assoc_zval(options, "args", params);
80
81 RETURN_ZVAL(getThis(), 1, 0);
82 }
83
PHP_METHOD(AnalyticsQuery,namedParams)84 PHP_METHOD(AnalyticsQuery, namedParams)
85 {
86 zval *params;
87 zval *options;
88 int rv;
89
90 rv = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", ¶ms);
91 if (rv == FAILURE) {
92 RETURN_NULL();
93 }
94
95 PCBC_READ_PROPERTY(options, pcbc_analytics_query_ce, getThis(), "options", 0);
96 {
97 #if PHP_VERSION_ID >= 70000
98 HashTable *ht;
99 zend_ulong num_key;
100 zend_string *string_key = NULL;
101 zval *entry;
102
103 ht = HASH_OF(params);
104 ZEND_HASH_FOREACH_KEY_VAL(ht, num_key, string_key, entry)
105 {
106 if (string_key) {
107 char *prefixed_key = NULL;
108 spprintf(&prefixed_key, 0, "$%s", ZSTR_VAL(string_key));
109 add_assoc_zval(options, prefixed_key, entry);
110 PCBC_ADDREF_P(entry);
111 efree(prefixed_key);
112 }
113 }
114 ZEND_HASH_FOREACH_END();
115 #else
116 HashPosition pos;
117 zval **entry;
118
119 zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(params), &pos);
120 while (zend_hash_get_current_data_ex(Z_ARRVAL_P(params), (void **)&entry, &pos) == SUCCESS) {
121 if (zend_hash_get_current_key_type_ex(Z_ARRVAL_P(params), &pos) == HASH_KEY_IS_STRING) {
122 char *key = NULL, *prefixed_key = NULL;
123 unsigned key_len = 0;
124 zend_hash_get_current_key_ex(Z_ARRVAL_P(params), &key, &key_len, NULL, 0, &pos);
125 spprintf(&prefixed_key, 0, "$%s", key);
126 add_assoc_zval(options, prefixed_key, *entry);
127 PCBC_ADDREF_P(*entry);
128 efree(prefixed_key);
129 }
130 zend_hash_move_forward_ex(Z_ARRVAL_P(params), &pos);
131 }
132 #endif
133 }
134 RETURN_ZVAL(getThis(), 1, 0);
135 }
136
137 ZEND_BEGIN_ARG_INFO_EX(ai_AnalyticsQuery_none, 0, 0, 0)
138 ZEND_END_ARG_INFO()
139
140 ZEND_BEGIN_ARG_INFO_EX(ai_AnalyticsQuery_fromString, 0, 0, 1)
141 ZEND_ARG_INFO(0, statement)
142 ZEND_END_ARG_INFO()
143
144 ZEND_BEGIN_ARG_INFO_EX(ai_AnalyticsQuery_params, 0, 0, 1)
145 ZEND_ARG_INFO(0, params)
146 ZEND_END_ARG_INFO()
147
148 ZEND_BEGIN_ARG_INFO_EX(ai_AnalyticsQuery_rawParam, 0, 0, 2)
149 ZEND_ARG_INFO(0, name)
150 ZEND_ARG_INFO(0, value)
151 ZEND_END_ARG_INFO()
152
153 // clang-format off
154 zend_function_entry analytics_query_methods[] = {
155 PHP_ME(AnalyticsQuery, __construct, ai_AnalyticsQuery_none, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL | ZEND_ACC_CTOR)
156 PHP_ME(AnalyticsQuery, fromString, ai_AnalyticsQuery_fromString, ZEND_ACC_STATIC | ZEND_ACC_PUBLIC)
157 PHP_ME(AnalyticsQuery, positionalParams, ai_AnalyticsQuery_params, ZEND_ACC_PUBLIC)
158 PHP_ME(AnalyticsQuery, namedParams, ai_AnalyticsQuery_params, ZEND_ACC_PUBLIC)
159 PHP_ME(AnalyticsQuery, rawParam, ai_AnalyticsQuery_rawParam, ZEND_ACC_PUBLIC)
160 PHP_FE_END
161 };
162 // clang-format on
163
164 zend_object_handlers pcbc_analytics_query_handlers;
165
pcbc_analytics_query_init(zval * return_value,const char * statement,int statement_len TSRMLS_DC)166 void pcbc_analytics_query_init(zval *return_value, const char *statement, int statement_len TSRMLS_DC)
167 {
168 pcbc_analytics_query_t *query;
169 PCBC_ZVAL options;
170
171 object_init_ex(return_value, pcbc_analytics_query_ce);
172 query = Z_ANALYTICS_QUERY_OBJ_P(return_value);
173
174 PCBC_ZVAL_ALLOC(options);
175 array_init(PCBC_P(options));
176 ADD_ASSOC_STRINGL(PCBC_P(options), "statement", statement, statement_len);
177 zend_update_property(pcbc_analytics_query_ce, return_value, ZEND_STRL("options"), PCBC_P(options) TSRMLS_CC);
178 zval_ptr_dtor(&options);
179 }
180
analytics_query_free_object(pcbc_free_object_arg * object TSRMLS_DC)181 static void analytics_query_free_object(pcbc_free_object_arg *object TSRMLS_DC) /* {{{ */
182 {
183 pcbc_analytics_query_t *obj = Z_ANALYTICS_QUERY_OBJ(object);
184
185 zend_object_std_dtor(&obj->std TSRMLS_CC);
186 #if PHP_VERSION_ID < 70000
187 efree(obj);
188 #endif
189 } /* }}} */
190
analytics_query_create_object(zend_class_entry * class_type TSRMLS_DC)191 static pcbc_create_object_retval analytics_query_create_object(zend_class_entry *class_type TSRMLS_DC)
192 {
193 pcbc_analytics_query_t *obj = NULL;
194
195 obj = PCBC_ALLOC_OBJECT_T(pcbc_analytics_query_t, class_type);
196
197 zend_object_std_init(&obj->std, class_type TSRMLS_CC);
198 object_properties_init(&obj->std, class_type);
199
200 #if PHP_VERSION_ID >= 70000
201 obj->std.handlers = &pcbc_analytics_query_handlers;
202 return &obj->std;
203 #else
204 {
205 zend_object_value ret;
206 ret.handle = zend_objects_store_put(obj, (zend_objects_store_dtor_t)zend_objects_destroy_object,
207 analytics_query_free_object, NULL TSRMLS_CC);
208 ret.handlers = &pcbc_analytics_query_handlers;
209 return ret;
210 }
211 #endif
212 }
213
analytics_query_get_debug_info(zval * object,int * is_temp TSRMLS_DC)214 static HashTable *analytics_query_get_debug_info(zval *object, int *is_temp TSRMLS_DC) /* {{{ */
215 {
216 pcbc_analytics_query_t *obj = NULL;
217 #if PHP_VERSION_ID >= 70000
218 zval retval;
219 #else
220 zval retval = zval_used_for_init;
221 #endif
222 zval *options;
223
224 *is_temp = 1;
225 obj = Z_ANALYTICS_QUERY_OBJ_P(object);
226
227 array_init(&retval);
228 PCBC_READ_PROPERTY(options, pcbc_analytics_query_ce, object, "options", 0);
229 PCBC_ADDREF_P(options);
230 add_assoc_zval(&retval, "options", options);
231
232 return Z_ARRVAL(retval);
233 } /* }}} */
234
PHP_MINIT_FUNCTION(AnalyticsQuery)235 PHP_MINIT_FUNCTION(AnalyticsQuery)
236 {
237 zend_class_entry ce;
238
239 INIT_NS_CLASS_ENTRY(ce, "Couchbase", "AnalyticsQuery", analytics_query_methods);
240 pcbc_analytics_query_ce = zend_register_internal_class(&ce TSRMLS_CC);
241 pcbc_analytics_query_ce->create_object = analytics_query_create_object;
242 PCBC_CE_DISABLE_SERIALIZATION(pcbc_analytics_query_ce);
243
244 memcpy(&pcbc_analytics_query_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
245 pcbc_analytics_query_handlers.get_debug_info = analytics_query_get_debug_info;
246 #if PHP_VERSION_ID >= 70000
247 pcbc_analytics_query_handlers.free_obj = analytics_query_free_object;
248 pcbc_analytics_query_handlers.offset = XtOffsetOf(pcbc_analytics_query_t, std);
249 #endif
250 zend_declare_property_null(pcbc_analytics_query_ce, ZEND_STRL("options"), ZEND_ACC_PUBLIC TSRMLS_CC);
251 return SUCCESS;
252 }
253