1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 5 |
4 +----------------------------------------------------------------------+
5 | This source file is subject to version 3.01 of the PHP license, |
6 | that is bundled with this package in the file LICENSE, and is |
7 | available through the world-wide-web at the following url: |
8 | http://www.php.net/license/3_01.txt |
9 | If you did not receive a copy of the PHP license and are unable to |
10 | obtain it through the world-wide-web, please send a note to |
11 | license@php.net so we can mail you a copy immediately. |
12 +----------------------------------------------------------------------+
13 | Authors: Gustavo Lopes <cataphract@php.net> |
14 +----------------------------------------------------------------------+
15 */
16
17 #ifdef HAVE_CONFIG_H
18 #include "config.h"
19 #endif
20
21 #include "../intl_cppshims.h"
22
23 #include <unicode/locid.h>
24 #include <unicode/calendar.h>
25 #include <unicode/ustring.h>
26
27 #include "../intl_convertcpp.h"
28 #include "../common/common_date.h"
29
30 extern "C" {
31 #include "../php_intl.h"
32 #define USE_TIMEZONE_POINTER 1
33 #include "../timezone/timezone_class.h"
34 #define USE_CALENDAR_POINTER 1
35 #include "calendar_class.h"
36 #include "../intl_convert.h"
37 #include <zend_exceptions.h>
38 #include <zend_interfaces.h>
39 #include <ext/date/php_date.h>
40 }
41 #include "../common/common_enum.h"
42
PHP_METHOD(IntlCalendar,__construct)43 U_CFUNC PHP_METHOD(IntlCalendar, __construct)
44 {
45 zend_throw_exception( NULL,
46 "An object of this type cannot be created with the new operator",
47 0 TSRMLS_CC );
48 }
49
PHP_FUNCTION(intlcal_create_instance)50 U_CFUNC PHP_FUNCTION(intlcal_create_instance)
51 {
52 zval **zv_timezone = NULL;
53 const char *locale_str = NULL;
54 int dummy;
55 TimeZone *timeZone;
56 UErrorCode status = U_ZERO_ERROR;
57 intl_error_reset(NULL TSRMLS_CC);
58
59 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|Zs!",
60 &zv_timezone, &locale_str, &dummy) == FAILURE) {
61 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
62 "intlcal_create_calendar: bad arguments", 0 TSRMLS_CC);
63 RETURN_NULL();
64 }
65
66 timeZone = timezone_process_timezone_argument(zv_timezone, NULL,
67 "intlcal_create_instance" TSRMLS_CC);
68 if (timeZone == NULL) {
69 RETURN_NULL();
70 }
71
72 if (!locale_str) {
73 locale_str = intl_locale_get_default(TSRMLS_C);
74 }
75
76 Calendar *cal = Calendar::createInstance(timeZone,
77 Locale::createFromName(locale_str), status);
78 if (cal == NULL) {
79 delete timeZone;
80 intl_error_set(NULL, status, "Error creating ICU Calendar object", 0 TSRMLS_CC);
81 RETURN_NULL();
82 }
83
84 calendar_object_create(return_value, cal TSRMLS_CC);
85 }
86
87 #if U_ICU_VERSION_MAJOR_NUM * 10 + U_ICU_VERSION_MINOR_NUM >= 42
88 class BugStringCharEnumeration : public StringEnumeration
89 {
90 public:
BugStringCharEnumeration(UEnumeration * _uenum)91 BugStringCharEnumeration(UEnumeration* _uenum) : uenum(_uenum) {}
92
~BugStringCharEnumeration()93 ~BugStringCharEnumeration()
94 {
95 uenum_close(uenum);
96 }
97
count(UErrorCode & status) const98 int32_t count(UErrorCode& status) const {
99 return uenum_count(uenum, &status);
100 }
101
snext(UErrorCode & status)102 virtual const UnicodeString* snext(UErrorCode& status)
103 {
104 int32_t length;
105 const UChar* str = uenum_unext(uenum, &length, &status);
106 if (str == 0 || U_FAILURE(status)) {
107 return 0;
108 }
109 return &unistr.setTo(str, length);
110 }
111
next(int32_t * resultLength,UErrorCode & status)112 virtual const char* next(int32_t *resultLength, UErrorCode &status)
113 {
114 int32_t length = -1;
115 const char* str = uenum_next(uenum, &length, &status);
116 if (str == 0 || U_FAILURE(status)) {
117 return 0;
118 }
119 if (resultLength) {
120 //the bug is that uenum_next doesn't set the length
121 *resultLength = (length == -1) ? strlen(str) : length;
122 }
123
124 return str;
125 }
126
reset(UErrorCode & status)127 void reset(UErrorCode& status)
128 {
129 uenum_reset(uenum, &status);
130 }
131
132 virtual UClassID getDynamicClassID() const;
133
134 static UClassID U_EXPORT2 getStaticClassID();
135
136 private:
137 UEnumeration *uenum;
138 };
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(BugStringCharEnumeration)139 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(BugStringCharEnumeration)
140
141 U_CFUNC PHP_FUNCTION(intlcal_get_keyword_values_for_locale)
142 {
143 UErrorCode status = U_ZERO_ERROR;
144 char *key,
145 *locale;
146 int key_len,
147 locale_len;
148 zend_bool commonly_used;
149 intl_error_reset(NULL TSRMLS_CC);
150
151 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssb",
152 &key, &key_len, &locale, &locale_len, &commonly_used) == FAILURE) {
153 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
154 "intlcal_get_keyword_values_for_locale: bad arguments", 0 TSRMLS_CC);
155 RETURN_FALSE;
156 }
157
158 //does not work; see ICU bug 9194
159 #if 0
160 StringEnumeration *se = Calendar::getKeywordValuesForLocale(key,
161 Locale::createFromName(locale), (UBool)commonly_used,
162 status);
163 if (se == NULL) {
164 intl_error_set(NULL, status, "intlcal_get_keyword_values_for_locale: "
165 "error calling underlying method", 0 TSRMLS_CC);
166 RETURN_FALSE;
167 }
168 #else
169 UEnumeration *uenum = ucal_getKeywordValuesForLocale(
170 key, locale, !!commonly_used, &status);
171 if (U_FAILURE(status)) {
172 uenum_close(uenum);
173 intl_error_set(NULL, status, "intlcal_get_keyword_values_for_locale: "
174 "error calling underlying method", 0 TSRMLS_CC);
175 RETURN_FALSE;
176 }
177
178 StringEnumeration *se = new BugStringCharEnumeration(uenum);
179 #endif
180
181 IntlIterator_from_StringEnumeration(se, return_value TSRMLS_CC);
182 }
183 #endif //ICU 4.2 only
184
PHP_FUNCTION(intlcal_get_now)185 U_CFUNC PHP_FUNCTION(intlcal_get_now)
186 {
187 intl_error_reset(NULL TSRMLS_CC);
188
189 if (zend_parse_parameters_none() == FAILURE) {
190 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
191 "intlcal_get_now: bad arguments", 0 TSRMLS_CC);
192 RETURN_FALSE;
193 }
194
195 RETURN_DOUBLE((double)Calendar::getNow());
196 }
197
PHP_FUNCTION(intlcal_get_available_locales)198 U_CFUNC PHP_FUNCTION(intlcal_get_available_locales)
199 {
200 intl_error_reset(NULL TSRMLS_CC);
201
202 if (zend_parse_parameters_none() == FAILURE) {
203 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
204 "intlcal_get_available_locales: bad arguments", 0 TSRMLS_CC);
205 RETURN_FALSE;
206 }
207
208 int32_t count;
209 const Locale *availLocales = Calendar::getAvailableLocales(count);
210 array_init(return_value);
211 for (int i = 0; i < count; i++) {
212 Locale locale = availLocales[i];
213 add_next_index_string(return_value, locale.getName(), 1);
214 }
215 }
216
_php_intlcal_field_uec_ret_in32t_method(int32_t (Calendar::* func)(UCalendarDateFields,UErrorCode &)const,const char * method_name,INTERNAL_FUNCTION_PARAMETERS)217 static void _php_intlcal_field_uec_ret_in32t_method(
218 int32_t (Calendar::*func)(UCalendarDateFields, UErrorCode&) const,
219 const char *method_name,
220 INTERNAL_FUNCTION_PARAMETERS)
221 {
222 long field;
223 char *message;
224 CALENDAR_METHOD_INIT_VARS;
225
226 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
227 "Ol", &object, Calendar_ce_ptr, &field) == FAILURE) {
228 spprintf(&message, 0, "%s: bad arguments", method_name);
229 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, message, 1 TSRMLS_CC);
230 efree(message);
231 RETURN_FALSE;
232 }
233
234 if (field < 0 || field >= UCAL_FIELD_COUNT) {
235 spprintf(&message, 0, "%s: invalid field", method_name);
236 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, message, 1 TSRMLS_CC);
237 efree(message);
238 RETURN_FALSE;
239 }
240
241 CALENDAR_METHOD_FETCH_OBJECT;
242
243 int32_t result = (co->ucal->*func)(
244 (UCalendarDateFields)field, CALENDAR_ERROR_CODE(co));
245 INTL_METHOD_CHECK_STATUS(co, "Call to ICU method has failed");
246
247 RETURN_LONG((long)result);
248 }
249
PHP_FUNCTION(intlcal_get)250 U_CFUNC PHP_FUNCTION(intlcal_get)
251 {
252 _php_intlcal_field_uec_ret_in32t_method(&Calendar::get,
253 "intlcal_get", INTERNAL_FUNCTION_PARAM_PASSTHRU);
254 }
255
PHP_FUNCTION(intlcal_get_time)256 U_CFUNC PHP_FUNCTION(intlcal_get_time)
257 {
258 CALENDAR_METHOD_INIT_VARS;
259
260 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
261 &object, Calendar_ce_ptr) == FAILURE) {
262 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
263 "intlcal_get_time: bad arguments", 0 TSRMLS_CC);
264 RETURN_FALSE;
265 }
266
267 CALENDAR_METHOD_FETCH_OBJECT;
268
269 UDate result = co->ucal->getTime(CALENDAR_ERROR_CODE(co));
270 INTL_METHOD_CHECK_STATUS(co,
271 "intlcal_get_time: error calling ICU Calendar::getTime");
272
273 RETURN_DOUBLE((double)result);
274 }
275
PHP_FUNCTION(intlcal_set_time)276 U_CFUNC PHP_FUNCTION(intlcal_set_time)
277 {
278 double time_arg;
279 CALENDAR_METHOD_INIT_VARS;
280
281 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Od",
282 &object, Calendar_ce_ptr, &time_arg) == FAILURE) {
283 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
284 "intlcal_set_time: bad arguments", 0 TSRMLS_CC);
285 RETURN_FALSE;
286 }
287
288 CALENDAR_METHOD_FETCH_OBJECT;
289
290 co->ucal->setTime((UDate)time_arg, CALENDAR_ERROR_CODE(co));
291 INTL_METHOD_CHECK_STATUS(co, "Call to underlying method failed");
292
293 RETURN_TRUE;
294 }
295
PHP_FUNCTION(intlcal_add)296 U_CFUNC PHP_FUNCTION(intlcal_add)
297 {
298 long field,
299 amount;
300 CALENDAR_METHOD_INIT_VARS;
301
302 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
303 "Oll", &object, Calendar_ce_ptr, &field, &amount) == FAILURE) {
304 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
305 "intlcal_add: bad arguments", 0 TSRMLS_CC);
306 RETURN_FALSE;
307 }
308
309 if (field < 0 || field >= UCAL_FIELD_COUNT) {
310 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
311 "intlcal_add: invalid field", 0 TSRMLS_CC);
312 RETURN_FALSE;
313 }
314 if (amount < INT32_MIN || amount > INT32_MAX) {
315 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
316 "intlcal_add: amount out of bounds", 0 TSRMLS_CC);
317 RETURN_FALSE;
318 }
319
320 CALENDAR_METHOD_FETCH_OBJECT;
321
322 co->ucal->add((UCalendarDateFields)field, (int32_t)amount, CALENDAR_ERROR_CODE(co));
323 INTL_METHOD_CHECK_STATUS(co, "intlcal_add: Call to underlying method failed");
324
325 RETURN_TRUE;
326 }
327
PHP_FUNCTION(intlcal_set_time_zone)328 U_CFUNC PHP_FUNCTION(intlcal_set_time_zone)
329 {
330 zval *zv_timezone;
331 TimeZone *timeZone;
332 CALENDAR_METHOD_INIT_VARS;
333
334 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
335 "Oz!", &object, Calendar_ce_ptr, &zv_timezone) == FAILURE) {
336 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
337 "intlcal_set_time_zone: bad arguments", 0 TSRMLS_CC);
338 RETURN_FALSE;
339 }
340
341 CALENDAR_METHOD_FETCH_OBJECT;
342
343 if (zv_timezone == NULL) {
344 RETURN_TRUE; /* the method does nothing if passed null */
345 }
346
347 timeZone = timezone_process_timezone_argument(&zv_timezone,
348 CALENDAR_ERROR_P(co), "intlcal_set_time_zone" TSRMLS_CC);
349 if (timeZone == NULL) {
350 RETURN_FALSE;
351 }
352
353 co->ucal->adoptTimeZone(timeZone);
354
355 RETURN_TRUE;
356 }
357
358
_php_intlcal_before_after(UBool (Calendar::* func)(const Calendar &,UErrorCode &)const,INTERNAL_FUNCTION_PARAMETERS)359 static void _php_intlcal_before_after(
360 UBool (Calendar::*func)(const Calendar&, UErrorCode&) const,
361 INTERNAL_FUNCTION_PARAMETERS)
362 {
363 zval *when_object;
364 Calendar_object *when_co;
365 CALENDAR_METHOD_INIT_VARS;
366
367 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
368 "OO", &object, Calendar_ce_ptr, &when_object, Calendar_ce_ptr)
369 == FAILURE) {
370 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
371 "intlcal_before/after: bad arguments", 0 TSRMLS_CC);
372 RETURN_FALSE;
373 }
374
375 CALENDAR_METHOD_FETCH_OBJECT;
376
377 when_co = static_cast<Calendar_object*>(
378 zend_object_store_get_object(when_object TSRMLS_CC));
379 if (when_co->ucal == NULL) {
380 intl_errors_set(&co->err, U_ILLEGAL_ARGUMENT_ERROR,
381 "intlcal_before/after: Other IntlCalendar was unconstructed", 0 TSRMLS_CC);
382 RETURN_FALSE;
383 }
384
385 UBool res = (co->ucal->*func)(*when_co->ucal, CALENDAR_ERROR_CODE(co));
386 INTL_METHOD_CHECK_STATUS(co, "intlcal_before/after: Error calling ICU method");
387
388 RETURN_BOOL((int)res);
389 }
390
PHP_FUNCTION(intlcal_after)391 U_CFUNC PHP_FUNCTION(intlcal_after)
392 {
393 _php_intlcal_before_after(&Calendar::after, INTERNAL_FUNCTION_PARAM_PASSTHRU);
394 }
395
PHP_FUNCTION(intlcal_before)396 U_CFUNC PHP_FUNCTION(intlcal_before)
397 {
398 _php_intlcal_before_after(&Calendar::before, INTERNAL_FUNCTION_PARAM_PASSTHRU);
399 }
400
PHP_FUNCTION(intlcal_set)401 U_CFUNC PHP_FUNCTION(intlcal_set)
402 {
403 long arg1, arg2, arg3, arg4, arg5, arg6;
404 zval **args_a[7] = {0},
405 ***args = &args_a[0];
406 int i;
407 int variant; /* number of args of the set() overload */
408 CALENDAR_METHOD_INIT_VARS;
409
410 /* must come before zpp because zpp would convert the args in the stack to 0 */
411 if (ZEND_NUM_ARGS() > (getThis() ? 6 : 7) ||
412 zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) {
413 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
414 "intlcal_set: too many arguments", 0 TSRMLS_CC);
415 RETURN_FALSE;
416 }
417 if (!getThis()) {
418 args++;
419 }
420 variant = ZEND_NUM_ARGS() - (getThis() ? 0 : 1);
421 while (variant > 2 && Z_TYPE_PP(args[variant - 1]) == IS_NULL) {
422 variant--;
423 }
424
425 if (variant == 4 ||
426 zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
427 "Oll|llll", &object, Calendar_ce_ptr, &arg1, &arg2, &arg3, &arg4,
428 &arg5, &arg6) == FAILURE) {
429 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
430 "intlcal_set: bad arguments", 0 TSRMLS_CC);
431 RETURN_FALSE;
432 }
433
434 for (i = 0; i < variant; i++) {
435 if (Z_LVAL_PP(args[i]) < INT32_MIN || Z_LVAL_PP(args[i]) > INT32_MAX) {
436 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
437 "intlcal_set: at least one of the arguments has an absolute "
438 "value that is too large", 0 TSRMLS_CC);
439 RETURN_FALSE;
440 }
441 }
442
443 if (variant == 2 && (arg1 < 0 || arg1 >= UCAL_FIELD_COUNT)) {
444 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
445 "intlcal_set: invalid field", 0 TSRMLS_CC);
446 RETURN_FALSE;
447 }
448
449 CALENDAR_METHOD_FETCH_OBJECT;
450
451 if (variant == 2) {
452 co->ucal->set((UCalendarDateFields)arg1, (int32_t)arg2);
453 } else if (variant == 3) {
454 co->ucal->set((int32_t)arg1, (int32_t)arg2, (int32_t)arg3);
455 } else if (variant == 5) {
456 co->ucal->set((int32_t)arg1, (int32_t)arg2, (int32_t)arg3, (int32_t)arg4, (int32_t)arg5);
457 } else if (variant == 6) {
458 co->ucal->set((int32_t)arg1, (int32_t)arg2, (int32_t)arg3, (int32_t)arg4, (int32_t)arg5, (int32_t)arg6);
459 }
460
461 RETURN_TRUE;
462 }
463
PHP_FUNCTION(intlcal_roll)464 U_CFUNC PHP_FUNCTION(intlcal_roll)
465 {
466 long field,
467 value;
468 zval **args_a[3] = {0},
469 ***args = &args_a[0];
470 zend_bool bool_variant_val = (zend_bool)-1;
471 CALENDAR_METHOD_INIT_VARS;
472
473 if (ZEND_NUM_ARGS() > (getThis() ? 2 :3) ||
474 zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) {
475 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
476 "intlcal_set: too many arguments", 0 TSRMLS_CC);
477 RETURN_FALSE;
478 }
479 if (!getThis()) {
480 args++;
481 }
482 if (args[1] != NULL && Z_TYPE_PP(args[1]) == IS_BOOL) {
483 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
484 "Olb", &object, Calendar_ce_ptr, &field, &bool_variant_val)
485 == FAILURE) {
486 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
487 "intlcal_roll: bad arguments", 0 TSRMLS_CC);
488 RETURN_FALSE;
489 }
490 bool_variant_val = Z_BVAL_PP(args[1]);
491 } else if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
492 "Oll", &object, Calendar_ce_ptr, &field, &value) == FAILURE) {
493 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
494 "intlcal_roll: bad arguments", 0 TSRMLS_CC);
495 RETURN_FALSE;
496 }
497
498 if (field < 0 || field >= UCAL_FIELD_COUNT) {
499 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
500 "intlcal_roll: invalid field", 0 TSRMLS_CC);
501 RETURN_FALSE;
502 }
503 if (bool_variant_val == (zend_bool)-1 &&
504 (value < INT32_MIN || value > INT32_MAX)) {
505 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
506 "intlcal_roll: value out of bounds", 0 TSRMLS_CC);
507 RETURN_FALSE;
508 }
509
510 CALENDAR_METHOD_FETCH_OBJECT;
511
512 if (bool_variant_val != (zend_bool)-1) {
513 co->ucal->roll((UCalendarDateFields)field, (UBool)bool_variant_val,
514 CALENDAR_ERROR_CODE(co));
515 } else {
516 co->ucal->roll((UCalendarDateFields)field, (int32_t)value,
517 CALENDAR_ERROR_CODE(co));
518 }
519 INTL_METHOD_CHECK_STATUS(co, "intlcal_roll: Error calling ICU Calendar::roll");
520
521 RETURN_TRUE;
522 }
523
PHP_FUNCTION(intlcal_clear)524 U_CFUNC PHP_FUNCTION(intlcal_clear)
525 {
526 zval **args_a[2] = {0},
527 ***args = &args_a[0];
528 long field;
529 int variant;
530 CALENDAR_METHOD_INIT_VARS;
531
532 if (ZEND_NUM_ARGS() > (getThis() ? 1 : 2) ||
533 zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) {
534 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
535 "intlcal_clear: too many arguments", 0 TSRMLS_CC);
536 RETURN_FALSE;
537 }
538 if (!getThis()) {
539 args++;
540 }
541 if (args[0] == NULL || Z_TYPE_PP(args[0]) == IS_NULL) {
542 zval *dummy; /* we know it's null */
543 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
544 getThis(), "O|z", &object, Calendar_ce_ptr, &dummy) == FAILURE) {
545 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
546 "intlcal_clear: bad arguments", 0 TSRMLS_CC);
547 RETURN_FALSE;
548 }
549 variant = 0;
550 } else if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
551 getThis(), "Ol", &object, Calendar_ce_ptr, &field) == FAILURE) {
552 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
553 "intlcal_clear: bad arguments", 0 TSRMLS_CC);
554 RETURN_FALSE;
555 } else if (field < 0 || field >= UCAL_FIELD_COUNT) {
556 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
557 "intlcal_clear: invalid field", 0 TSRMLS_CC);
558 RETURN_FALSE;
559 } else {
560 variant = 1;
561 }
562
563 CALENDAR_METHOD_FETCH_OBJECT;
564
565 if (variant == 0) {
566 co->ucal->clear();
567 } else {
568 co->ucal->clear((UCalendarDateFields)field);
569 }
570
571 RETURN_TRUE;
572 }
573
PHP_FUNCTION(intlcal_field_difference)574 U_CFUNC PHP_FUNCTION(intlcal_field_difference)
575 {
576 long field;
577 double when;
578 CALENDAR_METHOD_INIT_VARS;
579
580 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
581 "Odl", &object, Calendar_ce_ptr, &when, &field) == FAILURE) {
582 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
583 "intlcal_field_difference: bad arguments", 0 TSRMLS_CC);
584 RETURN_FALSE;
585 }
586
587 if (field < 0 || field >= UCAL_FIELD_COUNT) {
588 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
589 "intlcal_field_difference: invalid field", 0 TSRMLS_CC);
590 RETURN_FALSE;
591 }
592
593 CALENDAR_METHOD_FETCH_OBJECT;
594
595 int32_t result = co->ucal->fieldDifference((UDate)when,
596 (UCalendarDateFields)field, CALENDAR_ERROR_CODE(co));
597 INTL_METHOD_CHECK_STATUS(co,
598 "intlcal_field_difference: Call to ICU method has failed");
599
600 RETURN_LONG((long)result);
601 }
602
PHP_FUNCTION(intlcal_get_actual_maximum)603 U_CFUNC PHP_FUNCTION(intlcal_get_actual_maximum)
604 {
605 _php_intlcal_field_uec_ret_in32t_method(&Calendar::getActualMaximum,
606 "intlcal_get_actual_maximum", INTERNAL_FUNCTION_PARAM_PASSTHRU);
607 }
608
PHP_FUNCTION(intlcal_get_actual_minimum)609 U_CFUNC PHP_FUNCTION(intlcal_get_actual_minimum)
610 {
611 _php_intlcal_field_uec_ret_in32t_method(&Calendar::getActualMinimum,
612 "intlcal_get_actual_minimum", INTERNAL_FUNCTION_PARAM_PASSTHRU);
613 }
614
615 #if U_ICU_VERSION_MAJOR_NUM * 10 + U_ICU_VERSION_MINOR_NUM >= 44
PHP_FUNCTION(intlcal_get_day_of_week_type)616 U_CFUNC PHP_FUNCTION(intlcal_get_day_of_week_type)
617 {
618 long dow;
619 CALENDAR_METHOD_INIT_VARS;
620
621 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
622 "Ol", &object, Calendar_ce_ptr, &dow) == FAILURE) {
623 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
624 "intlcal_get_day_of_week_type: bad arguments", 0 TSRMLS_CC);
625 RETURN_FALSE;
626 }
627
628 if (dow < UCAL_SUNDAY || dow > UCAL_SATURDAY) {
629 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
630 "intlcal_get_day_of_week_type: invalid day of week", 0 TSRMLS_CC);
631 RETURN_FALSE;
632 }
633
634 CALENDAR_METHOD_FETCH_OBJECT;
635
636 int32_t result = co->ucal->getDayOfWeekType(
637 (UCalendarDaysOfWeek)dow, CALENDAR_ERROR_CODE(co));
638 INTL_METHOD_CHECK_STATUS(co,
639 "intlcal_get_day_of_week_type: Call to ICU method has failed");
640
641 RETURN_LONG((long)result);
642 }
643 #endif
644
PHP_FUNCTION(intlcal_get_first_day_of_week)645 U_CFUNC PHP_FUNCTION(intlcal_get_first_day_of_week)
646 {
647 CALENDAR_METHOD_INIT_VARS;
648
649 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
650 "O", &object, Calendar_ce_ptr) == FAILURE) {
651 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
652 "intlcal_get_first_day_of_week: bad arguments", 0 TSRMLS_CC);
653 RETURN_FALSE;
654 }
655
656 CALENDAR_METHOD_FETCH_OBJECT;
657
658 int32_t result = co->ucal->getFirstDayOfWeek(CALENDAR_ERROR_CODE(co));
659 INTL_METHOD_CHECK_STATUS(co,
660 "intlcal_get_first_day_of_week: Call to ICU method has failed");
661
662 RETURN_LONG((long)result);
663 }
664
_php_intlcal_field_ret_in32t_method(int32_t (Calendar::* func)(UCalendarDateFields)const,const char * method_name,INTERNAL_FUNCTION_PARAMETERS)665 static void _php_intlcal_field_ret_in32t_method(
666 int32_t (Calendar::*func)(UCalendarDateFields) const,
667 const char *method_name,
668 INTERNAL_FUNCTION_PARAMETERS)
669 {
670 long field;
671 char *message;
672 CALENDAR_METHOD_INIT_VARS;
673
674 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
675 "Ol", &object, Calendar_ce_ptr, &field) == FAILURE) {
676 spprintf(&message, 0, "%s: bad arguments", method_name);
677 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, message, 1 TSRMLS_CC);
678 efree(message);
679 RETURN_FALSE;
680 }
681
682 if (field < 0 || field >= UCAL_FIELD_COUNT) {
683 spprintf(&message, 0, "%s: invalid field", method_name);
684 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, message, 1 TSRMLS_CC);
685 efree(message);
686 RETURN_FALSE;
687 }
688
689 CALENDAR_METHOD_FETCH_OBJECT;
690
691 int32_t result = (co->ucal->*func)((UCalendarDateFields)field);
692 INTL_METHOD_CHECK_STATUS(co, "Call to ICU method has failed");
693
694 RETURN_LONG((long)result);
695 }
696
PHP_FUNCTION(intlcal_get_greatest_minimum)697 U_CFUNC PHP_FUNCTION(intlcal_get_greatest_minimum)
698 {
699 _php_intlcal_field_ret_in32t_method(&Calendar::getGreatestMinimum,
700 "intlcal_get_greatest_minimum", INTERNAL_FUNCTION_PARAM_PASSTHRU);
701 }
702
PHP_FUNCTION(intlcal_get_least_maximum)703 U_CFUNC PHP_FUNCTION(intlcal_get_least_maximum)
704 {
705 _php_intlcal_field_ret_in32t_method(&Calendar::getLeastMaximum,
706 "intlcal_get_least_maximum", INTERNAL_FUNCTION_PARAM_PASSTHRU);
707 }
708
PHP_FUNCTION(intlcal_get_locale)709 U_CFUNC PHP_FUNCTION(intlcal_get_locale)
710 {
711 long locale_type;
712 CALENDAR_METHOD_INIT_VARS;
713
714 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
715 "Ol", &object, Calendar_ce_ptr, &locale_type) == FAILURE) {
716 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
717 "intlcal_get_locale: bad arguments", 0 TSRMLS_CC);
718 RETURN_FALSE;
719 }
720
721 if (locale_type != ULOC_ACTUAL_LOCALE && locale_type != ULOC_VALID_LOCALE) {
722 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
723 "intlcal_get_locale: invalid locale type", 0 TSRMLS_CC);
724 RETURN_FALSE;
725 }
726
727 CALENDAR_METHOD_FETCH_OBJECT;
728
729 Locale locale = co->ucal->getLocale((ULocDataLocaleType)locale_type,
730 CALENDAR_ERROR_CODE(co));
731 INTL_METHOD_CHECK_STATUS(co,
732 "intlcal_get_locale: Call to ICU method has failed");
733
734 RETURN_STRING(locale.getName(), 1);
735 }
736
PHP_FUNCTION(intlcal_get_maximum)737 U_CFUNC PHP_FUNCTION(intlcal_get_maximum)
738 {
739 _php_intlcal_field_ret_in32t_method(&Calendar::getMaximum,
740 "intlcal_get_maximum", INTERNAL_FUNCTION_PARAM_PASSTHRU);
741 }
742
PHP_FUNCTION(intlcal_get_minimal_days_in_first_week)743 U_CFUNC PHP_FUNCTION(intlcal_get_minimal_days_in_first_week)
744 {
745 CALENDAR_METHOD_INIT_VARS;
746
747 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
748 "O", &object, Calendar_ce_ptr) == FAILURE) {
749 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
750 "intlcal_get_minimal_days_in_first_week: bad arguments", 0 TSRMLS_CC);
751 RETURN_FALSE;
752 }
753
754 CALENDAR_METHOD_FETCH_OBJECT;
755
756 uint8_t result = co->ucal->getMinimalDaysInFirstWeek();
757 INTL_METHOD_CHECK_STATUS(co,
758 "intlcal_get_first_day_of_week: Call to ICU method has failed");
759
760 RETURN_LONG((long)result);
761 }
762
PHP_FUNCTION(intlcal_get_minimum)763 U_CFUNC PHP_FUNCTION(intlcal_get_minimum)
764 {
765 _php_intlcal_field_ret_in32t_method(&Calendar::getMinimum,
766 "intlcal_get_minimum", INTERNAL_FUNCTION_PARAM_PASSTHRU);
767 }
768
PHP_FUNCTION(intlcal_get_time_zone)769 U_CFUNC PHP_FUNCTION(intlcal_get_time_zone)
770 {
771 CALENDAR_METHOD_INIT_VARS;
772
773 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
774 "O", &object, Calendar_ce_ptr) == FAILURE) {
775 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
776 "intlcal_get_time_zone: bad arguments", 0 TSRMLS_CC);
777 RETURN_FALSE;
778 }
779
780 CALENDAR_METHOD_FETCH_OBJECT;
781
782 TimeZone *tz = co->ucal->getTimeZone().clone();
783 if (tz == NULL) {
784 intl_errors_set(CALENDAR_ERROR_P(co), U_MEMORY_ALLOCATION_ERROR,
785 "intlcal_get_time_zone: could not clone TimeZone", 0 TSRMLS_CC);
786 RETURN_FALSE;
787 }
788
789 timezone_object_construct(tz, return_value, 1 TSRMLS_CC);
790 }
791
PHP_FUNCTION(intlcal_get_type)792 U_CFUNC PHP_FUNCTION(intlcal_get_type)
793 {
794 CALENDAR_METHOD_INIT_VARS;
795
796 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
797 "O", &object, Calendar_ce_ptr) == FAILURE) {
798 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
799 "intlcal_get_type: bad arguments", 0 TSRMLS_CC);
800 RETURN_FALSE;
801 }
802
803 CALENDAR_METHOD_FETCH_OBJECT;
804
805 RETURN_STRING(co->ucal->getType(), 1);
806 }
807
808 #if U_ICU_VERSION_MAJOR_NUM * 10 + U_ICU_VERSION_MINOR_NUM >= 44
PHP_FUNCTION(intlcal_get_weekend_transition)809 U_CFUNC PHP_FUNCTION(intlcal_get_weekend_transition)
810 {
811 long dow;
812 CALENDAR_METHOD_INIT_VARS;
813
814 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
815 "Ol", &object, Calendar_ce_ptr, &dow) == FAILURE) {
816 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
817 "intlcal_get_weekend_transition: bad arguments", 0 TSRMLS_CC);
818 RETURN_FALSE;
819 }
820
821 if (dow < UCAL_SUNDAY || dow > UCAL_SATURDAY) {
822 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
823 "intlcal_get_weekend_transition: invalid day of week", 0 TSRMLS_CC);
824 RETURN_FALSE;
825 }
826
827 CALENDAR_METHOD_FETCH_OBJECT;
828
829 int32_t res = co->ucal->getWeekendTransition((UCalendarDaysOfWeek)dow,
830 CALENDAR_ERROR_CODE(co));
831 INTL_METHOD_CHECK_STATUS(co, "intlcal_get_weekend_transition: "
832 "Error calling ICU method");
833
834 RETURN_LONG((long)res);
835 }
836 #endif
837
PHP_FUNCTION(intlcal_in_daylight_time)838 U_CFUNC PHP_FUNCTION(intlcal_in_daylight_time)
839 {
840 CALENDAR_METHOD_INIT_VARS;
841
842 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
843 "O", &object, Calendar_ce_ptr) == FAILURE) {
844 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
845 "intlcal_in_daylight_time: bad arguments", 0 TSRMLS_CC);
846 RETURN_FALSE;
847 }
848
849 CALENDAR_METHOD_FETCH_OBJECT;
850
851 UBool ret = co->ucal->inDaylightTime(CALENDAR_ERROR_CODE(co));
852 INTL_METHOD_CHECK_STATUS(co, "intlcal_in_daylight_time: "
853 "Error calling ICU method");
854
855 RETURN_BOOL((int)ret);
856 }
857
PHP_FUNCTION(intlcal_is_equivalent_to)858 U_CFUNC PHP_FUNCTION(intlcal_is_equivalent_to)
859 {
860 zval *other_object;
861 Calendar_object *other_co;
862 CALENDAR_METHOD_INIT_VARS;
863
864 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
865 "OO", &object, Calendar_ce_ptr, &other_object, Calendar_ce_ptr)
866 == FAILURE) {
867 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
868 "intlcal_is_equivalent_to: bad arguments", 0 TSRMLS_CC);
869 RETURN_FALSE;
870 }
871
872 other_co = (Calendar_object*)zend_object_store_get_object(other_object TSRMLS_CC);
873 if (other_co->ucal == NULL) {
874 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "intlcal_is_equivalent_to:"
875 " Other IntlCalendar is unconstructed", 0 TSRMLS_CC);
876 RETURN_FALSE;
877 }
878
879 CALENDAR_METHOD_FETCH_OBJECT;
880
881 RETURN_BOOL((int)co->ucal->isEquivalentTo(*other_co->ucal));
882 }
883
PHP_FUNCTION(intlcal_is_lenient)884 U_CFUNC PHP_FUNCTION(intlcal_is_lenient)
885 {
886 CALENDAR_METHOD_INIT_VARS;
887
888 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
889 "O", &object, Calendar_ce_ptr) == FAILURE) {
890 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
891 "intlcal_is_lenient: bad arguments", 0 TSRMLS_CC);
892 RETURN_FALSE;
893 }
894
895 CALENDAR_METHOD_FETCH_OBJECT;
896
897 RETURN_BOOL((int)co->ucal->isLenient());
898 }
899
PHP_FUNCTION(intlcal_is_set)900 U_CFUNC PHP_FUNCTION(intlcal_is_set)
901 {
902 long field;
903 CALENDAR_METHOD_INIT_VARS;
904
905 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
906 "Ol", &object, Calendar_ce_ptr, &field) == FAILURE) {
907 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
908 "intlcal_is_set: bad arguments", 0 TSRMLS_CC);
909 RETURN_FALSE;
910 }
911
912 if (field < 0 || field >= UCAL_FIELD_COUNT) {
913 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
914 "intlcal_is_set: invalid field", 0 TSRMLS_CC);
915 RETURN_FALSE;
916 }
917
918 CALENDAR_METHOD_FETCH_OBJECT;
919
920 RETURN_BOOL((int)co->ucal->isSet((UCalendarDateFields)field));
921 }
922
923 #if U_ICU_VERSION_MAJOR_NUM * 10 + U_ICU_VERSION_MINOR_NUM >= 44
PHP_FUNCTION(intlcal_is_weekend)924 U_CFUNC PHP_FUNCTION(intlcal_is_weekend)
925 {
926 double date;
927 zval *rawDate = NULL;
928 CALENDAR_METHOD_INIT_VARS;
929
930 if (zend_parse_method_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
931 ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
932 "O|z!", &object, Calendar_ce_ptr, &rawDate) == FAILURE
933 || (rawDate != NULL &&
934 zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
935 "O|d", &object, Calendar_ce_ptr, &date) == FAILURE)) {
936 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
937 "intlcal_is_weekend: bad arguments", 0 TSRMLS_CC);
938 RETURN_FALSE;
939 }
940
941 CALENDAR_METHOD_FETCH_OBJECT;
942
943 if (rawDate == NULL) {
944 RETURN_BOOL((int)co->ucal->isWeekend());
945 } else {
946 UBool ret = co->ucal->isWeekend((UDate)date, CALENDAR_ERROR_CODE(co));
947 INTL_METHOD_CHECK_STATUS(co, "intlcal_is_weekend: "
948 "Error calling ICU method");
949 RETURN_BOOL((int)ret);
950 }
951 }
952 #endif
953
954
PHP_FUNCTION(intlcal_set_first_day_of_week)955 U_CFUNC PHP_FUNCTION(intlcal_set_first_day_of_week)
956 {
957 long dow;
958 CALENDAR_METHOD_INIT_VARS;
959
960 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
961 "Ol", &object, Calendar_ce_ptr, &dow) == FAILURE) {
962 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
963 "intlcal_set_first_day_of_week: bad arguments", 0 TSRMLS_CC);
964 RETURN_FALSE;
965 }
966
967 if (dow < UCAL_SUNDAY || dow > UCAL_SATURDAY) {
968 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
969 "intlcal_set_first_day_of_week: invalid day of week", 0 TSRMLS_CC);
970 RETURN_FALSE;
971 }
972
973 CALENDAR_METHOD_FETCH_OBJECT;
974
975 co->ucal->setFirstDayOfWeek((UCalendarDaysOfWeek)dow);
976
977 RETURN_TRUE;
978 }
979
PHP_FUNCTION(intlcal_set_lenient)980 U_CFUNC PHP_FUNCTION(intlcal_set_lenient)
981 {
982 zend_bool is_lenient;
983 CALENDAR_METHOD_INIT_VARS;
984
985 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
986 "Ob", &object, Calendar_ce_ptr, &is_lenient) == FAILURE) {
987 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
988 "intlcal_set_lenient: bad arguments", 0 TSRMLS_CC);
989 RETURN_FALSE;
990 }
991
992 CALENDAR_METHOD_FETCH_OBJECT;
993
994 co->ucal->setLenient((UBool) is_lenient);
995
996 RETURN_TRUE;
997 }
998
PHP_FUNCTION(intlcal_set_minimal_days_in_first_week)999 U_CFUNC PHP_FUNCTION(intlcal_set_minimal_days_in_first_week)
1000 {
1001 long num_days;
1002 CALENDAR_METHOD_INIT_VARS;
1003
1004 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
1005 "Ol", &object, Calendar_ce_ptr, &num_days) == FAILURE) {
1006 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1007 "intlcal_set_minimal_days_in_first_week: bad arguments", 0 TSRMLS_CC);
1008 RETURN_FALSE;
1009 }
1010
1011 if (num_days < 1 || num_days > 7) {
1012 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1013 "intlcal_set_minimal_days_in_first_week: invalid number of days; "
1014 "must be between 1 and 7", 0 TSRMLS_CC);
1015 RETURN_FALSE;
1016 }
1017
1018 CALENDAR_METHOD_FETCH_OBJECT;
1019
1020 co->ucal->setMinimalDaysInFirstWeek((uint8_t)num_days);
1021
1022 RETURN_TRUE;
1023 }
1024
PHP_FUNCTION(intlcal_equals)1025 U_CFUNC PHP_FUNCTION(intlcal_equals)
1026 {
1027 zval *other_object;
1028 Calendar_object *other_co;
1029 CALENDAR_METHOD_INIT_VARS;
1030
1031 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
1032 "OO", &object, Calendar_ce_ptr, &other_object, Calendar_ce_ptr)
1033 == FAILURE) {
1034 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1035 "intlcal_equals: bad arguments", 0 TSRMLS_CC);
1036 RETURN_FALSE;
1037 }
1038
1039 CALENDAR_METHOD_FETCH_OBJECT;
1040 other_co = (Calendar_object *) zend_object_store_get_object(other_object TSRMLS_CC);
1041 if (other_co->ucal == NULL) {
1042 intl_errors_set(&co->err, U_ILLEGAL_ARGUMENT_ERROR,
1043 "intlcal_equals: The second IntlCalendar is unconstructed", 0 TSRMLS_CC);
1044 RETURN_FALSE;
1045 }
1046
1047 UBool result = co->ucal->equals(*other_co->ucal, CALENDAR_ERROR_CODE(co));
1048 INTL_METHOD_CHECK_STATUS(co, "intlcal_equals: error calling ICU Calendar::equals");
1049
1050 RETURN_BOOL((int)result);
1051 }
1052
1053 #if U_ICU_VERSION_MAJOR_NUM >= 49
1054
PHP_FUNCTION(intlcal_get_repeated_wall_time_option)1055 U_CFUNC PHP_FUNCTION(intlcal_get_repeated_wall_time_option)
1056 {
1057 CALENDAR_METHOD_INIT_VARS;
1058
1059 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
1060 "O", &object, Calendar_ce_ptr) == FAILURE) {
1061 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1062 "intlcal_get_repeated_wall_time_option: bad arguments", 0 TSRMLS_CC);
1063 RETURN_FALSE;
1064 }
1065
1066 CALENDAR_METHOD_FETCH_OBJECT;
1067
1068 RETURN_LONG(co->ucal->getRepeatedWallTimeOption());
1069 }
1070
PHP_FUNCTION(intlcal_get_skipped_wall_time_option)1071 U_CFUNC PHP_FUNCTION(intlcal_get_skipped_wall_time_option)
1072 {
1073 CALENDAR_METHOD_INIT_VARS;
1074
1075 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
1076 "O", &object, Calendar_ce_ptr) == FAILURE) {
1077 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1078 "intlcal_get_skipped_wall_time_option: bad arguments", 0 TSRMLS_CC);
1079 RETURN_FALSE;
1080 }
1081
1082 CALENDAR_METHOD_FETCH_OBJECT;
1083
1084 RETURN_LONG(co->ucal->getSkippedWallTimeOption());
1085 }
1086
PHP_FUNCTION(intlcal_set_repeated_wall_time_option)1087 U_CFUNC PHP_FUNCTION(intlcal_set_repeated_wall_time_option)
1088 {
1089 long option;
1090 CALENDAR_METHOD_INIT_VARS;
1091
1092 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
1093 "Ol", &object, Calendar_ce_ptr, &option) == FAILURE) {
1094 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1095 "intlcal_set_repeated_wall_time_option: bad arguments", 0 TSRMLS_CC);
1096 RETURN_FALSE;
1097 }
1098
1099 if (option != UCAL_WALLTIME_FIRST && option != UCAL_WALLTIME_LAST) {
1100 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1101 "intlcal_set_repeated_wall_time_option: invalid option", 0 TSRMLS_CC);
1102 RETURN_FALSE;
1103 }
1104
1105 CALENDAR_METHOD_FETCH_OBJECT;
1106
1107 co->ucal->setRepeatedWallTimeOption((UCalendarWallTimeOption)option);
1108
1109 RETURN_TRUE;
1110 }
1111
PHP_FUNCTION(intlcal_set_skipped_wall_time_option)1112 U_CFUNC PHP_FUNCTION(intlcal_set_skipped_wall_time_option)
1113 {
1114 long option;
1115 CALENDAR_METHOD_INIT_VARS;
1116
1117 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
1118 "Ol", &object, Calendar_ce_ptr, &option) == FAILURE) {
1119 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1120 "intlcal_set_skipped_wall_time_option: bad arguments", 0 TSRMLS_CC);
1121 RETURN_FALSE;
1122 }
1123
1124 if (option != UCAL_WALLTIME_FIRST && option != UCAL_WALLTIME_LAST
1125 && option != UCAL_WALLTIME_NEXT_VALID) {
1126 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1127 "intlcal_set_skipped_wall_time_option: invalid option", 0 TSRMLS_CC);
1128 RETURN_FALSE;
1129 }
1130
1131 CALENDAR_METHOD_FETCH_OBJECT;
1132
1133 co->ucal->setSkippedWallTimeOption((UCalendarWallTimeOption)option);
1134
1135 RETURN_TRUE;
1136 }
1137
1138 #endif
1139
PHP_FUNCTION(intlcal_from_date_time)1140 U_CFUNC PHP_FUNCTION(intlcal_from_date_time)
1141 {
1142 zval **zv_arg,
1143 *zv_datetime = NULL,
1144 *zv_timestamp = NULL;
1145 php_date_obj *datetime;
1146 char *locale_str = NULL;
1147 int locale_str_len;
1148 TimeZone *timeZone;
1149 UErrorCode status = U_ZERO_ERROR;
1150 Calendar *cal;
1151 intl_error_reset(NULL TSRMLS_CC);
1152
1153 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|s!",
1154 &zv_arg, &locale_str, &locale_str_len) == FAILURE) {
1155 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1156 "intlcal_from_date_time: bad arguments", 0 TSRMLS_CC);
1157 RETURN_NULL();
1158 }
1159
1160 if (!(Z_TYPE_PP(zv_arg) == IS_OBJECT && instanceof_function(
1161 Z_OBJCE_PP(zv_arg), php_date_get_date_ce() TSRMLS_CC))) {
1162 ALLOC_INIT_ZVAL(zv_datetime);
1163 object_init_ex(zv_datetime, php_date_get_date_ce());
1164 zend_call_method_with_1_params(&zv_datetime, NULL, NULL, "__construct",
1165 NULL, *zv_arg);
1166 if (EG(exception)) {
1167 zend_object_store_ctor_failed(zv_datetime TSRMLS_CC);
1168 goto error;
1169 }
1170 } else {
1171 zv_datetime = *zv_arg;
1172 }
1173
1174 datetime = (php_date_obj*)zend_object_store_get_object(zv_datetime TSRMLS_CC);
1175 if (!datetime->time) {
1176 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1177 "intlcal_from_date_time: DateTime object is unconstructed",
1178 0 TSRMLS_CC);
1179 goto error;
1180 }
1181
1182 zend_call_method_with_0_params(&zv_datetime, php_date_get_date_ce(),
1183 NULL, "gettimestamp", &zv_timestamp);
1184 if (!zv_timestamp || Z_TYPE_P(zv_timestamp) != IS_LONG) {
1185 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1186 "intlcal_from_date_time: bad DateTime; call to "
1187 "DateTime::getTimestamp() failed", 0 TSRMLS_CC);
1188 goto error;
1189 }
1190
1191 if (!datetime->time->is_localtime) {
1192 timeZone = TimeZone::getGMT()->clone();
1193 } else {
1194 timeZone = timezone_convert_datetimezone(datetime->time->zone_type,
1195 datetime, 1, NULL, "intlcal_from_date_time" TSRMLS_CC);
1196 if (timeZone == NULL) {
1197 goto error;
1198 }
1199 }
1200
1201 if (!locale_str) {
1202 locale_str = const_cast<char*>(intl_locale_get_default(TSRMLS_C));
1203 }
1204
1205 cal = Calendar::createInstance(timeZone,
1206 Locale::createFromName(locale_str), status);
1207 if (cal == NULL) {
1208 delete timeZone;
1209 intl_error_set(NULL, status, "intlcal_from_date_time: "
1210 "error creating ICU Calendar object", 0 TSRMLS_CC);
1211 goto error;
1212 }
1213 cal->setTime(((UDate)Z_LVAL_P(zv_timestamp)) * 1000., status);
1214 if (U_FAILURE(status)) {
1215 /* time zone was adopted by cal; should not be deleted here */
1216 delete cal;
1217 intl_error_set(NULL, status, "intlcal_from_date_time: "
1218 "error creating ICU Calendar::setTime()", 0 TSRMLS_CC);
1219 goto error;
1220 }
1221
1222 calendar_object_create(return_value, cal TSRMLS_CC);
1223
1224 error:
1225 if (zv_datetime != *zv_arg) {
1226 zval_ptr_dtor(&zv_datetime);
1227 }
1228 if (zv_timestamp) {
1229 zval_ptr_dtor(&zv_timestamp);
1230 }
1231 }
1232
PHP_FUNCTION(intlcal_to_date_time)1233 U_CFUNC PHP_FUNCTION(intlcal_to_date_time)
1234 {
1235 zval *retval = NULL;
1236 CALENDAR_METHOD_INIT_VARS;
1237
1238 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
1239 &object, Calendar_ce_ptr) == FAILURE) {
1240 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1241 "intlcal_to_date_time: bad arguments", 0 TSRMLS_CC);
1242 RETURN_FALSE;
1243 }
1244
1245 CALENDAR_METHOD_FETCH_OBJECT;
1246
1247 /* There are no exported functions in ext/date to this
1248 * in a more native fashion */
1249 double date = co->ucal->getTime(CALENDAR_ERROR_CODE(co)) / 1000.;
1250 int64_t ts;
1251 char ts_str[sizeof("@-9223372036854775808")];
1252 int ts_str_len;
1253 zval ts_zval = zval_used_for_init;
1254
1255 INTL_METHOD_CHECK_STATUS(co, "Call to ICU method has failed");
1256
1257 if (date > (double)U_INT64_MAX || date < (double)U_INT64_MIN) {
1258 intl_errors_set(CALENDAR_ERROR_P(co), U_ILLEGAL_ARGUMENT_ERROR,
1259 "intlcal_to_date_time: The calendar date is out of the "
1260 "range for a 64-bit integer", 0 TSRMLS_CC);
1261 RETURN_FALSE;
1262 }
1263
1264 ts = (int64_t)date;
1265
1266 ts_str_len = slprintf(ts_str, sizeof(ts_str), "@%I64d", ts);
1267 ZVAL_STRINGL(&ts_zval, ts_str, ts_str_len, 0);
1268
1269 /* Now get the time zone */
1270 const TimeZone& tz = co->ucal->getTimeZone();
1271 zval *timezone_zval = timezone_convert_to_datetimezone(
1272 &tz, CALENDAR_ERROR_P(co), "intlcal_to_date_time" TSRMLS_CC);
1273 if (timezone_zval == NULL) {
1274 RETURN_FALSE;
1275 }
1276
1277 /* resources allocated from now on */
1278
1279 /* Finally, instantiate object and call constructor */
1280 object_init_ex(return_value, php_date_get_date_ce());
1281 zend_call_method_with_2_params(&return_value, NULL, NULL, "__construct",
1282 NULL, &ts_zval, timezone_zval);
1283 if (EG(exception)) {
1284 intl_errors_set(CALENDAR_ERROR_P(co), U_ILLEGAL_ARGUMENT_ERROR,
1285 "intlcal_to_date_time: DateTime constructor has thrown exception",
1286 1 TSRMLS_CC);
1287 zend_object_store_ctor_failed(return_value TSRMLS_CC);
1288 zval_ptr_dtor(&return_value);
1289
1290 RETVAL_FALSE;
1291 goto error;
1292 }
1293
1294 /* due to bug #40743, we have to set the time zone again */
1295 zend_call_method_with_1_params(&return_value, NULL, NULL, "settimezone",
1296 &retval, timezone_zval);
1297 if (retval == NULL || Z_TYPE_P(retval) == IS_BOOL) {
1298 intl_errors_set(CALENDAR_ERROR_P(co), U_ILLEGAL_ARGUMENT_ERROR,
1299 "intlcal_to_date_time: call to DateTime::setTimeZone has failed",
1300 1 TSRMLS_CC);
1301 zval_ptr_dtor(&return_value);
1302 RETVAL_FALSE;
1303 goto error;
1304 }
1305
1306 error:
1307 zval_ptr_dtor(&timezone_zval);
1308 if (retval != NULL) {
1309 zval_ptr_dtor(&retval);
1310 }
1311 }
1312
PHP_FUNCTION(intlcal_get_error_code)1313 U_CFUNC PHP_FUNCTION(intlcal_get_error_code)
1314 {
1315 CALENDAR_METHOD_INIT_VARS;
1316
1317 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
1318 &object, Calendar_ce_ptr) == FAILURE) {
1319 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1320 "intlcal_get_error_code: bad arguments", 0 TSRMLS_CC);
1321 RETURN_FALSE;
1322 }
1323
1324 /* Fetch the object (without resetting its last error code ). */
1325 co = (Calendar_object*)zend_object_store_get_object(object TSRMLS_CC);
1326 if (co == NULL)
1327 RETURN_FALSE;
1328
1329 RETURN_LONG((long)CALENDAR_ERROR_CODE(co));
1330 }
1331
PHP_FUNCTION(intlcal_get_error_message)1332 U_CFUNC PHP_FUNCTION(intlcal_get_error_message)
1333 {
1334 const char* message = NULL;
1335 CALENDAR_METHOD_INIT_VARS;
1336
1337 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
1338 &object, Calendar_ce_ptr) == FAILURE) {
1339 intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
1340 "intlcal_get_error_message: bad arguments", 0 TSRMLS_CC );
1341 RETURN_FALSE;
1342 }
1343
1344
1345 /* Fetch the object (without resetting its last error code ). */
1346 co = (Calendar_object*)zend_object_store_get_object(object TSRMLS_CC);
1347 if (co == NULL)
1348 RETURN_FALSE;
1349
1350 /* Return last error message. */
1351 message = intl_error_get_message(CALENDAR_ERROR_P(co) TSRMLS_CC);
1352 RETURN_STRING(message, 0);
1353 }
1354