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: 90 106 84.9 %
Date: 2015-03-28 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(), "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();
      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             :                 uint32_t         idx;
      90             :                 zval                    *z;
      91             : 
      92           6 :                 if (zend_hash_num_elements(ht) != 2) {
      93             :                         intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
      94             :                                         "datefmt_format_object: bad format; if array, it must have "
      95           2 :                                         "two elements", 0);
      96           2 :                         RETURN_FALSE;
      97             :                 }
      98             : 
      99           4 :                 idx = 0;
     100           8 :                 while (idx < ht->nNumUsed) {
     101           4 :                         z = &ht->arData[idx].val;
     102           4 :                         if (Z_TYPE_P(z) != IS_UNDEF) {
     103           4 :                                 break;
     104             :                         }
     105           0 :                         idx++;
     106             :                 }
     107           4 :                 if (idx >= ht->nNumUsed || !valid_format(z)) {
     108             :                         intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     109             :                                         "datefmt_format_object: bad format; the date format (first "
     110           1 :                                         "element of the array) is not valid", 0);
     111           1 :                         RETURN_FALSE;
     112             :                 }
     113           3 :                 dateStyle = (DateFormat::EStyle)Z_LVAL_P(z);
     114             : 
     115           3 :                 idx++;
     116           6 :                 while (idx < ht->nNumUsed) {
     117           3 :                         z = &ht->arData[idx].val;
     118           3 :                         if (Z_TYPE_P(z) != IS_UNDEF) {
     119           3 :                                 break;
     120             :                         }
     121           0 :                         idx++;
     122             :                 }
     123           3 :                 if (idx >= ht->nNumUsed || !valid_format(z)) {
     124             :                         intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     125             :                                         "datefmt_format_object: bad format; the time format ("
     126           1 :                                         "second element of the array) is not valid", 0);
     127           1 :                         RETURN_FALSE;
     128             :                 }
     129           2 :                 timeStyle = (DateFormat::EStyle)Z_LVAL_P(z);
     130          18 :         } else if (Z_TYPE_P(format) == IS_LONG) {
     131           6 :                 if (!valid_format(format)) {
     132             :                         intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     133             :                                         "datefmt_format_object: the date/time format type is invalid",
     134           1 :                                         0);
     135           1 :                         RETURN_FALSE;
     136             :                 }
     137           5 :                 dateStyle = timeStyle = (DateFormat::EStyle)Z_LVAL_P(format);
     138             :         } else {
     139           6 :                 convert_to_string_ex(format);
     140           3 :                 if (Z_STRLEN_P(format) == 0) {
     141             :                         intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     142           1 :                                         "datefmt_format_object: the format is empty", 0);
     143           1 :                         RETURN_FALSE;
     144             :                 }
     145           2 :                 pattern = true;
     146             :         }
     147             : 
     148             :         //there's no support for relative time in ICU yet
     149          18 :         timeStyle = (DateFormat::EStyle)(timeStyle & ~DateFormat::kRelative);
     150             : 
     151          18 :         zend_class_entry *instance_ce = Z_OBJCE_P(object);
     152          18 :         if (instanceof_function(instance_ce, Calendar_ce_ptr)) {
     153           9 :                 Calendar *obj_cal = calendar_fetch_native_calendar(object);
     154           9 :                 if (obj_cal == NULL) {
     155             :                         intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
     156             :                                         "datefmt_format_object: bad IntlCalendar instance: "
     157           1 :                                         "not initialized properly", 0);
     158           1 :                         RETURN_FALSE;
     159             :                 }
     160           8 :                 timeZone = obj_cal->getTimeZone().clone();
     161           8 :                 date = obj_cal->getTime(status);
     162           8 :                 if (U_FAILURE(status)) {
     163             :                         intl_error_set(NULL, status,
     164             :                                         "datefmt_format_object: error obtaining instant from "
     165           0 :                                         "IntlCalendar", 0);
     166           0 :                         RETVAL_FALSE;
     167           0 :                         goto cleanup;
     168             :                 }
     169           8 :                 cal = obj_cal->clone();
     170           9 :         } else if (instanceof_function(instance_ce, php_date_get_date_ce())) {
     171           7 :                 if (intl_datetime_decompose(object, &date, &timeZone, NULL,
     172             :                                 "datefmt_format_object") == FAILURE) {
     173           1 :                         RETURN_FALSE;
     174             :                 }
     175           6 :                 cal = new GregorianCalendar(Locale::createFromName(locale_str), status);
     176           6 :                 if (U_FAILURE(status)) {
     177             :                         intl_error_set(NULL, status,
     178             :                                         "datefmt_format_object: could not create GregorianCalendar",
     179           0 :                                         0);
     180           0 :                         RETVAL_FALSE;
     181           0 :                         goto cleanup;
     182             :                 }
     183             :         } else {
     184             :                 intl_error_set(NULL, status, "datefmt_format_object: the passed object "
     185             :                                 "must be an instance of either IntlCalendar or DateTime",
     186           2 :                                 0);
     187           2 :                 RETURN_FALSE;
     188             :         }
     189             : 
     190          14 :         if (pattern) {
     191             :                  df = new SimpleDateFormat(
     192             :                                 UnicodeString(Z_STRVAL_P(format), Z_STRLEN_P(format),
     193             :                                                 UnicodeString::kInvariant),
     194             :                                 Locale::createFromName(locale_str),
     195           2 :                                 status);
     196             : 
     197           2 :                 if (U_FAILURE(status)) {
     198             :                         intl_error_set(NULL, status,
     199             :                                         "datefmt_format_object: could not create SimpleDateFormat",
     200           0 :                                         0);
     201           0 :                         RETVAL_FALSE;
     202           0 :                         goto cleanup;
     203             :                 }
     204             :         } else {
     205             :                 df = DateFormat::createDateTimeInstance(dateStyle, timeStyle,
     206          12 :                                 Locale::createFromName(locale_str));
     207             : 
     208          12 :                 if (df == NULL) { /* according to ICU sources, this should never happen */
     209             :                         intl_error_set(NULL, status,
     210             :                                         "datefmt_format_object: could not create DateFormat",
     211           0 :                                         0);
     212           0 :                         RETVAL_FALSE;
     213           0 :                         goto cleanup;
     214             :                 }
     215             :         }
     216             : 
     217             :         //must be in this order (or have the cal adopt the tz)
     218          14 :         df->adoptCalendar(cal);
     219          14 :         cal = NULL;
     220          14 :         df->adoptTimeZone(timeZone);
     221          14 :         timeZone = NULL;
     222             : 
     223             :         {
     224             :                 char *ret_str;
     225             :                 size_t ret_str_len;
     226          14 :                 UnicodeString result = UnicodeString();
     227          14 :                 df->format(date, result);
     228             : 
     229          14 :                 if (intl_charFromString(result, &ret_str, &ret_str_len, &status) == FAILURE) {
     230             :                         intl_error_set(NULL, status,
     231             :                                         "datefmt_format_object: error converting result to UTF-8",
     232           0 :                                         0);
     233           0 :                         RETVAL_FALSE;
     234             :                         goto cleanup;
     235             :                 }
     236          28 :                 RETVAL_STRINGL(ret_str, ret_str_len);
     237             :                 //???
     238          14 :                 efree(ret_str);
     239             :         }
     240             : 
     241             : 
     242             : cleanup:
     243          14 :         delete df;
     244          14 :         delete timeZone;
     245          14 :         delete cal;
     246             : }

Generated by: LCOV version 1.10

Generated at Sun, 29 Mar 2015 03:45:50 +0000 (4 days ago)

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