Completed
Pull Request — master (#640)
by Maxence
02:41
created

Membership::setCircleConfig()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 5
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
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 $circleConfig = 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->setLevel($member->getLevel());
103
	}
104
105
106
	/**
107
	 * @param string $singleId
108
	 *
109
	 * @return self
110
	 */
111
	public function setSingleId(string $singleId): self {
112
		$this->singleId = $singleId;
113
114
		return $this;
115
	}
116
117
	/**
118
	 * @return string
119
	 */
120
	public function getSingleId(): string {
121
		return $this->singleId;
122
	}
123
124
125
	/**
126
	 * @param string $circleId
127
	 *
128
	 * @return Membership
129
	 */
130
	public function setCircleId(string $circleId): self {
131
		$this->circleId = $circleId;
132
133
		return $this;
134
	}
135
136
	/**
137
	 * @return string
138
	 */
139
	public function getCircleId(): string {
140
		return $this->circleId;
141
	}
142
143
144
	/**
145
	 * @param int $circleConfig
146
	 *
147
	 * @return Membership
148
	 */
149
	public function setCircleConfig(int $circleConfig): self {
150
		$this->circleConfig = $circleConfig;
151
152
		return $this;
153
	}
154
155
	/**
156
	 * @return int
157
	 */
158
	public function getCircleConfig(): int {
159
		return $this->circleConfig;
160
	}
161
162
163
	/**
164
	 * @param int $level
165
	 *
166
	 * @return Membership
167
	 */
168
	public function setLevel(int $level): self {
169
		$this->level = $level;
170
171
		return $this;
172
	}
173
174
	/**
175
	 * @return int
176
	 */
177
	public function getLevel(): int {
178
		return $this->level;
179
	}
180
181
182
	/**
183
	 * @param string $inheritanceFirst
184
	 *
185
	 * @return Membership
186
	 */
187
	public function setInheritanceFirst(string $inheritanceFirst): self {
188
		$this->inheritanceFirst = $inheritanceFirst;
189
190
		return $this;
191
	}
192
193
	/**
194
	 * @return string
195
	 */
196
	public function getInheritanceFirst(): string {
197
		return $this->inheritanceFirst;
198
	}
199
200
201
	/**
202
	 * @param string $inheritanceLast
203
	 *
204
	 * @return Membership
205
	 */
206
	public function setInheritanceLast(string $inheritanceLast): self {
207
		$this->inheritanceLast = $inheritanceLast;
208
209
		return $this;
210
	}
211
212
	/**
213
	 * @return string
214
	 */
215
	public function getInheritanceLast(): string {
216
		return $this->inheritanceLast;
217
	}
218
219
220
	/**
221
	 * @param array $inheritancePath
222
	 *
223
	 * @return Membership
224
	 */
225
	public function setInheritancePath(array $inheritancePath): self {
226
		$this->inheritancePath = $inheritancePath;
227
228
		return $this;
229
	}
230
231
	/**
232
	 * @return array
233
	 */
234
	public function getInheritancePath(): array {
235
		return $this->inheritancePath;
236
	}
237
238
239
	/**
240
	 * @param int $inheritanceDepth
241
	 *
242
	 * @return Membership
243
	 */
244
	public function setInheritanceDepth(int $inheritanceDepth): self {
245
		$this->inheritanceDepth = $inheritanceDepth;
246
247
		return $this;
248
	}
249
250
	/**
251
	 * @return int
252
	 */
253
	public function getInheritanceDepth(): int {
254
		return $this->inheritanceDepth;
255
	}
256
257
258
	/**
259
	 * @param array $inheritanceDetails
260
	 *
261
	 * @return Membership
262
	 */
263
	public function setInheritanceDetails(array $inheritanceDetails): self {
264
		$this->inheritanceDetails = $inheritanceDetails;
265
266
		return $this;
267
	}
268
269
	/**
270
	 * @return array
271
	 */
272
	public function getInheritanceDetails(): array {
273
		return $this->inheritanceDetails;
274
	}
275
276
277
	/**
278
	 * @param array $data
279
	 *
280
	 * @return IDeserializable
281
	 * @throws InvalidItemException
282
	 */
283
	public function import(array $data): IDeserializable {
284
		if ($this->get('singleId', $data) === '') {
285
			throw new InvalidItemException();
286
		}
287
288
		$this->setSingleId($this->get('singleId', $data));
289
		$this->setCircleId($this->get('circleId', $data));
290
		$this->setCircleConfig($this->getInt('circleConfig', $data));
291
		$this->setLevel($this->getInt('level', $data));
292
		$this->setInheritanceFirst($this->get('inheritanceFirst', $data));
293
		$this->setInheritanceLast($this->get('inheritanceLast', $data));
294
		$this->setInheritancePath($this->getArray('inheritancePath', $data));
295
		$this->setInheritanceDepth($this->getInt('inheritanceDepth', $data));
296
297
		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...
298
	}
299
300
	/**
301
	 * @param array $data
302
	 * @param string $prefix
303
	 *
304
	 * @return INC22QueryRow
305
	 * @throws MembershipNotFoundException
306
	 */
307
	public function importFromDatabase(array $data, string $prefix = ''): INC22QueryRow {
308
		if ($this->get($prefix . 'single_id', $data) === '') {
309
			throw new MembershipNotFoundException();
310
		}
311
312
		$this->setSingleId($this->get($prefix . 'single_id', $data));
313
		$this->setCircleId($this->get($prefix . 'circle_id', $data));
314
		$this->setLevel($this->getInt($prefix . 'level', $data));
315
		$this->setCircleConfig($this->getInt($prefix . 'circle_config', $data));
316
		$this->setInheritanceFirst($this->get($prefix . 'inheritance_first', $data));
317
		$this->setInheritanceLast($this->get($prefix . 'inheritance_last', $data));
318
		$this->setInheritancePath($this->getArray($prefix . 'inheritance_path', $data));
319
		$this->setInheritanceDepth($this->getInt($prefix . 'inheritance_depth', $data));
320
321
		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...
322
	}
323
324
325
	/**
326
	 * @return array
327
	 */
328
	public function jsonSerialize(): array {
329
		$result = [
330
			'singleId'         => $this->getSingleId(),
331
			'circleId'         => $this->getCircleId(),
332
			'circleConfig'           => $this->getCircleConfig(),
333
			'level'            => $this->getLevel(),
334
			'inheritanceFirst' => $this->getInheritanceFirst(),
335
			'inheritanceLast'  => $this->getInheritanceLast(),
336
			'inheritancePath'  => $this->getInheritancePath(),
337
			'inheritanceDepth' => $this->getInheritanceDepth()
338
		];
339
340
		if (!empty($this->getInheritanceDetails())) {
341
			$result['inheritanceDetails'] = $this->getInheritanceDetails();
342
		}
343
344
		return $result;
345
	}
346
347
}
348
349