diff --git a/php/ext/google/protobuf/def.c b/php/ext/google/protobuf/def.c index 018dac19ac..8c3266eb07 100644 --- a/php/ext/google/protobuf/def.c +++ b/php/ext/google/protobuf/def.c @@ -456,6 +456,44 @@ PHP_METHOD(FieldDescriptor, getEnumType) { RETURN_COPY_VALUE(&ret); } +/* + * FieldDescriptor::getContainingOneof() + * + * Returns the OneofDescriptor for this field, or null if it is not inside + * a oneof. + */ +PHP_METHOD(FieldDescriptor, getContainingOneof) { + FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis()); + const upb_OneofDef *o = upb_FieldDef_ContainingOneof(intern->fielddef); + zval ret; + + if (!o) { + RETURN_NULL(); + } + + OneofDescriptor_FromOneofDef(&ret, o); + RETURN_COPY_VALUE(&ret); +} + +/* + * FieldDescriptor::getRealContainingOneof() + * + * Returns the non-synthetic OneofDescriptor for this field, or null if it is + * not inside a oneof. + */ +PHP_METHOD(FieldDescriptor, getRealContainingOneof) { + FieldDescriptor *intern = (FieldDescriptor*)Z_OBJ_P(getThis()); + const upb_OneofDef *o = upb_FieldDef_RealContainingOneof(intern->fielddef); + zval ret; + + if (!o) { + RETURN_NULL(); + } + + OneofDescriptor_FromOneofDef(&ret, o); + RETURN_COPY_VALUE(&ret); +} + /* * FieldDescriptor::getMessageType() * @@ -482,6 +520,8 @@ static zend_function_entry FieldDescriptor_methods[] = { PHP_ME(FieldDescriptor, getType, arginfo_void, ZEND_ACC_PUBLIC) PHP_ME(FieldDescriptor, isMap, arginfo_void, ZEND_ACC_PUBLIC) PHP_ME(FieldDescriptor, getEnumType, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(FieldDescriptor, getContainingOneof, arginfo_void, ZEND_ACC_PUBLIC) + PHP_ME(FieldDescriptor, getRealContainingOneof, arginfo_void, ZEND_ACC_PUBLIC) PHP_ME(FieldDescriptor, getMessageType, arginfo_void, ZEND_ACC_PUBLIC) ZEND_FE_END }; @@ -516,6 +556,7 @@ static zend_class_entry *Descriptor_GetGeneratedClass(const upb_MessageDef *m) { char *classname = GetPhpClassname(upb_MessageDef_File(m), upb_MessageDef_FullName(m), false); zend_error(E_ERROR, "Couldn't load generated class %s", classname); + return NULL; } void Descriptor_FromMessageDef(zval *val, const upb_MessageDef *m) { diff --git a/php/tests/DescriptorsTest.php b/php/tests/DescriptorsTest.php index 4f17a49571..336d979428 100644 --- a/php/tests/DescriptorsTest.php +++ b/php/tests/DescriptorsTest.php @@ -83,10 +83,10 @@ class DescriptorsTest extends TestBase $this->assertSame($class, $desc->getClass()); $this->assertInstanceOf('\Google\Protobuf\FieldDescriptor', $desc->getField(0)); - $this->assertSame(7, $desc->getFieldCount()); + $this->assertSame(8, $desc->getFieldCount()); $this->assertInstanceOf('\Google\Protobuf\OneofDescriptor', $desc->getOneofDecl(0)); - $this->assertSame(1, $desc->getOneofDeclCount()); + $this->assertSame(2, $desc->getOneofDeclCount()); } public function testDescriptorForIncludedMessage() @@ -180,6 +180,7 @@ class DescriptorsTest extends TestBase $this->assertSame(self::GPBTYPE_MESSAGE, $fieldDesc->getType()); $this->assertInstanceOf('\Google\Protobuf\Descriptor', $fieldDesc->getMessageType()); $this->assertFalse($fieldDesc->isMap()); + $this->assertNull($fieldDesc->getContainingOneof()); // Oneof int field // Tested further in testOneofDescriptor() @@ -189,6 +190,21 @@ class DescriptorsTest extends TestBase $this->assertSame(self::GPBLABEL_OPTIONAL, $fieldDesc->getLabel()); $this->assertSame(self::GPBTYPE_INT32, $fieldDesc->getType()); $this->assertFalse($fieldDesc->isMap()); + $this->assertSame($fieldDesc->getContainingOneof(), $fieldDesc->getRealContainingOneof()); + + $oneofDesc = $fieldDesc->getContainingOneof(); + $this->assertSame('my_oneof', $oneofDesc->getName()); + + // Proto3 optional it field. + // Tested further in testOneofDescriptor() + $fieldDesc = $fieldDescMap[52]; + $this->assertSame('proto3_optional_int32', $fieldDesc->getName()); + $this->assertSame(52, $fieldDesc->getNumber()); + $this->assertSame(self::GPBLABEL_OPTIONAL, $fieldDesc->getLabel()); + $this->assertSame(self::GPBTYPE_INT32, $fieldDesc->getType()); + $this->assertFalse($fieldDesc->isMap()); + $this->assertNull($fieldDesc->getRealContainingOneof()); + $this->assertNotNull($fieldDesc->getContainingOneof()); // Map int-enum field $fieldDesc = $fieldDescMap[71]; diff --git a/php/tests/proto/test_descriptors.proto b/php/tests/proto/test_descriptors.proto index d42aec7cec..b0956c6edd 100644 --- a/php/tests/proto/test_descriptors.proto +++ b/php/tests/proto/test_descriptors.proto @@ -14,6 +14,7 @@ message TestDescriptorsMessage { oneof my_oneof { int32 oneof_int32 = 51; } + optional int32 proto3_optional_int32 = 52; map map_int32_enum = 71;