Fix PhpDoc comments for message accessors to include "|null". (#8136)

Message accessors will return null when when the field is not
set, so this should be reflected in the PhpDoc.

Also updated the code generator for the well-known types to reflect
the edits made in https://github.com/protocolbuffers/protobuf/pull/8105.

Also explicitly check for upb_msg_has() in the oneof accessor, so
we are not implicitly relying on unset message fields returning NULL
at the upb level.
diff --git a/php/ext/google/protobuf/message.c b/php/ext/google/protobuf/message.c
index 8a5a0cf..0e61770 100644
--- a/php/ext/google/protobuf/message.c
+++ b/php/ext/google/protobuf/message.c
@@ -968,6 +968,10 @@
                      (int)field_num);
   }
 
+  if (upb_fielddef_issubmsg(f) && !upb_msg_has(intern->msg, f)) {
+    RETURN_NULL();
+  }
+
   {
     upb_msgval msgval = upb_msg_get(intern->msg, f);
     const Descriptor *subdesc = Descriptor_GetFromFieldDef(f);
diff --git a/php/src/Google/Protobuf/Api.php b/php/src/Google/Protobuf/Api.php
index 7733975..7cbb30e 100644
--- a/php/src/Google/Protobuf/Api.php
+++ b/php/src/Google/Protobuf/Api.php
@@ -271,7 +271,7 @@
      * message.
      *
      * Generated from protobuf field <code>.google.protobuf.SourceContext source_context = 5;</code>
-     * @return \Google\Protobuf\SourceContext
+     * @return \Google\Protobuf\SourceContext|null
      */
     public function getSourceContext()
     {
diff --git a/php/src/Google/Protobuf/Enum.php b/php/src/Google/Protobuf/Enum.php
index ed5afc4..2e0ac99 100644
--- a/php/src/Google/Protobuf/Enum.php
+++ b/php/src/Google/Protobuf/Enum.php
@@ -151,7 +151,7 @@
      * The source context.
      *
      * Generated from protobuf field <code>.google.protobuf.SourceContext source_context = 4;</code>
-     * @return \Google\Protobuf\SourceContext
+     * @return \Google\Protobuf\SourceContext|null
      */
     public function getSourceContext()
     {
diff --git a/php/src/Google/Protobuf/Internal/DescriptorProto.php b/php/src/Google/Protobuf/Internal/DescriptorProto.php
index e0822d7..ff308e7 100644
--- a/php/src/Google/Protobuf/Internal/DescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/DescriptorProto.php
@@ -252,7 +252,7 @@
 
     /**
      * Generated from protobuf field <code>optional .google.protobuf.MessageOptions options = 7;</code>
-     * @return \Google\Protobuf\Internal\MessageOptions
+     * @return \Google\Protobuf\Internal\MessageOptions|null
      */
     public function getOptions()
     {
diff --git a/php/src/Google/Protobuf/Internal/DescriptorProto/ExtensionRange.php b/php/src/Google/Protobuf/Internal/DescriptorProto/ExtensionRange.php
index 1594913..bbe4a6a 100644
--- a/php/src/Google/Protobuf/Internal/DescriptorProto/ExtensionRange.php
+++ b/php/src/Google/Protobuf/Internal/DescriptorProto/ExtensionRange.php
@@ -124,7 +124,7 @@
 
     /**
      * Generated from protobuf field <code>optional .google.protobuf.ExtensionRangeOptions options = 3;</code>
-     * @return \Google\Protobuf\Internal\ExtensionRangeOptions
+     * @return \Google\Protobuf\Internal\ExtensionRangeOptions|null
      */
     public function getOptions()
     {
diff --git a/php/src/Google/Protobuf/Internal/EnumDescriptorProto.php b/php/src/Google/Protobuf/Internal/EnumDescriptorProto.php
index 85dc246..b9b6342 100644
--- a/php/src/Google/Protobuf/Internal/EnumDescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/EnumDescriptorProto.php
@@ -124,7 +124,7 @@
 
     /**
      * Generated from protobuf field <code>optional .google.protobuf.EnumOptions options = 3;</code>
-     * @return \Google\Protobuf\Internal\EnumOptions
+     * @return \Google\Protobuf\Internal\EnumOptions|null
      */
     public function getOptions()
     {
diff --git a/php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php b/php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php
index 01097b6..eff1452 100644
--- a/php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php
@@ -112,7 +112,7 @@
 
     /**
      * Generated from protobuf field <code>optional .google.protobuf.EnumValueOptions options = 3;</code>
-     * @return \Google\Protobuf\Internal\EnumValueOptions
+     * @return \Google\Protobuf\Internal\EnumValueOptions|null
      */
     public function getOptions()
     {
diff --git a/php/src/Google/Protobuf/Internal/FieldDescriptorProto.php b/php/src/Google/Protobuf/Internal/FieldDescriptorProto.php
index 5c8823f..94e5fe1 100644
--- a/php/src/Google/Protobuf/Internal/FieldDescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/FieldDescriptorProto.php
@@ -511,7 +511,7 @@
 
     /**
      * Generated from protobuf field <code>optional .google.protobuf.FieldOptions options = 8;</code>
-     * @return \Google\Protobuf\Internal\FieldOptions
+     * @return \Google\Protobuf\Internal\FieldOptions|null
      */
     public function getOptions()
     {
diff --git a/php/src/Google/Protobuf/Internal/FileDescriptorProto.php b/php/src/Google/Protobuf/Internal/FileDescriptorProto.php
index 96e2c6a..d96c7a7 100644
--- a/php/src/Google/Protobuf/Internal/FileDescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/FileDescriptorProto.php
@@ -371,7 +371,7 @@
 
     /**
      * Generated from protobuf field <code>optional .google.protobuf.FileOptions options = 8;</code>
-     * @return \Google\Protobuf\Internal\FileOptions
+     * @return \Google\Protobuf\Internal\FileOptions|null
      */
     public function getOptions()
     {
@@ -408,7 +408,7 @@
      * development tools.
      *
      * Generated from protobuf field <code>optional .google.protobuf.SourceCodeInfo source_code_info = 9;</code>
-     * @return \Google\Protobuf\Internal\SourceCodeInfo
+     * @return \Google\Protobuf\Internal\SourceCodeInfo|null
      */
     public function getSourceCodeInfo()
     {
diff --git a/php/src/Google/Protobuf/Internal/MethodDescriptorProto.php b/php/src/Google/Protobuf/Internal/MethodDescriptorProto.php
index e2ea8ea..5814f08 100644
--- a/php/src/Google/Protobuf/Internal/MethodDescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/MethodDescriptorProto.php
@@ -176,7 +176,7 @@
 
     /**
      * Generated from protobuf field <code>optional .google.protobuf.MethodOptions options = 4;</code>
-     * @return \Google\Protobuf\Internal\MethodOptions
+     * @return \Google\Protobuf\Internal\MethodOptions|null
      */
     public function getOptions()
     {
diff --git a/php/src/Google/Protobuf/Internal/OneofDescriptorProto.php b/php/src/Google/Protobuf/Internal/OneofDescriptorProto.php
index 5ae36ce..33cf487 100644
--- a/php/src/Google/Protobuf/Internal/OneofDescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/OneofDescriptorProto.php
@@ -75,7 +75,7 @@
 
     /**
      * Generated from protobuf field <code>optional .google.protobuf.OneofOptions options = 2;</code>
-     * @return \Google\Protobuf\Internal\OneofOptions
+     * @return \Google\Protobuf\Internal\OneofOptions|null
      */
     public function getOptions()
     {
diff --git a/php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php b/php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php
index 9c2cc8f..f60561c 100644
--- a/php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php
@@ -102,7 +102,7 @@
 
     /**
      * Generated from protobuf field <code>optional .google.protobuf.ServiceOptions options = 3;</code>
-     * @return \Google\Protobuf\Internal\ServiceOptions
+     * @return \Google\Protobuf\Internal\ServiceOptions|null
      */
     public function getOptions()
     {
diff --git a/php/src/Google/Protobuf/Option.php b/php/src/Google/Protobuf/Option.php
index 9b2cc6c..5166a08 100644
--- a/php/src/Google/Protobuf/Option.php
+++ b/php/src/Google/Protobuf/Option.php
@@ -97,7 +97,7 @@
      * value using the google.protobuf.Int32Value type.
      *
      * Generated from protobuf field <code>.google.protobuf.Any value = 2;</code>
-     * @return \Google\Protobuf\Any
+     * @return \Google\Protobuf\Any|null
      */
     public function getValue()
     {
diff --git a/php/src/Google/Protobuf/Type.php b/php/src/Google/Protobuf/Type.php
index f606866..3f28359 100644
--- a/php/src/Google/Protobuf/Type.php
+++ b/php/src/Google/Protobuf/Type.php
@@ -185,7 +185,7 @@
      * The source context.
      *
      * Generated from protobuf field <code>.google.protobuf.SourceContext source_context = 5;</code>
-     * @return \Google\Protobuf\SourceContext
+     * @return \Google\Protobuf\SourceContext|null
      */
     public function getSourceContext()
     {
diff --git a/php/src/Google/Protobuf/Value.php b/php/src/Google/Protobuf/Value.php
index 20db3cc..7bebb99 100644
--- a/php/src/Google/Protobuf/Value.php
+++ b/php/src/Google/Protobuf/Value.php
@@ -174,7 +174,7 @@
      * Represents a structured value.
      *
      * Generated from protobuf field <code>.google.protobuf.Struct struct_value = 5;</code>
-     * @return \Google\Protobuf\Struct
+     * @return \Google\Protobuf\Struct|null
      */
     public function getStructValue()
     {
@@ -205,7 +205,7 @@
      * Represents a repeated `Value`.
      *
      * Generated from protobuf field <code>.google.protobuf.ListValue list_value = 6;</code>
-     * @return \Google\Protobuf\ListValue
+     * @return \Google\Protobuf\ListValue|null
      */
     public function getListValue()
     {
diff --git a/src/google/protobuf/compiler/php/php_generator.cc b/src/google/protobuf/compiler/php/php_generator.cc
index 6ac748c..04d8f8c 100644
--- a/src/google/protobuf/compiler/php/php_generator.cc
+++ b/src/google/protobuf/compiler/php/php_generator.cc
@@ -95,7 +95,6 @@
                                       const Options& options);
 std::string UnderscoresToCamelCase(const std::string& name,
                                    bool cap_first_letter);
-std::string BinaryToHex(const std::string& binary);
 void Indent(io::Printer* printer);
 void Outdent(io::Printer* printer);
 void GenerateAddFilesToPool(const FileDescriptor* file, const Options& options,
@@ -600,27 +599,6 @@
   return result;
 }
 
-std::string BinaryToHex(const std::string& binary) {
-  std::string dest;
-  size_t i;
-  unsigned char symbol[16] = {
-    '0', '1', '2', '3',
-    '4', '5', '6', '7',
-    '8', '9', 'a', 'b',
-    'c', 'd', 'e', 'f',
-  };
-
-  dest.resize(binary.size() * 2);
-  char* append_ptr = &dest[0];
-
-  for (i = 0; i < binary.size(); i++) {
-    *append_ptr++ = symbol[(binary[i] & 0xf0) >> 4];
-    *append_ptr++ = symbol[binary[i] & 0x0f];
-  }
-
-  return dest;
-}
-
 void Indent(io::Printer* printer) {
   printer->Indent();
   printer->Indent();
@@ -1757,8 +1735,11 @@
       "php_type", PhpSetterTypeName(field, options));
     printer->Print(" * @return $this\n");
   } else if (function_type == kFieldGetter) {
-    printer->Print(" * @return ^php_type^\n",
-      "php_type", PhpGetterTypeName(field, options));
+    bool can_return_null = field->has_presence() &&
+                           field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE;
+    printer->Print(" * @return ^php_type^^maybe_null^\n",
+      "php_type", PhpGetterTypeName(field, options),
+      "maybe_null", can_return_null ? "|null" : "");
   }
   printer->Print(" */\n");
 }
@@ -1858,7 +1839,7 @@
       "  const upb_enumdef *e = upb_symtab_lookupenum(symtab, \"$name$\");\n"
       "  const char *name;\n"
       "  zend_long value;\n"
-      "  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, \"l\", &value) ==\n"
+      "  if (zend_parse_parameters(ZEND_NUM_ARGS(), \"l\", &value) ==\n"
       "      FAILURE) {\n"
       "    return;\n"
       "  }\n"
@@ -1880,7 +1861,7 @@
       "  char *name = NULL;\n"
       "  size_t name_len;\n"
       "  int32_t num;\n"
-      "  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, \"s\", &name,\n"
+      "  if (zend_parse_parameters(ZEND_NUM_ARGS(), \"s\", &name,\n"
       "                            &name_len) == FAILURE) {\n"
       "    return;\n"
       "  }\n"
@@ -1895,8 +1876,8 @@
       "}\n"
       "\n"
       "static zend_function_entry $c_name$_phpmethods[] = {\n"
-      "  PHP_ME($c_name$, name, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)\n"
-      "  PHP_ME($c_name$, value, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)\n"
+      "  PHP_ME($c_name$, name, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)\n"
+      "  PHP_ME($c_name$, value, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)\n"
       "  ZEND_FE_END\n"
       "};\n"
       "\n"
@@ -1990,16 +1971,37 @@
       "camel_name", UnderscoresToCamelCase(oneof->name(), true));
   }
 
+  switch (message->well_known_type()) {
+    case Descriptor::WELLKNOWNTYPE_ANY:
+      printer->Print(
+          "ZEND_BEGIN_ARG_INFO_EX(arginfo_is, 0, 0, 1)\n"
+          "  ZEND_ARG_INFO(0, proto)\n"
+          "ZEND_END_ARG_INFO()\n"
+          "\n"
+      );
+      break;
+    case Descriptor::WELLKNOWNTYPE_TIMESTAMP:
+      printer->Print(
+          "ZEND_BEGIN_ARG_INFO_EX(arginfo_timestamp_fromdatetime, 0, 0, 1)\n"
+          "  ZEND_ARG_INFO(0, datetime)\n"
+          "ZEND_END_ARG_INFO()\n"
+          "\n"
+      );
+      break;
+    default:
+      break;
+  }
+
   printer->Print(
       "static zend_function_entry $c_name$_phpmethods[] = {\n"
-      "  PHP_ME($c_name$, __construct, NULL, ZEND_ACC_PUBLIC)\n",
+      "  PHP_ME($c_name$, __construct, arginfo_void, ZEND_ACC_PUBLIC)\n",
       "c_name", c_name);
 
   for (int i = 0; i < message->field_count(); i++) {
     auto field = message->field(i);
     printer->Print(
-      "  PHP_ME($c_name$, get$camel_name$, NULL, ZEND_ACC_PUBLIC)\n"
-      "  PHP_ME($c_name$, set$camel_name$, NULL, ZEND_ACC_PUBLIC)\n",
+      "  PHP_ME($c_name$, get$camel_name$, arginfo_void, ZEND_ACC_PUBLIC)\n"
+      "  PHP_ME($c_name$, set$camel_name$, arginfo_setter, ZEND_ACC_PUBLIC)\n",
       "c_name", c_name,
       "camel_name", UnderscoresToCamelCase(field->name(), true));
   }
@@ -2007,7 +2009,7 @@
   for (int i = 0; i < message->real_oneof_decl_count(); i++) {
     auto oneof = message->oneof_decl(i);
     printer->Print(
-      "  PHP_ME($c_name$, get$camel_name$, NULL, ZEND_ACC_PUBLIC)\n",
+      "  PHP_ME($c_name$, get$camel_name$, arginfo_void, ZEND_ACC_PUBLIC)\n",
       "c_name", c_name,
       "camel_name", UnderscoresToCamelCase(oneof->name(), true));
   }
@@ -2016,15 +2018,15 @@
   switch (message->well_known_type()) {
     case Descriptor::WELLKNOWNTYPE_ANY:
       printer->Print(
-        "  PHP_ME($c_name$, is, NULL, ZEND_ACC_PUBLIC)\n"
-        "  PHP_ME($c_name$, pack, NULL, ZEND_ACC_PUBLIC)\n"
-        "  PHP_ME($c_name$, unpack, NULL, ZEND_ACC_PUBLIC)\n",
+        "  PHP_ME($c_name$, is, arginfo_is, ZEND_ACC_PUBLIC)\n"
+        "  PHP_ME($c_name$, pack, arginfo_setter, ZEND_ACC_PUBLIC)\n"
+        "  PHP_ME($c_name$, unpack, arginfo_void, ZEND_ACC_PUBLIC)\n",
         "c_name", c_name);
       break;
     case Descriptor::WELLKNOWNTYPE_TIMESTAMP:
       printer->Print(
-        "  PHP_ME($c_name$, fromDateTime, NULL, ZEND_ACC_PUBLIC)\n"
-        "  PHP_ME($c_name$, toDateTime, NULL, ZEND_ACC_PUBLIC)\n",
+        "  PHP_ME($c_name$, fromDateTime, arginfo_timestamp_fromdatetime, ZEND_ACC_PUBLIC)\n"
+        "  PHP_ME($c_name$, toDateTime, arginfo_void, ZEND_ACC_PUBLIC)\n",
         "c_name", c_name);
       break;
     default:
@@ -2154,7 +2156,7 @@
         "}\n"
         "\n"
         "static zend_function_entry $metadata_c_name$_methods[] = {\n"
-        "  PHP_ME($metadata_c_name$, initOnce, NULL, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)\n"
+        "  PHP_ME($metadata_c_name$, initOnce, arginfo_void, ZEND_ACC_PUBLIC | ZEND_ACC_STATIC)\n"
         "  ZEND_FE_END\n"
         "};\n"
         "\n"