Completed
Push — dev ( 855972...5af1fb )
by Marcin
02:16
created

Converter   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 70
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 24
c 3
b 0
f 0
dl 0
loc 70
rs 10
wmc 11

3 Methods

Rating   Name   Duplication   Size   Complexity  
A getClassesMapping() 0 9 2
A hasClassesMapping() 0 18 4
A convert() 0 11 5
1
<?php
2
declare(strict_types=1);
3
4
namespace MarcinOrlowski\ResponseBuilder;
5
6
/**
7
 * Laravel API Response Builder
8
 *
9
 * @package   MarcinOrlowski\ResponseBuilder
10
 *
11
 * @author    Marcin Orlowski <mail (#) marcinorlowski (.) com>
12
 * @copyright 2016-2019 Marcin Orlowski
13
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
14
 * @link      https://github.com/MarcinOrlowski/laravel-api-response-builder
15
 */
16
17
use Illuminate\Support\Facades\Config;
18
19
20
/**
21
 * Data converter
22
 */
23
class Converter
24
{
25
	/**
26
	 * Reads and validates "classes" config mapping
27
	 *
28
	 * @return array Classes mapping as specified in configuration or empty array if configuration found
29
	 *
30
	 * @throws \RuntimeException if "classes" mapping is technically invalid (i.e. not array etc).
31
	 */
32
	public static function getClassesMapping(): array
33
	{
34
		$classes = Config::get(ResponseBuilder::CONF_KEY_CLASSES) ?? [];
35
		if (!is_array($classes)) {
36
			throw new \RuntimeException(
37
				sprintf('CONFIG: "classes" mapping must be an array (%s given)', gettype($classes)));
38
		}
39
40
		return $classes;
41
	}
42
43
	/**
44
	 * Checks if we have "classes" mapping configured for $data object class.
45
	 * Returns @true if there's valid config for this class.
46
	 *
47
	 * @param object $data Object to check mapping for.
48
	 *
49
	 * @return bool
50
	 *
51
	 * @throws \InvalidArgumentException if $data is not an object.
52
	 */
53
	public static function hasClassesMapping(object $data): bool
54
	{
55
		$classes = static::getClassesMapping();
56
57
		// check for exact class name match...
58
		$result = array_key_exists(get_class($data), $classes);
59
		if (!$result) {
60
			// no exact match, then lets try with `instanceof`
61
			$data_cls = get_class($data);
62
			foreach($classes as $class_name => $params) {
63
				if ($data_cls instanceof  $class_name) {
64
					$result = true;
65
					break;
66
				}
67
			}
68
		}
69
70
		return $result;
71
	}
72
73
	/**
74
	 * Recursively walks $data array and converts all known objects if found. Note
75
	 * $data array is passed by reference so source $data array may be modified.
76
	 *
77
	 * @param array $classes "classes" config mapping array
78
	 * @param array $data    array to recursively convert known elements of
79
	 *
80
	 * @return void
81
	 */
82
	public static function convert(array $classes, array &$data): void
83
	{
84
		foreach ($data as $data_key => &$data_val) {
85
			if (is_array($data_val)) {
86
				static::convert($classes, $data_val);
87
			} elseif (is_object($data_val)) {
88
				$obj_class_name = get_class($data_val);
89
				if (array_key_exists($obj_class_name, $classes)) {
90
					$conversion_method = $classes[ $obj_class_name ][ ResponseBuilder::KEY_METHOD ];
91
					$converted = $data_val->$conversion_method();
92
					$data[ $data_key ] = $converted;
93
				}
94
			}
95
		}
96
	}
97
}
98