|
@@ -66,19 +66,30 @@ class Message
|
|
/**
|
|
/**
|
|
* @ignore
|
|
* @ignore
|
|
*/
|
|
*/
|
|
- public function __construct($desc = NULL)
|
|
|
|
|
|
+ public function __construct($data = NULL)
|
|
{
|
|
{
|
|
// MapEntry message is shared by all types of map fields, whose
|
|
// MapEntry message is shared by all types of map fields, whose
|
|
// descriptors are different from each other. Thus, we cannot find a
|
|
// descriptors are different from each other. Thus, we cannot find a
|
|
// specific descriptor from the descriptor pool.
|
|
// 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();
|
|
$pool = DescriptorPool::getGeneratedPool();
|
|
$this->desc = $pool->getDescriptorByClassName(get_class($this));
|
|
$this->desc = $pool->getDescriptorByClassName(get_class($this));
|
|
if (is_null($this->desc)) {
|
|
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)
|
|
protected function readOneof($number)
|
|
{
|
|
{
|
|
$field = $this->desc->getFieldByNumber($number);
|
|
$field = $this->desc->getFieldByNumber($number);
|
|
@@ -628,58 +652,58 @@ class Message
|
|
*/
|
|
*/
|
|
public function mergeFrom($msg)
|
|
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 {
|
|
try {
|
|
$timestamp = GPBUtil::parseTimestamp($value);
|
|
$timestamp = GPBUtil::parseTimestamp($value);
|
|
} catch (\Exception $e) {
|
|
} 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());
|
|
$submsg->setSeconds($timestamp->getSeconds());
|
|
@@ -775,7 +800,8 @@ class Message
|
|
try {
|
|
try {
|
|
return GPBUtil::parseFieldMask($value);
|
|
return GPBUtil::parseFieldMask($value);
|
|
} catch (\Exception $e) {
|
|
} catch (\Exception $e) {
|
|
- throw new GPBDecodeException("Invalid FieldMask: ".$e->getMessage());
|
|
|
|
|
|
+ throw new GPBDecodeException(
|
|
|
|
+ "Invalid FieldMask: ".$e->getMessage());
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
if (is_null($value) &&
|
|
if (is_null($value) &&
|
|
@@ -792,21 +818,23 @@ class Message
|
|
case GPBType::ENUM:
|
|
case GPBType::ENUM:
|
|
if (is_null($value)) {
|
|
if (is_null($value)) {
|
|
return $this->defaultValue($field);
|
|
return $this->defaultValue($field);
|
|
- } else if (is_integer($value)) {
|
|
|
|
|
|
+ }
|
|
|
|
+ if (is_integer($value)) {
|
|
return $value;
|
|
return $value;
|
|
- } else {
|
|
|
|
- $enum_value =
|
|
|
|
- $field->getEnumType()->getValueByName($value);
|
|
|
|
}
|
|
}
|
|
|
|
+ $enum_value = $field->getEnumType()->getValueByName($value);
|
|
if (!is_null($enum_value)) {
|
|
if (!is_null($enum_value)) {
|
|
return $enum_value->getNumber();
|
|
return $enum_value->getNumber();
|
|
}
|
|
}
|
|
|
|
+ throw new GPBDecodeException(
|
|
|
|
+ "Enum field only accepts integer or enum value name");
|
|
case GPBType::STRING:
|
|
case GPBType::STRING:
|
|
if (is_null($value)) {
|
|
if (is_null($value)) {
|
|
return $this->defaultValue($field);
|
|
return $this->defaultValue($field);
|
|
}
|
|
}
|
|
if (!is_string($value)) {
|
|
if (!is_string($value)) {
|
|
- throw new GPBDecodeException("Expect string");
|
|
|
|
|
|
+ throw new GPBDecodeException(
|
|
|
|
+ "String field only accepts string value");
|
|
}
|
|
}
|
|
return $value;
|
|
return $value;
|
|
case GPBType::BYTES:
|
|
case GPBType::BYTES:
|
|
@@ -814,12 +842,12 @@ class Message
|
|
return $this->defaultValue($field);
|
|
return $this->defaultValue($field);
|
|
}
|
|
}
|
|
if (!is_string($value)) {
|
|
if (!is_string($value)) {
|
|
- throw new GPBDecodeException("Expect string");
|
|
|
|
|
|
+ throw new GPBDecodeException(
|
|
|
|
+ "Byte field only accepts string value");
|
|
}
|
|
}
|
|
$proto_value = base64_decode($value, true);
|
|
$proto_value = base64_decode($value, true);
|
|
if ($proto_value === false) {
|
|
if ($proto_value === false) {
|
|
- throw new GPBDecodeException(
|
|
|
|
- "Invalid base64 characters");
|
|
|
|
|
|
+ throw new GPBDecodeException("Invalid base64 characters");
|
|
}
|
|
}
|
|
return $proto_value;
|
|
return $proto_value;
|
|
case GPBType::BOOL:
|
|
case GPBType::BOOL:
|
|
@@ -834,27 +862,14 @@ class Message
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
throw new GPBDecodeException(
|
|
throw new GPBDecodeException(
|
|
- "Bool field only accept bool value");
|
|
|
|
|
|
+ "Bool field only accepts bool value");
|
|
}
|
|
}
|
|
if (!is_bool($value)) {
|
|
if (!is_bool($value)) {
|
|
throw new GPBDecodeException(
|
|
throw new GPBDecodeException(
|
|
- "Bool field only accept bool value");
|
|
|
|
|
|
+ "Bool field only accepts bool value");
|
|
}
|
|
}
|
|
return $value;
|
|
return $value;
|
|
case GPBType::FLOAT:
|
|
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:
|
|
case GPBType::DOUBLE:
|
|
if (is_null($value)) {
|
|
if (is_null($value)) {
|
|
return $this->defaultValue($field);
|
|
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)
|
|
protected function mergeFromJsonArray($array)
|
|
{
|
|
{
|
|
if (is_a($this, "Google\Protobuf\Any")) {
|
|
if (is_a($this, "Google\Protobuf\Any")) {
|
|
@@ -1035,6 +1083,11 @@ class Message
|
|
}
|
|
}
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
+ $this->mergeFromArrayJsonImpl($array);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private function mergeFromArrayJsonImpl($array)
|
|
|
|
+ {
|
|
foreach ($array as $key => $value) {
|
|
foreach ($array as $key => $value) {
|
|
$field = $this->desc->getFieldByJsonName($key);
|
|
$field = $this->desc->getFieldByJsonName($key);
|
|
if (is_null($field)) {
|
|
if (is_null($field)) {
|
|
@@ -1043,7 +1096,6 @@ class Message
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- $setter = $field->getSetter();
|
|
|
|
if ($field->isMap()) {
|
|
if ($field->isMap()) {
|
|
if (is_null($value)) {
|
|
if (is_null($value)) {
|
|
continue;
|
|
continue;
|
|
@@ -1055,15 +1107,13 @@ class Message
|
|
throw new \Exception(
|
|
throw new \Exception(
|
|
"Map value field element cannot be null.");
|
|
"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);
|
|
self::kvUpdateHelper($field, $proto_key, $proto_value);
|
|
}
|
|
}
|
|
} else if ($field->isRepeated()) {
|
|
} else if ($field->isRepeated()) {
|
|
@@ -1075,14 +1125,16 @@ class Message
|
|
throw new \Exception(
|
|
throw new \Exception(
|
|
"Repeated field elements cannot be null.");
|
|
"Repeated field elements cannot be null.");
|
|
}
|
|
}
|
|
- $proto_value =
|
|
|
|
- $this->convertJsonValueToProtoValue($tmp, $field);
|
|
|
|
|
|
+ $proto_value = $this->convertJsonValueToProtoValue(
|
|
|
|
+ $tmp,
|
|
|
|
+ $field);
|
|
self::appendHelper($field, $proto_value);
|
|
self::appendHelper($field, $proto_value);
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
$setter = $field->getSetter();
|
|
$setter = $field->getSetter();
|
|
- $proto_value =
|
|
|
|
- $this->convertJsonValueToProtoValue($value, $field);
|
|
|
|
|
|
+ $proto_value = $this->convertJsonValueToProtoValue(
|
|
|
|
+ $value,
|
|
|
|
+ $field);
|
|
if ($field->getType() === GPBType::MESSAGE) {
|
|
if ($field->getType() === GPBType::MESSAGE) {
|
|
if (is_null($proto_value)) {
|
|
if (is_null($proto_value)) {
|
|
continue;
|
|
continue;
|