Completed
Push — master ( c1a0d7...2f63de )
by Ron
02:18
created

DiffStorageStoreRowData::getDiff()   C

Complexity

Conditions 8
Paths 9

Size

Total Lines 35
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 1
Metric Value
c 2
b 1
f 1
dl 0
loc 35
rs 5.3846
cc 8
eloc 24
nc 9
nop 1
1
<?php
2
namespace DataDiff;
3
4
use Exception;
5
6
class DiffStorageStoreRowData implements DiffStorageStoreRowDataInterface {
7
	/** @var array */
8
	private $row;
9
	/** @var array */
10
	private $keys;
11
	/** @var array */
12
	private $valueKeys;
13
	/** @var array */
14
	private $converter;
15
	/** @var array */
16
	private $foreignRow;
17
18
	/**
19
	 * @param array $row
20
	 * @param array $foreignRow
21
	 * @param array $keys
22
	 * @param array $valueKeys
23
	 * @param array $converter
24
	 */
25
	public function __construct(array $row = [], array $foreignRow = [], array $keys, array $valueKeys, array $converter) {
26
		$this->row = $row;
27
		$this->foreignRow = $foreignRow;
28
		$this->keys = $keys;
29
		$this->valueKeys = $valueKeys;
30
		$this->converter = $converter;
31
	}
32
33
	/**
34
	 * @param array $options
35
	 * @return array
36
	 */
37
	public function getData(array $options = []) {
38
		return $this->applyOptions($this->row, $options);
39
	}
40
41
	/**
42
	 * @param array $options
43
	 * @return array
44
	 */
45
	public function getForeignData(array $options = []) {
46
		return $this->applyOptions($this->foreignRow, $options);
47
	}
48
49
	/**
50
	 * @param array $options
51
	 * @return array
52
	 */
53
	public function getKeyData(array $options = []) {
54
		$row = $this->getData();
55
		$row = array_intersect_key($row, array_combine($this->keys, $this->keys));
56
		return $row;
57
	}
58
59
	/**
60
	 * @param array $options
61
	 * @return array
62
	 */
63
	public function getValueData(array $options = []) {
64
		$row = $this->getData();
65
		$row = array_intersect_key($row, array_combine($this->valueKeys, $this->valueKeys));
66
		return $row;
67
	}
68
69
	/**
70
	 * @param array $fields
71
	 * @return array
72
	 */
73
	public function getDiff(array $fields = null) {
74
		$diff = [];
75
		$localRow = $this->getData(['keys' => $fields]);
76
		$foreignRow = $this->getForeignData(['keys' => $fields]);
77
		$keys = array_keys(array_merge($this->row, $this->foreignRow));
78
		$formattedLocalRow = $this->formatRow($localRow);
79
		$formattedForeignRow = $this->formatRow($foreignRow);
80
		foreach($keys as $key) {
81
			$conv = function (array $row) use ($key) {
82
				$value = null;
83
				if(array_key_exists($key, $row)) {
84
					$value = $row[$key];
85
					if(array_key_exists($key, $this->converter) && $value !== null) {
86
						$value = call_user_func($this->converter[$key], $value);
87
					}
88
				}
89
				return $value;
90
			};
91
			$localValue = call_user_func($conv, $formattedLocalRow);
92
			$foreignValue = call_user_func($conv, $formattedForeignRow);
93
94
			if(is_scalar($localValue)) {
95
				$localValue = (string) $localValue;
96
			}
97
98
			if(is_scalar($foreignValue)) {
99
				$foreignValue = (string) $foreignValue;
100
			}
101
102
			if(json_encode($localValue) !== json_encode($foreignValue)) {
103
				$diff[$key] = ['local' => $localValue, 'foreign' => $foreignValue];
104
			}
105
		}
106
		return $diff;
107
	}
108
109
	/**
110
	 * @param array $fields
111
	 * @param mixed $format
112
	 * @return array
113
	 * @throws Exception
114
	 */
115
	public function getDiffFormatted(array $fields = null, $format = null) {
116
		$diff = $this->getDiff($fields);
117
		if($format === null) {
118
			$result = [];
119
			$formatVal = function ($value) {
120
				$value = preg_replace('/\\s+/', ' ', $value);
121
				if(strlen($value) > 20) {
122
					$value = substr($value, 0, 16) . ' ...';
123
				}
124
				return $value;
125
			};
126
			foreach($diff as $fieldName => $values) {
127
				$foreignValue = $formatVal($values['foreign']);
128
				$localValue = $formatVal($values['local']);
129
				$result[] = sprintf("%s: %s -> %s", $fieldName, $foreignValue, $localValue);
130
			}
131
			return join(', ', $result);
132
		}
133
		throw new Exception("Unknown format: {$format}");
134
	}
135
136
	/**
137
	 * @param array $row
138
	 * @param array $options
139
	 * @return array
140
	 */
141
	private function applyOptions(array $row, array $options) {
142
		if(count($options) < 1) {
143
			return $row;
144
		}
145 View Code Duplication
		if(array_key_exists('keys', $options) && is_array($options['keys'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
146
			$row = array_intersect_key($row, array_combine($options['keys'], $options['keys']));
147
		}
148 View Code Duplication
		if(array_key_exists('ignore', $options) && is_array($options['ignore'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
149
			$row = array_diff_key($row, array_combine($options['ignore'], $options['ignore']));
150
		}
151
		return $row;
152
	}
153
154
	/**
155
	 * @param array $row
156
	 * @return array
157
	 */
158
	private function formatRow($row) {
159
		$schema = $this->converter;
160
		$schema = array_map(function () { return null; }, $schema);
161
		$row = array_merge($schema, $row);
162
		return $row;
163
	}
164
}
165