1 /*
2    +----------------------------------------------------------------------+
3    | This source file is subject to version 3.01 of the PHP license,      |
4    | that is bundled with this package in the file LICENSE, and is        |
5    | available through the world-wide-web at the following url:           |
6    | http://www.php.net/license/3_01.txt                                  |
7    | If you did not receive a copy of the PHP license and are unable to   |
8    | obtain it through the world-wide-web, please send a note to          |
9    | license@php.net so we can mail you a copy immediately.               |
10    +----------------------------------------------------------------------+
11    | Authors: Mel Dafert (mel@dafert.at)                                  |
12    +----------------------------------------------------------------------+
13 */
14 
15 #include "../intl_cppshims.h"
16 
17 #include <unicode/dtptngen.h>
18 
19 #include "../intl_convertcpp.h"
20 
21 extern "C" {
22 #include "php_intl.h"
23 #define USE_DATETIMEPATTERNGENERATOR_POINTER 1
24 #include "datepatterngenerator_class.h"
25 #include <zend_exceptions.h>
26 #include <assert.h>
27 }
28 
29 using icu::DateTimePatternGenerator;
30 using icu::Locale;
31 using icu::StringPiece;
32 
dtpg_ctor(INTERNAL_FUNCTION_PARAMETERS,zend_error_handling * error_handling,bool * error_handling_replaced)33 static zend_result dtpg_ctor(INTERNAL_FUNCTION_PARAMETERS, zend_error_handling *error_handling, bool *error_handling_replaced)
34 {
35 	char *locale_str;
36 	size_t locale_len = 0;
37 	IntlDatePatternGenerator_object* dtpgo;
38 
39 	intl_error_reset(NULL);
40 	zval *object = return_value;
41 
42 	ZEND_PARSE_PARAMETERS_START(0, 1)
43 		Z_PARAM_OPTIONAL
44 		Z_PARAM_STRING_OR_NULL(locale_str, locale_len)
45 	ZEND_PARSE_PARAMETERS_END_EX(return FAILURE);
46 
47 	if (error_handling != NULL) {
48 		zend_replace_error_handling(EH_THROW, IntlException_ce_ptr, error_handling);
49 		*error_handling_replaced = 1;
50 	}
51 
52 	DTPATTERNGEN_METHOD_FETCH_OBJECT_NO_CHECK;
53 
54 	if (dtpgo->dtpg != NULL) {
55 		intl_errors_set(DTPATTERNGEN_ERROR_P(dtpgo), U_ILLEGAL_ARGUMENT_ERROR, "Cannot call constructor twice", 0);
56 		return FAILURE;
57 	}
58 
59 	INTL_CHECK_LOCALE_LEN_OR_FAILURE(locale_len);
60 	if (locale_len == 0) {
61 		locale_str = (char *) intl_locale_get_default();
62 	}
63 	Locale locale = Locale::createFromName(locale_str);
64 
65 	dtpgo->dtpg = DateTimePatternGenerator::createInstance(
66 		locale,
67 		DTPATTERNGEN_ERROR_CODE(dtpgo));
68 
69 	if (U_FAILURE(DTPATTERNGEN_ERROR_CODE(dtpgo))) {
70 		intl_error_set(NULL, DTPATTERNGEN_ERROR_CODE(dtpgo),
71 				"Error creating DateTimePatternGenerator",
72 				0);
73 		return FAILURE;
74 	}
75 
76 	return SUCCESS;
77 }
78 
PHP_METHOD(IntlDatePatternGenerator,create)79 U_CFUNC PHP_METHOD( IntlDatePatternGenerator, create )
80 {
81     object_init_ex( return_value, IntlDatePatternGenerator_ce_ptr );
82     if (dtpg_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, NULL, NULL) == FAILURE) {
83 		zval_ptr_dtor(return_value);
84 		RETURN_NULL();
85 	}
86 }
87 
PHP_METHOD(IntlDatePatternGenerator,__construct)88 U_CFUNC PHP_METHOD( IntlDatePatternGenerator, __construct )
89 {
90 	zend_error_handling error_handling;
91 	bool error_handling_replaced = 0;
92 
93 	/* return_value param is being changed, therefore we will always return
94 	 * NULL here */
95 	return_value = ZEND_THIS;
96 	if (dtpg_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU, &error_handling, &error_handling_replaced) == FAILURE) {
97 		if (!EG(exception)) {
98 			zend_string *err = intl_error_get_message(NULL);
99 			zend_throw_exception(IntlException_ce_ptr, ZSTR_VAL(err), intl_error_get_code(NULL));
100 			zend_string_release_ex(err, 0);
101 		}
102 	}
103 	if (error_handling_replaced) {
104 		zend_restore_error_handling(&error_handling);
105 	}
106 }
107 
108 
PHP_METHOD(IntlDatePatternGenerator,getBestPattern)109 U_CFUNC PHP_METHOD( IntlDatePatternGenerator, getBestPattern )
110 {
111 	char			*skeleton_str	= NULL;
112 	size_t			skeleton_len;
113 	UnicodeString	skeleton_uncleaned;
114 
115 	DTPATTERNGEN_METHOD_INIT_VARS;
116 
117 	/* Parse parameters. */
118 	if( zend_parse_method_parameters( ZEND_NUM_ARGS(), getThis(), "Os",
119 		&object, IntlDatePatternGenerator_ce_ptr,  &skeleton_str, &skeleton_len ) == FAILURE )
120 	{
121 		RETURN_THROWS();
122 	}
123 
124 	DTPATTERNGEN_METHOD_FETCH_OBJECT;
125 
126 	intl_stringFromChar(skeleton_uncleaned, skeleton_str, skeleton_len, DTPATTERNGEN_ERROR_CODE_P(dtpgo));
127 
128 	INTL_METHOD_CHECK_STATUS(dtpgo, "Skeleton is not a valid UTF-8 string");
129 
130 	UnicodeString skeleton = dtpgo->dtpg->getSkeleton(skeleton_uncleaned, DTPATTERNGEN_ERROR_CODE(dtpgo));
131 
132 	INTL_METHOD_CHECK_STATUS(dtpgo, "Error getting cleaned skeleton");
133 
134 	UnicodeString result = dtpgo->dtpg->getBestPattern(skeleton, DTPATTERNGEN_ERROR_CODE(dtpgo));
135 
136 	INTL_METHOD_CHECK_STATUS(dtpgo, "Error retrieving pattern");
137 
138 	zend_string *u8str = intl_charFromString(result, DTPATTERNGEN_ERROR_CODE_P(dtpgo));
139 
140 	INTL_METHOD_CHECK_STATUS(dtpgo, "Error converting result to UTF-8");
141 
142 	RETVAL_STR(u8str);
143 }
144