|
1
|
|
|
<?php |
|
2
|
|
|
/** |
|
3
|
|
|
* HashType class file |
|
4
|
|
|
*/ |
|
5
|
|
|
|
|
6
|
|
|
namespace Graviton\DocumentBundle\Types; |
|
7
|
|
|
|
|
8
|
|
|
use Doctrine\ODM\MongoDB\Types\Type; |
|
9
|
|
|
use Graviton\DocumentBundle\Entity\ExtReference; |
|
10
|
|
|
use Graviton\DocumentBundle\Entity\Hash; |
|
11
|
|
|
use Graviton\DocumentBundle\Service\ExtReferenceConverterInterface; |
|
12
|
|
|
|
|
13
|
|
|
/** |
|
14
|
|
|
* Hash type |
|
15
|
|
|
* |
|
16
|
|
|
* @author List of contributors <https://github.com/libgraviton/graviton/graphs/contributors> |
|
17
|
|
|
* @license http://opensource.org/licenses/MIT MIT License |
|
18
|
|
|
* @link http://swisscom.ch |
|
19
|
|
|
*/ |
|
20
|
|
|
class HashType extends Type |
|
21
|
|
|
{ |
|
22
|
|
|
|
|
23
|
|
|
/** |
|
24
|
|
|
* extref converter |
|
25
|
|
|
* |
|
26
|
|
|
* @var ExtReferenceConverterInterface |
|
27
|
|
|
*/ |
|
28
|
|
|
private static $extRefConverter; |
|
29
|
|
|
|
|
30
|
|
|
/** |
|
31
|
|
|
* sets the converter |
|
32
|
|
|
* |
|
33
|
|
|
* @param ExtReferenceConverterInterface $converter converter |
|
34
|
|
|
* |
|
35
|
|
|
* @return void |
|
36
|
|
|
*/ |
|
37
|
2 |
|
public function setExtRefConverter(ExtReferenceConverterInterface $converter) |
|
38
|
|
|
{ |
|
39
|
2 |
|
self::$extRefConverter = $converter; |
|
40
|
2 |
|
} |
|
41
|
|
|
|
|
42
|
|
|
/** |
|
43
|
|
|
* Convert DB value to PHP representation |
|
44
|
|
|
* |
|
45
|
|
|
* @param mixed $value Value to convert |
|
46
|
|
|
* @return Hash|null |
|
47
|
|
|
*/ |
|
48
|
8 |
|
public static function convertToPhp($value) |
|
49
|
|
|
{ |
|
50
|
8 |
|
return is_array($value) ? new Hash(self::processDynExtRefs($value)) : null; |
|
51
|
|
|
} |
|
52
|
|
|
|
|
53
|
|
|
/** |
|
54
|
|
|
* Convert PHP value to MongoDb representation |
|
55
|
|
|
* |
|
56
|
|
|
* @param mixed $value Value to convert |
|
57
|
|
|
* @return object|null |
|
58
|
|
|
*/ |
|
59
|
8 |
|
public static function convertToDb($value) |
|
60
|
|
|
{ |
|
61
|
8 |
|
$dbValue = null; |
|
62
|
|
|
|
|
63
|
8 |
|
if (is_array($value)) { |
|
64
|
4 |
|
$dbValue = (object) $value; |
|
65
|
4 |
|
} elseif ($value instanceof \ArrayObject) { |
|
66
|
8 |
|
$dbValue = (object) $value->getArrayCopy(); |
|
67
|
6 |
|
} elseif (is_object($value)) { |
|
68
|
|
|
$dbValue = (object) get_object_vars($value); |
|
69
|
|
|
} |
|
70
|
|
|
|
|
71
|
8 |
|
if (!is_null($dbValue)) { |
|
72
|
8 |
|
$dbValue = (object) self::processDynExtRefs($dbValue); |
|
73
|
4 |
|
} |
|
74
|
|
|
|
|
75
|
8 |
|
return $dbValue; |
|
76
|
|
|
} |
|
77
|
|
|
|
|
78
|
|
|
/** |
|
79
|
|
|
* loops our structure recursively to find all $ref objects that need to be converted |
|
80
|
|
|
* either from that or to that.. |
|
81
|
|
|
* |
|
82
|
|
|
* @param mixed $input input structure |
|
83
|
|
|
* |
|
84
|
|
|
* @return array altered structure with replaced $ref objects |
|
85
|
|
|
*/ |
|
86
|
16 |
|
public static function processDynExtRefs($input) |
|
87
|
|
|
{ |
|
88
|
16 |
|
if ($input instanceof \stdClass) { |
|
89
|
8 |
|
if (!empty(get_object_vars($input))) { |
|
90
|
8 |
|
$input = self::processDynExtRefs(get_object_vars($input)); |
|
91
|
4 |
|
} |
|
92
|
8 |
|
return $input; |
|
93
|
|
|
} |
|
94
|
|
|
|
|
95
|
16 |
|
$externalRefFieldName = '$ref'; |
|
96
|
16 |
|
$internalRefFieldName = 'ref'; |
|
97
|
|
|
|
|
98
|
16 |
|
if (is_array($input)) { |
|
99
|
16 |
|
foreach ($input as $key => $value) { |
|
100
|
16 |
|
if ($key === $internalRefFieldName) { |
|
101
|
|
|
if (is_array($value) && isset($value['$ref']) && isset($value['$id'])) { |
|
102
|
|
|
$extRef = ExtReference::create($value['$ref'], $value['$id']); |
|
103
|
|
|
$input[$externalRefFieldName] = self::$extRefConverter->getUrl($extRef); |
|
104
|
|
|
unset($input[$internalRefFieldName]); |
|
105
|
|
|
} |
|
106
|
16 |
|
} elseif ($key === $externalRefFieldName) { |
|
107
|
|
|
$extRef = self::$extRefConverter->getExtReference($value); |
|
108
|
|
|
$input[$internalRefFieldName] = $extRef->jsonSerialize(); |
|
109
|
|
|
unset($input[$externalRefFieldName]); |
|
110
|
|
|
} else { |
|
111
|
16 |
|
if (is_array($value)) { |
|
112
|
|
|
$value = self::processDynExtRefs($value); |
|
113
|
|
|
} |
|
114
|
16 |
|
$input[$key] = $value; |
|
115
|
|
|
} |
|
116
|
8 |
|
} |
|
117
|
8 |
|
} |
|
118
|
|
|
|
|
119
|
16 |
|
return $input; |
|
|
|
|
|
|
120
|
|
|
} |
|
121
|
|
|
|
|
122
|
|
|
/** |
|
123
|
|
|
* Convert to PHP value |
|
124
|
|
|
* |
|
125
|
|
|
* @param mixed $value Db value |
|
126
|
|
|
* @return Hash|null |
|
127
|
|
|
*/ |
|
128
|
2 |
|
public function convertToPHPValue($value) |
|
129
|
|
|
{ |
|
130
|
2 |
|
return static::convertToPhp($value); |
|
131
|
|
|
} |
|
132
|
|
|
|
|
133
|
|
|
/** |
|
134
|
|
|
* Closure to convert to PHP value |
|
135
|
|
|
* |
|
136
|
|
|
* @return string |
|
137
|
|
|
*/ |
|
138
|
4 |
|
public function closureToPHP() |
|
139
|
|
|
{ |
|
140
|
4 |
|
return '$return = \\'.static::class.'::convertToPhp($value);'; |
|
141
|
|
|
} |
|
142
|
|
|
|
|
143
|
|
|
/** |
|
144
|
|
|
* Convert to DB value |
|
145
|
|
|
* |
|
146
|
|
|
* @param mixed $value PHP value |
|
147
|
|
|
* @return object|null |
|
148
|
|
|
*/ |
|
149
|
2 |
|
public function convertToDatabaseValue($value) |
|
150
|
|
|
{ |
|
151
|
2 |
|
return static::convertToDb($value); |
|
152
|
|
|
} |
|
153
|
|
|
|
|
154
|
|
|
/** |
|
155
|
|
|
* Closure to convert to DB value |
|
156
|
|
|
* |
|
157
|
|
|
* @return string |
|
158
|
|
|
*/ |
|
159
|
2 |
|
public function closureToMongo() |
|
160
|
|
|
{ |
|
161
|
2 |
|
return '$return = \\'.static::class.'::convertToDb($value);'; |
|
162
|
|
|
} |
|
163
|
|
|
} |
|
164
|
|
|
|
If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.
Let’s take a look at an example:
Our function
my_functionexpects aPostobject, and outputs the author of the post. The base classPostreturns a simple string and outputting a simple string will work just fine. However, the child classBlogPostwhich is a sub-type ofPostinstead decided to return anobject, and is therefore violating the SOLID principles. If aBlogPostwere passed tomy_function, PHP would not complain, but ultimately fail when executing thestrtouppercall in its body.