1 /*
2 +----------------------------------------------------------------------+
3 | PHP Version 7 |
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 );
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 size_t dummy;
55 TimeZone *timeZone;
56 UErrorCode status = U_ZERO_ERROR;
57 intl_error_reset(NULL);
58
59 if (zend_parse_parameters(ZEND_NUM_ARGS(), "|zs!",
60 &zv_timezone, &locale_str, &dummy) == FAILURE) {
61 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
62 "intlcal_create_calendar: bad arguments", 0);
63 RETURN_NULL();
64 }
65
66 timeZone = timezone_process_timezone_argument(zv_timezone, NULL,
67 "intlcal_create_instance");
68 if (timeZone == NULL) {
69 RETURN_NULL();
70 }
71
72 if (!locale_str) {
73 locale_str = intl_locale_get_default();
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);
81 RETURN_NULL();
82 }
83
84 calendar_object_create(return_value, cal);
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) ? (int32_t)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 size_t key_len,
147 locale_len;
148 zend_bool commonly_used;
149 intl_error_reset(NULL);
150
151 if (zend_parse_parameters(ZEND_NUM_ARGS(), "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);
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);
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);
175 RETURN_FALSE;
176 }
177
178 StringEnumeration *se = new BugStringCharEnumeration(uenum);
179 #endif
180
181 IntlIterator_from_StringEnumeration(se, return_value);
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);
188
189 if (zend_parse_parameters_none() == FAILURE) {
190 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
191 "intlcal_get_now: bad arguments", 0);
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);
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);
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());
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 zend_long field;
223 char *message;
224 CALENDAR_METHOD_INIT_VARS;
225
226 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), 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);
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);
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((zend_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(), getThis(), "O",
261 &object, Calendar_ce_ptr) == FAILURE) {
262 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
263 "intlcal_get_time: bad arguments", 0);
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(), 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);
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 zend_long field,
299 amount;
300 CALENDAR_METHOD_INIT_VARS;
301
302 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), 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);
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);
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);
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(), 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);
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");
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(), 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);
372 RETURN_FALSE;
373 }
374
375 CALENDAR_METHOD_FETCH_OBJECT;
376
377 when_co = Z_INTL_CALENDAR_P(when_object);
378 if (when_co->ucal == NULL) {
379 intl_errors_set(&co->err, U_ILLEGAL_ARGUMENT_ERROR,
380 "intlcal_before/after: Other IntlCalendar was unconstructed", 0);
381 RETURN_FALSE;
382 }
383
384 UBool res = (co->ucal->*func)(*when_co->ucal, CALENDAR_ERROR_CODE(co));
385 INTL_METHOD_CHECK_STATUS(co, "intlcal_before/after: Error calling ICU method");
386
387 RETURN_BOOL((int)res);
388 }
389
PHP_FUNCTION(intlcal_after)390 U_CFUNC PHP_FUNCTION(intlcal_after)
391 {
392 _php_intlcal_before_after(&Calendar::after, INTERNAL_FUNCTION_PARAM_PASSTHRU);
393 }
394
PHP_FUNCTION(intlcal_before)395 U_CFUNC PHP_FUNCTION(intlcal_before)
396 {
397 _php_intlcal_before_after(&Calendar::before, INTERNAL_FUNCTION_PARAM_PASSTHRU);
398 }
399
PHP_FUNCTION(intlcal_set)400 U_CFUNC PHP_FUNCTION(intlcal_set)
401 {
402 zend_long arg1, arg2, arg3, arg4, arg5, arg6;
403 zval args_a[7] = {0},
404 *args = args_a;
405 int i;
406 int variant; /* number of args of the set() overload */
407 CALENDAR_METHOD_INIT_VARS;
408
409 /* must come before zpp because zpp would convert the args in the stack to 0 */
410 if (ZEND_NUM_ARGS() > (getThis() ? 6 : 7) ||
411 zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) {
412 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
413 "intlcal_set: too many arguments", 0);
414 RETURN_FALSE;
415 }
416 if (!getThis()) {
417 args++;
418 }
419 variant = ZEND_NUM_ARGS() - (getThis() ? 0 : 1);
420 while (variant > 2 && Z_TYPE(args[variant - 1]) == IS_NULL) {
421 variant--;
422 }
423
424 if (variant == 4 ||
425 zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
426 "Oll|llll", &object, Calendar_ce_ptr, &arg1, &arg2, &arg3, &arg4,
427 &arg5, &arg6) == FAILURE) {
428 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
429 "intlcal_set: bad arguments", 0);
430 RETURN_FALSE;
431 }
432
433 for (i = 0; i < variant; i++) {
434 if (Z_LVAL(args[i]) < INT32_MIN || Z_LVAL(args[i]) > INT32_MAX) {
435 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
436 "intlcal_set: at least one of the arguments has an absolute "
437 "value that is too large", 0);
438 RETURN_FALSE;
439 }
440 }
441
442 if (variant == 2 && (arg1 < 0 || arg1 >= UCAL_FIELD_COUNT)) {
443 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
444 "intlcal_set: invalid field", 0);
445 RETURN_FALSE;
446 }
447
448 CALENDAR_METHOD_FETCH_OBJECT;
449
450 if (variant == 2) {
451 co->ucal->set((UCalendarDateFields)arg1, (int32_t)arg2);
452 } else if (variant == 3) {
453 co->ucal->set((int32_t)arg1, (int32_t)arg2, (int32_t)arg3);
454 } else if (variant == 5) {
455 co->ucal->set((int32_t)arg1, (int32_t)arg2, (int32_t)arg3, (int32_t)arg4, (int32_t)arg5);
456 } else if (variant == 6) {
457 co->ucal->set((int32_t)arg1, (int32_t)arg2, (int32_t)arg3, (int32_t)arg4, (int32_t)arg5, (int32_t)arg6);
458 }
459
460 RETURN_TRUE;
461 }
462
PHP_FUNCTION(intlcal_roll)463 U_CFUNC PHP_FUNCTION(intlcal_roll)
464 {
465 zend_long field,
466 value;
467 zval args_a[3] = {0},
468 *args = args_a;
469 zend_bool bool_variant_val = (zend_bool)-1;
470 CALENDAR_METHOD_INIT_VARS;
471
472 if (ZEND_NUM_ARGS() > (getThis() ? 2 :3) ||
473 zend_get_parameters_array_ex(ZEND_NUM_ARGS(), args) == FAILURE) {
474 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
475 "intlcal_set: too many arguments", 0);
476 RETURN_FALSE;
477 }
478 if (!getThis()) {
479 args++;
480 }
481 if (!Z_ISUNDEF(args[1]) && (Z_TYPE(args[1]) == IS_TRUE || Z_TYPE(args[1]) == IS_FALSE)) {
482 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
483 "Olb", &object, Calendar_ce_ptr, &field, &bool_variant_val)
484 == FAILURE) {
485 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
486 "intlcal_roll: bad arguments", 0);
487 RETURN_FALSE;
488 }
489 bool_variant_val = Z_TYPE(args[1]) == IS_TRUE? 1 : 0;
490 } else if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
491 "Oll", &object, Calendar_ce_ptr, &field, &value) == FAILURE) {
492 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
493 "intlcal_roll: bad arguments", 0);
494 RETURN_FALSE;
495 }
496
497 if (field < 0 || field >= UCAL_FIELD_COUNT) {
498 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
499 "intlcal_roll: invalid field", 0);
500 RETURN_FALSE;
501 }
502 if (bool_variant_val == (zend_bool)-1 &&
503 (value < INT32_MIN || value > INT32_MAX)) {
504 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
505 "intlcal_roll: value out of bounds", 0);
506 RETURN_FALSE;
507 }
508
509 CALENDAR_METHOD_FETCH_OBJECT;
510
511 if (bool_variant_val != (zend_bool)-1) {
512 co->ucal->roll((UCalendarDateFields)field, (UBool)bool_variant_val,
513 CALENDAR_ERROR_CODE(co));
514 } else {
515 co->ucal->roll((UCalendarDateFields)field, (int32_t)value,
516 CALENDAR_ERROR_CODE(co));
517 }
518 INTL_METHOD_CHECK_STATUS(co, "intlcal_roll: Error calling ICU Calendar::roll");
519
520 RETURN_TRUE;
521 }
522
PHP_FUNCTION(intlcal_clear)523 U_CFUNC PHP_FUNCTION(intlcal_clear)
524 {
525 zend_long field;
526 zend_bool field_is_null = 1;
527 CALENDAR_METHOD_INIT_VARS;
528
529 if (zend_parse_method_parameters(ZEND_NUM_ARGS(),
530 getThis(), "O|l!", &object, Calendar_ce_ptr, &field, &field_is_null) == FAILURE) {
531 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
532 "intlcal_clear: bad arguments", 0);
533 RETURN_FALSE;
534 }
535
536 CALENDAR_METHOD_FETCH_OBJECT;
537
538 if (field_is_null) {
539 co->ucal->clear();
540 } else {
541 if (field < 0 || field >= UCAL_FIELD_COUNT) {
542 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
543 "intlcal_clear: invalid field", 0);
544 RETURN_FALSE;
545 }
546
547 co->ucal->clear((UCalendarDateFields)field);
548 }
549
550 RETURN_TRUE;
551 }
552
PHP_FUNCTION(intlcal_field_difference)553 U_CFUNC PHP_FUNCTION(intlcal_field_difference)
554 {
555 zend_long field;
556 double when;
557 CALENDAR_METHOD_INIT_VARS;
558
559 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
560 "Odl", &object, Calendar_ce_ptr, &when, &field) == FAILURE) {
561 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
562 "intlcal_field_difference: bad arguments", 0);
563 RETURN_FALSE;
564 }
565
566 if (field < 0 || field >= UCAL_FIELD_COUNT) {
567 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
568 "intlcal_field_difference: invalid field", 0);
569 RETURN_FALSE;
570 }
571
572 CALENDAR_METHOD_FETCH_OBJECT;
573
574 int32_t result = co->ucal->fieldDifference((UDate)when,
575 (UCalendarDateFields)field, CALENDAR_ERROR_CODE(co));
576 INTL_METHOD_CHECK_STATUS(co,
577 "intlcal_field_difference: Call to ICU method has failed");
578
579 RETURN_LONG((zend_long)result);
580 }
581
PHP_FUNCTION(intlcal_get_actual_maximum)582 U_CFUNC PHP_FUNCTION(intlcal_get_actual_maximum)
583 {
584 _php_intlcal_field_uec_ret_in32t_method(&Calendar::getActualMaximum,
585 "intlcal_get_actual_maximum", INTERNAL_FUNCTION_PARAM_PASSTHRU);
586 }
587
PHP_FUNCTION(intlcal_get_actual_minimum)588 U_CFUNC PHP_FUNCTION(intlcal_get_actual_minimum)
589 {
590 _php_intlcal_field_uec_ret_in32t_method(&Calendar::getActualMinimum,
591 "intlcal_get_actual_minimum", INTERNAL_FUNCTION_PARAM_PASSTHRU);
592 }
593
594 #if U_ICU_VERSION_MAJOR_NUM * 10 + U_ICU_VERSION_MINOR_NUM >= 44
PHP_FUNCTION(intlcal_get_day_of_week_type)595 U_CFUNC PHP_FUNCTION(intlcal_get_day_of_week_type)
596 {
597 zend_long dow;
598 CALENDAR_METHOD_INIT_VARS;
599
600 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
601 "Ol", &object, Calendar_ce_ptr, &dow) == FAILURE) {
602 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
603 "intlcal_get_day_of_week_type: bad arguments", 0);
604 RETURN_FALSE;
605 }
606
607 if (dow < UCAL_SUNDAY || dow > UCAL_SATURDAY) {
608 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
609 "intlcal_get_day_of_week_type: invalid day of week", 0);
610 RETURN_FALSE;
611 }
612
613 CALENDAR_METHOD_FETCH_OBJECT;
614
615 int32_t result = co->ucal->getDayOfWeekType(
616 (UCalendarDaysOfWeek)dow, CALENDAR_ERROR_CODE(co));
617 INTL_METHOD_CHECK_STATUS(co,
618 "intlcal_get_day_of_week_type: Call to ICU method has failed");
619
620 RETURN_LONG((zend_long)result);
621 }
622 #endif
623
PHP_FUNCTION(intlcal_get_first_day_of_week)624 U_CFUNC PHP_FUNCTION(intlcal_get_first_day_of_week)
625 {
626 CALENDAR_METHOD_INIT_VARS;
627
628 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
629 "O", &object, Calendar_ce_ptr) == FAILURE) {
630 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
631 "intlcal_get_first_day_of_week: bad arguments", 0);
632 RETURN_FALSE;
633 }
634
635 CALENDAR_METHOD_FETCH_OBJECT;
636
637 int32_t result = co->ucal->getFirstDayOfWeek(CALENDAR_ERROR_CODE(co));
638 INTL_METHOD_CHECK_STATUS(co,
639 "intlcal_get_first_day_of_week: Call to ICU method has failed");
640
641 RETURN_LONG((zend_long)result);
642 }
643
_php_intlcal_field_ret_in32t_method(int32_t (Calendar::* func)(UCalendarDateFields)const,const char * method_name,INTERNAL_FUNCTION_PARAMETERS)644 static void _php_intlcal_field_ret_in32t_method(
645 int32_t (Calendar::*func)(UCalendarDateFields) const,
646 const char *method_name,
647 INTERNAL_FUNCTION_PARAMETERS)
648 {
649 zend_long field;
650 char *message;
651 CALENDAR_METHOD_INIT_VARS;
652
653 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
654 "Ol", &object, Calendar_ce_ptr, &field) == FAILURE) {
655 spprintf(&message, 0, "%s: bad arguments", method_name);
656 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, message, 1);
657 efree(message);
658 RETURN_FALSE;
659 }
660
661 if (field < 0 || field >= UCAL_FIELD_COUNT) {
662 spprintf(&message, 0, "%s: invalid field", method_name);
663 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, message, 1);
664 efree(message);
665 RETURN_FALSE;
666 }
667
668 CALENDAR_METHOD_FETCH_OBJECT;
669
670 int32_t result = (co->ucal->*func)((UCalendarDateFields)field);
671 INTL_METHOD_CHECK_STATUS(co, "Call to ICU method has failed");
672
673 RETURN_LONG((zend_long)result);
674 }
675
PHP_FUNCTION(intlcal_get_greatest_minimum)676 U_CFUNC PHP_FUNCTION(intlcal_get_greatest_minimum)
677 {
678 _php_intlcal_field_ret_in32t_method(&Calendar::getGreatestMinimum,
679 "intlcal_get_greatest_minimum", INTERNAL_FUNCTION_PARAM_PASSTHRU);
680 }
681
PHP_FUNCTION(intlcal_get_least_maximum)682 U_CFUNC PHP_FUNCTION(intlcal_get_least_maximum)
683 {
684 _php_intlcal_field_ret_in32t_method(&Calendar::getLeastMaximum,
685 "intlcal_get_least_maximum", INTERNAL_FUNCTION_PARAM_PASSTHRU);
686 }
687
PHP_FUNCTION(intlcal_get_locale)688 U_CFUNC PHP_FUNCTION(intlcal_get_locale)
689 {
690 zend_long locale_type;
691 CALENDAR_METHOD_INIT_VARS;
692
693 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
694 "Ol", &object, Calendar_ce_ptr, &locale_type) == FAILURE) {
695 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
696 "intlcal_get_locale: bad arguments", 0);
697 RETURN_FALSE;
698 }
699
700 if (locale_type != ULOC_ACTUAL_LOCALE && locale_type != ULOC_VALID_LOCALE) {
701 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
702 "intlcal_get_locale: invalid locale type", 0);
703 RETURN_FALSE;
704 }
705
706 CALENDAR_METHOD_FETCH_OBJECT;
707
708 Locale locale = co->ucal->getLocale((ULocDataLocaleType)locale_type,
709 CALENDAR_ERROR_CODE(co));
710 INTL_METHOD_CHECK_STATUS(co,
711 "intlcal_get_locale: Call to ICU method has failed");
712
713 RETURN_STRING(locale.getName());
714 }
715
PHP_FUNCTION(intlcal_get_maximum)716 U_CFUNC PHP_FUNCTION(intlcal_get_maximum)
717 {
718 _php_intlcal_field_ret_in32t_method(&Calendar::getMaximum,
719 "intlcal_get_maximum", INTERNAL_FUNCTION_PARAM_PASSTHRU);
720 }
721
PHP_FUNCTION(intlcal_get_minimal_days_in_first_week)722 U_CFUNC PHP_FUNCTION(intlcal_get_minimal_days_in_first_week)
723 {
724 CALENDAR_METHOD_INIT_VARS;
725
726 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
727 "O", &object, Calendar_ce_ptr) == FAILURE) {
728 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
729 "intlcal_get_minimal_days_in_first_week: bad arguments", 0);
730 RETURN_FALSE;
731 }
732
733 CALENDAR_METHOD_FETCH_OBJECT;
734
735 uint8_t result = co->ucal->getMinimalDaysInFirstWeek();
736 INTL_METHOD_CHECK_STATUS(co,
737 "intlcal_get_first_day_of_week: Call to ICU method has failed");
738
739 RETURN_LONG((zend_long)result);
740 }
741
PHP_FUNCTION(intlcal_get_minimum)742 U_CFUNC PHP_FUNCTION(intlcal_get_minimum)
743 {
744 _php_intlcal_field_ret_in32t_method(&Calendar::getMinimum,
745 "intlcal_get_minimum", INTERNAL_FUNCTION_PARAM_PASSTHRU);
746 }
747
PHP_FUNCTION(intlcal_get_time_zone)748 U_CFUNC PHP_FUNCTION(intlcal_get_time_zone)
749 {
750 CALENDAR_METHOD_INIT_VARS;
751
752 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
753 "O", &object, Calendar_ce_ptr) == FAILURE) {
754 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
755 "intlcal_get_time_zone: bad arguments", 0);
756 RETURN_FALSE;
757 }
758
759 CALENDAR_METHOD_FETCH_OBJECT;
760
761 TimeZone *tz = co->ucal->getTimeZone().clone();
762 if (tz == NULL) {
763 intl_errors_set(CALENDAR_ERROR_P(co), U_MEMORY_ALLOCATION_ERROR,
764 "intlcal_get_time_zone: could not clone TimeZone", 0);
765 RETURN_FALSE;
766 }
767
768 timezone_object_construct(tz, return_value, 1);
769 }
770
PHP_FUNCTION(intlcal_get_type)771 U_CFUNC PHP_FUNCTION(intlcal_get_type)
772 {
773 CALENDAR_METHOD_INIT_VARS;
774
775 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
776 "O", &object, Calendar_ce_ptr) == FAILURE) {
777 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
778 "intlcal_get_type: bad arguments", 0);
779 RETURN_FALSE;
780 }
781
782 CALENDAR_METHOD_FETCH_OBJECT;
783
784 RETURN_STRING(co->ucal->getType());
785 }
786
787 #if U_ICU_VERSION_MAJOR_NUM * 10 + U_ICU_VERSION_MINOR_NUM >= 44
PHP_FUNCTION(intlcal_get_weekend_transition)788 U_CFUNC PHP_FUNCTION(intlcal_get_weekend_transition)
789 {
790 zend_long dow;
791 CALENDAR_METHOD_INIT_VARS;
792
793 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
794 "Ol", &object, Calendar_ce_ptr, &dow) == FAILURE) {
795 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
796 "intlcal_get_weekend_transition: bad arguments", 0);
797 RETURN_FALSE;
798 }
799
800 if (dow < UCAL_SUNDAY || dow > UCAL_SATURDAY) {
801 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
802 "intlcal_get_weekend_transition: invalid day of week", 0);
803 RETURN_FALSE;
804 }
805
806 CALENDAR_METHOD_FETCH_OBJECT;
807
808 int32_t res = co->ucal->getWeekendTransition((UCalendarDaysOfWeek)dow,
809 CALENDAR_ERROR_CODE(co));
810 INTL_METHOD_CHECK_STATUS(co, "intlcal_get_weekend_transition: "
811 "Error calling ICU method");
812
813 RETURN_LONG((zend_long)res);
814 }
815 #endif
816
PHP_FUNCTION(intlcal_in_daylight_time)817 U_CFUNC PHP_FUNCTION(intlcal_in_daylight_time)
818 {
819 CALENDAR_METHOD_INIT_VARS;
820
821 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
822 "O", &object, Calendar_ce_ptr) == FAILURE) {
823 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
824 "intlcal_in_daylight_time: bad arguments", 0);
825 RETURN_FALSE;
826 }
827
828 CALENDAR_METHOD_FETCH_OBJECT;
829
830 UBool ret = co->ucal->inDaylightTime(CALENDAR_ERROR_CODE(co));
831 INTL_METHOD_CHECK_STATUS(co, "intlcal_in_daylight_time: "
832 "Error calling ICU method");
833
834 RETURN_BOOL((int)ret);
835 }
836
PHP_FUNCTION(intlcal_is_equivalent_to)837 U_CFUNC PHP_FUNCTION(intlcal_is_equivalent_to)
838 {
839 zval *other_object;
840 Calendar_object *other_co;
841 CALENDAR_METHOD_INIT_VARS;
842
843 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
844 "OO", &object, Calendar_ce_ptr, &other_object, Calendar_ce_ptr)
845 == FAILURE) {
846 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
847 "intlcal_is_equivalent_to: bad arguments", 0);
848 RETURN_FALSE;
849 }
850
851 other_co = Z_INTL_CALENDAR_P(other_object);
852 if (other_co->ucal == NULL) {
853 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "intlcal_is_equivalent_to:"
854 " Other IntlCalendar is unconstructed", 0);
855 RETURN_FALSE;
856 }
857
858 CALENDAR_METHOD_FETCH_OBJECT;
859
860 RETURN_BOOL((int)co->ucal->isEquivalentTo(*other_co->ucal));
861 }
862
PHP_FUNCTION(intlcal_is_lenient)863 U_CFUNC PHP_FUNCTION(intlcal_is_lenient)
864 {
865 CALENDAR_METHOD_INIT_VARS;
866
867 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
868 "O", &object, Calendar_ce_ptr) == FAILURE) {
869 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
870 "intlcal_is_lenient: bad arguments", 0);
871 RETURN_FALSE;
872 }
873
874 CALENDAR_METHOD_FETCH_OBJECT;
875
876 RETURN_BOOL((int)co->ucal->isLenient());
877 }
878
PHP_FUNCTION(intlcal_is_set)879 U_CFUNC PHP_FUNCTION(intlcal_is_set)
880 {
881 zend_long field;
882 CALENDAR_METHOD_INIT_VARS;
883
884 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
885 "Ol", &object, Calendar_ce_ptr, &field) == FAILURE) {
886 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
887 "intlcal_is_set: bad arguments", 0);
888 RETURN_FALSE;
889 }
890
891 if (field < 0 || field >= UCAL_FIELD_COUNT) {
892 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
893 "intlcal_is_set: invalid field", 0);
894 RETURN_FALSE;
895 }
896
897 CALENDAR_METHOD_FETCH_OBJECT;
898
899 RETURN_BOOL((int)co->ucal->isSet((UCalendarDateFields)field));
900 }
901
902 #if U_ICU_VERSION_MAJOR_NUM * 10 + U_ICU_VERSION_MINOR_NUM >= 44
PHP_FUNCTION(intlcal_is_weekend)903 U_CFUNC PHP_FUNCTION(intlcal_is_weekend)
904 {
905 double date;
906 zend_bool date_is_null = 1;
907 CALENDAR_METHOD_INIT_VARS;
908
909 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
910 "O|d!", &object, Calendar_ce_ptr, &date, &date_is_null) == FAILURE) {
911 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
912 "intlcal_is_weekend: bad arguments", 0);
913 RETURN_FALSE;
914 }
915
916 CALENDAR_METHOD_FETCH_OBJECT;
917
918 if (date_is_null) {
919 RETURN_BOOL((int)co->ucal->isWeekend());
920 } else {
921 UBool ret = co->ucal->isWeekend((UDate)date, CALENDAR_ERROR_CODE(co));
922 INTL_METHOD_CHECK_STATUS(co, "intlcal_is_weekend: "
923 "Error calling ICU method");
924 RETURN_BOOL((int)ret);
925 }
926 }
927 #endif
928
929
PHP_FUNCTION(intlcal_set_first_day_of_week)930 U_CFUNC PHP_FUNCTION(intlcal_set_first_day_of_week)
931 {
932 zend_long dow;
933 CALENDAR_METHOD_INIT_VARS;
934
935 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
936 "Ol", &object, Calendar_ce_ptr, &dow) == FAILURE) {
937 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
938 "intlcal_set_first_day_of_week: bad arguments", 0);
939 RETURN_FALSE;
940 }
941
942 if (dow < UCAL_SUNDAY || dow > UCAL_SATURDAY) {
943 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
944 "intlcal_set_first_day_of_week: invalid day of week", 0);
945 RETURN_FALSE;
946 }
947
948 CALENDAR_METHOD_FETCH_OBJECT;
949
950 co->ucal->setFirstDayOfWeek((UCalendarDaysOfWeek)dow);
951
952 RETURN_TRUE;
953 }
954
PHP_FUNCTION(intlcal_set_lenient)955 U_CFUNC PHP_FUNCTION(intlcal_set_lenient)
956 {
957 zend_bool is_lenient;
958 CALENDAR_METHOD_INIT_VARS;
959
960 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
961 "Ob", &object, Calendar_ce_ptr, &is_lenient) == FAILURE) {
962 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
963 "intlcal_set_lenient: bad arguments", 0);
964 RETURN_FALSE;
965 }
966
967 CALENDAR_METHOD_FETCH_OBJECT;
968
969 co->ucal->setLenient((UBool) is_lenient);
970
971 RETURN_TRUE;
972 }
973
PHP_FUNCTION(intlcal_set_minimal_days_in_first_week)974 U_CFUNC PHP_FUNCTION(intlcal_set_minimal_days_in_first_week)
975 {
976 zend_long num_days;
977 CALENDAR_METHOD_INIT_VARS;
978
979 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
980 "Ol", &object, Calendar_ce_ptr, &num_days) == FAILURE) {
981 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
982 "intlcal_set_minimal_days_in_first_week: bad arguments", 0);
983 RETURN_FALSE;
984 }
985
986 if (num_days < 1 || num_days > 7) {
987 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
988 "intlcal_set_minimal_days_in_first_week: invalid number of days; "
989 "must be between 1 and 7", 0);
990 RETURN_FALSE;
991 }
992
993 CALENDAR_METHOD_FETCH_OBJECT;
994
995 co->ucal->setMinimalDaysInFirstWeek((uint8_t)num_days);
996
997 RETURN_TRUE;
998 }
999
PHP_FUNCTION(intlcal_equals)1000 U_CFUNC PHP_FUNCTION(intlcal_equals)
1001 {
1002 zval *other_object;
1003 Calendar_object *other_co;
1004 CALENDAR_METHOD_INIT_VARS;
1005
1006 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
1007 "OO", &object, Calendar_ce_ptr, &other_object, Calendar_ce_ptr)
1008 == FAILURE) {
1009 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1010 "intlcal_equals: bad arguments", 0);
1011 RETURN_FALSE;
1012 }
1013
1014 CALENDAR_METHOD_FETCH_OBJECT;
1015 other_co = Z_INTL_CALENDAR_P(other_object);
1016 if (other_co->ucal == NULL) {
1017 intl_errors_set(&co->err, U_ILLEGAL_ARGUMENT_ERROR,
1018 "intlcal_equals: The second IntlCalendar is unconstructed", 0);
1019 RETURN_FALSE;
1020 }
1021
1022 UBool result = co->ucal->equals(*other_co->ucal, CALENDAR_ERROR_CODE(co));
1023 INTL_METHOD_CHECK_STATUS(co, "intlcal_equals: error calling ICU Calendar::equals");
1024
1025 RETURN_BOOL((int)result);
1026 }
1027
1028 #if U_ICU_VERSION_MAJOR_NUM >= 49
1029
PHP_FUNCTION(intlcal_get_repeated_wall_time_option)1030 U_CFUNC PHP_FUNCTION(intlcal_get_repeated_wall_time_option)
1031 {
1032 CALENDAR_METHOD_INIT_VARS;
1033
1034 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
1035 "O", &object, Calendar_ce_ptr) == FAILURE) {
1036 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1037 "intlcal_get_repeated_wall_time_option: bad arguments", 0);
1038 RETURN_FALSE;
1039 }
1040
1041 CALENDAR_METHOD_FETCH_OBJECT;
1042
1043 RETURN_LONG(co->ucal->getRepeatedWallTimeOption());
1044 }
1045
PHP_FUNCTION(intlcal_get_skipped_wall_time_option)1046 U_CFUNC PHP_FUNCTION(intlcal_get_skipped_wall_time_option)
1047 {
1048 CALENDAR_METHOD_INIT_VARS;
1049
1050 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
1051 "O", &object, Calendar_ce_ptr) == FAILURE) {
1052 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1053 "intlcal_get_skipped_wall_time_option: bad arguments", 0);
1054 RETURN_FALSE;
1055 }
1056
1057 CALENDAR_METHOD_FETCH_OBJECT;
1058
1059 RETURN_LONG(co->ucal->getSkippedWallTimeOption());
1060 }
1061
PHP_FUNCTION(intlcal_set_repeated_wall_time_option)1062 U_CFUNC PHP_FUNCTION(intlcal_set_repeated_wall_time_option)
1063 {
1064 zend_long option;
1065 CALENDAR_METHOD_INIT_VARS;
1066
1067 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
1068 "Ol", &object, Calendar_ce_ptr, &option) == FAILURE) {
1069 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1070 "intlcal_set_repeated_wall_time_option: bad arguments", 0);
1071 RETURN_FALSE;
1072 }
1073
1074 if (option != UCAL_WALLTIME_FIRST && option != UCAL_WALLTIME_LAST) {
1075 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1076 "intlcal_set_repeated_wall_time_option: invalid option", 0);
1077 RETURN_FALSE;
1078 }
1079
1080 CALENDAR_METHOD_FETCH_OBJECT;
1081
1082 co->ucal->setRepeatedWallTimeOption((UCalendarWallTimeOption)option);
1083
1084 RETURN_TRUE;
1085 }
1086
PHP_FUNCTION(intlcal_set_skipped_wall_time_option)1087 U_CFUNC PHP_FUNCTION(intlcal_set_skipped_wall_time_option)
1088 {
1089 zend_long option;
1090 CALENDAR_METHOD_INIT_VARS;
1091
1092 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(),
1093 "Ol", &object, Calendar_ce_ptr, &option) == FAILURE) {
1094 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1095 "intlcal_set_skipped_wall_time_option: bad arguments", 0);
1096 RETURN_FALSE;
1097 }
1098
1099 if (option != UCAL_WALLTIME_FIRST && option != UCAL_WALLTIME_LAST
1100 && option != UCAL_WALLTIME_NEXT_VALID) {
1101 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1102 "intlcal_set_skipped_wall_time_option: invalid option", 0);
1103 RETURN_FALSE;
1104 }
1105
1106 CALENDAR_METHOD_FETCH_OBJECT;
1107
1108 co->ucal->setSkippedWallTimeOption((UCalendarWallTimeOption)option);
1109
1110 RETURN_TRUE;
1111 }
1112
1113 #endif
1114
PHP_FUNCTION(intlcal_from_date_time)1115 U_CFUNC PHP_FUNCTION(intlcal_from_date_time)
1116 {
1117 zval *zv_arg,
1118 zv_tmp,
1119 *zv_datetime = NULL,
1120 zv_timestamp;
1121 php_date_obj *datetime;
1122 char *locale_str = NULL;
1123 size_t locale_str_len;
1124 TimeZone *timeZone;
1125 UErrorCode status = U_ZERO_ERROR;
1126 Calendar *cal;
1127 intl_error_reset(NULL);
1128
1129 if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|s!",
1130 &zv_arg, &locale_str, &locale_str_len) == FAILURE) {
1131 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1132 "intlcal_from_date_time: bad arguments", 0);
1133 RETURN_NULL();
1134 }
1135
1136 if (!(Z_TYPE_P(zv_arg) == IS_OBJECT && instanceof_function(
1137 Z_OBJCE_P(zv_arg), php_date_get_date_ce()))) {
1138 object_init_ex(&zv_tmp, php_date_get_date_ce());
1139 zend_call_method_with_1_params(&zv_tmp, NULL, NULL, "__construct", NULL, zv_arg);
1140 zv_datetime = &zv_tmp;
1141 if (EG(exception)) {
1142 zend_object_store_ctor_failed(Z_OBJ(zv_tmp));
1143 goto error;
1144 }
1145 } else {
1146 zv_datetime = zv_arg;
1147 }
1148
1149 datetime = Z_PHPDATE_P(zv_datetime);
1150 if (!datetime->time) {
1151 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1152 "intlcal_from_date_time: DateTime object is unconstructed",
1153 0);
1154 goto error;
1155 }
1156
1157 zend_call_method_with_0_params(zv_datetime, php_date_get_date_ce(), NULL, "gettimestamp", &zv_timestamp);
1158 if (Z_TYPE(zv_timestamp) != IS_LONG) {
1159 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1160 "intlcal_from_date_time: bad DateTime; call to "
1161 "DateTime::getTimestamp() failed", 0);
1162 zval_ptr_dtor(&zv_timestamp);
1163 goto error;
1164 }
1165
1166 if (!datetime->time->is_localtime) {
1167 timeZone = TimeZone::getGMT()->clone();
1168 } else {
1169 timeZone = timezone_convert_datetimezone(datetime->time->zone_type,
1170 datetime, 1, NULL, "intlcal_from_date_time");
1171 if (timeZone == NULL) {
1172 goto error;
1173 }
1174 }
1175
1176 if (!locale_str) {
1177 locale_str = const_cast<char*>(intl_locale_get_default());
1178 }
1179
1180 cal = Calendar::createInstance(timeZone,
1181 Locale::createFromName(locale_str), status);
1182 if (cal == NULL) {
1183 delete timeZone;
1184 intl_error_set(NULL, status, "intlcal_from_date_time: "
1185 "error creating ICU Calendar object", 0);
1186 goto error;
1187 }
1188 cal->setTime(((UDate)Z_LVAL(zv_timestamp)) * 1000., status);
1189 if (U_FAILURE(status)) {
1190 /* time zone was adopted by cal; should not be deleted here */
1191 delete cal;
1192 intl_error_set(NULL, status, "intlcal_from_date_time: "
1193 "error creating ICU Calendar::setTime()", 0);
1194 goto error;
1195 }
1196
1197 calendar_object_create(return_value, cal);
1198
1199 error:
1200 if (zv_datetime && zv_datetime != zv_arg) {
1201 zval_ptr_dtor(zv_datetime);
1202 }
1203 }
1204
PHP_FUNCTION(intlcal_to_date_time)1205 U_CFUNC PHP_FUNCTION(intlcal_to_date_time)
1206 {
1207 zval retval;
1208 CALENDAR_METHOD_INIT_VARS;
1209
1210 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O",
1211 &object, Calendar_ce_ptr) == FAILURE) {
1212 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1213 "intlcal_to_date_time: bad arguments", 0);
1214 RETURN_FALSE;
1215 }
1216
1217 CALENDAR_METHOD_FETCH_OBJECT;
1218
1219 /* There are no exported functions in ext/date to this
1220 * in a more native fashion */
1221 double date = co->ucal->getTime(CALENDAR_ERROR_CODE(co)) / 1000.;
1222 int64_t ts;
1223 char ts_str[sizeof("@-9223372036854775808")];
1224 int ts_str_len;
1225 zval ts_zval, tmp;
1226
1227 INTL_METHOD_CHECK_STATUS(co, "Call to ICU method has failed");
1228
1229 if (date > (double)U_INT64_MAX || date < (double)U_INT64_MIN) {
1230 intl_errors_set(CALENDAR_ERROR_P(co), U_ILLEGAL_ARGUMENT_ERROR,
1231 "intlcal_to_date_time: The calendar date is out of the "
1232 "range for a 64-bit integer", 0);
1233 RETURN_FALSE;
1234 }
1235
1236 ZVAL_UNDEF(&retval);
1237 ts = (int64_t)date;
1238
1239 ts_str_len = slprintf(ts_str, sizeof(ts_str), "@%I64d", ts);
1240 ZVAL_STRINGL(&ts_zval, ts_str, ts_str_len);
1241
1242 /* Now get the time zone */
1243 const TimeZone& tz = co->ucal->getTimeZone();
1244 zval *timezone_zval = timezone_convert_to_datetimezone(
1245 &tz, CALENDAR_ERROR_P(co), "intlcal_to_date_time", &tmp);
1246 if (timezone_zval == NULL) {
1247 zval_ptr_dtor(&ts_zval);
1248 RETURN_FALSE;
1249 }
1250
1251 /* resources allocated from now on */
1252
1253 /* Finally, instantiate object and call constructor */
1254 object_init_ex(return_value, php_date_get_date_ce());
1255 zend_call_method_with_2_params(return_value, NULL, NULL, "__construct", NULL, &ts_zval, timezone_zval);
1256 if (EG(exception)) {
1257 intl_errors_set(CALENDAR_ERROR_P(co), U_ILLEGAL_ARGUMENT_ERROR,
1258 "intlcal_to_date_time: DateTime constructor has thrown exception",
1259 1);
1260 zend_object_store_ctor_failed(Z_OBJ_P(return_value));
1261 zval_ptr_dtor(return_value);
1262 zval_ptr_dtor(&ts_zval);
1263
1264 RETVAL_FALSE;
1265 goto error;
1266 }
1267 zval_ptr_dtor(&ts_zval);
1268
1269 /* due to bug #40743, we have to set the time zone again */
1270 zend_call_method_with_1_params(return_value, NULL, NULL, "settimezone",
1271 &retval, timezone_zval);
1272 if (Z_ISUNDEF(retval) || Z_TYPE(retval) == IS_FALSE) {
1273 intl_errors_set(CALENDAR_ERROR_P(co), U_ILLEGAL_ARGUMENT_ERROR,
1274 "intlcal_to_date_time: call to DateTime::setTimeZone has failed",
1275 1);
1276 zval_ptr_dtor(return_value);
1277 RETVAL_FALSE;
1278 goto error;
1279 }
1280
1281 error:
1282 zval_ptr_dtor(timezone_zval);
1283 zval_ptr_dtor(&retval);
1284 }
1285
PHP_FUNCTION(intlcal_get_error_code)1286 U_CFUNC PHP_FUNCTION(intlcal_get_error_code)
1287 {
1288 CALENDAR_METHOD_INIT_VARS;
1289
1290 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O",
1291 &object, Calendar_ce_ptr) == FAILURE) {
1292 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
1293 "intlcal_get_error_code: bad arguments", 0);
1294 RETURN_FALSE;
1295 }
1296
1297 /* Fetch the object (without resetting its last error code ). */
1298 co = Z_INTL_CALENDAR_P(object);
1299 if (co == NULL)
1300 RETURN_FALSE;
1301
1302 RETURN_LONG((zend_long)CALENDAR_ERROR_CODE(co));
1303 }
1304
PHP_FUNCTION(intlcal_get_error_message)1305 U_CFUNC PHP_FUNCTION(intlcal_get_error_message)
1306 {
1307 zend_string* message = NULL;
1308 CALENDAR_METHOD_INIT_VARS;
1309
1310 if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O",
1311 &object, Calendar_ce_ptr) == FAILURE) {
1312 intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
1313 "intlcal_get_error_message: bad arguments", 0 );
1314 RETURN_FALSE;
1315 }
1316
1317
1318 /* Fetch the object (without resetting its last error code ). */
1319 co = Z_INTL_CALENDAR_P(object);
1320 if (co == NULL)
1321 RETURN_FALSE;
1322
1323 /* Return last error message. */
1324 message = intl_error_get_message(CALENDAR_ERROR_P(co));
1325 RETURN_STR(message);
1326 }
1327