]> granicus.if.org Git - php/commitdiff
Bug #58756: w.r.t MessageFormatter (partial fix)
authorGustavo André dos Santos Lopes <cataphract@php.net>
Wed, 16 May 2012 15:33:12 +0000 (17:33 +0200)
committerGustavo André dos Santos Lopes <cataphract@php.net>
Thu, 17 May 2012 15:57:01 +0000 (17:57 +0200)
I don't think the current ICU API allows this bug to be completely fixed.

Right now, the code cannot control the time zone used in date/time formats
that appear inside complex subformats. See the comment inside
umsg_set_timezone().

ext/intl/msgformat/msgformat_data.c
ext/intl/msgformat/msgformat_data.h
ext/intl/msgformat/msgformat_helpers.cpp
ext/intl/tests/bug58756_MessageFormatter.phpt [new file with mode: 0644]

index 9ed129f05829234e1a9b6cd9a0f3346386225321..62e034bebc664b3205a44432f3887aa662613c1e 100755 (executable)
@@ -29,9 +29,10 @@ void msgformat_data_init( msgformat_data* mf_data TSRMLS_DC )
        if( !mf_data )
                return;
 
-       mf_data->umsgf = NULL;
-       mf_data->orig_format = NULL;
-       mf_data->arg_types = NULL;
+       mf_data->umsgf                  = NULL;
+       mf_data->orig_format    = NULL;
+       mf_data->arg_types              = NULL;
+       mf_data->tz_set                 = 0;
        intl_error_reset( &mf_data->error TSRMLS_CC );
 }
 /* }}} */
index 5a820032402fdece14c54b04965c3e95765b51d7..063efd44729b09d219b75453c2690cee7cdcb2c6 100755 (executable)
@@ -32,6 +32,7 @@ typedef struct {
        char*                   orig_format;
        ulong                   orig_format_len;
        HashTable*              arg_types;
+       int                             tz_set; /* if we've already the time zone in sub-formats */
 } msgformat_data;
 
 msgformat_data* msgformat_data_create( TSRMLS_D );
index f8228df4d3d43431b783d1ce5e4eac0ea64136e2..84c6f40c18f873c77f111eb118a04a9fe3fbcedc 100755 (executable)
@@ -26,6 +26,8 @@
 #include <unicode/msgfmt.h>
 #include <unicode/chariter.h>
 #include <unicode/ustdio.h>
+#include <unicode/timezone.h>
+#include <unicode/datefmt.h>
 
 #include <vector>
 
@@ -40,6 +42,8 @@ extern "C" {
 /* avoid redefinition of int8_t, already defined in unicode/pwin32.h */
 #define _MSC_STDINT_H_ 1
 #include "ext/date/php_date.h"
+#define USE_TIMEZONE_POINTER
+#include "../timezone/timezone_class.h"
 }
 
 #ifndef INFINITY
@@ -368,6 +372,55 @@ static HashTable *umsg_get_types(MessageFormatter_object *mfo,
 #endif
 }
 
+static void umsg_set_timezone(MessageFormatter_object *mfo,
+                                                         intl_error& err TSRMLS_DC)
+{
+       MessageFormat *mf = (MessageFormat *)mfo->mf_data.umsgf;
+       TimeZone          *used_tz = NULL;
+       const Format  **formats;
+       int32_t           count;
+
+       /* Unfortanely, this cannot change the time zone for arguments that
+        * appear inside complex formats because ::getFormats() returns NULL
+        * for all uncached formats, which is the case for complex formats
+        * unless they were set via one of the ::setFormat() methods */
+       
+       if (mfo->mf_data.tz_set) {
+               return; /* already done */
+       }
+
+       formats = mf->getFormats(count);
+       
+       if (formats == NULL) {
+               intl_errors_set(&err, U_MEMORY_ALLOCATION_ERROR,
+                       "Out of memory retrieving subformats", 0 TSRMLS_CC);
+       }
+
+       for (int i = 0; U_SUCCESS(err.code) && i < count; i++) {
+               DateFormat* df = dynamic_cast<DateFormat*>(
+                       const_cast<Format *>(formats[i]));
+               if (df == NULL) {
+                       continue;
+               }
+               
+               if (used_tz == NULL) {
+                       zval nullzv = zval_used_for_init,
+                                *zvptr = &nullzv;
+                       used_tz = timezone_process_timezone_argument(&zvptr, &err,
+                               "msgfmt_format" TSRMLS_CC);
+                       if (used_tz == NULL) {
+                               continue;
+                       }
+               }
+               
+               df->setTimeZone(*used_tz);
+       }
+
+       if (U_SUCCESS(err.code)) {
+               mfo->mf_data.tz_set = 1;
+       }
+}
+
 U_CFUNC void umsg_format_helper(MessageFormatter_object *mfo,
                                                                HashTable *args,
                                                                UChar **formatted,
@@ -385,6 +438,8 @@ U_CFUNC void umsg_format_helper(MessageFormatter_object *mfo,
        }
 
        types = umsg_get_types(mfo, err TSRMLS_CC);
+       
+       umsg_set_timezone(mfo, err TSRMLS_CC);
 
        fargs.resize(arg_count);
        farg_names.resize(arg_count);
diff --git a/ext/intl/tests/bug58756_MessageFormatter.phpt b/ext/intl/tests/bug58756_MessageFormatter.phpt
new file mode 100644 (file)
index 0000000..bbe96b7
--- /dev/null
@@ -0,0 +1,34 @@
+--TEST--
+Bug #58756: w.r.t MessageFormatter
+--SKIPIF--
+<?php
+if (!extension_loaded('intl'))
+       die('skip intl extension not enabled');
+--FILE--
+<?php
+ini_set("intl.error_level", E_WARNING);
+//ini_set("intl.default_locale", "nl");
+
+$time = 1247013673;
+
+ini_set('date.timezone', 'America/New_York');
+
+$msgf = new MessageFormatter('en_US', '{0,date,full} {0,time,h:m:s a V}');
+
+echo "date:  " . date('l, F j, Y g:i:s A T', $time) . "\n";
+echo "msgf:  " . $msgf->format(array($time)) . "\n";
+
+//NOT FIXED:
+/*$msgf = new MessageFormatter('en_US',
+'{1, select, date {{0,date,full}} other {{0,time,h:m:s a V}}}');
+
+echo "msgf2: ", $msgf->format(array($time, 'date')), " ",
+               $msgf->format(array($time, 'time')), "\n";
+*/
+
+?>
+==DONE==
+--EXPECT--
+date:  Tuesday, July 7, 2009 8:41:13 PM EDT
+msgf:  Tuesday, July 7, 2009 8:41:13 PM EDT
+==DONE==
\ No newline at end of file