Passed
Push — feature/1061-random-view ( afd67b...1c2ae7 )
by Pauli
03:33
created

BaseMapper   C

Complexity

Total Complexity 54

Size/Duplication

Total Lines 428
Duplicated Lines 0 %

Importance

Changes 4
Bugs 0 Features 0
Metric Value
eloc 152
c 4
b 0
f 0
dl 0
loc 428
rs 6.4799
wmc 54

27 Methods

Rating   Name   Duplication   Size   Complexity  
A findById() 0 12 2
A createEntity() 0 2 1
A __construct() 0 5 1
A find() 0 3 1
A exists() 0 4 1
A findAllStarred() 0 5 1
A selectEntities() 0 2 1
A findAllIds() 0 5 1
A selectUserEntities() 0 8 2
A questionMarks() 0 6 2
A insertOrUpdate() 0 8 2
A deleteByCond() 0 3 1
A findAllUsers() 0 5 1
A insert() 0 16 4
A count() 0 5 1
A deleteById() 0 6 2
A deleteAll() 0 3 1
A updateOrInsert() 0 13 3
A update() 0 4 1
A setStarredDate() 0 10 2
A latestUpdateTime() 0 6 2
A formatTimestampConditions() 0 25 5
A findAll() 0 7 1
A findAllByName() 0 30 5
A latestInsertTime() 0 6 2
A prepareSubstringSearchPattern() 0 14 3
A formatSortingClause() 0 9 5

How to fix   Complexity   

Complex Class

Complex classes like BaseMapper often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use BaseMapper, and based on these observations, apply Extract Interface, too.

1
<?php declare(strict_types=1);
2
3
/**
4
 * ownCloud - Music app
5
 *
6
 * This file is licensed under the Affero General Public License version 3 or
7
 * later. See the COPYING file.
8
 *
9
 * @author Pauli Järvinen <[email protected]>
10
 * @copyright Pauli Järvinen 2016 - 2023
11
 */
12
13
namespace OCA\Music\Db;
14
15
use OCP\AppFramework\Db\DoesNotExistException;
16
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
17
use OCP\IDBConnection;
18
19
use OCA\Music\AppFramework\Db\CompatibleMapper;
20
use OCA\Music\AppFramework\Db\UniqueConstraintViolationException;
21
use OCA\Music\Utility\Util;
22
23
/**
24
 * Common base class for data access classes of the Music app
25
 * @phpstan-template EntityType of Entity
26
 * @phpstan-method EntityType findEntity(string $sql, array $params)
27
 * @phpstan-method EntityType[] findEntities(string $sql, array $params, ?int $limit=null, ?int $offset=null)
28
 */
29
abstract class BaseMapper extends CompatibleMapper {
0 ignored issues
show
Deprecated Code introduced by
The class OCA\Music\AppFramework\Db\OldNextcloudMapper has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

29
abstract class BaseMapper extends /** @scrutinizer ignore-deprecated */ CompatibleMapper {
Loading history...
30
	const SQL_DATE_FORMAT = 'Y-m-d H:i:s.v';
31
32
	protected $nameColumn;
33
	/** @phpstan-var class-string<EntityType> $entityClass */
34
	protected $entityClass;
35
36
	/**
37
	 * @phpstan-param class-string<EntityType> $entityClass
38
	 */
39
	public function __construct(IDBConnection $db, string $tableName, string $entityClass, string $nameColumn) {
40
		parent::__construct($db, $tableName, $entityClass);
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...udMapper::__construct() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

40
		/** @scrutinizer ignore-deprecated */ parent::__construct($db, $tableName, $entityClass);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
41
		$this->nameColumn = $nameColumn;
42
		// eclipse the base class property to help phpstan
43
		$this->entityClass = $entityClass;
44
	}
45
46
	/**
47
	 * Create an empty object of the entity class bound to this mapper
48
	 * @phpstan-return EntityType
49
	 */
50
	public function createEntity() : Entity {
51
		return new $this->entityClass();
52
	}
53
54
	/**
55
	 * Find a single entity by id and user_id
56
	 * @throws DoesNotExistException if the entity does not exist
57
	 * @throws MultipleObjectsReturnedException if more than one entity exists
58
	 * @phpstan-return EntityType
59
	 */
60
	public function find(int $id, string $userId) : Entity {
61
		$sql = $this->selectUserEntities("`{$this->getTableName()}`.`id` = ?");
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

61
		$sql = $this->selectUserEntities("`{/** @scrutinizer ignore-deprecated */ $this->getTableName()}`.`id` = ?");

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
62
		return $this->findEntity($sql, [$userId, $id]);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->findEntity...l, array($userId, $id)) returns the type OCP\AppFramework\Db\Entity which includes types incompatible with the type-hinted return OCA\Music\Db\Entity.
Loading history...
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...oudMapper::findEntity() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

62
		return /** @scrutinizer ignore-deprecated */ $this->findEntity($sql, [$userId, $id]);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
63
	}
64
65
	/**
66
	 * Find all entities matching the given IDs. Specifying the owning user is optional.
67
	 * @param integer[] $ids  IDs of the entities to be found
68
	 * @param string|null $userId
69
	 * @return Entity[]
70
	 * @phpstan-return EntityType[]
71
	 */
72
	public function findById(array $ids, string $userId=null) : array {
73
		$count = \count($ids);
74
		$condition = "`{$this->getTableName()}`.`id` IN ". $this->questionMarks($count);
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

74
		$condition = "`{/** @scrutinizer ignore-deprecated */ $this->getTableName()}`.`id` IN ". $this->questionMarks($count);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
75
76
		if (empty($userId)) {
77
			$sql = $this->selectEntities($condition);
78
		} else {
79
			$sql = $this->selectUserEntities($condition);
80
			$ids = \array_merge([$userId], $ids);
81
		}
82
83
		return $this->findEntities($sql, $ids);
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::findEntities() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

83
		return /** @scrutinizer ignore-deprecated */ $this->findEntities($sql, $ids);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
84
	}
85
86
	/**
87
	 * Find all user's entities
88
	 * @param string|null $createdMin Optional minimum `created` timestamp.
89
	 * @param string|null $createdMax Optional maximum `created` timestamp.
90
	 * @param string|null $updatedMin Optional minimum `updated` timestamp.
91
	 * @param string|null $updatedMax Optional maximum `updated` timestamp.
92
	 * @return Entity[]
93
	 * @phpstan-return EntityType[]
94
	 */
95
	public function findAll(string $userId, int $sortBy=SortBy::None, int $limit=null, int $offset=null,
96
							?string $createdMin=null, ?string $createdMax=null, ?string $updatedMin=null, ?string $updatedMax=null) : array {
97
		$sorting = $this->formatSortingClause($sortBy);
98
		[$condition, $params] = $this->formatTimestampConditions($createdMin, $createdMax, $updatedMin, $updatedMax);
99
		$sql = $this->selectUserEntities($condition, $sorting);
100
		\array_unshift($params, $userId);
101
		return $this->findEntities($sql, $params, $limit, $offset);
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::findEntities() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

101
		return /** @scrutinizer ignore-deprecated */ $this->findEntities($sql, $params, $limit, $offset);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
102
	}
103
104
	/**
105
	 * Find all user's entities matching the given name
106
	 * @param string|null $createdMin Optional minimum `created` timestamp.
107
	 * @param string|null $createdMax Optional maximum `created` timestamp.
108
	 * @param string|null $updatedMin Optional minimum `updated` timestamp.
109
	 * @param string|null $updatedMax Optional maximum `updated` timestamp.
110
	 * @return Entity[]
111
	 * @phpstan-return EntityType[]
112
	 */
113
	public function findAllByName(
114
		?string $name, string $userId, int $matchMode=MatchMode::Exact, int $limit=null, int $offset=null,
115
		?string $createdMin=null, ?string $createdMax=null, ?string $updatedMin=null, ?string $updatedMax=null) : array {
116
117
		$params = [$userId];
118
		$nameCol = "`{$this->getTableName()}`.`{$this->nameColumn}`";
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

118
		$nameCol = "`{/** @scrutinizer ignore-deprecated */ $this->getTableName()}`.`{$this->nameColumn}`";

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
119
		if ($name === null) {
120
			$condition = "$nameCol IS NULL";
121
		} else {
122
			if ($matchMode === MatchMode::Exact) {
123
				$condition = "LOWER($nameCol) = LOWER(?)";
124
			} else {
125
				$condition = "LOWER($nameCol) LIKE LOWER(?)";
126
			}
127
			if ($matchMode === MatchMode::Substring) {
128
				$params[] = self::prepareSubstringSearchPattern($name);
129
			} else {
130
				$params[] = $name;
131
			}
132
		}
133
134
		[$timestampConds, $timestampParams] = $this->formatTimestampConditions($createdMin, $createdMax, $updatedMin, $updatedMax);
135
		if (!empty($timestampConds)) {
136
			$condition .= ' AND ' . $timestampConds;
137
			$params = \array_merge($params, $timestampParams);
138
		}
139
140
		$sql = $this->selectUserEntities($condition, "ORDER BY LOWER($nameCol)");
141
142
		return $this->findEntities($sql, $params, $limit, $offset);
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::findEntities() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

142
		return /** @scrutinizer ignore-deprecated */ $this->findEntities($sql, $params, $limit, $offset);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
143
	}
144
145
	/**
146
	 * Find all user's starred entities
147
	 * @return Entity[]
148
	 * @phpstan-return EntityType[]
149
	 */
150
	public function findAllStarred(string $userId, int $limit=null, int $offset=null) : array {
151
		$sql = $this->selectUserEntities(
152
				"`{$this->getTableName()}`.`starred` IS NOT NULL",
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

152
				"`{/** @scrutinizer ignore-deprecated */ $this->getTableName()}`.`starred` IS NOT NULL",

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
153
				"ORDER BY LOWER(`{$this->getTableName()}`.`{$this->nameColumn}`)");
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

153
				"ORDER BY LOWER(`{/** @scrutinizer ignore-deprecated */ $this->getTableName()}`.`{$this->nameColumn}`)");

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
154
		return $this->findEntities($sql, [$userId], $limit, $offset);
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::findEntities() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

154
		return /** @scrutinizer ignore-deprecated */ $this->findEntities($sql, [$userId], $limit, $offset);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
155
	}
156
157
	/**
158
	 * Find IDs of all user's entities of this kind
159
	 * @return int[]
160
	 */
161
	public function findAllIds(string $userId) : array {
162
		$sql = "SELECT `id` FROM `{$this->getTableName()}` WHERE `user_id` = ?";
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

162
		$sql = "SELECT `id` FROM `{/** @scrutinizer ignore-deprecated */ $this->getTableName()}` WHERE `user_id` = ?";

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
163
		$result = $this->execute($sql, [$userId]);
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...tcloudMapper::execute() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

163
		$result = /** @scrutinizer ignore-deprecated */ $this->execute($sql, [$userId]);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
164
165
		return \array_map('intval', $result->fetchAll(\PDO::FETCH_COLUMN));
166
	}
167
168
	/**
169
	 * Find IDs of all users owning any entities of this mapper
170
	 * @return string[]
171
	 */
172
	public function findAllUsers() : array {
173
		$sql = "SELECT DISTINCT(`user_id`) FROM `{$this->getTableName()}`";
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

173
		$sql = "SELECT DISTINCT(`user_id`) FROM `{/** @scrutinizer ignore-deprecated */ $this->getTableName()}`";

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
174
		$result = $this->execute($sql);
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...tcloudMapper::execute() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

174
		$result = /** @scrutinizer ignore-deprecated */ $this->execute($sql);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
175
176
		return $result->fetchAll(\PDO::FETCH_COLUMN);
177
	}
178
179
	/**
180
	 * Delete all entities with given IDs without specifying the user
181
	 * @param integer[] $ids  IDs of the entities to be deleted
182
	 */
183
	public function deleteById(array $ids) : void {
184
		$count = \count($ids);
185
		if ($count === 0) {
186
			return;
187
		}
188
		$this->deleteByCond('`id` IN ' . $this->questionMarks($count), $ids);
189
	}
190
191
	/**
192
	 * Delete all entities matching the given SQL condition
193
	 * @param string $condition SQL 'WHERE' condition (without the keyword 'WHERE')
194
	 * @param array $params SQL parameters for the condition
195
	 */
196
	protected function deleteByCond(string $condition, array $params) : void {
197
		$sql = "DELETE FROM `{$this->getTableName()}` WHERE ". $condition;
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

197
		$sql = "DELETE FROM `{/** @scrutinizer ignore-deprecated */ $this->getTableName()}` WHERE ". $condition;

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
198
		$this->execute($sql, $params);
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...tcloudMapper::execute() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

198
		/** @scrutinizer ignore-deprecated */ $this->execute($sql, $params);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
199
	}
200
201
	/**
202
	 * Delete all entities of the given user
203
	 */
204
	public function deleteAll(string $userId) : void {
205
		$sql = "DELETE FROM `{$this->getTableName()}` WHERE `user_id` = ?";
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

205
		$sql = "DELETE FROM `{/** @scrutinizer ignore-deprecated */ $this->getTableName()}` WHERE `user_id` = ?";

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
206
		$this->execute($sql, [$userId]);
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...tcloudMapper::execute() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

206
		/** @scrutinizer ignore-deprecated */ $this->execute($sql, [$userId]);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
207
	}
208
209
	/**
210
	 * Tests if entity with given ID and user ID exists in the database
211
	 */
212
	public function exists(int $id, string $userId) : bool {
213
		$sql = "SELECT 1 FROM `{$this->getTableName()}` WHERE `id` = ? AND `user_id` = ?";
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

213
		$sql = "SELECT 1 FROM `{/** @scrutinizer ignore-deprecated */ $this->getTableName()}` WHERE `id` = ? AND `user_id` = ?";

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
214
		$result = $this->execute($sql, [$id, $userId]);
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...tcloudMapper::execute() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

214
		$result = /** @scrutinizer ignore-deprecated */ $this->execute($sql, [$id, $userId]);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
215
		return $result->rowCount() > 0;
216
	}
217
218
	/**
219
	 * Count all entities of a user
220
	 */
221
	public function count(string $userId) : int {
222
		$sql = "SELECT COUNT(*) AS count FROM `{$this->getTableName()}` WHERE `user_id` = ?";
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

222
		$sql = "SELECT COUNT(*) AS count FROM `{/** @scrutinizer ignore-deprecated */ $this->getTableName()}` WHERE `user_id` = ?";

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
223
		$result = $this->execute($sql, [$userId]);
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...tcloudMapper::execute() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

223
		$result = /** @scrutinizer ignore-deprecated */ $this->execute($sql, [$userId]);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
224
		$row = $result->fetch();
225
		return \intval($row['count']);
226
	}
227
228
	/**
229
	 * {@inheritDoc}
230
	 * @see CompatibleMapper::insert()
231
	 * @phpstan-param EntityType $entity
232
	 * @phpstan-return EntityType
233
	 */
234
	public function insert(\OCP\AppFramework\Db\Entity $entity) : \OCP\AppFramework\Db\Entity {
235
		$now = new \DateTime();
236
		$nowStr = $now->format(self::SQL_DATE_FORMAT);
237
		$entity->setCreated($nowStr);
238
		$entity->setUpdated($nowStr);
239
240
		try {
241
			return parent::insert($entity); // @phpstan-ignore-line: no way to tell phpstan that the parent uses the template type
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...xtcloudMapper::insert() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

241
			return /** @scrutinizer ignore-deprecated */ parent::insert($entity); // @phpstan-ignore-line: no way to tell phpstan that the parent uses the template type

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
242
		} catch (\Doctrine\DBAL\Exception\UniqueConstraintViolationException $e) {
243
			throw new UniqueConstraintViolationException($e->getMessage(), $e->getCode(), $e);
244
		} catch (\OCP\DB\Exception $e) {
245
			// Nextcloud 21+
246
			if ($e->getReason() == \OCP\DB\Exception::REASON_UNIQUE_CONSTRAINT_VIOLATION) {
247
				throw new UniqueConstraintViolationException($e->getMessage(), $e->getCode(), $e);
248
			} else {
249
				throw $e;
250
			}
251
		}
252
	}
253
254
	/**
255
	 * {@inheritDoc}
256
	 * @see CompatibleMapper::update()
257
	 * @phpstan-param EntityType $entity
258
	 * @phpstan-return EntityType
259
	 */
260
	public function update(\OCP\AppFramework\Db\Entity $entity) : \OCP\AppFramework\Db\Entity {
261
		$now = new \DateTime();
262
		$entity->setUpdated($now->format(self::SQL_DATE_FORMAT));
263
		return parent::update($entity); // @phpstan-ignore-line: no way to tell phpstan that the parent uses the template type
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...xtcloudMapper::update() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

263
		return /** @scrutinizer ignore-deprecated */ parent::update($entity); // @phpstan-ignore-line: no way to tell phpstan that the parent uses the template type

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
264
	}
265
266
	/**
267
	 * Insert an entity, or if an entity with the same identity already exists,
268
	 * update the existing entity.
269
	 * Note: The functions insertOrUpate and updateOrInsert get the exactly same thing done. The only difference is
270
	 * that the former is optimized for cases where the entity doens't exist and the latter for cases where it does exist.
271
	 * @return Entity The inserted or updated entity, containing also the id field
272
	 * @phpstan-param EntityType $entity
273
	 * @phpstan-return EntityType
274
	 */
275
	public function insertOrUpdate(Entity $entity) : Entity {
276
		try {
277
			return $this->insert($entity);
278
		} catch (UniqueConstraintViolationException $ex) {
279
			$existingEntity = $this->findUniqueEntity($entity);
280
			$entity->setId($existingEntity->getId());
281
			$entity->setCreated($existingEntity->getCreated());
282
			return $this->update($entity);
283
		}
284
	}
285
286
	/**
287
	 * Update an entity whose unique constraint fields match the given entity. If such entity is not found,
288
	 * a new entity is inserted.
289
	 * Note: The functions insertOrUpate and updateOrInsert get the exactly same thing done. The only difference is
290
	 * that the former is optimized for cases where the entity doens't exist and the latter for cases where it does exist.
291
	 * @return Entity The inserted or updated entity, containing also the id field
292
	 * @phpstan-param EntityType $entity
293
	 * @phpstan-return EntityType
294
	 */
295
	public function updateOrInsert(Entity $entity) : Entity {
296
		try {
297
			$existingEntity = $this->findUniqueEntity($entity);
298
			$entity->setId($existingEntity->getId());
299
			return $this->update($entity);
300
		} catch (DoesNotExistException $ex) {
301
			try {
302
				return $this->insert($entity);
303
			} catch (UniqueConstraintViolationException $ex) {
304
				// the conflicting entry didn't exist an eyeblink ago but now it does
305
				// => this is essentially a concurrent update and it is anyway non-deterministic, which
306
				//    update happens last; cancel this update
307
				return $this->findUniqueEntity($entity);
308
			}
309
		}
310
	}
311
312
	/**
313
	 * Set the "starred" column of the given entities
314
	 * @param \DateTime|null $date
315
	 * @param integer[] $ids
316
	 * @param string $userId
317
	 * @return int number of modified entities
318
	 */
319
	public function setStarredDate(?\DateTime $date, array $ids, string $userId) : int {
320
		$count = \count($ids);
321
		if (!empty($date)) {
322
			$date = $date->format(self::SQL_DATE_FORMAT);
323
		}
324
325
		$sql = "UPDATE `{$this->getTableName()}` SET `starred` = ?
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

325
		$sql = "UPDATE `{/** @scrutinizer ignore-deprecated */ $this->getTableName()}` SET `starred` = ?

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
326
				WHERE `id` IN {$this->questionMarks($count)} AND `user_id` = ?";
327
		$params = \array_merge([$date], $ids, [$userId]);
328
		return $this->execute($sql, $params)->rowCount();
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...tcloudMapper::execute() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

328
		return /** @scrutinizer ignore-deprecated */ $this->execute($sql, $params)->rowCount();

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
329
	}
330
331
	public function latestInsertTime(string $userId) : ?\DateTime {
332
		$sql = "SELECT MAX(`{$this->getTableName()}`.`created`) FROM `{$this->getTableName()}` WHERE `user_id` = ?";
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

332
		$sql = "SELECT MAX(`{/** @scrutinizer ignore-deprecated */ $this->getTableName()}`.`created`) FROM `{$this->getTableName()}` WHERE `user_id` = ?";

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
333
		$result = $this->execute($sql, [$userId]);
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...tcloudMapper::execute() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

333
		$result = /** @scrutinizer ignore-deprecated */ $this->execute($sql, [$userId]);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
334
		$createdTime = $result->fetch(\PDO::FETCH_COLUMN);
335
336
		return ($createdTime === null) ? null : new \DateTime($createdTime);
337
	}
338
339
	public function latestUpdateTime(string $userId) : ?\DateTime {
340
		$sql = "SELECT MAX(`{$this->getTableName()}`.`updated`) FROM `{$this->getTableName()}` WHERE `user_id` = ?";
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

340
		$sql = "SELECT MAX(`{$this->getTableName()}`.`updated`) FROM `{/** @scrutinizer ignore-deprecated */ $this->getTableName()}` WHERE `user_id` = ?";

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
341
		$result = $this->execute($sql, [$userId]);
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...tcloudMapper::execute() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

341
		$result = /** @scrutinizer ignore-deprecated */ $this->execute($sql, [$userId]);

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
342
		$createdTime = $result->fetch(\PDO::FETCH_COLUMN);
343
344
		return ($createdTime === null) ? null : new \DateTime($createdTime);
345
	}
346
347
	/**
348
	 * helper creating a string like '(?,?,?)' with the specified number of elements
349
	 */
350
	protected function questionMarks(int $count) : string {
351
		$questionMarks = [];
352
		for ($i = 0; $i < $count; $i++) {
353
			$questionMarks[] = '?';
354
		}
355
		return '(' . \implode(',', $questionMarks) . ')';
356
	}
357
358
	/**
359
	 * Build a SQL SELECT statement which selects all entities of the given user,
360
	 * and optionally applies other conditions, too.
361
	 * This is built upon `selectEntities` which may be overridden by the derived class.
362
	 * @param string|null $condition Optional extra condition. This will get automatically
363
	 *                               prefixed with ' AND ', so don't include that.
364
	 * @param string|null $extension Any extension (e.g. ORDER BY, LIMIT) to be added after
365
	 *                               the conditions in the SQL statement
366
	 */
367
	protected function selectUserEntities(string $condition=null, string $extension=null) : string {
368
		$allConditions = "`{$this->getTableName()}`.`user_id` = ?";
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

368
		$allConditions = "`{/** @scrutinizer ignore-deprecated */ $this->getTableName()}`.`user_id` = ?";

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
369
370
		if (!empty($condition)) {
371
			$allConditions .= " AND $condition";
372
		}
373
374
		return $this->selectEntities($allConditions, $extension);
375
	}
376
377
	/**
378
	 * Build a SQL SELECT statement which selects all entities matching the given condition.
379
	 * The derived class may override this if necessary.
380
	 * @param string $condition This will get automatically prefixed with ' WHERE '
381
	 * @param string|null $extension Any extension (e.g. ORDER BY, LIMIT) to be added after
382
	 *                               the conditions in the SQL statement
383
	 */
384
	protected function selectEntities(string $condition, string $extension=null) : string {
385
		return "SELECT * FROM `{$this->getTableName()}` WHERE $condition $extension ";
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

385
		return "SELECT * FROM `{/** @scrutinizer ignore-deprecated */ $this->getTableName()}` WHERE $condition $extension ";

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
386
	}
387
388
	/**
389
	 * @return array with two values: The SQL condition as string and the SQL parameters as string[]
390
	 */
391
	protected function formatTimestampConditions(?string $createdMin, ?string $createdMax, ?string $updatedMin, ?string $updatedMax) : array {
392
		$conditions = [];
393
		$params = [];
394
395
		if (!empty($createdMin)) {
396
			$conditions[] = "`{$this->getTableName()}`.`created` >= ?";
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

396
			$conditions[] = "`{/** @scrutinizer ignore-deprecated */ $this->getTableName()}`.`created` >= ?";

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
397
			$params[] = $createdMin;
398
		}
399
400
		if (!empty($createdMax)) {
401
			$conditions[] = "`{$this->getTableName()}`.`created` <= ?";
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

401
			$conditions[] = "`{/** @scrutinizer ignore-deprecated */ $this->getTableName()}`.`created` <= ?";

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
402
			$params[] = $createdMax;
403
		}
404
405
		if (!empty($updatedMin)) {
406
			$conditions[] = "`{$this->getTableName()}`.`updated` >= ?";
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

406
			$conditions[] = "`{/** @scrutinizer ignore-deprecated */ $this->getTableName()}`.`updated` >= ?";

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
407
			$params[] = $updatedMin;
408
		}
409
410
		if (!empty($updatedMax)) {
411
			$conditions[] = "`{$this->getTableName()}`.`updated` <= ?";
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

411
			$conditions[] = "`{/** @scrutinizer ignore-deprecated */ $this->getTableName()}`.`updated` <= ?";

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
412
			$params[] = $updatedMax;
413
		}
414
415
		return [\implode(' AND ', $conditions), $params];
416
	}
417
418
	/**
419
	 * Convert given sorting condition to an SQL clause. Derived class may overide this if necessary.
420
	 * @param int $sortBy One of the constants defined in the class SortBy
421
	 */
422
	protected function formatSortingClause(int $sortBy, bool $invertSort = false) : ?string {
423
		if ($sortBy == SortBy::Name) {
424
			$dir = $invertSort ? 'DESC' : 'ASC';
425
			return "ORDER BY LOWER(`{$this->getTableName()}`.`{$this->nameColumn}`) $dir";
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

425
			return "ORDER BY LOWER(`{/** @scrutinizer ignore-deprecated */ $this->getTableName()}`.`{$this->nameColumn}`) $dir";

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
426
		} elseif ($sortBy == SortBy::Newest) {
427
			$dir = $invertSort ? 'ASC' : 'DESC';
428
			return "ORDER BY `{$this->getTableName()}`.`id` $dir"; // abuse the fact that IDs are ever-incrementing values
0 ignored issues
show
Deprecated Code introduced by
The function OCA\Music\AppFramework\D...dMapper::getTableName() has been deprecated: 14.0.0 Move over to QBMapper ( Ignorable by Annotation )

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

428
			return "ORDER BY `{/** @scrutinizer ignore-deprecated */ $this->getTableName()}`.`id` $dir"; // abuse the fact that IDs are ever-incrementing values

This function has been deprecated. The supplier of the function has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the function will be removed and what other function to use instead.

Loading history...
429
		} else {
430
			return null;
431
		}
432
	}
433
434
	protected static function prepareSubstringSearchPattern(string $input) : string {
435
		// possibly multiparted query enclosed in quotation marks is handled as a single substring,
436
		// while the default interpretation of multipart string is that each of the parts can be found
437
		// separately as substring in the given order
438
		if (Util::startsWith($input, '"') && Util::endsWith($input, '"')) {
439
			// remove the quotation
440
			$pattern = \substr($input, 1, -1);
441
		} else {
442
			// split to parts by whitespace
443
			$parts = \preg_split('/\s+/', $input, -1, PREG_SPLIT_NO_EMPTY);
444
			// glue the parts back together with a wildcard charater
445
			$pattern = \implode('%', $parts);
446
		}
447
		return "%$pattern%";
448
	}
449
450
	/**
451
	 * Find an entity which has the same identity as the supplied entity.
452
	 * How the identity of the entity is defined, depends on the derived concrete class.
453
	 * @phpstan-param EntityType $entity
454
	 * @phpstan-return EntityType
455
	 */
456
	abstract protected function findUniqueEntity(Entity $entity) : Entity;
457
}
458