1 /**
2 * Copyright 2015-2017 DataStax, 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 "php_driver.h"
18 #include "php_driver_types.h"
19 #include "util/hash.h"
20 #include "util/types.h"
21 #include <time.h>
22 #include <ext/date/php_date.h>
23
24 zend_class_entry *php_driver_date_ce = NULL;
25
26 void
php_driver_date_init(INTERNAL_FUNCTION_PARAMETERS)27 php_driver_date_init(INTERNAL_FUNCTION_PARAMETERS)
28 {
29 zval *seconds = NULL;
30 php_driver_date *self;
31
32 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z", &seconds) == FAILURE) {
33 return;
34 }
35
36 if (getThis() && instanceof_function(Z_OBJCE_P(getThis()), php_driver_date_ce TSRMLS_CC)) {
37 self = PHP_DRIVER_GET_DATE(getThis());
38 } else {
39 object_init_ex(return_value, php_driver_date_ce);
40 self = PHP_DRIVER_GET_DATE(return_value);
41 }
42
43 if (seconds == NULL) {
44 self->date = cass_date_from_epoch(time(NULL));
45 } else {
46 if (Z_TYPE_P(seconds) != IS_LONG) {
47 INVALID_ARGUMENT(seconds, "a number of seconds since the Unix Epoch");
48 }
49 self->date = cass_date_from_epoch(Z_LVAL_P(seconds));
50 }
51 }
52
53 /* {{{ Date::__construct(string) */
PHP_METHOD(Date,__construct)54 PHP_METHOD(Date, __construct)
55 {
56 php_driver_date_init(INTERNAL_FUNCTION_PARAM_PASSTHRU);
57 }
58 /* }}} */
59
60 /* {{{ Date::type() */
PHP_METHOD(Date,type)61 PHP_METHOD(Date, type)
62 {
63 php5to7_zval type = php_driver_type_scalar(CASS_VALUE_TYPE_DATE TSRMLS_CC);
64 RETURN_ZVAL(PHP5TO7_ZVAL_MAYBE_P(type), 1, 1);
65 }
66 /* }}} */
67
68 /* {{{ Date::seconds() */
PHP_METHOD(Date,seconds)69 PHP_METHOD(Date, seconds)
70 {
71 php_driver_date *self = PHP_DRIVER_GET_DATE(getThis());
72
73 RETURN_LONG(cass_date_time_to_epoch(self->date, 0));
74 }
75 /* }}} */
76
77 /* {{{ Date::toDateTime() */
PHP_METHOD(Date,toDateTime)78 PHP_METHOD(Date, toDateTime)
79 {
80 php_driver_date *self;
81 zval *ztime = NULL;
82 php_driver_time* time_obj = NULL;
83 php5to7_zval datetime;
84 php_date_obj *datetime_obj = NULL;
85 char *str;
86 int str_len;
87
88 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|z", &ztime) == FAILURE) {
89 return;
90 }
91
92 if (ztime != NULL) {
93 time_obj = PHP_DRIVER_GET_TIME(ztime);
94 }
95 self = PHP_DRIVER_GET_DATE(getThis());
96
97 PHP5TO7_ZVAL_MAYBE_MAKE(datetime);
98 php_date_instantiate(php_date_get_date_ce(), PHP5TO7_ZVAL_MAYBE_P(datetime) TSRMLS_CC);
99
100 #if PHP_MAJOR_VERSION >= 7
101 datetime_obj = php_date_obj_from_obj(Z_OBJ(datetime));
102 #else
103 datetime_obj = zend_object_store_get_object(datetime TSRMLS_CC);
104 #endif
105
106 str_len = spprintf(&str, 0, "%lld",
107 cass_date_time_to_epoch(self->date,
108 time_obj != NULL ? time_obj->time : 0));
109 php_date_initialize(datetime_obj, str, str_len, "U", NULL, 0 TSRMLS_CC);
110 efree(str);
111
112 RETVAL_ZVAL(PHP5TO7_ZVAL_MAYBE_P(datetime), 0, 1);
113 }
114 /* }}} */
115
116 /* {{{ Date::fromDateTime() */
PHP_METHOD(Date,fromDateTime)117 PHP_METHOD(Date, fromDateTime)
118 {
119 php_driver_date *self;
120 zval *zdatetime;
121 php5to7_zval retval;
122
123 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &zdatetime) == FAILURE) {
124 return;
125 }
126
127 zend_call_method_with_0_params(PHP5TO7_ZVAL_MAYBE_ADDR_OF(zdatetime),
128 php_date_get_date_ce(),
129 NULL,
130 "gettimestamp",
131 &retval);
132
133 if (!PHP5TO7_ZVAL_IS_UNDEF(retval) &&
134 Z_TYPE_P(PHP5TO7_ZVAL_MAYBE_P(retval)) == IS_LONG) {
135 object_init_ex(return_value, php_driver_date_ce);
136 self = PHP_DRIVER_GET_DATE(return_value);
137 self->date = cass_date_from_epoch(PHP5TO7_Z_LVAL_MAYBE_P(retval));
138 zval_ptr_dtor(&retval);
139 return;
140 }
141 }
142 /* }}} */
143
144
145 /* {{{ Date::__toString() */
PHP_METHOD(Date,__toString)146 PHP_METHOD(Date, __toString)
147 {
148 php_driver_date *self;
149 char *ret = NULL;
150
151 if (zend_parse_parameters_none() == FAILURE) {
152 return;
153 }
154
155 self = PHP_DRIVER_GET_DATE(getThis());
156
157 spprintf(&ret, 0, PHP_DRIVER_NAMESPACE "\\Date(seconds=%lld)", cass_date_time_to_epoch(self->date, 0));
158 PHP5TO7_RETVAL_STRING(ret);
159 efree(ret);
160 }
161 /* }}} */
162
163 ZEND_BEGIN_ARG_INFO_EX(arginfo__construct, 0, ZEND_RETURN_VALUE, 0)
164 ZEND_ARG_INFO(0, seconds)
165 ZEND_END_ARG_INFO()
166
167 ZEND_BEGIN_ARG_INFO_EX(arginfo_time, 0, ZEND_RETURN_VALUE, 0)
168 PHP_DRIVER_NAMESPACE_ZEND_ARG_OBJ_INFO(0, time, Time, 0)
169 ZEND_END_ARG_INFO()
170
171 ZEND_BEGIN_ARG_INFO_EX(arginfo_datetime, 0, ZEND_RETURN_VALUE, 1)
172 ZEND_ARG_OBJ_INFO(0, datetime, DateTime, 0)
173 ZEND_END_ARG_INFO()
174
175 ZEND_BEGIN_ARG_INFO_EX(arginfo_none, 0, ZEND_RETURN_VALUE, 0)
176 ZEND_END_ARG_INFO()
177
178 static zend_function_entry php_driver_date_methods[] = {
179 PHP_ME(Date, __construct, arginfo__construct, ZEND_ACC_CTOR|ZEND_ACC_PUBLIC)
180 PHP_ME(Date, type, arginfo_none, ZEND_ACC_PUBLIC)
181 PHP_ME(Date, seconds, arginfo_none, ZEND_ACC_PUBLIC)
182 PHP_ME(Date, toDateTime, arginfo_time, ZEND_ACC_PUBLIC)
183 PHP_ME(Date, fromDateTime, arginfo_datetime, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
184 PHP_ME(Date, __toString, arginfo_none, ZEND_ACC_PUBLIC)
185 PHP_FE_END
186 };
187
188 static php_driver_value_handlers php_driver_date_handlers;
189
190 static HashTable *
php_driver_date_gc(zval * object,php5to7_zval_gc table,int * n TSRMLS_DC)191 php_driver_date_gc(zval *object, php5to7_zval_gc table, int *n TSRMLS_DC)
192 {
193 *table = NULL;
194 *n = 0;
195 return zend_std_get_properties(object TSRMLS_CC);
196 }
197
198 static HashTable *
php_driver_date_properties(zval * object TSRMLS_DC)199 php_driver_date_properties(zval *object TSRMLS_DC)
200 {
201 php5to7_zval type;
202 php5to7_zval seconds;
203
204 php_driver_date *self = PHP_DRIVER_GET_DATE(object);
205 HashTable *props = zend_std_get_properties(object TSRMLS_CC);
206
207 type = php_driver_type_scalar(CASS_VALUE_TYPE_DATE TSRMLS_CC);
208 PHP5TO7_ZEND_HASH_UPDATE(props, "type", sizeof("type"), PHP5TO7_ZVAL_MAYBE_P(type), sizeof(zval));
209
210 PHP5TO7_ZVAL_MAYBE_MAKE(seconds);
211 ZVAL_LONG(PHP5TO7_ZVAL_MAYBE_P(seconds), cass_date_time_to_epoch(self->date, 0));
212 PHP5TO7_ZEND_HASH_UPDATE(props, "seconds", sizeof("seconds"), PHP5TO7_ZVAL_MAYBE_P(seconds), sizeof(zval));
213
214 return props;
215 }
216
217 static int
php_driver_date_compare(zval * obj1,zval * obj2 TSRMLS_DC)218 php_driver_date_compare(zval *obj1, zval *obj2 TSRMLS_DC)
219 {
220 php_driver_date *date1 = NULL;
221 php_driver_date *date2 = NULL;
222 if (Z_OBJCE_P(obj1) != Z_OBJCE_P(obj2))
223 return 1; /* different classes */
224
225 date1 = PHP_DRIVER_GET_DATE(obj1);
226 date2 = PHP_DRIVER_GET_DATE(obj2);
227
228 return PHP_DRIVER_COMPARE(date1->date, date2->date);
229 }
230
231 static unsigned
php_driver_date_hash_value(zval * obj TSRMLS_DC)232 php_driver_date_hash_value(zval *obj TSRMLS_DC)
233 {
234 php_driver_date *self = PHP_DRIVER_GET_DATE(obj);
235 return 31 * 17 + self->date;
236 }
237
238 static void
php_driver_date_free(php5to7_zend_object_free * object TSRMLS_DC)239 php_driver_date_free(php5to7_zend_object_free *object TSRMLS_DC)
240 {
241 php_driver_date *self = PHP5TO7_ZEND_OBJECT_GET(date, object);
242
243 zend_object_std_dtor(&self->zval TSRMLS_CC);
244 PHP5TO7_MAYBE_EFREE(self);
245 }
246
247 static php5to7_zend_object
php_driver_date_new(zend_class_entry * ce TSRMLS_DC)248 php_driver_date_new(zend_class_entry *ce TSRMLS_DC)
249 {
250 php_driver_date *self =
251 PHP5TO7_ZEND_OBJECT_ECALLOC(date, ce);
252
253 self->date = 0;
254
255 PHP5TO7_ZEND_OBJECT_INIT(date, self, ce);
256 }
257
php_driver_define_Date(TSRMLS_D)258 void php_driver_define_Date(TSRMLS_D)
259 {
260 zend_class_entry ce;
261
262 INIT_CLASS_ENTRY(ce, PHP_DRIVER_NAMESPACE "\\Date", php_driver_date_methods);
263 php_driver_date_ce = zend_register_internal_class(&ce TSRMLS_CC);
264 zend_class_implements(php_driver_date_ce TSRMLS_CC, 1, php_driver_value_ce);
265 memcpy(&php_driver_date_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
266 php_driver_date_handlers.std.get_properties = php_driver_date_properties;
267 #if PHP_VERSION_ID >= 50400
268 php_driver_date_handlers.std.get_gc = php_driver_date_gc;
269 #endif
270 php_driver_date_handlers.std.compare_objects = php_driver_date_compare;
271 php_driver_date_ce->ce_flags |= PHP5TO7_ZEND_ACC_FINAL;
272 php_driver_date_ce->create_object = php_driver_date_new;
273
274 php_driver_date_handlers.hash_value = php_driver_date_hash_value;
275 }
276