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    |          Gustavo Lopes <cataphract@php.net>                          |
15    +----------------------------------------------------------------------+
16 */
17 
18 #include "../intl_cppshims.h"
19 
20 #include <unicode/timezone.h>
21 #include <unicode/calendar.h>
22 #include <unicode/datefmt.h>
23 
24 extern "C" {
25 #include <unicode/ustring.h>
26 #include <unicode/udat.h>
27 
28 #include "php_intl.h"
29 #include "dateformat_create.h"
30 #include "dateformat_class.h"
31 #define USE_TIMEZONE_POINTER 1
32 #include "../timezone/timezone_class.h"
33 #include "../intl_convert.h"
34 }
35 
36 #include "dateformat_helpers.h"
37 
38 /* {{{ */
datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS)39 static void datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS)
40 {
41 	zval		*object;
42 
43 	const char	*locale_str;
44 	int			locale_len		= 0;
45 	Locale		locale;
46     long		date_type		= 0;
47     long		time_type		= 0;
48 	zval		*calendar_zv	= NULL;
49 	Calendar	*calendar		= NULL;
50 	long		calendar_type;
51 	bool		calendar_owned;
52 	zval		**timezone_zv	= NULL;
53 	TimeZone	*timezone		= NULL;
54 	bool		explicit_tz;
55     char*       pattern_str		= NULL;
56     int         pattern_str_len	= 0;
57     UChar*      svalue			= NULL;		/* UTF-16 pattern_str */
58     int         slength			= 0;
59 	IntlDateFormatter_object* dfo;
60 
61 	intl_error_reset(NULL TSRMLS_CC);
62 	object = return_value;
63 	/* Parse parameters. */
64     if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sll|Zzs",
65 			&locale_str, &locale_len, &date_type, &time_type, &timezone_zv,
66 			&calendar_zv, &pattern_str, &pattern_str_len) == FAILURE) {
67 		intl_error_set( NULL, U_ILLEGAL_ARGUMENT_ERROR,	"datefmt_create: "
68 				"unable to parse input parameters", 0 TSRMLS_CC);
69 		zval_dtor(return_value);
70 		RETURN_NULL();
71     }
72 
73 	INTL_CHECK_LOCALE_LEN_OBJ(locale_len, return_value);
74 	if (locale_len == 0) {
75 		locale_str = intl_locale_get_default(TSRMLS_C);
76 	}
77 	locale = Locale::createFromName(locale_str);
78 
79 	DATE_FORMAT_METHOD_FETCH_OBJECT_NO_CHECK;
80 
81 	if (DATE_FORMAT_OBJECT(dfo) != NULL) {
82 		intl_errors_set(INTL_DATA_ERROR_P(dfo), U_ILLEGAL_ARGUMENT_ERROR,
83 				"datefmt_create: cannot call constructor twice", 0 TSRMLS_CC);
84 		return;
85 	}
86 
87 	/* process calendar */
88 	if (datefmt_process_calendar_arg(calendar_zv, locale, "datefmt_create",
89 			INTL_DATA_ERROR_P(dfo), calendar, calendar_type,
90 			calendar_owned TSRMLS_CC)
91 			== FAILURE) {
92 		goto error;
93 	}
94 
95 	/* process timezone */
96 	explicit_tz = timezone_zv != NULL && Z_TYPE_PP(timezone_zv) != IS_NULL;
97 
98 	if (explicit_tz || calendar_owned ) {
99 		//we have an explicit time zone or a non-object calendar
100 		timezone = timezone_process_timezone_argument(timezone_zv,
101 				INTL_DATA_ERROR_P(dfo), "datefmt_create" TSRMLS_CC);
102 		if (timezone == NULL) {
103 			goto error;
104 		}
105 	}
106 
107 	/* Convert pattern (if specified) to UTF-16. */
108 	if (pattern_str && pattern_str_len > 0) {
109 		intl_convert_utf8_to_utf16(&svalue, &slength,
110 				pattern_str, pattern_str_len, &INTL_DATA_ERROR_CODE(dfo));
111 		if (U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) {
112 			/* object construction -> only set global error */
113 			intl_error_set(NULL, INTL_DATA_ERROR_CODE(dfo), "datefmt_create: "
114 					"error converting pattern to UTF-16", 0 TSRMLS_CC);
115 			goto error;
116 		}
117 	}
118 
119 	if (pattern_str && pattern_str_len > 0) {
120 		DATE_FORMAT_OBJECT(dfo) = udat_open(UDAT_IGNORE, UDAT_IGNORE,
121 				locale_str, NULL, 0, svalue, slength,
122 				&INTL_DATA_ERROR_CODE(dfo));
123 	} else {
124 		DATE_FORMAT_OBJECT(dfo) = udat_open((UDateFormatStyle)time_type,
125 				(UDateFormatStyle)date_type, locale_str, NULL, 0, svalue,
126 				slength, &INTL_DATA_ERROR_CODE(dfo));
127 	}
128 
129     if (!U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) {
130 		DateFormat *df = (DateFormat*)DATE_FORMAT_OBJECT(dfo);
131 		if (calendar_owned) {
132 			df->adoptCalendar(calendar);
133 			calendar_owned = false;
134 		} else {
135 			df->setCalendar(*calendar);
136 		}
137 
138 		if (timezone != NULL) {
139 			df->adoptTimeZone(timezone);
140 		}
141     } else {
142 		intl_error_set(NULL, INTL_DATA_ERROR_CODE(dfo),	"datefmt_create: date "
143 				"formatter creation failed", 0 TSRMLS_CC);
144 		goto error;
145 	}
146 
147 	/* Set the class variables */
148 	dfo->date_type			= date_type;
149 	dfo->time_type			= time_type;
150 	dfo->calendar			= calendar_type;
151 	dfo->requested_locale	= estrdup(locale_str);
152 
153 error:
154 	if (svalue) {
155 		efree(svalue);
156 	}
157 	if (timezone != NULL && DATE_FORMAT_OBJECT(dfo) == NULL) {
158 		delete timezone;
159 	}
160 	if (calendar != NULL && calendar_owned) {
161 		delete calendar;
162 	}
163 	if (U_FAILURE(intl_error_get_code(NULL TSRMLS_CC))) {
164 		/* free_object handles partially constructed instances fine */
165 		zval_dtor(return_value);
166 		RETVAL_NULL();
167 	}
168 }
169 /* }}} */
170 
171 /* {{{ proto IntlDateFormatter IntlDateFormatter::create(string $locale, long date_type, long time_type[, string $timezone_str, long $calendar, string $pattern] )
172  * Create formatter. }}} */
173 /* {{{ proto IntlDateFormatter datefmt_create(string $locale, long date_type, long time_type[, string $timezone_str, long $calendar, string $pattern)
174  * Create formatter.
175  */
PHP_FUNCTION(datefmt_create)176 U_CFUNC PHP_FUNCTION( datefmt_create )
177 {
178     object_init_ex( return_value, IntlDateFormatter_ce_ptr );
179 	datefmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU);
180 }
181 /* }}} */
182 
183 /* {{{ proto void IntlDateFormatter::__construct(string $locale, long date_type, long time_type[, string $timezone_str, long $calendar, string $pattern])
184  * IntlDateFormatter object constructor.
185  */
PHP_METHOD(IntlDateFormatter,__construct)186 U_CFUNC PHP_METHOD( IntlDateFormatter, __construct )
187 {
188 	/* return_value param is being changed, therefore we will always return
189 	 * NULL here */
190 	return_value = getThis();
191 	datefmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU);
192 }
193 /* }}} */
194