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 #include "../intl_cppshims.h"
18
19 #include <unicode/timezone.h>
20 #include <unicode/calendar.h>
21 #include <unicode/datefmt.h>
22
23 extern "C" {
24 #include "../php_intl.h"
25 #include "dateformat_class.h"
26 #include "dateformat_attrcpp.h"
27 #define USE_TIMEZONE_POINTER 1
28 #include "../timezone/timezone_class.h"
29 #define USE_CALENDAR_POINTER 1
30 #include "../calendar/calendar_class.h"
31 }
32
33 #include "../intl_convertcpp.h"
34 #include "dateformat_helpers.h"
35
fetch_datefmt(IntlDateFormatter_object * dfo)36 static inline DateFormat *fetch_datefmt(IntlDateFormatter_object *dfo) {
37 return (DateFormat *)dfo->datef_data.udatf;
38 }
39
40 /* {{{ proto string IntlDateFormatter::getTimeZoneId()
41 * Get formatter timezone_id. }}} */
42 /* {{{ proto string datefmt_get_timezone_id(IntlDateFormatter $mf)
43 * Get formatter timezone_id.
44 */
PHP_FUNCTION(datefmt_get_timezone_id)45 U_CFUNC PHP_FUNCTION(datefmt_get_timezone_id)
46 {
47 DATE_FORMAT_METHOD_INIT_VARS;
48
49 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
50 &object, IntlDateFormatter_ce_ptr ) == FAILURE) {
51 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_get_timezone_"
52 "id: unable to parse input params", 0 TSRMLS_CC);
53 RETURN_FALSE;
54 }
55
56 DATE_FORMAT_METHOD_FETCH_OBJECT;
57
58 UnicodeString res = UnicodeString();
59 fetch_datefmt(dfo)->getTimeZone().getID(res);
60 intl_charFromString(res, &Z_STRVAL_P(return_value),
61 &Z_STRLEN_P(return_value), &INTL_DATA_ERROR_CODE(dfo));
62 INTL_METHOD_CHECK_STATUS(dfo, "Could not convert time zone id to UTF-8");
63
64 Z_TYPE_P(return_value) = IS_STRING;
65 }
66
67 /* {{{ proto IntlTimeZone IntlDateFormatter::getTimeZone()
68 * Get formatter timezone. }}} */
69 /* {{{ proto IntlTimeZone datefmt_get_timezone(IntlDateFormatter $mf)
70 * Get formatter timezone.
71 */
PHP_FUNCTION(datefmt_get_timezone)72 U_CFUNC PHP_FUNCTION(datefmt_get_timezone)
73 {
74 DATE_FORMAT_METHOD_INIT_VARS;
75
76 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
77 &object, IntlDateFormatter_ce_ptr ) == FAILURE) {
78 intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
79 "datefmt_get_timezone: unable to parse input params", 0 TSRMLS_CC );
80 RETURN_FALSE;
81 }
82
83 DATE_FORMAT_METHOD_FETCH_OBJECT;
84
85 const TimeZone& tz = fetch_datefmt(dfo)->getTimeZone();
86 TimeZone *tz_clone = tz.clone();
87 if (tz_clone == NULL) {
88 intl_errors_set(INTL_DATA_ERROR_P(dfo), U_MEMORY_ALLOCATION_ERROR,
89 "datefmt_get_timezone: Out of memory when cloning time zone",
90 0 TSRMLS_CC);
91 RETURN_FALSE;
92 }
93
94 object_init_ex(return_value, TimeZone_ce_ptr);
95 timezone_object_construct(tz_clone, return_value, 1 TSRMLS_CC);
96 }
97
PHP_FUNCTION(datefmt_set_timezone_id)98 U_CFUNC PHP_FUNCTION(datefmt_set_timezone_id)
99 {
100 php_error_docref0(NULL TSRMLS_CC, E_DEPRECATED,
101 "Use datefmt_set_timezone() instead, which also accepts a plain "
102 "time zone identifier and for which this function is now an "
103 "alias");
104 PHP_FN(datefmt_set_timezone)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
105 }
106
107 /* {{{ proto boolean IntlDateFormatter::setTimeZone(mixed $timezone)
108 * Set formatter's timezone. }}} */
109 /* {{{ proto boolean datefmt_set_timezone_id(IntlDateFormatter $mf, $timezone_id)
110 * Set formatter timezone_id.
111 */
PHP_FUNCTION(datefmt_set_timezone)112 U_CFUNC PHP_FUNCTION(datefmt_set_timezone)
113 {
114 zval **timezone_zv;
115 TimeZone *timezone;
116
117 DATE_FORMAT_METHOD_INIT_VARS;
118
119 if ( zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(),
120 "OZ", &object, IntlDateFormatter_ce_ptr, &timezone_zv) == FAILURE) {
121 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_set_timezone: "
122 "unable to parse input params", 0 TSRMLS_CC);
123 RETURN_FALSE;
124 }
125
126 DATE_FORMAT_METHOD_FETCH_OBJECT;
127
128 timezone = timezone_process_timezone_argument(timezone_zv,
129 INTL_DATA_ERROR_P(dfo), "datefmt_set_timezone" TSRMLS_CC);
130 if (timezone == NULL) {
131 RETURN_FALSE;
132 }
133
134 fetch_datefmt(dfo)->adoptTimeZone(timezone);
135 }
136
137 /* {{{ proto int IntlDateFormatter::getCalendar( )
138 * Get formatter calendar type. }}} */
139 /* {{{ proto int datefmt_get_calendar(IntlDateFormatter $mf)
140 * Get formatter calendar type.
141 */
PHP_FUNCTION(datefmt_get_calendar)142 U_CFUNC PHP_FUNCTION(datefmt_get_calendar)
143 {
144 DATE_FORMAT_METHOD_INIT_VARS;
145
146 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
147 &object, IntlDateFormatter_ce_ptr ) == FAILURE) {
148 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
149 "datefmt_get_calendar: unable to parse input params", 0 TSRMLS_CC);
150 RETURN_FALSE;
151 }
152
153 DATE_FORMAT_METHOD_FETCH_OBJECT;
154
155 if (dfo->calendar == -1) {
156 /* an IntlCalendar was provided to the constructor */
157 RETURN_FALSE;
158 }
159
160 RETURN_LONG(dfo->calendar);
161 }
162 /* }}} */
163
164 /* {{{ proto IntlCalendar IntlDateFormatter::getCalendarObject()
165 * Get formatter calendar. }}} */
166 /* {{{ proto IntlCalendar datefmt_get_calendar_object(IntlDateFormatter $mf)
167 * Get formatter calendar.
168 */
PHP_FUNCTION(datefmt_get_calendar_object)169 U_CFUNC PHP_FUNCTION(datefmt_get_calendar_object)
170 {
171 DATE_FORMAT_METHOD_INIT_VARS;
172
173 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
174 &object, IntlDateFormatter_ce_ptr ) == FAILURE) {
175 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
176 "datefmt_get_calendar_object: unable to parse input params",
177 0 TSRMLS_CC);
178 RETURN_FALSE;
179 }
180
181 DATE_FORMAT_METHOD_FETCH_OBJECT;
182
183 const Calendar *cal = fetch_datefmt(dfo)->getCalendar();
184 if (cal == NULL) {
185 RETURN_NULL();
186 }
187
188 Calendar *cal_clone = cal->clone();
189 if (cal_clone == NULL) {
190 intl_errors_set(INTL_DATA_ERROR_P(dfo), U_MEMORY_ALLOCATION_ERROR,
191 "datefmt_get_calendar_object: Out of memory when cloning "
192 "calendar", 0 TSRMLS_CC);
193 RETURN_FALSE;
194 }
195
196 calendar_object_create(return_value, cal_clone TSRMLS_CC);
197 }
198 /* }}} */
199
200 /* {{{ proto bool IntlDateFormatter::setCalendar(mixed $calendar)
201 * Set formatter's calendar. }}} */
202 /* {{{ proto bool datefmt_set_calendar(IntlDateFormatter $mf, mixed $calendar)
203 * Set formatter's calendar.
204 */
PHP_FUNCTION(datefmt_set_calendar)205 U_CFUNC PHP_FUNCTION(datefmt_set_calendar)
206 {
207 zval *calendar_zv;
208 DATE_FORMAT_METHOD_INIT_VARS;
209
210 if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oz",
211 &object, IntlDateFormatter_ce_ptr, &calendar_zv) == FAILURE) {
212 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
213 "datefmt_set_calendar: unable to parse input params", 0 TSRMLS_CC);
214 RETURN_FALSE;
215 }
216
217 DATE_FORMAT_METHOD_FETCH_OBJECT;
218
219 Calendar *cal;
220 long cal_type;
221 bool cal_owned;
222 Locale locale = Locale::createFromName(dfo->requested_locale);
223 // getting the actual locale from the DateFormat is not enough
224 // because we would have lost modifiers such as @calendar. We
225 // must store the requested locale on object creation
226
227 if (datefmt_process_calendar_arg(calendar_zv, locale,
228 "datefmt_set_calendar", INTL_DATA_ERROR_P(dfo), cal, cal_type,
229 cal_owned TSRMLS_CC) == FAILURE) {
230 RETURN_FALSE;
231 }
232
233 if (cal_owned) {
234 /* a non IntlCalendar was specified, we want to keep the timezone */
235 TimeZone *old_timezone = fetch_datefmt(dfo)->getTimeZone().clone();
236 if (old_timezone == NULL) {
237 intl_errors_set(INTL_DATA_ERROR_P(dfo), U_MEMORY_ALLOCATION_ERROR,
238 "datefmt_set_calendar: Out of memory when cloning calendar",
239 0 TSRMLS_CC);
240 delete cal;
241 RETURN_FALSE;
242 }
243 cal->adoptTimeZone(old_timezone);
244 } else {
245 cal = cal->clone();
246 if (cal == NULL) {
247 intl_errors_set(INTL_DATA_ERROR_P(dfo), U_MEMORY_ALLOCATION_ERROR,
248 "datefmt_set_calendar: Out of memory when cloning calendar",
249 0 TSRMLS_CC);
250 RETURN_FALSE;
251 }
252 }
253
254 fetch_datefmt(dfo)->adoptCalendar(cal);
255
256 dfo->calendar = cal_type;
257
258 RETURN_TRUE;
259 }
260 /* }}} */
261
262