Passed
Push — master ( 509b8c...0b1212 )
by Richard
01:44
created

ManyMany::offsetSetAutotraverse()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
c 0
b 0
f 0
nc 1
nop 3
dl 0
loc 5
rs 9.4285
1
<?php
2
namespace Maphper\Relation;
3
class ManyMany implements \IteratorAggregate, \ArrayAccess, \Countable, \Maphper\Relation {
4
	private $results;
5
	private $localField;
6
	private $parentField;
7
	private $iterator = 0;
8
	private $otherInfo;
9
	private $relatedMapper;
10
	private $intermediateMapper;
11
	private $autoTraverse = false;
12
	private $object;
13
	private $intermediateName;
14
15
	public function __construct(\Maphper\Maphper $intermediateMapper, \Maphper\Maphper $relatedMapper, $localField, $parentField, $intermediateName = null) {
16
		$this->intermediateMapper = $intermediateMapper;
17
		$this->relatedMapper = $relatedMapper;
18
		$this->localField = $localField;
19
		$this->parentField = $parentField;
20
		$this->autoTraverse = $intermediateName ? false : true;
21
		$this->intermediateName = $intermediateName ?: 'rel_' . $parentField;
22
		$this->intermediateMapper->addRelation($this->intermediateName, new One($this->relatedMapper, $parentField, $localField));
23
24
	}
25
26
	public function getData($parentObject) {
27
		$this->object = $parentObject;
28
		return clone $this;
29
	}
30
31
	public function overwrite($parentObject, &$data) {
32
		$this->results = $data;
33
		$this->object = $parentObject;
34
		foreach ($data as $dt) $this[] = $dt;
35
	}
36
37
	//bit hacky, breaking encapsulation, but simplest way to work out the info for the other side of the many:many relationship.
38
	private function getOtherFieldNameInfo() {
39
		if ($this->otherInfo == null) {
40
			$propertyReader = function($name) {return $this->$name;	};
41
42
			$reader = $propertyReader->bindTo($this->intermediateMapper, $this->intermediateMapper);
43
44
			foreach ($reader('relations') as $relation) {
45
				$propertyReader = $propertyReader->bindTo($relation, $relation);
46
				if ($propertyReader('parentField') != $this->parentField) {
47
					$relation = $relation->getData($this->object);
0 ignored issues
show
Unused Code introduced by
The assignment to $relation is dead and can be removed.
Loading history...
48
					$this->otherInfo = [$propertyReader('localField'),  $propertyReader('parentField'), $propertyReader('mapper')];
49
				}
50
			}
51
		}
52
		return $this->otherInfo;
53
	}
54
55
	public function count() {
56
		return count($this->getResults());
57
	}
58
59
	private function getResults() {
60
		list ($relatedField, $valueField, $relatedMapper) = $this->getOtherFieldNameInfo();
61
62
		$x = $this->intermediateMapper->filter([$valueField => $this->object->$relatedField]);
0 ignored issues
show
Bug introduced by
The method filter() does not exist on Maphper\Maphper. Since you implemented __call, consider adding a @method annotation. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

62
		/** @scrutinizer ignore-call */ 
63
  $x = $this->intermediateMapper->filter([$valueField => $this->object->$relatedField]);
Loading history...
63
		return $x;
64
	}
65
66
	public function getIterator() {
67
		$results = $this->getResults()->getIterator();
68
		return new ManyManyIterator($results, $this->autoTraverse ? $this->intermediateName : null);
69
	}
70
71
	public function item($i) {
72
		return iterator_to_array($this->getIterator(), false)[$i];
73
	}
74
75
	public function offsetExists($name) {
76
		$items = $this->getResults()->filter([$this->parentField => $name]);
77
78
		return $items->getIterator()->valid();
79
	}
80
81
	public function offsetGet($name) {
82
		$items = $this->getResults()->filter([$this->parentField => $name]);
83
84
		return $items->getIterator()->current()->{$this->intermediateName};
85
	}
86
87
	public function offsetSet($name, $value) {
88
		list($relatedField, $valueField, $mapper) = $this->getOtherFieldNameInfo();
89
		if ($this->autoTraverse) $this->offsetSetAutotraverse($value, $relatedField, $valueField);
90
		else if ($this->doUpdateInterMapper($value, $relatedField, $valueField)) {
91
            $record = $value;
92
			$record->{$this->parentField} = $value->{$this->intermediateName}->{$this->localField};
93
			$record->$valueField = $this->object->{$relatedField};
94
			$this->intermediateMapper[] = $record;
95
		}
96
	}
97
98
    private function doUpdateInterMapper($record, $relatedField, $valueField) {
99
        return !(isset($record->{$this->parentField}) && isset($record->{$this->intermediateName}) &&
100
                $record->{$this->parentField} == $record->{$this->intermediateName}->{$this->localField} &&
101
                $record->$valueField == $this->object->{$relatedField});
102
    }
103
104
    private function offsetSetAutotraverse($value, $relatedField, $valueField) {
105
        $record = new \stdClass;
106
        $record->{$this->parentField} =  $value->{$this->localField};
107
        $record->$valueField = $this->object->{$relatedField};
108
        $this->intermediateMapper[] = $record;
109
    }
110
111
	public function offsetUnset($id) {
112
		//$this->relation->mapper->filter([$relatedField => $this->object->$valueField, $this->relation->parentField => $id])->delete();
113
	}
114
}
115