From 21b0e5587c01948927ede9be789671ff116b7ad4 Mon Sep 17 00:00:00 2001 From: michaelbausor Date: Fri, 4 Aug 2017 16:35:22 -0700 Subject: [PATCH] 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 --- Makefile.am | 9 +- composer.json | 4 +- php/composer.json | 8 +- php/phpunit.xml | 1 + php/src/Google/Protobuf/Descriptor.php | 100 +++++++++++++++ php/src/Google/Protobuf/DescriptorPool.php | 76 ++++++++++++ php/src/Google/Protobuf/EnumDescriptor.php | 79 ++++++++++++ .../{Internal => }/EnumValueDescriptor.php | 19 +-- php/src/Google/Protobuf/FieldDescriptor.php | 117 ++++++++++++++++++ .../Google/Protobuf/Internal/Descriptor.php | 21 +++- .../Protobuf/Internal/EnumBuilderContext.php | 4 +- .../Protobuf/Internal/EnumDescriptor.php | 20 +++ .../Protobuf/Internal/FieldDescriptor.php | 6 + .../Internal/GetPublicDescriptorTrait.php | 41 ++++++ .../Internal/HasPublicDescriptorTrait.php | 43 +++++++ .../Protobuf/Internal/OneofDescriptor.php | 15 ++- php/src/Google/Protobuf/OneofDescriptor.php | 75 +++++++++++ 17 files changed, 617 insertions(+), 21 deletions(-) create mode 100644 php/src/Google/Protobuf/Descriptor.php create mode 100644 php/src/Google/Protobuf/DescriptorPool.php create mode 100644 php/src/Google/Protobuf/EnumDescriptor.php rename php/src/Google/Protobuf/{Internal => }/EnumValueDescriptor.php (91%) create mode 100644 php/src/Google/Protobuf/FieldDescriptor.php create mode 100644 php/src/Google/Protobuf/Internal/GetPublicDescriptorTrait.php create mode 100644 php/src/Google/Protobuf/Internal/HasPublicDescriptorTrait.php create mode 100644 php/src/Google/Protobuf/OneofDescriptor.php diff --git a/Makefile.am b/Makefile.am index 6279b2de1a..fafe1d252f 100644 --- a/Makefile.am +++ b/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 \ diff --git a/composer.json b/composer.json index 80d90eabf3..2c64ad220f 100644 --- a/composer.json +++ b/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" } } } diff --git a/php/composer.json b/php/composer.json index 724a45dd88..34e0447c80 100644 --- a/php/composer.json +++ b/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" } } diff --git a/php/phpunit.xml b/php/phpunit.xml index 637467bec2..d7077038dd 100644 --- a/php/phpunit.xml +++ b/php/phpunit.xml @@ -10,6 +10,7 @@ tests/generated_phpdoc_test.php tests/map_field_test.php tests/well_known_test.php + tests/descriptors_test.php tests/generated_service_test.php diff --git a/php/src/Google/Protobuf/Descriptor.php b/php/src/Google/Protobuf/Descriptor.php new file mode 100644 index 0000000000..986b81e12d --- /dev/null +++ b/php/src/Google/Protobuf/Descriptor.php @@ -0,0 +1,100 @@ +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()); + } +} diff --git a/php/src/Google/Protobuf/DescriptorPool.php b/php/src/Google/Protobuf/DescriptorPool.php new file mode 100644 index 0000000000..119f0e2e60 --- /dev/null +++ b/php/src/Google/Protobuf/DescriptorPool.php @@ -0,0 +1,76 @@ +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(); + } +} diff --git a/php/src/Google/Protobuf/EnumDescriptor.php b/php/src/Google/Protobuf/EnumDescriptor.php new file mode 100644 index 0000000000..a8b56c0d46 --- /dev/null +++ b/php/src/Google/Protobuf/EnumDescriptor.php @@ -0,0 +1,79 @@ +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(); + } +} diff --git a/php/src/Google/Protobuf/Internal/EnumValueDescriptor.php b/php/src/Google/Protobuf/EnumValueDescriptor.php similarity index 91% rename from php/src/Google/Protobuf/Internal/EnumValueDescriptor.php rename to php/src/Google/Protobuf/EnumValueDescriptor.php index 549766e3ae..e76e199718 100644 --- a/php/src/Google/Protobuf/Internal/EnumValueDescriptor.php +++ b/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; diff --git a/php/src/Google/Protobuf/FieldDescriptor.php b/php/src/Google/Protobuf/FieldDescriptor.php new file mode 100644 index 0000000000..ac9271f98b --- /dev/null +++ b/php/src/Google/Protobuf/FieldDescriptor.php @@ -0,0 +1,117 @@ +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(); + } +} diff --git a/php/src/Google/Protobuf/Internal/Descriptor.php b/php/src/Google/Protobuf/Internal/Descriptor.php index 44225ad276..ee3a8bdec5 100644 --- a/php/src/Google/Protobuf/Internal/Descriptor.php +++ b/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; diff --git a/php/src/Google/Protobuf/Internal/EnumBuilderContext.php b/php/src/Google/Protobuf/Internal/EnumBuilderContext.php index c1dac24dd8..08397284e9 100644 --- a/php/src/Google/Protobuf/Internal/EnumBuilderContext.php +++ b/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; } diff --git a/php/src/Google/Protobuf/Internal/EnumDescriptor.php b/php/src/Google/Protobuf/Internal/EnumDescriptor.php index 33a55a4a6c..01649fec4f 100644 --- a/php/src/Google/Protobuf/Internal/EnumDescriptor.php +++ b/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; diff --git a/php/src/Google/Protobuf/Internal/FieldDescriptor.php b/php/src/Google/Protobuf/Internal/FieldDescriptor.php index f18bf810af..1443c6fd0b 100644 --- a/php/src/Google/Protobuf/Internal/FieldDescriptor.php +++ b/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; diff --git a/php/src/Google/Protobuf/Internal/GetPublicDescriptorTrait.php b/php/src/Google/Protobuf/Internal/GetPublicDescriptorTrait.php new file mode 100644 index 0000000000..d22bc305b2 --- /dev/null +++ b/php/src/Google/Protobuf/Internal/GetPublicDescriptorTrait.php @@ -0,0 +1,41 @@ +getPublicDescriptor(); + } +} diff --git a/php/src/Google/Protobuf/Internal/HasPublicDescriptorTrait.php b/php/src/Google/Protobuf/Internal/HasPublicDescriptorTrait.php new file mode 100644 index 0000000000..ed5d1660ba --- /dev/null +++ b/php/src/Google/Protobuf/Internal/HasPublicDescriptorTrait.php @@ -0,0 +1,43 @@ +public_desc; + } +} diff --git a/php/src/Google/Protobuf/Internal/OneofDescriptor.php b/php/src/Google/Protobuf/Internal/OneofDescriptor.php index 57961f394d..67b107f6a4 100644 --- a/php/src/Google/Protobuf/Internal/OneofDescriptor.php +++ b/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; } } diff --git a/php/src/Google/Protobuf/OneofDescriptor.php b/php/src/Google/Protobuf/OneofDescriptor.php new file mode 100644 index 0000000000..d9736634e3 --- /dev/null +++ b/php/src/Google/Protobuf/OneofDescriptor.php @@ -0,0 +1,75 @@ +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()); + } +}