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: Kirti Velankar <kirtig@yahoo-inc.com> |
14 +----------------------------------------------------------------------+
15 */
16 #ifdef HAVE_CONFIG_H
17 #include "config.h"
18 #endif
19
20 #include <unicode/ustring.h>
21 #include <unicode/udat.h>
22 #include <unicode/ucal.h>
23
24 #include "php_intl.h"
25 #include "intl_convert.h"
26 #include "dateformat_class.h"
27 #include "dateformat.h"
28
29 /* {{{ dateformat_register_constants
30 * Register constants common for the both (OO and procedural)
31 * APIs.
32 */
dateformat_register_constants(INIT_FUNC_ARGS)33 void dateformat_register_constants( INIT_FUNC_ARGS )
34 {
35 if( IntlDateFormatter_ce_ptr == NULL) {
36 zend_error(E_ERROR, "DateFormat class not defined");
37 return;
38 }
39
40 #define DATEFORMATTER_EXPOSE_CONST(x) REGISTER_LONG_CONSTANT(#x, x, CONST_CS)
41 #define DATEFORMATTER_EXPOSE_CLASS_CONST(x) zend_declare_class_constant_long( IntlDateFormatter_ce_ptr, ZEND_STRS( #x ) - 1, UDAT_##x TSRMLS_CC );
42 #define DATEFORMATTER_EXPOSE_CUSTOM_CLASS_CONST(name, value) zend_declare_class_constant_long( IntlDateFormatter_ce_ptr, ZEND_STRS( name ) - 1, value TSRMLS_CC );
43
44 #define DATEFORMATTER_EXPOSE_UCAL_CLASS_CONST(x) zend_declare_class_constant_long( IntlDateFormatter_ce_ptr, ZEND_STRS( #x ) - 1, UCAL_##x TSRMLS_CC );
45
46 /* UDateFormatStyle constants */
47 DATEFORMATTER_EXPOSE_CLASS_CONST( FULL );
48 DATEFORMATTER_EXPOSE_CLASS_CONST( LONG );
49 DATEFORMATTER_EXPOSE_CLASS_CONST( MEDIUM );
50 DATEFORMATTER_EXPOSE_CLASS_CONST( SHORT );
51 DATEFORMATTER_EXPOSE_CLASS_CONST( NONE );
52
53 /*
54 DATEFORMATTER_EXPOSE_CUSTOM_CLASS_CONST( "GREGORIAN", DATEF_GREGORIAN );
55 DATEFORMATTER_EXPOSE_CUSTOM_CLASS_CONST( "CUSTOMARY", DATEF_CUSTOMARY );
56 DATEFORMATTER_EXPOSE_CUSTOM_CLASS_CONST( "BUDDHIST", DATEF_BUDDHIST );
57 DATEFORMATTER_EXPOSE_CUSTOM_CLASS_CONST( "JAPANESE_IMPERIAL", DATEF_JAPANESE_IMPERIAL );
58 */
59
60 DATEFORMATTER_EXPOSE_UCAL_CLASS_CONST( GREGORIAN );
61 DATEFORMATTER_EXPOSE_UCAL_CLASS_CONST( TRADITIONAL );
62
63 #undef DATEFORMATTER_EXPOSE_UCAL_CLASS_CONST
64 #undef DATEFORMATTER_EXPOSE_CUSTOM_CLASS_CONST
65 #undef DATEFORMATTER_EXPOSE_CLASS_CONST
66 #undef DATEFORMATTER_EXPOSE_CONST
67 }
68 /* }}} */
69
70 /* {{{ */
datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS)71 static void datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS)
72 {
73 char* locale;
74 int locale_len = 0;
75 zval* object;
76 long date_type = 0;
77 long time_type = 0;
78 long calendar = UCAL_GREGORIAN;
79 char* timezone_str = NULL;
80 int timezone_str_len = 0;
81 char* pattern_str = NULL;
82 int pattern_str_len = 0;
83 UChar* svalue = NULL; /* UTF-16 pattern_str */
84 int slength = 0;
85 UChar* timezone_utf16 = NULL; /* UTF-16 timezone_str */
86 int timezone_utf16_len = 0;
87 UCalendar ucal_obj = NULL;
88 IntlDateFormatter_object* dfo;
89
90 intl_error_reset( NULL TSRMLS_CC );
91 object = return_value;
92 /* Parse parameters. */
93 if( zend_parse_parameters( ZEND_NUM_ARGS() TSRMLS_CC, "sll|sls",
94 &locale, &locale_len, &date_type, &time_type, &timezone_str, &timezone_str_len, &calendar,&pattern_str, &pattern_str_len ) == FAILURE )
95 {
96 intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_create: unable to parse input parameters", 0 TSRMLS_CC );
97 zval_dtor(return_value);
98 RETURN_NULL();
99 }
100
101 INTL_CHECK_LOCALE_LEN_OBJ(locale_len, return_value);
102
103 if (calendar != UCAL_TRADITIONAL && calendar != UCAL_GREGORIAN) {
104 intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_create: "
105 "invalid value for calendar type; it must be one of "
106 "IntlDateFormatter::TRADITIONAL (locale's default calendar) "
107 "or IntlDateFormatter::GREGORIAN", 0 TSRMLS_CC);
108 goto error;
109 }
110
111 DATE_FORMAT_METHOD_FETCH_OBJECT_NO_CHECK;
112
113 if (DATE_FORMAT_OBJECT(dfo) != NULL) {
114 intl_errors_set(INTL_DATA_ERROR_P(dfo), U_ILLEGAL_ARGUMENT_ERROR,
115 "datefmt_create: cannot call constructor twice", 0 TSRMLS_CC);
116 return;
117 }
118
119 /* Convert pattern (if specified) to UTF-16. */
120 if( pattern_str && pattern_str_len>0 ){
121 intl_convert_utf8_to_utf16(&svalue, &slength,
122 pattern_str, pattern_str_len, &INTL_DATA_ERROR_CODE(dfo));
123 if (U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) {
124 /* object construction -> only set global error */
125 intl_error_set(NULL, INTL_DATA_ERROR_CODE(dfo), "datefmt_create: "
126 "error converting pattern to UTF-16", 0 TSRMLS_CC);
127 goto error;
128 }
129 }
130
131 /* resources allocated from now on */
132
133 /* Convert pattern (if specified) to UTF-16. */
134 if( timezone_str && timezone_str_len >0 ){
135 intl_convert_utf8_to_utf16(&timezone_utf16, &timezone_utf16_len,
136 timezone_str, timezone_str_len, &INTL_DATA_ERROR_CODE(dfo));
137 if (U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) {
138 intl_error_set(NULL, INTL_DATA_ERROR_CODE(dfo), "datefmt_create: "
139 "error converting timezone_str to UTF-16", 0 TSRMLS_CC);
140 goto error;
141 }
142 }
143
144 if(locale_len == 0) {
145 locale = INTL_G(default_locale);
146 }
147
148 if( pattern_str && pattern_str_len>0 ){
149 DATE_FORMAT_OBJECT(dfo) = udat_open(UDAT_IGNORE, UDAT_IGNORE, locale, timezone_utf16, timezone_utf16_len, svalue, slength, &INTL_DATA_ERROR_CODE(dfo));
150 } else {
151 DATE_FORMAT_OBJECT(dfo) = udat_open(time_type, date_type, locale, timezone_utf16, timezone_utf16_len, svalue, slength, &INTL_DATA_ERROR_CODE(dfo));
152 }
153
154 if (!U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) {
155 if (calendar != UCAL_TRADITIONAL) {
156 ucal_obj = ucal_open(timezone_utf16, timezone_utf16_len, locale,
157 calendar, &INTL_DATA_ERROR_CODE(dfo));
158 if (!U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) {
159 udat_setCalendar(DATE_FORMAT_OBJECT(dfo), ucal_obj);
160 ucal_close(ucal_obj);
161 } else {
162 intl_error_set(NULL, INTL_DATA_ERROR_CODE(dfo), "datefmt_create"
163 ": error opening calendar", 0 TSRMLS_CC);
164 goto error;
165 }
166 }
167 } else {
168 intl_error_set(NULL, INTL_DATA_ERROR_CODE(dfo), "datefmt_create: date "
169 "formatter creation failed", 0 TSRMLS_CC);
170 goto error;
171 }
172
173 /* Set the class variables */
174 dfo->date_type = date_type;
175 dfo->time_type = time_type;
176 dfo->calendar = calendar;
177 if( timezone_str && timezone_str_len > 0){
178 dfo->timezone_id = estrndup( timezone_str, timezone_str_len);
179 }
180
181 error:
182 if (svalue) {
183 efree(svalue);
184 }
185 if (timezone_utf16) {
186 efree(timezone_utf16);
187 }
188 if (U_FAILURE(intl_error_get_code(NULL TSRMLS_CC))) {
189 /* free_object handles partially constructed instances fine */
190 zval_dtor(return_value);
191 RETVAL_NULL();
192 }
193 }
194 /* }}} */
195
196 /* {{{ proto IntlDateFormatter IntlDateFormatter::create(string $locale, long date_type, long time_type[, string $timezone_str, long $calendar, string $pattern] )
197 * Create formatter. }}} */
198 /* {{{ proto IntlDateFormatter datefmt_create(string $locale, long date_type, long time_type[, string $timezone_str, long $calendar, string $pattern] )
199
200 * Create formatter.
201 */
PHP_FUNCTION(datefmt_create)202 PHP_FUNCTION( datefmt_create )
203 {
204 object_init_ex( return_value, IntlDateFormatter_ce_ptr );
205 datefmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU);
206 }
207 /* }}} */
208
209 /* {{{ proto void IntlDateFormatter::__construct(string $locale, long date_type, long time_type[, string $timezone_str, long $calendar, string $pattern])
210 * IntlDateFormatter object constructor.
211 */
PHP_METHOD(IntlDateFormatter,__construct)212 PHP_METHOD( IntlDateFormatter, __construct )
213 {
214 /* return_value param is being changed, therefore we will always return
215 * NULL here */
216 return_value = getThis();
217 datefmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU);
218 }
219 /* }}} */
220
221 /* {{{ proto int IntlDateFormatter::getErrorCode()
222 * Get formatter's last error code. }}} */
223 /* {{{ proto int datefmt_get_error_code( IntlDateFormatter $nf )
224 * Get formatter's last error code.
225 */
PHP_FUNCTION(datefmt_get_error_code)226 PHP_FUNCTION( datefmt_get_error_code )
227 {
228 DATE_FORMAT_METHOD_INIT_VARS;
229
230 /* Parse parameters. */
231 if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
232 &object, IntlDateFormatter_ce_ptr ) == FAILURE )
233 {
234 intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
235 "datefmt_get_error_code: unable to parse input params", 0 TSRMLS_CC );
236 RETURN_FALSE;
237 }
238
239 dfo = (IntlDateFormatter_object *) zend_object_store_get_object( object TSRMLS_CC );
240
241 /* Return formatter's last error code. */
242 RETURN_LONG( INTL_DATA_ERROR_CODE(dfo) );
243 }
244 /* }}} */
245
246 /* {{{ proto string IntlDateFormatter::getErrorMessage( )
247 * Get text description for formatter's last error code. }}} */
248 /* {{{ proto string datefmt_get_error_message( IntlDateFormatter $coll )
249 * Get text description for formatter's last error code.
250 */
PHP_FUNCTION(datefmt_get_error_message)251 PHP_FUNCTION( datefmt_get_error_message )
252 {
253 char* message = NULL;
254 DATE_FORMAT_METHOD_INIT_VARS;
255
256 /* Parse parameters. */
257 if( zend_parse_method_parameters( ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",
258 &object, IntlDateFormatter_ce_ptr ) == FAILURE )
259 {
260 intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,
261 "datefmt_get_error_message: unable to parse input params", 0 TSRMLS_CC );
262
263 RETURN_FALSE;
264 }
265
266 dfo = (IntlDateFormatter_object *) zend_object_store_get_object( object TSRMLS_CC );
267
268 /* Return last error message. */
269 message = intl_error_get_message( INTL_DATA_ERROR_P(dfo) TSRMLS_CC );
270 RETURN_STRING( message, 0);
271 }
272 /* }}} */
273