Completed
Push — master ( cd91c1...62d6de )
by Maxence
02:26
created

Membership::getInheritanceDetails()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
6
/**
7
 * Circles - Bring cloud-users closer together.
8
 *
9
 * This file is licensed under the Affero General Public License version 3 or
10
 * later. See the COPYING file.
11
 *
12
 * @author Maxence Lange <[email protected]>
13
 * @copyright 2021
14
 * @license GNU AGPL version 3 or any later version
15
 *
16
 * This program is free software: you can redistribute it and/or modify
17
 * it under the terms of the GNU Affero General Public License as
18
 * published by the Free Software Foundation, either version 3 of the
19
 * License, or (at your option) any later version.
20
 *
21
 * This program is distributed in the hope that it will be useful,
22
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24
 * GNU Affero General Public License for more details.
25
 *
26
 * You should have received a copy of the GNU Affero General Public License
27
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
28
 *
29
 */
30
31
32
namespace OCA\Circles\Model;
33
34
use ArtificialOwl\MySmallPhpTools\Db\Nextcloud\nc22\INC22QueryRow;
35
use ArtificialOwl\MySmallPhpTools\Exceptions\InvalidItemException;
36
use ArtificialOwl\MySmallPhpTools\IDeserializable;
37
use ArtificialOwl\MySmallPhpTools\Traits\TArrayTools;
38
use JsonSerializable;
39
use OCA\Circles\Exceptions\MembershipNotFoundException;
40
41
42
/**
43
 * Class Membership
44
 *
45
 * @package OCA\Circles\Model
46
 */
47
class Membership extends ManagedModel implements IDeserializable, INC22QueryRow, JsonSerializable {
48
49
50
	use TArrayTools;
51
52
53
	/** @var string */
54
	private $singleId = '';
55
56
	/** @var string */
57
	private $circleId = '';
58
59
	/** @var int */
60
	private $config = 0;
61
62
	/** @var int */
63
	private $level = 0;
64
65
	/** @var string */
66
	private $inheritanceFirst = '';
67
68
	/** @var string */
69
	private $inheritanceLast = '';
70
71
	/** @var array */
72
	private $inheritancePath = [];
73
74
	/** @var int */
75
	private $inheritanceDepth = 0;
76
77
	/** @var array */
78
	private $inheritanceDetails = [];
79
80
81
	/**
82
	 * Membership constructor.
83
	 *
84
	 * @param string $singleId
85
	 * @param Member|null $member
86
	 * @param string $inheritanceLast
87
	 */
88
	public function __construct(
89
		string $singleId = '',
90
		string $inheritanceLast = '',
91
		?Member $member = null
92
	) {
93
		if (is_null($member)) {
94
			return;
95
		}
96
97
		$circle = $member->getCircle();
98
		$this->setSingleId($singleId);
99
		$this->setCircleId($circle->getSingleId());
100
		$this->setInheritanceFirst($member->getSingleId());
101
		$this->setInheritanceLast($inheritanceLast === '' ? $member->getCircleId() : $inheritanceLast);
102
		$this->setConfig($circle->getConfig());
103
		$this->setLevel($member->getLevel());
104
	}
105
106
107
	/**
108
	 * @param string $singleId
109
	 *
110
	 * @return self
111
	 */
112
	public function setSingleId(string $singleId): self {
113
		$this->singleId = $singleId;
114
115
		return $this;
116
	}
117
118
	/**
119
	 * @return string
120
	 */
121
	public function getSingleId(): string {
122
		return $this->singleId;
123
	}
124
125
126
	/**
127
	 * @param string $circleId
128
	 *
129
	 * @return Membership
130
	 */
131
	public function setCircleId(string $circleId): self {
132
		$this->circleId = $circleId;
133
134
		return $this;
135
	}
136
137
	/**
138
	 * @return string
139
	 */
140
	public function getCircleId(): string {
141
		return $this->circleId;
142
	}
143
144
145
	/**
146
	 * @param int $config
147
	 *
148
	 * @return Membership
149
	 */
150
	public function setConfig(int $config): self {
151
		$this->config = $config;
152
153
		return $this;
154
	}
155
156
	/**
157
	 * @return int
158
	 */
159
	public function getConfig(): int {
160
		return $this->config;
161
	}
162
163
164
	/**
165
	 * @param int $level
166
	 *
167
	 * @return Membership
168
	 */
169
	public function setLevel(int $level): self {
170
		$this->level = $level;
171
172
		return $this;
173
	}
174
175
	/**
176
	 * @return int
177
	 */
178
	public function getLevel(): int {
179
		return $this->level;
180
	}
181
182
183
	/**
184
	 * @param string $inheritanceFirst
185
	 *
186
	 * @return Membership
187
	 */
188
	public function setInheritanceFirst(string $inheritanceFirst): self {
189
		$this->inheritanceFirst = $inheritanceFirst;
190
191
		return $this;
192
	}
193
194
	/**
195
	 * @return string
196
	 */
197
	public function getInheritanceFirst(): string {
198
		return $this->inheritanceFirst;
199
	}
200
201
202
	/**
203
	 * @param string $inheritanceLast
204
	 *
205
	 * @return Membership
206
	 */
207
	public function setInheritanceLast(string $inheritanceLast): self {
208
		$this->inheritanceLast = $inheritanceLast;
209
210
		return $this;
211
	}
212
213
	/**
214
	 * @return string
215
	 */
216
	public function getInheritanceLast(): string {
217
		return $this->inheritanceLast;
218
	}
219
220
221
	/**
222
	 * @param array $inheritancePath
223
	 *
224
	 * @return Membership
225
	 */
226
	public function setInheritancePath(array $inheritancePath): self {
227
		$this->inheritancePath = $inheritancePath;
228
229
		return $this;
230
	}
231
232
	/**
233
	 * @return array
234
	 */
235
	public function getInheritancePath(): array {
236
		return $this->inheritancePath;
237
	}
238
239
240
	/**
241
	 * @param int $inheritanceDepth
242
	 *
243
	 * @return Membership
244
	 */
245
	public function setInheritanceDepth(int $inheritanceDepth): self {
246
		$this->inheritanceDepth = $inheritanceDepth;
247
248
		return $this;
249
	}
250
251
	/**
252
	 * @return int
253
	 */
254
	public function getInheritanceDepth(): int {
255
		return $this->inheritanceDepth;
256
	}
257
258
259
	/**
260
	 * @param array $inheritanceDetails
261
	 *
262
	 * @return Membership
263
	 */
264
	public function setInheritanceDetails(array $inheritanceDetails): self {
265
		$this->inheritanceDetails = $inheritanceDetails;
266
267
		return $this;
268
	}
269
270
	/**
271
	 * @return array
272
	 */
273
	public function getInheritanceDetails(): array {
274
		return $this->inheritanceDetails;
275
	}
276
277
278
	/**
279
	 * @param array $data
280
	 *
281
	 * @return IDeserializable
282
	 * @throws InvalidItemException
283
	 */
284
	public function import(array $data): IDeserializable {
285
		if ($this->get('singleId', $data) === '') {
286
			throw new InvalidItemException();
287
		}
288
289
		$this->setSingleId($this->get('singleId', $data));
290
		$this->setCircleId($this->get('circleId', $data));
291
		$this->setLevel($this->getInt('level', $data));
292
		$this->setConfig($this->getInt('config', $data));
293
		$this->setInheritanceFirst($this->get('inheritanceFirst', $data));
294
		$this->setInheritanceLast($this->get('inheritanceLast', $data));
295
		$this->setInheritancePath($this->getArray('inheritancePath', $data));
296
		$this->setInheritanceDepth($this->getInt('inheritanceDepth', $data));
297
298
		return $this;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this; (OCA\Circles\Model\Membership) is incompatible with the return type declared by the interface ArtificialOwl\MySmallPhp...IDeserializable::import of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
299
	}
300
301
	/**
302
	 * @param array $data
303
	 * @param string $prefix
304
	 *
305
	 * @return INC22QueryRow
306
	 * @throws MembershipNotFoundException
307
	 */
308
	public function importFromDatabase(array $data, string $prefix = ''): INC22QueryRow {
309
		if ($this->get($prefix . 'single_id', $data) === '') {
310
			throw new MembershipNotFoundException();
311
		}
312
313
		$this->setSingleId($this->get($prefix . 'single_id', $data));
314
		$this->setCircleId($this->get($prefix . 'circle_id', $data));
315
		$this->setLevel($this->getInt($prefix . 'level', $data));
316
		$this->setConfig($this->getInt($prefix . 'config', $data));
317
		$this->setInheritanceFirst($this->get($prefix . 'inheritance_first', $data));
318
		$this->setInheritanceLast($this->get($prefix . 'inheritance_last', $data));
319
		$this->setInheritancePath($this->getArray($prefix . 'inheritance_path', $data));
320
		$this->setInheritanceDepth($this->getInt($prefix . 'inheritance_depth', $data));
321
322
		return $this;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this; (OCA\Circles\Model\Membership) is incompatible with the return type declared by the interface ArtificialOwl\MySmallPhp...Row::importFromDatabase of type self.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
323
	}
324
325
326
	/**
327
	 * @return array
328
	 */
329
	public function jsonSerialize(): array {
330
		$result = [
331
			'singleId'         => $this->getSingleId(),
332
			'circleId'         => $this->getCircleId(),
333
			'config'           => $this->getConfig(),
334
			'level'            => $this->getLevel(),
335
			'inheritanceFirst' => $this->getInheritanceFirst(),
336
			'inheritanceLast'  => $this->getInheritanceLast(),
337
			'inheritancePath'  => $this->getInheritancePath(),
338
			'inheritanceDepth' => $this->getInheritanceDepth()
339
		];
340
341
		if (!empty($this->getInheritanceDetails())) {
342
			$result['inheritanceDetails'] = $this->getInheritanceDetails();
343
		}
344
345
		return $result;
346
	}
347
348
}
349
350