Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion phpstan.baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -1986,7 +1986,7 @@ parameters:
-
message: '#^Access to an undefined property SP\\Domain\\Common\\Models\\Simple\:\:\$icon\.$#'
identifier: property.notFound
count: 4
count: 1
path: src/Infrastructure/Adapter/In/Web/Controllers/User/UserViewBase.php

-
Expand Down
23 changes: 10 additions & 13 deletions src/Infrastructure/Adapter/In/Web/Controllers/User/UserViewBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -132,19 +132,16 @@ protected function setViewData(?int $userId = null, bool $isView = false): void
'usage',
array_map(
static function ($value) {
switch ($value->ref) {
case 'Account':
$value->icon = 'description';
break;
case 'UserGroup':
$value->icon = 'group';
break;
case 'PublicLink':
$value->icon = 'link';
break;
default:
$value->icon = 'info_outline';
}
// One assignment rather than one per kind: a kind the map does not know
// still gets an icon, so a row is never rendered without one.
$value->icon = match ($value->ref) {
'Account' => 'description',
'AccountHistory' => 'history',
'Notification' => 'notifications',
'PublicLink' => 'link',
'UserGroup' => 'group',
default => 'info_outline',
};

return $value;
},
Expand Down
68 changes: 67 additions & 1 deletion src/Infrastructure/Adapter/Out/User/Repositories/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@
use Exception;
use JsonException;
use SP\Domain\Account\Models\Account as AccountModel;
use SP\Domain\Account\Models\AccountHistory as AccountHistoryModel;
use SP\Domain\Account\Models\AccountToUser as AccountToUserModel;
use SP\Domain\Account\Models\PublicLink as PublicLinkModel;
use SP\Domain\Client\Models\Client as ClientModel;
use SP\Domain\Notification\Models\Notification as NotificationModel;
use SP\Domain\Common\Models\Simple;
use SP\Domain\Core\Dtos\ItemSearchDto;
use SP\Domain\Core\Exceptions\ConstraintException;
Expand Down Expand Up @@ -588,6 +590,19 @@ public function getUserEmailById(array $ids): QueryResult
/**
* Returns the usage of the given user's id
*
* This is what the user view shows as "what would break if this user were removed", so it has
* to cover the relations that actually stop the removal. Six foreign keys reference `User`
* without `ON DELETE`, which is `RESTRICT`: `Account.userId` / `userEditId`,
* `AccountHistory.userId` / `userEditId`, `Notification.userId` and `PublicLink.userId`. Two
* of those — the account history and the notifications — were missing here, so the panel could
* show nothing that blocks a delete while the delete was blocked all the same: having once
* edited an account, or having a single unread notification, is enough. The administrator was
* left with a refusal and a panel that disagreed with it.
*
* The account memberships and group memberships listed alongside them cascade away and do not
* block anything; they are shown because they are still worth knowing about before removing
* somebody.
*
* @param int $id
*
* @return QueryResult<Simple>
Expand Down Expand Up @@ -691,11 +706,62 @@ public function getUsageForUser(int $id): QueryResult
),
'"PublicLink" AS ref'
]
)
// One row per account rather than per revision: the history keeps a row for
// every change ever made, and an account edited fifty times would otherwise
// fill the panel with fifty identical-looking entries. The name is taken from
// one of the recorded revisions, which is why it is aggregated — the account
// may have been renamed since, and may not exist at all any more.
->unionAll()
->from(AccountHistoryModel::TABLE)
->innerJoin(
ClientModel::TABLE,
sprintf('%s.id = %s.clientId', ClientModel::TABLE, AccountHistoryModel::TABLE)
)
->where(
sprintf(
'%s.userId = :userId5 OR %s.userEditId = :userEditId2',
AccountHistoryModel::TABLE,
AccountHistoryModel::TABLE
)
)
->groupBy([sprintf('%s.accountId', AccountHistoryModel::TABLE)])
->cols(
[
sprintf('%s.accountId as id', AccountHistoryModel::TABLE),
sprintf(
'CONCAT(MAX(%s.name), "(", MAX(%s.name), ")") AS name',
AccountHistoryModel::TABLE,
ClientModel::TABLE
),
'"AccountHistory" AS ref'
]
)
->unionAll()
->from(NotificationModel::TABLE)
->where(sprintf('%s.userId = :userId6', NotificationModel::TABLE))
->cols(
[
sprintf('%s.id as id', NotificationModel::TABLE),
sprintf('%s.component AS name', NotificationModel::TABLE),
'"Notification" AS ref'
]
),
'Items'
)
->orderBy(['Items.ref'])
->bindValues(['userId1' => $id, 'userEditId' => $id, 'userId2' => $id, 'userId3' => $id, 'userId4' => $id]);
->bindValues(
[
'userId1' => $id,
'userEditId' => $id,
'userId2' => $id,
'userId3' => $id,
'userId4' => $id,
'userId5' => $id,
'userEditId2' => $id,
'userId6' => $id,
]
);

return $this->db->runQuery(QueryData::build($query));
}
Expand Down
Loading