Bladeren bron

php: Fix formatting of Duration (#6155)

* php: Fixed php notices for unknown enum indices

* php: Fixed formatting of Duration

This fixes:
* Missing nanoseconds. The nanoseconds where divided as a float and
  implicitly converted to a string before being passed to bcadd.
  This can result in a float formatted in scientific/exponential notation,
  which bcmath doesn't understand.
* Durations are supposed to be formatted without trailing zeroes.
Leonard Hecker 6 jaren geleden
bovenliggende
commit
43307d4da0

+ 0 - 4
conformance/failure_list_php.txt

@@ -3,10 +3,6 @@ Recommended.FieldMaskPathsDontRoundTrip.JsonOutput
 Recommended.FieldMaskTooManyUnderscore.JsonOutput
 Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
 Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
-Recommended.Proto3.JsonInput.DurationHas3FractionalDigits.Validator
-Recommended.Proto3.JsonInput.DurationHas6FractionalDigits.Validator
-Recommended.Proto3.JsonInput.DurationHas9FractionalDigits.Validator
-Recommended.Proto3.JsonInput.DurationHasZeroFractionalDigit.Validator
 Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter
 Required.Proto3.JsonInput.FloatFieldTooLarge
 Required.Proto3.JsonInput.FloatFieldTooSmall

+ 12 - 3
php/src/Google/Protobuf/Internal/EnumDescriptor.php

@@ -39,17 +39,26 @@ class EnumDescriptor
 
     public function getValueByNumber($number)
     {
-        return $this->value[$number];
+        if (isset($this->value[$number])) {
+            return $this->value[$number];
+        }
+        return null;
     }
 
     public function getValueByName($name)
     {
-        return $this->name_to_value[$name];
+        if (isset($this->name_to_value[$name])) {
+            return $this->name_to_value[$name];
+        }
+        return null;
     }
 
     public function getValueDescriptorByIndex($index)
     {
-        return $this->value_descriptor[$index];
+        if (isset($this->value_descriptor[$index])) {
+            return $this->value_descriptor[$index];
+        }
+        return null;
     }
 
     public function getValueCount()

+ 19 - 7
php/src/Google/Protobuf/Internal/GPBUtil.php

@@ -504,17 +504,29 @@ class GPBUtil
 
     public static function formatDuration($value)
     {
-        if (bccomp($value->getSeconds(), "315576000001") != -1) {
-          throw new GPBDecodeException("Duration number too large.");
+        if (bccomp($value->getSeconds(), '315576000001') != -1) {
+            throw new GPBDecodeException('Duration number too large.');
         }
-        if (bccomp($value->getSeconds(), "-315576000001") != 1) {
-          throw new GPBDecodeException("Duration number too small.");
+        if (bccomp($value->getSeconds(), '-315576000001') != 1) {
+            throw new GPBDecodeException('Duration number too small.');
+        }
+
+        $nanos = $value->getNanos();
+        if ($nanos === 0) {
+            return (string) $value->getSeconds();
         }
-        return strval(bcadd($value->getSeconds(),
-                      $value->getNanos() / 1000000000.0, 9));
-    }
 
+        if ($nanos % 1000000 === 0) {
+            $digits = 3;
+        } elseif ($nanos % 1000 === 0) {
+            $digits = 6;
+        } else {
+            $digits = 9;
+        }
 
+        $nanos = bcdiv($nanos, '1000000000', $digits);
+        return bcadd($value->getSeconds(), $nanos, $digits);
+    }
 
     public static function parseFieldMask($paths_string)
     {