diff options
Diffstat (limited to 'php/src/Google/Protobuf/Internal/Message.php')
-rw-r--r-- | php/src/Google/Protobuf/Internal/Message.php | 248 |
1 files changed, 150 insertions, 98 deletions
diff --git a/php/src/Google/Protobuf/Internal/Message.php b/php/src/Google/Protobuf/Internal/Message.php index 3aff7bd6..73ac375e 100644 --- a/php/src/Google/Protobuf/Internal/Message.php +++ b/php/src/Google/Protobuf/Internal/Message.php @@ -66,19 +66,30 @@ class Message /** * @ignore */ - public function __construct($desc = NULL) + public function __construct($data = NULL) { // MapEntry message is shared by all types of map fields, whose // descriptors are different from each other. Thus, we cannot find a // specific descriptor from the descriptor pool. - if (get_class($this) === 'Google\Protobuf\Internal\MapEntry') { - $this->desc = $desc; - foreach ($desc->getField() as $field) { - $setter = $field->getSetter(); - $this->$setter($this->defaultValue($field)); + if ($this instanceof MapEntry) { + $this->initWithDescriptor($data); + } else { + $this->initWithGeneratedPool(); + if (is_array($data)) { + $this->mergeFromArray($data); + } else if (!empty($data)) { + throw new \InvalidArgumentException( + 'Message constructor must be an array or null.' + ); } - return; } + } + + /** + * @ignore + */ + private function initWithGeneratedPool() + { $pool = DescriptorPool::getGeneratedPool(); $this->desc = $pool->getDescriptorByClassName(get_class($this)); if (is_null($this->desc)) { @@ -151,6 +162,19 @@ class Message } } + /** + * @ignore + */ + private function initWithDescriptor(Descriptor $desc) + { + $this->desc = $desc; + foreach ($desc->getField() as $field) { + $setter = $field->getSetter(); + $defaultValue = $this->defaultValue($field); + $this->$setter($defaultValue); + } + } + protected function readOneof($number) { $field = $this->desc->getFieldByNumber($number); @@ -628,58 +652,58 @@ class Message */ public function mergeFrom($msg) { - if (get_class($this) !== get_class($msg)) { - user_error("Cannot merge messages with different class."); - return; - } - - foreach ($this->desc->getField() as $field) { - $setter = $field->getSetter(); - $getter = $field->getGetter(); - if ($field->isMap()) { - if (count($msg->$getter()) != 0) { - $value_field = $field->getMessageType()->getFieldByNumber(2); - foreach ($msg->$getter() as $key => $value) { - if ($value_field->getType() == GPBType::MESSAGE) { - $klass = $value_field->getMessageType()->getClass(); - $copy = new $klass; - $copy->mergeFrom($value); - - $this->kvUpdateHelper($field, $key, $copy); - } else { - $this->kvUpdateHelper($field, $key, $value); - } - } - } - } else if ($field->getLabel() === GPBLabel::REPEATED) { - if (count($msg->$getter()) != 0) { - foreach ($msg->$getter() as $tmp) { - if ($field->getType() == GPBType::MESSAGE) { - $klass = $field->getMessageType()->getClass(); - $copy = new $klass; - $copy->mergeFrom($tmp); - $this->appendHelper($field, $copy); - } else { - $this->appendHelper($field, $tmp); - } - } - } - } else if ($field->getLabel() === GPBLabel::OPTIONAL) { - if($msg->$getter() !== $this->defaultValue($field)) { - $tmp = $msg->$getter(); - if ($field->getType() == GPBType::MESSAGE) { - if (is_null($this->$getter())) { - $klass = $field->getMessageType()->getClass(); - $new_msg = new $klass; - $this->$setter($new_msg); - } - $this->$getter()->mergeFrom($tmp); - } else { - $this->$setter($tmp); - } - } - } - } + if (get_class($this) !== get_class($msg)) { + user_error("Cannot merge messages with different class."); + return; + } + + foreach ($this->desc->getField() as $field) { + $setter = $field->getSetter(); + $getter = $field->getGetter(); + if ($field->isMap()) { + if (count($msg->$getter()) != 0) { + $value_field = $field->getMessageType()->getFieldByNumber(2); + foreach ($msg->$getter() as $key => $value) { + if ($value_field->getType() == GPBType::MESSAGE) { + $klass = $value_field->getMessageType()->getClass(); + $copy = new $klass; + $copy->mergeFrom($value); + + $this->kvUpdateHelper($field, $key, $copy); + } else { + $this->kvUpdateHelper($field, $key, $value); + } + } + } + } else if ($field->getLabel() === GPBLabel::REPEATED) { + if (count($msg->$getter()) != 0) { + foreach ($msg->$getter() as $tmp) { + if ($field->getType() == GPBType::MESSAGE) { + $klass = $field->getMessageType()->getClass(); + $copy = new $klass; + $copy->mergeFrom($tmp); + $this->appendHelper($field, $copy); + } else { + $this->appendHelper($field, $tmp); + } + } + } + } else if ($field->getLabel() === GPBLabel::OPTIONAL) { + if($msg->$getter() !== $this->defaultValue($field)) { + $tmp = $msg->$getter(); + if ($field->getType() == GPBType::MESSAGE) { + if (is_null($this->$getter())) { + $klass = $field->getMessageType()->getClass(); + $new_msg = new $klass; + $this->$setter($new_msg); + } + $this->$getter()->mergeFrom($tmp); + } else { + $this->$setter($tmp); + } + } + } + } } /** @@ -763,7 +787,8 @@ class Message try { $timestamp = GPBUtil::parseTimestamp($value); } catch (\Exception $e) { - throw new GPBDecodeException("Invalid RFC 3339 timestamp: ".$e->getMessage()); + throw new GPBDecodeException( + "Invalid RFC 3339 timestamp: ".$e->getMessage()); } $submsg->setSeconds($timestamp->getSeconds()); @@ -775,7 +800,8 @@ class Message try { return GPBUtil::parseFieldMask($value); } catch (\Exception $e) { - throw new GPBDecodeException("Invalid FieldMask: ".$e->getMessage()); + throw new GPBDecodeException( + "Invalid FieldMask: ".$e->getMessage()); } } else { if (is_null($value) && @@ -792,21 +818,23 @@ class Message case GPBType::ENUM: if (is_null($value)) { return $this->defaultValue($field); - } else if (is_integer($value)) { + } + if (is_integer($value)) { return $value; - } else { - $enum_value = - $field->getEnumType()->getValueByName($value); } + $enum_value = $field->getEnumType()->getValueByName($value); if (!is_null($enum_value)) { return $enum_value->getNumber(); } + throw new GPBDecodeException( + "Enum field only accepts integer or enum value name"); case GPBType::STRING: if (is_null($value)) { return $this->defaultValue($field); } if (!is_string($value)) { - throw new GPBDecodeException("Expect string"); + throw new GPBDecodeException( + "String field only accepts string value"); } return $value; case GPBType::BYTES: @@ -814,12 +842,12 @@ class Message return $this->defaultValue($field); } if (!is_string($value)) { - throw new GPBDecodeException("Expect string"); + throw new GPBDecodeException( + "Byte field only accepts string value"); } $proto_value = base64_decode($value, true); if ($proto_value === false) { - throw new GPBDecodeException( - "Invalid base64 characters"); + throw new GPBDecodeException("Invalid base64 characters"); } return $proto_value; case GPBType::BOOL: @@ -834,27 +862,14 @@ class Message return false; } throw new GPBDecodeException( - "Bool field only accept bool value"); + "Bool field only accepts bool value"); } if (!is_bool($value)) { throw new GPBDecodeException( - "Bool field only accept bool value"); + "Bool field only accepts bool value"); } return $value; case GPBType::FLOAT: - if (is_null($value)) { - return $this->defaultValue($field); - } - if ($value === "Infinity") { - return INF; - } - if ($value === "-Infinity") { - return -INF; - } - if ($value === "NaN") { - return NAN; - } - return $value; case GPBType::DOUBLE: if (is_null($value)) { return $this->defaultValue($field); @@ -943,6 +958,39 @@ class Message } } + /** + * Populates the message from a user-supplied PHP array. Array keys + * correspond to Message properties and nested message properties. + * + * Example: + * ``` + * $message->mergeFromArray([ + * 'name' => 'This is a message name', + * 'interval' => [ + * 'startTime' => time() - 60, + * 'endTime' => time(), + * ] + * ]); + * ``` + * + * @param array $array An array containing message properties and values. + * @return null. + * @throws Exception Invalid data. + */ + protected function mergeFromArray(array $array) + { + // Just call the setters for the field names + foreach ($array as $key => $value) { + $field = $this->desc->getFieldByName($key); + if (is_null($field)) { + throw new \UnexpectedValueException( + 'Invalid message property: ' . $key); + } + $setter = $field->getSetter(); + $this->$setter($value); + } + } + protected function mergeFromJsonArray($array) { if (is_a($this, "Google\Protobuf\Any")) { @@ -1035,6 +1083,11 @@ class Message } return; } + $this->mergeFromArrayJsonImpl($array); + } + + private function mergeFromArrayJsonImpl($array) + { foreach ($array as $key => $value) { $field = $this->desc->getFieldByJsonName($key); if (is_null($field)) { @@ -1043,7 +1096,6 @@ class Message continue; } } - $setter = $field->getSetter(); if ($field->isMap()) { if (is_null($value)) { continue; @@ -1055,15 +1107,13 @@ class Message throw new \Exception( "Map value field element cannot be null."); } - $proto_key = - $this->convertJsonValueToProtoValue( - $tmp_key, - $key_field, - true); - $proto_value = - $this->convertJsonValueToProtoValue( - $tmp_value, - $value_field); + $proto_key = $this->convertJsonValueToProtoValue( + $tmp_key, + $key_field, + true); + $proto_value = $this->convertJsonValueToProtoValue( + $tmp_value, + $value_field); self::kvUpdateHelper($field, $proto_key, $proto_value); } } else if ($field->isRepeated()) { @@ -1075,14 +1125,16 @@ class Message throw new \Exception( "Repeated field elements cannot be null."); } - $proto_value = - $this->convertJsonValueToProtoValue($tmp, $field); + $proto_value = $this->convertJsonValueToProtoValue( + $tmp, + $field); self::appendHelper($field, $proto_value); } } else { $setter = $field->getSetter(); - $proto_value = - $this->convertJsonValueToProtoValue($value, $field); + $proto_value = $this->convertJsonValueToProtoValue( + $value, + $field); if ($field->getType() === GPBType::MESSAGE) { if (is_null($proto_value)) { continue; |