瀏覽代碼

PHP namespaces for nested messages and enums (#4536)

* uses namespaces for nested messages and enums

* fixes namespaces for PHP dist

* fixes namespace for Descriptors, adds Cardinality and Kind

* fixes nested namespaces for reserved words and adds tests

* adds tests and generator fix for php class prefixes

* fixes escaping of protobuf packages, enum comments, misc others

* nice refactor of generated code

* adds class files for backwards compatibility

* simplifies code with templates

* adds compatibility files to makefile

* cleanup of generator and fixes nested namespace bug

* regenerates proto types

* remove internal BC classes

* adds deprecated warning, adds methods back

* simplifies if statement

* fixes dist files

* addresses review comments

* adds back TYPE_URL_PREFIX constant

* adds @deprecated to old nested class files

* skips tests which require a separate process when protobuf.so is enabled

* Adds tests for legacy nested classes that do not require separate processes to test

* uses legacy names for GPBUtil message check

* adds block for IDE @deprecated message

* Namespace for nested message/enum in c extension

* Remove unused code
Brent Shaffer 7 年之前
父節點
當前提交
2774e5441d
共有 77 個文件被更改,包括 1477 次插入657 次删除
  1. 15 13
      Makefile.am
  2. 164 89
      php/ext/google/protobuf/def.c
  3. 6 2
      php/ext/google/protobuf/message.c
  4. 6 6
      php/src/GPBMetadata/Google/Protobuf/Internal/Descriptor.php
  5. 81 27
      php/src/Google/Protobuf/Any.php
  6. 42 2
      php/src/Google/Protobuf/Api.php
  7. 12 2
      php/src/Google/Protobuf/BoolValue.php
  8. 12 2
      php/src/Google/Protobuf/BytesValue.php
  9. 12 2
      php/src/Google/Protobuf/DoubleValue.php
  10. 22 2
      php/src/Google/Protobuf/Duration.php
  11. 20 2
      php/src/Google/Protobuf/Enum.php
  12. 16 2
      php/src/Google/Protobuf/EnumValue.php
  13. 32 2
      php/src/Google/Protobuf/Field.php
  14. 42 0
      php/src/Google/Protobuf/Field/Cardinality.php
  15. 132 0
      php/src/Google/Protobuf/Field/Kind.php
  16. 16 2
      php/src/Google/Protobuf/FieldMask.php
  17. 6 29
      php/src/Google/Protobuf/Field_Cardinality.php
  18. 6 119
      php/src/Google/Protobuf/Field_Kind.php
  19. 12 2
      php/src/Google/Protobuf/FloatValue.php
  20. 10 2
      php/src/Google/Protobuf/GPBEmpty.php
  21. 12 2
      php/src/Google/Protobuf/Int32Value.php
  22. 12 2
      php/src/Google/Protobuf/Int64Value.php
  23. 6 6
      php/src/Google/Protobuf/Internal/DescriptorProto.php
  24. 5 2
      php/src/Google/Protobuf/Internal/DescriptorProto/ExtensionRange.php
  25. 5 2
      php/src/Google/Protobuf/Internal/DescriptorProto/ReservedRange.php
  26. 3 3
      php/src/Google/Protobuf/Internal/EnumDescriptorProto.php
  27. 5 2
      php/src/Google/Protobuf/Internal/EnumDescriptorProto/EnumReservedRange.php
  28. 6 3
      php/src/Google/Protobuf/Internal/FieldDescriptorProto/Label.php
  29. 6 3
      php/src/Google/Protobuf/Internal/FieldDescriptorProto/Type.php
  30. 6 3
      php/src/Google/Protobuf/Internal/FieldOptions/CType.php
  31. 6 3
      php/src/Google/Protobuf/Internal/FieldOptions/JSType.php
  32. 8 0
      php/src/Google/Protobuf/Internal/FileOptions.php
  33. 6 3
      php/src/Google/Protobuf/Internal/FileOptions/OptimizeMode.php
  34. 13 5
      php/src/Google/Protobuf/Internal/GPBUtil.php
  35. 3 3
      php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php
  36. 5 2
      php/src/Google/Protobuf/Internal/GeneratedCodeInfo/Annotation.php
  37. 6 3
      php/src/Google/Protobuf/Internal/MethodOptions/IdempotencyLevel.php
  38. 3 3
      php/src/Google/Protobuf/Internal/SourceCodeInfo.php
  39. 5 2
      php/src/Google/Protobuf/Internal/SourceCodeInfo/Location.php
  40. 3 3
      php/src/Google/Protobuf/Internal/UninterpretedOption.php
  41. 5 2
      php/src/Google/Protobuf/Internal/UninterpretedOption/NamePart.php
  42. 12 2
      php/src/Google/Protobuf/ListValue.php
  43. 24 2
      php/src/Google/Protobuf/Method.php
  44. 15 2
      php/src/Google/Protobuf/Mixin.php
  45. 1 1
      php/src/Google/Protobuf/NullValue.php
  46. 20 2
      php/src/Google/Protobuf/Option.php
  47. 13 2
      php/src/Google/Protobuf/SourceContext.php
  48. 12 2
      php/src/Google/Protobuf/StringValue.php
  49. 12 2
      php/src/Google/Protobuf/Struct.php
  50. 1 1
      php/src/Google/Protobuf/Syntax.php
  51. 20 3
      php/src/Google/Protobuf/Timestamp.php
  52. 22 2
      php/src/Google/Protobuf/Type.php
  53. 12 2
      php/src/Google/Protobuf/UInt32Value.php
  54. 12 2
      php/src/Google/Protobuf/UInt64Value.php
  55. 22 2
      php/src/Google/Protobuf/Value.php
  56. 6 6
      php/tests/array_test.php
  57. 1 1
      php/tests/descriptors_test.php
  58. 3 3
      php/tests/encode_decode_test.php
  59. 2 2
      php/tests/gdb_test.sh
  60. 135 30
      php/tests/generated_class_test.php
  61. 3 3
      php/tests/generated_phpdoc_test.php
  62. 5 5
      php/tests/map_field_test.php
  63. 5 5
      php/tests/memory_leak_test.php
  64. 2 2
      php/tests/php_implementation_test.php
  65. 17 0
      php/tests/proto/empty/echo.proto
  66. 10 0
      php/tests/proto/test_empty_php_namespace.proto
  67. 11 0
      php/tests/proto/test_include.proto
  68. 8 4
      php/tests/proto/test_no_namespace.proto
  69. 22 0
      php/tests/proto/test_php_namespace.proto
  70. 8 0
      php/tests/proto/test_prefix.proto
  71. 1 1
      php/tests/test_base.php
  72. 9 9
      php/tests/test_util.php
  73. 43 43
      php/tests/undefined_test.php
  74. 6 6
      php/tests/well_known_test.php
  75. 187 135
      src/google/protobuf/compiler/php/php_generator.cc
  76. 0 10
      src/google/protobuf/compiler/php/php_generator.h
  77. 2 1
      tests.sh

+ 15 - 13
Makefile.am

@@ -619,7 +619,9 @@ php_EXTRA_DIST=                                                       \
   php/src/Google/Protobuf/Field.php                                   \
   php/src/Google/Protobuf/FieldDescriptor.php                         \
   php/src/Google/Protobuf/FieldMask.php                               \
+  php/src/Google/Protobuf/Field/Cardinality.php                       \
   php/src/Google/Protobuf/Field_Cardinality.php                       \
+  php/src/Google/Protobuf/Field/Kind.php                              \
   php/src/Google/Protobuf/Field_Kind.php                              \
   php/src/Google/Protobuf/FloatValue.php                              \
   php/src/Google/Protobuf/GPBEmpty.php                                \
@@ -630,30 +632,29 @@ php_EXTRA_DIST=                                                       \
   php/src/Google/Protobuf/Internal/Descriptor.php                     \
   php/src/Google/Protobuf/Internal/DescriptorPool.php                 \
   php/src/Google/Protobuf/Internal/DescriptorProto.php                \
-  php/src/Google/Protobuf/Internal/DescriptorProto_ExtensionRange.php \
-  php/src/Google/Protobuf/Internal/DescriptorProto_ReservedRange.php  \
+  php/src/Google/Protobuf/Internal/DescriptorProto/ExtensionRange.php \
+  php/src/Google/Protobuf/Internal/DescriptorProto/ReservedRange.php  \
   php/src/Google/Protobuf/Internal/EnumBuilderContext.php             \
   php/src/Google/Protobuf/Internal/EnumDescriptor.php                 \
   php/src/Google/Protobuf/Internal/EnumDescriptorProto.php            \
-  php/src/Google/Protobuf/Internal/EnumDescriptorProto_EnumReservedRange.php \
+  php/src/Google/Protobuf/Internal/EnumDescriptorProto/EnumReservedRange.php \
   php/src/Google/Protobuf/Internal/EnumOptions.php                    \
   php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php       \
   php/src/Google/Protobuf/Internal/EnumValueOptions.php               \
   php/src/Google/Protobuf/Internal/ExtensionRangeOptions.php          \
-  php/src/Google/Protobuf/Internal/FieldDescriptorProto_Label.php     \
   php/src/Google/Protobuf/Internal/FieldDescriptorProto.php           \
   php/src/Google/Protobuf/Internal/FieldDescriptor.php                \
   php/src/Google/Protobuf/Internal/FieldDescriptorProto.php           \
-  php/src/Google/Protobuf/Internal/FieldDescriptorProto_Label.php     \
-  php/src/Google/Protobuf/Internal/FieldDescriptorProto_Type.php      \
+  php/src/Google/Protobuf/Internal/FieldDescriptorProto/Label.php     \
+  php/src/Google/Protobuf/Internal/FieldDescriptorProto/Type.php      \
   php/src/Google/Protobuf/Internal/FieldOptions.php                   \
-  php/src/Google/Protobuf/Internal/FieldOptions_CType.php             \
-  php/src/Google/Protobuf/Internal/FieldOptions_JSType.php            \
+  php/src/Google/Protobuf/Internal/FieldOptions/CType.php             \
+  php/src/Google/Protobuf/Internal/FieldOptions/JSType.php            \
   php/src/Google/Protobuf/Internal/FileDescriptor.php                 \
   php/src/Google/Protobuf/Internal/FileDescriptorProto.php            \
   php/src/Google/Protobuf/Internal/FileDescriptorSet.php              \
   php/src/Google/Protobuf/Internal/FileOptions.php                    \
-  php/src/Google/Protobuf/Internal/FileOptions_OptimizeMode.php       \
+  php/src/Google/Protobuf/Internal/FileOptions/OptimizeMode.php       \
   php/src/Google/Protobuf/Internal/GPBDecodeException.php             \
   php/src/Google/Protobuf/Internal/GPBJsonWire.php                    \
   php/src/Google/Protobuf/Internal/GPBLabel.php                       \
@@ -662,7 +663,7 @@ php_EXTRA_DIST=                                                       \
   php/src/Google/Protobuf/Internal/GPBWire.php                        \
   php/src/Google/Protobuf/Internal/GPBWireType.php                    \
   php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php              \
-  php/src/Google/Protobuf/Internal/GeneratedCodeInfo_Annotation.php   \
+  php/src/Google/Protobuf/Internal/GeneratedCodeInfo/Annotation.php   \
   php/src/Google/Protobuf/Internal/GetPublicDescriptorTrait.php       \
   php/src/Google/Protobuf/Internal/HasPublicDescriptorTrait.php       \
   php/src/Google/Protobuf/Internal/MapEntry.php                       \
@@ -673,7 +674,7 @@ php_EXTRA_DIST=                                                       \
   php/src/Google/Protobuf/Internal/MessageOptions.php                 \
   php/src/Google/Protobuf/Internal/MethodDescriptorProto.php          \
   php/src/Google/Protobuf/Internal/MethodOptions.php                  \
-  php/src/Google/Protobuf/Internal/MethodOptions_IdempotencyLevel.php \
+  php/src/Google/Protobuf/Internal/MethodOptions/IdempotencyLevel.php \
   php/src/Google/Protobuf/Internal/OneofDescriptor.php                \
   php/src/Google/Protobuf/Internal/OneofDescriptorProto.php           \
   php/src/Google/Protobuf/Internal/OneofField.php                     \
@@ -684,9 +685,9 @@ php_EXTRA_DIST=                                                       \
   php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php         \
   php/src/Google/Protobuf/Internal/ServiceOptions.php                 \
   php/src/Google/Protobuf/Internal/SourceCodeInfo.php                 \
-  php/src/Google/Protobuf/Internal/SourceCodeInfo_Location.php        \
+  php/src/Google/Protobuf/Internal/SourceCodeInfo/Location.php        \
   php/src/Google/Protobuf/Internal/UninterpretedOption.php            \
-  php/src/Google/Protobuf/Internal/UninterpretedOption_NamePart.php   \
+  php/src/Google/Protobuf/Internal/UninterpretedOption/NamePart.php   \
   php/src/Google/Protobuf/ListValue.php                               \
   php/src/Google/Protobuf/Method.php                                  \
   php/src/Google/Protobuf/Mixin.php                                   \
@@ -716,6 +717,7 @@ php_EXTRA_DIST=                                                       \
   php/tests/map_field_test.php                                        \
   php/tests/memory_leak_test.php                                      \
   php/tests/php_implementation_test.php                               \
+  php/tests/proto/empty/echo.proto                                    \
   php/tests/proto/test.proto                                          \
   php/tests/proto/test_descriptors.proto                              \
   php/tests/proto/test_empty_php_namespace.proto                      \

+ 164 - 89
php/ext/google/protobuf/def.c

@@ -718,105 +718,186 @@ PHP_METHOD(InternalDescriptorPool, getGeneratedPool) {
 #endif
 }
 
-static void classname_no_prefix(const char *fullname, const char *package_name,
-                                char *class_name) {
-  size_t i = 0, j;
-  bool first_char = true, is_reserved = false;
-  size_t pkg_name_len = package_name == NULL ? 0 : strlen(package_name);
-  size_t message_name_start = package_name == NULL ? 0 : pkg_name_len + 1;
-  size_t message_len = (strlen(fullname) - message_name_start);
+static size_t classname_len_max(const char *fullname,
+                                const char *package,
+                                const char *php_namespace,
+                                const char *prefix) {
+  size_t fullname_len = strlen(fullname);
+  size_t package_len = 0;
+  size_t prefix_len = 0;
+  size_t namespace_len = 0;
+  size_t length = fullname_len;
+  int i, segment, classname_start = 0;
+
+  if (package != NULL) {
+    package_len = strlen(package);
+  }
+  if (prefix != NULL) {
+    prefix_len = strlen(prefix);
+  }
+  if (php_namespace != NULL) {
+    namespace_len = strlen(php_namespace);
+  }
 
-  // Submessage is concatenated with its containing messages by '_'.
-  for (j = message_name_start; j < message_name_start + message_len; j++) {
-    if (fullname[j] == '.') {
-      class_name[i++] = '_';
-    } else {
-      class_name[i++] = fullname[j];
+  // Process package
+  if (package_len > 0) {
+    segment = 1;
+    for (i = 0; i < package_len; i++) {
+      if (package[i] == '.') {
+        segment++;
+      }
     }
-  }
-}
+    // In case of reserved name in package.
+    length += 3 * segment;
 
-static const char *classname_prefix(const char *classname,
-                                    const char *prefix_given,
-                                    const char *package_name) {
-  size_t i;
-  bool is_reserved = false;
+    classname_start = package_len + 1;
+  }
 
-  if (prefix_given != NULL && strcmp(prefix_given, "") != 0) {
-    return prefix_given;
+  // Process class name
+  segment = 1;
+  for (i = classname_start; i < fullname_len; i++) {
+    if (fullname[i] == '.') {
+      segment++;
+    }
+  }
+  if (prefix_len == 0) {
+    length += 3 * segment;
+  } else {
+    length += prefix_len * segment;
   }
 
-  char* lower = ALLOC_N(char, strlen(classname) + 1);
-  i = 0;
-  while(classname[i]) {
-    lower[i] = (char)tolower(classname[i]);
+  // The additional 2, one is for preceding '.' and the other is for trailing 0.
+  return length + namespace_len + 2;
+}
+
+static bool is_reserved(const char *segment, int length) {
+  bool result;
+  char* lower = ALLOC_N(char, length + 1);
+  memcpy(lower, segment, length);
+  int i = 0;
+  while(lower[i]) {
+    lower[i] = (char)tolower(lower[i]);
     i++;
   }
-  lower[i] = 0;
-
-  is_reserved = is_reserved_name(lower);
+  lower[length] = 0;
+  result = is_reserved_name(lower);
   FREE(lower);
+  return result;
+}
 
-  if (is_reserved) {
-    if (package_name != NULL && strcmp("google.protobuf", package_name) == 0) {
-      return "GPB";
-    } else {
-      return "PB";
+static char* fill_prefix(const char *segment, int length,
+                         const char *prefix_given,
+                         const char *package_name, char *classname) {
+  size_t i;
+
+  if (prefix_given != NULL && strcmp(prefix_given, "") != 0) {
+    size_t prefix_len = strlen(prefix_given);
+    memcpy(classname, prefix_given, strlen(prefix_given));
+    classname += prefix_len;
+  } else {
+    if (is_reserved(segment, length)) {
+      if (package_name != NULL &&
+          strcmp("google.protobuf", package_name) == 0) {
+        memcpy(classname, "GPB", 3);
+        classname += 3;
+      } else {
+        memcpy(classname, "PB", 2);
+        classname += 2;
+      }
     }
   }
+  return classname;
+}
 
-  return "";
+static char* fill_segment(const char *segment, int length,
+                          char *classname, bool use_camel) {
+  memcpy(classname, segment, length);
+  if (use_camel && (segment[0] < 'A' || segment[0] > 'Z')) {
+    classname[0] += 'A' - 'a';
+  }
+  return classname + length;
 }
 
-static void convert_to_class_name_inplace(const char *package,
-                                          const char *namespace_given,
-                                          const char *prefix, char *classname) {
-  size_t prefix_len = prefix == NULL ? 0 : strlen(prefix);
-  size_t classname_len = strlen(classname);
-  int i = 0, j;
-  bool first_char = true;
+static char* fill_namespace(const char *package, const char *namespace_given,
+                            char *classname) {
+  if (namespace_given != NULL) {
+    size_t namespace_len = strlen(namespace_given);
+    memcpy(classname, namespace_given, namespace_len);
+    classname += namespace_len;
+    *classname = '\\';
+    classname++;
+  } else if (package != NULL) {
+    int i = 0, j, offset = 0;
+    size_t package_len = strlen(package);
+    while (i < package_len) {
+      j = i;
+      while (j < package_len && package[j] != '.') {
+        j++;
+      }
+      classname = fill_prefix(package + i, j - i, "", package, classname);
+      classname = fill_segment(package + i, j - i, classname, true);
+      classname[0] = '\\';
+      classname++;
+      i = j + 1;
+    }
+  }
+  return classname;
+}
 
-  size_t package_len = package == NULL ? 0 : strlen(package);
-  size_t namespace_given_len =
-      namespace_given == NULL ? 0 : strlen(namespace_given);
-  bool use_namespace_given = namespace_given != NULL;
-  size_t namespace_len =
-      use_namespace_given ? namespace_given_len : package_len;
+static char* fill_classname(const char *fullname,
+                            const char *package,
+                            const char *namespace_given,
+                            const char *prefix, char *classname) {
+  int classname_start = 0;
+  if (package != NULL) {
+    size_t package_len = strlen(package);
+    classname_start = package_len == 0 ? 0 : package_len + 1;
+  }
+  size_t fullname_len = strlen(fullname);
+  classname = fill_prefix(fullname + classname_start,
+                          fullname_len - classname_start,
+                          prefix, package, classname);
+
+  int i = classname_start, j;
+  while (i < fullname_len) {
+    j = i;
+    while (j < fullname_len && fullname[j] != '.') {
+      j++;
+    }
+    classname = fill_segment(fullname + i, j - i, classname, false);
+    if (j != fullname_len) {
+      *classname = '_';
+      classname++;
+    }
+    i = j + 1;
+  }
+  return classname;
+}
 
-  int offset = namespace_len != 0 ? 2 : 0;
+static char* fill_qualified_classname(const char *fullname,
+                                      const char *package,
+                                      const char *namespace_given,
+                                      const char *prefix, char *classname) {
+  classname = fill_namespace(package, namespace_given, classname);
+  return fill_classname(fullname, package, namespace_given, prefix, classname);
+}
 
-  for (j = 0; j < classname_len; j++) {
-    classname[namespace_len + prefix_len + classname_len + offset - 1 - j] =
-        classname[classname_len - j - 1];
-  }
+static void classname_no_prefix(const char *fullname, const char *package_name,
+                                char *class_name) {
+  size_t i = 0, j;
+  bool first_char = true, is_reserved = false;
+  size_t pkg_name_len = package_name == NULL ? 0 : strlen(package_name);
+  size_t message_name_start = package_name == NULL ? 0 : pkg_name_len + 1;
+  size_t message_len = (strlen(fullname) - message_name_start);
 
-  if (namespace_len != 0) {
-    classname[i++] = '\\';
-    for (j = 0; j < namespace_len; j++) {
-      if (use_namespace_given) {
-        classname[i++] = namespace_given[j];
-        continue;
-      }
-      // php packages are divided by '\'.
-      if (package[j] == '.') {
-        classname[i++] = '\\';
-        first_char = true;
-      } else if (first_char) {
-        // PHP package uses camel case.
-        if (package[j] < 'A' || package[j] > 'Z') {
-          classname[i++] = package[j] + 'A' - 'a';
-        } else {
-          classname[i++] = package[j];
-        }
-        first_char = false;
-      } else {
-        classname[i++] = package[j];
-      }
+  // Submessage is concatenated with its containing messages by '_'.
+  for (j = message_name_start; j < message_name_start + message_len; j++) {
+    if (fullname[j] == '.') {
+      class_name[i++] = '_';
+    } else {
+      class_name[i++] = fullname[j];
     }
-    classname[i++] = '\\';
   }
-
-  memcpy(classname + i, prefix, prefix_len);
 }
 
 void internal_add_generated_file(const char *data, PHP_PROTO_SIZE data_len,
@@ -858,20 +939,14 @@ void internal_add_generated_file(const char *data, PHP_PROTO_SIZE data_len,
      * bytes allocated, one for '.', one for trailing 0, and 3 for 'GPB' if    \
      * given message is google.protobuf.Empty.*/                               \
     const char *fullname = upb_##def_type_lower##_fullname(def_type_lower);    \
+    const char *package = upb_filedef_package(files[0]);                       \
     const char *php_namespace = upb_filedef_phpnamespace(files[0]);            \
     const char *prefix_given = upb_filedef_phpprefix(files[0]);                \
-    size_t classname_len = strlen(fullname) + 5;                               \
-    if (prefix_given != NULL) {                                                \
-      classname_len += strlen(prefix_given);                                   \
-    }                                                                          \
-    if (php_namespace != NULL) {                                               \
-      classname_len += strlen(php_namespace);                                  \
-    }                                                                          \
+    size_t classname_len = classname_len_max(fullname, package,                \
+                                             php_namespace, prefix_given);     \
     char *classname = ecalloc(sizeof(char), classname_len);                    \
-    const char *package = upb_filedef_package(files[0]);                       \
-    classname_no_prefix(fullname, package, classname);                         \
-    const char *prefix = classname_prefix(classname, prefix_given, package);   \
-    convert_to_class_name_inplace(package, php_namespace, prefix, classname);  \
+    fill_qualified_classname(fullname, package, php_namespace,                 \
+                             prefix_given, classname);                         \
     PHP_PROTO_CE_DECLARE pce;                                                  \
     if (php_proto_zend_lookup_class(classname, strlen(classname), &pce) ==     \
         FAILURE) {                                                             \

+ 6 - 2
php/ext/google/protobuf/message.c

@@ -858,7 +858,7 @@ static zend_function_entry field_cardinality_methods[] = {
 zend_class_entry* field_cardinality_type;
 
 // Init class entry.
-PHP_PROTO_INIT_ENUMCLASS_START("Google\\Protobuf\\Field_Cardinality",
+PHP_PROTO_INIT_ENUMCLASS_START("Google\\Protobuf\\Field\\Cardinality",
                                 Field_Cardinality, field_cardinality)
   zend_declare_class_constant_long(field_cardinality_type,
                                    "CARDINALITY_UNKNOWN", 19, 0 TSRMLS_CC);
@@ -868,6 +868,8 @@ PHP_PROTO_INIT_ENUMCLASS_START("Google\\Protobuf\\Field_Cardinality",
                                    "CARDINALITY_REQUIRED", 20, 2 TSRMLS_CC);
   zend_declare_class_constant_long(field_cardinality_type,
                                    "CARDINALITY_REPEATED", 20, 3 TSRMLS_CC);
+  const char *alias = "Google\\Protobuf\\Field_Cardinality";
+  zend_register_class_alias_ex(alias, strlen(alias), field_cardinality_type TSRMLS_CC);
 PHP_PROTO_INIT_ENUMCLASS_END
 
 // -----------------------------------------------------------------------------
@@ -881,7 +883,7 @@ static zend_function_entry field_kind_methods[] = {
 zend_class_entry* field_kind_type;
 
 // Init class entry.
-PHP_PROTO_INIT_ENUMCLASS_START("Google\\Protobuf\\Field_Kind",
+PHP_PROTO_INIT_ENUMCLASS_START("Google\\Protobuf\\Field\\Kind",
                                 Field_Kind, field_kind)
   zend_declare_class_constant_long(field_kind_type,
                                    "TYPE_UNKNOWN", 12, 0 TSRMLS_CC);
@@ -921,6 +923,8 @@ PHP_PROTO_INIT_ENUMCLASS_START("Google\\Protobuf\\Field_Kind",
                                    "TYPE_SINT32", 11, 17 TSRMLS_CC);
   zend_declare_class_constant_long(field_kind_type,
                                    "TYPE_SINT64", 11, 18 TSRMLS_CC);
+  const char *alias = "Google\\Protobuf\\Field_Kind";
+  zend_register_class_alias_ex(alias, strlen(alias), field_kind_type TSRMLS_CC);
 PHP_PROTO_INIT_ENUMCLASS_END
 
 // -----------------------------------------------------------------------------

+ 6 - 6
php/src/GPBMetadata/Google/Protobuf/Internal/Descriptor.php

@@ -46,13 +46,13 @@ class Descriptor
             ->repeated('reserved_name', \Google\Protobuf\Internal\GPBType::STRING, 10)
             ->finalizeToPool();
 
-        $pool->addMessage('google.protobuf.internal.DescriptorProto.ExtensionRange', \Google\Protobuf\Internal\DescriptorProto_ExtensionRange::class)
+        $pool->addMessage('google.protobuf.internal.DescriptorProto.ExtensionRange', \Google\Protobuf\Internal\DescriptorProto\ExtensionRange::class)
             ->optional('start', \Google\Protobuf\Internal\GPBType::INT32, 1)
             ->optional('end', \Google\Protobuf\Internal\GPBType::INT32, 2)
             ->optional('options', \Google\Protobuf\Internal\GPBType::MESSAGE, 3, 'google.protobuf.internal.ExtensionRangeOptions')
             ->finalizeToPool();
 
-        $pool->addMessage('google.protobuf.internal.DescriptorProto.ReservedRange', \Google\Protobuf\Internal\DescriptorProto_ReservedRange::class)
+        $pool->addMessage('google.protobuf.internal.DescriptorProto.ReservedRange', \Google\Protobuf\Internal\DescriptorProto\ReservedRange::class)
             ->optional('start', \Google\Protobuf\Internal\GPBType::INT32, 1)
             ->optional('end', \Google\Protobuf\Internal\GPBType::INT32, 2)
             ->finalizeToPool();
@@ -114,7 +114,7 @@ class Descriptor
             ->repeated('reserved_name', \Google\Protobuf\Internal\GPBType::STRING, 5)
             ->finalizeToPool();
 
-        $pool->addMessage('google.protobuf.internal.EnumDescriptorProto.EnumReservedRange', \Google\Protobuf\Internal\EnumDescriptorProto_EnumReservedRange::class)
+        $pool->addMessage('google.protobuf.internal.EnumDescriptorProto.EnumReservedRange', \Google\Protobuf\Internal\EnumDescriptorProto\EnumReservedRange::class)
             ->optional('start', \Google\Protobuf\Internal\GPBType::INT32, 1)
             ->optional('end', \Google\Protobuf\Internal\GPBType::INT32, 2)
             ->finalizeToPool();
@@ -242,7 +242,7 @@ class Descriptor
             ->optional('aggregate_value', \Google\Protobuf\Internal\GPBType::STRING, 8)
             ->finalizeToPool();
 
-        $pool->addMessage('google.protobuf.internal.UninterpretedOption.NamePart', \Google\Protobuf\Internal\UninterpretedOption_NamePart::class)
+        $pool->addMessage('google.protobuf.internal.UninterpretedOption.NamePart', \Google\Protobuf\Internal\UninterpretedOption\NamePart::class)
             ->required('name_part', \Google\Protobuf\Internal\GPBType::STRING, 1)
             ->required('is_extension', \Google\Protobuf\Internal\GPBType::BOOL, 2)
             ->finalizeToPool();
@@ -251,7 +251,7 @@ class Descriptor
             ->repeated('location', \Google\Protobuf\Internal\GPBType::MESSAGE, 1, 'google.protobuf.internal.SourceCodeInfo.Location')
             ->finalizeToPool();
 
-        $pool->addMessage('google.protobuf.internal.SourceCodeInfo.Location', \Google\Protobuf\Internal\SourceCodeInfo_Location::class)
+        $pool->addMessage('google.protobuf.internal.SourceCodeInfo.Location', \Google\Protobuf\Internal\SourceCodeInfo\Location::class)
             ->repeated('path', \Google\Protobuf\Internal\GPBType::INT32, 1)
             ->repeated('span', \Google\Protobuf\Internal\GPBType::INT32, 2)
             ->optional('leading_comments', \Google\Protobuf\Internal\GPBType::STRING, 3)
@@ -263,7 +263,7 @@ class Descriptor
             ->repeated('annotation', \Google\Protobuf\Internal\GPBType::MESSAGE, 1, 'google.protobuf.internal.GeneratedCodeInfo.Annotation')
             ->finalizeToPool();
 
-        $pool->addMessage('google.protobuf.internal.GeneratedCodeInfo.Annotation', \Google\Protobuf\Internal\GeneratedCodeInfo_Annotation::class)
+        $pool->addMessage('google.protobuf.internal.GeneratedCodeInfo.Annotation', \Google\Protobuf\Internal\GeneratedCodeInfo\Annotation::class)
             ->repeated('path', \Google\Protobuf\Internal\GPBType::INT32, 1)
             ->optional('source_file', \Google\Protobuf\Internal\GPBType::STRING, 2)
             ->optional('begin', \Google\Protobuf\Internal\GPBType::INT32, 3)

+ 81 - 27
php/src/Google/Protobuf/Any.php

@@ -5,9 +5,9 @@
 namespace Google\Protobuf;
 
 use Google\Protobuf\Internal\GPBType;
-use Google\Protobuf\Internal\GPBUtil;
 use Google\Protobuf\Internal\Message;
 use Google\Protobuf\Internal\RepeatedField;
+use Google\Protobuf\Internal\GPBUtil;
 
 /**
  * `Any` contains an arbitrary serialized protocol buffer message along with a
@@ -37,6 +37,14 @@ use Google\Protobuf\Internal\RepeatedField;
  *     if any.Is(Foo.DESCRIPTOR):
  *       any.Unpack(foo)
  *       ...
+ *  Example 4: Pack and unpack a message in Go
+ *      foo := &pb.Foo{...}
+ *      any, err := ptypes.MarshalAny(foo)
+ *      ...
+ *      foo := &pb.Foo{}
+ *      if err := ptypes.UnmarshalAny(any, foo); err != nil {
+ *        ...
+ *      }
  * The pack methods provided by protobuf library will by default use
  * 'type.googleapis.com/full.type.name' as the type URL and the unpack
  * methods only use the fully qualified type name after the last '/'
@@ -71,15 +79,16 @@ use Google\Protobuf\Internal\RepeatedField;
 class Any extends \Google\Protobuf\Internal\Message
 {
     /**
-     * A URL/resource name whose content describes the type of the
-     * serialized protocol buffer message.
-     * For URLs which use the scheme `http`, `https`, or no scheme, the
-     * following restrictions and interpretations apply:
+     * A URL/resource name that uniquely identifies the type of the serialized
+     * protocol buffer message. The last segment of the URL's path must represent
+     * the fully qualified name of the type (as in
+     * `path/google.protobuf.Duration`). The name should be in a canonical form
+     * (e.g., leading "." is not accepted).
+     * In practice, teams usually precompile into the binary all types that they
+     * expect it to use in the context of Any. However, for URLs which use the
+     * scheme `http`, `https`, or no scheme, one can optionally set up a type
+     * server that maps type URLs to message definitions as follows:
      * * If no scheme is provided, `https` is assumed.
-     * * The last segment of the URL's path must represent the fully
-     *   qualified name of the type (as in `path/google.protobuf.Duration`).
-     *   The name should be in a canonical form (e.g., leading "." is
-     *   not accepted).
      * * An HTTP GET on the URL must yield a [google.protobuf.Type][]
      *   value in binary format, or produce an error.
      * * Applications are allowed to cache lookup results based on the
@@ -87,6 +96,9 @@ class Any extends \Google\Protobuf\Internal\Message
      *   lookup. Therefore, binary compatibility needs to be preserved
      *   on changes to types. (Use versioned type names to manage
      *   breaking changes.)
+     * Note: this functionality is not currently available in the official
+     * protobuf release, and it is not used for type URLs beginning with
+     * type.googleapis.com.
      * Schemes other than `http`, `https` (or the empty scheme) might be
      * used with implementation specific semantics.
      *
@@ -102,21 +114,55 @@ class Any extends \Google\Protobuf\Internal\Message
 
     const TYPE_URL_PREFIX = 'type.googleapis.com/';
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string $type_url
+     *           A URL/resource name that uniquely identifies the type of the serialized
+     *           protocol buffer message. The last segment of the URL's path must represent
+     *           the fully qualified name of the type (as in
+     *           `path/google.protobuf.Duration`). The name should be in a canonical form
+     *           (e.g., leading "." is not accepted).
+     *           In practice, teams usually precompile into the binary all types that they
+     *           expect it to use in the context of Any. However, for URLs which use the
+     *           scheme `http`, `https`, or no scheme, one can optionally set up a type
+     *           server that maps type URLs to message definitions as follows:
+     *           * If no scheme is provided, `https` is assumed.
+     *           * An HTTP GET on the URL must yield a [google.protobuf.Type][]
+     *             value in binary format, or produce an error.
+     *           * Applications are allowed to cache lookup results based on the
+     *             URL, or have them precompiled into a binary to avoid any
+     *             lookup. Therefore, binary compatibility needs to be preserved
+     *             on changes to types. (Use versioned type names to manage
+     *             breaking changes.)
+     *           Note: this functionality is not currently available in the official
+     *           protobuf release, and it is not used for type URLs beginning with
+     *           type.googleapis.com.
+     *           Schemes other than `http`, `https` (or the empty scheme) might be
+     *           used with implementation specific semantics.
+     *     @type string $value
+     *           Must be a valid serialized protocol buffer of the above specified type.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Any::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
-     * A URL/resource name whose content describes the type of the
-     * serialized protocol buffer message.
-     * For URLs which use the scheme `http`, `https`, or no scheme, the
-     * following restrictions and interpretations apply:
+     * A URL/resource name that uniquely identifies the type of the serialized
+     * protocol buffer message. The last segment of the URL's path must represent
+     * the fully qualified name of the type (as in
+     * `path/google.protobuf.Duration`). The name should be in a canonical form
+     * (e.g., leading "." is not accepted).
+     * In practice, teams usually precompile into the binary all types that they
+     * expect it to use in the context of Any. However, for URLs which use the
+     * scheme `http`, `https`, or no scheme, one can optionally set up a type
+     * server that maps type URLs to message definitions as follows:
      * * If no scheme is provided, `https` is assumed.
-     * * The last segment of the URL's path must represent the fully
-     *   qualified name of the type (as in `path/google.protobuf.Duration`).
-     *   The name should be in a canonical form (e.g., leading "." is
-     *   not accepted).
      * * An HTTP GET on the URL must yield a [google.protobuf.Type][]
      *   value in binary format, or produce an error.
      * * Applications are allowed to cache lookup results based on the
@@ -124,6 +170,9 @@ class Any extends \Google\Protobuf\Internal\Message
      *   lookup. Therefore, binary compatibility needs to be preserved
      *   on changes to types. (Use versioned type names to manage
      *   breaking changes.)
+     * Note: this functionality is not currently available in the official
+     * protobuf release, and it is not used for type URLs beginning with
+     * type.googleapis.com.
      * Schemes other than `http`, `https` (or the empty scheme) might be
      * used with implementation specific semantics.
      *
@@ -136,15 +185,16 @@ class Any extends \Google\Protobuf\Internal\Message
     }
 
     /**
-     * A URL/resource name whose content describes the type of the
-     * serialized protocol buffer message.
-     * For URLs which use the scheme `http`, `https`, or no scheme, the
-     * following restrictions and interpretations apply:
+     * A URL/resource name that uniquely identifies the type of the serialized
+     * protocol buffer message. The last segment of the URL's path must represent
+     * the fully qualified name of the type (as in
+     * `path/google.protobuf.Duration`). The name should be in a canonical form
+     * (e.g., leading "." is not accepted).
+     * In practice, teams usually precompile into the binary all types that they
+     * expect it to use in the context of Any. However, for URLs which use the
+     * scheme `http`, `https`, or no scheme, one can optionally set up a type
+     * server that maps type URLs to message definitions as follows:
      * * If no scheme is provided, `https` is assumed.
-     * * The last segment of the URL's path must represent the fully
-     *   qualified name of the type (as in `path/google.protobuf.Duration`).
-     *   The name should be in a canonical form (e.g., leading "." is
-     *   not accepted).
      * * An HTTP GET on the URL must yield a [google.protobuf.Type][]
      *   value in binary format, or produce an error.
      * * Applications are allowed to cache lookup results based on the
@@ -152,6 +202,9 @@ class Any extends \Google\Protobuf\Internal\Message
      *   lookup. Therefore, binary compatibility needs to be preserved
      *   on changes to types. (Use versioned type names to manage
      *   breaking changes.)
+     * Note: this functionality is not currently available in the official
+     * protobuf release, and it is not used for type URLs beginning with
+     * type.googleapis.com.
      * Schemes other than `http`, `https` (or the empty scheme) might be
      * used with implementation specific semantics.
      *
@@ -269,3 +322,4 @@ class Any extends \Google\Protobuf\Internal\Message
         return $this->type_url === $type_url;
     }
 }
+

+ 42 - 2
php/src/Google/Protobuf/Api.php

@@ -83,9 +83,49 @@ class Api extends \Google\Protobuf\Internal\Message
      */
     private $syntax = 0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string $name
+     *           The fully qualified name of this interface, including package name
+     *           followed by the interface's simple name.
+     *     @type \Google\Protobuf\Method[]|\Google\Protobuf\Internal\RepeatedField $methods
+     *           The methods of this interface, in unspecified order.
+     *     @type \Google\Protobuf\Option[]|\Google\Protobuf\Internal\RepeatedField $options
+     *           Any metadata attached to the interface.
+     *     @type string $version
+     *           A version string for this interface. If specified, must have the form
+     *           `major-version.minor-version`, as in `1.10`. If the minor version is
+     *           omitted, it defaults to zero. If the entire version field is empty, the
+     *           major version is derived from the package name, as outlined below. If the
+     *           field is not empty, the version in the package name will be verified to be
+     *           consistent with what is provided here.
+     *           The versioning schema uses [semantic
+     *           versioning](http://semver.org) where the major version number
+     *           indicates a breaking change and the minor version an additive,
+     *           non-breaking change. Both version numbers are signals to users
+     *           what to expect from different versions, and should be carefully
+     *           chosen based on the product plan.
+     *           The major version is also reflected in the package name of the
+     *           interface, which must end in `v<major-version>`, as in
+     *           `google.feature.v1`. For major versions 0 and 1, the suffix can
+     *           be omitted. Zero major versions must only be used for
+     *           experimental, non-GA interfaces.
+     *     @type \Google\Protobuf\SourceContext $source_context
+     *           Source context for the protocol buffer service represented by this
+     *           message.
+     *     @type \Google\Protobuf\Mixin[]|\Google\Protobuf\Internal\RepeatedField $mixins
+     *           Included interfaces. See [Mixin][].
+     *     @type int $syntax
+     *           The source syntax of the service.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Api::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**

+ 12 - 2
php/src/Google/Protobuf/BoolValue.php

@@ -23,9 +23,19 @@ class BoolValue extends \Google\Protobuf\Internal\Message
      */
     private $value = false;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type bool $value
+     *           The bool value.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Wrappers::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**

+ 12 - 2
php/src/Google/Protobuf/BytesValue.php

@@ -23,9 +23,19 @@ class BytesValue extends \Google\Protobuf\Internal\Message
      */
     private $value = '';
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string $value
+     *           The bytes value.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Wrappers::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**

+ 12 - 2
php/src/Google/Protobuf/DoubleValue.php

@@ -23,9 +23,19 @@ class DoubleValue extends \Google\Protobuf\Internal\Message
      */
     private $value = 0.0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type float $value
+     *           The double value.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Wrappers::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**

+ 22 - 2
php/src/Google/Protobuf/Duration.php

@@ -79,9 +79,28 @@ class Duration extends \Google\Protobuf\Internal\Message
      */
     private $nanos = 0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int|string $seconds
+     *           Signed seconds of the span of time. Must be from -315,576,000,000
+     *           to +315,576,000,000 inclusive. Note: these bounds are computed from:
+     *           60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years
+     *     @type int $nanos
+     *           Signed fractions of a second at nanosecond resolution of the span
+     *           of time. Durations less than one second are represented with a 0
+     *           `seconds` field and a positive or negative `nanos` field. For durations
+     *           of one second or more, a non-zero value for the `nanos` field must be
+     *           of the same sign as the `seconds` field. Must be from -999,999,999
+     *           to +999,999,999 inclusive.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Duration::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
@@ -149,5 +168,6 @@ class Duration extends \Google\Protobuf\Internal\Message
 
         return $this;
     }
+
 }
 

+ 20 - 2
php/src/Google/Protobuf/Enum.php

@@ -46,9 +46,27 @@ class Enum extends \Google\Protobuf\Internal\Message
      */
     private $syntax = 0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string $name
+     *           Enum type name.
+     *     @type \Google\Protobuf\EnumValue[]|\Google\Protobuf\Internal\RepeatedField $enumvalue
+     *           Enum value definitions.
+     *     @type \Google\Protobuf\Option[]|\Google\Protobuf\Internal\RepeatedField $options
+     *           Protocol buffer options.
+     *     @type \Google\Protobuf\SourceContext $source_context
+     *           The source context.
+     *     @type int $syntax
+     *           The source syntax.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Type::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**

+ 16 - 2
php/src/Google/Protobuf/EnumValue.php

@@ -34,9 +34,23 @@ class EnumValue extends \Google\Protobuf\Internal\Message
      */
     private $options;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string $name
+     *           Enum value name.
+     *     @type int $number
+     *           Enum value number.
+     *     @type \Google\Protobuf\Option[]|\Google\Protobuf\Internal\RepeatedField $options
+     *           Protocol buffer options.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Type::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**

+ 32 - 2
php/src/Google/Protobuf/Field.php

@@ -78,9 +78,39 @@ class Field extends \Google\Protobuf\Internal\Message
      */
     private $default_value = '';
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int $kind
+     *           The field type.
+     *     @type int $cardinality
+     *           The field cardinality.
+     *     @type int $number
+     *           The field number.
+     *     @type string $name
+     *           The field name.
+     *     @type string $type_url
+     *           The field type URL, without the scheme, for message or enumeration
+     *           types. Example: `"type.googleapis.com/google.protobuf.Timestamp"`.
+     *     @type int $oneof_index
+     *           The index of the field type in `Type.oneofs`, for message or enumeration
+     *           types. The first type has index 1; zero means the type is not in the list.
+     *     @type bool $packed
+     *           Whether to use alternative packed wire representation.
+     *     @type \Google\Protobuf\Option[]|\Google\Protobuf\Internal\RepeatedField $options
+     *           The protocol buffer options.
+     *     @type string $json_name
+     *           The field JSON name.
+     *     @type string $default_value
+     *           The string value of the default value of this field. Proto2 syntax only.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Type::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**

+ 42 - 0
php/src/Google/Protobuf/Field/Cardinality.php

@@ -0,0 +1,42 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: google/protobuf/type.proto
+
+namespace Google\Protobuf\Field;
+
+/**
+ * Whether a field is optional, required, or repeated.
+ *
+ * Protobuf type <code>google.protobuf.Field.Cardinality</code>
+ */
+class Cardinality
+{
+    /**
+     * For fields with unknown cardinality.
+     *
+     * Generated from protobuf enum <code>CARDINALITY_UNKNOWN = 0;</code>
+     */
+    const CARDINALITY_UNKNOWN = 0;
+    /**
+     * For optional fields.
+     *
+     * Generated from protobuf enum <code>CARDINALITY_OPTIONAL = 1;</code>
+     */
+    const CARDINALITY_OPTIONAL = 1;
+    /**
+     * For required fields. Proto2 syntax only.
+     *
+     * Generated from protobuf enum <code>CARDINALITY_REQUIRED = 2;</code>
+     */
+    const CARDINALITY_REQUIRED = 2;
+    /**
+     * For repeated fields.
+     *
+     * Generated from protobuf enum <code>CARDINALITY_REPEATED = 3;</code>
+     */
+    const CARDINALITY_REPEATED = 3;
+}
+
+// Adding a class alias for backwards compatibility with the previous class name.
+class_alias(Cardinality::class, \Google\Protobuf\Field_Cardinality::class);
+

+ 132 - 0
php/src/Google/Protobuf/Field/Kind.php

@@ -0,0 +1,132 @@
+<?php
+# Generated by the protocol buffer compiler.  DO NOT EDIT!
+# source: google/protobuf/type.proto
+
+namespace Google\Protobuf\Field;
+
+/**
+ * Basic field types.
+ *
+ * Protobuf type <code>google.protobuf.Field.Kind</code>
+ */
+class Kind
+{
+    /**
+     * Field type unknown.
+     *
+     * Generated from protobuf enum <code>TYPE_UNKNOWN = 0;</code>
+     */
+    const TYPE_UNKNOWN = 0;
+    /**
+     * Field type double.
+     *
+     * Generated from protobuf enum <code>TYPE_DOUBLE = 1;</code>
+     */
+    const TYPE_DOUBLE = 1;
+    /**
+     * Field type float.
+     *
+     * Generated from protobuf enum <code>TYPE_FLOAT = 2;</code>
+     */
+    const TYPE_FLOAT = 2;
+    /**
+     * Field type int64.
+     *
+     * Generated from protobuf enum <code>TYPE_INT64 = 3;</code>
+     */
+    const TYPE_INT64 = 3;
+    /**
+     * Field type uint64.
+     *
+     * Generated from protobuf enum <code>TYPE_UINT64 = 4;</code>
+     */
+    const TYPE_UINT64 = 4;
+    /**
+     * Field type int32.
+     *
+     * Generated from protobuf enum <code>TYPE_INT32 = 5;</code>
+     */
+    const TYPE_INT32 = 5;
+    /**
+     * Field type fixed64.
+     *
+     * Generated from protobuf enum <code>TYPE_FIXED64 = 6;</code>
+     */
+    const TYPE_FIXED64 = 6;
+    /**
+     * Field type fixed32.
+     *
+     * Generated from protobuf enum <code>TYPE_FIXED32 = 7;</code>
+     */
+    const TYPE_FIXED32 = 7;
+    /**
+     * Field type bool.
+     *
+     * Generated from protobuf enum <code>TYPE_BOOL = 8;</code>
+     */
+    const TYPE_BOOL = 8;
+    /**
+     * Field type string.
+     *
+     * Generated from protobuf enum <code>TYPE_STRING = 9;</code>
+     */
+    const TYPE_STRING = 9;
+    /**
+     * Field type group. Proto2 syntax only, and deprecated.
+     *
+     * Generated from protobuf enum <code>TYPE_GROUP = 10;</code>
+     */
+    const TYPE_GROUP = 10;
+    /**
+     * Field type message.
+     *
+     * Generated from protobuf enum <code>TYPE_MESSAGE = 11;</code>
+     */
+    const TYPE_MESSAGE = 11;
+    /**
+     * Field type bytes.
+     *
+     * Generated from protobuf enum <code>TYPE_BYTES = 12;</code>
+     */
+    const TYPE_BYTES = 12;
+    /**
+     * Field type uint32.
+     *
+     * Generated from protobuf enum <code>TYPE_UINT32 = 13;</code>
+     */
+    const TYPE_UINT32 = 13;
+    /**
+     * Field type enum.
+     *
+     * Generated from protobuf enum <code>TYPE_ENUM = 14;</code>
+     */
+    const TYPE_ENUM = 14;
+    /**
+     * Field type sfixed32.
+     *
+     * Generated from protobuf enum <code>TYPE_SFIXED32 = 15;</code>
+     */
+    const TYPE_SFIXED32 = 15;
+    /**
+     * Field type sfixed64.
+     *
+     * Generated from protobuf enum <code>TYPE_SFIXED64 = 16;</code>
+     */
+    const TYPE_SFIXED64 = 16;
+    /**
+     * Field type sint32.
+     *
+     * Generated from protobuf enum <code>TYPE_SINT32 = 17;</code>
+     */
+    const TYPE_SINT32 = 17;
+    /**
+     * Field type sint64.
+     *
+     * Generated from protobuf enum <code>TYPE_SINT64 = 18;</code>
+     */
+    const TYPE_SINT64 = 18;
+}
+
+// Adding a class alias for backwards compatibility with the previous class name.
+class_alias(Kind::class, \Google\Protobuf\Field_Kind::class);
+

+ 16 - 2
php/src/Google/Protobuf/FieldMask.php

@@ -162,6 +162,10 @@ use Google\Protobuf\Internal\GPBUtil;
  *     }
  * Note that oneof type names ("test_oneof" in this case) cannot be used in
  * paths.
+ * ## Field Mask Verification
+ * The implementation of any API method which has a FieldMask type field in the
+ * request should verify the included field paths, and return an
+ * `INVALID_ARGUMENT` error if any path is duplicated or unmappable.
  *
  * Generated from protobuf message <code>google.protobuf.FieldMask</code>
  */
@@ -174,9 +178,19 @@ class FieldMask extends \Google\Protobuf\Internal\Message
      */
     private $paths;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string[]|\Google\Protobuf\Internal\RepeatedField $paths
+     *           The set of field mask paths.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\FieldMask::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**

+ 6 - 29
php/src/Google/Protobuf/Field_Cardinality.php

@@ -4,36 +4,13 @@
 
 namespace Google\Protobuf;
 
-/**
- * Whether a field is optional, required, or repeated.
- *
- * Protobuf enum <code>Google\Protobuf\Field\Cardinality</code>
- */
-class Field_Cardinality
-{
+if (false) {
     /**
-     * For fields with unknown cardinality.
-     *
-     * Generated from protobuf enum <code>CARDINALITY_UNKNOWN = 0;</code>
+     * This class is deprecated. Use Google\Protobuf\Field\Cardinality instead.
+     * @deprecated
      */
-    const CARDINALITY_UNKNOWN = 0;
-    /**
-     * For optional fields.
-     *
-     * Generated from protobuf enum <code>CARDINALITY_OPTIONAL = 1;</code>
-     */
-    const CARDINALITY_OPTIONAL = 1;
-    /**
-     * For required fields. Proto2 syntax only.
-     *
-     * Generated from protobuf enum <code>CARDINALITY_REQUIRED = 2;</code>
-     */
-    const CARDINALITY_REQUIRED = 2;
-    /**
-     * For repeated fields.
-     *
-     * Generated from protobuf enum <code>CARDINALITY_REPEATED = 3;</code>
-     */
-    const CARDINALITY_REPEATED = 3;
+    class Field_Cardinality {}
 }
+class_exists(Field\Cardinality::class);
+@trigger_error('Google\Protobuf\Field_Cardinality is deprecated and will be removed in the next major release. Use Google\Protobuf\Field\Cardinality instead', E_USER_DEPRECATED);
 

+ 6 - 119
php/src/Google/Protobuf/Field_Kind.php

@@ -4,126 +4,13 @@
 
 namespace Google\Protobuf;
 
-/**
- * Basic field types.
- *
- * Protobuf enum <code>Google\Protobuf\Field\Kind</code>
- */
-class Field_Kind
-{
+if (false) {
     /**
-     * Field type unknown.
-     *
-     * Generated from protobuf enum <code>TYPE_UNKNOWN = 0;</code>
+     * This class is deprecated. Use Google\Protobuf\Field\Kind instead.
+     * @deprecated
      */
-    const TYPE_UNKNOWN = 0;
-    /**
-     * Field type double.
-     *
-     * Generated from protobuf enum <code>TYPE_DOUBLE = 1;</code>
-     */
-    const TYPE_DOUBLE = 1;
-    /**
-     * Field type float.
-     *
-     * Generated from protobuf enum <code>TYPE_FLOAT = 2;</code>
-     */
-    const TYPE_FLOAT = 2;
-    /**
-     * Field type int64.
-     *
-     * Generated from protobuf enum <code>TYPE_INT64 = 3;</code>
-     */
-    const TYPE_INT64 = 3;
-    /**
-     * Field type uint64.
-     *
-     * Generated from protobuf enum <code>TYPE_UINT64 = 4;</code>
-     */
-    const TYPE_UINT64 = 4;
-    /**
-     * Field type int32.
-     *
-     * Generated from protobuf enum <code>TYPE_INT32 = 5;</code>
-     */
-    const TYPE_INT32 = 5;
-    /**
-     * Field type fixed64.
-     *
-     * Generated from protobuf enum <code>TYPE_FIXED64 = 6;</code>
-     */
-    const TYPE_FIXED64 = 6;
-    /**
-     * Field type fixed32.
-     *
-     * Generated from protobuf enum <code>TYPE_FIXED32 = 7;</code>
-     */
-    const TYPE_FIXED32 = 7;
-    /**
-     * Field type bool.
-     *
-     * Generated from protobuf enum <code>TYPE_BOOL = 8;</code>
-     */
-    const TYPE_BOOL = 8;
-    /**
-     * Field type string.
-     *
-     * Generated from protobuf enum <code>TYPE_STRING = 9;</code>
-     */
-    const TYPE_STRING = 9;
-    /**
-     * Field type group. Proto2 syntax only, and deprecated.
-     *
-     * Generated from protobuf enum <code>TYPE_GROUP = 10;</code>
-     */
-    const TYPE_GROUP = 10;
-    /**
-     * Field type message.
-     *
-     * Generated from protobuf enum <code>TYPE_MESSAGE = 11;</code>
-     */
-    const TYPE_MESSAGE = 11;
-    /**
-     * Field type bytes.
-     *
-     * Generated from protobuf enum <code>TYPE_BYTES = 12;</code>
-     */
-    const TYPE_BYTES = 12;
-    /**
-     * Field type uint32.
-     *
-     * Generated from protobuf enum <code>TYPE_UINT32 = 13;</code>
-     */
-    const TYPE_UINT32 = 13;
-    /**
-     * Field type enum.
-     *
-     * Generated from protobuf enum <code>TYPE_ENUM = 14;</code>
-     */
-    const TYPE_ENUM = 14;
-    /**
-     * Field type sfixed32.
-     *
-     * Generated from protobuf enum <code>TYPE_SFIXED32 = 15;</code>
-     */
-    const TYPE_SFIXED32 = 15;
-    /**
-     * Field type sfixed64.
-     *
-     * Generated from protobuf enum <code>TYPE_SFIXED64 = 16;</code>
-     */
-    const TYPE_SFIXED64 = 16;
-    /**
-     * Field type sint32.
-     *
-     * Generated from protobuf enum <code>TYPE_SINT32 = 17;</code>
-     */
-    const TYPE_SINT32 = 17;
-    /**
-     * Field type sint64.
-     *
-     * Generated from protobuf enum <code>TYPE_SINT64 = 18;</code>
-     */
-    const TYPE_SINT64 = 18;
+    class Field_Kind {}
 }
+class_exists(Field\Kind::class);
+@trigger_error('Google\Protobuf\Field_Kind is deprecated and will be removed in the next major release. Use Google\Protobuf\Field\Kind instead', E_USER_DEPRECATED);
 

+ 12 - 2
php/src/Google/Protobuf/FloatValue.php

@@ -23,9 +23,19 @@ class FloatValue extends \Google\Protobuf\Internal\Message
      */
     private $value = 0.0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type float $value
+     *           The float value.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Wrappers::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**

+ 10 - 2
php/src/Google/Protobuf/GPBEmpty.php

@@ -22,9 +22,17 @@ use Google\Protobuf\Internal\GPBUtil;
 class GPBEmpty extends \Google\Protobuf\Internal\Message
 {
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\GPBEmpty::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
 }

+ 12 - 2
php/src/Google/Protobuf/Int32Value.php

@@ -23,9 +23,19 @@ class Int32Value extends \Google\Protobuf\Internal\Message
      */
     private $value = 0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int $value
+     *           The int32 value.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Wrappers::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**

+ 12 - 2
php/src/Google/Protobuf/Int64Value.php

@@ -23,9 +23,19 @@ class Int64Value extends \Google\Protobuf\Internal\Message
      */
     private $value = 0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int|string $value
+     *           The int64 value.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Wrappers::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**

+ 6 - 6
php/src/Google/Protobuf/Internal/DescriptorProto.php

@@ -82,10 +82,10 @@ class DescriptorProto extends \Google\Protobuf\Internal\Message
      *     @type \Google\Protobuf\Internal\FieldDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $extension
      *     @type \Google\Protobuf\Internal\DescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $nested_type
      *     @type \Google\Protobuf\Internal\EnumDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $enum_type
-     *     @type \Google\Protobuf\Internal\DescriptorProto_ExtensionRange[]|\Google\Protobuf\Internal\RepeatedField $extension_range
+     *     @type \Google\Protobuf\Internal\DescriptorProto\ExtensionRange[]|\Google\Protobuf\Internal\RepeatedField $extension_range
      *     @type \Google\Protobuf\Internal\OneofDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $oneof_decl
      *     @type \Google\Protobuf\Internal\MessageOptions $options
-     *     @type \Google\Protobuf\Internal\DescriptorProto_ReservedRange[]|\Google\Protobuf\Internal\RepeatedField $reserved_range
+     *     @type \Google\Protobuf\Internal\DescriptorProto\ReservedRange[]|\Google\Protobuf\Internal\RepeatedField $reserved_range
      *     @type string[]|\Google\Protobuf\Internal\RepeatedField $reserved_name
      *           Reserved field names, which may not be used by fields in the same message.
      *           A given name may only be reserved once.
@@ -247,12 +247,12 @@ class DescriptorProto extends \Google\Protobuf\Internal\Message
 
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;</code>
-     * @param \Google\Protobuf\Internal\DescriptorProto_ExtensionRange[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @param \Google\Protobuf\Internal\DescriptorProto\ExtensionRange[]|\Google\Protobuf\Internal\RepeatedField $var
      * @return $this
      */
     public function setExtensionRange($var)
     {
-        $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto_ExtensionRange::class);
+        $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto\ExtensionRange::class);
         $this->extension_range = $arr;
         $this->has_extension_range = true;
 
@@ -331,12 +331,12 @@ class DescriptorProto extends \Google\Protobuf\Internal\Message
 
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;</code>
-     * @param \Google\Protobuf\Internal\DescriptorProto_ReservedRange[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @param \Google\Protobuf\Internal\DescriptorProto\ReservedRange[]|\Google\Protobuf\Internal\RepeatedField $var
      * @return $this
      */
     public function setReservedRange($var)
     {
-        $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto_ReservedRange::class);
+        $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\DescriptorProto\ReservedRange::class);
         $this->reserved_range = $arr;
         $this->has_reserved_range = true;
 

+ 5 - 2
php/src/Google/Protobuf/Internal/DescriptorProto_ExtensionRange.php → php/src/Google/Protobuf/Internal/DescriptorProto/ExtensionRange.php

@@ -2,7 +2,7 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: google/protobuf/descriptor.proto
 
-namespace Google\Protobuf\Internal;
+namespace Google\Protobuf\Internal\DescriptorProto;
 
 use Google\Protobuf\Internal\GPBType;
 use Google\Protobuf\Internal\GPBWire;
@@ -13,7 +13,7 @@ use Google\Protobuf\Internal\GPBUtil;
 /**
  * Generated from protobuf message <code>google.protobuf.DescriptorProto.ExtensionRange</code>
  */
-class DescriptorProto_ExtensionRange extends \Google\Protobuf\Internal\Message
+class ExtensionRange extends \Google\Protobuf\Internal\Message
 {
     /**
      * Generated from protobuf field <code>optional int32 start = 1;</code>
@@ -133,3 +133,6 @@ class DescriptorProto_ExtensionRange extends \Google\Protobuf\Internal\Message
 
 }
 
+// Adding a class alias for backwards compatibility with the previous class name.
+class_alias(ExtensionRange::class, \Google\Protobuf\Internal\DescriptorProto_ExtensionRange::class);
+

+ 5 - 2
php/src/Google/Protobuf/Internal/DescriptorProto_ReservedRange.php → php/src/Google/Protobuf/Internal/DescriptorProto/ReservedRange.php

@@ -2,7 +2,7 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: google/protobuf/descriptor.proto
 
-namespace Google\Protobuf\Internal;
+namespace Google\Protobuf\Internal\DescriptorProto;
 
 use Google\Protobuf\Internal\GPBType;
 use Google\Protobuf\Internal\GPBWire;
@@ -17,7 +17,7 @@ use Google\Protobuf\Internal\GPBUtil;
  *
  * Generated from protobuf message <code>google.protobuf.DescriptorProto.ReservedRange</code>
  */
-class DescriptorProto_ReservedRange extends \Google\Protobuf\Internal\Message
+class ReservedRange extends \Google\Protobuf\Internal\Message
 {
     /**
      * Inclusive.
@@ -117,3 +117,6 @@ class DescriptorProto_ReservedRange extends \Google\Protobuf\Internal\Message
 
 }
 
+// Adding a class alias for backwards compatibility with the previous class name.
+class_alias(ReservedRange::class, \Google\Protobuf\Internal\DescriptorProto_ReservedRange::class);
+

+ 3 - 3
php/src/Google/Protobuf/Internal/EnumDescriptorProto.php

@@ -59,7 +59,7 @@ class EnumDescriptorProto extends \Google\Protobuf\Internal\Message
      *     @type string $name
      *     @type \Google\Protobuf\Internal\EnumValueDescriptorProto[]|\Google\Protobuf\Internal\RepeatedField $value
      *     @type \Google\Protobuf\Internal\EnumOptions $options
-     *     @type \Google\Protobuf\Internal\EnumDescriptorProto_EnumReservedRange[]|\Google\Protobuf\Internal\RepeatedField $reserved_range
+     *     @type \Google\Protobuf\Internal\EnumDescriptorProto\EnumReservedRange[]|\Google\Protobuf\Internal\RepeatedField $reserved_range
      *           Range of reserved numeric values. Reserved numeric values may not be used
      *           by enum values in the same enum declaration. Reserved ranges may not
      *           overlap.
@@ -176,12 +176,12 @@ class EnumDescriptorProto extends \Google\Protobuf\Internal\Message
      * overlap.
      *
      * Generated from protobuf field <code>repeated .google.protobuf.EnumDescriptorProto.EnumReservedRange reserved_range = 4;</code>
-     * @param \Google\Protobuf\Internal\EnumDescriptorProto_EnumReservedRange[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @param \Google\Protobuf\Internal\EnumDescriptorProto\EnumReservedRange[]|\Google\Protobuf\Internal\RepeatedField $var
      * @return $this
      */
     public function setReservedRange($var)
     {
-        $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\EnumDescriptorProto_EnumReservedRange::class);
+        $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\EnumDescriptorProto\EnumReservedRange::class);
         $this->reserved_range = $arr;
         $this->has_reserved_range = true;
 

+ 5 - 2
php/src/Google/Protobuf/Internal/EnumDescriptorProto_EnumReservedRange.php → php/src/Google/Protobuf/Internal/EnumDescriptorProto/EnumReservedRange.php

@@ -2,7 +2,7 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: google/protobuf/descriptor.proto
 
-namespace Google\Protobuf\Internal;
+namespace Google\Protobuf\Internal\EnumDescriptorProto;
 
 use Google\Protobuf\Internal\GPBType;
 use Google\Protobuf\Internal\GPBWire;
@@ -19,7 +19,7 @@ use Google\Protobuf\Internal\GPBUtil;
  *
  * Generated from protobuf message <code>google.protobuf.EnumDescriptorProto.EnumReservedRange</code>
  */
-class EnumDescriptorProto_EnumReservedRange extends \Google\Protobuf\Internal\Message
+class EnumReservedRange extends \Google\Protobuf\Internal\Message
 {
     /**
      * Inclusive.
@@ -119,3 +119,6 @@ class EnumDescriptorProto_EnumReservedRange extends \Google\Protobuf\Internal\Me
 
 }
 
+// Adding a class alias for backwards compatibility with the previous class name.
+class_alias(EnumReservedRange::class, \Google\Protobuf\Internal\EnumDescriptorProto_EnumReservedRange::class);
+

+ 6 - 3
php/src/Google/Protobuf/Internal/FieldDescriptorProto_Label.php → php/src/Google/Protobuf/Internal/FieldDescriptorProto/Label.php

@@ -2,12 +2,12 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: google/protobuf/descriptor.proto
 
-namespace Google\Protobuf\Internal;
+namespace Google\Protobuf\Internal\FieldDescriptorProto;
 
 /**
- * Protobuf enum <code>Google\Protobuf\Internal</code>
+ * Protobuf type <code>google.protobuf.FieldDescriptorProto.Label</code>
  */
-class FieldDescriptorProto_Label
+class Label
 {
     /**
      * 0 is reserved for errors
@@ -25,3 +25,6 @@ class FieldDescriptorProto_Label
     const LABEL_REPEATED = 3;
 }
 
+// Adding a class alias for backwards compatibility with the previous class name.
+class_alias(Label::class, \Google\Protobuf\Internal\FieldDescriptorProto_Label::class);
+

+ 6 - 3
php/src/Google/Protobuf/Internal/FieldDescriptorProto_Type.php → php/src/Google/Protobuf/Internal/FieldDescriptorProto/Type.php

@@ -2,12 +2,12 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: google/protobuf/descriptor.proto
 
-namespace Google\Protobuf\Internal;
+namespace Google\Protobuf\Internal\FieldDescriptorProto;
 
 /**
- * Protobuf enum <code>Google\Protobuf\Internal</code>
+ * Protobuf type <code>google.protobuf.FieldDescriptorProto.Type</code>
  */
-class FieldDescriptorProto_Type
+class Type
 {
     /**
      * 0 is reserved for errors.
@@ -105,3 +105,6 @@ class FieldDescriptorProto_Type
     const TYPE_SINT64 = 18;
 }
 
+// Adding a class alias for backwards compatibility with the previous class name.
+class_alias(Type::class, \Google\Protobuf\Internal\FieldDescriptorProto_Type::class);
+

+ 6 - 3
php/src/Google/Protobuf/Internal/FieldOptions_CType.php → php/src/Google/Protobuf/Internal/FieldOptions/CType.php

@@ -2,12 +2,12 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: google/protobuf/descriptor.proto
 
-namespace Google\Protobuf\Internal;
+namespace Google\Protobuf\Internal\FieldOptions;
 
 /**
- * Protobuf enum <code>Google\Protobuf\Internal</code>
+ * Protobuf type <code>google.protobuf.FieldOptions.CType</code>
  */
-class FieldOptions_CType
+class CType
 {
     /**
      * Default mode.
@@ -25,3 +25,6 @@ class FieldOptions_CType
     const STRING_PIECE = 2;
 }
 
+// Adding a class alias for backwards compatibility with the previous class name.
+class_alias(CType::class, \Google\Protobuf\Internal\FieldOptions_CType::class);
+

+ 6 - 3
php/src/Google/Protobuf/Internal/FieldOptions_JSType.php → php/src/Google/Protobuf/Internal/FieldOptions/JSType.php

@@ -2,12 +2,12 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: google/protobuf/descriptor.proto
 
-namespace Google\Protobuf\Internal;
+namespace Google\Protobuf\Internal\FieldOptions;
 
 /**
- * Protobuf enum <code>Google\Protobuf\Internal</code>
+ * Protobuf type <code>google.protobuf.FieldOptions.JSType</code>
  */
-class FieldOptions_JSType
+class JSType
 {
     /**
      * Use the default type.
@@ -29,3 +29,6 @@ class FieldOptions_JSType
     const JS_NUMBER = 2;
 }
 
+// Adding a class alias for backwards compatibility with the previous class name.
+class_alias(JSType::class, \Google\Protobuf\Internal\FieldOptions_JSType::class);
+

+ 8 - 0
php/src/Google/Protobuf/Internal/FileOptions.php

@@ -278,6 +278,14 @@ class FileOptions extends \Google\Protobuf\Internal\Message
      *           Use this option to change the namespace of php generated classes. Default
      *           is empty. When this option is empty, the package name will be used for
      *           determining the namespace.
+     *     @type string $php_metadata_namespace
+     *           Use this option to change the namespace of php generated metadata classes.
+     *           Default is empty. When this option is empty, the proto file name will be used
+     *           for determining the namespace.
+     *     @type string $ruby_package
+     *           Use this option to change the package of ruby generated classes. Default
+     *           is empty. When this option is not set, the package name will be used for
+     *           determining the ruby package.
      *     @type \Google\Protobuf\Internal\UninterpretedOption[]|\Google\Protobuf\Internal\RepeatedField $uninterpreted_option
      *           The parser stores options it doesn't recognize here.
      *           See the documentation for the "Options" section above.

+ 6 - 3
php/src/Google/Protobuf/Internal/FileOptions_OptimizeMode.php → php/src/Google/Protobuf/Internal/FileOptions/OptimizeMode.php

@@ -2,14 +2,14 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: google/protobuf/descriptor.proto
 
-namespace Google\Protobuf\Internal;
+namespace Google\Protobuf\Internal\FileOptions;
 
 /**
  * Generated classes can be optimized for speed or code size.
  *
- * Protobuf enum <code>Google\Protobuf\Internal</code>
+ * Protobuf type <code>google.protobuf.FileOptions.OptimizeMode</code>
  */
-class FileOptions_OptimizeMode
+class OptimizeMode
 {
     /**
      * Generate complete code for parsing, serialization,
@@ -31,3 +31,6 @@ class FileOptions_OptimizeMode
     const LITE_RUNTIME = 3;
 }
 
+// Adding a class alias for backwards compatibility with the previous class name.
+class_alias(OptimizeMode::class, \Google\Protobuf\Internal\FileOptions_OptimizeMode::class);
+

+ 13 - 5
php/src/Google/Protobuf/Internal/GPBUtil.php

@@ -191,7 +191,7 @@ class GPBUtil
         $var = boolval($var);
     }
 
-    public static function checkMessage(&$var, $klass)
+    public static function checkMessage(&$var, $klass, $newClass = null)
     {
         if (!$var instanceof $klass && !is_null($var)) {
             throw new \Exception("Expect $klass.");
@@ -303,8 +303,11 @@ class GPBUtil
         $name,
         $file_proto)
     {
-        $classname = implode('_', explode('.', $name));
-        return static::getClassNamePrefix($classname, $file_proto) . $classname;
+        $parts = explode('.', $name);
+        foreach ($parts as $i => $part) {
+            $parts[$i] = static::getClassNamePrefix($parts[$i], $file_proto) . $parts[$i];
+        }
+        return implode('\\', $parts);
     }
 
     public static function getFullClassName(
@@ -347,9 +350,14 @@ class GPBUtil
         if ($package === "") {
             $classname = $class_name_without_package;
         } else {
+            $parts = array_map('ucwords', explode('.', $package));
+            foreach ($parts as $i => $part) {
+                $parts[$i] = self::getClassNamePrefix($part, $file_proto).$part;
+            }
             $classname =
-                implode('\\', array_map('ucwords', explode('.', $package))).
-                "\\".$class_name_without_package;
+                implode('\\', $parts) .
+                "\\".self::getClassNamePrefix($class_name_without_package,$file_proto).
+                $class_name_without_package;
         }
     }
 

+ 3 - 3
php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php

@@ -34,7 +34,7 @@ class GeneratedCodeInfo extends \Google\Protobuf\Internal\Message
      * @param array $data {
      *     Optional. Data for populating the Message object.
      *
-     *     @type \Google\Protobuf\Internal\GeneratedCodeInfo_Annotation[]|\Google\Protobuf\Internal\RepeatedField $annotation
+     *     @type \Google\Protobuf\Internal\GeneratedCodeInfo\Annotation[]|\Google\Protobuf\Internal\RepeatedField $annotation
      *           An Annotation connects some span of text in generated code to an element
      *           of its generating .proto file.
      * }
@@ -61,12 +61,12 @@ class GeneratedCodeInfo extends \Google\Protobuf\Internal\Message
      * of its generating .proto file.
      *
      * Generated from protobuf field <code>repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;</code>
-     * @param \Google\Protobuf\Internal\GeneratedCodeInfo_Annotation[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @param \Google\Protobuf\Internal\GeneratedCodeInfo\Annotation[]|\Google\Protobuf\Internal\RepeatedField $var
      * @return $this
      */
     public function setAnnotation($var)
     {
-        $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\GeneratedCodeInfo_Annotation::class);
+        $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\GeneratedCodeInfo\Annotation::class);
         $this->annotation = $arr;
         $this->has_annotation = true;
 

+ 5 - 2
php/src/Google/Protobuf/Internal/GeneratedCodeInfo_Annotation.php → php/src/Google/Protobuf/Internal/GeneratedCodeInfo/Annotation.php

@@ -2,7 +2,7 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: google/protobuf/descriptor.proto
 
-namespace Google\Protobuf\Internal;
+namespace Google\Protobuf\Internal\GeneratedCodeInfo;
 
 use Google\Protobuf\Internal\GPBType;
 use Google\Protobuf\Internal\GPBWire;
@@ -13,7 +13,7 @@ use Google\Protobuf\Internal\GPBUtil;
 /**
  * Generated from protobuf message <code>google.protobuf.GeneratedCodeInfo.Annotation</code>
  */
-class GeneratedCodeInfo_Annotation extends \Google\Protobuf\Internal\Message
+class Annotation extends \Google\Protobuf\Internal\Message
 {
     /**
      * Identifies the element in the original source .proto file. This field
@@ -211,3 +211,6 @@ class GeneratedCodeInfo_Annotation extends \Google\Protobuf\Internal\Message
 
 }
 
+// Adding a class alias for backwards compatibility with the previous class name.
+class_alias(Annotation::class, \Google\Protobuf\Internal\GeneratedCodeInfo_Annotation::class);
+

+ 6 - 3
php/src/Google/Protobuf/Internal/MethodOptions_IdempotencyLevel.php → php/src/Google/Protobuf/Internal/MethodOptions/IdempotencyLevel.php

@@ -2,16 +2,16 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: google/protobuf/descriptor.proto
 
-namespace Google\Protobuf\Internal;
+namespace Google\Protobuf\Internal\MethodOptions;
 
 /**
  * Is this method side-effect-free (or safe in HTTP parlance), or idempotent,
  * or neither? HTTP based RPC implementation may choose GET verb for safe
  * methods, and PUT verb for idempotent methods instead of the default POST.
  *
- * Protobuf enum <code>Google\Protobuf\Internal</code>
+ * Protobuf type <code>google.protobuf.MethodOptions.IdempotencyLevel</code>
  */
-class MethodOptions_IdempotencyLevel
+class IdempotencyLevel
 {
     /**
      * Generated from protobuf enum <code>IDEMPOTENCY_UNKNOWN = 0;</code>
@@ -31,3 +31,6 @@ class MethodOptions_IdempotencyLevel
     const IDEMPOTENT = 2;
 }
 
+// Adding a class alias for backwards compatibility with the previous class name.
+class_alias(IdempotencyLevel::class, \Google\Protobuf\Internal\MethodOptions_IdempotencyLevel::class);
+

+ 3 - 3
php/src/Google/Protobuf/Internal/SourceCodeInfo.php

@@ -72,7 +72,7 @@ class SourceCodeInfo extends \Google\Protobuf\Internal\Message
      * @param array $data {
      *     Optional. Data for populating the Message object.
      *
-     *     @type \Google\Protobuf\Internal\SourceCodeInfo_Location[]|\Google\Protobuf\Internal\RepeatedField $location
+     *     @type \Google\Protobuf\Internal\SourceCodeInfo\Location[]|\Google\Protobuf\Internal\RepeatedField $location
      *           A Location identifies a piece of source code in a .proto file which
      *           corresponds to a particular definition.  This information is intended
      *           to be useful to IDEs, code indexers, documentation generators, and similar
@@ -216,12 +216,12 @@ class SourceCodeInfo extends \Google\Protobuf\Internal\Message
      *   be recorded in the future.
      *
      * Generated from protobuf field <code>repeated .google.protobuf.SourceCodeInfo.Location location = 1;</code>
-     * @param \Google\Protobuf\Internal\SourceCodeInfo_Location[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @param \Google\Protobuf\Internal\SourceCodeInfo\Location[]|\Google\Protobuf\Internal\RepeatedField $var
      * @return $this
      */
     public function setLocation($var)
     {
-        $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\SourceCodeInfo_Location::class);
+        $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\SourceCodeInfo\Location::class);
         $this->location = $arr;
         $this->has_location = true;
 

+ 5 - 2
php/src/Google/Protobuf/Internal/SourceCodeInfo_Location.php → php/src/Google/Protobuf/Internal/SourceCodeInfo/Location.php

@@ -2,7 +2,7 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: google/protobuf/descriptor.proto
 
-namespace Google\Protobuf\Internal;
+namespace Google\Protobuf\Internal\SourceCodeInfo;
 
 use Google\Protobuf\Internal\GPBType;
 use Google\Protobuf\Internal\GPBWire;
@@ -13,7 +13,7 @@ use Google\Protobuf\Internal\GPBUtil;
 /**
  * Generated from protobuf message <code>google.protobuf.SourceCodeInfo.Location</code>
  */
-class SourceCodeInfo_Location extends \Google\Protobuf\Internal\Message
+class Location extends \Google\Protobuf\Internal\Message
 {
     /**
      * Identifies which part of the FileDescriptorProto was defined at this
@@ -458,3 +458,6 @@ class SourceCodeInfo_Location extends \Google\Protobuf\Internal\Message
 
 }
 
+// Adding a class alias for backwards compatibility with the previous class name.
+class_alias(Location::class, \Google\Protobuf\Internal\SourceCodeInfo_Location::class);
+

+ 3 - 3
php/src/Google/Protobuf/Internal/UninterpretedOption.php

@@ -67,7 +67,7 @@ class UninterpretedOption extends \Google\Protobuf\Internal\Message
      * @param array $data {
      *     Optional. Data for populating the Message object.
      *
-     *     @type \Google\Protobuf\Internal\UninterpretedOption_NamePart[]|\Google\Protobuf\Internal\RepeatedField $name
+     *     @type \Google\Protobuf\Internal\UninterpretedOption\NamePart[]|\Google\Protobuf\Internal\RepeatedField $name
      *     @type string $identifier_value
      *           The value of the uninterpreted option, in whatever type the tokenizer
      *           identified it as during parsing. Exactly one of these should be set.
@@ -94,12 +94,12 @@ class UninterpretedOption extends \Google\Protobuf\Internal\Message
 
     /**
      * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption.NamePart name = 2;</code>
-     * @param \Google\Protobuf\Internal\UninterpretedOption_NamePart[]|\Google\Protobuf\Internal\RepeatedField $var
+     * @param \Google\Protobuf\Internal\UninterpretedOption\NamePart[]|\Google\Protobuf\Internal\RepeatedField $var
      * @return $this
      */
     public function setName($var)
     {
-        $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption_NamePart::class);
+        $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption\NamePart::class);
         $this->name = $arr;
         $this->has_name = true;
 

+ 5 - 2
php/src/Google/Protobuf/Internal/UninterpretedOption_NamePart.php → php/src/Google/Protobuf/Internal/UninterpretedOption/NamePart.php

@@ -2,7 +2,7 @@
 # Generated by the protocol buffer compiler.  DO NOT EDIT!
 # source: google/protobuf/descriptor.proto
 
-namespace Google\Protobuf\Internal;
+namespace Google\Protobuf\Internal\UninterpretedOption;
 
 use Google\Protobuf\Internal\GPBType;
 use Google\Protobuf\Internal\GPBWire;
@@ -19,7 +19,7 @@ use Google\Protobuf\Internal\GPBUtil;
  *
  * Generated from protobuf message <code>google.protobuf.UninterpretedOption.NamePart</code>
  */
-class UninterpretedOption_NamePart extends \Google\Protobuf\Internal\Message
+class NamePart extends \Google\Protobuf\Internal\Message
 {
     /**
      * Generated from protobuf field <code>required string name_part = 1;</code>
@@ -105,3 +105,6 @@ class UninterpretedOption_NamePart extends \Google\Protobuf\Internal\Message
 
 }
 
+// Adding a class alias for backwards compatibility with the previous class name.
+class_alias(NamePart::class, \Google\Protobuf\Internal\UninterpretedOption_NamePart::class);
+

+ 12 - 2
php/src/Google/Protobuf/ListValue.php

@@ -23,9 +23,19 @@ class ListValue extends \Google\Protobuf\Internal\Message
      */
     private $values;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type \Google\Protobuf\Value[]|\Google\Protobuf\Internal\RepeatedField $values
+     *           Repeated field of dynamically typed values.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Struct::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**

+ 24 - 2
php/src/Google/Protobuf/Method.php

@@ -58,9 +58,31 @@ class Method extends \Google\Protobuf\Internal\Message
      */
     private $syntax = 0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string $name
+     *           The simple name of this method.
+     *     @type string $request_type_url
+     *           A URL of the input message type.
+     *     @type bool $request_streaming
+     *           If true, the request is streamed.
+     *     @type string $response_type_url
+     *           The URL of the output message type.
+     *     @type bool $response_streaming
+     *           If true, the response is streamed.
+     *     @type \Google\Protobuf\Option[]|\Google\Protobuf\Internal\RepeatedField $options
+     *           Any metadata attached to the method.
+     *     @type int $syntax
+     *           The source syntax of this method.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Api::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**

+ 15 - 2
php/src/Google/Protobuf/Mixin.php

@@ -90,9 +90,22 @@ class Mixin extends \Google\Protobuf\Internal\Message
      */
     private $root = '';
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string $name
+     *           The fully qualified name of the interface which is included.
+     *     @type string $root
+     *           If non-empty specifies a path under which inherited HTTP paths
+     *           are rooted.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Api::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**

+ 1 - 1
php/src/Google/Protobuf/NullValue.php

@@ -9,7 +9,7 @@ namespace Google\Protobuf;
  * `Value` type union.
  *  The JSON representation for `NullValue` is JSON `null`.
  *
- * Protobuf enum <code>Google\Protobuf\NullValue</code>
+ * Protobuf type <code>google.protobuf.NullValue</code>
  */
 class NullValue
 {

+ 20 - 2
php/src/Google/Protobuf/Option.php

@@ -35,9 +35,27 @@ class Option extends \Google\Protobuf\Internal\Message
      */
     private $value = null;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string $name
+     *           The option's name. For protobuf built-in options (options defined in
+     *           descriptor.proto), this is the short name. For example, `"map_entry"`.
+     *           For custom options, it should be the fully-qualified name. For example,
+     *           `"google.api.http"`.
+     *     @type \Google\Protobuf\Any $value
+     *           The option's value packed in an Any message. If the value is a primitive,
+     *           the corresponding wrapper type defined in google/protobuf/wrappers.proto
+     *           should be used. If the value is an enum, it should be stored as an int32
+     *           value using the google.protobuf.Int32Value type.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Type::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**

+ 13 - 2
php/src/Google/Protobuf/SourceContext.php

@@ -24,9 +24,20 @@ class SourceContext extends \Google\Protobuf\Internal\Message
      */
     private $file_name = '';
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string $file_name
+     *           The path-qualified name of the .proto file that contained the associated
+     *           protobuf element.  For example: `"google/protobuf/source_context.proto"`.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\SourceContext::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**

+ 12 - 2
php/src/Google/Protobuf/StringValue.php

@@ -23,9 +23,19 @@ class StringValue extends \Google\Protobuf\Internal\Message
      */
     private $value = '';
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string $value
+     *           The string value.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Wrappers::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**

+ 12 - 2
php/src/Google/Protobuf/Struct.php

@@ -28,9 +28,19 @@ class Struct extends \Google\Protobuf\Internal\Message
      */
     private $fields;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type array|\Google\Protobuf\Internal\MapField $fields
+     *           Unordered map of dynamically typed values.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Struct::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**

+ 1 - 1
php/src/Google/Protobuf/Syntax.php

@@ -7,7 +7,7 @@ namespace Google\Protobuf;
 /**
  * The syntax in which a protocol buffer element is defined.
  *
- * Protobuf enum <code>Google\Protobuf\Syntax</code>
+ * Protobuf type <code>google.protobuf.Syntax</code>
  */
 class Syntax
 {

+ 20 - 3
php/src/Google/Protobuf/Timestamp.php

@@ -89,9 +89,26 @@ class Timestamp extends \Google\Protobuf\Internal\Message
      */
     private $nanos = 0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int|string $seconds
+     *           Represents seconds of UTC time since Unix epoch
+     *           1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
+     *           9999-12-31T23:59:59Z inclusive.
+     *     @type int $nanos
+     *           Non-negative fractions of a second at nanosecond resolution. Negative
+     *           second values with fractions must still have non-negative nanos values
+     *           that count forward in time. Must be from 0 to 999,999,999
+     *           inclusive.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Timestamp::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**
@@ -156,7 +173,7 @@ class Timestamp extends \Google\Protobuf\Internal\Message
         return $this;
     }
 
-    /**
+    /*
      * Converts PHP DateTime to Timestamp.
      *
      * @param \DateTime $datetime

+ 22 - 2
php/src/Google/Protobuf/Type.php

@@ -52,9 +52,29 @@ class Type extends \Google\Protobuf\Internal\Message
      */
     private $syntax = 0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type string $name
+     *           The fully qualified message name.
+     *     @type \Google\Protobuf\Field[]|\Google\Protobuf\Internal\RepeatedField $fields
+     *           The list of fields.
+     *     @type string[]|\Google\Protobuf\Internal\RepeatedField $oneofs
+     *           The list of types appearing in `oneof` definitions in this type.
+     *     @type \Google\Protobuf\Option[]|\Google\Protobuf\Internal\RepeatedField $options
+     *           The protocol buffer options.
+     *     @type \Google\Protobuf\SourceContext $source_context
+     *           The source context.
+     *     @type int $syntax
+     *           The source syntax.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Type::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**

+ 12 - 2
php/src/Google/Protobuf/UInt32Value.php

@@ -23,9 +23,19 @@ class UInt32Value extends \Google\Protobuf\Internal\Message
      */
     private $value = 0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int $value
+     *           The uint32 value.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Wrappers::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**

+ 12 - 2
php/src/Google/Protobuf/UInt64Value.php

@@ -23,9 +23,19 @@ class UInt64Value extends \Google\Protobuf\Internal\Message
      */
     private $value = 0;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int|string $value
+     *           The uint64 value.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Wrappers::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**

+ 22 - 2
php/src/Google/Protobuf/Value.php

@@ -21,9 +21,29 @@ class Value extends \Google\Protobuf\Internal\Message
 {
     protected $kind;
 
-    public function __construct() {
+    /**
+     * Constructor.
+     *
+     * @param array $data {
+     *     Optional. Data for populating the Message object.
+     *
+     *     @type int $null_value
+     *           Represents a null value.
+     *     @type float $number_value
+     *           Represents a double value.
+     *     @type string $string_value
+     *           Represents a string value.
+     *     @type bool $bool_value
+     *           Represents a boolean value.
+     *     @type \Google\Protobuf\Struct $struct_value
+     *           Represents a structured value.
+     *     @type \Google\Protobuf\ListValue $list_value
+     *           Represents a repeated `Value`.
+     * }
+     */
+    public function __construct($data = NULL) {
         \GPBMetadata\Google\Protobuf\Struct::initOnce();
-        parent::__construct();
+        parent::__construct($data);
     }
 
     /**

+ 6 - 6
php/tests/array_test.php

@@ -5,7 +5,7 @@ require_once('test_util.php');
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\GPBType;
 use Foo\TestMessage;
-use Foo\TestMessage_Sub;
+use Foo\TestMessage\Sub;
 
 class RepeatedFieldTest extends PHPUnit_Framework_TestCase
 {
@@ -456,10 +456,10 @@ class RepeatedFieldTest extends PHPUnit_Framework_TestCase
 
     public function testMessage()
     {
-        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
+        $arr = new RepeatedField(GPBType::MESSAGE, Sub::class);
 
         // Test append.
-        $sub_m = new TestMessage_Sub();
+        $sub_m = new Sub();
         $sub_m->setA(1);
         $arr[] = $sub_m;
         $this->assertSame(1, $arr[0]->getA());
@@ -467,15 +467,15 @@ class RepeatedFieldTest extends PHPUnit_Framework_TestCase
         $this->assertEquals(1, count($arr));
 
         // Test set.
-        $sub_m = new TestMessage_Sub();
+        $sub_m = new Sub();
         $sub_m->setA(2);
         $arr[0] = $sub_m;
         $this->assertSame(2, $arr[0]->getA());
 
         // Test foreach.
-        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
+        $arr = new RepeatedField(GPBType::MESSAGE, Sub::class);
         for ($i = 0; $i < 3; $i++) {
-          $arr[] = new TestMessage_Sub();
+          $arr[] = new Sub();
           $arr[$i]->setA($i);
         }
         $i = 0;

+ 1 - 1
php/tests/descriptors_test.php

@@ -10,7 +10,7 @@ use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\MapField;
 use Descriptors\TestDescriptorsEnum;
 use Descriptors\TestDescriptorsMessage;
-use Descriptors\TestDescriptorsMessage_Sub;
+use Descriptors\TestDescriptorsMessage\Sub;
 
 class DescriptorsTest extends TestBase
 {

+ 3 - 3
php/tests/encode_decode_test.php

@@ -7,7 +7,7 @@ use Google\Protobuf\RepeatedField;
 use Google\Protobuf\GPBType;
 use Foo\TestEnum;
 use Foo\TestMessage;
-use Foo\TestMessage_Sub;
+use Foo\TestMessage\Sub;
 use Foo\TestPackedMessage;
 use Foo\TestRandomFieldOrder;
 use Foo\TestUnpackedMessage;
@@ -82,7 +82,7 @@ class EncodeDecodeTest extends TestBase
         $n->mergeFromString($data);
         $this->assertSame('abc', $n->getOneofString());
 
-        $sub_m = new TestMessage_Sub();
+        $sub_m = new Sub();
         $sub_m->setA(1);
         $m->setOneofMessage($sub_m);
         $data = $m->serializeToString();
@@ -105,7 +105,7 @@ class EncodeDecodeTest extends TestBase
         $this->assertSame("oneof_string", $n->getMyOneof());
         $this->assertSame("", $n->getOneofString());
 
-        $sub_m = new TestMessage_Sub();
+        $sub_m = new Sub();
         $m->setOneofMessage($sub_m);
         $data = $m->serializeToString();
         $n = new TestMessage();

+ 2 - 2
php/tests/gdb_test.sh

@@ -11,8 +11,8 @@ php -i | grep "Configuration"
 # gdb --args php -dextension=../ext/google/protobuf/modules/protobuf.so `which
 # phpunit` --bootstrap autoload.php tmp_test.php
 #
-# gdb --args php -dextension=../ext/google/protobuf/modules/protobuf.so `which phpunit` --bootstrap autoload.php encode_decode_test.php
+gdb --args php -dextension=../ext/google/protobuf/modules/protobuf.so `which phpunit` --bootstrap autoload.php generated_class_test.php
 #
-gdb --args php -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php
+# gdb --args php -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php
 #
 # USE_ZEND_ALLOC=0 valgrind --leak-check=yes php -dextension=../ext/google/protobuf/modules/protobuf.so memory_leak_test.php

+ 135 - 30
php/tests/generated_class_test.php

@@ -8,14 +8,20 @@ require_once('test_util.php');
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\MapField;
 use Google\Protobuf\Internal\GPBType;
+use Bar\TestLegacyMessage;
+use Bar\TestLegacyMessage_NestedEnum;
+use Bar\TestLegacyMessage_NestedMessage;
 use Foo\TestEnum;
 use Foo\TestIncludeNamespaceMessage;
 use Foo\TestIncludePrefixMessage;
 use Foo\TestMessage;
+use Foo\TestMessage\Sub;
 use Foo\TestMessage_Sub;
+use Foo\TestMessage\NestedEnum;
 use Foo\TestReverseFieldOrder;
 use Foo\testLowerCaseMessage;
 use Foo\testLowerCaseEnum;
+use PBEmpty\PBEcho\TestEmptyPackage;
 use Php\Test\TestNamespace;
 
 class GeneratedClassTest extends TestBase
@@ -229,11 +235,28 @@ class GeneratedClassTest extends TestBase
     }
 
     public function testNestedEnum()
+    {
+        $m = new TestMessage();
+        $m->setOptionalNestedEnum(NestedEnum::ZERO);
+    }
+
+    public function testLegacyNestedEnum()
     {
         $m = new TestMessage();
         $m->setOptionalNestedEnum(\Foo\TestMessage_NestedEnum::ZERO);
     }
 
+    public function testLegacyTypehintWithNestedEnums()
+    {
+        $this->legacyEnum(new TestLegacyMessage\NestedEnum);
+    }
+
+    private function legacyEnum(TestLegacyMessage_NestedEnum $enum)
+    {
+        // If we made it here without a PHP Fatal error, the typehint worked
+        $this->assertTrue(true);
+    }
+
     #########################################################
     # Test float field.
     #########################################################
@@ -370,6 +393,20 @@ class GeneratedClassTest extends TestBase
     {
         $m = new TestMessage();
 
+        $sub_m = new Sub();
+        $sub_m->setA(1);
+        $m->setOptionalMessage($sub_m);
+        $this->assertSame(1, $m->getOptionalMessage()->getA());
+
+        $null = null;
+        $m->setOptionalMessage($null);
+        $this->assertNull($m->getOptionalMessage());
+    }
+
+    public function testLegacyMessageField()
+    {
+        $m = new TestMessage();
+
         $sub_m = new TestMessage_Sub();
         $sub_m->setA(1);
         $m->setOptionalMessage($sub_m);
@@ -380,6 +417,17 @@ class GeneratedClassTest extends TestBase
         $this->assertNull($m->getOptionalMessage());
     }
 
+    public function testLegacyTypehintWithNestedMessages()
+    {
+        $this->legacyMessage(new TestLegacyMessage\NestedMessage);
+    }
+
+    private function legacyMessage(TestLegacyMessage_NestedMessage $sub)
+    {
+        // If we made it here without a PHP Fatal error, the typehint worked
+        $this->assertTrue(true);
+    }
+
     #########################################################
     # Test repeated field.
     #########################################################
@@ -474,7 +522,7 @@ class GeneratedClassTest extends TestBase
         $this->assertSame(NULL, $m->getOneofMessage());
         $this->assertSame("oneof_string", $m->getMyOneof());
 
-        $sub_m = new TestMessage_Sub();
+        $sub_m = new Sub();
         $sub_m->setA(1);
         $m->setOneofMessage($sub_m);
         $this->assertSame(0, $m->getOneofInt32());
@@ -513,7 +561,7 @@ class GeneratedClassTest extends TestBase
 
         // Singular
         $n->setOptionalInt32(100);
-        $sub1 = new TestMessage_Sub();
+        $sub1 = new Sub();
         $sub1->setA(101);
 
         $b = $sub1->getB();
@@ -531,7 +579,7 @@ class GeneratedClassTest extends TestBase
         $repeatedString[] = 'abc';
         $n->setRepeatedString($repeatedString);
 
-        $sub2 = new TestMessage_Sub();
+        $sub2 = new Sub();
         $sub2->setA(201);
         $repeatedMessage = $n->getRepeatedMessage();
         $repeatedMessage[] = $sub2;
@@ -548,9 +596,9 @@ class GeneratedClassTest extends TestBase
         $n->setMapStringString($mapStringString);
 
         $mapInt32Message = $n->getMapInt32Message();
-        $mapInt32Message[1] = new TestMessage_Sub();
+        $mapInt32Message[1] = new Sub();
         $mapInt32Message[1]->setA(302);
-        $mapInt32Message[2] = new TestMessage_Sub();
+        $mapInt32Message[2] = new Sub();
         $mapInt32Message[2]->setA(303);
         $n->setMapInt32Message($mapInt32Message);
 
@@ -607,7 +655,7 @@ class GeneratedClassTest extends TestBase
         $m->mergeFrom($n);
         $this->assertSame(1, $m->getOneofInt32());
 
-        $sub = new TestMessage_Sub();
+        $sub = new Sub();
         $n->setOneofMessage($sub);
         $n->getOneofMessage()->setA(400);
         $m->mergeFrom($n);
@@ -630,14 +678,15 @@ class GeneratedClassTest extends TestBase
     public function testMessageWithoutNamespace()
     {
         $m = new TestMessage();
-        $sub = new NoNameSpaceMessage();
-        $m->setOptionalNoNamespaceMessage($sub);
+        $n = new NoNameSpaceMessage();
+        $m->setOptionalNoNamespaceMessage($n);
         $repeatedNoNamespaceMessage = $m->getRepeatedNoNamespaceMessage();
         $repeatedNoNamespaceMessage[] = new NoNameSpaceMessage();
         $m->setRepeatedNoNamespaceMessage($repeatedNoNamespaceMessage);
 
-        $n = new NoNamespaceMessage();
-        $n->setB(NoNamespaceMessage_NestedEnum::ZERO);
+        // test nested messages
+        $sub = new NoNamespaceMessage\NestedMessage();
+        $n->setNestedMessage($sub);
     }
 
     public function testEnumWithoutNamespace()
@@ -650,35 +699,91 @@ class GeneratedClassTest extends TestBase
     }
 
     #########################################################
-    # Test message with given prefix.
+    # Test message with given namespace.
     #########################################################
 
-    public function testPrefixMessage()
+    public function testNestedMessagesAndEnums()
+    {
+        $m = new TestMessage();
+        $n = new TestMessage\Sub();
+        $m->setOptionalMessage($n);
+        $m->setOptionalNestedEnum(TestMessage\NestedEnum::ZERO);
+        $this->assertSame($n, $m->getOptionalMessage());
+        $this->assertSame(TestMessage\NestedEnum::ZERO, $m->getOptionalNestedEnum());
+    }
+
+    public function testMessagesAndEnumsWithPrefix()
     {
+        // Test message prefix
         $m = new TestIncludePrefixMessage();
         $n = new PrefixTestPrefix();
         $n->setA(1);
         $m->setPrefixMessage($n);
         $this->assertSame(1, $m->getPrefixMessage()->getA());
+
+        // Test nested message prefix
+        $o = new PrefixTestPrefix();
+        $p = new PrefixTestPrefix\PrefixNestedMessage();
+        $o->setNestedMessage($p);
+        $o->setNestedEnum(PrefixTestPrefix\PrefixNestedEnum::ZERO);
+        $this->assertSame($p, $o->getNestedMessage());
+        $this->assertSame(PrefixTestPrefix\PrefixNestedEnum::ZERO, $o->getNestedEnum());
     }
 
-    #########################################################
-    # Test message with given namespace.
-    #########################################################
+    public function testMessagesAndEnumsWithPhpNamespace()
+    {
+        $m = new TestNamespace();
+        $n = new TestNamespace\NestedMessage();
+        $m->setNestedMessage($n);
+        $m->setNestedEnum(TestNamespace\NestedEnum::ZERO);
+        $this->assertSame($n, $m->getNestedMessage());
+        $this->assertSame(TestNamespace\NestedEnum::ZERO, $m->getNestedEnum());
+    }
 
-    public function testNamespaceMessage()
+    public function testMesssagesAndEnumsWithEmptyPhpNamespace()
     {
-        $m = new TestIncludeNamespaceMessage();
+        $m = new TestEmptyNamespace();
+        $n = new TestEmptyNamespace\NestedMessage();
+        $m->setNestedMessage($n);
+        $m->setNestedEnum(TestEmptyNamespace\NestedEnum::ZERO);
+        $this->assertSame($n, $m->getNestedMessage());
+        $this->assertSame(TestEmptyNamespace\NestedEnum::ZERO, $m->getNestedEnum());
+    }
 
-        $n = new TestNamespace();
-        $n->setA(1);
-        $m->setNamespaceMessage($n);
-        $this->assertSame(1, $m->getNamespaceMessage()->getA());
+    public function testMessagesAndEnumsWithNoNamespace()
+    {
+        $m = new NoNamespaceMessage();
+        $n = new NoNamespaceMessage\NestedMessage();
+        $m->setNestedMessage($n);
+        $m->setNestedEnum(NoNamespaceMessage\NestedEnum::ZERO);
+        $this->assertSame($n, $m->getNestedMessage());
+        $this->assertSame(NoNamespaceMessage\NestedEnum::ZERO, $m->getNestedEnum());
+    }
 
-        $n = new TestEmptyNamespace();
-        $n->setA(1);
-        $m->setEmptyNamespaceMessage($n);
-        $this->assertSame(1, $m->getEmptyNamespaceMessage()->getA());
+    public function testReservedWordsInPackageName()
+    {
+        $m = new TestEmptyPackage();
+        $n = new TestEmptyPackage\NestedMessage();
+        $m->setNestedMessage($n);
+        $m->setNestedEnum(TestEmptyPackage\NestedEnum::ZERO);
+        $this->assertSame($n, $m->getNestedMessage());
+        $this->assertSame(TestEmptyPackage\NestedEnum::ZERO, $m->getNestedEnum());
+    }
+
+    public function testReservedWordsInNamespace()
+    {
+        $m = new TestNamespace();
+        $n = new TestNamespace\PBEmpty();
+        $o = new TestNamespace\PBEmpty\NestedMessage();
+        $n->setNestedMessage($o);
+        $n->setNestedEnum(TestNamespace\PBEmpty\NestedEnum::ZERO);
+        $m->setReservedName($n);
+        $this->assertSame($n, $m->getReservedName());
+        $this->assertSame($o, $n->getNestedMessage());
+        $this->assertSame(
+            TestNamespace\PBEmpty\NestedEnum::ZERO,
+            $n->getNestedEnum()
+        );
     }
 
     #########################################################
@@ -687,7 +792,7 @@ class GeneratedClassTest extends TestBase
 
     public function testPrefixForReservedWords()
     {
-        $m = new \Foo\TestMessage_Empty();
+        $m = new \Foo\TestMessage\PBEmpty();
         $m = new \Foo\PBEmpty();
         $m = new \PrefixEmpty();
         $m = new \Foo\PBARRAY();
@@ -1195,7 +1300,7 @@ class GeneratedClassTest extends TestBase
             'optional_string' => 'a',
             'optional_bytes' => 'b',
             'optional_enum' => TestEnum::ONE,
-            'optional_message' => new TestMessage_Sub([
+            'optional_message' => new Sub([
                 'a' => 33
             ]),
             'repeated_int32' => [-42, -52],
@@ -1214,8 +1319,8 @@ class GeneratedClassTest extends TestBase
             'repeated_string' => ['a', 'c'],
             'repeated_bytes' => ['b', 'd'],
             'repeated_enum' => [TestEnum::ZERO, TestEnum::ONE],
-            'repeated_message' => [new TestMessage_Sub(['a' => 34]),
-                                   new TestMessage_Sub(['a' => 35])],
+            'repeated_message' => [new Sub(['a' => 34]),
+                                   new Sub(['a' => 35])],
             'map_int32_int32' => [-62 => -62],
             'map_int64_int64' => [-63 => -63],
             'map_uint32_uint32' => [62 => 62],
@@ -1232,7 +1337,7 @@ class GeneratedClassTest extends TestBase
             'map_string_string' => ['e' => 'e'],
             'map_int32_bytes' => [1 => 'f'],
             'map_int32_enum' => [1 => TestEnum::ONE],
-            'map_int32_message' => [1 => new TestMessage_Sub(['a' => 36])],
+            'map_int32_message' => [1 => new Sub(['a' => 36])],
         ]);
 
         TestUtil::assertTestMessage($m);

+ 3 - 3
php/tests/generated_phpdoc_test.php

@@ -201,7 +201,7 @@ class GeneratedPhpdocTest extends TestBase
                 [
                     'setRepeatedMessage',
                 ],
-                '@param \Foo\TestMessage_Sub[]|\Google\Protobuf\Internal\RepeatedField $var'
+                '@param \Foo\TestMessage\Sub[]|\Google\Protobuf\Internal\RepeatedField $var'
             ],
             [
                 [
@@ -294,14 +294,14 @@ class GeneratedPhpdocTest extends TestBase
                     'getOptionalMessage',
                     'getOneofMessage'
                 ],
-                '@return \Foo\TestMessage_Sub'
+                '@return \Foo\TestMessage\Sub'
             ],
             [
                 [
                     'setOptionalMessage',
                     'setOneofMessage'
                 ],
-                '@param \Foo\TestMessage_Sub $var'
+                '@param \Foo\TestMessage\Sub $var'
             ],
             [
                 [

+ 5 - 5
php/tests/map_field_test.php

@@ -5,7 +5,7 @@ require_once('test_util.php');
 use Google\Protobuf\Internal\GPBType;
 use Google\Protobuf\Internal\MapField;
 use Foo\TestMessage;
-use Foo\TestMessage_Sub;
+use Foo\TestMessage\Sub;
 
 class MapFieldTest extends PHPUnit_Framework_TestCase {
 
@@ -408,10 +408,10 @@ class MapFieldTest extends PHPUnit_Framework_TestCase {
 
     public function testMessage() {
         $arr = new MapField(GPBType::INT32,
-            GPBType::MESSAGE, TestMessage_Sub::class);
+            GPBType::MESSAGE, Sub::class);
 
         // Test append.
-        $sub_m = new TestMessage_Sub();
+        $sub_m = new Sub();
         $sub_m->setA(1);
         $arr[0] = $sub_m;
         $this->assertSame(1, $arr[0]->getA());
@@ -420,9 +420,9 @@ class MapFieldTest extends PHPUnit_Framework_TestCase {
 
         // Test foreach.
         $arr = new MapField(GPBType::INT32,
-            GPBType::MESSAGE, TestMessage_Sub::class);
+            GPBType::MESSAGE, Sub::class);
         for ($i = 0; $i < 3; $i++) {
-          $arr[$i] = new TestMessage_Sub();;
+          $arr[$i] = new Sub();;
           $arr[$i]->setA($i);
         }
         $i = 0;

+ 5 - 5
php/tests/memory_leak_test.php

@@ -15,9 +15,9 @@ require_once('generated/Foo/TestEnum.php');
 require_once('generated/Foo/TestIncludeNamespaceMessage.php');
 require_once('generated/Foo/TestIncludePrefixMessage.php');
 require_once('generated/Foo/TestMessage.php');
-require_once('generated/Foo/TestMessage_Empty.php');
-require_once('generated/Foo/TestMessage_NestedEnum.php');
-require_once('generated/Foo/TestMessage_Sub.php');
+require_once('generated/Foo/TestMessage/PBEmpty.php');
+require_once('generated/Foo/TestMessage/NestedEnum.php');
+require_once('generated/Foo/TestMessage/Sub.php');
 require_once('generated/Foo/TestPackedMessage.php');
 require_once('generated/Foo/TestPhpDoc.php');
 require_once('generated/Foo/TestRandomFieldOrder.php');
@@ -37,7 +37,7 @@ require_once('test_util.php');
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\GPBType;
 use Foo\TestMessage;
-use Foo\TestMessage_Sub;
+use Foo\TestMessage\Sub;
 
 $from = new TestMessage();
 TestUtil::setTestMessage($from);
@@ -97,7 +97,7 @@ $n = new TestMessage();
 $n->mergeFromString($data);
 assert('abc' === $n->getOneofString());
 
-$sub_m = new TestMessage_Sub();
+$sub_m = new Sub();
 $sub_m->setA(1);
 $m->setOneofMessage($sub_m);
 assert(0 === $m->getOneofInt32());

+ 2 - 2
php/tests/php_implementation_test.php

@@ -5,7 +5,7 @@ require_once('test_util.php');
 
 use Foo\TestEnum;
 use Foo\TestMessage;
-use Foo\TestMessage_Sub;
+use Foo\TestMessage\Sub;
 use Foo\TestPackedMessage;
 use Google\Protobuf\Internal\CodedInputStream;
 use Google\Protobuf\Internal\FileDescriptorSet;
@@ -527,7 +527,7 @@ class ImplementationTest extends TestBase
 
     /**
      * @expectedException Exception
-     * @expectedExceptionMessage Expect message.
+     * @expectedExceptionMessage Expect Foo\TestMessage_Sub.
      */
     public function testArraysForMessagesThrowsException()
     {

+ 17 - 0
php/tests/proto/empty/echo.proto

@@ -0,0 +1,17 @@
+syntax = "proto3";
+
+package empty.echo;
+
+message TestEmptyPackage {
+  int32 a = 1;
+
+  // Test nested messages, enums, and reserved names
+  NestedMessage nested_message = 2;
+  NestedEnum nested_enum = 3;
+  message NestedMessage {
+    int32 a = 1;
+  }
+  enum NestedEnum {
+      ZERO = 0;
+  };
+}

+ 10 - 0
php/tests/proto/test_empty_php_namespace.proto

@@ -6,4 +6,14 @@ option php_metadata_namespace = "";
 
 message TestEmptyNamespace {
   int32 a = 1;
+
+  // Test nested messages, enums, and reserved names
+  NestedMessage nested_message = 2;
+  NestedEnum nested_enum = 3;
+  message NestedMessage {
+    int32 a = 1;
+  }
+  enum NestedEnum {
+      ZERO = 0;
+  };
 }

+ 11 - 0
php/tests/proto/test_include.proto

@@ -5,3 +5,14 @@ package bar;
 message TestInclude {
   int32 a = 1;
 }
+
+message TestLegacyMessage {
+  NestedMessage message = 1;
+  NestedEnum enum = 2;
+  message NestedMessage {
+    int32 a = 1;
+  }
+  enum NestedEnum {
+    ZERO = 0;
+  }
+}

+ 8 - 4
php/tests/proto/test_no_namespace.proto

@@ -5,11 +5,15 @@ option php_metadata_namespace = "\\";
 message NoNamespaceMessage {
   int32 a = 1;
 
-  enum NestedEnum {
-    ZERO = 0;
+  // Test nested messages, enums, and reserved names
+  NestedMessage nested_message = 2;
+  NestedEnum nested_enum = 3;
+  message NestedMessage {
+    int32 a = 1;
   }
-  NestedEnum b = 2;
-  repeated NestedEnum c = 3;
+  enum NestedEnum {
+      ZERO = 0;
+  };
 }
 
 enum NoNamespaceEnum {

+ 22 - 0
php/tests/proto/test_php_namespace.proto

@@ -6,4 +6,26 @@ option php_metadata_namespace = "Metadata\\Php\\Test";
 
 message TestNamespace {
   int32 a = 1;
+
+  // Test nested messages, enums, and reserved names
+  NestedMessage nested_message = 2;
+  NestedEnum nested_enum = 3;
+  Empty reserved_name = 4;
+  message NestedMessage {
+    int32 a = 1;
+  }
+  enum NestedEnum {
+      ZERO = 0;
+  };
+  // Test reserved name
+  message Empty {
+    NestedMessage nested_message = 1;
+    NestedEnum nested_enum = 2;
+    message NestedMessage {
+      int32 a = 1;
+    }
+    enum NestedEnum {
+      ZERO = 0;
+    };
+  }
 }

+ 8 - 0
php/tests/proto/test_prefix.proto

@@ -4,6 +4,14 @@ option php_class_prefix = "Prefix";
 
 message TestPrefix {
   int32 a = 1;
+  NestedMessage nested_message = 2;
+  NestedEnum nested_enum = 3;
+  message NestedMessage {
+    int32 a = 1;
+  }
+  enum NestedEnum {
+      ZERO = 0;
+  };
 }
 
 // Test prefix for reserved words.

+ 1 - 1
php/tests/test_base.php

@@ -2,7 +2,7 @@
 
 use Foo\TestMessage;
 use Foo\TestEnum;
-use Foo\TestMessage_Sub;
+use Foo\TestMessage\Sub;
 
 class TestBase extends PHPUnit_Framework_TestCase
 {

+ 9 - 9
php/tests/test_util.php

@@ -2,7 +2,7 @@
 
 use Foo\TestEnum;
 use Foo\TestMessage;
-use Foo\TestMessage_Sub;
+use Foo\TestMessage\Sub;
 use Foo\TestPackedMessage;
 use Foo\TestUnpackedMessage;
 
@@ -67,7 +67,7 @@ class TestUtil
         $m->setOptionalString('a');
         $m->setOptionalBytes('b');
         $m->setOptionalEnum(TestEnum::ONE);
-        $sub = new TestMessage_Sub();
+        $sub = new Sub();
         $m->setOptionalMessage($sub);
         $m->getOptionalMessage()->SetA(33);
 
@@ -87,7 +87,7 @@ class TestUtil
         self::appendHelper($m, 'RepeatedString',   'a');
         self::appendHelper($m, 'RepeatedBytes',    'b');
         self::appendHelper($m, 'RepeatedEnum',     TestEnum::ZERO);
-        self::appendHelper($m, 'RepeatedMessage',  new TestMessage_Sub());
+        self::appendHelper($m, 'RepeatedMessage',  new Sub());
         $m->getRepeatedMessage()[0]->setA(34);
 
         self::appendHelper($m, 'RepeatedInt32',    -52);
@@ -106,7 +106,7 @@ class TestUtil
         self::appendHelper($m, 'RepeatedString',   'c');
         self::appendHelper($m, 'RepeatedBytes',    'd');
         self::appendHelper($m, 'RepeatedEnum',     TestEnum::ONE);
-        self::appendHelper($m, 'RepeatedMessage',  new TestMessage_Sub());
+        self::appendHelper($m, 'RepeatedMessage',  new Sub());
         $m->getRepeatedMessage()[1]->SetA(35);
 
         self::kvUpdateHelper($m, 'MapInt32Int32', -62, -62);
@@ -125,13 +125,13 @@ class TestUtil
         self::kvUpdateHelper($m, 'MapStringString', 'e', 'e');
         self::kvUpdateHelper($m, 'MapInt32Bytes', 1, 'f');
         self::kvUpdateHelper($m, 'MapInt32Enum', 1, TestEnum::ONE);
-        self::kvUpdateHelper($m, 'MapInt32Message', 1, new TestMessage_Sub());
+        self::kvUpdateHelper($m, 'MapInt32Message', 1, new Sub());
         $m->getMapInt32Message()[1]->SetA(36);
     }
 
     public static function setTestMessage2(TestMessage $m)
     {
-        $sub = new TestMessage_Sub();
+        $sub = new Sub();
 
         $m->setOptionalInt32(-142);
         $m->setOptionalInt64(-143);
@@ -168,7 +168,7 @@ class TestUtil
         self::appendHelper($m, 'RepeatedString',   'aa');
         self::appendHelper($m, 'RepeatedBytes',    'bb');
         self::appendHelper($m, 'RepeatedEnum',     TestEnum::TWO);
-        self::appendHelper($m, 'RepeatedMessage',  new TestMessage_Sub());
+        self::appendHelper($m, 'RepeatedMessage',  new Sub());
         $m->getRepeatedMessage()[0]->setA(134);
 
         self::kvUpdateHelper($m, 'MapInt32Int32', -62, -162);
@@ -187,7 +187,7 @@ class TestUtil
         self::kvUpdateHelper($m, 'MapStringString', 'e', 'ee');
         self::kvUpdateHelper($m, 'MapInt32Bytes', 1, 'ff');
         self::kvUpdateHelper($m, 'MapInt32Enum', 1, TestEnum::TWO);
-        self::kvUpdateHelper($m, 'MapInt32Message', 1, new TestMessage_Sub());
+        self::kvUpdateHelper($m, 'MapInt32Message', 1, new Sub());
         $m->getMapInt32Message()[1]->SetA(136);
 
         self::kvUpdateHelper($m, 'MapInt32Int32', -162, -162);
@@ -206,7 +206,7 @@ class TestUtil
         self::kvUpdateHelper($m, 'MapStringString', 'ee', 'ee');
         self::kvUpdateHelper($m, 'MapInt32Bytes', 2, 'ff');
         self::kvUpdateHelper($m, 'MapInt32Enum', 2, TestEnum::TWO);
-        self::kvUpdateHelper($m, 'MapInt32Message', 2, new TestMessage_Sub());
+        self::kvUpdateHelper($m, 'MapInt32Message', 2, new Sub());
         $m->getMapInt32Message()[2]->SetA(136);
     }
 

+ 43 - 43
php/tests/undefined_test.php

@@ -5,7 +5,7 @@ require_once('test_util.php');
 use Google\Protobuf\Internal\RepeatedField;
 use Google\Protobuf\Internal\GPBType;
 use Foo\TestMessage;
-use Foo\TestMessage_Sub;
+use Foo\TestMessage\Sub;
 
 class UndefinedTest extends PHPUnit_Framework_TestCase
 {
@@ -35,7 +35,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
     public function testInt32AppendMessageFail()
     {
         $arr = new RepeatedField(GPBType::INT32);
-        $arr[] = new TestMessage_Sub();
+        $arr[] = new Sub();
     }
 
     /**
@@ -45,7 +45,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
     {
         $arr = new RepeatedField(GPBType::INT32);
         $arr[] = 0;
-        $arr[0] = new TestMessage_Sub();
+        $arr[0] = new Sub();
     }
 
     /**
@@ -73,7 +73,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
     public function testUint32AppendMessageFail()
     {
         $arr = new RepeatedField(GPBType::UINT32);
-        $arr[] = new TestMessage_Sub();
+        $arr[] = new Sub();
     }
 
     /**
@@ -83,7 +83,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
     {
         $arr = new RepeatedField(GPBType::UINT32);
         $arr[] = 0;
-        $arr[0] = new TestMessage_Sub();
+        $arr[0] = new Sub();
     }
 
     /**
@@ -111,7 +111,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
     public function testInt64AppendMessageFail()
     {
         $arr = new RepeatedField(GPBType::INT64);
-        $arr[] = new TestMessage_Sub();
+        $arr[] = new Sub();
     }
 
     /**
@@ -121,7 +121,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
     {
         $arr = new RepeatedField(GPBType::INT64);
         $arr[] = 0;
-        $arr[0] = new TestMessage_Sub();
+        $arr[0] = new Sub();
     }
 
     /**
@@ -149,7 +149,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
     public function testUint64AppendMessageFail()
     {
         $arr = new RepeatedField(GPBType::UINT64);
-        $arr[] = new TestMessage_Sub();
+        $arr[] = new Sub();
     }
 
     /**
@@ -159,7 +159,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
     {
         $arr = new RepeatedField(GPBType::UINT64);
         $arr[] = 0;
-        $arr[0] = new TestMessage_Sub();
+        $arr[0] = new Sub();
     }
 
     /**
@@ -187,7 +187,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
     public function testFloatAppendMessageFail()
     {
         $arr = new RepeatedField(GPBType::FLOAT);
-        $arr[] = new TestMessage_Sub();
+        $arr[] = new Sub();
     }
 
     /**
@@ -197,7 +197,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
     {
         $arr = new RepeatedField(GPBType::FLOAT);
         $arr[] = 0.0;
-        $arr[0] = new TestMessage_Sub();
+        $arr[0] = new Sub();
     }
 
     /**
@@ -225,7 +225,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
     public function testDoubleAppendMessageFail()
     {
         $arr = new RepeatedField(GPBType::DOUBLE);
-        $arr[] = new TestMessage_Sub();
+        $arr[] = new Sub();
     }
 
     /**
@@ -235,7 +235,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
     {
         $arr = new RepeatedField(GPBType::DOUBLE);
         $arr[] = 0.0;
-        $arr[0] = new TestMessage_Sub();
+        $arr[0] = new Sub();
     }
 
     /**
@@ -244,7 +244,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
     public function testBoolAppendMessageFail()
     {
         $arr = new RepeatedField(GPBType::BOOL);
-        $arr[] = new TestMessage_Sub();
+        $arr[] = new Sub();
     }
 
     /**
@@ -254,7 +254,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
     {
         $arr = new RepeatedField(GPBType::BOOL);
         $arr[] = true;
-        $arr[0] = new TestMessage_Sub();
+        $arr[0] = new Sub();
     }
 
     /**
@@ -263,7 +263,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
     public function testStringAppendMessageFail()
     {
         $arr = new RepeatedField(GPBType::STRING);
-        $arr[] = new TestMessage_Sub();
+        $arr[] = new Sub();
     }
 
     /**
@@ -273,7 +273,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
     {
         $arr = new RepeatedField(GPBType::STRING);
         $arr[] = 'abc';
-        $arr[0] = new TestMessage_Sub();
+        $arr[0] = new Sub();
     }
 
     /**
@@ -302,7 +302,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
      */
     public function testMessageAppendIntFail()
     {
-        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
+        $arr = new RepeatedField(GPBType::MESSAGE, Sub::class);
         $arr[] = 1;
     }
 
@@ -311,8 +311,8 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
      */
     public function testMessageSetIntFail()
     {
-        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
-        $arr[] = new TestMessage_Sub;
+        $arr = new RepeatedField(GPBType::MESSAGE, Sub::class);
+        $arr[] = new Sub;
         $arr[0] = 'abc';
     }
 
@@ -321,7 +321,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
      */
     public function testMessageAppendStringFail()
     {
-        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
+        $arr = new RepeatedField(GPBType::MESSAGE, Sub::class);
         $arr[] = 'abc';
     }
 
@@ -330,8 +330,8 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
      */
     public function testMessageSetStringFail()
     {
-        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
-        $arr[] = new TestMessage_Sub;
+        $arr = new RepeatedField(GPBType::MESSAGE, Sub::class);
+        $arr[] = new Sub;
         $arr[0] = 'abc';
     }
 
@@ -340,7 +340,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
      */
     public function testMessageAppendOtherMessageFail()
     {
-        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
+        $arr = new RepeatedField(GPBType::MESSAGE, Sub::class);
         $arr[] = new TestMessage;
     }
 
@@ -349,7 +349,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
      */
     public function testMessageAppendNullFail()
     {
-        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
+        $arr = new RepeatedField(GPBType::MESSAGE, Sub::class);
         $null = null;
         $arr[] = $null;
     }
@@ -359,8 +359,8 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
      */
     public function testMessageSetNullFail()
     {
-        $arr = new RepeatedField(GPBType::MESSAGE, TestMessage_Sub::class);
-        $arr[] = new TestMessage_Sub();
+        $arr = new RepeatedField(GPBType::MESSAGE, Sub::class);
+        $arr[] = new Sub();
         $null = null;
         $arr[0] = $null;
     }
@@ -397,7 +397,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
     {
         $arr = new RepeatedField(GPBType::INT32);
         $arr[] = 0;
-        $arr[new TestMessage_Sub()] = 0;
+        $arr[new Sub()] = 0;
     }
 
     /**
@@ -656,7 +656,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
     public function testMessageMergeFromInvalidTypeFail()
     {
         $m = new TestMessage();
-        $n = new TestMessage_Sub();
+        $n = new Sub();
         $m->mergeFrom($n);
     }
 
@@ -684,7 +684,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
     public function testInt32SetMessageKeyFail()
     {
         $arr = new MapField(GPBType::INT32, GPBType::INT32);
-        $arr[new TestMessage_Sub()] = 0;
+        $arr[new Sub()] = 0;
     }
 
     /**
@@ -693,7 +693,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
     public function testInt32SetMessageValueFail()
     {
         $arr = new MapField(GPBType::INT32, GPBType::INT32);
-        $arr[0] = new TestMessage_Sub();
+        $arr[0] = new Sub();
     }
 
     /**
@@ -720,7 +720,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
     public function testUint32SetMessageKeyFail()
     {
         $arr = new MapField(GPBType::UINT32, GPBType::UINT32);
-        $arr[new TestMessage_Sub()] = 0;
+        $arr[new Sub()] = 0;
     }
 
     /**
@@ -729,7 +729,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
     public function testUint32SetMessageValueFail()
     {
         $arr = new MapField(GPBType::UINT32, GPBType::UINT32);
-        $arr[0] = new TestMessage_Sub();
+        $arr[0] = new Sub();
     }
 
     /**
@@ -756,7 +756,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
     public function testInt64SetMessageKeyFail()
     {
         $arr = new MapField(GPBType::INT64, GPBType::INT64);
-        $arr[new TestMessage_Sub()] = 0;
+        $arr[new Sub()] = 0;
     }
 
     /**
@@ -765,7 +765,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
     public function testInt64SetMessageValueFail()
     {
         $arr = new MapField(GPBType::INT64, GPBType::INT64);
-        $arr[0] = new TestMessage_Sub();
+        $arr[0] = new Sub();
     }
 
     /**
@@ -792,7 +792,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
     public function testUint64SetMessageKeyFail()
     {
         $arr = new MapField(GPBType::UINT64, GPBType::UINT64);
-        $arr[new TestMessage_Sub()] = 0;
+        $arr[new Sub()] = 0;
     }
 
     /**
@@ -801,7 +801,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
     public function testUint64SetMessageValueFail()
     {
         $arr = new MapField(GPBType::UINT64, GPBType::UINT64);
-        $arr[0] = new TestMessage_Sub();
+        $arr[0] = new Sub();
     }
 
     /**
@@ -819,7 +819,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
     public function testDoubleSetMessageValueFail()
     {
         $arr = new MapField(GPBType::INT64, GPBType::DOUBLE);
-        $arr[0] = new TestMessage_Sub();
+        $arr[0] = new Sub();
     }
 
     /**
@@ -828,7 +828,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
     public function testBoolSetMessageKeyFail()
     {
         $arr = new MapField(GPBType::BOOL, GPBType::BOOL);
-        $arr[new TestMessage_Sub()] = true;
+        $arr[new Sub()] = true;
     }
 
     /**
@@ -837,7 +837,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
     public function testBoolSetMessageValueFail()
     {
         $arr = new MapField(GPBType::BOOL, GPBType::BOOL);
-        $arr[true] = new TestMessage_Sub();
+        $arr[true] = new Sub();
     }
 
     /**
@@ -864,7 +864,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
     public function testStringSetMessageKeyFail()
     {
         $arr = new MapField(GPBType::STRING, GPBType::STRING);
-        $arr[new TestMessage_Sub()] = 'abc';
+        $arr[new Sub()] = 'abc';
     }
 
     /**
@@ -873,7 +873,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
     public function testStringSetMessageValueFail()
     {
         $arr = new MapField(GPBType::STRING, GPBType::STRING);
-        $arr['abc'] = new TestMessage_Sub();
+        $arr['abc'] = new Sub();
     }
 
     /**
@@ -903,7 +903,7 @@ class UndefinedTest extends PHPUnit_Framework_TestCase
     {
        $arr =
            new MapField(GPBType::INT32, GPBType::MESSAGE, TestMessage::class);
-       $arr[0] = new TestMessage_Sub();
+       $arr[0] = new Sub();
     }
 
     /**

+ 6 - 6
php/tests/well_known_test.php

@@ -14,8 +14,8 @@ use Google\Protobuf\Enum;
 use Google\Protobuf\EnumValue;
 use Google\Protobuf\Field;
 use Google\Protobuf\FieldMask;
-use Google\Protobuf\Field_Cardinality;
-use Google\Protobuf\Field_Kind;
+use Google\Protobuf\Field\Cardinality;
+use Google\Protobuf\Field\Kind;
 use Google\Protobuf\FloatValue;
 use Google\Protobuf\GPBEmpty;
 use Google\Protobuf\Int32Value;
@@ -206,11 +206,11 @@ class WellKnownTest extends TestBase {
     {
         $m = new Field();
 
-        $m->setKind(Field_Kind::TYPE_DOUBLE);
-        $this->assertSame(Field_Kind::TYPE_DOUBLE, $m->getKind());
+        $m->setKind(Kind::TYPE_DOUBLE);
+        $this->assertSame(Kind::TYPE_DOUBLE, $m->getKind());
 
-        $m->setCardinality(Field_Cardinality::CARDINALITY_OPTIONAL);
-        $this->assertSame(Field_Cardinality::CARDINALITY_OPTIONAL, $m->getCardinality());
+        $m->setCardinality(Cardinality::CARDINALITY_OPTIONAL);
+        $this->assertSame(Cardinality::CARDINALITY_OPTIONAL, $m->getCardinality());
 
         $m->setNumber(1);
         $this->assertSame(1, $m->getNumber());

+ 187 - 135
src/google/protobuf/compiler/php/php_generator.cc

@@ -108,31 +108,40 @@ void GenerateServiceDocComment(io::Printer* printer,
 void GenerateServiceMethodDocComment(io::Printer* printer,
                               const MethodDescriptor* method);
 
-std::string RenameEmpty(const std::string& name) {
-  if (name == "Empty") {
-    return "GPBEmpty";
-  } else {
-    return name;
+
+std::string ReservedNamePrefix(const string& classname,
+                                const FileDescriptor* file) {
+  bool is_reserved = false;
+
+  string lower = classname;
+  transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
+
+  for (int i = 0; i < kReservedNamesSize; i++) {
+    if (lower == kReservedNames[i]) {
+      is_reserved = true;
+      break;
+    }
   }
-}
 
-std::string MessageFullName(const Descriptor* message, bool is_descriptor) {
-  if (is_descriptor) {
-    return StringReplace(message->full_name(),
-                         "google.protobuf",
-                         "google.protobuf.internal", false);
-  } else {
-    return message->full_name();
+  if (is_reserved) {
+    if (file->package() == "google.protobuf") {
+      return "GPB";
+    } else {
+      return "PB";
+    }
   }
+
+  return "";
 }
 
-std::string EnumFullName(const EnumDescriptor* envm, bool is_descriptor) {
+template <typename DescriptorType>
+std::string DescriptorFullName(const DescriptorType* desc, bool is_descriptor) {
   if (is_descriptor) {
-    return StringReplace(envm->full_name(),
+    return StringReplace(desc->full_name(),
                          "google.protobuf",
                          "google.protobuf.internal", false);
   } else {
-    return envm->full_name();
+    return desc->full_name();
   }
 }
 
@@ -144,22 +153,43 @@ std::string ClassNamePrefix(const string& classname,
     return prefix;
   }
 
-  bool is_reserved = false;
+  return ReservedNamePrefix(classname, desc->file());
+}
+
+template <typename DescriptorType>
+std::string GeneratedClassName(const DescriptorType* desc) {
+  std::string classname = ClassNamePrefix(desc->name(), desc) + desc->name();
+  const Descriptor* containing = desc->containing_type();
+  while (containing != NULL) {
+    classname = ClassNamePrefix(containing->name(), desc) + containing->name()
+       + '\\' + classname;
+    containing = containing->containing_type();
+  }
+  return classname;
+}
+
+std::string GeneratedClassName(const ServiceDescriptor* desc) {
+  std::string classname = desc->name();
+  return ClassNamePrefix(classname, desc) + classname;
+}
 
+template <typename DescriptorType>
+std::string LegacyGeneratedClassName(const DescriptorType* desc) {
+  std::string classname = desc->name();
+  const Descriptor* containing = desc->containing_type();
+  while (containing != NULL) {
+    classname = containing->name() + '_' + classname;
+    containing = containing->containing_type();
+  }
+  return ClassNamePrefix(classname, desc) + classname;
+}
+
+std::string ClassNamePrefix(const string& classname) {
   string lower = classname;
   transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
 
   for (int i = 0; i < kReservedNamesSize; i++) {
     if (lower == kReservedNames[i]) {
-      is_reserved = true;
-      break;
-    }
-  }
-
-  if (is_reserved) {
-    if (desc->file()->package() == "google.protobuf") {
-      return "GPB";
-    } else {
       return "PB";
     }
   }
@@ -195,34 +225,39 @@ std::string ConstantNamePrefix(const string& classname) {
 }
 
 template <typename DescriptorType>
-std::string NamespacedName(const string& classname,
-                            const DescriptorType* desc, bool is_descriptor) {
+std::string RootPhpNamespace(const DescriptorType* desc, bool is_descriptor) {
   if (desc->file()->options().has_php_namespace()) {
     const string& php_namespace = desc->file()->options().php_namespace();
     if (php_namespace != "") {
-      return php_namespace + '\\' + classname;
-    } else {
-      return classname;
+      return php_namespace;
     }
+    return "";
   }
 
-  if (desc->file()->package() == "") {
-    return classname;
-  } else {
-    return PhpName(desc->file()->package(), is_descriptor) + '\\' +
-           classname;
+  if (desc->file()->package() != "") {
+    return PhpName(desc->file()->package(), is_descriptor);
   }
+  return "";
 }
 
 template <typename DescriptorType>
 std::string FullClassName(const DescriptorType* desc, bool is_descriptor) {
   string classname = GeneratedClassName(desc);
-  return NamespacedName(classname, desc, is_descriptor);
+  string php_namespace = RootPhpNamespace(desc, is_descriptor);
+  if (php_namespace != "") {
+    return php_namespace + "\\" + classname;
+  }
+  return classname;
 }
 
-std::string FullClassName(const ServiceDescriptor* desc, bool is_descriptor) {
-  string classname = GeneratedClassName(desc);
-  return NamespacedName(classname, desc, is_descriptor);
+template <typename DescriptorType>
+std::string LegacyFullClassName(const DescriptorType* desc, bool is_descriptor) {
+  string classname = LegacyGeneratedClassName(desc);
+  string php_namespace = RootPhpNamespace(desc, is_descriptor);
+  if (php_namespace != "") {
+    return php_namespace + "\\" + classname;
+  }
+  return classname;
 }
 
 std::string PhpName(const std::string& full_name, bool is_descriptor) {
@@ -230,20 +265,23 @@ std::string PhpName(const std::string& full_name, bool is_descriptor) {
     return kDescriptorPackageName;
   }
 
+  std::string segment;
   std::string result;
   bool cap_next_letter = true;
   for (int i = 0; i < full_name.size(); i++) {
     if ('a' <= full_name[i] && full_name[i] <= 'z' && cap_next_letter) {
-      result += full_name[i] + ('A' - 'a');
+      segment += full_name[i] + ('A' - 'a');
       cap_next_letter = false;
     } else if (full_name[i] == '.') {
-      result += '\\';
+      result += ClassNamePrefix(segment) + segment + '\\';
+      segment = "";
       cap_next_letter = true;
     } else {
-      result += full_name[i];
+      segment += full_name[i];
       cap_next_letter = false;
     }
   }
+  result += ClassNamePrefix(segment) + segment;
   return result;
 }
 
@@ -277,6 +315,7 @@ std::string GeneratedMetadataFileName(const FileDescriptor* file,
   int start_index = 0;
   int first_index = proto_file.find_first_of("/", start_index);
   std::string result = "";
+  std::string segment = "";
 
   if (proto_file == kEmptyFile) {
     return kEmptyMetadataFile;
@@ -307,9 +346,9 @@ std::string GeneratedMetadataFileName(const FileDescriptor* file,
   } else {
     result += "GPBMetadata/";
     while (first_index != string::npos) {
-      result += UnderscoresToCamelCase(
+      segment = UnderscoresToCamelCase(
           file_no_suffix.substr(start_index, first_index - start_index), true);
-      result += "/";
+      result += ReservedNamePrefix(segment, file) + segment + "/";
       start_index = first_index + 1;
       first_index = file_no_suffix.find_first_of("/", start_index);
     }
@@ -322,15 +361,16 @@ std::string GeneratedMetadataFileName(const FileDescriptor* file,
   } else {
     file_name_start += 1;
   }
-  result += RenameEmpty(UnderscoresToCamelCase(
-      file_no_suffix.substr(file_name_start, first_index - file_name_start), true));
+  segment = UnderscoresToCamelCase(
+      file_no_suffix.substr(file_name_start, first_index - file_name_start), true);
 
-  return result += ".php";
+  return result + ReservedNamePrefix(segment, file) + segment + ".php";
 }
 
-std::string GeneratedMessageFileName(const Descriptor* message,
+template <typename DescriptorType>
+std::string GeneratedClassFileName(const DescriptorType* desc,
                                      bool is_descriptor) {
-  std::string result = FullClassName(message, is_descriptor);
+  std::string result = FullClassName(desc, is_descriptor);
   for (int i = 0; i < result.size(); i++) {
     if (result[i] == '\\') {
       result[i] = '/';
@@ -339,9 +379,11 @@ std::string GeneratedMessageFileName(const Descriptor* message,
   return result + ".php";
 }
 
-std::string GeneratedEnumFileName(const EnumDescriptor* en,
-                                  bool is_descriptor) {
-  std::string result = FullClassName(en, is_descriptor);
+template <typename DescriptorType>
+std::string LegacyGeneratedClassFileName(const DescriptorType* desc,
+                                     bool is_descriptor) {
+  std::string result = LegacyFullClassName(desc, is_descriptor);
+
   for (int i = 0; i < result.size(); i++) {
     if (result[i] == '\\') {
       result[i] = '/';
@@ -484,10 +526,10 @@ std::string PhpGetterTypeName(const FieldDescriptor* field, bool is_descriptor)
 std::string EnumOrMessageSuffix(
     const FieldDescriptor* field, bool is_descriptor) {
   if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
-    return ", '" + MessageFullName(field->message_type(), is_descriptor) + "'";
+    return ", '" + DescriptorFullName(field->message_type(), is_descriptor) + "'";
   }
   if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
-    return ", '" + EnumFullName(field->enum_type(), is_descriptor) + "'";
+    return ", '" + DescriptorFullName(field->enum_type(), is_descriptor) + "'";
   }
   return "";
 }
@@ -674,11 +716,11 @@ void GenerateFieldAccessor(const FieldDescriptor* field, bool is_descriptor,
   } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
     printer->Print(
         "GPBUtil::checkMessage($var, \\^class_name^::class);\n",
-        "class_name", FullClassName(field->message_type(), is_descriptor));
+        "class_name", LegacyFullClassName(field->message_type(), is_descriptor));
   } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
     printer->Print(
         "GPBUtil::checkEnum($var, \\^class_name^::class);\n",
-        "class_name", FullClassName(field->enum_type(), is_descriptor));
+        "class_name", LegacyFullClassName(field->enum_type(), is_descriptor));
   } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
     printer->Print(
         "GPBUtil::checkString($var, ^utf8^);\n",
@@ -734,7 +776,7 @@ void GenerateEnumToPool(const EnumDescriptor* en, io::Printer* printer) {
   printer->Print(
       "$pool->addEnum('^name^', "
       "\\Google\\Protobuf\\Internal\\^class_name^::class)\n",
-      "name", EnumFullName(en, true),
+      "name", DescriptorFullName(en, true),
       "class_name", en->name());
   Indent(printer);
 
@@ -766,13 +808,13 @@ void GenerateMessageToPool(const string& name_prefix, const Descriptor* message,
   if (message->options().map_entry()) {
     return;
   }
-  string class_name = name_prefix.empty()?
-      message->name() : name_prefix + "_" + message->name();
+  string class_name = (name_prefix.empty() ? "" : name_prefix + "\\") +
+    ReservedNamePrefix(message->name(), message->file()) + message->name();
 
   printer->Print(
       "$pool->addMessage('^message^', "
       "\\Google\\Protobuf\\Internal\\^class_name^::class)\n",
-      "message", MessageFullName(message, true),
+      "message", DescriptorFullName(message, true),
       "class_name", class_name);
 
   Indent(printer);
@@ -1001,9 +1043,47 @@ void GenerateMetadataFile(const FileDescriptor* file,
   printer.Print("}\n\n");
 }
 
+template <typename DescriptorType>
+void LegacyGenerateClassFile(const FileDescriptor* file, const DescriptorType* desc,
+                         bool is_descriptor,
+                         GeneratorContext* generator_context) {
+
+  std::string filename = LegacyGeneratedClassFileName(desc, is_descriptor);
+  std::unique_ptr<io::ZeroCopyOutputStream> output(
+      generator_context->Open(filename));
+  io::Printer printer(output.get(), '^');
+
+  GenerateHead(file, &printer);
+
+  std::string php_namespace = RootPhpNamespace(desc, is_descriptor);
+  if (php_namespace != "") {
+    printer.Print(
+        "namespace ^name^;\n\n",
+        "name", php_namespace);
+  }
+  std::string newname = FullClassName(desc, is_descriptor);
+  printer.Print("if (false) {\n");
+  Indent(&printer);
+  printer.Print("/**\n");
+  printer.Print(" * This class is deprecated. Use ^new^ instead.\n",
+      "new", newname);
+  printer.Print(" * @deprecated\n");
+  printer.Print(" */\n");
+  printer.Print("class ^old^ {}\n",
+      "old", LegacyGeneratedClassName(desc));
+  Outdent(&printer);
+  printer.Print("}\n");
+  printer.Print("class_exists(^new^::class);\n",
+      "new", GeneratedClassName(desc));
+  printer.Print("@trigger_error('^old^ is deprecated and will be removed in "
+      "the next major release. Use ^fullname^ instead', E_USER_DEPRECATED);\n\n",
+      "old", LegacyFullClassName(desc, is_descriptor),
+      "fullname", newname);
+}
+
 void GenerateEnumFile(const FileDescriptor* file, const EnumDescriptor* en,
                       bool is_descriptor, GeneratorContext* generator_context) {
-  std::string filename = GeneratedEnumFileName(en, is_descriptor);
+  std::string filename = GeneratedClassFileName(en, is_descriptor);
   std::unique_ptr<io::ZeroCopyOutputStream> output(
       generator_context->Open(filename));
   io::Printer printer(output.get(), '^');
@@ -1013,32 +1093,22 @@ void GenerateEnumFile(const FileDescriptor* file, const EnumDescriptor* en,
   std::string fullname = FilenameToClassname(filename);
   int lastindex = fullname.find_last_of("\\");
 
-  if (file->options().has_php_namespace()) {
-    const string& php_namespace = file->options().php_namespace();
-    if (!php_namespace.empty()) {
-      printer.Print(
-          "namespace ^name^;\n\n",
-          "name", php_namespace);
-    }
-  } else if (!file->package().empty()) {
+  if (lastindex != string::npos) {
     printer.Print(
         "namespace ^name^;\n\n",
         "name", fullname.substr(0, lastindex));
   }
 
-  GenerateEnumDocComment(&printer, en, is_descriptor);
-
   if (lastindex != string::npos) {
-    printer.Print(
-        "class ^name^\n"
-        "{\n",
-        "name", fullname.substr(lastindex + 1));
-  } else {
-    printer.Print(
-        "class ^name^\n"
-        "{\n",
-        "name", fullname);
+    fullname = fullname.substr(lastindex + 1);
   }
+
+  GenerateEnumDocComment(&printer, en, is_descriptor);
+
+  printer.Print(
+      "class ^name^\n"
+      "{\n",
+      "name", fullname);
   Indent(&printer);
 
   for (int i = 0; i < en->value_count(); i++) {
@@ -1051,6 +1121,17 @@ void GenerateEnumFile(const FileDescriptor* file, const EnumDescriptor* en,
 
   Outdent(&printer);
   printer.Print("}\n\n");
+
+  // write legacy file for backwards compatiblity with nested messages and enums
+  if (en->containing_type() != NULL) {
+    printer.Print(
+        "// Adding a class alias for backwards compatibility with the previous class name.\n");
+    printer.Print(
+        "class_alias(^new^::class, \\^old^::class);\n\n",
+        "new", fullname,
+        "old", LegacyFullClassName(en, is_descriptor));
+    LegacyGenerateClassFile(file, en, is_descriptor, generator_context);
+  }
 }
 
 void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message,
@@ -1062,7 +1143,7 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message,
     return;
   }
 
-  std::string filename = GeneratedMessageFileName(message, is_descriptor);
+  std::string filename = GeneratedClassFileName(message, is_descriptor);
   std::unique_ptr<io::ZeroCopyOutputStream> output(
       generator_context->Open(filename));
   io::Printer printer(output.get(), '^');
@@ -1072,14 +1153,7 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message,
   std::string fullname = FilenameToClassname(filename);
   int lastindex = fullname.find_last_of("\\");
 
-  if (file->options().has_php_namespace()) {
-    const string& php_namespace = file->options().php_namespace();
-    if (!php_namespace.empty()) {
-      printer.Print(
-          "namespace ^name^;\n\n",
-          "name", php_namespace);
-    }
-  } else if (!file->package().empty()) {
+  if (lastindex != string::npos) {
     printer.Print(
         "namespace ^name^;\n\n",
         "name", fullname.substr(0, lastindex));
@@ -1089,16 +1163,13 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message,
 
   GenerateMessageDocComment(&printer, message, is_descriptor);
   if (lastindex != string::npos) {
-    printer.Print(
-        "class ^name^ extends \\Google\\Protobuf\\Internal\\Message\n"
-        "{\n",
-        "name", fullname.substr(lastindex + 1));
-  } else {
-    printer.Print(
-        "class ^name^ extends \\Google\\Protobuf\\Internal\\Message\n"
-        "{\n",
-        "name", fullname);
+    fullname = fullname.substr(lastindex + 1);
   }
+
+  printer.Print(
+      "class ^name^ extends \\Google\\Protobuf\\Internal\\Message\n"
+      "{\n",
+      "name", fullname);
   Indent(&printer);
 
   // Field and oneof definitions.
@@ -1150,6 +1221,17 @@ void GenerateMessageFile(const FileDescriptor* file, const Descriptor* message,
   Outdent(&printer);
   printer.Print("}\n\n");
 
+  // write legacy file for backwards compatiblity with nested messages and enums
+  if (message->containing_type() != NULL) {
+    printer.Print(
+        "// Adding a class alias for backwards compatibility with the previous class name.\n");
+    printer.Print(
+        "class_alias(^new^::class, \\^old^::class);\n\n",
+        "new", fullname,
+        "old", LegacyFullClassName(message, is_descriptor));
+    LegacyGenerateClassFile(file, message, is_descriptor, generator_context);
+  }
+
   // Nested messages and enums.
   for (int i = 0; i < message->nested_type_count(); i++) {
     GenerateMessageFile(file, message->nested_type(i), is_descriptor,
@@ -1174,14 +1256,9 @@ void GenerateServiceFile(const FileDescriptor* file,
   std::string fullname = FilenameToClassname(filename);
   int lastindex = fullname.find_last_of("\\");
 
-  if (file->options().has_php_namespace()) {
-    const string& php_namespace = file->options().php_namespace();
-    if (!php_namespace.empty()) {
-      printer.Print(
-          "namespace ^name^;\n\n",
-          "name", php_namespace);
-    }
-  } else if (!file->package().empty()) {
+  if (!file->options().php_namespace().empty() ||
+      (!file->options().has_php_namespace() && !file->package().empty()) ||
+      lastindex != string::npos) {
     printer.Print(
         "namespace ^name^;\n\n",
         "name", fullname.substr(0, lastindex));
@@ -1337,7 +1414,7 @@ void GenerateMessageDocComment(io::Printer* printer,
   printer->Print(
     " * Generated from protobuf message <code>^messagename^</code>\n"
     " */\n",
-    "fullname", EscapePhpdoc(PhpName(message->full_name(), is_descriptor)),
+    "fullname", EscapePhpdoc(FullClassName(message, is_descriptor)),
     "messagename", EscapePhpdoc(message->full_name()));
 }
 
@@ -1413,9 +1490,9 @@ void GenerateEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_,
   printer->Print("/**\n");
   GenerateDocCommentBody(printer, enum_);
   printer->Print(
-    " * Protobuf enum <code>^fullname^</code>\n"
+    " * Protobuf type <code>^fullname^</code>\n"
     " */\n",
-    "fullname", EscapePhpdoc(PhpName(enum_->full_name(), is_descriptor)));
+    "fullname", EscapePhpdoc(enum_->full_name()));
 }
 
 void GenerateEnumValueDocComment(io::Printer* printer,
@@ -1468,31 +1545,6 @@ bool Generator::Generate(const FileDescriptor* file, const string& parameter,
   return true;
 }
 
-std::string GeneratedClassName(const Descriptor* desc) {
-  std::string classname = desc->name();
-  const Descriptor* containing = desc->containing_type();
-  while (containing != NULL) {
-    classname = containing->name() + '_' + classname;
-    containing = containing->containing_type();
-  }
-  return ClassNamePrefix(classname, desc) + classname;
-}
-
-std::string GeneratedClassName(const EnumDescriptor* desc) {
-  std::string classname = desc->name();
-  const Descriptor* containing = desc->containing_type();
-  while (containing != NULL) {
-    classname = containing->name() + '_' + classname;
-    containing = containing->containing_type();
-  }
-  return ClassNamePrefix(classname, desc) + classname;
-}
-
-std::string GeneratedClassName(const ServiceDescriptor* desc) {
-  std::string classname = desc->name();
-  return ClassNamePrefix(classname, desc) + classname;
-}
-
 }  // namespace php
 }  // namespace compiler
 }  // namespace protobuf

+ 0 - 10
src/google/protobuf/compiler/php/php_generator.h

@@ -51,16 +51,6 @@ class LIBPROTOC_EXPORT Generator
 
 };
 
-// To skip reserved keywords in php, some generated classname are prefixed.
-// Other code generators may need following API to figure out the actual
-// classname.
-LIBPROTOC_EXPORT std::string GeneratedClassName(
-    const google::protobuf::Descriptor* desc);
-LIBPROTOC_EXPORT std::string GeneratedClassName(
-    const google::protobuf::EnumDescriptor* desc);
-LIBPROTOC_EXPORT std::string GeneratedClassName(
-    const google::protobuf::ServiceDescriptor* desc);
-
 }  // namespace php
 }  // namespace compiler
 }  // namespace protobuf

+ 2 - 1
tests.sh

@@ -107,7 +107,7 @@ build_csharp() {
   # Check that the protos haven't broken C# codegen.
   # TODO(jonskeet): Fail if regenerating creates any changes.
   csharp/generate_protos.sh
-  
+
   csharp/buildall.sh
   cd conformance && make test_csharp && cd ..
 
@@ -352,6 +352,7 @@ generate_php_test_proto() {
   rm -rf generated
   mkdir generated
   ../../src/protoc --php_out=generated         \
+    proto/empty/echo.proto                     \
     proto/test.proto                           \
     proto/test_include.proto                   \
     proto/test_no_namespace.proto              \