mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-23 09:53:15 +00:00
Merge branch 'master' into PHRAS-2911-gif-preview-video
This commit is contained in:
@@ -19,8 +19,10 @@ use Alchemy\Phrasea\Core\PhraseaEvents;
|
|||||||
use Alchemy\Phrasea\Feed\Aggregate;
|
use Alchemy\Phrasea\Feed\Aggregate;
|
||||||
use Alchemy\Phrasea\Feed\Link\AggregateLinkGenerator;
|
use Alchemy\Phrasea\Feed\Link\AggregateLinkGenerator;
|
||||||
use Alchemy\Phrasea\Feed\Link\FeedLinkGenerator;
|
use Alchemy\Phrasea\Feed\Link\FeedLinkGenerator;
|
||||||
|
use Alchemy\Phrasea\Model\Entities\Feed;
|
||||||
use Alchemy\Phrasea\Model\Entities\FeedEntry;
|
use Alchemy\Phrasea\Model\Entities\FeedEntry;
|
||||||
use Alchemy\Phrasea\Model\Entities\FeedItem;
|
use Alchemy\Phrasea\Model\Entities\FeedItem;
|
||||||
|
use Alchemy\Phrasea\Model\Entities\FeedPublisher;
|
||||||
use Alchemy\Phrasea\Model\Repositories\FeedEntryRepository;
|
use Alchemy\Phrasea\Model\Repositories\FeedEntryRepository;
|
||||||
use Alchemy\Phrasea\Model\Repositories\FeedItemRepository;
|
use Alchemy\Phrasea\Model\Repositories\FeedItemRepository;
|
||||||
use Alchemy\Phrasea\Model\Repositories\FeedPublisherRepository;
|
use Alchemy\Phrasea\Model\Repositories\FeedPublisherRepository;
|
||||||
@@ -46,6 +48,7 @@ class FeedController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function createFeedEntryAction(Request $request) {
|
public function createFeedEntryAction(Request $request) {
|
||||||
|
/** @var Feed $feed */
|
||||||
$feed = $this->getFeedRepository()->find($request->request->get('feed_id'));
|
$feed = $this->getFeedRepository()->find($request->request->get('feed_id'));
|
||||||
|
|
||||||
if (null === $feed) {
|
if (null === $feed) {
|
||||||
@@ -53,6 +56,8 @@ class FeedController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
$user = $this->getAuthenticatedUser();
|
$user = $this->getAuthenticatedUser();
|
||||||
|
|
||||||
|
/** @var FeedPublisher $publisher */
|
||||||
$publisher = $this->getFeedPublisherRepository()->findOneBy([
|
$publisher = $this->getFeedPublisherRepository()->findOneBy([
|
||||||
'feed' => $feed,
|
'feed' => $feed,
|
||||||
'user' => $user,
|
'user' => $user,
|
||||||
|
@@ -13,7 +13,9 @@ namespace Alchemy\Phrasea\Core\Event\Subscriber;
|
|||||||
|
|
||||||
use Alchemy\Phrasea\Core\Event\FeedEntryEvent;
|
use Alchemy\Phrasea\Core\Event\FeedEntryEvent;
|
||||||
use Alchemy\Phrasea\Core\PhraseaEvents;
|
use Alchemy\Phrasea\Core\PhraseaEvents;
|
||||||
|
use Alchemy\Phrasea\Model\Entities\User;
|
||||||
use Alchemy\Phrasea\Model\Entities\WebhookEvent;
|
use Alchemy\Phrasea\Model\Entities\WebhookEvent;
|
||||||
|
use Alchemy\Phrasea\Model\Manipulator\TokenManipulator;
|
||||||
use Alchemy\Phrasea\Notification\Receiver;
|
use Alchemy\Phrasea\Notification\Receiver;
|
||||||
use Alchemy\Phrasea\Notification\Mail\MailInfoNewPublication;
|
use Alchemy\Phrasea\Notification\Mail\MailInfoNewPublication;
|
||||||
|
|
||||||
@@ -53,36 +55,43 @@ class FeedEntrySubscriber extends AbstractNotificationSubscriber
|
|||||||
do {
|
do {
|
||||||
$results = $Query->limit($start, $perLoop)->execute()->get_results();
|
$results = $Query->limit($start, $perLoop)->execute()->get_results();
|
||||||
|
|
||||||
foreach ($results as $user_to_notif) {
|
$users_emailed = []; // for all users
|
||||||
$mailed = false;
|
$users_to_email = []; // list only users who must be emailed (=create tokens)
|
||||||
|
|
||||||
if ($params['notify_email'] && $this->shouldSendNotificationFor($user_to_notif, 'eventsmanager_notify_feed')) {
|
/** @var User $user */
|
||||||
$readyToSend = false;
|
foreach ($results as $user) {
|
||||||
try {
|
$users_emailed[$user->getId()] = false;
|
||||||
$token = $this->app['manipulator.token']->createFeedEntryToken($user_to_notif, $entry);
|
if ($params['notify_email'] && $this->shouldSendNotificationFor($user, 'eventsmanager_notify_feed')) {
|
||||||
$url = $this->app->url('lightbox', ['LOG' => $token->getValue()]);
|
$users_to_email[$user->getId()] = $user;
|
||||||
|
|
||||||
$receiver = Receiver::fromUser($user_to_notif);
|
|
||||||
$readyToSend = true;
|
|
||||||
} catch (\Exception $e) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($readyToSend) {
|
|
||||||
$mail = MailInfoNewPublication::create($this->app, $receiver);
|
|
||||||
$mail->setButtonUrl($url);
|
|
||||||
$mail->setAuthor($entry->getAuthorName());
|
|
||||||
$mail->setTitle($entry->getTitle());
|
|
||||||
|
|
||||||
$this->deliver($mail);
|
|
||||||
$mailed = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->app['events-manager']->notify($user_to_notif->getId(), 'eventsmanager_notify_feed', $datas, $mailed);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get many tokens in one shot
|
||||||
|
$tokens = $this->getTokenManipulator()->createFeedEntryTokens($users_to_email, $entry);
|
||||||
|
foreach($tokens as $token) {
|
||||||
|
try {
|
||||||
|
$url = $this->app->url('lightbox', ['LOG' => $token->getValue()]);
|
||||||
|
$receiver = Receiver::fromUser($token->getUser());
|
||||||
|
|
||||||
|
$mail = MailInfoNewPublication::create($this->app, $receiver);
|
||||||
|
$mail->setButtonUrl($url);
|
||||||
|
$mail->setAuthor($entry->getAuthorName());
|
||||||
|
$mail->setTitle($entry->getTitle());
|
||||||
|
|
||||||
|
$this->deliver($mail);
|
||||||
|
$users_emailed[$token->getUser()->getId()] = true;
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach($users_emailed as $id => $emailed) {
|
||||||
|
$this->app['events-manager']->notify($id, 'eventsmanager_notify_feed', $datas, $emailed);
|
||||||
|
}
|
||||||
|
|
||||||
$start += $perLoop;
|
$start += $perLoop;
|
||||||
} while (count($results) > 0);
|
}
|
||||||
|
while (count($results) > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getSubscribedEvents()
|
public static function getSubscribedEvents()
|
||||||
@@ -91,4 +100,12 @@ class FeedEntrySubscriber extends AbstractNotificationSubscriber
|
|||||||
PhraseaEvents::FEED_ENTRY_CREATE => 'onCreate',
|
PhraseaEvents::FEED_ENTRY_CREATE => 'onCreate',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return TokenManipulator
|
||||||
|
*/
|
||||||
|
private function getTokenManipulator()
|
||||||
|
{
|
||||||
|
return $this->app['manipulator.token'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -16,7 +16,7 @@ class Version
|
|||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
private $number = '4.1.0-alpha.21a';
|
private $number = '4.1.0-alpha.22a';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var string
|
* @var string
|
||||||
|
@@ -15,7 +15,14 @@ use Doctrine\ORM\Mapping as ORM;
|
|||||||
use Gedmo\Mapping\Annotation as Gedmo;
|
use Gedmo\Mapping\Annotation as Gedmo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ORM\Table(name="Tokens")
|
* @ORM\Table(name="Tokens",
|
||||||
|
* indexes={
|
||||||
|
* @ORM\index(name="type", columns={"type"}),
|
||||||
|
* @ORM\index(name="created", columns={"created"}),
|
||||||
|
* @ORM\index(name="updated", columns={"updated"}),
|
||||||
|
* @ORM\index(name="expiration", columns={"expiration"})
|
||||||
|
* }
|
||||||
|
* )
|
||||||
* @ORM\Entity(repositoryClass="Alchemy\Phrasea\Model\Repositories\TokenRepository")
|
* @ORM\Entity(repositoryClass="Alchemy\Phrasea\Model\Repositories\TokenRepository")
|
||||||
*/
|
*/
|
||||||
class Token
|
class Token
|
||||||
|
@@ -22,7 +22,6 @@ use RandomLib\Generator;
|
|||||||
class TokenManipulator implements ManipulatorInterface
|
class TokenManipulator implements ManipulatorInterface
|
||||||
{
|
{
|
||||||
const LETTERS_AND_NUMBERS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
const LETTERS_AND_NUMBERS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||||
|
|
||||||
const TYPE_FEED_ENTRY = 'FEED_ENTRY';
|
const TYPE_FEED_ENTRY = 'FEED_ENTRY';
|
||||||
const TYPE_PASSWORD = 'password';
|
const TYPE_PASSWORD = 'password';
|
||||||
const TYPE_ACCOUNT_UNLOCK = 'account-unlock';
|
const TYPE_ACCOUNT_UNLOCK = 'account-unlock';
|
||||||
@@ -126,6 +125,38 @@ class TokenManipulator implements ManipulatorInterface
|
|||||||
return $this->create($user, self::TYPE_FEED_ENTRY, null, $entry->getId());
|
return $this->create($user, self::TYPE_FEED_ENTRY, null, $entry->getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create feedEntryTokens for many users in one shot
|
||||||
|
*
|
||||||
|
* @param User[] $users
|
||||||
|
* @param FeedEntry $entry
|
||||||
|
* @return Token[]
|
||||||
|
* @throws \Doctrine\DBAL\DBALException
|
||||||
|
*/
|
||||||
|
public function createFeedEntryTokens($users, FeedEntry $entry)
|
||||||
|
{
|
||||||
|
// $this->removeExpiredTokens();
|
||||||
|
|
||||||
|
$tokens = [];
|
||||||
|
foreach ($users as $user) {
|
||||||
|
$value = $this->random->generateString(32, self::LETTERS_AND_NUMBERS) . $user->getId();
|
||||||
|
|
||||||
|
$token = new Token();
|
||||||
|
$token->setUser($user)
|
||||||
|
->setType(self::TYPE_FEED_ENTRY)
|
||||||
|
->setValue($value)
|
||||||
|
->setExpiration(null)
|
||||||
|
->setData($entry->getId());
|
||||||
|
$tokens[] = $token;
|
||||||
|
|
||||||
|
$this->om->persist($token);
|
||||||
|
}
|
||||||
|
$this->om->flush();
|
||||||
|
$this->om->clear();
|
||||||
|
|
||||||
|
return $tokens;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param User $user
|
* @param User $user
|
||||||
* @param $data
|
* @param $data
|
||||||
|
@@ -72,4 +72,9 @@ class TokenRepository extends EntityRepository
|
|||||||
|
|
||||||
return $query->getResult();
|
return $query->getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getEntityManager()
|
||||||
|
{
|
||||||
|
return parent::getEntityManager();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
75
lib/classes/patch/410alpha22a.php
Normal file
75
lib/classes/patch/410alpha22a.php
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of Phraseanet
|
||||||
|
*
|
||||||
|
* (c) 2005-2019 Alchemy
|
||||||
|
*
|
||||||
|
* For the full copyright and license information, please view the LICENSE
|
||||||
|
* file that was distributed with this source code.
|
||||||
|
*/
|
||||||
|
|
||||||
|
use Alchemy\Phrasea\Application;
|
||||||
|
|
||||||
|
class patch_410alpha22a implements patchInterface
|
||||||
|
{
|
||||||
|
/** @var string */
|
||||||
|
private $release = '4.1.0-alpha.22a';
|
||||||
|
|
||||||
|
/** @var array */
|
||||||
|
private $concern = [base::APPLICATION_BOX];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the release version.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function get_release()
|
||||||
|
{
|
||||||
|
return $this->release;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function concern()
|
||||||
|
{
|
||||||
|
return $this->concern;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function require_all_upgrades()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function getDoctrineMigrations()
|
||||||
|
{
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*/
|
||||||
|
public function apply(base $appbox, Application $app)
|
||||||
|
{
|
||||||
|
foreach(['type', 'created', 'updated', 'expiration'] as $t) {
|
||||||
|
$sql = "ALTER TABLE `Tokens` ADD INDEX `".$t."` (`".$t."`);";
|
||||||
|
try {
|
||||||
|
$stmt = $appbox->get_connection()->prepare($sql);
|
||||||
|
$stmt->execute();
|
||||||
|
$stmt->closeCursor();
|
||||||
|
}
|
||||||
|
catch (\Exception $e) {
|
||||||
|
// the inex already exists ?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
@@ -27,3 +27,17 @@
|
|||||||
|
|
||||||
{# bootstrap admin field backbone application #}
|
{# bootstrap admin field backbone application #}
|
||||||
<script type="text/javascript" src="{{ path('minifier', { 'f' : '/scripts/apps/admin/fields/main.js' }) }}"></script>
|
<script type="text/javascript" src="{{ path('minifier', { 'f' : '/scripts/apps/admin/fields/main.js' }) }}"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(document).ready(function () {
|
||||||
|
$('#admin-field-app').on('change', '#tbranch', function () {
|
||||||
|
if ($(this).val() === '') {
|
||||||
|
$('#generate_cterms').prop('checked', false);
|
||||||
|
$('.generate-cterms').addClass('hidden');
|
||||||
|
} else {
|
||||||
|
$('.generate-cterms').removeClass('hidden');
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@@ -259,11 +259,14 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td><label for="tbranch">{% trans %}Thesaurus branch{% endtrans %}</label></td>
|
<td><label for="tbranch">{% trans %}Thesaurus branch{% endtrans %}</label></td>
|
||||||
<td><input id="tbranch" type="text" value="<%= field.tbranch %>"/></td>
|
<td>
|
||||||
</tr>
|
<input id="tbranch" type="text" value="<%= field.tbranch %>"/>
|
||||||
<tr>
|
<div style="display: inline-block;" <%= (field.tbranch == "") ? "class='generate-cterms hidden'" : "class='generate-cterms'" %> >
|
||||||
<td><label for="generate_cterms" class="checkbox">{% trans %}Generate-cterms{% endtrans %}</label></td>
|
<label for="generate_cterms" class="checkbox">
|
||||||
<td><input id="generate_cterms" type="checkbox" <%= field.generate_cterms ? "checked='checked'" : "" %> /></td>
|
<input id="generate_cterms" type="checkbox" <%= field.generate_cterms ? "checked='checked'" : "" %> />
|
||||||
|
{% trans %}Generate-cterms{% endtrans %}</label>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -30,7 +30,11 @@
|
|||||||
<li><p>{{ 'help::help-section-bullet: search-in-a-specific-field' | trans }}</p></li>
|
<li><p>{{ 'help::help-section-bullet: search-in-a-specific-field' | trans }}</p></li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<p>
|
<br>
|
||||||
<span class="btn btn-info btn-lg trigger-reload-search" onclick="jQuery('.reload-search').trigger('click');">{{ 'help::help-search: relaunch search without filter' | trans }}</span></p>
|
<p class="text-center">{{ 'help::help-search: OR' | trans }}</p>
|
||||||
|
<br>
|
||||||
|
<p class="text-center">
|
||||||
|
<span class="btn btn-info btn-lg trigger-reload-search" onclick="jQuery('.reload-search').trigger('click');">{{ 'help::help-search: relaunch search without filter' | trans }}</span>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
Reference in New Issue
Block a user