浏览代码

Update PHP descriptors (#3391)

* Add descriptors test

* Update descriptors tests

* Add public descriptors

* Add test_desriptors.proto to test script

* Update composer files

* Remove references to GPBType, update tests to be compatible with c

* Update for c extension compatibility

* Remove nested enums for descriptor, update tests

* Strip leading '.' from descriptor name

* Update tests with test for getClass, fix OneofDescriptor

* Add new files to Makefile.am
michaelbausor 8 年之前
父节点
当前提交
21b0e5587c

+ 8 - 1
Makefile.am

@@ -597,6 +597,12 @@ php_EXTRA_DIST=                                                       \
   php/ext/google/protobuf/upb.c                                       \
   php/ext/google/protobuf/protobuf.c                                  \
   php/src/phpdoc.dist.xml                                             \
+  php/src/Google/Protobuf/Descriptor.php                              \
+  php/src/Google/Protobuf/DescriptorPool.php                          \
+  php/src/Google/Protobuf/EnumDescriptor.php                          \
+  php/src/Google/Protobuf/EnumValueDescriptor.php                     \
+  php/src/Google/Protobuf/FieldDescriptor.php                         \
+  php/src/Google/Protobuf/OneofDescriptor.php                         \
   php/src/Google/Protobuf/Internal/CodedInputStream.php               \
   php/src/Google/Protobuf/Internal/CodedOutputStream.php              \
   php/src/Google/Protobuf/Internal/DescriptorPool.php                 \
@@ -609,7 +615,6 @@ php_EXTRA_DIST=                                                       \
   php/src/Google/Protobuf/Internal/EnumDescriptorProto.php            \
   php/src/Google/Protobuf/Internal/EnumOptions.php                    \
   php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php       \
-  php/src/Google/Protobuf/Internal/EnumValueDescriptor.php            \
   php/src/Google/Protobuf/Internal/EnumValueOptions.php               \
   php/src/Google/Protobuf/Internal/FieldDescriptorProto_Label.php     \
   php/src/Google/Protobuf/Internal/FieldDescriptorProto.php           \
@@ -625,6 +630,7 @@ php_EXTRA_DIST=                                                       \
   php/src/Google/Protobuf/Internal/FileOptions.php                    \
   php/src/Google/Protobuf/Internal/GeneratedCodeInfo_Annotation.php   \
   php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php              \
+  php/src/Google/Protobuf/Internal/GetPublicDescriptorTrait.php       \
   php/src/Google/Protobuf/Internal/GPBDecodeException.php             \
   php/src/Google/Protobuf/Internal/GPBJsonWire.php                    \
   php/src/Google/Protobuf/Internal/GPBLabel.php                       \
@@ -632,6 +638,7 @@ php_EXTRA_DIST=                                                       \
   php/src/Google/Protobuf/Internal/GPBUtil.php                        \
   php/src/Google/Protobuf/Internal/GPBWireType.php                    \
   php/src/Google/Protobuf/Internal/GPBWire.php                        \
+  php/src/Google/Protobuf/Internal/HasPublicDescriptorTrait.php       \
   php/src/Google/Protobuf/Internal/MapEntry.php                       \
   php/src/Google/Protobuf/Internal/MapFieldIter.php                   \
   php/src/Google/Protobuf/Internal/MapField.php                       \

+ 2 - 2
composer.json

@@ -16,8 +16,8 @@
   },
   "autoload": {
     "psr-4": {
-      "Google\\Protobuf\\Internal\\": "php/src/Google/Protobuf/Internal",
-      "GPBMetadata\\Google\\Protobuf\\Internal\\": "php/src/GPBMetadata/Google/Protobuf/Internal"
+      "Google\\Protobuf\\": "php/src/Google/Protobuf",
+      "GPBMetadata\\Google\\Protobuf\\": "php/src/GPBMetadata/Google/Protobuf"
     }
   }
 }

+ 2 - 6
php/composer.json

@@ -13,12 +13,8 @@
   },
   "autoload": {
     "psr-4": {
-      "Foo\\": "tests/generated/Foo",
-      "Bar\\": "tests/generated/Bar",
-      "Google\\Protobuf\\": "tests/generated/Google/Protobuf",
-      "Google\\Protobuf\\Internal\\": "src/Google/Protobuf/Internal",
-      "GPBMetadata\\": "tests/generated/GPBMetadata",
-      "GPBMetadata\\Google\\Protobuf\\Internal\\": "src/GPBMetadata/Google/Protobuf/Internal",
+      "Google\\Protobuf\\": "src/Google/Protobuf",
+      "GPBMetadata\\Google\\Protobuf\\": "src/GPBMetadata/Google/Protobuf",
       "": "tests/generated"
     }
   }

+ 1 - 0
php/phpunit.xml

@@ -10,6 +10,7 @@
       <file>tests/generated_phpdoc_test.php</file>
       <file>tests/map_field_test.php</file>
       <file>tests/well_known_test.php</file>
+      <file>tests/descriptors_test.php</file>
       <file>tests/generated_service_test.php</file>
     </testsuite>
   </testsuites>

+ 100 - 0
php/src/Google/Protobuf/Descriptor.php

@@ -0,0 +1,100 @@
+<?php
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2017 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+namespace Google\Protobuf;
+
+use Google\Protobuf\Internal\GetPublicDescriptorTrait;
+
+class Descriptor
+{
+    use GetPublicDescriptorTrait;
+
+    private $internal_desc;
+
+    /**
+     * @internal
+     */
+    public function __construct($internal_desc)
+    {
+        $this->internal_desc = $internal_desc;
+    }
+
+    /**
+     * @return string Full protobuf message name
+     */
+    public function getFullName()
+    {
+        return trim($this->internal_desc->getFullName(), ".");
+    }
+
+    /**
+     * @return string PHP class name
+     */
+    public function getClass()
+    {
+        return $this->internal_desc->getClass();
+    }
+
+    /**
+     * @param int $index Must be >= 0 and < getFieldCount()
+     * @return FieldDescriptor
+     */
+    public function getField($index)
+    {
+        return $this->getPublicDescriptor($this->internal_desc->getFieldByIndex($index));
+    }
+
+    /**
+     * @return int Number of fields in message
+     */
+    public function getFieldCount()
+    {
+        return count($this->internal_desc->getField());
+    }
+
+    /**
+     * @param int $index Must be >= 0 and < getOneofDeclCount()
+     * @return OneofDescriptor
+     */
+    public function getOneofDecl($index)
+    {
+        return $this->getPublicDescriptor($this->internal_desc->getOneofDecl()[$index]);
+    }
+
+    /**
+     * @return int Number of oneofs in message
+     */
+    public function getOneofDeclCount()
+    {
+        return count($this->internal_desc->getOneofDecl());
+    }
+}

+ 76 - 0
php/src/Google/Protobuf/DescriptorPool.php

@@ -0,0 +1,76 @@
+<?php
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2017 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+namespace Google\Protobuf;
+
+class DescriptorPool
+{
+    private static $pool;
+
+    private $internal_pool;
+
+    /**
+     * @return DescriptorPool
+     */
+    public static function getGeneratedPool()
+    {
+        if (!isset(self::$pool)) {
+            self::$pool = new DescriptorPool(\Google\Protobuf\Internal\DescriptorPool::getGeneratedPool());
+        }
+        return self::$pool;
+    }
+
+    private function __construct($internal_pool)
+    {
+        $this->internal_pool = $internal_pool;
+    }
+
+    /**
+     * @param string $className A fully qualified protobuf class name
+     * @return Descriptor
+     */
+    public function getDescriptorByClassName($className)
+    {
+        $desc = $this->internal_pool->getDescriptorByClassName($className);
+        return is_null($desc) ? null : $desc->getPublicDescriptor();
+    }
+
+    /**
+     * @param string $className A fully qualified protobuf class name
+     * @return EnumDescriptor
+     */
+    public function getEnumDescriptorByClassName($className)
+    {
+        $desc = $this->internal_pool->getEnumDescriptorByClassName($className);
+        return is_null($desc) ? null : $desc->getPublicDescriptor();
+    }
+}

+ 79 - 0
php/src/Google/Protobuf/EnumDescriptor.php

@@ -0,0 +1,79 @@
+<?php
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2017 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+namespace Google\Protobuf;
+
+class EnumDescriptor
+{
+    private $internal_desc;
+
+    /**
+     * @internal
+     */
+    public function __construct($internal_desc)
+    {
+        $this->internal_desc = $internal_desc;
+    }
+
+    /**
+     * @return string Full protobuf message name
+     */
+    public function getFullName()
+    {
+        return $this->internal_desc->getFullName();
+    }
+
+    /**
+     * @return string PHP class name
+     */
+    public function getClass()
+    {
+        return $this->internal_desc->getClass();
+    }
+
+    /**
+     * @param int $index Must be >= 0 and < getValueCount()
+     * @return EnumValueDescriptor
+     */
+    public function getValue($index)
+    {
+        return $this->internal_desc->getValueDescriptorByIndex($index);
+    }
+
+    /**
+     * @return int Number of values in enum
+     */
+    public function getValueCount()
+    {
+        return $this->internal_desc->getValueCount();
+    }
+}

+ 12 - 7
php/src/Google/Protobuf/Internal/EnumValueDescriptor.php → php/src/Google/Protobuf/EnumValueDescriptor.php

@@ -30,28 +30,33 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-namespace Google\Protobuf\Internal;
+namespace Google\Protobuf;
 
 class EnumValueDescriptor
 {
     private $name;
     private $number;
 
-    public function setName($name)
+    /**
+     * @internal
+     */
+    public function __construct($name, $number)
     {
         $this->name = $name;
+        $this->number = $number;
     }
 
+    /**
+     * @return string
+     */
     public function getName()
     {
         return $this->name;
     }
 
-    public function setNumber($number)
-    {
-        $this->number = $number;
-    }
-
+    /**
+     * @return int
+     */
     public function getNumber()
     {
         return $this->number;

+ 117 - 0
php/src/Google/Protobuf/FieldDescriptor.php

@@ -0,0 +1,117 @@
+<?php
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2017 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+namespace Google\Protobuf;
+
+use Google\Protobuf\Internal\GetPublicDescriptorTrait;
+use Google\Protobuf\Internal\GPBType;
+
+class FieldDescriptor
+{
+    use GetPublicDescriptorTrait;
+
+    private $internal_desc;
+
+    /**
+     * @internal
+     */
+    public function __construct($internal_desc)
+    {
+        $this->internal_desc = $internal_desc;
+    }
+
+    /**
+     * @return string Field name
+     */
+    public function getName()
+    {
+        return $this->internal_desc->getName();
+    }
+
+    /**
+     * @return int Protobuf field number
+     */
+    public function getNumber()
+    {
+        return $this->internal_desc->getNumber();
+    }
+
+    /**
+     * @return int
+     */
+    public function getLabel()
+    {
+        return $this->internal_desc->getLabel();
+    }
+
+    /**
+     * @return int
+     */
+    public function getType()
+    {
+        return $this->internal_desc->getType();
+    }
+
+    /**
+     * @return Descriptor Returns a descriptor for the field type if the field type is a message, otherwise throws \Exception
+     * @throws \Exception
+     */
+    public function getMessageType()
+    {
+        if ($this->getType() == GPBType::MESSAGE) {
+            return $this->getPublicDescriptor($this->internal_desc->getMessageType());
+        } else {
+            throw new \Exception("Cannot get message type for non-message field '" . $this->getName() . "'");
+        }
+    }
+
+    /**
+     * @return EnumDescriptor Returns an enum descriptor if the field type is an enum, otherwise throws \Exception
+     * @throws \Exception
+     */
+    public function getEnumType()
+    {
+        if ($this->getType() == GPBType::ENUM) {
+            return $this->getPublicDescriptor($this->internal_desc->getEnumType());
+        } else {
+            throw new \Exception("Cannot get enum type for non-enum field '" . $this->getName() . "'");
+        }
+    }
+
+    /**
+     * @return boolean
+     */
+    public function isMap()
+    {
+        return $this->internal_desc->isMap();
+    }
+}

+ 20 - 1
php/src/Google/Protobuf/Internal/Descriptor.php

@@ -34,17 +34,24 @@ namespace Google\Protobuf\Internal;
 
 class Descriptor
 {
+    use HasPublicDescriptorTrait;
 
     private $full_name;
     private $field = [];
     private $json_to_field = [];
     private $name_to_field = [];
+    private $index_to_field = [];
     private $nested_type = [];
     private $enum_type = [];
     private $klass;
     private $options;
     private $oneof_decl = [];
 
+    public function __construct()
+    {
+        $this->public_desc = new \Google\Protobuf\Descriptor($this);
+    }
+
     public function addOneofDecl($oneof)
     {
         $this->oneof_decl[] = $oneof;
@@ -70,6 +77,7 @@ class Descriptor
         $this->field[$field->getNumber()] = $field;
         $this->json_to_field[$field->getJsonName()] = $field;
         $this->name_to_field[$field->getName()] = $field;
+        $this->index_to_field[] = $field;
     }
 
     public function getField()
@@ -124,6 +132,15 @@ class Descriptor
         }
     }
 
+    public function getFieldByIndex($index)
+    {
+        if (count($this->index_to_field) <= $index) {
+            return NULL;
+        } else {
+            return $this->index_to_field[$index];
+        }
+    }
+
     public function setClass($klass)
     {
         $this->klass = $klass;
@@ -179,9 +196,11 @@ class Descriptor
         }
 
         // Handle oneof fields.
+        $index = 0;
         foreach ($proto->getOneofDecl() as $oneof_proto) {
             $desc->addOneofDecl(
-                OneofDescriptor::buildFromProto($oneof_proto, $desc));
+                OneofDescriptor::buildFromProto($oneof_proto, $desc, $index));
+            $index++;
         }
 
         return $desc;

+ 2 - 2
php/src/Google/Protobuf/Internal/EnumBuilderContext.php

@@ -33,7 +33,7 @@
 namespace Google\Protobuf\Internal;
 
 use Google\Protobuf\Internal\EnumDescriptor;
-use Google\Protobuf\Internal\EnumValueDescriptor;
+use Google\Protobuf\EnumValueDescriptor;
 
 class EnumBuilderContext
 {
@@ -51,7 +51,7 @@ class EnumBuilderContext
 
     public function value($name, $number)
     {
-        $value = new EnumValueDescriptor();
+        $value = new EnumValueDescriptor($name, $number);
         $this->descriptor->addValue($number, $value);
         return $this;
     }

+ 20 - 0
php/src/Google/Protobuf/Internal/EnumDescriptor.php

@@ -2,13 +2,22 @@
 
 namespace Google\Protobuf\Internal;
 
+use Google\Protobuf\EnumValueDescriptor;
+
 class EnumDescriptor
 {
+    use HasPublicDescriptorTrait;
 
     private $klass;
     private $full_name;
     private $value;
     private $name_to_value;
+    private $value_descriptor = [];
+
+    public function __construct()
+    {
+        $this->public_desc = new \Google\Protobuf\EnumDescriptor($this);
+    }
 
     public function setFullName($full_name)
     {
@@ -24,6 +33,7 @@ class EnumDescriptor
     {
         $this->value[$number] = $value;
         $this->name_to_value[$value->getName()] = $value;
+        $this->value_descriptor[] = new EnumValueDescriptor($value->getName(), $number);
     }
 
     public function getValueByNumber($number)
@@ -36,6 +46,16 @@ class EnumDescriptor
         return $this->name_to_value[$name];
     }
 
+    public function getValueDescriptorByIndex($index)
+    {
+        return $this->value_descriptor[$index];
+    }
+
+    public function getValueCount()
+    {
+        return count($this->value);
+    }
+
     public function setClass($klass)
     {
         $this->klass = $klass;

+ 6 - 0
php/src/Google/Protobuf/Internal/FieldDescriptor.php

@@ -34,6 +34,7 @@ namespace Google\Protobuf\Internal;
 
 class FieldDescriptor
 {
+    use HasPublicDescriptorTrait;
 
     private $name;
     private $json_name;
@@ -48,6 +49,11 @@ class FieldDescriptor
     private $is_map;
     private $oneof_index = -1;
 
+    public function __construct()
+    {
+        $this->public_desc = new \Google\Protobuf\FieldDescriptor($this);
+    }
+
     public function setOneofIndex($index)
     {
         $this->oneof_index = $index;

+ 41 - 0
php/src/Google/Protobuf/Internal/GetPublicDescriptorTrait.php

@@ -0,0 +1,41 @@
+<?php
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2017 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+namespace Google\Protobuf\Internal;
+
+trait GetPublicDescriptorTrait
+{
+    private function getPublicDescriptor($desc)
+    {
+        return is_null($desc) ? null : $desc->getPublicDescriptor();
+    }
+}

+ 43 - 0
php/src/Google/Protobuf/Internal/HasPublicDescriptorTrait.php

@@ -0,0 +1,43 @@
+<?php
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+namespace Google\Protobuf\Internal;
+
+trait HasPublicDescriptorTrait
+{
+    private $public_desc;
+
+    public function getPublicDescriptor()
+    {
+        return $this->public_desc;
+    }
+}

+ 13 - 2
php/src/Google/Protobuf/Internal/OneofDescriptor.php

@@ -34,10 +34,16 @@ namespace Google\Protobuf\Internal;
 
 class OneofDescriptor
 {
+    use HasPublicDescriptorTrait;
 
     private $name;
     private $fields;
 
+    public function __construct()
+    {
+        $this->public_desc = new \Google\Protobuf\OneofDescriptor($this);
+    }
+
     public function setName($name)
     {
         $this->name = $name;
@@ -48,7 +54,7 @@ class OneofDescriptor
         return $this->name;
     }
 
-    public function addField(Descriptor $field)
+    public function addField(FieldDescriptor $field)
     {
         $this->fields[] = $field;
     }
@@ -58,10 +64,15 @@ class OneofDescriptor
         return $this->fields;
     }
 
-    public static function buildFromProto($oneof_proto)
+    public static function buildFromProto($oneof_proto, $desc, $index)
     {
         $oneof = new OneofDescriptor();
         $oneof->setName($oneof_proto->getName());
+        foreach ($desc->getField() as $field) {
+            if ($field->getOneofIndex() == $index) {
+                $oneof->addField($field);
+            }
+        }
         return $oneof;
     }
 }

+ 75 - 0
php/src/Google/Protobuf/OneofDescriptor.php

@@ -0,0 +1,75 @@
+<?php
+
+// Protocol Buffers - Google's data interchange format
+// Copyright 2017 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+namespace Google\Protobuf;
+
+use Google\Protobuf\Internal\GetPublicDescriptorTrait;
+
+class OneofDescriptor
+{
+    use GetPublicDescriptorTrait;
+
+    private $internal_desc;
+
+    /**
+     * @internal
+     */
+    public function __construct($internal_desc)
+    {
+        $this->internal_desc = $internal_desc;
+    }
+
+    /**
+     * @return string The name of the oneof
+     */
+    public function getName()
+    {
+        return $this->internal_desc->getName();
+    }
+
+    /**
+     * @param int $index Must be >= 0 and < getFieldCount()
+     * @return FieldDescriptor
+     */
+    public function getField($index)
+    {
+        return $this->getPublicDescriptor($this->internal_desc->getFields()[$index]);
+    }
+
+    /**
+     * @return int Number of fields in the oneof
+     */
+    public function getFieldCount()
+    {
+        return count($this->internal_desc->getFields());
+    }
+}