Skip to content

Commit 3c901c0

Browse files
author
František Mazura
committed
namespace update
1 parent 0211608 commit 3c901c0

File tree

7 files changed

+167
-176
lines changed

7 files changed

+167
-176
lines changed

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
.PHONY: tests
22

33
COMPOSER_IMAGE=composer
4-
PHP_IMAGE=php:7.3
4+
PHP_IMAGE=php:7.4
55

66
composer:
77
docker pull $(COMPOSER_IMAGE)
@@ -14,6 +14,7 @@ composer_update:
1414
make composer P=update
1515

1616
phpunit:
17+
docker pull $(PHP_IMAGE)
1718
docker run --rm -it -w /app --volume `pwd`:/app $(PHP_IMAGE) ./vendor/bin/phpunit $(P)
1819

1920
tests:

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ PHP Value object for storing valid data.
2020
# Changelog
2121

2222
- 2021-02-26
23-
- ignored attributes
24-
- touch (`setTouched`, `isTouched`, `getTouchedAll`)
25-
- add interface `ValueObjectInterface`
23+
- ignored attributes
24+
- touch (`setTouched`, `isTouched`, `getTouchedAll`)
25+
- add interface `ValueObjectInterface`
26+
- remove trait
27+
- min request PHP 7.4

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
}
2222
},
2323
"require": {
24-
"php": "^7.3|8.*",
24+
"php": "7.4|8.*",
2525
"nesbot/carbon": "^2.42.0"
2626
},
2727
"require-dev": {

src/AbstractValueObject.php

Lines changed: 153 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,21 @@
22

33
namespace OGSoft\ValueObjects;
44

5+
use Carbon\Carbon;
6+
use Exception;
57
use OGSoft\ValueObjects\Exceptions\ValidatorException;
68
use OGSoft\ValueObjects\Interfaces\GlobalValidatorInterface;
79
use OGSoft\ValueObjects\Interfaces\ValueObjectInterface;
10+
use ReflectionClass;
11+
use ReflectionException;
12+
use ReflectionParameter;
13+
use ReflectionType;
814
use Throwable;
915

1016
abstract class AbstractValueObject implements ValueObjectInterface
1117
{
12-
private $touched = [];
13-
private $ignoredAttrs = ["ignoredAttrs", "touched"];
18+
private array $touched = [];
19+
private array $ignoredAttrs = ["ignoredAttrs", "touched"];
1420

1521
public function isIgnoredAttr(string $attrName): bool
1622
{
@@ -20,9 +26,10 @@ public function isIgnoredAttr(string $attrName): bool
2026
/**
2127
* @inheritDoc
2228
*/
23-
public function setTouched(string $attrName): void
29+
public function setTouched(string $attrName): self
2430
{
2531
$this->touched[$attrName] = true;
32+
return $this;
2633
}
2734

2835
/**
@@ -44,7 +51,7 @@ public function getTouchedAll(): array
4451
/**
4552
* @inheritDoc
4653
*/
47-
public function init($data): void
54+
public function init($data): self
4855
{
4956
if (is_object($data)) {
5057
$data = get_object_vars($data);
@@ -71,6 +78,8 @@ public function init($data): void
7178
if ($this instanceof GlobalValidatorInterface) {
7279
$this->globalValidate();
7380
}
81+
82+
return $this;
7483
}
7584

7685
/**
@@ -116,4 +125,144 @@ public function toArray(): array
116125
return $out;
117126
}
118127

128+
public function setValue(string $attrName, string $attrSetter, $attrValue, object $obj): self
129+
{
130+
$reflectionParameter = self::getReflectionParameter($obj, $attrSetter);
131+
// build-in types
132+
if ($reflectionParameter->getType()->isBuiltin()) {
133+
if (is_array($attrValue)) {
134+
$attrValue = array_map(function ($v) use ($reflectionParameter) {
135+
return self::transformBuildInType($reflectionParameter, $v);
136+
}, $attrValue);
137+
$obj->$attrSetter(...$attrValue);
138+
} else {
139+
$attrValue = self::transformBuildInType($reflectionParameter, $attrValue);
140+
$obj->$attrSetter($attrValue);
141+
}
142+
} // custom types
143+
else {
144+
self::initAndValidateValueObject($obj, $attrSetter, $reflectionParameter, $attrValue);
145+
}
146+
147+
return $this;
148+
}
149+
150+
/**
151+
* @param $obj
152+
* @param $setter
153+
* @return null|ReflectionParameter
154+
* @throws ReflectionException
155+
*/
156+
private static function getReflectionParameter($obj, $setter): ?ReflectionParameter
157+
{
158+
$reflectionClass = new ReflectionClass($obj);
159+
$params = $reflectionClass->getMethod($setter)->getParameters();
160+
// setter has only one param
161+
$param = $params[0];
162+
if ($param->getType() instanceof ReflectionType) {
163+
// $name = $param->getType()->getName();
164+
return $param;
165+
}
166+
return null;
167+
}
168+
169+
/**
170+
* Normalize build-in type
171+
*
172+
* @param ReflectionParameter $reflectionParameter
173+
* @param $value
174+
* @return mixed
175+
*/
176+
private static function transformBuildInType(ReflectionParameter $reflectionParameter, $value)
177+
{
178+
// bool transform
179+
if ($reflectionParameter->getType()->getName() == "bool") {
180+
if (is_bool($value) || is_null($value)) {
181+
return $value;
182+
} else {
183+
return filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
184+
}
185+
}
186+
187+
// int transform
188+
if ($reflectionParameter->getType()->getName() == "int") {
189+
if ($value === '') {
190+
return null; // set null on empty string (because of Mango API and types handling)
191+
}
192+
}
193+
194+
// general
195+
return $value;
196+
}
197+
198+
/**
199+
* @param object $obj
200+
* @param string $setter
201+
* @param ReflectionParameter $parameter
202+
* @param $data
203+
* @throws Exception
204+
*/
205+
private static function initAndValidateValueObject(object $obj, string $setter, ReflectionParameter $parameter, $data)
206+
{
207+
$type = $parameter->getType()->getName();
208+
if (is_subclass_of($type, AbstractValueObject::class)) {
209+
if (empty($data) && !is_array($data)) {
210+
if ($parameter->allowsNull()) {
211+
return;
212+
}
213+
throw new ValidatorException(" Wrong data type of property. Data can not be null", get_class($obj), $parameter->name, $data);
214+
}
215+
if ($parameter->isVariadic()) {
216+
if (!is_array($data)) {
217+
$obj->$setter(null);
218+
return;
219+
}
220+
$dataArr = [];
221+
foreach ($data as $objData) {
222+
$reqObj = self::createValueObject($type, $objData);
223+
if ($reqObj) {
224+
$dataArr[] = $reqObj;
225+
}
226+
}
227+
$obj->$setter(...$dataArr);
228+
} else {
229+
$reqObj = self::createValueObject($type, $data);
230+
$obj->$setter($reqObj);
231+
}
232+
return;
233+
} elseif ($type == DateTime::class || $type == Carbon::class) {
234+
if (!$parameter->allowsNull() && empty($data)) {
235+
throw new ValidatorException(" Wrong data type of property. Date can not be null", get_class($obj), $parameter->name, $data);
236+
}
237+
/**
238+
* Parse date and time from data, if timezone is not part of the data string, user setting timezone is used (eg. messages from
239+
* machines come in UTC and without timezone information). If the timezone is part of the string, this one is used and has higher
240+
* priority, than user settings.
241+
* If the timezone is not specified within data string, nor in the user settings, the application default timezone is used.
242+
*/
243+
// TODO add timezone support
244+
$dateTime = empty($data) ? null : Carbon::parse($data, /*getCustomUserTimezone()*/);
245+
//$dateTime->setTimezone(new \DateTimeZone(config("app.timezone")));
246+
247+
$obj->$setter($dateTime);
248+
return;
249+
}
250+
throw new Exception("Unknown array type. Type has to be build in or subclass of AbstractRequestBody - " . $setter);
251+
}
252+
253+
/**
254+
* @param $className
255+
* @param $data
256+
* @return false|AbstractValueObject
257+
* @throws ValidatorException
258+
*/
259+
private static function createValueObject($className, $data)
260+
{
261+
$valueObject = new $className();
262+
if ($valueObject instanceof AbstractValueObject) {
263+
$valueObject->init($data);
264+
return $valueObject;
265+
}
266+
return false;
267+
}
119268
}

src/Interfaces/ValueObjectInterface.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@ interface ValueObjectInterface
1414
* Init object from array or object
1515
*
1616
* @param object|array $data
17-
* @return void
17+
* @return self
1818
* @throws ValidatorException
1919
*/
20-
public function init($data): void;
20+
public function init($data): self;
2121

2222
/**
2323
* setter for attribute of ValueObject
@@ -26,10 +26,10 @@ public function init($data): void;
2626
* @param string $attrSetter
2727
* @param $attrValue
2828
* @param object $valueObject
29-
* @return mixed
29+
* @return self
3030
* @throws ValidatorException
3131
*/
32-
public function setValue(string $attrName, string $attrSetter, $attrValue, object $valueObject): void;
32+
public function setValue(string $attrName, string $attrSetter, $attrValue, object $valueObject): self;
3333

3434
/**
3535
* @param Throwable $throwable
@@ -74,9 +74,9 @@ public function handleUndefinedAttribute(string $attrName, string $attrSetter, $
7474
* set attribute touch
7575
*
7676
* @param string $attrName
77-
* @return void
77+
* @return self
7878
*/
79-
public function setTouched(string $attrName): void;
79+
public function setTouched(string $attrName): self;
8080

8181
/**
8282
* check if attribute touched

0 commit comments

Comments
 (0)