Skip to content

Commit 53ef9ba

Browse files
author
Jonathan Oddy
committed
Classes for type configuration.
1 parent b4ff9ef commit 53ef9ba

File tree

8 files changed

+194
-77
lines changed

8 files changed

+194
-77
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
namespace Weasel\JsonMarshaller\Config\Type;
3+
4+
use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty;
5+
6+
class ListType extends Type {
7+
8+
/**
9+
* @var Type
10+
* @JsonProperty(type="\Weasel\JsonMarshaller\Config\Type\Type")
11+
*/
12+
public $valueType;
13+
14+
function __construct($valueType = null)
15+
{
16+
$this->valueType = $valueType;
17+
}
18+
19+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
namespace Weasel\JsonMarshaller\Config\Type;
3+
4+
use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty;
5+
6+
class MapType extends ListType {
7+
8+
/**
9+
* @var Type
10+
* @JsonProperty(type="\Weasel\JsonMarshaller\Config\Type\Type")
11+
*/
12+
public $keyType;
13+
14+
function __construct($keyType = null, $valueType = null)
15+
{
16+
$this->keyType = $keyType;
17+
parent::__construct($valueType);
18+
}
19+
20+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
namespace Weasel\JsonMarshaller\Config\Type;
3+
4+
use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty;
5+
6+
class ObjectType extends Type {
7+
8+
/**
9+
* @var string
10+
* @JsonProperty(type="string")
11+
*/
12+
public $class;
13+
14+
function __construct($class = null)
15+
{
16+
$this->class = $class;
17+
}
18+
19+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php
2+
namespace Weasel\JsonMarshaller\Config\Type;
3+
4+
use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonProperty;
5+
use Weasel\JsonMarshaller\Types\JsonType;
6+
7+
class ScalarType extends Type {
8+
9+
public function __construct($typeName = null) {
10+
$this->typeName = $typeName;
11+
}
12+
13+
/**
14+
* @var string
15+
* @JsonProperty(type="string")
16+
*/
17+
public $typeName;
18+
19+
/**
20+
* This is a bit of a dirty hack...
21+
* @var JsonType
22+
*/
23+
public $jsonType;
24+
25+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
namespace Weasel\JsonMarshaller\Config\Type;
3+
4+
use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonSubTypes;
5+
use Weasel\JsonMarshaller\Config\DoctrineAnnotations\JsonTypeInfo;
6+
7+
8+
/**
9+
* Class Type
10+
* @package Weasel\JsonMarshaller\Config\Type
11+
* @JsonSubTypes({
12+
* @JsonSubTypes\Type("\Weasel\JsonMarshaller\Config\Type\ListType"),
13+
* @JsonSubTypes\Type("\Weasel\JsonMarshaller\Config\Type\MapType"),
14+
* @JsonSubTypes\Type("\Weasel\JsonMarshaller\Config\Type\ScalarType"),
15+
* })
16+
* @JsonTypeInfo(use=JsonTypeInfo::ID_NAME, include=JsonTypeInfo::AS_PROPERTY, property="type")
17+
*/
18+
abstract class Type {
19+
20+
}

lib/Weasel/JsonMarshaller/JsonMapper.php

Lines changed: 77 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@
77
namespace Weasel\JsonMarshaller;
88

99
use Weasel\Common\Utils\ReflectionUtils;
10+
use Weasel\JsonMarshaller\Config\Type\ListType;
11+
use Weasel\JsonMarshaller\Config\Type\MapType;
12+
use Weasel\JsonMarshaller\Config\Type\ObjectType;
13+
use Weasel\JsonMarshaller\Config\Type\ScalarType;
14+
use Weasel\JsonMarshaller\Config\Type\Type;
1015
use Weasel\JsonMarshaller\Exception\InvalidTypeException;
1116
use InvalidArgumentException;
1217
use Weasel\JsonMarshaller\Types;
@@ -277,23 +282,23 @@ protected function _encodeObject($object, $typeInfo = null, $type = null)
277282
break;
278283
}
279284
$property = $typeInfo->typeInfoProperty;
280-
$properties[$property] = $this->_encodeValue($classId, array(TypeParser::TYPE_SCALAR, "string"));
285+
$properties[$property] = $this->_encodeValue($classId, new ScalarType("string"));
281286
break;
282287
case Config\Serialization\TypeInfo::TI_AS_WRAPPER_ARRAY:
283288
// We're actually going to encase this encoded object in an array containing the classId.
284289
if (!isset($classId)) {
285290
break;
286291
}
287292
return '[' . $this->_encodeValue($classId,
288-
array(TypeParser::TYPE_SCALAR, 'string')) . ', ' . $this->_objectToJson($properties) . ']';
293+
new ScalarType('string')) . ', ' . $this->_objectToJson($properties) . ']';
289294
break;
290295
case Config\Serialization\TypeInfo::TI_AS_WRAPPER_OBJECT:
291296
// Very similar yo the wrapper array case, but this time it's a map from the classId to the object.
292297
if (!isset($classId)) {
293298
break;
294299
}
295300
return '{' . $this->_encodeValue($classId,
296-
array(TypeParser::TYPE_SCALAR, 'string')) . ': ' . $this->_objectToJson($properties) . '}';
301+
new ScalarType('string')) . ': ' . $this->_objectToJson($properties) . '}';
297302
break;
298303
default:
299304
throw new \Exception("Unsupported type info storage at class level");
@@ -308,7 +313,7 @@ protected function _objectToJson($properties)
308313
{
309314
$elements = array();
310315
foreach ($properties as $key => $property) {
311-
$elements[] = $this->_encodeValue($key, array(TypeParser::TYPE_SCALAR, 'string')) . ': ' . $property;
316+
$elements[] = $this->_encodeValue($key, new ScalarType('string')) . ': ' . $property;
312317
}
313318
return '{' . implode(', ', $elements) . '}';
314319
}
@@ -473,58 +478,82 @@ protected function _decodeClass($array, $class, $strict)
473478

474479
}
475480

481+
/**
482+
* @param Type $type
483+
* @return Type
484+
*/
476485
protected function _parseType($type) {
477-
if (!is_array($type)) {
486+
if (!$type instanceof Type) {
478487
if (defined('E_USER_DEPRECATED')) {
479488
// TODO: need to handle serialized configs before we can properly deprecate this.
480489
// trigger_error("Use of unexpanded types is deprecated", E_USER_DEPRECATED);
481490
}
482491
// This is the really slow path.
483492
$type = TypeParser::parseType($type, false);
484493
}
485-
if ($type[0] == TypeParser::TYPE_SCALAR) {
486-
if (isset($this->typeHandlers[$type[1]])) {
494+
if ($type instanceof ScalarType) {
495+
if (isset($this->typeHandlers[$type->typeName])) {
487496
// Assumption: if there's a type handler for this type string, then it's the right thing to use.
488-
return array(TypeParser::TYPE_SCALAR, $type[1], $this->typeHandlers[$type[1]]);
497+
$type->jsonType = $this->typeHandlers[$type->typeName];
489498
} else {
490-
return array(TypeParser::TYPE_OBJECT, $type[1]);
499+
$type = new ObjectType($type->typeName);
491500
}
492501
}
493502
return $type;
494503
}
495504

505+
/**
506+
* @param $value
507+
* @param $type
508+
* @throws Exception\InvalidTypeException
509+
* @throws Exception\JsonMarshallerException
510+
* @throws \Exception
511+
* @return mixed
512+
*/
496513
protected function _decodeKey($value, $type)
497514
{
498515
if (!isset($value)) {
499516
throw new JsonMarshallerException("Key values cannot be null");
500517
}
501518
$typeData = $this->_parseType($type);
502-
switch ($typeData[0]) {
503-
case TypeParser::TYPE_SCALAR:
504-
// Keys are always strings, however we will allow other types, and disable strict type checking.
505-
return $this->_decodeValue($value, $typeData, false);
506-
default:
507-
throw new JsonMarshallerException("Keys must be of type int or string, not " . $type);
519+
if ($typeData instanceof ScalarType) {
520+
// Keys are always strings, however we will allow other types, and disable strict type checking.
521+
return $this->_decodeValue($value, $typeData, false);
522+
} else {
523+
throw new JsonMarshallerException("Keys must be of type int or string, not " . $type);
508524
}
509525
}
510526

527+
/**
528+
* @param $value
529+
* @param $type
530+
* @param $strict
531+
* @return mixed
532+
* @throws Exception\InvalidTypeException
533+
* @throws Exception\JsonMarshallerException
534+
* @throws \Exception
535+
*/
511536
protected function _decodeValue($value, $type, $strict)
512537
{
513538
if (!isset($value)) {
514539
return null;
515540
}
516541
$typeData = $this->_parseType($type);
517-
switch (array_shift($typeData)) {
518-
case TypeParser::TYPE_OBJECT:
542+
switch (true) {
543+
case ($typeData instanceof ObjectType):
519544
if (!is_array($value)) {
520-
throw new InvalidTypeException($typeData[0], $value);
545+
throw new InvalidTypeException($typeData->class, $value);
521546
}
522-
return $this->_decodeClass($value, $typeData[0], $strict);
547+
return $this->_decodeClass($value, $typeData->class, $strict);
523548
break;
524549
/** @noinspection PhpMissingBreakStatementInspection */
525-
case TypeParser::TYPE_LIST:
526-
case TypeParser::TYPE_MAP:
527-
list ($indexType, $elementType) = $typeData;
550+
case ($typeData instanceof MapType):
551+
$indexType = $typeData->keyType;
552+
case ($typeData instanceof ListType):
553+
if (!isset($indexType)) {
554+
$indexType = new ScalarType("int");
555+
}
556+
$elementType = $typeData->valueType;
528557
$result = array();
529558
if (!is_array($value)) {
530559
$value = array($value);
@@ -533,13 +562,10 @@ protected function _decodeValue($value, $type, $strict)
533562
$result[$this->_decodeKey($key, $indexType)] = $this->_decodeValue($element, $elementType, $strict);
534563
}
535564
return $result;
536-
break;
565+
case ($typeData instanceof ScalarType):
566+
return $typeData->jsonType->decodeValue($value, $this, $strict);
537567
default:
538-
/**
539-
* @var $typeHandler Types\JsonType
540-
*/
541-
list ($typeName, $typeHandler) = $typeData;
542-
return $typeHandler->decodeValue($value, $this, $strict);
568+
throw new \Exception("Invalid config for type");
543569
}
544570

545571
}
@@ -550,12 +576,10 @@ protected function _encodeKey($value, $type)
550576
throw new JsonMarshallerException("Key values cannot be null");
551577
}
552578
$typeData = $this->_parseType($type);
553-
switch (array_shift($typeData)) {
554-
/** @noinspection PhpMissingBreakStatementInspection */
555-
case TypeParser::TYPE_SCALAR:
556-
return $this->_encodeValue($value, array(TypeParser::TYPE_SCALAR, "string"));
557-
default:
558-
throw new JsonMarshallerException("Keys must be of type int or string, not " . $type);
579+
if ($typeData instanceof ScalarType) {
580+
return $this->_encodeValue($value, new ScalarType("string"));
581+
} else {
582+
throw new JsonMarshallerException("Keys must be of type int or string, not " . $type);
559583
}
560584
}
561585

@@ -572,43 +596,39 @@ protected function _encodeValue($value, $type, $typeInfo = null)
572596
return json_encode(null);
573597
}
574598
$typeData = $this->_parseType($type);
575-
switch (array_shift($typeData)) {
576-
case TypeParser::TYPE_OBJECT:
599+
switch (true) {
600+
case ($typeData instanceof ObjectType):
577601
if (!is_object($value)) {
578-
throw new InvalidTypeException($typeData[0], $value);
602+
throw new InvalidTypeException($typeData->class, $value);
579603
}
580-
return $this->_encodeObject($value, $typeInfo, $typeData[0]);
581-
break;
582-
case TypeParser::TYPE_LIST:
583-
list ($indexType, $elementType) = $typeData;
604+
return $this->_encodeObject($value, $typeInfo, $typeData->class);
605+
case ($typeData instanceof MapType):
606+
$indexType = $typeData->keyType;
607+
$elementType = $typeData->valueType;
584608
if (!is_array($value)) {
585609
$value = array($value);
586610
}
587611
$elements = array();
588-
foreach ($value as $element) {
589-
$elements[] = $this->_encodeValue($element, $elementType);
612+
foreach ($value as $key => $element) {
613+
$elements[] = $this->_encodeKey($key, $indexType) . ': ' . $this->_encodeValue($element,
614+
$elementType);
590615
}
591-
return '[' . implode(', ', $elements) . ']';
592-
case TypeParser::TYPE_MAP:
593-
list ($indexType, $elementType) = $typeData;
616+
return '{' . implode(', ', $elements) . '}';
617+
case ($typeData instanceof ListType):
618+
$elementType = $typeData->valueType;
594619
if (!is_array($value)) {
595620
$value = array($value);
596621
}
597622
$elements = array();
598-
foreach ($value as $key => $element) {
599-
$elements[] = $this->_encodeKey($key, $indexType) . ': ' . $this->_encodeValue($element,
600-
$elementType);
623+
foreach ($value as $element) {
624+
$elements[] = $this->_encodeValue($element, $elementType);
601625
}
602-
return '{' . implode(', ', $elements) . '}';
626+
return '[' . implode(', ', $elements) . ']';
627+
case ($typeData instanceof ScalarType):
628+
return $typeData->jsonType->encodeValue($value, $this);
603629
default:
604-
/**
605-
* @var $typeHandler Types\JsonType
606-
*/
607-
list ($typeName, $typeHandler) = $typeData;
608-
return $typeHandler->encodeValue($value, $this);
609-
630+
throw new \Exception("Unable to work out what to do with type");
610631
}
611-
612632
}
613633

614634

0 commit comments

Comments
 (0)