Skip to content

Commit

Permalink
Merge pull request #1133 from Daniel-KM/feature/batch_edit_user
Browse files Browse the repository at this point in the history
Feature/batch edit user
  • Loading branch information
zerocrates authored Sep 14, 2018
2 parents 9248fb0 + 29cc959 commit 3c98452
Show file tree
Hide file tree
Showing 26 changed files with 1,143 additions and 86 deletions.
98 changes: 98 additions & 0 deletions application/Module.php
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,12 @@ function (ZendEvent $event) {
},
2
);

$sharedEventManager->attach(
\Omeka\Api\Adapter\UserAdapter::class,
'api.batch_update.post',
[$this, 'batchUpdatePostUser']
);
}

/**
Expand Down Expand Up @@ -345,4 +351,96 @@ public function filterSites(ZendEvent $event)
}
$qb->andWhere($expression);
}

public function batchUpdatePostUser(ZendEvent $event)
{
$response = $event->getParam('response');
$data = $response->getRequest()->getContent();
if (!empty($data['remove_from_site_permission'])) {
$siteIds = $data['remove_from_site_permission'];
$collectionAction = 'remove';
$role = null;
} elseif (!empty($data['add_to_site_permission'])) {
$siteIds = $data['add_to_site_permission'];
$collectionAction = 'append';
$role = empty($data['add_to_site_permission_role'])
? 'viewer'
: $data['add_to_site_permission_role'];
} else {
return;
}

$api = $this->getServiceLocator()->get('Omeka\ApiManager');
if (in_array(-1, $siteIds)) {
$siteIds = $api->search('sites', [], ['responseContent' => 'resource'])->getContent();
}
if (empty($siteIds)) {
return;
}

// The site adapter doesn't manage partial remove/append of users,
// (collectionAction), so fetch all users first for each site directly.
// Nevertheless, use the standard api next in order to trigger api
// events of Site.
// TODO Replace $fileData by $relatedData in ApiManager, so any related
// entity will be able to be updated with the main entity.
$userIds = array_intersect_key($response->getRequest()->getIds(), $response->getContent());
foreach ($siteIds as $siteId) {
$site = is_object($siteId)
? $siteId
: $api->read('sites', $siteId, [], ['responseContent' => 'resource'])->getContent();
$sitePermissions = $site->getSitePermissions();
$newSitePermissions = [];
switch ($collectionAction) {
case 'remove':
if (empty($sitePermissions)) {
continue 2;
}
foreach ($sitePermissions as $sitePermission) {
$siteUserId = $sitePermission->getUser()->getId();
if (in_array($siteUserId, $userIds)) {
continue;
}
$newSitePermissions[] = [
'o:user' => ['o:id' => $siteUserId],
'o:role' => $sitePermission->getRole(),
];
}
if (count($sitePermissions) == count($newSitePermissions)) {
continue 2;
}
break;
case 'append':
foreach ($sitePermissions as $sitePermission) {
$siteUserId = $sitePermission->getUser()->getId();
$newSitePermissions[$siteUserId] = [
'o:user' => ['o:id' => $siteUserId],
'o:role' => $sitePermission->getRole(),
];
}
foreach ($userIds as $userId) {
$newSitePermissions[$userId] = [
'o:user' => ['o:id' => $userId],
'o:role' => $role,
];
}
break;
}
$api->update('sites',
$site->getId(),
['o:site_permission' => $newSitePermissions],
[],
[
'isPartial' => true,
'collectionAction' => 'replace',
'flushEntityManager' => false,
'responseContent' => 'resource',
'finalize' => true,
]
);
}

$entityManager = $this->getServiceLocator()->get('Omeka\EntityManager');
$entityManager->flush();
}
}
2 changes: 1 addition & 1 deletion application/asset/css/iconfonts.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion application/asset/css/style.css

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion application/asset/sass/_screen.scss
Original file line number Diff line number Diff line change
Expand Up @@ -1394,7 +1394,8 @@ div[role="main"] {
}
}

td .o-icon-private {
td .o-icon-private,
td .o-icon-user-inactive {
display: inline-block;
vertical-align: bottom;
margin-left: .5em;
Expand Down
3 changes: 2 additions & 1 deletion application/asset/sass/_tablet.scss
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,8 @@ footer {
width: 100%;
}

td .o-icon-private {
td .o-icon-private,
td .o-icon-user-inactive {
vertical-align: top;
margin: 0;
}
Expand Down
4 changes: 4 additions & 0 deletions application/asset/sass/iconfonts.scss
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@
@extend .fa-eye-slash;
}

.o-icon-user-inactive {
@extend .fa-user-times;
}

.o-icon-activate {
@extend .fa-toggle-off;
}
Expand Down
4 changes: 4 additions & 0 deletions application/config/module.config.php
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,8 @@
'resourceClassSelect' => Service\ViewHelper\ResourceClassSelectFactory::class,
'propertySelect' => Service\ViewHelper\PropertySelectFactory::class,
'itemSetSelect' => Service\ViewHelper\ItemSetSelectFactory::class,
'roleSelect' => Service\ViewHelper\RoleSelectFactory::class,
'searchUserFilters' => Service\ViewHelper\SearchUserFiltersFactory::class,
'siteSelect' => Service\ViewHelper\SiteSelectFactory::class,
'resourceSelect' => Service\ViewHelper\ResourceSelectFactory::class,
'jsTranslate' => Service\ViewHelper\JsTranslateFactory::class,
Expand Down Expand Up @@ -450,12 +452,14 @@
'Omeka\Form\ModuleStateChangeForm' => Service\Form\ModuleStateChangeFormFactory::class,
'Omeka\Form\SiteForm' => Service\Form\SiteFormFactory::class,
'Omeka\Form\SiteSettingsForm' => Service\Form\SiteSettingsFormFactory::class,
'Omeka\Form\UserBatchUpdateForm' => Service\Form\UserBatchUpdateFormFactory::class,
'Omeka\Form\Element\ResourceSelect' => Service\Form\Element\ResourceSelectFactory::class,
'Omeka\Form\Element\ResourceClassSelect' => Service\Form\Element\ResourceClassSelectFactory::class,
'Omeka\Form\Element\PropertySelect' => Service\Form\Element\PropertySelectFactory::class,
'Omeka\Form\Element\ItemSetSelect' => Service\Form\Element\ItemSetSelectFactory::class,
'Omeka\Form\Element\SiteSelect' => Service\Form\Element\SiteSelectFactory::class,
'Omeka\Form\Element\LocaleSelect' => Service\Form\Element\LocaleSelectFactory::class,
'Omeka\Form\Element\RoleSelect' => Service\Form\Element\RoleSelectFactory::class,
'Omeka\Form\Element\Recaptcha' => Service\Form\Element\RecaptchaFactory::class,
'Omeka\Form\Element\HtmlTextarea' => Service\Form\Element\HtmlTextareaFactory::class,
'Omeka\Form\Element\Ckeditor' => Service\Form\Element\CkeditorFactory::class,
Expand Down
75 changes: 74 additions & 1 deletion application/src/Api/Adapter/UserAdapter.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,47 @@ public function hydrate(Request $request, EntityInterface $entity,

public function buildQuery(QueryBuilder $qb, array $query)
{
if (isset($query['email'])) {
if (!empty($query['email'])) {
$qb->andWhere($qb->expr()->eq(
"Omeka\Entity\User.email",
$this->createNamedParameter($qb, $query['email']))
);
}

if (!empty($query['name'])) {
$qb->andWhere($qb->expr()->eq(
"Omeka\Entity\User.name",
$this->createNamedParameter($qb, $query['name']))
);
}

if (!empty($query['role'])) {
$qb->andWhere($qb->expr()->eq(
'Omeka\Entity\User.role',
$this->createNamedParameter($qb, $query['role']))
);
}

if (isset($query['is_active']) && is_numeric($query['is_active'])) {
$qb->andWhere($qb->expr()->eq(
'Omeka\Entity\User.isActive',
$this->createNamedParameter($qb, (bool) $query['is_active']))
);
}

if (!empty($query['site_permission_site_id'])) {
$sitePermissionAlias = $this->createAlias();
$qb->innerJoin(
'Omeka\Entity\SitePermission',
$sitePermissionAlias,
'WITH',
$sitePermissionAlias . '.user = ' . $this->getEntityClass()
);
$qb->andWhere($qb->expr()->eq(
"$sitePermissionAlias.site",
$this->createNamedParameter($qb, $query['site_permission_site_id']))
);
}
}

public function validateEntity(EntityInterface $entity, ErrorStore $errorStore)
Expand All @@ -99,6 +134,44 @@ public function validateEntity(EntityInterface $entity, ErrorStore $errorStore)
}
}

public function batchUpdate(Request $request)
{
$this->unsetCurrentUserFromBatch($request);
return parent::batchUpdate($request);
}

public function batchDelete(Request $request)
{
$this->unsetCurrentUserFromBatch($request);
return parent::batchDelete($request);
}

/**
* Remove the current user before a batch process.
*
* @param Request $request
*/
protected function unsetCurrentUserFromBatch(Request $request)
{
$services = $this->getServiceLocator();
$ids = $request->getIds();
$ids = array_filter(array_unique(array_map('intval', $ids)));
$identity = $services->get('ControllerPluginManager')->get('identity');
$userId = $identity()->getId();
$key = array_search($userId, $ids);
if ($key !== false) {
$logger = $services->get('Omeka\Logger');
$logger->warn(
new Message(
'The current user #%d was removed from the batch process.', // @translate
$userId
)
);
unset($ids[$key]);
}
$request->setIds($ids);
}

public function preprocessBatchUpdate(array $data, Request $request)
{
$rawData = $request->getContent();
Expand Down
5 changes: 5 additions & 0 deletions application/src/Api/Representation/UserRepresentation.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ public function role()
return $this->resource->getRole();
}

public function isActive()
{
return $this->resource->isActive();
}

public function created()
{
return $this->resource->getCreated();
Expand Down
Loading

0 comments on commit 3c98452

Please sign in to comment.