Recursively clear unknown fields in submessages. (#3982)

* Recursively clear unknown fields in submessages.

* Recursively discard unknown fields in submsg for c extension

* Fix zts build

* Add comment for tests

* Add a TODO to add a util for encoding varint for better readability.

* Add test for oneof message field.
diff --git a/php/tests/encode_decode_test.php b/php/tests/encode_decode_test.php
index 4512c87..74d5526 100644
--- a/php/tests/encode_decode_test.php
+++ b/php/tests/encode_decode_test.php
@@ -443,36 +443,74 @@
 
     public function testUnknown()
     {
+        // Test preserve unknown for varint.
         $m = new TestMessage();
-        $from = hex2bin('F80601');
+        $from = hex2bin('F80601');  // TODO(teboring): Add a util to encode
+                                    // varint for better readability
         $m->mergeFromString($from);
         $to = $m->serializeToString();
         $this->assertSame(bin2hex($from), bin2hex($to));
 
+        // Test preserve unknown for 64-bit.
         $m = new TestMessage();
         $from = hex2bin('F9060000000000000000');
         $m->mergeFromString($from);
         $to = $m->serializeToString();
         $this->assertSame(bin2hex($from), bin2hex($to));
 
+        // Test preserve unknown for length delimited.
         $m = new TestMessage();
         $from = hex2bin('FA0600');
         $m->mergeFromString($from);
         $to = $m->serializeToString();
         $this->assertSame(bin2hex($from), bin2hex($to));
 
+        // Test preserve unknown for 32-bit.
         $m = new TestMessage();
         $from = hex2bin('FD0600000000');
         $m->mergeFromString($from);
         $to = $m->serializeToString();
         $this->assertSame(bin2hex($from), bin2hex($to));
 
+        // Test discard unknown in message.
         $m = new TestMessage();
         $from = hex2bin('F80601');
         $m->mergeFromString($from);
         $m->discardUnknownFields();
         $to = $m->serializeToString();
         $this->assertSame("", bin2hex($to));
+
+        // Test discard unknown for singular message field.
+        $m = new TestMessage();
+        $from = hex2bin('8A0103F80601');
+        $m->mergeFromString($from);
+        $m->discardUnknownFields();
+        $to = $m->serializeToString();
+        $this->assertSame("8a0100", bin2hex($to));
+
+        // Test discard unknown for repeated message field.
+        $m = new TestMessage();
+        $from = hex2bin('FA0203F80601');
+        $m->mergeFromString($from);
+        $m->discardUnknownFields();
+        $to = $m->serializeToString();
+        $this->assertSame("fa0200", bin2hex($to));
+
+        // Test discard unknown for map message value field.
+        $m = new TestMessage();
+        $from = hex2bin("BA050708011203F80601");
+        $m->mergeFromString($from);
+        $m->discardUnknownFields();
+        $to = $m->serializeToString();
+        $this->assertSame("ba050408011200", bin2hex($to));
+
+        // Test discard unknown for singular message field.
+        $m = new TestMessage();
+        $from = hex2bin('9A0403F80601');
+        $m->mergeFromString($from);
+        $m->discardUnknownFields();
+        $to = $m->serializeToString();
+        $this->assertSame("9a0400", bin2hex($to));
     }
 
     public function testJsonEncode()