Call php method via function name instead of calling directly.

This changes the linking error if php extension is not statically linked
to a runtime error. In this way, users who don't need Timestamp can
still use protobuf even if date extension is not statically linked in
php.
diff --git a/php/ext/google/protobuf/message.c b/php/ext/google/protobuf/message.c
index 5b654a7..7d7d865 100644
--- a/php/ext/google/protobuf/message.c
+++ b/php/ext/google/protobuf/message.c
@@ -31,10 +31,6 @@
 #include <php.h>
 #include <stdlib.h>
 
-#ifdef PROTOBUF_ENABLE_TIMESTAMP
-#include <ext/date/php_date.h>
-#endif
-
 #include "protobuf.h"
 #include "utf8.h"
 
@@ -1124,7 +1120,6 @@
 PHP_PROTO_FIELD_ACCESSORS(Timestamp, timestamp, Nanos,   "nanos")
 
 PHP_METHOD(Timestamp, fromDateTime) {
-#ifdef PROTOBUF_ENABLE_TIMESTAMP
   zval* datetime;
   zval member;
 
@@ -1134,23 +1129,27 @@
   }
 
   // Get timestamp from Datetime object.
-  zval* retval_ptr;
-  zval* function_name;
+  zval retval;
+  zval function_name;
   int64_t timestamp;
 
-  MAKE_STD_ZVAL(retval_ptr);
-  MAKE_STD_ZVAL(function_name);
+#if PHP_MAJOR_VERSION < 7
+  INIT_ZVAL(retval);
+  INIT_ZVAL(function_name);
+#endif
 
-  ZVAL_STRING(function_name, "date_timestamp_get", 1);
+  PHP_PROTO_ZVAL_STRING(&function_name, "date_timestamp_get", 1);
 
-  if (call_user_function(EG(function_table), NULL,
-                         function_name, retval_ptr, 1,
-                         &datetime TSRMLS_CC) == SUCCESS) {
-    protobuf_convert_to_int64(retval_ptr, &timestamp);
+  if (call_user_function(EG(function_table), NULL, &function_name, &retval, 1,
+          ZVAL_PTR_TO_CACHED_PTR(datetime) TSRMLS_CC) == FAILURE) {
+    zend_error(E_ERROR, "Cannot get timestamp from DateTime.");
+    return;
   }
 
-  zval_ptr_dtor(&retval_ptr);
-  zval_ptr_dtor(&function_name);
+  protobuf_convert_to_int64(&retval, &timestamp);
+
+  zval_dtor(&retval);
+  zval_dtor(&function_name);
 
   // Set seconds
   MessageHeader* self = UNBOX(MessageHeader, getThis());
@@ -1167,17 +1166,9 @@
   *(int32_t*)memory = 0;
 
   RETURN_NULL();
-#else
-  zend_error(E_USER_ERROR, "fromDateTime needs date extension.");
-#endif
 }
 
 PHP_METHOD(Timestamp, toDateTime) {
-#ifdef PROTOBUF_ENABLE_TIMESTAMP
-  zval datetime;
-  php_date_instantiate(php_date_get_date_ce(), &datetime TSRMLS_CC);
-  php_date_obj* dateobj = UNBOX(php_date_obj, &datetime);
-
   // Get seconds
   MessageHeader* self = UNBOX(MessageHeader, getThis());
   const upb_fielddef* field =
@@ -1198,16 +1189,37 @@
   strftime(formated_time, sizeof(formated_time), "%Y-%m-%dT%H:%M:%SUTC",
            utc_time);
 
-  if (!php_date_initialize(dateobj, formated_time, strlen(formated_time), NULL,
-                           NULL, 0 TSRMLS_CC)) {
-    zval_dtor(&datetime);
-    RETURN_NULL();
+  // Create Datetime object.
+  zval datetime;
+  zval formated_time_php;
+  zval function_name;
+  int64_t timestamp = 0;
+
+#if PHP_MAJOR_VERSION < 7
+  INIT_ZVAL(function_name);
+  INIT_ZVAL(formated_time_php);
+#endif
+
+  PHP_PROTO_ZVAL_STRING(&function_name, "date_create", 1);
+  PHP_PROTO_ZVAL_STRING(&formated_time_php, formated_time, 1);
+
+  CACHED_VALUE params[1] = {ZVAL_TO_CACHED_VALUE(formated_time_php)};
+
+  if (call_user_function(EG(function_table), NULL,
+                         &function_name, &datetime, 1,
+                         params TSRMLS_CC) == FAILURE) {
+    zend_error(E_ERROR, "Cannot create DateTime.");
+    return;
   }
 
+  zval_dtor(&formated_time_php);
+  zval_dtor(&function_name);
+
+#if PHP_MAJOR_VERSION < 7
   zval* datetime_ptr = &datetime;
   PHP_PROTO_RETVAL_ZVAL(datetime_ptr);
 #else
-  zend_error(E_USER_ERROR, "toDateTime needs date extension.");
+  ZVAL_OBJ(return_value, Z_OBJ(datetime));
 #endif
 }
 
diff --git a/php/ext/google/protobuf/protobuf.h b/php/ext/google/protobuf/protobuf.h
index f299b41..6ab0f13 100644
--- a/php/ext/google/protobuf/protobuf.h
+++ b/php/ext/google/protobuf/protobuf.h
@@ -182,6 +182,8 @@
 #define CACHED_TO_ZVAL_PTR(VALUE) (VALUE)
 #define CACHED_PTR_TO_ZVAL_PTR(VALUE) (*VALUE)
 #define ZVAL_PTR_TO_CACHED_PTR(VALUE) (&VALUE)
+#define ZVAL_PTR_TO_CACHED_VALUE(VALUE) (VALUE)
+#define ZVAL_TO_CACHED_VALUE(VALUE) (&VALUE)
 
 #define CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(zval_ptr, class_type) \
   ZVAL_OBJ(zval_ptr, class_type->create_object(class_type TSRMLS_CC));
@@ -452,6 +454,8 @@
 #define CACHED_TO_ZVAL_PTR(VALUE) (&VALUE)
 #define CACHED_PTR_TO_ZVAL_PTR(VALUE) (VALUE)
 #define ZVAL_PTR_TO_CACHED_PTR(VALUE) (VALUE)
+#define ZVAL_PTR_TO_CACHED_VALUE(VALUE) (*VALUE)
+#define ZVAL_TO_CACHED_VALUE(VALUE) (VALUE)
 
 #define CREATE_OBJ_ON_ALLOCATED_ZVAL_PTR(zval_ptr, class_type) \
   ZVAL_OBJ(zval_ptr, class_type->create_object(class_type));
diff --git a/php/tests/memory_leak_test.php b/php/tests/memory_leak_test.php
index ce26883..507635e 100644
--- a/php/tests/memory_leak_test.php
+++ b/php/tests/memory_leak_test.php
@@ -131,12 +131,12 @@
 date_default_timezone_set('UTC');
 $from = new DateTime('2011-01-01T15:03:01.012345UTC');
 $timestamp->fromDateTime($from);
-assert($from->format('U'), $timestamp->getSeconds());
-assert(0, $timestamp->getNanos());
+assert($from->format('U') == $timestamp->getSeconds());
+assert(0 == $timestamp->getNanos());
 
 $to = $timestamp->toDateTime();
-assert(\DateTime::class, get_class($to));
-assert($from->format('U'), $to->format('U'));
+assert(\DateTime::class == get_class($to));
+assert($from->format('U') == $to->format('U'));
 
 $from = new \Google\Protobuf\Value();
 $from->setNumberValue(1);
diff --git a/php/tests/test.sh b/php/tests/test.sh
index a308a1d..c35372d 100755
--- a/php/tests/test.sh
+++ b/php/tests/test.sh
@@ -5,7 +5,7 @@
 make clean || true
 set -e
 # Add following in configure for debug: --enable-debug CFLAGS='-g -O0'
-phpize && ./configure CFLAGS='-g -O0 -DPROTOBUF_ENABLE_TIMESTAMP' && make
+phpize && ./configure CFLAGS='-g -O0' && make
 popd
 
 tests=( array_test.php encode_decode_test.php generated_class_test.php generated_phpdoc_test.php map_field_test.php well_known_test.php generated_service_test.php descriptors_test.php )