mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-11 03:53:13 +00:00

* PHRAS-3602 : migrate validations to baskets WIP [skip ci] * PHRAS-3602 : migrate validations code to baskets code (wip) WIP [skip ci] * PHRAS-3602 : migrate validations to baskets WIP [skip ci] * PHRAS-3602 : migrate validations to baskets WIP [skip ci] * PHRAS-3602 : fake commit to run tests * PHRAS-3602 : migrate validations to baskets fix typo * PHRAS-3602 : migrate validations to baskets fixed (some) tests * PHRAS-3602 : migrate validations to baskets fixed (some) tests * PHRAS-3602 : migrate validations to baskets fixed (some) tests. need to remove method():return_type signature because of old phpunit which does not mock it * PHRAS-3602 : migrate validations to baskets fix * PHRAS-3602 : migrate validations to baskets fix err 500 when a "vote" (feedback) is deployed in wz * PHRAS-3602 : migrate validations to baskets fix missing votes for element+participant fix update vote dates on basket * PHRAS-3602 : ux bump production-client to 34 WIP [skip ci] * PHRAS-3602 : rebase (bump production-client to 37) WIP [skip ci] * PHRAS-3602 : refacto css/twig/templates/... ; replace many png's by fonts WIP [skip ci] * PHRAS-3602 : fix icon / css WIP * PHRAS-3602 : better icon align ; back button color fix : save button after adding a user WIP [skip ci] * PHRAS-3602 : restore sharebasket controller todo : implement modification right ; owner is participant ? WIP [skip ci] * PHRAS-3602 : set "canModifiy" ; cleanup WIP [skip ci] * PHRAS-3602 : respect "can_modify" on shared basket WIP [skip ci] * PHRAS-3602 : fix badge icon bg ; fix button css WIP [skip ci] * PHRAS-3602 : fix css & cleanup WIP [skip ci] * PHRAS-3602 : fix 500 on preview/feedback tab WIP [skip ci] * PHRAS-3602 : fix allow to display dlg without selection * PHRAS-3602 : bump version to 4.1.6-rc1 ; prodclient=38 WIP [skip ci] * PHRAS-3602 : factorize baskets menu (wip) WIP [skip ci] * PHRAS-3602 : modify already shared or feedback basket (general menu) 4th icon on badges (vote != modify) quitshare option (todo back) allow fa-icons in toolbar WIP [skip ci] * PHRAS-3602 : add share end-date (todo:db write) add 4th general toggle button fix badge selection bug fix css badges zone (form position) WIP [skip ci] * PHRAS-3602 : big refacto to use "sharebasket" vocab. fusion "feedback/sharebasket" removed "feedback" adaptative ux: 1 "can_agree" ==> feedback display bump production-client to v50 todo: save shr/fbk end-dates todo: rename "pushXXX" to pushAndShare ? WIP [skip ci] * PHRAS-3602 : share / feedback expiration dates are saved in db date pickers with delta menu better adaptive ux todo: move select general togglers WIP [skip ci] * PHRAS-3602 : revert validation* tables (remove "dead" rename) drop all foreign keys from validation* WIP [skip ci] * PHRAS-3602 : restore deleted fields in validation, regenerate proxies WIP [skip ci] * PHRAS-3602 : fix initiator_id WIP [skip ci] * fix initiator_id-bis * PHRAS-3602 : css for input-text with glued button dynamic load of users-lists (left zone) = less duplicated code fix : users-lists works after refresh WIP [skip ci] * PHRAS-3602 : fix users-lists manager (orange) : go flex ! * PHRAS-3602 : empty dist to ease rebase WIP [skip ci] * PHRAS-3602 : rebase WIP [skip ci] * PHRAS-3602 : new ux for "owner" feedback mode is an independent toggle fix "missing mandatory parameter" WIP [skip ci] * PHRAS-3602 : fix css of owner badge WIP [skip ci] * PHRAS-3602 : fix handling of feedback initiator WIP [skip ci] * PHRAS-3602 : better wss to follow "skins" full roboto removed useless class "with-button" WIP [skip ci] * PHRAS-3602 : fix "a token require a validation" temporary fix 500 due to send email to (null) vote-initiator for simple share todo: send a specific email for simple share WIP [skip ci] * PHRAS-3602 : different emails depending if user can vote or not WIP [skip ci] * PHRAS-3602 : expired shared baskets removed from wz WIP [skip ci] * PHRAS-3602 : fix logic error on last sql WIP [skip ci] * PHRAS-3602 : fix missing shared baskets on wz WIP [skip ci] * PHRAS-3602 : fix blinking of wz/basket detail now only the title:hover displays detail WIP [skip ci] * PHRAS-3602 : rebase WIP [skip ci] * PHRAS-3602 : update basket proxy WIP [skip ci] * PHRAS-3602 : fix forever "unread" basket WIP [skip ci] * PHRAS-3602 : fix display of unread basket ; sync "eye" icon with css change WIP [skip ci] * PHRAS-3602 : "quitshare" action works WIP [skip ci] * PHRAS-3602 : missing dist files WIP [skip ci] * PHRAS-3602 : cleanup & run ci * PHRAS-3602 : disable failing unit test ; remove blue on onread basket * PHRAS-3602 : separate "vote" & "share" emails templates & u-tests * PHRAS-3602 : add 2 icons "stack" to icomoon set WIP [skip ci] * PHRAS-3602 : fix test * PHRAS-3602 : fix test ; add test for simple share email notification * PHRAS-3602 : changed proxy * PHRAS-3602 : colored basket icons WIP [skip ci] * PHRAS-3602 : circle basket icons WIP [skip ci] * PHRAS-3602 : fix wz filters, add "share" filter. todo: fix fr writing (new string) WIP [skip ci] * PHRAS-3602 : fix "share" dichotomy : use "shared" for wz filter WIP [skip ci] * PHRAS-3602 : fix PHRAS-3624 ; PHRAS-3623 ; now adding/removing a user from user list is immediate (no more save button) WIP [skip ci] * PHRAS-3602 : fix PHRAS-3647 ; shared basket are listed in api (for list and related record) * PHRAS-3602 : fix due to failing test * PHRAS-3602 : fix: can load a 1000 users list todo : move slow code to worker * PHRAS-3602 : fix due to failing test * PHRAS-3468 : (fixed in 3602) fix basket content still visible when baskets are hidden (wz-filter) * PHRAS-3602 : add "wip" baskets with notification & lock todo : move slow code from message to worker * PHRAS-3602 : fix tests due to accidental rename * PHRAS-3602 : fix : menu closes when mouse out : bump to 4.1.6-rc3 todo : fast move to another basket makes the menu appear on top ? * add shareBasket worker * fix test * PHRAS-3602 : fix : rights buttons on badges now works for users added from search (did work only from loading list) * PHRAS-3590 Co-authored-by: aynsix <asr@esokia-webagency.com> Co-authored-by: Nicolas Maillat <maillat@alchemy.fr>
877 lines
29 KiB
PHP
877 lines
29 KiB
PHP
<?php
|
|
/*
|
|
* This file is part of Phraseanet
|
|
*
|
|
* (c) 2005-2016 Alchemy
|
|
*
|
|
* For the full copyright and license information, please view the LICENSE
|
|
* file that was distributed with this source code.
|
|
*/
|
|
namespace Alchemy\Phrasea\Controller\Prod;
|
|
|
|
use ACL;
|
|
use Alchemy\Phrasea\Application\Helper\DataboxLoggerAware;
|
|
use Alchemy\Phrasea\Application\Helper\DispatcherAware;
|
|
use Alchemy\Phrasea\Application\Helper\EntityManagerAware;
|
|
use Alchemy\Phrasea\Application\Helper\UserQueryAware;
|
|
use Alchemy\Phrasea\Controller\Controller;
|
|
use Alchemy\Phrasea\Controller\Exception as ControllerException;
|
|
use Alchemy\Phrasea\Core\Event\PushEvent;
|
|
use Alchemy\Phrasea\Core\Event\ShareEvent;
|
|
use Alchemy\Phrasea\Core\PhraseaEvents;
|
|
use Alchemy\Phrasea\Helper\Record as RecordHelper;
|
|
use Alchemy\Phrasea\Model\Entities\Basket;
|
|
use Alchemy\Phrasea\Model\Entities\BasketElement;
|
|
use Alchemy\Phrasea\Model\Entities\BasketParticipant;
|
|
use Alchemy\Phrasea\Model\Entities\User;
|
|
use Alchemy\Phrasea\Model\Entities\UsrList;
|
|
use Alchemy\Phrasea\Model\Manipulator\TokenManipulator;
|
|
use Alchemy\Phrasea\Model\Manipulator\UserManipulator;
|
|
use Alchemy\Phrasea\Model\Repositories\BasketRepository;
|
|
use Alchemy\Phrasea\Model\Repositories\TokenRepository;
|
|
use Alchemy\Phrasea\Model\Repositories\UserRepository;
|
|
use Alchemy\Phrasea\Model\Repositories\UsrListRepository;
|
|
use DateTime;
|
|
use Doctrine\Common\Collections\ArrayCollection;
|
|
use Exception;
|
|
use RandomLib\Generator;
|
|
use record_adapter;
|
|
use Session_Logger;
|
|
use Swift_Validate;
|
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
use User_Query;
|
|
|
|
class PushController extends Controller
|
|
{
|
|
use DataboxLoggerAware;
|
|
use DispatcherAware;
|
|
use EntityManagerAware;
|
|
use UserQueryAware;
|
|
|
|
public function postFormAction(Request $request)
|
|
{
|
|
return $this->renderPushTemplate($request, 'Push');
|
|
}
|
|
|
|
public function sharebasketFormAction(Request $request)
|
|
{
|
|
return $this->renderPushTemplate($request, 'Sharebasket');
|
|
}
|
|
|
|
|
|
/** ----------------------------------------------------------------------------------
|
|
* a simple push is made by the current user to many "receivers" (=participants)
|
|
*
|
|
* this is the same code as "validation" request, except here we don't create a validation session
|
|
*
|
|
*
|
|
* @param Request $request
|
|
* @return JsonResponse
|
|
*/
|
|
public function sendAction(Request $request)
|
|
{
|
|
$ret = [
|
|
'success' => false,
|
|
'message' => $this->app->trans('Unable to send the documents')
|
|
];
|
|
|
|
try {
|
|
$pusher = new RecordHelper\Push($this->app, $request);
|
|
|
|
$push_name = $request->request->get(
|
|
'name',
|
|
$this->app->trans('Push from %user%', [
|
|
'%user%' => $this->getAuthenticatedUser()->getDisplayName(),
|
|
])
|
|
);
|
|
$push_description = $request->request->get('push_description');
|
|
|
|
$receivers = $request->request->get('participants');
|
|
|
|
if (!is_array($receivers) || empty($receivers)) {
|
|
throw new ControllerException($this->app->trans('No receivers specified'));
|
|
}
|
|
|
|
if (!is_array($pusher->get_elements()) || empty($pusher->get_elements())) {
|
|
throw new ControllerException($this->app->trans('No elements to push'));
|
|
}
|
|
|
|
$manager = $this->getEntityManager();
|
|
foreach ($receivers as $receiver) {
|
|
try {
|
|
/** @var User $user_receiver */
|
|
$user_receiver = $this->getUserRepository()->find($receiver['usr_id']);
|
|
} catch (Exception $e) {
|
|
throw new ControllerException(
|
|
$this->app->trans('Unknown user %user_id%', ['%user_id%' => $receiver['usr_id']])
|
|
);
|
|
}
|
|
|
|
$Basket = new Basket();
|
|
$Basket->setName($push_name);
|
|
$Basket->setDescription($push_description);
|
|
$Basket->setUser($user_receiver);
|
|
$Basket->setPusher($this->getAuthenticatedUser());
|
|
$Basket->markUnread();
|
|
|
|
$manager->persist($Basket);
|
|
|
|
foreach ($pusher->get_elements() as $element) {
|
|
$basketElement = new BasketElement();
|
|
$basketElement->setRecord($element);
|
|
$basketElement->setBasket($Basket);
|
|
|
|
$manager->persist($basketElement);
|
|
|
|
$Basket->addElement($basketElement);
|
|
|
|
if ($receiver['HD']) {
|
|
$this->getAclForUser($user_receiver)->grant_hd_on(
|
|
$basketElement->getRecord($this->app),
|
|
$this->getAuthenticatedUser(),
|
|
ACL::GRANT_ACTION_PUSH
|
|
);
|
|
} else {
|
|
$this->getAclForUser($user_receiver)->grant_preview_on(
|
|
$basketElement->getRecord($this->app),
|
|
$this->getAuthenticatedUser(),
|
|
ACL::GRANT_ACTION_PUSH
|
|
);
|
|
}
|
|
|
|
$this->getDataboxLogger($element->getDatabox())->log(
|
|
$element,
|
|
Session_Logger::EVENT_PUSH,
|
|
$user_receiver->getId(),
|
|
''
|
|
);
|
|
}
|
|
|
|
$manager->flush();
|
|
|
|
$arguments = [
|
|
'basket' => $Basket->getId(),
|
|
];
|
|
|
|
// here we send an email to each participant
|
|
//
|
|
// if we don't request the user to auth (=type his login/pwd),
|
|
// we generate a !!!! 'view' !!!! token to be included as 'LOG' parameter in url
|
|
//
|
|
// - the 'view' token is created to give access to lightbox in "compare" mode, NOT "validation"
|
|
// - the 'view' token has no expiration
|
|
//
|
|
if (!$this->getConf()->get(['registry', 'actions', 'enable-push-authentication']) || !$request->get('force_authentication') ) {
|
|
$arguments['LOG'] = $this->getTokenManipulator()->createBasketAccessToken($Basket, $user_receiver)->getValue();
|
|
}
|
|
|
|
$url = $this->app->url('lightbox_compare', $arguments);
|
|
|
|
|
|
$receipt = $request->get('recept') ? $this->getAuthenticatedUser()->getEmail() : '';
|
|
$this->dispatch(
|
|
PhraseaEvents::BASKET_PUSH,
|
|
new PushEvent($Basket, $request->request->get('message'), $url, $receipt)
|
|
);
|
|
}
|
|
|
|
$manager->flush();
|
|
|
|
$message = $this->app->trans(
|
|
'%quantity_records% records have been sent to %quantity_users% users',
|
|
[
|
|
'%quantity_records%' => count($pusher->get_elements()),
|
|
'%quantity_users%' => count($receivers),
|
|
]
|
|
);
|
|
|
|
$ret = [
|
|
'success' => true,
|
|
'message' => $message
|
|
];
|
|
} catch (ControllerException $e) {
|
|
$ret['message'] = $e->getMessage() . $e->getFile() . $e->getLine();
|
|
}
|
|
|
|
return $this->app->json($ret);
|
|
}
|
|
|
|
|
|
/** ----------------------------------------------------------------------------------
|
|
* a sharebasket request is made by the current user to many participants
|
|
*
|
|
* this is the same code as "send" request (=simple push), except here we
|
|
* - create a validation session,
|
|
* - register participants and data...
|
|
*
|
|
*
|
|
* @param Request $request
|
|
* @return JsonResponse
|
|
* @throws Exception
|
|
*
|
|
* @TODO This is too slow even for 100 records + 100 participants --> move this to a worker
|
|
*/
|
|
public function sharebasketAction(Request $request)
|
|
{
|
|
$ret = [
|
|
'success' => false,
|
|
'message' => $this->app->trans('Unable to send the documents')
|
|
];
|
|
|
|
$manager = $this->getEntityManager();
|
|
$manager->beginTransaction();
|
|
|
|
try {
|
|
$pusher = $this->getPushFromRequest($request);
|
|
|
|
$validation_name = $request->request->get('name', $this->app->trans(
|
|
'Validation from %user%', [
|
|
'%user%' => $this->getAuthenticatedUser()->getDisplayName(),
|
|
]));
|
|
$validation_description = $request->request->get('message');
|
|
|
|
$isFeedback = $request->request->get('isFeedback') == "1";
|
|
|
|
$participants = $request->request->get('participants');
|
|
|
|
if (!is_array($participants) || empty($participants)) {
|
|
throw new ControllerException($this->app->trans('No participants specified'));
|
|
}
|
|
|
|
if (!is_array($pusher->get_elements()) || empty($pusher->get_elements())) {
|
|
throw new ControllerException($this->app->trans('No elements to validate'));
|
|
}
|
|
|
|
// a sharebasket must apply to a basket...
|
|
//
|
|
if ($pusher->is_basket()) {
|
|
$basket = $pusher->get_original_basket();
|
|
if($basket->isVoteBasket()) {
|
|
// this basket is already under vote
|
|
// we check this is from the same initator (me)
|
|
if(!$basket->isVoteInitiator($this->getAuthenticatedUser())) {
|
|
// one tries to initiate a vote session on a basket which already has another vote initiaton
|
|
throw new ControllerException("basket already have another vote initiator");
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
// ...so if we got a list of elements (records), we create a basket for those
|
|
$basket = new Basket();
|
|
$basket
|
|
->setName($validation_name)
|
|
->setDescription($validation_description)
|
|
->setUser($this->getAuthenticatedUser())
|
|
->markUnread();
|
|
|
|
$manager->persist($basket);
|
|
|
|
foreach ($pusher->get_elements() as $element) {
|
|
$basketElement = new BasketElement();
|
|
$basketElement->setRecord($element);
|
|
$basketElement->setBasket($basket);
|
|
|
|
$manager->persist($basketElement);
|
|
|
|
$basket->addElement($basketElement);
|
|
}
|
|
}
|
|
|
|
if(!empty($shareExpiresDate = $request->request->get('shareExpires'))) {
|
|
$shareExpiresDate = new DateTime($shareExpiresDate); // d: "Y-m-d"
|
|
}
|
|
else {
|
|
$shareExpiresDate = null;
|
|
}
|
|
$basket->setShareExpires($shareExpiresDate); // can be null
|
|
|
|
if(!empty($voteExpiresDate = $request->request->get('voteExpires'))) {
|
|
$voteExpiresDate = new DateTime($voteExpiresDate); // d: "Y-m-d"
|
|
}
|
|
else {
|
|
$voteExpiresDate = null;
|
|
}
|
|
$basket->setVoteExpires($voteExpiresDate); // can be null, will be used for token
|
|
|
|
if($isFeedback) {
|
|
// in case of feedback, the owner must be participant (to see others votes)
|
|
// he is already on the participants
|
|
$basket->setVoteInitiator($this->getAuthenticatedUser());
|
|
}
|
|
else {
|
|
// for a simple share, we will ignore the owner
|
|
$basket->setVoteInitiator(null);
|
|
}
|
|
|
|
$manager->persist($basket);
|
|
$manager->flush();
|
|
|
|
$manager->refresh($basket);
|
|
|
|
$message = $this->app->trans(
|
|
'%quantity_records% records have been sent for validation to %quantity_users% users',
|
|
[
|
|
'%quantity_records%' => count($pusher->get_elements()),
|
|
'%quantity_users%' => count($request->request->get('participants')),
|
|
]
|
|
);
|
|
|
|
$ret = [
|
|
'success' => true,
|
|
'message' => $message,
|
|
];
|
|
|
|
$manager->commit();
|
|
|
|
$this->dispatch(
|
|
PhraseaEvents::BASKET_SHARE,
|
|
new ShareEvent(
|
|
$request,
|
|
$basket,
|
|
$this->getAuthenticatedUser()
|
|
)
|
|
);
|
|
}
|
|
catch (ControllerException $e) {
|
|
$ret['message'] = $e->getMessage();
|
|
$manager->rollback();
|
|
}
|
|
|
|
return $this->app->json($ret);
|
|
}
|
|
|
|
public function quitshareAction(Request $request, Basket $basket)
|
|
{
|
|
$ret = [
|
|
'success' => false,
|
|
'message' => ""
|
|
];
|
|
|
|
$user = $this->getAuthenticatedUser();
|
|
if( !is_null($participant = $basket->getParticipant($user))) {
|
|
$manager = $this->getEntityManager();
|
|
$manager->beginTransaction();
|
|
|
|
$basket->removeParticipant($participant);
|
|
$manager->remove($participant);
|
|
$manager->persist($basket);
|
|
$manager->flush();
|
|
|
|
$manager->commit();
|
|
$ret['success'] = true;
|
|
}
|
|
|
|
return $this->app->json($ret);
|
|
}
|
|
|
|
/**
|
|
* @param $usr_id
|
|
* @return JsonResponse
|
|
*/
|
|
public function getUserAction($usr_id)
|
|
{
|
|
$data = null;
|
|
|
|
$query = $this->createUserQuery();
|
|
$query->on_bases_where_i_am($this->getAclForUser($this->getAuthenticatedUser()), [ACL::CANPUSH]);
|
|
|
|
$query->in([$usr_id]);
|
|
|
|
$result = $query->include_phantoms()
|
|
->limit(0, 1)
|
|
->execute()->get_results();
|
|
|
|
if ($result) {
|
|
foreach ($result as $user) {
|
|
$data = $this->formatUser($user);
|
|
}
|
|
}
|
|
|
|
return $this->app->json($data);
|
|
}
|
|
|
|
/**
|
|
* @param $list_id
|
|
* @return JsonResponse
|
|
*/
|
|
public function getListAction($list_id)
|
|
{
|
|
$data = null;
|
|
|
|
$repository = $this->getUserListRepository();
|
|
$list = $repository->findUserListByUserAndId($this->getAuthenticatedUser(), $list_id);
|
|
|
|
if ($list) {
|
|
$data = $this->formatUserList($list);
|
|
}
|
|
|
|
return $this->app->json($data);
|
|
}
|
|
|
|
/**
|
|
* @param Request $request
|
|
* @return JsonResponse
|
|
* @throws Exception
|
|
*/
|
|
public function addUserAction(Request $request)
|
|
{
|
|
$result = ['success' => false, 'message' => '', 'user' => null];
|
|
|
|
try {
|
|
if (!$this->getAclForUser($this->getAuthenticatedUser())->has_right(ACL::CANADMIN))
|
|
throw new ControllerException($this->app->trans('You are not allowed to add users'));
|
|
|
|
if (!$request->request->get('firstname'))
|
|
throw new ControllerException($this->app->trans('First name is required'));
|
|
|
|
if (!$request->request->get('lastname'))
|
|
throw new ControllerException($this->app->trans('Last name is required'));
|
|
|
|
if (!$request->request->get('email'))
|
|
throw new ControllerException($this->app->trans('Email is required'));
|
|
|
|
if (!Swift_Validate::email($request->request->get('email')))
|
|
throw new ControllerException($this->app->trans('Email is invalid'));
|
|
} catch (ControllerException $e) {
|
|
$result['message'] = $e->getMessage();
|
|
|
|
return $this->app->json($result);
|
|
}
|
|
|
|
$user = null;
|
|
$email = $request->request->get('email');
|
|
|
|
if (null !== $user = $this->getUserRepository()->findByEmail($email)) {
|
|
$result['message'] = $this->app->trans('User already exists');
|
|
$result['success'] = true;
|
|
$result['user'] = $this->formatUser($user);
|
|
|
|
return $this->app->json($result);
|
|
}
|
|
|
|
try {
|
|
$manager = $this->getEntityManager();
|
|
|
|
$password = $this->getRandomGenerator()->generateString(128);
|
|
|
|
$user = $this->getUserManipulator()->createUser($email, $password, $email);
|
|
|
|
$user
|
|
->setFirstName($request->request->get('firstname'))
|
|
->setLastName($request->request->get('lastname'))
|
|
;
|
|
|
|
if ($request->request->get('company')) {
|
|
$user->setCompany($request->request->get('company'));
|
|
}
|
|
if ($request->request->get('job')) {
|
|
$user->setJob($request->request->get('job'));
|
|
}
|
|
if ($request->request->get('city')) {
|
|
$this->getUserManipulator()->setGeonameId($user, $request->request->get('city'));
|
|
}
|
|
|
|
$manager->persist($user);
|
|
$manager->flush();
|
|
|
|
$result['message'] = $this->app->trans('User successfully created');
|
|
$result['success'] = true;
|
|
$result['user'] = $this->formatUser($user);
|
|
} catch (Exception $e) {
|
|
$result['message'] = $this->app->trans('Error while creating user');
|
|
}
|
|
|
|
return $this->app->json($result);
|
|
}
|
|
|
|
/**
|
|
* @param Request $request
|
|
* @return string
|
|
*/
|
|
public function getAddUserFormAction(Request $request)
|
|
{
|
|
$params = ['callback' => $request->query->get('callback')];
|
|
|
|
return $this->render('prod/User/Add.html.twig', $params);
|
|
}
|
|
|
|
/**
|
|
* @param Request $request
|
|
* @return JsonResponse
|
|
*/
|
|
public function searchUserAction(Request $request)
|
|
{
|
|
$query = $this->createUserQuery();
|
|
$query->on_bases_where_i_am($this->getAclForUser($this->getAuthenticatedUser()), [ACL::CANPUSH]);
|
|
$query
|
|
->like(User_Query::LIKE_FIRSTNAME, $request->query->get('query'))
|
|
->like(User_Query::LIKE_LASTNAME, $request->query->get('query'))
|
|
->like(User_Query::LIKE_LOGIN, $request->query->get('query'))
|
|
->like(User_Query::LIKE_EMAIL, $request->query->get('query'))
|
|
->like(User_Query::LIKE_COMPANY, $request->query->get('query'))
|
|
->like_match(User_Query::LIKE_MATCH_OR);
|
|
|
|
$result = $query
|
|
->include_phantoms()
|
|
->limit(0, 50)
|
|
->execute()->get_results();
|
|
|
|
$repository = $this->getUserListRepository();
|
|
$lists = $repository->findUserListLike($this->getAuthenticatedUser(), $request->query->get('query'));
|
|
|
|
$data = [];
|
|
|
|
if ($lists) {
|
|
foreach ($lists as $list) {
|
|
$data[] = $this->formatUserList($list);
|
|
}
|
|
}
|
|
|
|
if ($result) {
|
|
foreach ($result as $user) {
|
|
$data[] = $this->formatUser($user);
|
|
}
|
|
}
|
|
|
|
return $this->app->json($data);
|
|
}
|
|
|
|
/**
|
|
* @param Request $request
|
|
* @param $list_id
|
|
* @return Response
|
|
*/
|
|
public function editListAction(Request $request, $list_id)
|
|
{
|
|
$repository = $this->getUserListRepository();
|
|
$list = $repository->findUserListByUserAndId($this->getAuthenticatedUser(), $list_id);
|
|
|
|
$query = $this->createUserQuery();
|
|
$query->on_bases_where_i_am($this->getAclForUser($this->getAuthenticatedUser()), [ACL::CANPUSH]);
|
|
|
|
if ($request->get('query')) {
|
|
$query
|
|
->like($request->get('like_field'), $request->get('query'))
|
|
->like_match(User_Query::LIKE_MATCH_OR);
|
|
}
|
|
|
|
if (is_array($request->get('EmailDomain'))) {
|
|
$query->haveEmailDomains($request->get('EmailDomain'));
|
|
}
|
|
if (is_array($request->get('Activity'))) {
|
|
$query->haveActivities($request->get('Activity'));
|
|
}
|
|
if (is_array($request->get('Template'))) {
|
|
$query->haveTemplate($request->get('Template'));
|
|
}
|
|
if (is_array($request->get('Company'))) {
|
|
$query->inCompanies($request->get('Company'));
|
|
}
|
|
if (is_array($request->get('Country'))) {
|
|
$query->inCountries($request->get('Country'));
|
|
}
|
|
if (is_array($request->get('Position'))) {
|
|
$query->havePositions($request->get('Position'));
|
|
}
|
|
|
|
$sort = $request->get('srt', 'usr_creationdate');
|
|
$ord = $request->get('ord', 'desc');
|
|
|
|
$perPage = 10;
|
|
$offset_start = Max(((int) $request->get('page') - 1) * $perPage, 0);
|
|
|
|
$query->sort_by($sort, $ord);
|
|
|
|
$results = $query
|
|
->include_phantoms()
|
|
->limit($offset_start, $perPage)
|
|
->execute()->get_results();
|
|
|
|
$params = [
|
|
'query' => $query,
|
|
'results' => $results,
|
|
'list' => $list,
|
|
'sort' => $sort,
|
|
'ord' => $ord,
|
|
];
|
|
|
|
if ($request->get('type') === 'fragment') {
|
|
return new Response(
|
|
$this->render('prod/actions/Feedback/ResultTable.html.twig', $params)
|
|
);
|
|
}
|
|
|
|
return new Response(
|
|
$this->render('prod/actions/Feedback/list.html.twig', $params)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* update the expiration date of a validation session
|
|
* also update the expiration of the participants validation tokens
|
|
*
|
|
* @param Request $request
|
|
* @return JsonResponse
|
|
* @throws Exception
|
|
*/
|
|
public function updateExpirationAction(Request $request)
|
|
{
|
|
// sanity check
|
|
if (is_null($request->request->get('date'))) {
|
|
throw new Exception('The provided date is null!');
|
|
}
|
|
|
|
$manager = $this->getEntityManager();
|
|
$manager->beginTransaction();
|
|
try {
|
|
$basket = $this->getBasketRepository()->findUserBasket($request->request->get('basket_id'), $this->app->getAuthenticatedUser(), true);
|
|
$expirationDate = new DateTime($request->request->get('date') . " 23:59:59");
|
|
|
|
if (!$basket->isVoteBasket()) {
|
|
throw new Exception('Unable to find the validation session');
|
|
}
|
|
|
|
// update validation tokens expiration
|
|
//
|
|
/** @var BasketParticipant $participant */
|
|
foreach($basket->getParticipants() as $participant) {
|
|
try {
|
|
if(!is_null($token = $this->getTokenRepository()->findValidationToken($basket, $participant->getUser()))) {
|
|
if($participant->getUser()->getId() === $basket->getVoteInitiator()->getId()) {
|
|
// the initiator keeps a no-expiration token
|
|
$token->setExpiration(null); // shoud already be null, but who knows...
|
|
}
|
|
else {
|
|
// the "normal" user token is fixed
|
|
$token->setExpiration($expirationDate);
|
|
}
|
|
}
|
|
}
|
|
catch (Exception $e) {
|
|
// not unique token ? should not happen.
|
|
// no-op
|
|
}
|
|
}
|
|
|
|
$basket->setVoteExpires($expirationDate);
|
|
$manager->persist($basket);
|
|
$manager->flush();
|
|
$manager->commit();
|
|
$ret = [
|
|
'success' => true,
|
|
'message' => $this->app->trans('Expiration date successfully updated!')
|
|
];
|
|
}
|
|
catch (Exception $e) {
|
|
$ret = [
|
|
'success' => false,
|
|
'message' => $e->getMessage()
|
|
];
|
|
$manager->rollback();
|
|
}
|
|
|
|
return $this->app->json($ret);
|
|
}
|
|
|
|
|
|
|
|
private function formatUser(User $user)
|
|
{
|
|
$subtitle = array_filter([$user->getJob(), $user->getCompany()]);
|
|
|
|
return [
|
|
'type' => 'USER',
|
|
'usr_id' => $user->getId(),
|
|
'firstname' => $user->getFirstName(),
|
|
'lastname' => $user->getLastName(),
|
|
'email' => $user->getEmail(),
|
|
'display_name' => $user->getDisplayName(),
|
|
'subtitle' => implode(', ', $subtitle),
|
|
];
|
|
}
|
|
|
|
private function formatUserList(UsrList $list)
|
|
{
|
|
$entries = [];
|
|
|
|
foreach ($list->getEntries() as $entry) {
|
|
$entries[] = [
|
|
'Id' => $entry->getId(),
|
|
'User' => $this->formatUser($entry->getUser()),
|
|
];
|
|
}
|
|
|
|
return [
|
|
'type' => 'LIST',
|
|
'list_id' => $list->getId(),
|
|
'name' => $list->getName(),
|
|
'length' => count($entries),
|
|
'entries' => $entries,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* from a list of records, return "users" from field(s) declared as vocabularyType/user
|
|
*
|
|
* this list of users will be displayed as "RecommendedUsers" for push
|
|
* !!!!!!!!!!!!!!! todo : also for share baskets ? !!!!!!!!!!!!
|
|
* !!!!! useless (?) in 4.1 since editing a vocab field does nothing special :
|
|
* the field value has no vocab/id value
|
|
*
|
|
*
|
|
* @param array|record_adapter[] $selection
|
|
* @return ArrayCollection Users
|
|
*/
|
|
private function getUsersInSelectionExtractor($selection)
|
|
{
|
|
$users = new ArrayCollection();
|
|
|
|
foreach ($selection as $record) {
|
|
foreach ($record->get_caption()->get_fields() as $caption_field) {
|
|
foreach ($caption_field->get_values() as $value) {
|
|
if (!$value->getVocabularyType())
|
|
continue;
|
|
|
|
if ($value->getVocabularyType()->getType() !== 'User')
|
|
continue;
|
|
|
|
$user = $value->getResource();
|
|
|
|
$users->set($user->getId(), $user);
|
|
}
|
|
}
|
|
}
|
|
|
|
return $users;
|
|
}
|
|
|
|
/**
|
|
* @return UsrListRepository
|
|
*/
|
|
private function getUserListRepository()
|
|
{
|
|
return $this->app['repo.usr-lists'];
|
|
}
|
|
|
|
/**
|
|
* @param Request $request
|
|
* @param $context
|
|
* @return string
|
|
*/
|
|
public function renderPushTemplate(Request $request, $context)
|
|
{
|
|
$push = $this->getPushFromRequest($request);
|
|
|
|
$feedbackaction = $request->request->get('feedbackaction');
|
|
$participants = [];
|
|
$participantUserIds = '';
|
|
$initiatorUserId = null;
|
|
|
|
if ($context === 'Sharebasket') {
|
|
if ($push->is_basket() ) {
|
|
// edit an existing sharebasket
|
|
//
|
|
$basket = $push->get_original_basket();
|
|
$participants = $basket->getParticipants();
|
|
$participantUserIds = implode('_', $basket->getListParticipantsUserId());
|
|
// $initiatorUserId = $basket->isVoteBasket()
|
|
// ? $basket->getVoteInitiator()->getId()
|
|
// : $this->getAuthenticatedUser()->getId();
|
|
$initiatorUserId = $basket->getVoteInitiator() ? $basket->getVoteInitiator()->getId() : null;
|
|
}
|
|
else {
|
|
// initiate a share from a list of records
|
|
// add the initiator in the participant list window when the first time to create a feedback
|
|
$basketParticipant = new BasketParticipant($this->getAuthenticatedUser());
|
|
$basketParticipant->setCanSeeOthers(1);
|
|
array_push($participants, $basketParticipant);
|
|
$participantUserIds = $this->getAuthenticatedUser()->getId(); // list with a single user
|
|
// $initiatorUserId = $this->getAuthenticatedUser()->getId();
|
|
$initiatorUserId = null;
|
|
}
|
|
}
|
|
else {
|
|
// context = "Push"
|
|
}
|
|
|
|
$repository = $this->getUserListRepository();
|
|
$recommendedUsers = $this->getUsersInSelectionExtractor($push->get_elements());
|
|
|
|
return $this->render(
|
|
'prod/actions/Push.html.twig',
|
|
[
|
|
'push' => $push,
|
|
'message' => '',
|
|
'lists' => $repository->findUserLists($this->getAuthenticatedUser()),
|
|
'context' => $context,
|
|
'RecommendedUsers' => $recommendedUsers,
|
|
'participants' => $participants,
|
|
'participantUserIds' => $participantUserIds,
|
|
'feedbackAction' => $feedbackaction,
|
|
'owner' => $this->getAuthenticatedUser(),
|
|
'initiatorUserId' => $initiatorUserId
|
|
]
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @return UserRepository
|
|
*/
|
|
private function getUserRepository()
|
|
{
|
|
return $this->app['repo.users'];
|
|
}
|
|
|
|
/**
|
|
* @return TokenManipulator
|
|
*/
|
|
private function getTokenManipulator()
|
|
{
|
|
return $this->app['manipulator.token'];
|
|
}
|
|
|
|
/**
|
|
* @param Request $request
|
|
* @return RecordHelper\Push
|
|
*/
|
|
private function getPushFromRequest(Request $request)
|
|
{
|
|
return new RecordHelper\Push($this->app, $request);
|
|
}
|
|
|
|
/**
|
|
* @return UserManipulator
|
|
*/
|
|
private function getUserManipulator()
|
|
{
|
|
return $this->app['manipulator.user'];
|
|
}
|
|
|
|
/**
|
|
* @return Generator
|
|
*/
|
|
private function getRandomGenerator()
|
|
{
|
|
return $this->app['random.medium'];
|
|
}
|
|
|
|
/**
|
|
* @return BasketRepository
|
|
*/
|
|
private function getBasketRepository()
|
|
{
|
|
return $this->app['repo.baskets'];
|
|
}
|
|
|
|
/**
|
|
* @return TokenRepository
|
|
*/
|
|
private function getTokenRepository()
|
|
{
|
|
return $this->app['repo.tokens'];
|
|
}
|
|
|
|
}
|