RelationalEntity::addResolvable()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 1
1
<?php
2
/**
3
 * @copyright Copyright (c) 2017 Julius Härtl <[email protected]>
4
 *
5
 * @author Julius Härtl <[email protected]>
6
 *
7
 * @license GNU AGPL version 3 or any later version
8
 *  
9
 *  This program is free software: you can redistribute it and/or modify
10
 *  it under the terms of the GNU Affero General Public License as
11
 *  published by the Free Software Foundation, either version 3 of the
12
 *  License, or (at your option) any later version.
13
 *  
14
 *  This program is distributed in the hope that it will be useful,
15
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 *  GNU Affero General Public License for more details.
18
 *  
19
 *  You should have received a copy of the GNU Affero General Public License
20
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
 *  
22
 */
23
24
namespace OCA\Deck\Db;
25
26
use OCP\AppFramework\Db\Entity;
27
28
class RelationalEntity extends Entity implements \JsonSerializable {
29
30
	private $_relations = array();
31
	private $_resolvedProperties = [];
32
33
	/**
34
	 * Mark a property as relation so it will not get updated using Mapper::update
35
	 * @param string $property string Name of the property
36
	 */
37
	public function addRelation($property) {
38
		if (!in_array($property, $this->_relations, true)) {
39
			$this->_relations[] = $property;
40
		}
41
	}
42
43
	/**
44
	 * Mark a property as resolvable via resolveRelation()
45
	 * @param string $property string Name of the property
46
	 */
47
	public function addResolvable($property) {
48
		$this->_resolvedProperties[$property] = null;
49
	}
50
51
	/**
52
	 * Mark am attribute as updated
53
	 * overwritten from \OCP\AppFramework\Db\Entity to avoid writing relational attributes
54
	 * @param string $attribute the name of the attribute
55
	 * @since 7.0.0
56
	 */
57
	protected function markFieldUpdated($attribute) {
58
		if (!in_array($attribute, $this->_relations, true)) {
59
			parent::markFieldUpdated($attribute);
60
		}
61
	}
62
63
	/**
64
	 * @return array serialized data
65
	 * @throws \ReflectionException
66
	 */
67
	public function jsonSerialize() {
68
		$properties = get_object_vars($this);
69
		$reflection = new \ReflectionClass($this);
70
		$json = [];
71
		foreach ($properties as $property => $value) {
72
			if (strpos($property, '_') !== 0 && $reflection->hasProperty($property)) {
73
				$propertyReflection = $reflection->getProperty($property);
74
				if (!$propertyReflection->isPrivate() && !in_array($property, $this->_resolvedProperties, true)) {
75
					$json[$property] = $this->getter($property);
76
				}
77
			}
78
		}
79
		foreach ($this->_resolvedProperties as $property => $value) {
80
			if ($value !== null) {
81
				$json[$property] = $value;
82
			}
83
		}
84
		return $json;
85
	}
86
87
	/*
88
	 * Resolve relational data from external methods
89
	 *
90
	 * example usage:
91
	 *
92
	 * in Board::__construct()
93
	 * 		$this->addResolvable('owner')
94
	 *
95
	 * in BoardMapper
96
	 * 		$board->resolveRelation('owner', function($owner) use (&$userManager) {
97
	 * 			return new \OCA\Deck\Db\User($userManager->get($owner));
98
	 * 		});
99
	 *
100
	 * resolved values can be obtained by calling resolveProperty
101
	 * e.g. $board->resolveOwner()
102
	 *
103
	 * @param string $property name of the property
104
	 * @param callable $resolver anonymous function to resolve relational
105
	 * data defined by $property as unique identifier
106
	 * @throws \Exception
107
	 */
108
	public function resolveRelation($property, $resolver) {
109
		$result = null;
110
		if ($property !== null && $this->$property !== null) {
111
			$result = $resolver($this->$property);
112
		}
113
114
		if ($result instanceof RelationalObject || $result === null) {
115
			$this->_resolvedProperties[$property] = $result;
116
		} else {
117
			throw new \Exception('resolver must return an instance of RelationalObject');
118
		}
119
	}
120
121
	public function __call($methodName, $args) {
122
		$attr = lcfirst(substr($methodName, 7));
123
		if (array_key_exists($attr, $this->_resolvedProperties) && strpos($methodName, 'resolve') === 0) {
124
			if ($this->_resolvedProperties[$attr] !== null) {
125
				return $this->_resolvedProperties[$attr];
126
			}
127
			return $this->getter($attr);
128
		}
129
130
		$attr = lcfirst(substr($methodName, 3));
131
		if (array_key_exists($attr, $this->_resolvedProperties) && strpos($methodName, 'set') === 0) {
132
			if (!is_scalar($args[0])) {
133
				$args[0] = $args[0]['primaryKey'];
134
			}
135
			parent::setter($attr, $args);
0 ignored issues
show
Comprehensibility Bug introduced by
It seems like you call parent on a different method (setter() instead of __call()). Are you sure this is correct? If so, you might want to change this to $this->setter().

This check looks for a call to a parent method whose name is different than the method from which it is called.

Consider the following code:

class Daddy
{
    protected function getFirstName()
    {
        return "Eidur";
    }

    protected function getSurName()
    {
        return "Gudjohnsen";
    }
}

class Son
{
    public function getFirstName()
    {
        return parent::getSurname();
    }
}

The getFirstName() method in the Son calls the wrong method in the parent class.

Loading history...
136
			return null;
137
		}
138
		return parent::__call($methodName, $args);
139
	}
140
141
}