-
Notifications
You must be signed in to change notification settings - Fork 261
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
PHPLIB-1180: Add basic infrastructure for codecs (#1125)
* Add psalm stubs for new BSON classes * Add basic codec infrastructure * Introduce codec library * Exclude methods inherited from traits in PedantryTest This commit also uses dataset names for better visibility during debugging * Exclude stubs from git exports * Improve architecture document * Use native types for DocumentCodec interface * Add description to codec interfaces * Remove internal designation from Decoder and Encoder interfaces * Remove unnecessary psalm-param annotations * Rename attachLibrary method in KnowsCodecLibrary interface The new method name is more specific and helps prevent naming conflicts * Use better values in test codecs * Add comment explaining stub files are temporary * Add comment explaining potential mocking when using PHPUnit 10 * Introduce domain exceptions for decoding and encoding * Improve codec architecture documentation
- Loading branch information
Showing
18 changed files
with
904 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
<?php | ||
/* | ||
* Copyright 2023-present MongoDB, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
namespace MongoDB\Codec; | ||
|
||
/** | ||
* The Codec interface allows decoding BSON data to native PHP types and back | ||
* to BSON. | ||
* | ||
* @psalm-template BSONType | ||
* @psalm-template NativeType | ||
* @template-extends Decoder<BSONType, NativeType> | ||
* @template-extends Encoder<BSONType, NativeType> | ||
*/ | ||
interface Codec extends Decoder, Encoder | ||
{ | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
<?php | ||
/* | ||
* Copyright 2023-present MongoDB, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
namespace MongoDB\Codec; | ||
|
||
use MongoDB\Exception\InvalidArgumentException; | ||
use MongoDB\Exception\UnsupportedValueException; | ||
|
||
class CodecLibrary implements Codec | ||
{ | ||
use DecodeIfSupported; | ||
use EncodeIfSupported; | ||
|
||
/** @var array<Decoder> */ | ||
private $decoders = []; | ||
|
||
/** @var array<Encoder> */ | ||
private $encoders = []; | ||
|
||
/** @param Decoder|Encoder $items */ | ||
public function __construct(...$items) | ||
{ | ||
foreach ($items as $item) { | ||
if (! $item instanceof Decoder && ! $item instanceof Encoder) { | ||
throw InvalidArgumentException::invalidType('$items', $item, [Decoder::class, Encoder::class]); | ||
} | ||
|
||
if ($item instanceof Codec) { | ||
// Use attachCodec to avoid multiple calls to attachLibrary | ||
$this->attachCodec($item); | ||
|
||
continue; | ||
} | ||
|
||
if ($item instanceof Decoder) { | ||
$this->attachDecoder($item); | ||
} | ||
|
||
if ($item instanceof Encoder) { | ||
$this->attachEncoder($item); | ||
} | ||
} | ||
} | ||
|
||
/** @return static */ | ||
final public function attachCodec(Codec $codec): self | ||
{ | ||
$this->decoders[] = $codec; | ||
$this->encoders[] = $codec; | ||
if ($codec instanceof KnowsCodecLibrary) { | ||
$codec->attachCodecLibrary($this); | ||
} | ||
|
||
return $this; | ||
} | ||
|
||
/** @return static */ | ||
final public function attachDecoder(Decoder $decoder): self | ||
{ | ||
$this->decoders[] = $decoder; | ||
if ($decoder instanceof KnowsCodecLibrary) { | ||
$decoder->attachCodecLibrary($this); | ||
} | ||
|
||
return $this; | ||
} | ||
|
||
/** @return static */ | ||
final public function attachEncoder(Encoder $encoder): self | ||
{ | ||
$this->encoders[] = $encoder; | ||
if ($encoder instanceof KnowsCodecLibrary) { | ||
$encoder->attachCodecLibrary($this); | ||
} | ||
|
||
return $this; | ||
} | ||
|
||
/** @param mixed $value */ | ||
final public function canDecode($value): bool | ||
{ | ||
foreach ($this->decoders as $decoder) { | ||
if ($decoder->canDecode($value)) { | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
/** @param mixed $value */ | ||
final public function canEncode($value): bool | ||
{ | ||
foreach ($this->encoders as $encoder) { | ||
if ($encoder->canEncode($value)) { | ||
return true; | ||
} | ||
} | ||
|
||
return false; | ||
} | ||
|
||
/** | ||
* @param mixed $value | ||
* @return mixed | ||
*/ | ||
final public function decode($value) | ||
{ | ||
foreach ($this->decoders as $decoder) { | ||
if ($decoder->canDecode($value)) { | ||
return $decoder->decode($value); | ||
} | ||
} | ||
|
||
throw UnsupportedValueException::invalidDecodableValue($value); | ||
} | ||
|
||
/** | ||
* @param mixed $value | ||
* @return mixed | ||
*/ | ||
final public function encode($value) | ||
{ | ||
foreach ($this->encoders as $encoder) { | ||
if ($encoder->canEncode($value)) { | ||
return $encoder->encode($value); | ||
} | ||
} | ||
|
||
throw UnsupportedValueException::invalidEncodableValue($value); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
<?php | ||
/* | ||
* Copyright 2023-present MongoDB, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
namespace MongoDB\Codec; | ||
|
||
use MongoDB\Exception\UnsupportedValueException; | ||
|
||
/** | ||
* @psalm-template BSONType | ||
* @psalm-template NativeType | ||
*/ | ||
trait DecodeIfSupported | ||
{ | ||
/** | ||
* @param mixed $value | ||
* @psalm-assert-if-true BSONType $value | ||
*/ | ||
abstract public function canDecode($value): bool; | ||
|
||
/** | ||
* @param mixed $value | ||
* @psalm-param BSONType $value | ||
* @return mixed | ||
* @psalm-return NativeType | ||
* @throws UnsupportedValueException if the decoder does not support the value | ||
*/ | ||
abstract public function decode($value); | ||
|
||
/** | ||
* @param mixed $value | ||
* @return mixed | ||
* @psalm-return ($value is BSONType ? NativeType : $value) | ||
*/ | ||
public function decodeIfSupported($value) | ||
{ | ||
return $this->canDecode($value) ? $this->decode($value) : $value; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
<?php | ||
/* | ||
* Copyright 2023-present MongoDB, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
namespace MongoDB\Codec; | ||
|
||
use MongoDB\Exception\UnsupportedValueException; | ||
|
||
/** | ||
* @psalm-template BSONType | ||
* @psalm-template NativeType | ||
*/ | ||
interface Decoder | ||
{ | ||
/** | ||
* Checks if the decoder supports a given value. | ||
* | ||
* @param mixed $value | ||
* @psalm-assert-if-true BSONType $value | ||
*/ | ||
public function canDecode($value): bool; | ||
|
||
/** | ||
* Decodes a given value. If the decoder does not support the value, it | ||
* should throw an exception. | ||
* | ||
* @param mixed $value | ||
* @psalm-param BSONType $value | ||
* @return mixed | ||
* @psalm-return NativeType | ||
* @throws UnsupportedValueException if the decoder does not support the value | ||
*/ | ||
public function decode($value); | ||
|
||
/** | ||
* Decodes a given value if supported, otherwise returns the value as-is. | ||
* | ||
* The DecodeIfSupported trait provides a default implementation of this | ||
* method. | ||
* | ||
* @param mixed $value | ||
* @return mixed | ||
* @psalm-return ($value is BSONType ? NativeType : $value) | ||
*/ | ||
public function decodeIfSupported($value); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
<?php | ||
/* | ||
* Copyright 2023-present MongoDB, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* https://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
namespace MongoDB\Codec; | ||
|
||
use MongoDB\BSON\Document; | ||
use MongoDB\Exception\UnsupportedValueException; | ||
|
||
/** | ||
* The DocumentCodec interface allows decoding BSON document data to native PHP | ||
* objects and back to BSON documents. | ||
* | ||
* @psalm-template ObjectType of object | ||
* @template-extends Codec<Document, ObjectType> | ||
*/ | ||
interface DocumentCodec extends Codec | ||
{ | ||
/** | ||
* @param mixed $value | ||
* @psalm-param Document $value | ||
* @psalm-return ObjectType | ||
* @throws UnsupportedValueException if the decoder does not support the value | ||
*/ | ||
public function decode($value): object; | ||
|
||
/** | ||
* @param mixed $value | ||
* @psalm-param ObjectType $value | ||
* @throws UnsupportedValueException if the encoder does not support the value | ||
*/ | ||
public function encode($value): Document; | ||
} |
Oops, something went wrong.