PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/intl/dateformat - dateformat_format_object.cpp (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 85 99 85.9 %
Date: 2014-12-13 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :    +----------------------------------------------------------------------+
       3             :    | PHP Version 7                                                        |
       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/calendar.h>
      20             : #include <unicode/gregocal.h>
      21             : #include <unicode/datefmt.h>
      22             : #include <unicode/smpdtfmt.h>
      23             : #include <unicode/locid.h>
      24             : 
      25             : #include "../intl_convertcpp.h"
      26             : 
      27             : extern "C" {
      28             : #include "../php_intl.h"
      29             : #include "../locale/locale.h"
      30             : #define USE_CALENDAR_POINTER 1
      31             : #include "../calendar/calendar_class.h"
      32             : #include <ext/date/php_date.h>
      33             : #include "../common/common_date.h"
      34             : }
      35             : 
      36             : static const DateFormat::EStyle valid_styles[] = {
      37             :                 DateFormat::kNone,
      38             :                 DateFormat::kFull,
      39             :                 DateFormat::kLong,
      40             :                 DateFormat::kMedium,
      41             :                 DateFormat::kShort,
      42             :                 DateFormat::kFullRelative,
      43             :                 DateFormat::kLongRelative,
      44             :                 DateFormat::kMediumRelative,
      45             :                 DateFormat::kShortRelative,
      46             : };
      47             : 
      48          13 : static bool valid_format(zval *z) {
      49          13 :         if (Z_TYPE_P(z) == IS_LONG) {
      50          12 :                 zend_long lval = Z_LVAL_P(z);
      51          47 :                 for (int i = 0; i < sizeof(valid_styles) / sizeof(*valid_styles); i++) {
      52          45 :                         if ((zend_long)valid_styles[i] == lval) {
      53          10 :                                 return true;
      54             :                         }
      55             :                 }
      56             :         }
      57             : 
      58           3 :         return false;
      59             : }
      60             : 
      61          27 : U_CFUNC PHP_FUNCTION(datefmt_format_object)
      62             : {
      63             :         zval                            *object,
      64          27 :                                                 *format = NULL;
      65          27 :         const char                      *locale_str     = NULL;
      66             :         size_t                                  locale_len;
      67          27 :         bool                            pattern         = false;
      68             :         UDate                           date;
      69          27 :         TimeZone                        *timeZone       = NULL;
      70          27 :         UErrorCode                      status          = U_ZERO_ERROR;
      71          27 :         DateFormat                      *df                     = NULL;
      72          27 :         Calendar                        *cal            = NULL;
      73          27 :         DateFormat::EStyle      dateStyle = DateFormat::kDefault,
      74          27 :                                                 timeStyle = DateFormat::kDefault;
      75             : 
      76          27 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o|zs!",
      77             :                         &object, &format, &locale_str, &locale_len) == FAILURE) {
      78           3 :                 RETURN_FALSE;
      79             :         }
      80             : 
      81          24 :         if (!locale_str) {
      82          17 :                 locale_str = intl_locale_get_default(TSRMLS_C);
      83             :         }
      84             : 
      85          41 :         if (format == NULL || Z_TYPE_P(format) == IS_NULL) {
      86             :                 //nothing
      87          30 :         } else if (Z_TYPE_P(format) == IS_ARRAY) {
      88           6 :                 HashTable               *ht     = Z_ARRVAL_P(format);
      89           6 :                 HashPosition    pos     = {0};
      90             :                 zval                    *z;
      91           6 :                 if (zend_hash_num_elements(ht) != 2) {
      92             :                         intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
      93             :                                         "datefmt_format_object: bad format; if array, it must have "
      94           2 :                                         "two elements", 0 TSRMLS_CC);
      95           2 :                         RETURN_FALSE;
      96             :                 }
      97             : 
      98           4 :                 zend_hash_internal_pointer_reset_ex(ht, &pos);
      99           4 :                 z = zend_hash_get_current_data_ex(ht, &pos);
     100           4 :                 if (!valid_format(z)) {
     101             :                         intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     102             :                                         "datefmt_format_object: bad format; the date format (first "
     103           1 :                                         "element of the array) is not valid", 0 TSRMLS_CC);
     104           1 :                         RETURN_FALSE;
     105             :                 }
     106           3 :                 dateStyle = (DateFormat::EStyle)Z_LVAL_P(z);
     107             : 
     108           3 :                 zend_hash_move_forward_ex(ht, &pos);
     109           3 :                 z = zend_hash_get_current_data_ex(ht, &pos);
     110           3 :                 if (!valid_format(z)) {
     111             :                         intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     112             :                                         "datefmt_format_object: bad format; the time format ("
     113           1 :                                         "second element of the array) is not valid", 0 TSRMLS_CC);
     114           1 :                         RETURN_FALSE;
     115             :                 }
     116           2 :                 timeStyle = (DateFormat::EStyle)Z_LVAL_P(z);
     117          18 :         } else if (Z_TYPE_P(format) == IS_LONG) {
     118           6 :                 if (!valid_format(format)) {
     119             :                         intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     120             :                                         "datefmt_format_object: the date/time format type is invalid",
     121           1 :                                         0 TSRMLS_CC);
     122           1 :                         RETURN_FALSE;
     123             :                 }
     124           5 :                 dateStyle = timeStyle = (DateFormat::EStyle)Z_LVAL_P(format);
     125             :         } else {
     126           6 :                 convert_to_string_ex(format);
     127           3 :                 if (Z_STRLEN_P(format) == 0) {
     128             :                         intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     129           1 :                                         "datefmt_format_object: the format is empty", 0 TSRMLS_CC);
     130           1 :                         RETURN_FALSE;
     131             :                 }
     132           2 :                 pattern = true;
     133             :         }
     134             : 
     135             :         //there's no support for relative time in ICU yet
     136          18 :         timeStyle = (DateFormat::EStyle)(timeStyle & ~DateFormat::kRelative);
     137             : 
     138          18 :         zend_class_entry *instance_ce = Z_OBJCE_P(object);
     139          18 :         if (instanceof_function(instance_ce, Calendar_ce_ptr TSRMLS_CC)) {
     140           9 :                 Calendar *obj_cal = calendar_fetch_native_calendar(object TSRMLS_CC);
     141           9 :                 if (obj_cal == NULL) {
     142             :                         intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     143             :                                         "datefmt_format_object: bad IntlCalendar instance: "
     144           1 :                                         "not initialized properly", 0 TSRMLS_CC);
     145           1 :                         RETURN_FALSE;
     146             :                 }
     147           8 :                 timeZone = obj_cal->getTimeZone().clone();
     148           8 :                 date = obj_cal->getTime(status);
     149           8 :                 if (U_FAILURE(status)) {
     150             :                         intl_error_set(NULL, status,
     151             :                                         "datefmt_format_object: error obtaining instant from "
     152           0 :                                         "IntlCalendar", 0 TSRMLS_CC);
     153           0 :                         RETVAL_FALSE;
     154           0 :                         goto cleanup;
     155             :                 }
     156           8 :                 cal = obj_cal->clone();
     157           9 :         } else if (instanceof_function(instance_ce, php_date_get_date_ce() TSRMLS_CC)) {
     158           7 :                 if (intl_datetime_decompose(object, &date, &timeZone, NULL,
     159             :                                 "datefmt_format_object" TSRMLS_CC) == FAILURE) {
     160           1 :                         RETURN_FALSE;
     161             :                 }
     162           6 :                 cal = new GregorianCalendar(Locale::createFromName(locale_str), status);
     163           6 :                 if (U_FAILURE(status)) {
     164             :                         intl_error_set(NULL, status,
     165             :                                         "datefmt_format_object: could not create GregorianCalendar",
     166           0 :                                         0 TSRMLS_CC);
     167           0 :                         RETVAL_FALSE;
     168           0 :                         goto cleanup;
     169             :                 }
     170             :         } else {
     171             :                 intl_error_set(NULL, status, "datefmt_format_object: the passed object "
     172             :                                 "must be an instance of either IntlCalendar or DateTime",
     173           2 :                                 0 TSRMLS_CC);
     174           2 :                 RETURN_FALSE;
     175             :         }
     176             : 
     177          14 :         if (pattern) {
     178             :                  df = new SimpleDateFormat(
     179             :                                 UnicodeString(Z_STRVAL_P(format), Z_STRLEN_P(format),
     180             :                                                 UnicodeString::kInvariant),
     181             :                                 Locale::createFromName(locale_str),
     182           2 :                                 status);
     183             : 
     184           2 :                 if (U_FAILURE(status)) {
     185             :                         intl_error_set(NULL, status,
     186             :                                         "datefmt_format_object: could not create SimpleDateFormat",
     187           0 :                                         0 TSRMLS_CC);
     188           0 :                         RETVAL_FALSE;
     189           0 :                         goto cleanup;
     190             :                 }
     191             :         } else {
     192             :                 df = DateFormat::createDateTimeInstance(dateStyle, timeStyle,
     193          12 :                                 Locale::createFromName(locale_str));
     194             : 
     195          12 :                 if (df == NULL) { /* according to ICU sources, this should never happen */
     196             :                         intl_error_set(NULL, status,
     197             :                                         "datefmt_format_object: could not create DateFormat",
     198           0 :                                         0 TSRMLS_CC);
     199           0 :                         RETVAL_FALSE;
     200           0 :                         goto cleanup;
     201             :                 }
     202             :         }
     203             : 
     204             :         //must be in this order (or have the cal adopt the tz)
     205          14 :         df->adoptCalendar(cal);
     206          14 :         cal = NULL;
     207          14 :         df->adoptTimeZone(timeZone);
     208          14 :         timeZone = NULL;
     209             : 
     210             :         {
     211             :                 char *ret_str;
     212             :                 int ret_str_len;
     213          14 :                 UnicodeString result = UnicodeString();
     214          14 :                 df->format(date, result);
     215             : 
     216          14 :                 if (intl_charFromString(result, &ret_str, &ret_str_len, &status) == FAILURE) {
     217             :                         intl_error_set(NULL, status,
     218             :                                         "datefmt_format_object: error converting result to UTF-8",
     219           0 :                                         0 TSRMLS_CC);
     220           0 :                         RETVAL_FALSE;
     221             :                         goto cleanup;
     222             :                 }
     223          28 :                 RETVAL_STRINGL(ret_str, ret_str_len);
     224             :                 //???
     225          14 :                 efree(ret_str);
     226             :         }
     227             : 
     228             : 
     229             : cleanup:
     230          14 :         delete df;
     231          14 :         delete timeZone;
     232          14 :         delete cal;
     233             : }

Generated by: LCOV version 1.10

Generated at Sat, 13 Dec 2014 06:16:14 +0000 (9 days ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.