mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-23 18:03:17 +00:00
Merge branch 'master' of https://github.com/alchemy-fr/Phraseanet into PHRAS-2430_Port_to_41-Advance_search_refacto_Restore_Query
This commit is contained in:
@@ -84,6 +84,15 @@ class CollectionRepositoryRegistry
|
||||
throw new \OutOfBoundsException('No repository available for given base [baseId: ' . $baseId . ' ].');
|
||||
}
|
||||
|
||||
public function getBaseIdMap()
|
||||
{
|
||||
if ($this->baseIdMap === null) {
|
||||
$this->loadBaseIdMap();
|
||||
}
|
||||
|
||||
return $this->baseIdMap;
|
||||
}
|
||||
|
||||
public function purgeRegistry()
|
||||
{
|
||||
$this->baseIdMap = null;
|
||||
|
@@ -90,35 +90,44 @@ class RecordController extends Controller
|
||||
}
|
||||
$recordCaptions["technicalInfo"] = $record->getPositionFromTechnicalInfos();
|
||||
|
||||
// escape record title before rendering
|
||||
$recordTitle = explode("</span>", $record->get_title());
|
||||
if (count($recordTitle) >1) {
|
||||
$recordTitle[1] = htmlspecialchars($recordTitle[1]);
|
||||
$recordTitle = implode("</span>", $recordTitle);
|
||||
} else {
|
||||
$recordTitle = htmlspecialchars($record->get_title());
|
||||
}
|
||||
|
||||
return $this->app->json([
|
||||
"desc" => $this->render('prod/preview/caption.html.twig', [
|
||||
"desc" => $this->render('prod/preview/caption.html.twig', [
|
||||
'record' => $record,
|
||||
'highlight' => $query,
|
||||
'searchEngine' => $searchEngine,
|
||||
'searchOptions' => $options,
|
||||
]),
|
||||
"recordCaptions"=> $recordCaptions,
|
||||
"html_preview" => $this->render('common/preview.html.twig', [
|
||||
"recordCaptions" => $recordCaptions,
|
||||
"html_preview" => $this->render('common/preview.html.twig', [
|
||||
'record' => $record
|
||||
]),
|
||||
"others" => $this->render('prod/preview/appears_in.html.twig', [
|
||||
"others" => $this->render('prod/preview/appears_in.html.twig', [
|
||||
'parents' => $record->get_grouping_parents(),
|
||||
'baskets' => $record->get_container_baskets($this->getEntityManager(), $this->getAuthenticatedUser()),
|
||||
]),
|
||||
"current" => $train,
|
||||
"record" => $currentRecord,
|
||||
"history" => $this->render('prod/preview/short_history.html.twig', [
|
||||
"current" => $train,
|
||||
"record" => $currentRecord,
|
||||
"history" => $this->render('prod/preview/short_history.html.twig', [
|
||||
'record' => $record,
|
||||
]),
|
||||
"popularity" => $this->render('prod/preview/popularity.html.twig', [
|
||||
"popularity" => $this->render('prod/preview/popularity.html.twig', [
|
||||
'record' => $record,
|
||||
]),
|
||||
"tools" => $this->render('prod/preview/tools.html.twig', [
|
||||
"tools" => $this->render('prod/preview/tools.html.twig', [
|
||||
'record' => $record,
|
||||
]),
|
||||
"pos" => $record->getNumber(),
|
||||
"title" => $record->get_title(),
|
||||
"databox_name" => $record->getDatabox()->get_dbname(),
|
||||
"pos" => $record->getNumber(),
|
||||
"title" => $recordTitle,
|
||||
"databox_name" => $record->getDatabox()->get_dbname(),
|
||||
"collection_name" => $record->getCollection()->get_name(),
|
||||
"collection_logo" => $record->getCollection()->getLogo($record->getBaseId(), $this->app),
|
||||
]);
|
||||
|
@@ -17,20 +17,27 @@ use Alchemy\Phrasea\Application\Helper\EntityManagerAware;
|
||||
use Alchemy\Phrasea\Application\Helper\NotifierAware;
|
||||
use Alchemy\Phrasea\Authentication\Phrasea\PasswordEncoder;
|
||||
use Alchemy\Phrasea\Controller\Controller;
|
||||
use Alchemy\Phrasea\ControllerProvider\Root\Login;
|
||||
use Alchemy\Phrasea\Core\Configuration\RegistrationManager;
|
||||
use Alchemy\Phrasea\Exception\InvalidArgumentException;
|
||||
use Alchemy\Phrasea\Form\Login\PhraseaRenewPasswordForm;
|
||||
use Alchemy\Phrasea\Model\Entities\ApiApplication;
|
||||
use Alchemy\Phrasea\Model\Entities\FtpCredential;
|
||||
use Alchemy\Phrasea\Model\Entities\Session;
|
||||
use Alchemy\Phrasea\Model\Entities\User;
|
||||
use Alchemy\Phrasea\Model\Manipulator\ApiAccountManipulator;
|
||||
use Alchemy\Phrasea\Model\Manipulator\ApiApplicationManipulator;
|
||||
use Alchemy\Phrasea\Model\Manipulator\BasketManipulator;
|
||||
use Alchemy\Phrasea\Model\Manipulator\TokenManipulator;
|
||||
use Alchemy\Phrasea\Model\Manipulator\UserManipulator;
|
||||
use Alchemy\Phrasea\Model\Repositories\ApiAccountRepository;
|
||||
use Alchemy\Phrasea\Model\Repositories\ApiApplicationRepository;
|
||||
use Alchemy\Phrasea\Model\Repositories\BasketRepository;
|
||||
use Alchemy\Phrasea\Model\Repositories\FeedPublisherRepository;
|
||||
use Alchemy\Phrasea\Model\Repositories\TokenRepository;
|
||||
use Alchemy\Phrasea\Model\Repositories\ValidationSessionRepository;
|
||||
use Alchemy\Phrasea\Notification\Mail\MailRequestAccountDelete;
|
||||
use Alchemy\Phrasea\Notification\Mail\MailRequestEmailUpdate;
|
||||
use Alchemy\Phrasea\Notification\Mail\MailSuccessAccountDelete;
|
||||
use Alchemy\Phrasea\Notification\Receiver;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
@@ -299,13 +306,102 @@ class AccountController extends Controller
|
||||
$manager = $this->getEventManager();
|
||||
$user = $this->getAuthenticatedUser();
|
||||
|
||||
$repo_baskets = $this->getBasketRepository();
|
||||
$baskets = $repo_baskets->findActiveValidationAndBasketByUser($user);
|
||||
|
||||
$apiAccounts = $this->getApiAccountRepository()->findByUser($user);
|
||||
|
||||
$ownedFeeds = $this->getFeedPublisherRepository()->findBy(['user' => $user, 'owner' => true]);
|
||||
|
||||
$initiatedValidations = $this->getValidationSessionRepository()->findby(['initiator' => $user, ]);
|
||||
|
||||
return $this->render('account/account.html.twig', [
|
||||
'user' => $user,
|
||||
'evt_mngr' => $manager,
|
||||
'notifications' => $manager->list_notifications_available($user),
|
||||
'user' => $user,
|
||||
'evt_mngr' => $manager,
|
||||
'notifications' => $manager->list_notifications_available($user),
|
||||
'baskets' => $baskets,
|
||||
'api_accounts' => $apiAccounts,
|
||||
'owned_feeds' => $ownedFeeds,
|
||||
'initiated_validations' => $initiatedValidations,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function processDeleteAccount(Request $request)
|
||||
{
|
||||
$user = $this->getAuthenticatedUser();
|
||||
|
||||
if($this->app['conf']->get(['user_account', 'deleting_policies', 'email_confirmation'])) {
|
||||
|
||||
// send email confirmation
|
||||
|
||||
try {
|
||||
$receiver = Receiver::fromUser($user);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
$this->app->addFlash('error', $this->app->trans('phraseanet::erreur: echec du serveur de mail'));
|
||||
|
||||
return $this->app->redirectPath('account');
|
||||
}
|
||||
|
||||
$token = $this->getTokenManipulator()->createAccountDeleteToken($user, $user->getEmail());
|
||||
$url = $this->app->url('account_confirm_delete', ['token' => $token->getValue()]);
|
||||
|
||||
|
||||
$mail = MailRequestAccountDelete::create($this->app, $receiver);
|
||||
$mail->setUserOwner($user);
|
||||
$mail->setButtonUrl($url);
|
||||
$mail->setExpiration($token->getExpiration());
|
||||
|
||||
$this->deliver($mail);
|
||||
|
||||
$this->app->addFlash('info', $this->app->trans('phraseanet::account: A confirmation e-mail has been sent. Please follow the instructions contained to continue account deletion'));
|
||||
|
||||
return $this->app->redirectPath('account');
|
||||
|
||||
} else {
|
||||
$this->doDeleteAccount($user);
|
||||
|
||||
$response = $this->app->redirectPath('homepage', [
|
||||
'redirect' => $request->query->get("redirect")
|
||||
]);
|
||||
|
||||
$response->headers->clearCookie('persistent');
|
||||
$response->headers->clearCookie('last_act');
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function confirmDeleteAccount(Request $request)
|
||||
{
|
||||
if (($tokenValue = $request->query->get('token')) !== null ) {
|
||||
if (null === $token = $this->getTokenRepository()->findValidToken($tokenValue)) {
|
||||
$this->app->addFlash('error', $this->app->trans('Token not found'));
|
||||
|
||||
return $this->app->redirectPath('account');
|
||||
}
|
||||
|
||||
$user = $token->getUser();
|
||||
// delete account and datas
|
||||
$this->doDeleteAccount($user);
|
||||
|
||||
$this->getTokenManipulator()->delete($token);
|
||||
}
|
||||
|
||||
$response = $this->app->redirectPath('homepage', [
|
||||
'redirect' => $request->query->get("redirect")
|
||||
]);
|
||||
|
||||
$response->headers->clearCookie('persistent');
|
||||
$response->headers->clearCookie('last_act');
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update account information
|
||||
*
|
||||
@@ -406,6 +502,49 @@ class AccountController extends Controller
|
||||
return $this->app->redirectPath('account');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
*/
|
||||
private function doDeleteAccount(User $user)
|
||||
{
|
||||
// basket
|
||||
$repo_baskets = $this->getBasketRepository();
|
||||
$baskets = $repo_baskets->findActiveByUser($user);
|
||||
$this->getBasketManipulator()->removeBaskets($baskets);
|
||||
|
||||
// application
|
||||
$applications = $this->getApiApplicationRepository()->findByUser($user);
|
||||
|
||||
$this->getApiApplicationManipulator()->deleteApiApplications($applications);
|
||||
|
||||
|
||||
// revoke access and delete phraseanet user account
|
||||
|
||||
$list = array_keys($this->app['repo.collections-registry']->getBaseIdMap());
|
||||
|
||||
$this->app->getAclForUser($user)->revoke_access_from_bases($list);
|
||||
|
||||
if ($this->app->getAclForUser($user)->is_phantom()) {
|
||||
// send confirmation email: the account has been deleted
|
||||
|
||||
try {
|
||||
$receiver = Receiver::fromUser($user);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
$this->app->addFlash('error', $this->app->trans('phraseanet::erreur: echec du serveur de mail'));
|
||||
}
|
||||
|
||||
$mail = MailSuccessAccountDelete::create($this->app, $receiver);
|
||||
|
||||
$this->app['manipulator.user']->delete($user);
|
||||
|
||||
$this->deliver($mail);
|
||||
}
|
||||
|
||||
$this->getAuthenticator()->closeAccount();
|
||||
$this->app->addFlash('info', $this->app->trans('phraseanet::account The account has been deleted'));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return PasswordEncoder
|
||||
*/
|
||||
@@ -501,4 +640,44 @@ class AccountController extends Controller
|
||||
{
|
||||
return $this->app['events-manager'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BasketManipulator
|
||||
*/
|
||||
private function getBasketManipulator()
|
||||
{
|
||||
return $this->app['manipulator.basket'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BasketRepository
|
||||
*/
|
||||
private function getBasketRepository()
|
||||
{
|
||||
return $this->app['repo.baskets'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ApiApplicationManipulator
|
||||
*/
|
||||
private function getApiApplicationManipulator()
|
||||
{
|
||||
return $this->app['manipulator.api-application'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return FeedPublisherRepository
|
||||
*/
|
||||
private function getFeedPublisherRepository()
|
||||
{
|
||||
return $this->app['repo.feed-publishers'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ValidationSessionRepository
|
||||
*/
|
||||
private function getValidationSessionRepository()
|
||||
{
|
||||
return $this->app['repo.validation-session'];
|
||||
}
|
||||
}
|
||||
|
@@ -806,7 +806,7 @@ class ThesaurusController extends Controller
|
||||
if (!$t) {
|
||||
$t = "...";
|
||||
}
|
||||
$fullBranch = " / " . $t . $fullBranch;
|
||||
$fullBranch = " / " . htmlspecialchars($t) . $fullBranch;
|
||||
}
|
||||
}
|
||||
$nodes = $xpathstruct->query("/record/description/*");
|
||||
@@ -1159,7 +1159,7 @@ class ThesaurusController extends Controller
|
||||
'1',
|
||||
null
|
||||
);
|
||||
$fullpath = $dom->getElementsByTagName("fullpath_html")->item(0)->firstChild->nodeValue;
|
||||
$fullpathHtml = $dom->getElementsByTagName("fullpath_html")->item(0)->firstChild->nodeValue;
|
||||
$hits = $dom->getElementsByTagName("allhits")->item(0)->firstChild->nodeValue;
|
||||
|
||||
$languages = $synonyms = [];
|
||||
@@ -1180,6 +1180,16 @@ class ThesaurusController extends Controller
|
||||
$languages[$lng_code[0]] = $language;
|
||||
}
|
||||
|
||||
// Escape path between span tag in fullpath_html
|
||||
preg_match_all("'(<[^><]*>)(.*?)(<[^><]*>)'", $fullpathHtml, $matches, PREG_SET_ORDER);
|
||||
|
||||
$safeFullpath = '';
|
||||
foreach($matches as $match) {
|
||||
unset($match[0]); // full match result not used
|
||||
$match[2] = htmlspecialchars($match[2]);
|
||||
$safeFullpath .= implode('', $match);
|
||||
}
|
||||
|
||||
return $this->render('thesaurus/properties.html.twig', [
|
||||
'typ' => $request->get('typ'),
|
||||
'bid' => $request->get('bid'),
|
||||
@@ -1187,7 +1197,7 @@ class ThesaurusController extends Controller
|
||||
'id' => $request->get('id'),
|
||||
'dlg' => $request->get('dlg'),
|
||||
'languages' => $languages,
|
||||
'fullpath' => $fullpath,
|
||||
'fullpath' => $safeFullpath,
|
||||
'hits' => $hits,
|
||||
'synonyms' => $synonyms,
|
||||
]);
|
||||
|
@@ -52,6 +52,14 @@ class Account implements ControllerProviderInterface, ServiceProviderInterface
|
||||
$controllers->get('/', 'account.controller:displayAccount')
|
||||
->bind('account');
|
||||
|
||||
// allow to delete phraseanet account
|
||||
$controllers->get('/delete/process', 'account.controller:processDeleteAccount')
|
||||
->bind('account_process_delete');
|
||||
|
||||
$controllers->get('/delete/confirm', 'account.controller:confirmDeleteAccount')
|
||||
->bind('account_confirm_delete');
|
||||
|
||||
|
||||
// Updates current logged in user account
|
||||
$controllers->post('/', 'account.controller:updateAccount')
|
||||
->bind('submit_update_account');
|
||||
|
@@ -66,6 +66,9 @@ class RepositoriesServiceProvider implements ServiceProviderInterface
|
||||
$app['repo.validation-participants'] = $app->share(function (PhraseaApplication $app) {
|
||||
return $app['orm.em']->getRepository('Phraseanet:ValidationParticipant');
|
||||
});
|
||||
$app['repo.validation-session'] = $app->share(function (PhraseaApplication $app) {
|
||||
return $app['orm.em']->getRepository('Phraseanet:ValidationSession');
|
||||
});
|
||||
$app['repo.story-wz'] = $app->share(function (PhraseaApplication $app) {
|
||||
return $app['orm.em']->getRepository('Phraseanet:StoryWZ');
|
||||
});
|
||||
|
@@ -18,7 +18,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
/**
|
||||
* @ORM\Table(name="ValidationSessions")
|
||||
* @ORM\Entity
|
||||
* @ORM\Entity(repositoryClass="Alchemy\Phrasea\Model\Repositories\ValidationSessionRepository")
|
||||
*/
|
||||
class ValidationSession
|
||||
{
|
||||
|
@@ -57,6 +57,14 @@ class ApiApplicationManipulator implements ManipulatorInterface
|
||||
$this->om->flush();
|
||||
}
|
||||
|
||||
public function deleteApiApplications(array $applications)
|
||||
{
|
||||
foreach ($applications as $application) {
|
||||
$this->om->remove($application);
|
||||
}
|
||||
$this->om->flush();
|
||||
}
|
||||
|
||||
public function update(ApiApplication $application)
|
||||
{
|
||||
$this->om->persist($application);
|
||||
|
@@ -118,4 +118,12 @@ class BasketManipulator
|
||||
$this->manager->remove($basket);
|
||||
$this->manager->flush();
|
||||
}
|
||||
|
||||
public function removeBaskets(array $baskets)
|
||||
{
|
||||
foreach ($baskets as $basket) {
|
||||
$this->manager->remove($basket);
|
||||
}
|
||||
$this->manager->flush();
|
||||
}
|
||||
}
|
||||
|
@@ -26,6 +26,7 @@ class TokenManipulator implements ManipulatorInterface
|
||||
const TYPE_FEED_ENTRY = 'FEED_ENTRY';
|
||||
const TYPE_PASSWORD = 'password';
|
||||
const TYPE_ACCOUNT_UNLOCK = 'account-unlock';
|
||||
const TYPE_ACCOUNT_DELETE = 'account-delete';
|
||||
const TYPE_DOWNLOAD = 'download';
|
||||
const TYPE_MAIL_DOWNLOAD = 'mail-download';
|
||||
const TYPE_EMAIL = 'email';
|
||||
@@ -167,6 +168,16 @@ class TokenManipulator implements ManipulatorInterface
|
||||
return $this->create($user, self::TYPE_ACCOUNT_UNLOCK, new \DateTime('+3 days'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
*
|
||||
* @return Token
|
||||
*/
|
||||
public function createAccountDeleteToken(User $user, $email)
|
||||
{
|
||||
return $this->create($user, self::TYPE_ACCOUNT_DELETE, new \DateTime('+1 hour'), $email);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
*
|
||||
|
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2014 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Model\Repositories;
|
||||
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
|
||||
/**
|
||||
* ValidationSessionRepository
|
||||
*
|
||||
* This class was generated by the Doctrine ORM. Add your own custom
|
||||
* repository methods below.
|
||||
*/
|
||||
class ValidationSessionRepository extends EntityRepository
|
||||
{
|
||||
}
|
@@ -17,6 +17,8 @@ use Alchemy\Phrasea\Notification\ReceiverInterface;
|
||||
|
||||
abstract class AbstractMail implements MailInterface
|
||||
{
|
||||
const MAIL_SKIN = 'default';
|
||||
|
||||
/** @var Application */
|
||||
protected $app;
|
||||
/** @var EmitterInterface */
|
||||
@@ -59,6 +61,7 @@ abstract class AbstractMail implements MailInterface
|
||||
'expiration' => $this->getExpiration(),
|
||||
'buttonUrl' => $this->getButtonURL(),
|
||||
'buttonText' => $this->getButtonText(),
|
||||
'mailSkin' => $this->getMailSkin(),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -166,6 +169,14 @@ abstract class AbstractMail implements MailInterface
|
||||
$this->url = $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getMailSkin()
|
||||
{
|
||||
return self::MAIL_SKIN;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@@ -0,0 +1,105 @@
|
||||
<?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\Notification\Mail;
|
||||
|
||||
use Alchemy\Phrasea\Exception\LogicException;
|
||||
use Alchemy\Phrasea\Model\Entities\User;
|
||||
|
||||
class MailRequestAccountDelete extends AbstractMailWithLink
|
||||
{
|
||||
const MAIL_SKIN = 'warning';
|
||||
|
||||
/** @var User */
|
||||
private $user;
|
||||
|
||||
/**
|
||||
* Set the user owner
|
||||
*
|
||||
* @param User $userOwner
|
||||
*/
|
||||
public function setUserOwner(User $userOwner)
|
||||
{
|
||||
$this->user = $userOwner;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSubject()
|
||||
{
|
||||
return $this->app->trans('Email:deletion:request:subject Delete account confirmation');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getMessage()
|
||||
{
|
||||
if (!$this->user) {
|
||||
throw new LogicException('You must set a user before calling getMessage');
|
||||
}
|
||||
|
||||
return $this->app->trans("Email:deletion:request:message Hello %civility% %firstName% %lastName%.
|
||||
We have received an account deletion request for your account on %urlInstance%, please confirm this deletion by clicking on the link below.
|
||||
If you are not at the origin of this request, please change your password as soon as possible %resetPassword%
|
||||
Link is valid for one hour.", [
|
||||
'%civility%' => $this->getOwnerCivility(),
|
||||
'%firstName%'=> $this->user->getFirstName(),
|
||||
'%lastName%' => $this->user->getLastName(),
|
||||
'%urlInstance%' => '<a href="'.$this->getPhraseanetURL().'">'.$this->getPhraseanetURL().'</a>',
|
||||
'%resetPassword%' => '<a href="'.$this->app->url('reset_password').'">'.$this->app->url('reset_password').'</a>',
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getButtonText()
|
||||
{
|
||||
return $this->app->trans('Email:deletion:request:textButton Delete my account');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getButtonURL()
|
||||
{
|
||||
return $this->url;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getMailSkin()
|
||||
{
|
||||
return self::MAIL_SKIN;
|
||||
}
|
||||
|
||||
private function getOwnerCivility()
|
||||
{
|
||||
if (!$this->user) {
|
||||
throw new LogicException('You must set a user before calling getMessage');
|
||||
}
|
||||
|
||||
$civilities = [
|
||||
User::GENDER_MISS => 'Miss',
|
||||
User::GENDER_MRS => 'Mrs',
|
||||
User::GENDER_MR => 'Mr',
|
||||
];
|
||||
|
||||
if (array_key_exists($this->user->getGender(), $civilities)) {
|
||||
return $civilities[$this->user->getGender()];
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,45 @@
|
||||
<?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\Notification\Mail;
|
||||
|
||||
class MailSuccessAccountDelete extends AbstractMail
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSubject()
|
||||
{
|
||||
return $this->app->trans('Delete account successfull');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getMessage()
|
||||
{
|
||||
return $this->app->trans('Your phraseanet account on %urlInstance% has been deleted!', ['%urlInstance%' => '<a href="'.$this->getPhraseanetURL().'">'.$this->getPhraseanetURL().'</a>']);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getButtonText()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getButtonURL()
|
||||
{
|
||||
}
|
||||
}
|
@@ -43,7 +43,7 @@ class QuotedTextNode extends Node
|
||||
|
||||
$private_fields = $context->getPrivateFields();
|
||||
$private_fields = ValueChecker::filterByValueCompatibility($private_fields, $this->text);
|
||||
foreach (QueryHelper::wrapPrivateFieldQueries($private_fields, $query_builder) as $private_field_query) {
|
||||
foreach (QueryHelper::wrapPrivateFieldQueries($private_fields, $unrestricted_fields, $query_builder) as $private_field_query) {
|
||||
$query = QueryHelper::applyBooleanClause($query, 'should', $private_field_query);
|
||||
}
|
||||
|
||||
|
@@ -61,7 +61,7 @@ class RawNode extends Node
|
||||
|
||||
$private_fields = $context->getPrivateFields();
|
||||
$private_fields = ValueChecker::filterByValueCompatibility($private_fields, $this->text);
|
||||
foreach (QueryHelper::wrapPrivateFieldQueries($private_fields, $query_builder) as $private_field_query) {
|
||||
foreach (QueryHelper::wrapPrivateFieldQueries($private_fields, $unrestricted_fields, $query_builder) as $private_field_query) {
|
||||
$query = QueryHelper::applyBooleanClause($query, 'should', $private_field_query);
|
||||
}
|
||||
|
||||
|
@@ -19,9 +19,11 @@ class TermNode extends AbstractTermNode
|
||||
return $query;
|
||||
};
|
||||
|
||||
$query = $query_builder($context->getUnrestrictedFields());
|
||||
$unrestricted_fields = $context->getUnrestrictedFields();
|
||||
$private_fields = $context->getPrivateFields();
|
||||
foreach (QueryHelper::wrapPrivateFieldQueries($private_fields, $query_builder) as $concept_query) {
|
||||
$query = $query_builder($unrestricted_fields);
|
||||
|
||||
foreach (QueryHelper::wrapPrivateFieldQueries($private_fields, $unrestricted_fields, $query_builder) as $concept_query) {
|
||||
$query = QueryHelper::applyBooleanClause($query, 'should', $concept_query);
|
||||
}
|
||||
|
||||
|
@@ -66,12 +66,11 @@ class TextNode extends AbstractTermNode implements ContextAbleInterface
|
||||
return $query;
|
||||
};
|
||||
|
||||
// Unrestricted fields
|
||||
$query = $query_builder($context->getUnrestrictedFields());
|
||||
|
||||
// Private fields
|
||||
$unrestricted_fields = $context->getUnrestrictedFields();
|
||||
$private_fields = $context->getPrivateFields();
|
||||
foreach (QueryHelper::wrapPrivateFieldQueries($private_fields, $query_builder) as $private_field_query) {
|
||||
|
||||
$query = $query_builder($unrestricted_fields);
|
||||
foreach (QueryHelper::wrapPrivateFieldQueries($private_fields, $unrestricted_fields, $query_builder) as $private_field_query) {
|
||||
$query = QueryHelper::applyBooleanClause($query, 'should', $private_field_query);
|
||||
}
|
||||
|
||||
|
@@ -10,13 +10,13 @@ class QueryHelper
|
||||
{
|
||||
private function __construct() {}
|
||||
|
||||
public static function wrapPrivateFieldQueries(array $fields, \Closure $query_builder)
|
||||
public static function wrapPrivateFieldQueries(array $private_fields, array $unrestricted_fields, \Closure $query_builder)
|
||||
{
|
||||
// We make a boolean clause for each collection set to shrink query size
|
||||
// (instead of a clause for each field, with his collection set)
|
||||
$fields_map = [];
|
||||
$collections_map = [];
|
||||
foreach ($fields as $field) {
|
||||
foreach ($private_fields as $field) {
|
||||
$collections = $field->getDependantCollections();
|
||||
$hash = self::hashCollections($collections);
|
||||
$collections_map[$hash] = $collections;
|
||||
@@ -31,7 +31,7 @@ class QueryHelper
|
||||
foreach ($fields_map as $hash => $fields) {
|
||||
// Right to query on a private field is dependant of document collection
|
||||
// Here we make sure we can only match on allowed collections
|
||||
$query = $query_builder($fields);
|
||||
$query = $query_builder(array_merge($fields, $unrestricted_fields));
|
||||
if ($query !== null) {
|
||||
$queries[] = self::restrictQueryToCollections($query, $collections_map[$hash]);
|
||||
}
|
||||
|
Reference in New Issue
Block a user