mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-18 15:33:15 +00:00
Merge remote-tracking branch 'origin/feature/controller-as-service'
This commit is contained in:
@@ -12,12 +12,6 @@
|
||||
namespace Alchemy\Phrasea;
|
||||
|
||||
use Alchemy\Geonames\GeonamesServiceProvider;
|
||||
use Alchemy\Phrasea\ControllerProvider\Prod\BasketController;
|
||||
use Alchemy\Phrasea\ControllerProvider\Prod\Bridge;
|
||||
use Alchemy\Phrasea\ControllerProvider\Prod\DoDownload;
|
||||
use Alchemy\Phrasea\ControllerProvider\Prod\Download;
|
||||
use Alchemy\Phrasea\ControllerProvider\Prod\Edit;
|
||||
use Alchemy\Phrasea\ControllerProvider\Prod\Export;
|
||||
use Alchemy\Phrasea\ControllerProvider\Prod\Feed;
|
||||
use Alchemy\Phrasea\ControllerProvider\Prod\Language;
|
||||
use Alchemy\Phrasea\ControllerProvider\Prod\Lazaret;
|
||||
@@ -115,6 +109,8 @@ use Dflydev\Silex\Provider\DoctrineOrm\DoctrineOrmServiceProvider;
|
||||
use FFMpeg\FFMpegServiceProvider;
|
||||
use Gedmo\DoctrineExtensions as GedmoExtension;
|
||||
use MediaAlchemyst\MediaAlchemystServiceProvider;
|
||||
use MediaVorus\Media\MediaInterface;
|
||||
use MediaVorus\MediaVorus;
|
||||
use MediaVorus\MediaVorusServiceProvider;
|
||||
use Monolog\Handler\NullHandler;
|
||||
use Monolog\Logger;
|
||||
@@ -313,6 +309,12 @@ class Application extends SilexApplication
|
||||
'Alchemy\Phrasea\ControllerProvider\Admin\TaskManager' => [],
|
||||
'Alchemy\Phrasea\ControllerProvider\Admin\Users' => [],
|
||||
'Alchemy\Phrasea\ControllerProvider\Client\Root' => [],
|
||||
'Alchemy\Phrasea\ControllerProvider\Prod\BasketProvider' => [],
|
||||
'Alchemy\Phrasea\ControllerProvider\Prod\Bridge' => [],
|
||||
'Alchemy\Phrasea\ControllerProvider\Prod\DoDownload' => [],
|
||||
'Alchemy\Phrasea\ControllerProvider\Prod\Download' => [],
|
||||
'Alchemy\Phrasea\ControllerProvider\Prod\Edit' => [],
|
||||
'Alchemy\Phrasea\ControllerProvider\Prod\Export' => [],
|
||||
'Alchemy\Phrasea\ControllerProvider\Datafiles' => [],
|
||||
'Alchemy\Phrasea\ControllerProvider\Lightbox' => [],
|
||||
'Alchemy\Phrasea\ControllerProvider\Minifier' => [],
|
||||
@@ -594,7 +596,7 @@ class Application extends SilexApplication
|
||||
/**
|
||||
* Returns true if application has terms of use
|
||||
*
|
||||
* @return noolean
|
||||
* @return bool
|
||||
*/
|
||||
public function hasTermsOfUse()
|
||||
{
|
||||
@@ -624,20 +626,15 @@ class Application extends SilexApplication
|
||||
|
||||
$this->mount('/prod/query/', new Query());
|
||||
$this->mount('/prod/order/', new Order());
|
||||
$this->mount('/prod/baskets', new BasketController());
|
||||
$this->mount('/prod/download', new Download());
|
||||
$this->mount('/prod/story', new Story());
|
||||
$this->mount('/prod/WorkZone', new WorkZone());
|
||||
$this->mount('/prod/lists', new UsrLists());
|
||||
$this->mount('/prod/records/', new Records());
|
||||
$this->mount('/prod/records/edit', new Edit());
|
||||
$this->mount('/prod/records/property', new Property());
|
||||
$this->mount('/prod/records/movecollection', new MoveCollection());
|
||||
$this->mount('/prod/bridge/', new Bridge());
|
||||
$this->mount('/prod/push/', new Push());
|
||||
$this->mount('/prod/printer/', new Printer());
|
||||
$this->mount('/prod/share/', new Share());
|
||||
$this->mount('/prod/export/', new Export());
|
||||
$this->mount('/prod/TOU/', new TOU());
|
||||
$this->mount('/prod/feeds', new Feed());
|
||||
$this->mount('/prod/tooltip', new Tooltip());
|
||||
@@ -650,7 +647,6 @@ class Application extends SilexApplication
|
||||
$this->mount('/user/preferences/', new Preferences());
|
||||
$this->mount('/user/notifications/', new Notifications());
|
||||
|
||||
$this->mount('/download/', new DoDownload());
|
||||
$this->mount('/session/', new Session());
|
||||
|
||||
$this->mount('/report/', new ReportRoot());
|
||||
@@ -676,9 +672,15 @@ class Application extends SilexApplication
|
||||
'/admin/users' => 'Alchemy\Phrasea\ControllerProvider\Admin\Users',
|
||||
'/client/' => 'Alchemy\Phrasea\ControllerProvider\Client\Root',
|
||||
'/datafiles' => 'Alchemy\Phrasea\ControllerProvider\Datafiles',
|
||||
'/download/' => 'Alchemy\Phrasea\ControllerProvider\Prod\DoDownload',
|
||||
'/include/minify' => 'Alchemy\Phrasea\ControllerProvider\Minifier',
|
||||
'/lightbox' => 'Alchemy\Phrasea\ControllerProvider\Lightbox',
|
||||
'/permalink' => 'Alchemy\Phrasea\ControllerProvider\Permalink',
|
||||
'/prod/baskets' => 'Alchemy\Phrasea\ControllerProvider\Prod\BasketProvider',
|
||||
'/prod/bridge/' => 'Alchemy\Phrasea\ControllerProvider\Prod\Bridge',
|
||||
'/prod/download' => 'Alchemy\Phrasea\ControllerProvider\Prod\Download',
|
||||
'/prod/export/' => 'Alchemy\Phrasea\ControllerProvider\Prod\Export',
|
||||
'/prod/records/edit' => 'Alchemy\Phrasea\ControllerProvider\Prod\Edit',
|
||||
'/setup' => 'Alchemy\Phrasea\ControllerProvider\Setup',
|
||||
];
|
||||
foreach ($providers as $prefix => $class) {
|
||||
@@ -706,6 +708,21 @@ class Application extends SilexApplication
|
||||
return static::$flashTypes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Media instance given a file uri.
|
||||
*
|
||||
* @param string $uri
|
||||
*
|
||||
* @return MediaInterface
|
||||
*/
|
||||
public function getMediaFromUri($uri)
|
||||
{
|
||||
/** @var MediaVorus $mediavorus */
|
||||
$mediavorus = $this['mediavorus'];
|
||||
|
||||
return $mediavorus->guess($uri);
|
||||
}
|
||||
|
||||
private function setupApplicationPaths()
|
||||
{
|
||||
// app root path
|
||||
|
65
lib/Alchemy/Phrasea/Application/Helper/DispatcherAware.php
Normal file
65
lib/Alchemy/Phrasea/Application/Helper/DispatcherAware.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2015 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Alchemy\Phrasea\Application\Helper;
|
||||
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
trait DispatcherAware
|
||||
{
|
||||
private $dispatcher;
|
||||
|
||||
/**
|
||||
* Set Locator to use to locate event dispatcher
|
||||
*
|
||||
* @param callable $locator
|
||||
* @return $this
|
||||
*/
|
||||
public function setDispatcherLocator(callable $locator)
|
||||
{
|
||||
$this->dispatcher = $locator;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return EventDispatcherInterface
|
||||
*/
|
||||
public function getDispatcher()
|
||||
{
|
||||
if ($this->dispatcher instanceof EventDispatcherInterface) {
|
||||
return $this->dispatcher;
|
||||
}
|
||||
|
||||
if (null === $this->dispatcher) {
|
||||
throw new \LogicException('Dispatcher locator was not set');
|
||||
}
|
||||
|
||||
$dispatcher = call_user_func($this->dispatcher);
|
||||
if (!$dispatcher instanceof EventDispatcherInterface) {
|
||||
throw new \LogicException(sprintf(
|
||||
'Expects locator to return instance of "%s", got "%s"',
|
||||
EventDispatcherInterface::class,
|
||||
is_object($dispatcher) ? get_class($dispatcher) : gettype($dispatcher)
|
||||
));
|
||||
}
|
||||
$this->dispatcher = $dispatcher;
|
||||
|
||||
return $this->dispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \Symfony\Component\EventDispatcher\EventDispatcherInterface::dispatch
|
||||
*/
|
||||
public function dispatch($eventName, Event $event = null)
|
||||
{
|
||||
return $this->getDispatcher()->dispatch($eventName, $event);
|
||||
}
|
||||
}
|
56
lib/Alchemy/Phrasea/Application/Helper/FileSystemAware.php
Normal file
56
lib/Alchemy/Phrasea/Application/Helper/FileSystemAware.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2015 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Alchemy\Phrasea\Application\Helper;
|
||||
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
|
||||
trait FilesystemAware
|
||||
{
|
||||
private $filesystem;
|
||||
|
||||
/**
|
||||
* Set Locator to use to locate FileSystem
|
||||
*
|
||||
* @param callable $locator
|
||||
* @return $this
|
||||
*/
|
||||
public function setFileSystemLocator(callable $locator)
|
||||
{
|
||||
$this->filesystem = $locator;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Filesystem
|
||||
*/
|
||||
public function getFilesystem()
|
||||
{
|
||||
if ($this->filesystem instanceof Filesystem) {
|
||||
return $this->filesystem;
|
||||
}
|
||||
|
||||
if (null === $this->filesystem) {
|
||||
throw new \LogicException('Filesystem locator was not set');
|
||||
}
|
||||
|
||||
$instance = call_user_func($this->filesystem);
|
||||
if (!$instance instanceof Filesystem) {
|
||||
throw new \LogicException(sprintf(
|
||||
'Expects locator to return instance of "%s", got "%s"',
|
||||
Filesystem::class,
|
||||
is_object($instance) ? get_class($instance) : gettype($instance)
|
||||
));
|
||||
}
|
||||
$this->filesystem = $instance;
|
||||
|
||||
return $this->filesystem;
|
||||
}
|
||||
}
|
68
lib/Alchemy/Phrasea/Application/Helper/NotifierAware.php
Normal file
68
lib/Alchemy/Phrasea/Application/Helper/NotifierAware.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2015 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Alchemy\Phrasea\Application\Helper;
|
||||
|
||||
use Alchemy\Phrasea\Notification\Deliverer;
|
||||
use Alchemy\Phrasea\Notification\Mail\MailInterface;
|
||||
|
||||
trait NotifierAware
|
||||
{
|
||||
private $deliverer;
|
||||
|
||||
/**
|
||||
* Set Locator to use to locate Deliverer
|
||||
*
|
||||
* @param callable $locator
|
||||
* @return $this
|
||||
*/
|
||||
public function setDelivererLocator(callable $locator)
|
||||
{
|
||||
$this->deliverer = $locator;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Deliverer
|
||||
*/
|
||||
public function getDeliverer()
|
||||
{
|
||||
if ($this->deliverer instanceof Deliverer) {
|
||||
return $this->deliverer;
|
||||
}
|
||||
|
||||
if (null === $this->deliverer) {
|
||||
throw new \LogicException('Locator was not set');
|
||||
}
|
||||
|
||||
$instance = call_user_func($this->deliverer);
|
||||
if (!$instance instanceof Deliverer) {
|
||||
throw new \LogicException(sprintf(
|
||||
'Expects locator to return instance of "%s", got "%s"',
|
||||
Deliverer::class,
|
||||
is_object($instance) ? get_class($instance) : gettype($instance)
|
||||
));
|
||||
}
|
||||
$this->deliverer = $instance;
|
||||
|
||||
return $this->deliverer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param MailInterface $mail
|
||||
* @param bool $readReceipt
|
||||
* @param array $attachments
|
||||
* @return int
|
||||
*/
|
||||
public function deliver(MailInterface $mail, $readReceipt = false, array $attachments = null)
|
||||
{
|
||||
return $this->getDeliverer()->deliver($mail, $readReceipt, $attachments);
|
||||
}
|
||||
}
|
@@ -22,10 +22,10 @@ use Monolog\Logger;
|
||||
use Monolog\Processor\WebProcessor;
|
||||
use Silex\Provider\WebProfilerServiceProvider;
|
||||
use Sorien\Provider\DoctrineProfilerServiceProvider;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
return call_user_func(function ($environment = PhraseaApplication::ENV_PROD) {
|
||||
|
||||
$app = new PhraseaApplication($environment);
|
||||
$app->loadPlugins();
|
||||
|
||||
@@ -74,7 +74,7 @@ return call_user_func(function ($environment = PhraseaApplication::ENV_PROD) {
|
||||
}
|
||||
|
||||
$app['dispatcher'] = $app->share(
|
||||
$app->extend('dispatcher', function ($dispatcher, PhraseaApplication $app) {
|
||||
$app->extend('dispatcher', function (EventDispatcherInterface $dispatcher, PhraseaApplication $app) {
|
||||
$dispatcher->addSubscriber(new BridgeExceptionSubscriber($app));
|
||||
$dispatcher->addSubscriber(new FirewallSubscriber());
|
||||
$dispatcher->addSubscriber(new JsonRequestSubscriber());
|
||||
|
@@ -41,7 +41,7 @@ class File
|
||||
|
||||
/**
|
||||
*
|
||||
* @var \MediaVorus\Media\MediaInterface
|
||||
* @var MediaInterface
|
||||
*/
|
||||
protected $media;
|
||||
protected $uuid;
|
||||
@@ -54,7 +54,7 @@ class File
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param Applciation $app Application context
|
||||
* @param Application $app Application context
|
||||
* @param MediaInterface $media The media
|
||||
* @param \collection $collection The destination collection
|
||||
* @param string $originalName The original name of the file
|
||||
@@ -227,7 +227,7 @@ class File
|
||||
/**
|
||||
* Returns an instance of MediaVorus\Media\MediaInterface corresponding to the file
|
||||
*
|
||||
* @return MediaVorus\Media\MediaInterface
|
||||
* @return MediaInterface
|
||||
*/
|
||||
public function getMedia()
|
||||
{
|
||||
@@ -282,7 +282,7 @@ class File
|
||||
public static function buildFromPathfile($pathfile, \collection $collection, Application $app, $originalName = null)
|
||||
{
|
||||
try {
|
||||
$media = $app['mediavorus']->guess($pathfile);
|
||||
$media = $app->getMediaFromUri($pathfile);
|
||||
} catch (FileNotFoundException $e) {
|
||||
throw new \InvalidArgumentException(sprintf('Unable to build media file from non existant %s', $pathfile));
|
||||
}
|
||||
|
@@ -124,7 +124,7 @@ class Step31 implements DatasUpgraderInterface
|
||||
|
||||
$uuid = Uuid::uuid4();
|
||||
try {
|
||||
$media = $this->app['mediavorus']->guess($pathfile);
|
||||
$media = $this->app->getMediaFromUri($pathfile);
|
||||
$collection = \collection::get_from_coll_id($this->$app, $databox, (int) $record['coll_id']);
|
||||
|
||||
$file = new File($this->app, $media, $collection);
|
||||
|
@@ -10,7 +10,7 @@
|
||||
|
||||
namespace Alchemy\Phrasea\Controller\Admin;
|
||||
|
||||
use Alchemy\Phrasea\Application;
|
||||
use Alchemy\Phrasea\Application\Helper\NotifierAware;
|
||||
use Alchemy\Phrasea\Authentication\Authenticator;
|
||||
use Alchemy\Phrasea\Cache\Cache;
|
||||
use Alchemy\Phrasea\Controller\Controller;
|
||||
@@ -19,7 +19,6 @@ use Alchemy\Phrasea\Exception\RuntimeException;
|
||||
use Alchemy\Phrasea\Model\Manipulator\ACLManipulator;
|
||||
use Alchemy\Phrasea\Model\Manipulator\UserManipulator;
|
||||
use Alchemy\Phrasea\Model\Repositories\UserRepository;
|
||||
use Alchemy\Phrasea\Notification\Deliverer;
|
||||
use Alchemy\Phrasea\Notification\Mail\MailTest;
|
||||
use Alchemy\Phrasea\Notification\Receiver;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
@@ -27,6 +26,8 @@ use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class DashboardController extends Controller
|
||||
{
|
||||
use NotifierAware;
|
||||
|
||||
/**
|
||||
* Display admin dashboard page
|
||||
*
|
||||
@@ -89,9 +90,7 @@ class DashboardController extends Controller
|
||||
|
||||
$mail = MailTest::create($this->app, $receiver);
|
||||
|
||||
/** @var Deliverer $deliverer */
|
||||
$deliverer = $this->app['notification.deliverer'];
|
||||
$deliverer->deliver($mail);
|
||||
$this->deliver($mail);
|
||||
|
||||
/** @var \Swift_SpoolTransport $spoolTransport */
|
||||
$spoolTransport = $this->app['swiftmailer.spooltransport'];
|
||||
|
@@ -152,9 +152,7 @@ class FeedController extends Controller
|
||||
throw new BadRequestHttpException('Uploaded file is invalid');
|
||||
}
|
||||
|
||||
/** @var MediaVorus $mediavorus */
|
||||
$mediavorus = $this->app['mediavorus'];
|
||||
$media = $mediavorus->guess($file->getPathname());
|
||||
$media = $this->app->getMediaFromUri($file->getPathname());
|
||||
|
||||
if ($media->getType() !== MediaInterface::TYPE_IMAGE) {
|
||||
throw new BadRequestHttpException('Bad filetype');
|
||||
|
@@ -10,6 +10,7 @@
|
||||
|
||||
namespace Alchemy\Phrasea\Controller\Admin;
|
||||
|
||||
use Alchemy\Phrasea\Application\Helper\DispatcherAware;
|
||||
use Alchemy\Phrasea\Controller\Controller;
|
||||
use Alchemy\Phrasea\Exception\InvalidArgumentException;
|
||||
use Alchemy\Phrasea\Exception\RuntimeException;
|
||||
@@ -21,8 +22,6 @@ use Alchemy\Phrasea\TaskManager\Job\Factory;
|
||||
use Alchemy\Phrasea\TaskManager\LiveInformation;
|
||||
use Alchemy\Phrasea\TaskManager\Log\LogFileFactory;
|
||||
use Alchemy\Phrasea\TaskManager\TaskManagerStatus;
|
||||
use Silex\Application;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
@@ -30,6 +29,8 @@ use Symfony\Component\Process\Process;
|
||||
|
||||
class TaskManagerController extends Controller
|
||||
{
|
||||
use DispatcherAware;
|
||||
|
||||
public function startScheduler()
|
||||
{
|
||||
/** @var TaskManagerStatus $status */
|
||||
@@ -43,9 +44,7 @@ class TaskManagerController extends Controller
|
||||
'task-manager:scheduler:run'
|
||||
);
|
||||
|
||||
/** @var EventDispatcherInterface $dispatcher */
|
||||
$dispatcher = $this->app['dispatcher'];
|
||||
$dispatcher->addListener(KernelEvents::TERMINATE, function () use ($cmdLine) {
|
||||
$this->getDispatcher()->addListener(KernelEvents::TERMINATE, function () use ($cmdLine) {
|
||||
$process = new Process($cmdLine);
|
||||
$process->setTimeout(0);
|
||||
$process->disableOutput();
|
||||
|
@@ -10,6 +10,7 @@
|
||||
|
||||
namespace Alchemy\Phrasea\Controller\Admin;
|
||||
|
||||
use Alchemy\Phrasea\Application\Helper\NotifierAware;
|
||||
use Alchemy\Phrasea\Controller\Controller;
|
||||
use Alchemy\Phrasea\Core\Response\CSVFileResponse;
|
||||
use Alchemy\Phrasea\Helper\User as UserHelper;
|
||||
@@ -20,7 +21,6 @@ use Alchemy\Phrasea\Model\Manipulator\UserManipulator;
|
||||
use Alchemy\Phrasea\Model\NativeQueryProvider;
|
||||
use Alchemy\Phrasea\Model\Repositories\RegistrationRepository;
|
||||
use Alchemy\Phrasea\Model\Repositories\UserRepository;
|
||||
use Alchemy\Phrasea\Notification\Deliverer;
|
||||
use Alchemy\Phrasea\Notification\Mail\MailSuccessEmailUpdate;
|
||||
use Alchemy\Phrasea\Notification\Receiver;
|
||||
use Goodby\CSV\Export\Protocol\ExporterInterface;
|
||||
@@ -30,6 +30,8 @@ use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class UserController extends Controller
|
||||
{
|
||||
use NotifierAware;
|
||||
|
||||
public function editRightsAction(Request $request)
|
||||
{
|
||||
$rights = $this->getUserEditHelper($request);
|
||||
@@ -507,9 +509,7 @@ class UserController extends Controller
|
||||
$receiver = new Receiver(null, $user->getEmail());
|
||||
$mail = MailSuccessEmailUpdate::create($this->app, $receiver, null, $message);
|
||||
|
||||
/** @var Deliverer $deliverer */
|
||||
$deliverer = $this->app['notification.deliverer'];
|
||||
$deliverer->deliver($mail);
|
||||
$this->deliver($mail);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -10,6 +10,7 @@
|
||||
namespace Alchemy\Phrasea\Controller\Api;
|
||||
|
||||
use Alchemy\Phrasea\Application;
|
||||
use Alchemy\Phrasea\Application\Helper\DispatcherAware;
|
||||
use Alchemy\Phrasea\Authentication\Context;
|
||||
use Alchemy\Phrasea\Authentication\Exception\AccountLockedException;
|
||||
use Alchemy\Phrasea\Authentication\Exception\RequireCaptchaException;
|
||||
@@ -20,7 +21,6 @@ use Alchemy\Phrasea\Core\Event\PreAuthenticate;
|
||||
use Alchemy\Phrasea\Core\PhraseaEvents;
|
||||
use Alchemy\Phrasea\Model\Manipulator\ApiAccountManipulator;
|
||||
use Alchemy\Phrasea\Model\Repositories\ApiApplicationRepository;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\Session\Session;
|
||||
@@ -29,16 +29,15 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
class OAuth2Controller extends Controller
|
||||
{
|
||||
use DispatcherAware;
|
||||
|
||||
/** @var \API_OAuth2_Adapter */
|
||||
private $oAuth2Adapter;
|
||||
/** @var EventDispatcherInterface */
|
||||
private $dispatcher;
|
||||
|
||||
public function __construct(Application $app)
|
||||
{
|
||||
parent::__construct($app);
|
||||
$this->oAuth2Adapter = $app['oauth2-server'];
|
||||
$this->dispatcher = $app['dispatcher'];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -52,7 +51,7 @@ class OAuth2Controller extends Controller
|
||||
public function authorizeAction(Request $request)
|
||||
{
|
||||
$context = new Context(Context::CONTEXT_OAUTH2_NATIVE);
|
||||
$this->dispatcher->dispatch(PhraseaEvents::PRE_AUTHENTICATE, new PreAuthenticate($request, $context));
|
||||
$this->dispatch(PhraseaEvents::PRE_AUTHENTICATE, new PreAuthenticate($request, $context));
|
||||
|
||||
//Check for auth params, send error or redirect if not valid
|
||||
$params = $this->oAuth2Adapter->getAuthorizationRequestParameters($request);
|
||||
@@ -106,7 +105,7 @@ class OAuth2Controller extends Controller
|
||||
$user = $this->app['repo.users']->find($usrId);
|
||||
$this->getAuthenticator()->openAccount($user);
|
||||
$event = new PostAuthenticate($request, new Response(), $user, $context);
|
||||
$this->dispatcher->dispatch(PhraseaEvents::POST_AUTHENTICATE, $event);
|
||||
$this->dispatch(PhraseaEvents::POST_AUTHENTICATE, $event);
|
||||
} else {
|
||||
$r = new Response($this->render($template, array('error' => $error, "auth" => $this->oAuth2Adapter)));
|
||||
$r->headers->set('Content-Type', 'text/html');
|
||||
|
@@ -9,6 +9,7 @@
|
||||
*/
|
||||
namespace Alchemy\Phrasea\Controller\Api;
|
||||
|
||||
use Alchemy\Phrasea\Application\Helper\DispatcherAware;
|
||||
use Alchemy\Phrasea\Authentication\Context;
|
||||
use Alchemy\Phrasea\Border\Attribute\Status;
|
||||
use Alchemy\Phrasea\Border\Checker\Response as CheckerResponse;
|
||||
@@ -58,7 +59,6 @@ use JsonSchema\Uri\UriRetriever;
|
||||
use JsonSchema\Validator;
|
||||
use MediaVorus\MediaVorus;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
@@ -68,6 +68,8 @@ use Symfony\Component\Translation\TranslatorInterface;
|
||||
|
||||
class V1Controller extends Controller
|
||||
{
|
||||
use DispatcherAware;
|
||||
|
||||
const OBJECT_TYPE_USER = 'http://api.phraseanet.com/api/objects/user';
|
||||
const OBJECT_TYPE_STORY = 'http://api.phraseanet.com/api/objects/story';
|
||||
const OBJECT_TYPE_STORY_METADATA_BAG = 'http://api.phraseanet.com/api/objects/story-metadata-bag';
|
||||
@@ -769,9 +771,7 @@ class V1Controller extends Controller
|
||||
))->createResponse();
|
||||
}
|
||||
|
||||
/** @var MediaVorus $mediavorus */
|
||||
$mediavorus = $this->app['mediavorus'];
|
||||
$media = $mediavorus->guess($file->getPathname());
|
||||
$media = $this->app->getMediaFromUri($file->getPathname());
|
||||
|
||||
$Package = new File($this->app, $media, $collection, $file->getClientOriginalName());
|
||||
|
||||
@@ -858,9 +858,7 @@ class V1Controller extends Controller
|
||||
return $this->getBadRequestAction($request, 'Missing name parameter');
|
||||
}
|
||||
|
||||
/** @var MediaVorus $mediavorus */
|
||||
$mediavorus = $this->app['mediavorus'];
|
||||
$media = $mediavorus->guess($file->getPathname());
|
||||
$media = $this->app->getMediaFromUri($file->getPathname());
|
||||
$record = $this->findDataboxById($request->get('databox_id'))->get_record($request->get('record_id'));
|
||||
$base_id = $record->get_base_id();
|
||||
$collection = \collection::get_from_base_id($this->app, $base_id);
|
||||
@@ -2140,9 +2138,7 @@ class V1Controller extends Controller
|
||||
if (!in_array($name, array('thumbnail', 'preview'))) {
|
||||
continue;
|
||||
}
|
||||
/** @var MediaVorus $mediavorus */
|
||||
$mediavorus = $this->app['mediavorus'];
|
||||
$media = $mediavorus->guess($value->get_pathfile());
|
||||
$media = $this->app->getMediaFromUri($value->get_pathfile());
|
||||
$story->substitute_subdef($name, $media, $this->app);
|
||||
$this->app['phraseanet.logger']($story->get_databox())->log(
|
||||
$story,
|
||||
@@ -2254,14 +2250,6 @@ class V1Controller extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return EventDispatcherInterface
|
||||
*/
|
||||
private function getDispatcher()
|
||||
{
|
||||
return $this->app['dispatcher'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \API_OAuth2_Adapter
|
||||
*/
|
||||
|
@@ -10,8 +10,7 @@
|
||||
|
||||
namespace Alchemy\Phrasea\Controller;
|
||||
|
||||
use Alchemy\Phrasea\Application;
|
||||
use Alchemy\Phrasea\Authentication\Authenticator;
|
||||
use Alchemy\Phrasea\Application\Helper\DispatcherAware;
|
||||
use Alchemy\Phrasea\Core\Event\ValidationEvent;
|
||||
use Alchemy\Phrasea\Core\PhraseaEvents;
|
||||
use Alchemy\Phrasea\Exception\SessionNotFound;
|
||||
@@ -26,6 +25,8 @@ use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class LightboxController extends Controller
|
||||
{
|
||||
use DispatcherAware;
|
||||
|
||||
public function rootAction()
|
||||
{
|
||||
try {
|
||||
@@ -436,8 +437,7 @@ class LightboxController extends Controller
|
||||
$token = $this->app['manipulator.token']->createBasketValidationToken($basket);
|
||||
$url = $this->app->url('lightbox', ['LOG' => $token->getValue()]);
|
||||
|
||||
$this->app['dispatcher']
|
||||
->dispatch(PhraseaEvents::VALIDATION_DONE, new ValidationEvent($participant, $basket, $url));
|
||||
$this->dispatch(PhraseaEvents::VALIDATION_DONE, new ValidationEvent($participant, $basket, $url));
|
||||
|
||||
$participant->setIsConfirmed(true);
|
||||
|
||||
|
325
lib/Alchemy/Phrasea/Controller/Prod/BasketController.php
Normal file
325
lib/Alchemy/Phrasea/Controller/Prod/BasketController.php
Normal file
@@ -0,0 +1,325 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2015 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 Alchemy\Phrasea\Application;
|
||||
use Alchemy\Phrasea\Controller\Controller;
|
||||
use Alchemy\Phrasea\Controller\RecordsRequest;
|
||||
use Alchemy\Phrasea\Model\Entities\Basket;
|
||||
use Alchemy\Phrasea\Model\Entities\BasketElement;
|
||||
use Alchemy\Phrasea\Model\Entities\ValidationData;
|
||||
use Alchemy\Phrasea\Model\Repositories\BasketElementRepository;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
class BasketController extends Controller
|
||||
{
|
||||
public function displayBasket(Request $request, Basket $basket)
|
||||
{
|
||||
if ($basket->getIsRead() === false) {
|
||||
$basket->setIsRead(true);
|
||||
$this->getEntityManager()->flush();
|
||||
}
|
||||
|
||||
if ($basket->getValidation()) {
|
||||
if ($basket->getValidation()->getParticipant($this->getAuthenticatedUser())->getIsAware() === false) {
|
||||
$basket->getValidation()->getParticipant($this->getAuthenticatedUser())->setIsAware(true);
|
||||
$this->getEntityManager()->flush();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->render('prod/WorkZone/Basket.html.twig', [
|
||||
'basket' => $basket,
|
||||
'ordre' => $request->query->get('order'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function createBasket(Request $request)
|
||||
{
|
||||
$Basket = new Basket();
|
||||
|
||||
$Basket->setName($request->request->get('name', ''));
|
||||
$Basket->setUser($this->getAuthenticatedUser());
|
||||
$Basket->setDescription($request->request->get('desc'));
|
||||
|
||||
$this->getEntityManager()->persist($Basket);
|
||||
|
||||
$n = 0;
|
||||
|
||||
$records = RecordsRequest::fromRequest($this->app, $request, true);
|
||||
|
||||
foreach ($records as $record) {
|
||||
if ($Basket->hasRecord($this->app, $record)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$basket_element = new BasketElement();
|
||||
$basket_element->setRecord($record);
|
||||
$basket_element->setBasket($Basket);
|
||||
|
||||
$this->getEntityManager()->persist($basket_element);
|
||||
|
||||
$Basket->addElement($basket_element);
|
||||
|
||||
$n++;
|
||||
}
|
||||
|
||||
$this->getEntityManager()->flush();
|
||||
|
||||
if ($request->getRequestFormat() === 'json') {
|
||||
$data = [
|
||||
'success' => true,
|
||||
'message' => $this->app->trans('Basket created'),
|
||||
'basket' => [
|
||||
'id' => $Basket->getId(),
|
||||
]
|
||||
];
|
||||
|
||||
return $this->app->json($data);
|
||||
}
|
||||
|
||||
return $this->app->redirectPath('prod_baskets_basket', ['basket' => $Basket->getId()]);
|
||||
}
|
||||
|
||||
public function deleteBasket(Request $request, Basket $basket)
|
||||
{
|
||||
$this->getEntityManager()->remove($basket);
|
||||
$this->getEntityManager()->flush();
|
||||
|
||||
$data = [
|
||||
'success' => true
|
||||
, 'message' => $this->app->trans('Basket has been deleted')
|
||||
];
|
||||
|
||||
if ($request->getRequestFormat() === 'json') {
|
||||
return $this->app->json($data);
|
||||
}
|
||||
|
||||
return $this->app->redirectPath('prod_workzone_show');
|
||||
}
|
||||
|
||||
public function removeBasketElement(Request $request, Basket $basket, $basket_element_id)
|
||||
{
|
||||
/** @var BasketElement $basketElement */
|
||||
$basketElement = $this->getEntityManager()->getRepository('Phraseanet:BasketElement')->find($basket_element_id);
|
||||
$ord = $basketElement->getOrd();
|
||||
|
||||
foreach ($basket->getElements() as $basket_element) {
|
||||
if ($basket_element->getOrd() > $ord) {
|
||||
$basket_element->setOrd($basket_element->getOrd() - 1);
|
||||
}
|
||||
if ($basket_element->getId() === (int) $basket_element_id) {
|
||||
$basket->removeElement($basket_element);
|
||||
$this->getEntityManager()->remove($basket_element);
|
||||
}
|
||||
}
|
||||
|
||||
$this->getEntityManager()->persist($basket);
|
||||
$this->getEntityManager()->flush();
|
||||
|
||||
$data = ['success' => true, 'message' => $this->app->trans('Record removed from basket')];
|
||||
|
||||
if ($request->getRequestFormat() === 'json') {
|
||||
return $this->app->json($data);
|
||||
}
|
||||
|
||||
return $this->app->redirectPath('prod_workzone_show');
|
||||
}
|
||||
|
||||
public function updateBasket(Request $request, Basket $basket)
|
||||
{
|
||||
$success = false;
|
||||
|
||||
try {
|
||||
$basket->setName($request->request->get('name', ''));
|
||||
$basket->setDescription($request->request->get('description'));
|
||||
|
||||
$this->getEntityManager()->merge($basket);
|
||||
$this->getEntityManager()->flush();
|
||||
|
||||
$success = true;
|
||||
$msg = $this->app->trans('Basket has been updated');
|
||||
} catch (NotFoundHttpException $e) {
|
||||
$msg = $this->app->trans('The requested basket does not exist');
|
||||
} catch (AccessDeniedHttpException $e) {
|
||||
$msg = $this->app->trans('You do not have access to this basket');
|
||||
} catch (\Exception $e) {
|
||||
$msg = $this->app->trans('An error occurred');
|
||||
}
|
||||
|
||||
$data = [
|
||||
'success' => $success,
|
||||
'message' => $msg,
|
||||
'basket' => ['id' => $basket->getId()],
|
||||
];
|
||||
|
||||
if ($request->getRequestFormat() === 'json') {
|
||||
return $this->app->json($data);
|
||||
}
|
||||
|
||||
return $this->app->redirectPath('prod_workzone_show');
|
||||
}
|
||||
|
||||
public function displayUpdateForm(Basket $basket)
|
||||
{
|
||||
return $this->render('prod/Baskets/Update.html.twig', ['basket' => $basket]);
|
||||
}
|
||||
|
||||
public function displayReorderForm(Basket $basket)
|
||||
{
|
||||
return $this->render('prod/Baskets/Reorder.html.twig', ['basket' => $basket]);
|
||||
}
|
||||
|
||||
public function reorder(Request $request, Basket $basket)
|
||||
{
|
||||
$ret = ['success' => false, 'message' => $this->app->trans('An error occured')];
|
||||
try {
|
||||
$order = $request->request->get('element');
|
||||
|
||||
foreach ($basket->getElements() as $basketElement) {
|
||||
if (isset($order[$basketElement->getId()])) {
|
||||
$basketElement->setOrd($order[$basketElement->getId()]);
|
||||
|
||||
$this->getEntityManager()->merge($basketElement);
|
||||
}
|
||||
}
|
||||
|
||||
$this->getEntityManager()->flush();
|
||||
$ret = ['success' => true, 'message' => $this->app->trans('Basket updated')];
|
||||
} catch (\Exception $e) {
|
||||
|
||||
}
|
||||
|
||||
return $this->app->json($ret);
|
||||
}
|
||||
|
||||
public function archiveBasket(Request $request, Basket $basket)
|
||||
{
|
||||
$archive_status = (Boolean) $request->query->get('archive');
|
||||
|
||||
$basket->setArchived($archive_status);
|
||||
|
||||
$this->getEntityManager()->merge($basket);
|
||||
$this->getEntityManager()->flush();
|
||||
|
||||
if ($archive_status) {
|
||||
$message = $this->app->trans('Basket has been archived');
|
||||
} else {
|
||||
$message = $this->app->trans('Basket has been unarchived');
|
||||
}
|
||||
|
||||
$data = [
|
||||
'success' => true,
|
||||
'archive' => $archive_status,
|
||||
'message' => $message,
|
||||
];
|
||||
|
||||
if ($request->getRequestFormat() === 'json') {
|
||||
return $this->app->json($data);
|
||||
}
|
||||
|
||||
return $this->app->redirectPath('prod_workzone_show');
|
||||
}
|
||||
|
||||
public function addElements(Request $request, Basket $basket)
|
||||
{
|
||||
$n = 0;
|
||||
|
||||
$records = RecordsRequest::fromRequest($this->app, $request, true);
|
||||
|
||||
$em = $this->getEntityManager();
|
||||
foreach ($records as $record) {
|
||||
if ($basket->hasRecord($this->app, $record))
|
||||
continue;
|
||||
|
||||
$basket_element = new BasketElement();
|
||||
$basket_element->setRecord($record);
|
||||
$basket_element->setBasket($basket);
|
||||
|
||||
$em->persist($basket_element);
|
||||
|
||||
$basket->addElement($basket_element);
|
||||
|
||||
if (null !== $validationSession = $basket->getValidation()) {
|
||||
|
||||
$participants = $validationSession->getParticipants();
|
||||
|
||||
foreach ($participants as $participant) {
|
||||
$validationData = new ValidationData();
|
||||
$validationData->setParticipant($participant);
|
||||
$validationData->setBasketElement($basket_element);
|
||||
|
||||
$em->persist($validationData);
|
||||
}
|
||||
}
|
||||
|
||||
$n++;
|
||||
}
|
||||
|
||||
$em->flush();
|
||||
|
||||
$data = [
|
||||
'success' => true,
|
||||
'message' => $this->app->trans('%quantity% records added', ['%quantity%' => $n]),
|
||||
];
|
||||
|
||||
if ($request->getRequestFormat() === 'json') {
|
||||
return $this->app->json($data);
|
||||
}
|
||||
|
||||
return $this->app->redirectPath('prod_workzone_show');
|
||||
}
|
||||
|
||||
public function stealElements(Request $request, Basket $basket)
|
||||
{
|
||||
$n = 0;
|
||||
|
||||
$user = $this->getAuthenticatedUser();
|
||||
/** @var BasketElementRepository $repository */
|
||||
$repository = $this->app['repo.basket-elements'];
|
||||
foreach ($request->request->get('elements') as $bask_element_id) {
|
||||
try {
|
||||
$basket_element = $repository->findUserElement($bask_element_id, $user);
|
||||
} catch (\Exception $e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$basket_element->getBasket()->removeElement($basket_element);
|
||||
$basket_element->setBasket($basket);
|
||||
$basket->addElement($basket_element);
|
||||
$n++;
|
||||
}
|
||||
|
||||
$this->getEntityManager()->flush();
|
||||
|
||||
$data = ['success' => true, 'message' => $this->app->trans('%quantity% records moved', ['%quantity%' => $n])];
|
||||
|
||||
if ($request->getRequestFormat() === 'json') {
|
||||
return $this->app->json($data);
|
||||
}
|
||||
|
||||
return $this->app->redirectPath('prod_workzone_show');
|
||||
}
|
||||
|
||||
public function displayCreateForm()
|
||||
{
|
||||
return $this->render('prod/Baskets/Create.html.twig');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return EntityManagerInterface
|
||||
*/
|
||||
private function getEntityManager()
|
||||
{
|
||||
return $this->app['orm.em'];
|
||||
}
|
||||
}
|
395
lib/Alchemy/Phrasea/Controller/Prod/BridgeController.php
Normal file
395
lib/Alchemy/Phrasea/Controller/Prod/BridgeController.php
Normal file
@@ -0,0 +1,395 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2015 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 Alchemy\Phrasea\Controller\Controller;
|
||||
use Alchemy\Phrasea\Helper\Record as RecordHelper;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\HttpException;
|
||||
|
||||
class BridgeController extends Controller
|
||||
{
|
||||
private function requireConnection(\Bridge_Account $account)
|
||||
{
|
||||
$this->app['bridge.account'] = $account;
|
||||
|
||||
if (!$account->get_api()->get_connector()->is_configured()) {
|
||||
throw new \Bridge_Exception_ApiConnectorNotConfigured("Bridge API Connector is not configured");
|
||||
}
|
||||
if (!$account->get_api()->get_connector()->is_connected()) {
|
||||
throw new \Bridge_Exception_ApiConnectorNotConnected("Bridge API Connector is not connected");
|
||||
}
|
||||
}
|
||||
|
||||
public function doPostManager(Request $request)
|
||||
{
|
||||
$route = new RecordHelper\Bridge($this->app, $request);
|
||||
$params = [
|
||||
'user_accounts' => \Bridge_Account::get_accounts_by_user($this->app, $this->getAuthenticatedUser()),
|
||||
'available_apis' => \Bridge_Api::get_availables($this->app),
|
||||
'route' => $route,
|
||||
'current_account_id' => '',
|
||||
];
|
||||
|
||||
return $this->render('prod/actions/Bridge/index.html.twig', $params);
|
||||
}
|
||||
|
||||
public function doGetLogin($api_name)
|
||||
{
|
||||
$connector = \Bridge_Api::get_connector_by_name($this->app, $api_name);
|
||||
|
||||
return $this->app->redirect($connector->get_auth_url());
|
||||
}
|
||||
|
||||
public function doGetCallback($api_name)
|
||||
{
|
||||
$error_message = '';
|
||||
try {
|
||||
$api = \Bridge_Api::get_by_api_name($this->app, $api_name);
|
||||
$connector = $api->get_connector();
|
||||
$response = $connector->connect();
|
||||
$user_id = $connector->get_user_id();
|
||||
|
||||
try {
|
||||
$account = \Bridge_Account::load_account_from_distant_id($this->app, $api, $this->getAuthenticatedUser(), $user_id);
|
||||
} catch (\Bridge_Exception_AccountNotFound $e) {
|
||||
$account = \Bridge_Account::create($this->app, $api, $this->getAuthenticatedUser(), $user_id, $connector->get_user_name());
|
||||
}
|
||||
|
||||
$settings = $account->get_settings();
|
||||
|
||||
if (isset($response['auth_token'])) {
|
||||
$settings->set('auth_token', $response['auth_token']);
|
||||
}
|
||||
if (isset($response['refresh_token'])) {
|
||||
$settings->set('refresh_token', $response['refresh_token']);
|
||||
}
|
||||
|
||||
$connector->set_auth_settings($settings);
|
||||
$connector->reconnect();
|
||||
} catch (\Exception $e) {
|
||||
$error_message = $e->getMessage();
|
||||
}
|
||||
|
||||
$params = ['error_message' => $error_message];
|
||||
|
||||
return $this->render('prod/actions/Bridge/callback.html.twig', $params);
|
||||
}
|
||||
|
||||
public function doGetAccountLogout($account_id)
|
||||
{
|
||||
$account = \Bridge_Account::load_account($this->app, $account_id);
|
||||
$this->requireConnection($account);
|
||||
$account->get_api()->get_connector()->disconnect();
|
||||
|
||||
return $this->app->redirectPath('bridge_load_elements', [
|
||||
'account_id' => $account_id,
|
||||
'type' => $account->get_api()->get_connector()->get_default_element_type(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function doPostAccountDelete($account_id)
|
||||
{
|
||||
$success = false;
|
||||
$message = '';
|
||||
try {
|
||||
$account = \Bridge_Account::load_account($this->app, $account_id);
|
||||
|
||||
if ($account->get_user()->getId() !== $this->getAuthenticatedUser()->getId()) {
|
||||
throw new HttpException(403, 'Access forbiden');
|
||||
}
|
||||
|
||||
$account->delete();
|
||||
$success = true;
|
||||
} catch (\Bridge_Exception_AccountNotFound $e) {
|
||||
$message = $this->app->trans('Account is not found.');
|
||||
} catch (\Exception $e) {
|
||||
$message = $this->app->trans('Something went wrong, please contact an administrator');
|
||||
}
|
||||
|
||||
return $this->app->json(['success' => $success, 'message' => $message]);
|
||||
}
|
||||
|
||||
public function doGetloadRecords(Request $request, $account_id)
|
||||
{
|
||||
$page = max((int) $request->query->get('page'), 0);
|
||||
$quantity = 10;
|
||||
$offset_start = max(($page - 1) * $quantity, 0);
|
||||
$account = \Bridge_Account::load_account($this->app, $account_id);
|
||||
$elements = \Bridge_Element::get_elements_by_account($this->app, $account, $offset_start, $quantity);
|
||||
|
||||
$this->requireConnection($account);
|
||||
|
||||
$params = [
|
||||
'adapter_action' => 'load-records',
|
||||
'account' => $account,
|
||||
'elements' => $elements,
|
||||
'error_message' => $request->query->get('error'),
|
||||
'notice_message' => $request->query->get('notice'),
|
||||
];
|
||||
|
||||
return $this->render('prod/actions/Bridge/records_list.html.twig', $params);
|
||||
}
|
||||
|
||||
public function doGetLoadElements(Request $request, $account_id, $type)
|
||||
{
|
||||
$page = max((int) $request->query->get('page'), 0);
|
||||
$quantity = 5;
|
||||
$offset_start = max(($page - 1) * $quantity, 0);
|
||||
$account = \Bridge_Account::load_account($this->app, $account_id);
|
||||
|
||||
$this->requireConnection($account);
|
||||
|
||||
$elements = $account->get_api()->list_elements($type, $offset_start, $quantity);
|
||||
|
||||
$params = [
|
||||
'action_type' => $type,
|
||||
'adapter_action' => 'load-elements',
|
||||
'account' => $account,
|
||||
'elements' => $elements,
|
||||
'error_message' => $request->query->get('error'),
|
||||
'notice_message' => $request->query->get('notice'),
|
||||
];
|
||||
|
||||
return $this->render('prod/actions/Bridge/element_list.html.twig', $params);
|
||||
}
|
||||
|
||||
public function doGetLoadContainers(Request $request, $account_id, $type)
|
||||
{
|
||||
$page = max((int) $request->query->get('page'), 0);
|
||||
$quantity = 5;
|
||||
$offset_start = max(($page - 1) * $quantity, 0);
|
||||
$account = \Bridge_Account::load_account($this->app, $account_id);
|
||||
|
||||
$this->requireConnection($account);
|
||||
$elements = $account->get_api()->list_containers($type, $offset_start, $quantity);
|
||||
|
||||
$params = [
|
||||
'action_type' => $type,
|
||||
'adapter_action' => 'load-containers',
|
||||
'account' => $account,
|
||||
'elements' => $elements,
|
||||
'error_message' => $request->query->get('error'),
|
||||
'notice_message' => $request->query->get('notice'),
|
||||
];
|
||||
|
||||
return $this->render('prod/actions/Bridge/element_list.html.twig', $params);
|
||||
}
|
||||
|
||||
public function doGetAction(Request $request, $account_id, $action, $element_type)
|
||||
{
|
||||
$account = \Bridge_Account::load_account($this->app, $account_id);
|
||||
|
||||
$this->requireConnection($account);
|
||||
$elements = $request->query->get('elements_list', []);
|
||||
$elements = is_array($elements) ? $elements : explode(';', $elements);
|
||||
|
||||
$destination = $request->query->get('destination');
|
||||
$route_params = [];
|
||||
$class = $account->get_api()->get_connector()->get_object_class_from_type($element_type);
|
||||
|
||||
switch ($action) {
|
||||
case 'createcontainer':
|
||||
break;
|
||||
|
||||
case 'modify':
|
||||
if (count($elements) != 1) {
|
||||
return $this->app->redirectPath('bridge_load_elements', [
|
||||
'account_id' => $account_id,
|
||||
'type' => $element_type,
|
||||
'page' => '',
|
||||
'error' => $this->app->trans('Vous ne pouvez pas editer plusieurs elements simultanement'),
|
||||
]);
|
||||
}
|
||||
foreach ($elements as $element_id) {
|
||||
if ($class === \Bridge_Api_Interface::OBJECT_CLASS_ELEMENT) {
|
||||
$route_params = ['element' => $account->get_api()->get_element_from_id($element_id, $element_type)];
|
||||
}
|
||||
if ($class === \Bridge_Api_Interface::OBJECT_CLASS_CONTAINER) {
|
||||
$route_params = ['element' => $account->get_api()->get_container_from_id($element_id, $element_type)];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'moveinto':
|
||||
$route_params = ['containers' => $account->get_api()->list_containers($destination, 0, 0)];
|
||||
break;
|
||||
|
||||
case 'deleteelement':
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \Exception($this->app->trans('Vous essayez de faire une action que je ne connais pas !'));
|
||||
break;
|
||||
}
|
||||
|
||||
$params = [
|
||||
'account' => $account,
|
||||
'destination' => $destination,
|
||||
'element_type' => $element_type,
|
||||
'action' => $action,
|
||||
'constraint_errors' => null,
|
||||
'adapter_action' => $action,
|
||||
'elements' => $elements,
|
||||
'error_message' => $request->query->get('error'),
|
||||
'notice_message' => $request->query->get('notice'),
|
||||
];
|
||||
|
||||
$params = array_merge($params, $route_params);
|
||||
$template = 'prod/actions/Bridge/' . $account->get_api()->get_connector()->get_name() . '/' . $element_type . '_' . $action . ($destination ? '_' . $destination : '') . '.html.twig';
|
||||
|
||||
return $this->render($template, $params);
|
||||
}
|
||||
|
||||
public function doPostAction(Request $request, $account_id, $action, $element_type)
|
||||
{
|
||||
$account = \Bridge_Account::load_account($this->app, $account_id);
|
||||
|
||||
$this->requireConnection($account);
|
||||
|
||||
$elements = $request->request->get('elements_list', []);
|
||||
$elements = is_array($elements) ? $elements : explode(';', $elements);
|
||||
|
||||
$destination = $request->request->get('destination');
|
||||
|
||||
$class = $account->get_api()->get_connector()->get_object_class_from_type($element_type);
|
||||
switch ($action) {
|
||||
case 'modify':
|
||||
if (count($elements) != 1) {
|
||||
return $this->app->redirect('/prod/bridge/action/' . $account_id . '/' . $action . '/' . $element_type . '/?elements_list=' . implode(';', $elements) . '&error=' . $this->app->trans('Vous ne pouvez pas editer plusieurs elements simultanement'));
|
||||
}
|
||||
$element_id = reset($elements);
|
||||
try {
|
||||
$datas = $account->get_api()->get_connector()->get_update_datas($request);
|
||||
$errors = $account->get_api()->get_connector()->check_update_constraints($datas);
|
||||
|
||||
if (count($errors) > 0) {
|
||||
$params = [
|
||||
'element' => $account->get_api()->get_element_from_id($element_id, $element_type),
|
||||
'account' => $account,
|
||||
'destination' => $destination,
|
||||
'element_type' => $element_type,
|
||||
'action' => $action,
|
||||
'elements' => $elements,
|
||||
'adapter_action' => $action,
|
||||
'error_message' => $this->app->trans('Request contains invalid datas'),
|
||||
'constraint_errors' => $errors,
|
||||
'notice_message' => $request->request->get('notice'),
|
||||
];
|
||||
|
||||
$template = 'prod/actions/Bridge/' . $account->get_api()->get_connector()->get_name() . '/' . $element_type . '_' . $action . ($destination ? '_' . $destination : '') . '.html.twig';
|
||||
|
||||
return $this->render($template, $params);
|
||||
}
|
||||
|
||||
$account->get_api()->update_element($element_type, $element_id, $datas);
|
||||
} catch (\Exception $e) {
|
||||
return $this->app->redirect('/prod/bridge/action/' . $account_id . '/' . $action . '/' . $element_type . '/?elements_list[]=' . $element_id . '&error=' . get_class($e) . ' : ' . $e->getMessage());
|
||||
}
|
||||
|
||||
return $this->app->redirect('/prod/bridge/adapter/' . $account_id . '/load-' . $class . 's/' . $element_type . '/?page=&update=success#anchor');
|
||||
case 'createcontainer':
|
||||
try {
|
||||
$container_type = $request->request->get('f_container_type');
|
||||
|
||||
$account->get_api()->create_container($container_type, $request);
|
||||
} catch (\Exception $e) {
|
||||
return $this->app->redirect('/prod/bridge/action/' . $account_id . '/' . $action . '/' . $element_type . '/?error=' . get_class($e) . ' : ' . $e->getMessage());
|
||||
}
|
||||
|
||||
return $this->app->redirect('/prod/bridge/adapter/' . $account_id . '/load-' . $class . 's/' . $element_type . '/?page=&update=success#anchor');
|
||||
case 'moveinto':
|
||||
try {
|
||||
$container_id = $request->request->get('container_id');
|
||||
foreach ($elements as $element_id) {
|
||||
$account->get_api()->add_element_to_container($element_type, $element_id, $destination, $container_id);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
return $this->app->redirect('/prod/bridge/action/' . $account_id . '/' . $action . '/' . $element_type . '/?error=' . get_class($e) . ' : ' . $e->getMessage());
|
||||
}
|
||||
|
||||
return $this->app->redirect('/prod/bridge/adapter/' . $account_id . '/load-containers/' . $destination . '/?page=&update=success#anchor');
|
||||
case 'deleteelement':
|
||||
try {
|
||||
foreach ($elements as $element_id) {
|
||||
$account->get_api()->delete_object($element_type, $element_id);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
return $this->app->redirect('/prod/bridge/action/' . $account_id . '/' . $action . '/' . $element_type . '/?error=' . get_class($e) . $e->getMessage());
|
||||
}
|
||||
|
||||
return $this->app->redirect('/prod/bridge/adapter/' . $account_id . '/load-' . $class . 's/' . $element_type . '/');
|
||||
default:
|
||||
throw new \Exception('Unknown action');
|
||||
}
|
||||
}
|
||||
|
||||
public function doGetUpload(Request $request)
|
||||
{
|
||||
$account = \Bridge_Account::load_account($this->app, $request->query->get('account_id'));
|
||||
$this->requireConnection($account);
|
||||
|
||||
$route = new RecordHelper\Bridge($this->app, $request);
|
||||
|
||||
$route->grep_records($account->get_api()->acceptable_records());
|
||||
|
||||
$params = [
|
||||
'route' => $route,
|
||||
'account' => $account,
|
||||
'error_message' => $request->query->get('error'),
|
||||
'notice_message' => $request->query->get('notice'),
|
||||
'constraint_errors' => null,
|
||||
'adapter_action' => 'upload',
|
||||
];
|
||||
|
||||
return $this->render(
|
||||
'prod/actions/Bridge/' . $account->get_api()->get_connector()->get_name() . '/upload.html.twig', $params
|
||||
);
|
||||
}
|
||||
|
||||
public function doPostUpload(Request $request)
|
||||
{
|
||||
$errors = [];
|
||||
$account = \Bridge_Account::load_account($this->app, $request->request->get('account_id'));
|
||||
$this->requireConnection($account);
|
||||
|
||||
$route = new RecordHelper\Bridge($this->app, $request);
|
||||
$route->grep_records($account->get_api()->acceptable_records());
|
||||
$connector = $account->get_api()->get_connector();
|
||||
|
||||
// check constraints
|
||||
foreach ($route->get_elements() as $record) {
|
||||
$datas = $connector->get_upload_datas($request, $record);
|
||||
$errors = array_merge($errors, $connector->check_upload_constraints($datas, $record));
|
||||
}
|
||||
|
||||
if (count($errors) > 0) {
|
||||
$params = [
|
||||
'route' => $route,
|
||||
'account' => $account,
|
||||
'error_message' => $this->app->trans('Request contains invalid datas'),
|
||||
'constraint_errors' => $errors,
|
||||
'notice_message' => $request->request->get('notice'),
|
||||
'adapter_action' => 'upload',
|
||||
];
|
||||
|
||||
return $this->render('prod/actions/Bridge/' . $account->get_api()->get_connector()->get_name() . '/upload.html.twig', $params);
|
||||
}
|
||||
|
||||
foreach ($route->get_elements() as $record) {
|
||||
$datas = $connector->get_upload_datas($request, $record);
|
||||
$title = isset($datas["title"]) ? $datas["title"] : '';
|
||||
$default_type = $connector->get_default_element_type();
|
||||
\Bridge_Element::create($this->app, $account, $record, $title, \Bridge_Element::STATUS_PENDING, $default_type, $datas);
|
||||
}
|
||||
|
||||
return $this->app->redirect('/prod/bridge/adapter/' . $account->get_id() . '/load-records/?notice=' . $this->app->trans('%quantity% elements en attente', ['%quantity%' => count($route->get_elements())]));
|
||||
}
|
||||
}
|
195
lib/Alchemy/Phrasea/Controller/Prod/DoDownloadController.php
Normal file
195
lib/Alchemy/Phrasea/Controller/Prod/DoDownloadController.php
Normal file
@@ -0,0 +1,195 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2015 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 Alchemy\Phrasea\Application;
|
||||
use Alchemy\Phrasea\Application\Helper\DispatcherAware;
|
||||
use Alchemy\Phrasea\Controller\Controller;
|
||||
use Alchemy\Phrasea\Http\DeliverDataInterface;
|
||||
use Alchemy\Phrasea\Model\Entities\Token;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\Session\Session;
|
||||
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
|
||||
class DoDownloadController extends Controller
|
||||
{
|
||||
use DispatcherAware;
|
||||
|
||||
/**
|
||||
* Prepare a set of documents for download
|
||||
*
|
||||
* @param Request $request
|
||||
* @param Token $token
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function prepareDownload(Request $request, Token $token)
|
||||
{
|
||||
if (false === $list = @unserialize($token->getData())) {
|
||||
$this->app->abort(500, 'Invalid datas');
|
||||
}
|
||||
if (!is_array($list)) {
|
||||
$this->app->abort(500, 'Invalid datas');
|
||||
}
|
||||
|
||||
foreach (['export_name', 'files'] as $key) {
|
||||
if (!isset($list[$key])) {
|
||||
$this->app->abort(500, 'Invalid datas');
|
||||
}
|
||||
}
|
||||
|
||||
$records = [];
|
||||
|
||||
foreach ($list['files'] as $file) {
|
||||
if (!is_array($file) || !isset($file['base_id']) || !isset($file['record_id'])) {
|
||||
continue;
|
||||
}
|
||||
$sbasId = \phrasea::sbasFromBas($this->app, $file['base_id']);
|
||||
|
||||
try {
|
||||
$record = new \record_adapter($this->app, $sbasId, $file['record_id']);
|
||||
} catch (\Exception $e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$records[sprintf('%s_%s', $sbasId, $file['record_id'])] = $record;
|
||||
}
|
||||
|
||||
return new Response($this->render(
|
||||
'/prod/actions/Download/prepare.html.twig', [
|
||||
'module_name' => $this->app->trans('Export'),
|
||||
'module' => $this->app->trans('Export'),
|
||||
'list' => $list,
|
||||
'records' => $records,
|
||||
'token' => $token,
|
||||
'anonymous' => $request->query->get('anonymous', false),
|
||||
'type' => $request->query->get('type', \Session_Logger::EVENT_EXPORTDOWNLOAD)
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Download a set of documents
|
||||
*
|
||||
* @param Token $token
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function downloadDocuments(Token $token)
|
||||
{
|
||||
if (false === $list = @unserialize($token->getData())) {
|
||||
$this->app->abort(500, 'Invalid datas');
|
||||
}
|
||||
if (!is_array($list)) {
|
||||
$this->app->abort(500, 'Invalid datas');
|
||||
}
|
||||
|
||||
foreach (['export_name', 'files'] as $key) {
|
||||
if (!isset($list[$key])) {
|
||||
$this->app->abort(500, 'Invalid datas');
|
||||
}
|
||||
}
|
||||
|
||||
$exportName = $list['export_name'];
|
||||
|
||||
if ($list['count'] === 1) {
|
||||
$file = end($list['files']);
|
||||
$subdef = end($file['subdefs']);
|
||||
$exportName = sprintf('%s%s.%s', $file['export_name'], $subdef['ajout'], $subdef['exportExt']);
|
||||
$exportFile = \p4string::addEndSlash($subdef['path']) . $subdef['file'];
|
||||
$mime = $subdef['mime'];
|
||||
$list['complete'] = true;
|
||||
} else {
|
||||
$exportFile = $this->app['tmp.download.path'].'/'.$token->getValue() . '.zip';
|
||||
$mime = 'application/zip';
|
||||
}
|
||||
|
||||
if (!$this->getFileSystem()->exists($exportFile)) {
|
||||
$this->app->abort(404, 'Download file not found');
|
||||
}
|
||||
|
||||
$this->getDispatcher()->addListener(KernelEvents::RESPONSE, function (FilterResponseEvent $event) use ($list) {
|
||||
\set_export::log_download(
|
||||
$this->app,
|
||||
$list,
|
||||
$event->getRequest()->get('type'),
|
||||
!!$event->getRequest()->get('anonymous', false),
|
||||
(isset($list['email']) ? $list['email'] : '')
|
||||
);
|
||||
});
|
||||
|
||||
return $this->getDeliverer()
|
||||
->deliverFile($exportFile, $exportName, DeliverDataInterface::DISPOSITION_ATTACHMENT, $mime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a zip of downloaded documents
|
||||
*
|
||||
* @param Token $token
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function downloadExecute(Token $token)
|
||||
{
|
||||
if (false === $list = @unserialize($token->getData())) {
|
||||
return $this->app->json([
|
||||
'success' => false,
|
||||
'message' => 'Invalid datas'
|
||||
]);
|
||||
}
|
||||
|
||||
set_time_limit(0);
|
||||
// Force the session to be saved and closed.
|
||||
/** @var Session $session */
|
||||
$session = $this->app['session'];
|
||||
$session->save();
|
||||
ignore_user_abort(true);
|
||||
|
||||
if ($list['count'] > 1) {
|
||||
\set_export::build_zip(
|
||||
$this->app,
|
||||
$token,
|
||||
$list,
|
||||
sprintf($this->app['tmp.download.path'].'/%s.zip', $token->getValue()) // Dest file
|
||||
);
|
||||
} else {
|
||||
$list['complete'] = true;
|
||||
$token->setData(serialize($list));
|
||||
/** @var EntityManagerInterface $manager */
|
||||
$manager = $this->app['orm.em'];
|
||||
$manager->persist($token);
|
||||
$manager->flush();
|
||||
}
|
||||
|
||||
return $this->app->json([
|
||||
'success' => true,
|
||||
'message' => ''
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Filesystem
|
||||
*/
|
||||
private function getFileSystem()
|
||||
{
|
||||
return $this->app['filesystem'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return DeliverDataInterface
|
||||
*/
|
||||
private function getDeliverer()
|
||||
{
|
||||
return $this->app['phraseanet.file-serve'];
|
||||
}
|
||||
}
|
66
lib/Alchemy/Phrasea/Controller/Prod/DownloadController.php
Normal file
66
lib/Alchemy/Phrasea/Controller/Prod/DownloadController.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2015 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 Alchemy\Phrasea\Application\Helper\DispatcherAware;
|
||||
use Alchemy\Phrasea\Controller\Controller;
|
||||
use Alchemy\Phrasea\Core\Event\ExportEvent;
|
||||
use Alchemy\Phrasea\Core\PhraseaEvents;
|
||||
use Alchemy\Phrasea\Model\Manipulator\TokenManipulator;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class DownloadController extends Controller
|
||||
{
|
||||
use DispatcherAware;
|
||||
|
||||
/**
|
||||
* Download a set of documents
|
||||
*
|
||||
* @param Request $request
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function checkDownload(Request $request)
|
||||
{
|
||||
$lst = $request->request->get('lst');
|
||||
$ssttid = $request->request->get('ssttid', '');
|
||||
$subdefs = $request->request->get('obj', []);
|
||||
|
||||
$download = new \set_export($this->app, $lst, $ssttid);
|
||||
|
||||
if (0 === $download->get_total_download()) {
|
||||
$this->app->abort(403);
|
||||
}
|
||||
|
||||
$list = $download->prepare_export(
|
||||
$this->getAuthenticatedUser(),
|
||||
$this->app['filesystem'],
|
||||
$subdefs,
|
||||
$request->request->get('type') === 'title' ? true : false,
|
||||
$request->request->get('businessfields')
|
||||
);
|
||||
|
||||
$list['export_name'] = sprintf('%s.zip', $download->getExportName());
|
||||
$token = $this->getTokenManipulator()->createDownloadToken($this->getAuthenticatedUser(), serialize($list));
|
||||
$this->getDispatcher()->dispatch(PhraseaEvents::EXPORT_CREATE, new ExportEvent(
|
||||
$this->getAuthenticatedUser(), $ssttid, $lst, $subdefs, $download->getExportName())
|
||||
);
|
||||
|
||||
return $this->app->redirectPath('prepare_download', ['token' => $token->getValue()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TokenManipulator
|
||||
*/
|
||||
private function getTokenManipulator()
|
||||
{
|
||||
return $this->app['manipulator.token'];
|
||||
}
|
||||
}
|
391
lib/Alchemy/Phrasea/Controller/Prod/EditController.php
Normal file
391
lib/Alchemy/Phrasea/Controller/Prod/EditController.php
Normal file
@@ -0,0 +1,391 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2015 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 Alchemy\Phrasea\Application\Helper\DispatcherAware;
|
||||
use Alchemy\Phrasea\Controller\Controller;
|
||||
use Alchemy\Phrasea\Controller\RecordsRequest;
|
||||
use Alchemy\Phrasea\Core\Event\RecordEdit;
|
||||
use Alchemy\Phrasea\Core\PhraseaEvents;
|
||||
use Alchemy\Phrasea\Media\SubdefSubstituer;
|
||||
use Alchemy\Phrasea\Vocabulary\Controller as VocabularyController;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class EditController extends Controller
|
||||
{
|
||||
use DispatcherAware;
|
||||
|
||||
public function submitAction(Request $request)
|
||||
{
|
||||
$records = RecordsRequest::fromRequest(
|
||||
$this->app,
|
||||
$request,
|
||||
RecordsRequest::FLATTEN_YES_PRESERVE_STORIES,
|
||||
['canmodifrecord']
|
||||
);
|
||||
|
||||
$thesaurus = false;
|
||||
$status = $ids = $elements = $suggValues = $fields = $JSFields = [];
|
||||
$databox = null;
|
||||
$databoxes = $records->databoxes();
|
||||
|
||||
$multipleDataboxes = count($databoxes) > 1;
|
||||
|
||||
if (1 === count($databoxes)) {
|
||||
/** @var \databox $databox */
|
||||
$databox = current($databoxes);
|
||||
|
||||
// generate javascript fields
|
||||
foreach ($databox->get_meta_structure() as $meta) {
|
||||
/** @var \databox_field $meta */
|
||||
$fields[] = $meta;
|
||||
|
||||
$separator = $meta->get_separator();
|
||||
|
||||
/** @Ignore */
|
||||
$JSFields[$meta->get_id()] = [
|
||||
'meta_struct_id' => $meta->get_id(),
|
||||
'name' => $meta->get_name(),
|
||||
'_status' => 0,
|
||||
'_value' => '',
|
||||
'_sgval' => [],
|
||||
'required' => $meta->is_required(),
|
||||
/** @Ignore */
|
||||
'label' => $meta->get_label($this->app['locale']),
|
||||
'readonly' => $meta->is_readonly(),
|
||||
'type' => $meta->get_type(),
|
||||
'format' => '',
|
||||
'explain' => '',
|
||||
'tbranch' => $meta->get_tbranch(),
|
||||
'maxLength' => $meta->get_tag()
|
||||
->getMaxLength(),
|
||||
'minLength' => $meta->get_tag()
|
||||
->getMinLength(),
|
||||
'multi' => $meta->is_multi(),
|
||||
'separator' => $separator,
|
||||
'vocabularyControl' => $meta->getVocabularyControl() ? $meta->getVocabularyControl()
|
||||
->getType() : null,
|
||||
'vocabularyRestricted' => $meta->getVocabularyControl() ? $meta->isVocabularyRestricted()
|
||||
: false,
|
||||
];
|
||||
|
||||
if (trim($meta->get_tbranch()) !== '') {
|
||||
$thesaurus = true;
|
||||
}
|
||||
}
|
||||
|
||||
// generate javascript sugg values
|
||||
foreach ($records->collections() as $collection) {
|
||||
$suggValues['b' . $collection->get_base_id()] = [];
|
||||
|
||||
if ($sxe = simplexml_load_string($collection->get_prefs())) {
|
||||
$z = $sxe->xpath('/baseprefs/sugestedValues');
|
||||
|
||||
if (!$z || !is_array($z)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($z[0] as $ki => $vi) { // les champs
|
||||
$field = $databox->get_meta_structure()
|
||||
->get_element_by_name($ki);
|
||||
if (!$field || !$vi) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$suggValues['b' . $collection->get_base_id()][$field->get_id()] = [];
|
||||
|
||||
foreach ($vi->value as $oneValue) {
|
||||
$suggValues['b' . $collection->get_base_id()][$field->get_id()][] = (string)$oneValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
unset($collection);
|
||||
}
|
||||
|
||||
// generate javascript status
|
||||
if ($this->getAclForUser()->has_right('changestatus')) {
|
||||
$statusStructure = $databox->getStatusStructure();
|
||||
foreach ($statusStructure as $statbit) {
|
||||
$bit = $statbit['bit'];
|
||||
|
||||
$status[$bit] = [];
|
||||
$status[$bit]['label0'] = $statbit['labels_off_i18n'][$this->app['locale']];
|
||||
$status[$bit]['label1'] = $statbit['labels_on_i18n'][$this->app['locale']];
|
||||
$status[$bit]['img_off'] = $statbit['img_off'];
|
||||
$status[$bit]['img_on'] = $statbit['img_on'];
|
||||
$status[$bit]['_value'] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// generate javascript elements
|
||||
$databox_fields = [];
|
||||
foreach ($databox->get_meta_structure() as $field) {
|
||||
$databox_fields[$field->get_id()] = [
|
||||
'dirty' => false,
|
||||
'meta_struct_id' => $field->get_id(),
|
||||
'values' => []
|
||||
];
|
||||
}
|
||||
|
||||
/** @var \record_adapter $record */
|
||||
foreach ($records as $record) {
|
||||
$indice = $record->get_number();
|
||||
$elements[$indice] = [
|
||||
'bid' => $record->get_base_id(),
|
||||
'rid' => $record->get_record_id(),
|
||||
'sselcont_id' => null,
|
||||
'_selected' => false,
|
||||
'fields' => $databox_fields,
|
||||
];
|
||||
|
||||
$elements[$indice]['statbits'] = [];
|
||||
if ($this->getAclForUser()->has_right_on_base($record->get_base_id(), 'chgstatus')) {
|
||||
foreach ($status as $n => $s) {
|
||||
$tmp_val = substr(strrev($record->get_status()), $n, 1);
|
||||
$elements[$indice]['statbits'][$n]['value'] = ($tmp_val == '1') ? '1' : '0';
|
||||
$elements[$indice]['statbits'][$n]['dirty'] = false;
|
||||
}
|
||||
}
|
||||
|
||||
$elements[$indice]['originalname'] = $record->get_original_name();
|
||||
|
||||
foreach ($record->get_caption()->get_fields(null, true) as $field) {
|
||||
$meta_struct_id = $field->get_meta_struct_id();
|
||||
if (!isset($JSFields[$meta_struct_id])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$values = [];
|
||||
foreach ($field->get_values() as $value) {
|
||||
$type = $id = null;
|
||||
|
||||
if ($value->getVocabularyType()) {
|
||||
$type = $value->getVocabularyType()->getType();
|
||||
$id = $value->getVocabularyId();
|
||||
}
|
||||
|
||||
$values[$value->getId()] = [
|
||||
'meta_id' => $value->getId(),
|
||||
'value' => $value->getValue(),
|
||||
'vocabularyId' => $id,
|
||||
'vocabularyType' => $type,
|
||||
];
|
||||
}
|
||||
|
||||
$elements[$indice]['fields'][$meta_struct_id] = [
|
||||
'dirty' => false,
|
||||
'meta_struct_id' => $meta_struct_id,
|
||||
'values' => $values,
|
||||
];
|
||||
}
|
||||
|
||||
$elements[$indice]['subdefs'] = [];
|
||||
|
||||
$thumbnail = $record->get_thumbnail();
|
||||
|
||||
$elements[$indice]['subdefs']['thumbnail'] = [
|
||||
'url' => (string)$thumbnail->get_url(),
|
||||
'w' => $thumbnail->get_width(),
|
||||
'h' => $thumbnail->get_height(),
|
||||
];
|
||||
|
||||
$elements[$indice]['preview'] = $this->render(
|
||||
'common/preview.html.twig',
|
||||
['record' => $record]
|
||||
);
|
||||
|
||||
$elements[$indice]['type'] = $record->get_type();
|
||||
}
|
||||
}
|
||||
|
||||
$params = [
|
||||
'multipleDataboxes' => $multipleDataboxes,
|
||||
'recordsRequest' => $records,
|
||||
'databox' => $databox,
|
||||
'JSonStatus' => json_encode($status),
|
||||
'JSonRecords' => json_encode($elements),
|
||||
'JSonFields' => json_encode($JSFields),
|
||||
'JSonIds' => json_encode(array_keys($elements)),
|
||||
'status' => $status,
|
||||
'fields' => $fields,
|
||||
'JSonSuggValues' => json_encode($suggValues),
|
||||
'thesaurus' => $thesaurus,
|
||||
];
|
||||
|
||||
return $this->render('prod/actions/edit_default.html.twig', $params);
|
||||
}
|
||||
|
||||
public function searchVocabularyAction(Request $request, $vocabulary) {
|
||||
$datas = ['success' => false, 'message' => '', 'results' => []];
|
||||
|
||||
$sbas_id = (int) $request->query->get('sbas_id');
|
||||
|
||||
try {
|
||||
if ($sbas_id === 0) {
|
||||
throw new \Exception('Invalid sbas_id');
|
||||
}
|
||||
|
||||
$VC = VocabularyController::get($this->app, $vocabulary);
|
||||
$databox = $this->findDataboxById($sbas_id);
|
||||
} catch (\Exception $e) {
|
||||
$datas['message'] = $this->app->trans('Vocabulary not found');
|
||||
|
||||
return $this->app->json($datas);
|
||||
}
|
||||
|
||||
$query = $request->query->get('query');
|
||||
|
||||
$results = $VC->find($query, $this->getAuthenticatedUser(), $databox);
|
||||
|
||||
$list = [];
|
||||
|
||||
foreach ($results as $Term) {
|
||||
/* @var \Alchemy\Phrasea\Vocabulary\Term $Term */
|
||||
$list[] = [
|
||||
'id' => $Term->getId(),
|
||||
'context' => $Term->getContext(),
|
||||
'value' => $Term->getValue(),
|
||||
];
|
||||
}
|
||||
|
||||
$datas['success'] = true;
|
||||
$datas['results'] = $list;
|
||||
|
||||
return $this->app->json($datas);
|
||||
}
|
||||
|
||||
public function applyAction(Request $request) {
|
||||
|
||||
$records = RecordsRequest::fromRequest($this->app, $request, RecordsRequest::FLATTEN_YES_PRESERVE_STORIES, ['canmodifrecord']);
|
||||
|
||||
$databoxes = $records->databoxes();
|
||||
if (count($databoxes) !== 1) {
|
||||
throw new \Exception('Unable to edit on multiple databoxes');
|
||||
}
|
||||
/** @var \databox $databox */
|
||||
$databox = reset($databoxes);
|
||||
|
||||
if ($request->request->get('act_option') == 'SAVEGRP'
|
||||
&& $request->request->get('newrepresent')
|
||||
&& $records->isSingleStory()
|
||||
) {
|
||||
try {
|
||||
$reg_record = $records->singleStory();
|
||||
|
||||
$newsubdef_reg = new \record_adapter($this->app, $reg_record->get_sbas_id(), $request->request->get('newrepresent'));
|
||||
|
||||
foreach ($newsubdef_reg->get_subdefs() as $name => $value) {
|
||||
if (!in_array($name, ['thumbnail', 'preview'])) {
|
||||
continue;
|
||||
}
|
||||
if ($value->get_type() !== \media_subdef::TYPE_IMAGE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$media = $this->app->getMediaFromUri($value->get_pathfile());
|
||||
$this->getSubDefinitionSubstituer()->substitute($reg_record, $name, $media);
|
||||
$this->getDispatcher()->dispatch(PhraseaEvents::RECORD_EDIT, new RecordEdit($reg_record));
|
||||
$this->getDataboxLogger($reg_record->get_databox())->log(
|
||||
$reg_record,
|
||||
\Session_Logger::EVENT_SUBSTITUTE,
|
||||
$name == 'document' ? 'HD' : $name,
|
||||
''
|
||||
);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_array($request->request->get('mds'))) {
|
||||
return $this->app->json(['message' => '', 'error' => false]);
|
||||
}
|
||||
|
||||
$elements = $records->toArray();
|
||||
|
||||
foreach ($request->request->get('mds') as $rec) {
|
||||
try {
|
||||
$record = $databox->get_record($rec['record_id']);
|
||||
} catch (\Exception $e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$key = $record->get_serialize_key();
|
||||
|
||||
if (!array_key_exists($key, $elements)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$statbits = $rec['status'];
|
||||
$editDirty = $rec['edit'];
|
||||
|
||||
if ($editDirty == '0') {
|
||||
$editDirty = false;
|
||||
} else {
|
||||
$editDirty = true;
|
||||
}
|
||||
|
||||
if (isset($rec['metadatas']) && is_array($rec['metadatas'])) {
|
||||
$record->set_metadatas($rec['metadatas']);
|
||||
$this->getDispatcher()->dispatch(PhraseaEvents::RECORD_EDIT, new RecordEdit($record));
|
||||
}
|
||||
|
||||
$newstat = $record->get_status();
|
||||
$statbits = ltrim($statbits, 'x');
|
||||
if (!in_array($statbits, ['', 'null'])) {
|
||||
$mask_and = ltrim(str_replace(['x', '0', '1', 'z'], ['1', 'z', '0', '1'], $statbits), '0');
|
||||
if ($mask_and != '') {
|
||||
$newstat = \databox_status::operation_and_not($newstat, $mask_and);
|
||||
}
|
||||
|
||||
$mask_or = ltrim(str_replace('x', '0', $statbits), '0');
|
||||
|
||||
if ($mask_or != '') {
|
||||
$newstat = \databox_status::operation_or($newstat, $mask_or);
|
||||
}
|
||||
|
||||
$record->set_binary_status($newstat);
|
||||
}
|
||||
|
||||
$record
|
||||
->write_metas()
|
||||
->get_collection()
|
||||
->reset_stamp($record->get_record_id());
|
||||
|
||||
if ($statbits != '') {
|
||||
$this->getDataboxLogger($databox)
|
||||
->log($record, \Session_Logger::EVENT_STATUS, '', '');
|
||||
}
|
||||
if ($editDirty) {
|
||||
$this->getDataboxLogger($databox)
|
||||
->log($record, \Session_Logger::EVENT_EDIT, '', '');
|
||||
}
|
||||
}
|
||||
|
||||
return $this->app->json(['success' => true]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \databox $databox
|
||||
* @return \Session_Logger
|
||||
*/
|
||||
private function getDataboxLogger(\databox $databox)
|
||||
{
|
||||
return $this->app['phraseanet.logger']($databox);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SubdefSubstituer
|
||||
*/
|
||||
private function getSubDefinitionSubstituer()
|
||||
{
|
||||
return $this->app['subdef.substituer'];
|
||||
}
|
||||
}
|
247
lib/Alchemy/Phrasea/Controller/Prod/ExportController.php
Normal file
247
lib/Alchemy/Phrasea/Controller/Prod/ExportController.php
Normal file
@@ -0,0 +1,247 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2015 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 Alchemy\Phrasea\Application;
|
||||
use Alchemy\Phrasea\Application\Helper\DispatcherAware;
|
||||
use Alchemy\Phrasea\Application\Helper\FilesystemAware;
|
||||
use Alchemy\Phrasea\Application\Helper\NotifierAware;
|
||||
use Alchemy\Phrasea\Controller\Controller;
|
||||
use Alchemy\Phrasea\Core\Event\ExportFailureEvent;
|
||||
use Alchemy\Phrasea\Core\PhraseaEvents;
|
||||
use Alchemy\Phrasea\Exception\InvalidArgumentException;
|
||||
use Alchemy\Phrasea\Model\Manipulator\TokenManipulator;
|
||||
use Alchemy\Phrasea\Notification\Emitter;
|
||||
use Alchemy\Phrasea\Notification\Mail\MailRecordsExport;
|
||||
use Alchemy\Phrasea\Notification\Receiver;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class ExportController extends Controller
|
||||
{
|
||||
use DispatcherAware;
|
||||
use FilesystemAware;
|
||||
use NotifierAware;
|
||||
|
||||
/**
|
||||
* Display form to export documents
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function displayMultiExport(Request $request)
|
||||
{
|
||||
$download = new \set_export(
|
||||
$this->app,
|
||||
$request->request->get('lst', ''),
|
||||
$request->request->get('ssel', ''),
|
||||
$request->request->get('story')
|
||||
);
|
||||
|
||||
return new Response($this->render('common/dialog_export.html.twig', [
|
||||
'download' => $download,
|
||||
'ssttid' => $request->request->get('ssel'),
|
||||
'lst' => $download->serialize_list(),
|
||||
'default_export_title' => $this->getConf()->get(['registry', 'actions', 'default-export-title']),
|
||||
'choose_export_title' => $this->getConf()->get(['registry', 'actions', 'export-title-choice'])
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a FTP connexion
|
||||
*
|
||||
* @param Request $request
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function testFtpConnexion(Request $request)
|
||||
{
|
||||
if (!$request->isXmlHttpRequest()) {
|
||||
$this->app->abort(400);
|
||||
}
|
||||
|
||||
$success = false;
|
||||
$msg = _('Error while connecting to FTP');
|
||||
|
||||
try {
|
||||
/** @var \ftpclient $ftpClient */
|
||||
$ftpClient = $this->app['phraseanet.ftp.client']($request->request->get('address', ''), 21, 90, !!$request->request->get('ssl'));
|
||||
$ftpClient->login($request->request->get('login', 'anonymous'), $request->request->get('password', 'anonymous'));
|
||||
$ftpClient->close();
|
||||
$msg = $this->app->trans('Connection to FTP succeed');
|
||||
$success = true;
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
|
||||
return $this->app->json([
|
||||
'success' => $success,
|
||||
'message' => $msg
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function exportFtp(Request $request)
|
||||
{
|
||||
$download = new \set_exportftp($this->app, $request->request->get('lst'), $request->request->get('ssttid'));
|
||||
|
||||
$mandatoryParameters = ['address', 'login', 'obj'];
|
||||
|
||||
foreach ($mandatoryParameters as $parameter) {
|
||||
if (!$request->request->get($parameter)) {
|
||||
$this->app->abort(400, sprintf('required parameter `%s` is missing', $parameter));
|
||||
}
|
||||
}
|
||||
|
||||
if (count($download->get_display_ftp()) == 0) {
|
||||
return $this->app->json([
|
||||
'success' => false,
|
||||
'message' => $this->app->trans("You do not have required rights to send these documents over FTP")
|
||||
]);
|
||||
}
|
||||
|
||||
try {
|
||||
$download->prepare_export(
|
||||
$this->getAuthenticatedUser(),
|
||||
$this->getFilesystem(),
|
||||
$request->request->get('obj'),
|
||||
false,
|
||||
$request->request->get('businessfields')
|
||||
);
|
||||
|
||||
$download->export_ftp(
|
||||
$request->request->get('user_dest'),
|
||||
$request->request->get('address'),
|
||||
$request->request->get('login'),
|
||||
$request->request->get('password', ''),
|
||||
$request->request->get('ssl'),
|
||||
$request->request->get('max_retry'),
|
||||
$request->request->get('passive'),
|
||||
$request->request->get('dest_folder'),
|
||||
$request->request->get('prefix_folder'),
|
||||
$request->request->get('logfile')
|
||||
);
|
||||
|
||||
return $this->app->json([
|
||||
'success' => true,
|
||||
'message' => $this->app->trans('Export saved in the waiting queue')
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
return $this->app->json([
|
||||
'success' => false,
|
||||
'message' => $this->app->trans('Something went wrong')
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Export document by mail
|
||||
*
|
||||
* @param Request $request
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function exportMail(Request $request)
|
||||
{
|
||||
set_time_limit(0);
|
||||
session_write_close();
|
||||
ignore_user_abort(true);
|
||||
|
||||
$lst = $request->request->get('lst', '');
|
||||
$ssttid = $request->request->get('ssttid', '');
|
||||
|
||||
//prepare export
|
||||
$download = new \set_export($this->app, $lst, $ssttid);
|
||||
$list = $download->prepare_export(
|
||||
$this->getAuthenticatedUser(),
|
||||
$this->getFilesystem(),
|
||||
(array) $request->request->get('obj'),
|
||||
$request->request->get("type") == "title" ? : false,
|
||||
$request->request->get('businessfields')
|
||||
);
|
||||
|
||||
$separator = preg_split('//', ' ;,', -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
|
||||
$separator = '/\\' . implode('|\\', $separator) . '/';
|
||||
|
||||
$list['export_name'] = sprintf("%s.zip", $download->getExportName());
|
||||
$list['email'] = implode(';', preg_split($separator, $request->request->get("destmail", "")));
|
||||
|
||||
$destMails = [];
|
||||
//get destination mails
|
||||
foreach (explode(";", $list['email']) as $mail) {
|
||||
if (filter_var($mail, FILTER_VALIDATE_EMAIL)) {
|
||||
$destMails[] = $mail;
|
||||
} else {
|
||||
$this->dispatch(PhraseaEvents::EXPORT_MAIL_FAILURE, new ExportFailureEvent(
|
||||
$this->getAuthenticatedUser(),
|
||||
$ssttid,
|
||||
$lst,
|
||||
\eventsmanager_notify_downloadmailfail::MAIL_NO_VALID,
|
||||
$mail
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
$token = $this->getTokenManipulator()->createEmailExportToken(serialize($list));
|
||||
|
||||
if (count($destMails) > 0) {
|
||||
//zip documents
|
||||
\set_export::build_zip(
|
||||
$this->app,
|
||||
$token,
|
||||
$list,
|
||||
$this->app['tmp.download.path'].'/'. $token->getValue() . '.zip'
|
||||
);
|
||||
|
||||
$remaingEmails = $destMails;
|
||||
|
||||
$url = $this->app->url('prepare_download', ['token' => $token->getValue(), 'anonymous' => false, 'type' => \Session_Logger::EVENT_EXPORTMAIL]);
|
||||
|
||||
$user = $this->getAuthenticatedUser();
|
||||
$emitter = new Emitter($user->getDisplayName(), $user->getEmail());
|
||||
|
||||
foreach ($destMails as $key => $mail) {
|
||||
try {
|
||||
$receiver = new Receiver(null, trim($mail));
|
||||
} catch (InvalidArgumentException $e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$mail = MailRecordsExport::create($this->app, $receiver, $emitter, $request->request->get('textmail'));
|
||||
$mail->setButtonUrl($url);
|
||||
$mail->setExpiration($token->getExpiration());
|
||||
|
||||
$this->deliver($mail, !!$request->request->get('reading_confirm', false));
|
||||
unset($remaingEmails[$key]);
|
||||
}
|
||||
|
||||
//some mails failed
|
||||
if (count($remaingEmails) > 0) {
|
||||
foreach ($remaingEmails as $mail) {
|
||||
$this->dispatch(PhraseaEvents::EXPORT_MAIL_FAILURE, new ExportFailureEvent($this->getAuthenticatedUser(), $ssttid, $lst, \eventsmanager_notify_downloadmailfail::MAIL_FAIL, $mail));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this->app->json([
|
||||
'success' => true,
|
||||
'message' => ''
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TokenManipulator
|
||||
*/
|
||||
private function getTokenManipulator()
|
||||
{
|
||||
return $this->app['manipulator.token'];
|
||||
}
|
||||
}
|
@@ -72,7 +72,7 @@ class RecordsRequest extends ArrayCollection
|
||||
/**
|
||||
* Return all distinct databoxes related to the contained records
|
||||
*
|
||||
* @return array
|
||||
* @return \databox[]
|
||||
*/
|
||||
public function databoxes()
|
||||
{
|
||||
@@ -94,13 +94,14 @@ class RecordsRequest extends ArrayCollection
|
||||
/**
|
||||
* Return all distinct collections related to the contained records
|
||||
*
|
||||
* @return array
|
||||
* @return \collection[]
|
||||
*/
|
||||
public function collections()
|
||||
{
|
||||
if (!$this->collections) {
|
||||
$this->collections = [];
|
||||
|
||||
/** @var \record_adapter $record */
|
||||
foreach ($this as $record) {
|
||||
if (false === array_key_exists($record->get_base_id(), $this->collections)) {
|
||||
$this->collections[$record->get_base_id()] = $record->get_collection();
|
||||
@@ -160,7 +161,7 @@ class RecordsRequest extends ArrayCollection
|
||||
/**
|
||||
* Return the first story if a single story is contained, null otherwise
|
||||
*
|
||||
* @return record_adapter|null
|
||||
* @return \record_adapter|null
|
||||
*/
|
||||
public function singleStory()
|
||||
{
|
||||
|
@@ -23,7 +23,10 @@ class Dashboard implements ControllerProviderInterface, ServiceProviderInterface
|
||||
public function register(Application $app)
|
||||
{
|
||||
$app['controller.admin.dashboard'] = $app->share(function (PhraseaApplication $app) {
|
||||
return new DashboardController($app);
|
||||
return (new DashboardController($app))
|
||||
->setDelivererLocator(function () use ($app) {
|
||||
return $app['notification.deliverer'];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -25,7 +25,10 @@ class TaskManager implements ControllerProviderInterface, ServiceProviderInterfa
|
||||
public function register(Application $app)
|
||||
{
|
||||
$app['controller.admin.task'] = $app->share(function (\Alchemy\Phrasea\Application $app) {
|
||||
return new TaskManagerController($app);
|
||||
return (new TaskManagerController($app))
|
||||
->setDispatcherLocator(function () use ($app) {
|
||||
return $app['dispatcher'];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -24,7 +24,10 @@ class Users implements ControllerProviderInterface, ServiceProviderInterface
|
||||
public function register(Application $app)
|
||||
{
|
||||
$app['controller.admin.users'] = $app->share(function () use ($app) {
|
||||
return new UserController($app);
|
||||
return (new UserController($app))
|
||||
->setDelivererLocator(function () use ($app) {
|
||||
return $app['notification.deliverer'];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -23,7 +23,10 @@ class OAuth2 implements ControllerProviderInterface, ServiceProviderInterface
|
||||
public function register(Application $app)
|
||||
{
|
||||
$app['controller.oauth2'] = $app->share(function (PhraseaApplication $app) {
|
||||
return new OAuth2Controller($app);
|
||||
return (new OAuth2Controller($app))
|
||||
->setDispatcherLocator(function () use ($app) {
|
||||
return $app['dispatcher'];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -31,7 +31,10 @@ class V1 implements ControllerProviderInterface, ServiceProviderInterface
|
||||
public function register(Application $app)
|
||||
{
|
||||
$app['controller.api.v1'] = $app->share(function (PhraseaApplication $app) {
|
||||
return new V1Controller($app);
|
||||
return (new V1Controller($app))
|
||||
->setDispatcherLocator(function () use ($app) {
|
||||
return $app['dispatcher'];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -28,7 +28,10 @@ class Lightbox implements ControllerProviderInterface, ServiceProviderInterface
|
||||
public function register(Application $app)
|
||||
{
|
||||
$app['controller.lightbox'] = $app->share(function (PhraseaApplication $app) {
|
||||
return new LightboxController($app);
|
||||
return (new LightboxController($app))
|
||||
->setDispatcherLocator(function () use ($app) {
|
||||
return $app['dispatcher'];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -1,384 +0,0 @@
|
||||
<?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\ControllerProvider\Prod;
|
||||
|
||||
use Alchemy\Phrasea\Controller\RecordsRequest;
|
||||
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
|
||||
use Alchemy\Phrasea\Model\Entities\Basket as BasketEntity;
|
||||
use Alchemy\Phrasea\Model\Entities\BasketElement;
|
||||
use Alchemy\Phrasea\Model\Entities\ValidationData;
|
||||
use Silex\Application;
|
||||
use Silex\ControllerProviderInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
class BasketController implements ControllerProviderInterface
|
||||
{
|
||||
use ControllerProviderTrait;
|
||||
|
||||
public function connect(Application $app)
|
||||
{
|
||||
$app['controller.prod.basket'] = $this;
|
||||
|
||||
$controllers = $this->createAuthenticatedCollection($app);
|
||||
|
||||
$controllers
|
||||
// Silex\Route::convert is not used as this should be done prior the before middleware
|
||||
->before($app['middleware.basket.converter'])
|
||||
->before($app['middleware.basket.user-access']);
|
||||
|
||||
$controllers->get('/{basket}/', 'controller.prod.basket:displayBasket')
|
||||
->bind('prod_baskets_basket')
|
||||
->assert('basket', '\d+');
|
||||
|
||||
$controllers->post('/', 'controller.prod.basket:createBasket')
|
||||
->bind('prod_baskets');
|
||||
|
||||
$controllers->post('/{basket}/delete/', 'controller.prod.basket:deleteBasket')
|
||||
->assert('basket', '\d+')
|
||||
->bind('basket_delete')
|
||||
->before($app['middleware.basket.user-is-owner']);
|
||||
|
||||
$controllers->post('/{basket}/delete/{basket_element_id}/', 'controller.prod.basket:removeBasketElement')
|
||||
->bind('prod_baskets_basket_element_remove')
|
||||
->assert('basket', '\d+')
|
||||
->assert('basket_element_id', '\d+')
|
||||
->before($app['middleware.basket.user-is-owner']);
|
||||
|
||||
$controllers->post('/{basket}/update/', 'controller.prod.basket:updateBasket')
|
||||
->bind('prod_baskets_basket_update')
|
||||
->assert('basket', '\d+')
|
||||
->before($app['middleware.basket.user-is-owner']);
|
||||
|
||||
$controllers->get('/{basket}/update/', 'controller.prod.basket:displayUpdateForm')
|
||||
->assert('basket', '\d+')
|
||||
->before($app['middleware.basket.user-is-owner']);
|
||||
|
||||
$controllers->get('/{basket}/reorder/', 'controller.prod.basket:displayReorderForm')
|
||||
->assert('basket', '\d+')
|
||||
->bind('prod_baskets_basket_reorder')
|
||||
->before($app['middleware.basket.user-is-owner']);
|
||||
|
||||
$controllers->post('/{basket}/reorder/', 'controller.prod.basket:reorder')
|
||||
->assert('basket', '\d+')
|
||||
->before($app['middleware.basket.user-is-owner']);
|
||||
|
||||
$controllers->post('/{basket}/archive/', 'controller.prod.basket:archiveBasket')
|
||||
->bind('prod_baskets_basket_archive')
|
||||
->assert('basket', '\d+')
|
||||
->before($app['middleware.basket.user-is-owner']);
|
||||
|
||||
$controllers->post('/{basket}/addElements/', 'controller.prod.basket:addElements')
|
||||
->assert('basket', '\d+')
|
||||
->before($app['middleware.basket.user-is-owner']);
|
||||
|
||||
$controllers->post('/{basket}/stealElements/', 'controller.prod.basket:stealElements')
|
||||
->assert('basket', '\d+')
|
||||
->before($app['middleware.basket.user-is-owner']);
|
||||
|
||||
$controllers->get('/create/', 'controller.prod.basket:displayCreateForm')
|
||||
->bind('prod_baskets_create');
|
||||
|
||||
return $controllers;
|
||||
}
|
||||
|
||||
public function displayBasket(Application $app, Request $request, BasketEntity $basket)
|
||||
{
|
||||
if ($basket->getIsRead() === false) {
|
||||
$basket->setIsRead(true);
|
||||
$app['orm.em']->flush();
|
||||
}
|
||||
|
||||
if ($basket->getValidation()) {
|
||||
if ($basket->getValidation()->getParticipant($app['authentication']->getUser())->getIsAware() === false) {
|
||||
$basket->getValidation()->getParticipant($app['authentication']->getUser())->setIsAware(true);
|
||||
$app['orm.em']->flush();
|
||||
}
|
||||
}
|
||||
|
||||
$params = [
|
||||
'basket' => $basket,
|
||||
'ordre' => $request->query->get('order')
|
||||
];
|
||||
|
||||
return $app['twig']->render('prod/WorkZone/Basket.html.twig', $params);
|
||||
}
|
||||
|
||||
public function createBasket(Application $app, Request $request)
|
||||
{
|
||||
$Basket = new BasketEntity();
|
||||
|
||||
$Basket->setName($request->request->get('name', ''));
|
||||
$Basket->setUser($app['authentication']->getUser());
|
||||
$Basket->setDescription($request->request->get('desc'));
|
||||
|
||||
$app['orm.em']->persist($Basket);
|
||||
|
||||
$n = 0;
|
||||
|
||||
$records = RecordsRequest::fromRequest($app, $request, true);
|
||||
|
||||
foreach ($records as $record) {
|
||||
if ($Basket->hasRecord($app, $record)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$basket_element = new BasketElement();
|
||||
$basket_element->setRecord($record);
|
||||
$basket_element->setBasket($Basket);
|
||||
|
||||
$app['orm.em']->persist($basket_element);
|
||||
|
||||
$Basket->addElement($basket_element);
|
||||
|
||||
$n++;
|
||||
}
|
||||
|
||||
$app['orm.em']->flush();
|
||||
|
||||
if ($request->getRequestFormat() === 'json') {
|
||||
$data = [
|
||||
'success' => true
|
||||
, 'message' => $app->trans('Basket created')
|
||||
, 'basket' => [
|
||||
'id' => $Basket->getId()
|
||||
]
|
||||
];
|
||||
|
||||
return $app->json($data);
|
||||
} else {
|
||||
return $app->redirectPath('prod_baskets_basket', ['basket' => $Basket->getId()]);
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteBasket(Application $app, Request $request, BasketEntity $basket)
|
||||
{
|
||||
$app['orm.em']->remove($basket);
|
||||
$app['orm.em']->flush();
|
||||
|
||||
$data = [
|
||||
'success' => true
|
||||
, 'message' => $app->trans('Basket has been deleted')
|
||||
];
|
||||
|
||||
if ($request->getRequestFormat() === 'json') {
|
||||
return $app->json($data);
|
||||
} else {
|
||||
return $app->redirectPath('prod_workzone_show');
|
||||
}
|
||||
}
|
||||
|
||||
public function removeBasketElement(Application $app, Request $request, BasketEntity $basket, $basket_element_id)
|
||||
{
|
||||
$basketElement = $app['orm.em']->getRepository('Phraseanet:BasketElement')->find($basket_element_id);
|
||||
$ord = $basketElement->getOrd();
|
||||
|
||||
foreach ($basket->getElements() as $basket_element) {
|
||||
if ($basket_element->getOrd() > $ord) {
|
||||
$basket_element->setOrd($basket_element->getOrd() - 1);
|
||||
}
|
||||
if ($basket_element->getId() === (int) $basket_element_id) {
|
||||
$basket->removeElement($basket_element);
|
||||
$app['orm.em']->remove($basket_element);
|
||||
}
|
||||
}
|
||||
|
||||
$app['orm.em']->persist($basket);
|
||||
$app['orm.em']->flush();
|
||||
|
||||
$data = ['success' => true, 'message' => $app->trans('Record removed from basket')];
|
||||
|
||||
if ($request->getRequestFormat() === 'json') {
|
||||
return $app->json($data);
|
||||
} else {
|
||||
return $app->redirectPath('prod_workzone_show');
|
||||
}
|
||||
}
|
||||
|
||||
public function updateBasket(Application $app, Request $request, BasketEntity $basket)
|
||||
{
|
||||
$success = false;
|
||||
|
||||
try {
|
||||
$basket->setName($request->request->get('name', ''));
|
||||
$basket->setDescription($request->request->get('description'));
|
||||
|
||||
$app['orm.em']->merge($basket);
|
||||
$app['orm.em']->flush();
|
||||
|
||||
$success = true;
|
||||
$msg = $app->trans('Basket has been updated');
|
||||
} catch (NotFoundHttpException $e) {
|
||||
$msg = $app->trans('The requested basket does not exist');
|
||||
} catch (AccessDeniedHttpException $e) {
|
||||
$msg = $app->trans('You do not have access to this basket');
|
||||
} catch (\Exception $e) {
|
||||
$msg = $app->trans('An error occurred');
|
||||
}
|
||||
|
||||
$data = [
|
||||
'success' => $success
|
||||
, 'message' => $msg
|
||||
, 'basket' => ['id' => $basket->getId()]
|
||||
];
|
||||
|
||||
if ($request->getRequestFormat() === 'json') {
|
||||
return $app->json($data);
|
||||
} else {
|
||||
return $app->redirectPath('prod_workzone_show');
|
||||
}
|
||||
}
|
||||
|
||||
public function displayUpdateForm(Application $app, BasketEntity $basket)
|
||||
{
|
||||
return $app['twig']->render('prod/Baskets/Update.html.twig', ['basket' => $basket]);
|
||||
}
|
||||
|
||||
public function displayReorderForm(Application $app, BasketEntity $basket)
|
||||
{
|
||||
return $app['twig']->render('prod/Baskets/Reorder.html.twig', ['basket' => $basket]);
|
||||
}
|
||||
|
||||
public function reorder(Application $app, BasketEntity $basket)
|
||||
{
|
||||
$ret = ['success' => false, 'message' => $app->trans('An error occured')];
|
||||
try {
|
||||
$order = $app['request']->request->get('element');
|
||||
|
||||
/* @var $basket BasketEntity */
|
||||
foreach ($basket->getElements() as $basketElement) {
|
||||
if (isset($order[$basketElement->getId()])) {
|
||||
$basketElement->setOrd($order[$basketElement->getId()]);
|
||||
|
||||
$app['orm.em']->merge($basketElement);
|
||||
}
|
||||
}
|
||||
|
||||
$app['orm.em']->flush();
|
||||
$ret = ['success' => true, 'message' => $app->trans('Basket updated')];
|
||||
} catch (\Exception $e) {
|
||||
|
||||
}
|
||||
|
||||
return $app->json($ret);
|
||||
}
|
||||
|
||||
public function archiveBasket(Application $app, Request $request, BasketEntity $basket)
|
||||
{
|
||||
$archive_status = (Boolean) $request->query->get('archive');
|
||||
|
||||
$basket->setArchived($archive_status);
|
||||
|
||||
$app['orm.em']->merge($basket);
|
||||
$app['orm.em']->flush();
|
||||
|
||||
if ($archive_status) {
|
||||
$message = $app->trans('Basket has been archived');
|
||||
} else {
|
||||
$message = $app->trans('Basket has been unarchived');
|
||||
}
|
||||
|
||||
$data = [
|
||||
'success' => true
|
||||
, 'archive' => $archive_status
|
||||
, 'message' => $message
|
||||
];
|
||||
|
||||
if ($request->getRequestFormat() === 'json') {
|
||||
return $app->json($data);
|
||||
} else {
|
||||
return $app->redirectPath('prod_workzone_show');
|
||||
}
|
||||
}
|
||||
|
||||
public function addElements(Application $app, Request $request, BasketEntity $basket)
|
||||
{
|
||||
$n = 0;
|
||||
|
||||
$records = RecordsRequest::fromRequest($app, $request, true);
|
||||
|
||||
foreach ($records as $record) {
|
||||
if ($basket->hasRecord($app, $record))
|
||||
continue;
|
||||
|
||||
$basket_element = new BasketElement();
|
||||
$basket_element->setRecord($record);
|
||||
$basket_element->setBasket($basket);
|
||||
|
||||
$app['orm.em']->persist($basket_element);
|
||||
|
||||
$basket->addElement($basket_element);
|
||||
|
||||
if (null !== $validationSession = $basket->getValidation()) {
|
||||
|
||||
$participants = $validationSession->getParticipants();
|
||||
|
||||
foreach ($participants as $participant) {
|
||||
$validationData = new ValidationData();
|
||||
$validationData->setParticipant($participant);
|
||||
$validationData->setBasketElement($basket_element);
|
||||
|
||||
$app['orm.em']->persist($validationData);
|
||||
}
|
||||
}
|
||||
|
||||
$n++;
|
||||
}
|
||||
|
||||
$app['orm.em']->flush();
|
||||
|
||||
$data = [
|
||||
'success' => true
|
||||
, 'message' => $app->trans('%quantity% records added', ['%quantity%' => $n])
|
||||
];
|
||||
|
||||
if ($request->getRequestFormat() === 'json') {
|
||||
return $app->json($data);
|
||||
} else {
|
||||
return $app->redirectPath('prod_workzone_show');
|
||||
}
|
||||
}
|
||||
|
||||
public function stealElements(Application $app, Request $request, BasketEntity $basket)
|
||||
{
|
||||
$n = 0;
|
||||
|
||||
foreach ($request->request->get('elements') as $bask_element_id) {
|
||||
try {
|
||||
$basket_element = $app['repo.basket-elements']->findUserElement($bask_element_id, $app['authentication']->getUser());
|
||||
} catch (\Exception $e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$basket_element->getBasket()->removeElement($basket_element);
|
||||
$basket_element->setBasket($basket);
|
||||
$basket->addElement($basket_element);
|
||||
$n++;
|
||||
}
|
||||
|
||||
$app['orm.em']->flush();
|
||||
|
||||
$data = ['success' => true, 'message' => $app->trans('%quantity% records moved', ['%quantity%' => $n])];
|
||||
|
||||
if ($request->getRequestFormat() === 'json') {
|
||||
return $app->json($data);
|
||||
} else {
|
||||
return $app->redirectPath('prod_workzone_show');
|
||||
}
|
||||
}
|
||||
|
||||
public function displayCreateForm(Application $app)
|
||||
{
|
||||
return $app['twig']->render('prod/Baskets/Create.html.twig');
|
||||
}
|
||||
}
|
100
lib/Alchemy/Phrasea/ControllerProvider/Prod/BasketProvider.php
Normal file
100
lib/Alchemy/Phrasea/ControllerProvider/Prod/BasketProvider.php
Normal file
@@ -0,0 +1,100 @@
|
||||
<?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\ControllerProvider\Prod;
|
||||
|
||||
use Alchemy\Phrasea\Application as PhraseaApplication;
|
||||
use Alchemy\Phrasea\Controller\Prod\BasketController;
|
||||
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
|
||||
use Silex\Application;
|
||||
use Silex\ControllerProviderInterface;
|
||||
use Silex\ServiceProviderInterface;
|
||||
|
||||
class BasketProvider implements ControllerProviderInterface, ServiceProviderInterface
|
||||
{
|
||||
use ControllerProviderTrait;
|
||||
|
||||
public function register(Application $app)
|
||||
{
|
||||
$app['controller.prod.basket'] = $app->share(function (PhraseaApplication $app) {
|
||||
return new BasketController($app);
|
||||
});
|
||||
}
|
||||
|
||||
public function boot(Application $app)
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
|
||||
public function connect(Application $app)
|
||||
{
|
||||
$controllers = $this->createAuthenticatedCollection($app);
|
||||
|
||||
$controllers
|
||||
// Silex\Route::convert is not used as this should be done prior the before middleware
|
||||
->before($app['middleware.basket.converter'])
|
||||
->before($app['middleware.basket.user-access']);
|
||||
|
||||
$controllers->get('/{basket}/', 'controller.prod.basket:displayBasket')
|
||||
->bind('prod_baskets_basket')
|
||||
->assert('basket', '\d+');
|
||||
|
||||
$controllers->post('/', 'controller.prod.basket:createBasket')
|
||||
->bind('prod_baskets');
|
||||
|
||||
$controllers->post('/{basket}/delete/', 'controller.prod.basket:deleteBasket')
|
||||
->assert('basket', '\d+')
|
||||
->bind('basket_delete')
|
||||
->before($app['middleware.basket.user-is-owner']);
|
||||
|
||||
$controllers->post('/{basket}/delete/{basket_element_id}/', 'controller.prod.basket:removeBasketElement')
|
||||
->bind('prod_baskets_basket_element_remove')
|
||||
->assert('basket', '\d+')
|
||||
->assert('basket_element_id', '\d+')
|
||||
->before($app['middleware.basket.user-is-owner']);
|
||||
|
||||
$controllers->post('/{basket}/update/', 'controller.prod.basket:updateBasket')
|
||||
->bind('prod_baskets_basket_update')
|
||||
->assert('basket', '\d+')
|
||||
->before($app['middleware.basket.user-is-owner']);
|
||||
|
||||
$controllers->get('/{basket}/update/', 'controller.prod.basket:displayUpdateForm')
|
||||
->assert('basket', '\d+')
|
||||
->before($app['middleware.basket.user-is-owner']);
|
||||
|
||||
$controllers->get('/{basket}/reorder/', 'controller.prod.basket:displayReorderForm')
|
||||
->assert('basket', '\d+')
|
||||
->bind('prod_baskets_basket_reorder')
|
||||
->before($app['middleware.basket.user-is-owner']);
|
||||
|
||||
$controllers->post('/{basket}/reorder/', 'controller.prod.basket:reorder')
|
||||
->assert('basket', '\d+')
|
||||
->before($app['middleware.basket.user-is-owner']);
|
||||
|
||||
$controllers->post('/{basket}/archive/', 'controller.prod.basket:archiveBasket')
|
||||
->bind('prod_baskets_basket_archive')
|
||||
->assert('basket', '\d+')
|
||||
->before($app['middleware.basket.user-is-owner']);
|
||||
|
||||
$controllers->post('/{basket}/addElements/', 'controller.prod.basket:addElements')
|
||||
->assert('basket', '\d+')
|
||||
->before($app['middleware.basket.user-is-owner']);
|
||||
|
||||
$controllers->post('/{basket}/stealElements/', 'controller.prod.basket:stealElements')
|
||||
->assert('basket', '\d+')
|
||||
->before($app['middleware.basket.user-is-owner']);
|
||||
|
||||
$controllers->get('/create/', 'controller.prod.basket:displayCreateForm')
|
||||
->bind('prod_baskets_create');
|
||||
|
||||
return $controllers;
|
||||
}
|
||||
}
|
@@ -11,26 +11,36 @@
|
||||
|
||||
namespace Alchemy\Phrasea\ControllerProvider\Prod;
|
||||
|
||||
use Alchemy\Phrasea\Controller\Prod\HttpException;
|
||||
use Alchemy\Phrasea\Application as PhraseaApplication;
|
||||
use Alchemy\Phrasea\Controller\Prod\BridgeController;
|
||||
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
|
||||
use Alchemy\Phrasea\Helper\Record as RecordHelper;
|
||||
use Silex\Application;
|
||||
use Silex\ControllerProviderInterface;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Silex\ServiceProviderInterface;
|
||||
|
||||
class Bridge implements ControllerProviderInterface
|
||||
class Bridge implements ControllerProviderInterface, ServiceProviderInterface
|
||||
{
|
||||
use ControllerProviderTrait;
|
||||
|
||||
public function register(Application $app)
|
||||
{
|
||||
$app['bridge.controller'] = $app->share(function (PhraseaApplication $app) {
|
||||
return new BridgeController($app);
|
||||
});
|
||||
}
|
||||
|
||||
public function boot(Application $app)
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
|
||||
public function connect(Application $app)
|
||||
{
|
||||
$app['bridge.controller'] = $this;
|
||||
|
||||
$controllers = $this->createAuthenticatedCollection($app);
|
||||
|
||||
$controllers->before(function (Request $request) use ($app) {
|
||||
$app['firewall']->requireRight('bas_chupub');
|
||||
$firewall = $this->getFirewall($app);
|
||||
$controllers->before(function () use ($firewall) {
|
||||
$firewall->requireRight('bas_chupub');
|
||||
});
|
||||
|
||||
$controllers
|
||||
@@ -89,389 +99,4 @@ class Bridge implements ControllerProviderInterface
|
||||
|
||||
return $controllers;
|
||||
}
|
||||
|
||||
private function requireConnection(Application $app, \Bridge_Account $account)
|
||||
{
|
||||
$app['bridge.account'] = $account;
|
||||
|
||||
if (!$account->get_api()->get_connector()->is_configured()) {
|
||||
throw new \Bridge_Exception_ApiConnectorNotConfigured("Bridge API Connector is not configured");
|
||||
}
|
||||
if (!$account->get_api()->get_connector()->is_connected()) {
|
||||
throw new \Bridge_Exception_ApiConnectorNotConnected("Bridge API Connector is not connected");
|
||||
}
|
||||
}
|
||||
|
||||
public function doPostManager(Application $app, Request $request)
|
||||
{
|
||||
$route = new RecordHelper\Bridge($app, $request);
|
||||
$params = [
|
||||
'user_accounts' => \Bridge_Account::get_accounts_by_user($app, $app['authentication']->getUser()),
|
||||
'available_apis' => \Bridge_Api::get_availables($app),
|
||||
'route' => $route,
|
||||
'current_account_id' => '',
|
||||
];
|
||||
|
||||
return $app['twig']->render('prod/actions/Bridge/index.html.twig', $params);
|
||||
}
|
||||
|
||||
public function doGetLogin(Application $app, Request $request, $api_name)
|
||||
{
|
||||
$connector = \Bridge_Api::get_connector_by_name($app, $api_name);
|
||||
|
||||
return $app->redirect($connector->get_auth_url());
|
||||
}
|
||||
|
||||
public function doGetCallback(Application $app, Request $request, $api_name)
|
||||
{
|
||||
$error_message = '';
|
||||
try {
|
||||
$api = \Bridge_Api::get_by_api_name($app, $api_name);
|
||||
$connector = $api->get_connector();
|
||||
$response = $connector->connect();
|
||||
$user_id = $connector->get_user_id();
|
||||
|
||||
try {
|
||||
$account = \Bridge_Account::load_account_from_distant_id($app, $api, $app['authentication']->getUser(), $user_id);
|
||||
} catch (\Bridge_Exception_AccountNotFound $e) {
|
||||
$account = \Bridge_Account::create($app, $api, $app['authentication']->getUser(), $user_id, $connector->get_user_name());
|
||||
}
|
||||
|
||||
$settings = $account->get_settings();
|
||||
|
||||
if (isset($response['auth_token'])) {
|
||||
$settings->set('auth_token', $response['auth_token']);
|
||||
}
|
||||
if (isset($response['refresh_token'])) {
|
||||
$settings->set('refresh_token', $response['refresh_token']);
|
||||
}
|
||||
|
||||
$connector->set_auth_settings($settings);
|
||||
$connector->reconnect();
|
||||
} catch (\Exception $e) {
|
||||
$error_message = $e->getMessage();
|
||||
}
|
||||
|
||||
$params = ['error_message' => $error_message];
|
||||
|
||||
return $app['twig']->render('prod/actions/Bridge/callback.html.twig', $params);
|
||||
}
|
||||
|
||||
public function doGetAccountLogout(Application $app, Request $request, $account_id)
|
||||
{
|
||||
$account = \Bridge_Account::load_account($app, $account_id);
|
||||
$this->requireConnection($app, $account);
|
||||
$account->get_api()->get_connector()->disconnect();
|
||||
|
||||
return $app->redirectPath('bridge_load_elements', [
|
||||
'account_id' => $account_id,
|
||||
'type' => $account->get_api()->get_connector()->get_default_element_type(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function doPostAccountDelete(Application $app, Request $request, $account_id)
|
||||
{
|
||||
$success = false;
|
||||
$message = '';
|
||||
try {
|
||||
$account = \Bridge_Account::load_account($app, $account_id);
|
||||
|
||||
if ($account->get_user()->getId() !== $app['authentication']->getUser()->getId()) {
|
||||
throw new HttpException(403, 'Access forbiden');
|
||||
}
|
||||
|
||||
$account->delete();
|
||||
$success = true;
|
||||
} catch (\Bridge_Exception_AccountNotFound $e) {
|
||||
$message = $app->trans('Account is not found.');
|
||||
} catch (\Exception $e) {
|
||||
$message = $app->trans('Something went wrong, please contact an administrator');
|
||||
}
|
||||
|
||||
return $app->json(['success' => $success, 'message' => $message]);
|
||||
}
|
||||
|
||||
public function doGetloadRecords(Application $app, Request $request, $account_id)
|
||||
{
|
||||
$page = max((int) $request->query->get('page'), 0);
|
||||
$quantity = 10;
|
||||
$offset_start = max(($page - 1) * $quantity, 0);
|
||||
$account = \Bridge_Account::load_account($app, $account_id);
|
||||
$elements = \Bridge_Element::get_elements_by_account($app, $account, $offset_start, $quantity);
|
||||
|
||||
$this->requireConnection($app, $account);
|
||||
|
||||
$params = [
|
||||
'adapter_action' => 'load-records'
|
||||
, 'account' => $account
|
||||
, 'elements' => $elements
|
||||
, 'error_message' => $request->query->get('error')
|
||||
, 'notice_message' => $request->query->get('notice')
|
||||
];
|
||||
|
||||
return $app['twig']->render('prod/actions/Bridge/records_list.html.twig', $params);
|
||||
}
|
||||
|
||||
public function doGetLoadElements(Application $app, Request $request, $account_id, $type)
|
||||
{
|
||||
$page = max((int) $request->query->get('page'), 0);
|
||||
$quantity = 5;
|
||||
$offset_start = max(($page - 1) * $quantity, 0);
|
||||
$account = \Bridge_Account::load_account($app, $account_id);
|
||||
|
||||
$this->requireConnection($app, $account);
|
||||
|
||||
$elements = $account->get_api()->list_elements($type, $offset_start, $quantity);
|
||||
|
||||
$params = [
|
||||
'action_type' => $type,
|
||||
'adapter_action' => 'load-elements',
|
||||
'account' => $account,
|
||||
'elements' => $elements,
|
||||
'error_message' => $request->query->get('error'),
|
||||
'notice_message' => $request->query->get('notice'),
|
||||
];
|
||||
|
||||
return $app['twig']->render('prod/actions/Bridge/element_list.html.twig', $params);
|
||||
}
|
||||
|
||||
public function doGetLoadContainers(Application $app, Request $request, $account_id, $type)
|
||||
{
|
||||
$page = max((int) $request->query->get('page'), 0);
|
||||
$quantity = 5;
|
||||
$offset_start = max(($page - 1) * $quantity, 0);
|
||||
$account = \Bridge_Account::load_account($app, $account_id);
|
||||
|
||||
$this->requireConnection($app, $account);
|
||||
$elements = $account->get_api()->list_containers($type, $offset_start, $quantity);
|
||||
|
||||
$params = [
|
||||
'action_type' => $type,
|
||||
'adapter_action' => 'load-containers',
|
||||
'account' => $account,
|
||||
'elements' => $elements,
|
||||
'error_message' => $request->query->get('error'),
|
||||
'notice_message' => $request->query->get('notice'),
|
||||
];
|
||||
|
||||
return $app['twig']->render('prod/actions/Bridge/element_list.html.twig', $params);
|
||||
}
|
||||
|
||||
public function doGetAction(Application $app, Request $request, $account_id, $action, $element_type)
|
||||
{
|
||||
$account = \Bridge_Account::load_account($app, $account_id);
|
||||
|
||||
$this->requireConnection($app, $account);
|
||||
$elements = $request->query->get('elements_list', []);
|
||||
$elements = is_array($elements) ? $elements : explode(';', $elements);
|
||||
|
||||
$destination = $request->query->get('destination');
|
||||
$route_params = [];
|
||||
$class = $account->get_api()->get_connector()->get_object_class_from_type($element_type);
|
||||
|
||||
switch ($action) {
|
||||
case 'createcontainer':
|
||||
break;
|
||||
|
||||
case 'modify':
|
||||
if (count($elements) != 1) {
|
||||
return $app->redirectPath('bridge_load_elements', [
|
||||
'account_id' => $account_id,
|
||||
'type' => $element_type,
|
||||
'page' => '',
|
||||
'error' => $app->trans('Vous ne pouvez pas editer plusieurs elements simultanement'),
|
||||
]);
|
||||
}
|
||||
foreach ($elements as $element_id) {
|
||||
if ($class === \Bridge_Api_Interface::OBJECT_CLASS_ELEMENT) {
|
||||
$route_params = ['element' => $account->get_api()->get_element_from_id($element_id, $element_type)];
|
||||
}
|
||||
if ($class === \Bridge_Api_Interface::OBJECT_CLASS_CONTAINER) {
|
||||
$route_params = ['element' => $account->get_api()->get_container_from_id($element_id, $element_type)];
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'moveinto':
|
||||
$route_params = ['containers' => $account->get_api()->list_containers($destination, 0, 0)];
|
||||
break;
|
||||
|
||||
case 'deleteelement':
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \Exception($app->trans('Vous essayez de faire une action que je ne connais pas !'));
|
||||
break;
|
||||
}
|
||||
|
||||
$params = [
|
||||
'account' => $account,
|
||||
'destination' => $destination,
|
||||
'element_type' => $element_type,
|
||||
'action' => $action,
|
||||
'constraint_errors' => null,
|
||||
'adapter_action' => $action,
|
||||
'elements' => $elements,
|
||||
'error_message' => $request->query->get('error'),
|
||||
'notice_message' => $request->query->get('notice'),
|
||||
];
|
||||
|
||||
$params = array_merge($params, $route_params);
|
||||
$template = 'prod/actions/Bridge/' . $account->get_api()->get_connector()->get_name() . '/' . $element_type . '_' . $action . ($destination ? '_' . $destination : '') . '.html.twig';
|
||||
|
||||
return $app['twig']->render($template, $params);
|
||||
}
|
||||
|
||||
public function doPostAction(Application $app, Request $request, $account_id, $action, $element_type)
|
||||
{
|
||||
$account = \Bridge_Account::load_account($app, $account_id);
|
||||
|
||||
$this->requireConnection($app, $account);
|
||||
|
||||
$elements = $request->request->get('elements_list', []);
|
||||
$elements = is_array($elements) ? $elements : explode(';', $elements);
|
||||
|
||||
$destination = $request->request->get('destination');
|
||||
|
||||
$class = $account->get_api()->get_connector()->get_object_class_from_type($element_type);
|
||||
$html = '';
|
||||
switch ($action) {
|
||||
case 'modify':
|
||||
if (count($elements) != 1) {
|
||||
return $app->redirect('/prod/bridge/action/' . $account_id . '/' . $action . '/' . $element_type . '/?elements_list=' . implode(';', $elements) . '&error=' . $app->trans('Vous ne pouvez pas editer plusieurs elements simultanement'));
|
||||
}
|
||||
try {
|
||||
foreach ($elements as $element_id) {
|
||||
$datas = $account->get_api()->get_connector()->get_update_datas($request);
|
||||
$errors = $account->get_api()->get_connector()->check_update_constraints($datas);
|
||||
}
|
||||
|
||||
if (count($errors) > 0) {
|
||||
$params = [
|
||||
'element' => $account->get_api()->get_element_from_id($element_id, $element_type),
|
||||
'account' => $account,
|
||||
'destination' => $destination,
|
||||
'element_type' => $element_type,
|
||||
'action' => $action,
|
||||
'elements' => $elements,
|
||||
'adapter_action' => $action,
|
||||
'error_message' => $app->trans('Request contains invalid datas'),
|
||||
'constraint_errors' => $errors,
|
||||
'notice_message' => $request->request->get('notice'),
|
||||
];
|
||||
|
||||
$template = 'prod/actions/Bridge/' . $account->get_api()->get_connector()->get_name() . '/' . $element_type . '_' . $action . ($destination ? '_' . $destination : '') . '.html.twig';
|
||||
|
||||
return $app['twig']->render($template, $params);
|
||||
}
|
||||
|
||||
foreach ($elements as $element_id) {
|
||||
$datas = $account->get_api()->get_connector()->get_update_datas($request);
|
||||
$account->get_api()->update_element($element_type, $element_id, $datas);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
return $app->redirect('/prod/bridge/action/' . $account_id . '/' . $action . '/' . $element_type . '/?elements_list[]=' . $element_id . '&error=' . get_class($e) . ' : ' . $e->getMessage());
|
||||
}
|
||||
|
||||
return $app->redirect('/prod/bridge/adapter/' . $account_id . '/load-' . $class . 's/' . $element_type . '/?page=&update=success#anchor');
|
||||
case 'createcontainer':
|
||||
try {
|
||||
$container_type = $request->request->get('f_container_type');
|
||||
|
||||
$account->get_api()->create_container($container_type, $request);
|
||||
} catch (\Exception $e) {
|
||||
return $app->redirect('/prod/bridge/action/' . $account_id . '/' . $action . '/' . $element_type . '/?error=' . get_class($e) . ' : ' . $e->getMessage());
|
||||
}
|
||||
|
||||
return $app->redirect('/prod/bridge/adapter/' . $account_id . '/load-' . $class . 's/' . $element_type . '/?page=&update=success#anchor');
|
||||
case 'moveinto':
|
||||
try {
|
||||
$container_id = $request->request->get('container_id');
|
||||
foreach ($elements as $element_id) {
|
||||
$account->get_api()->add_element_to_container($element_type, $element_id, $destination, $container_id);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
return $app->redirect('/prod/bridge/action/' . $account_id . '/' . $action . '/' . $element_type . '/?error=' . get_class($e) . ' : ' . $e->getMessage());
|
||||
}
|
||||
|
||||
return $app->redirect('/prod/bridge/adapter/' . $account_id . '/load-containers/' . $destination . '/?page=&update=success#anchor');
|
||||
case 'deleteelement':
|
||||
try {
|
||||
foreach ($elements as $element_id) {
|
||||
$account->get_api()->delete_object($element_type, $element_id);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
return $app->redirect('/prod/bridge/action/' . $account_id . '/' . $action . '/' . $element_type . '/?error=' . get_class($e) . $e->getMessage());
|
||||
}
|
||||
|
||||
return $app->redirect('/prod/bridge/adapter/' . $account_id . '/load-' . $class . 's/' . $element_type . '/');
|
||||
default:
|
||||
throw new \Exception('Unknown action');
|
||||
break;
|
||||
}
|
||||
|
||||
return new Response($html);
|
||||
}
|
||||
|
||||
public function doGetUpload(Application $app, Request $request)
|
||||
{
|
||||
$account = \Bridge_Account::load_account($app, $request->query->get('account_id'));
|
||||
$this->requireConnection($app, $account);
|
||||
|
||||
$route = new RecordHelper\Bridge($app, $request);
|
||||
|
||||
$route->grep_records($account->get_api()->acceptable_records());
|
||||
|
||||
$params = [
|
||||
'route' => $route,
|
||||
'account' => $account,
|
||||
'error_message' => $request->query->get('error'),
|
||||
'notice_message' => $request->query->get('notice'),
|
||||
'constraint_errors' => null,
|
||||
'adapter_action' => 'upload',
|
||||
];
|
||||
|
||||
return $app['twig']->render(
|
||||
'prod/actions/Bridge/' . $account->get_api()->get_connector()->get_name() . '/upload.html.twig', $params
|
||||
);
|
||||
}
|
||||
|
||||
public function doPostUpload(Application $app, Request $request)
|
||||
{
|
||||
$errors = [];
|
||||
$account = \Bridge_Account::load_account($app, $request->request->get('account_id'));
|
||||
$this->requireConnection($app, $account);
|
||||
|
||||
$route = new RecordHelper\Bridge($app, $request);
|
||||
$route->grep_records($account->get_api()->acceptable_records());
|
||||
$connector = $account->get_api()->get_connector();
|
||||
|
||||
// check constraints
|
||||
foreach ($route->get_elements() as $record) {
|
||||
$datas = $connector->get_upload_datas($request, $record);
|
||||
$errors = array_merge($errors, $connector->check_upload_constraints($datas, $record));
|
||||
}
|
||||
|
||||
if (count($errors) > 0) {
|
||||
$params = [
|
||||
'route' => $route,
|
||||
'account' => $account,
|
||||
'error_message' => $app->trans('Request contains invalid datas'),
|
||||
'constraint_errors' => $errors,
|
||||
'notice_message' => $request->request->get('notice'),
|
||||
'adapter_action' => 'upload',
|
||||
];
|
||||
|
||||
return $app['twig']->render('prod/actions/Bridge/' . $account->get_api()->get_connector()->get_name() . '/upload.html.twig', $params);
|
||||
}
|
||||
|
||||
foreach ($route->get_elements() as $record) {
|
||||
$datas = $connector->get_upload_datas($request, $record);
|
||||
$title = isset($datas["title"]) ? $datas["title"] : '';
|
||||
$default_type = $connector->get_default_element_type();
|
||||
\Bridge_Element::create($app, $account, $record, $title, \Bridge_Element::STATUS_PENDING, $default_type, $datas);
|
||||
}
|
||||
|
||||
return $app->redirect('/prod/bridge/adapter/' . $account->get_id() . '/load-records/?notice=' . $app->trans('%quantity% elements en attente', ['%quantity%' => count($route->get_elements())]));
|
||||
}
|
||||
}
|
||||
|
@@ -11,25 +11,38 @@
|
||||
|
||||
namespace Alchemy\Phrasea\ControllerProvider\Prod;
|
||||
|
||||
use Alchemy\Phrasea\Http\DeliverDataInterface;
|
||||
use Alchemy\Phrasea\Model\Entities\Token;
|
||||
use Alchemy\Phrasea\Application as PhraseaApplication;
|
||||
use Alchemy\Phrasea\Controller\Prod\DoDownloadController;
|
||||
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
|
||||
use Silex\Application;
|
||||
use Silex\ControllerProviderInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
use Silex\ServiceProviderInterface;
|
||||
|
||||
class DoDownload implements ControllerProviderInterface
|
||||
class DoDownload implements ControllerProviderInterface, ServiceProviderInterface
|
||||
{
|
||||
use ControllerProviderTrait;
|
||||
|
||||
public function register(Application $app)
|
||||
{
|
||||
$app['controller.prod.do-download'] = $app->share(function (PhraseaApplication $app) {
|
||||
return (new DoDownloadController($app))
|
||||
->setDispatcherLocator(function () use ($app) {
|
||||
return $app['dispatcher'];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public function boot(Application $app)
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function connect(Application $app)
|
||||
{
|
||||
$app['controller.prod.do-download'] = $this;
|
||||
|
||||
$controllers = $app['controllers_factory'];
|
||||
$controllers = $this->createCollection($app);
|
||||
|
||||
$controllers->get('/{token}/prepare/', 'controller.prod.do-download:prepareDownload')
|
||||
->before($app['middleware.token.converter'])
|
||||
@@ -48,155 +61,4 @@ class DoDownload implements ControllerProviderInterface
|
||||
|
||||
return $controllers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare a set of documents for download
|
||||
*
|
||||
* @param Application $app
|
||||
* @param Request $request
|
||||
* @param Token $token
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function prepareDownload(Application $app, Request $request, Token $token)
|
||||
{
|
||||
if (false === $list = @unserialize($token->getData())) {
|
||||
$app->abort(500, 'Invalid datas');
|
||||
}
|
||||
if (!is_array($list)) {
|
||||
$app->abort(500, 'Invalid datas');
|
||||
}
|
||||
|
||||
foreach (['export_name', 'files'] as $key) {
|
||||
if (!isset($list[$key])) {
|
||||
$app->abort(500, 'Invalid datas');
|
||||
}
|
||||
}
|
||||
|
||||
$records = [];
|
||||
|
||||
foreach ($list['files'] as $file) {
|
||||
if (!is_array($file) || !isset($file['base_id']) || !isset($file['record_id'])) {
|
||||
continue;
|
||||
}
|
||||
$sbasId = \phrasea::sbasFromBas($app, $file['base_id']);
|
||||
|
||||
try {
|
||||
$record = new \record_adapter($app, $sbasId, $file['record_id']);
|
||||
} catch (\Exception $e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$records[sprintf('%s_%s', $sbasId, $file['record_id'])] = $record;
|
||||
}
|
||||
|
||||
return new Response($app['twig']->render(
|
||||
'/prod/actions/Download/prepare.html.twig', [
|
||||
'module_name' => $app->trans('Export'),
|
||||
'module' => $app->trans('Export'),
|
||||
'list' => $list,
|
||||
'records' => $records,
|
||||
'token' => $token,
|
||||
'anonymous' => $request->query->get('anonymous', false),
|
||||
'type' => $request->query->get('type', \Session_Logger::EVENT_EXPORTDOWNLOAD)
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Download a set of documents
|
||||
*
|
||||
* @param Application $app
|
||||
* @param Request $request
|
||||
* @param Token $token
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function downloadDocuments(Application $app, Request $request, Token $token)
|
||||
{
|
||||
if (false === $list = @unserialize($token->getData())) {
|
||||
$app->abort(500, 'Invalid datas');
|
||||
}
|
||||
if (!is_array($list)) {
|
||||
$app->abort(500, 'Invalid datas');
|
||||
}
|
||||
|
||||
foreach (['export_name', 'files'] as $key) {
|
||||
if (!isset($list[$key])) {
|
||||
$app->abort(500, 'Invalid datas');
|
||||
}
|
||||
}
|
||||
|
||||
$exportName = $list['export_name'];
|
||||
|
||||
if ($list['count'] === 1) {
|
||||
$file = end($list['files']);
|
||||
$subdef = end($file['subdefs']);
|
||||
$exportName = sprintf('%s%s.%s', $file['export_name'], $subdef['ajout'], $subdef['exportExt']);
|
||||
$exportFile = \p4string::addEndSlash($subdef['path']) . $subdef['file'];
|
||||
$mime = $subdef['mime'];
|
||||
$list['complete'] = true;
|
||||
} else {
|
||||
$exportFile = $app['tmp.download.path'].'/'.$token->getValue() . '.zip';
|
||||
$mime = 'application/zip';
|
||||
}
|
||||
|
||||
if (!$app['filesystem']->exists($exportFile)) {
|
||||
$app->abort(404, 'Download file not found');
|
||||
}
|
||||
|
||||
$app['dispatcher']->addListener(KernelEvents::RESPONSE, function (FilterResponseEvent $event) use ($list, $app) {
|
||||
\set_export::log_download(
|
||||
$app,
|
||||
$list,
|
||||
$event->getRequest()->get('type'),
|
||||
!!$event->getRequest()->get('anonymous', false),
|
||||
(isset($list['email']) ? $list['email'] : '')
|
||||
);
|
||||
});
|
||||
|
||||
return $app['phraseanet.file-serve']->deliverFile($exportFile, $exportName, DeliverDataInterface::DISPOSITION_ATTACHMENT, $mime);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a zip of downloaded documents
|
||||
*
|
||||
* @param Application $app
|
||||
* @param Request $request
|
||||
* @param Token $token
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function downloadExecute(Application $app, Request $request, Token $token)
|
||||
{
|
||||
if (false === $list = @unserialize($token->getData())) {
|
||||
return $app->json([
|
||||
'success' => false,
|
||||
'message' => 'Invalid datas'
|
||||
]);
|
||||
}
|
||||
|
||||
set_time_limit(0);
|
||||
// Force the session to be saved and closed.
|
||||
$app['session']->save();
|
||||
ignore_user_abort(true);
|
||||
|
||||
if ($list['count'] > 1) {
|
||||
\set_export::build_zip(
|
||||
$app,
|
||||
$token,
|
||||
$list,
|
||||
sprintf($app['tmp.download.path'].'/%s.zip', $token->getValue()) // Dest file
|
||||
);
|
||||
} else {
|
||||
$list['complete'] = true;
|
||||
$token->setData(serialize($list));
|
||||
$app['orm.em']->persist($token);
|
||||
$app['orm.em']->flush();
|
||||
}
|
||||
|
||||
return $app->json([
|
||||
'success' => true,
|
||||
'message' => ''
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@@ -11,25 +11,37 @@
|
||||
|
||||
namespace Alchemy\Phrasea\ControllerProvider\Prod;
|
||||
|
||||
use Alchemy\Phrasea\Application as PhraseaApplication;
|
||||
use Alchemy\Phrasea\Controller\Prod\DownloadController;
|
||||
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
|
||||
use Alchemy\Phrasea\Core\Event\ExportEvent;
|
||||
use Alchemy\Phrasea\Core\PhraseaEvents;
|
||||
use Silex\Application;
|
||||
use Silex\ControllerProviderInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||
use Silex\ServiceProviderInterface;
|
||||
|
||||
class Download implements ControllerProviderInterface
|
||||
class Download implements ControllerProviderInterface, ServiceProviderInterface
|
||||
{
|
||||
use ControllerProviderTrait;
|
||||
|
||||
public function register(Application $app)
|
||||
{
|
||||
$app['controller.prod.download'] = $app->share(function (PhraseaApplication $app) {
|
||||
return (new DownloadController($app))
|
||||
->setDispatcherLocator(function () use ($app) {
|
||||
return $app['dispatcher'];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public function boot(Application $app)
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function connect(Application $app)
|
||||
{
|
||||
$app['controller.prod.download'] = $this;
|
||||
|
||||
$controllers = $this->createAuthenticatedCollection($app);
|
||||
|
||||
$controllers->post('/', 'controller.prod.download:checkDownload')
|
||||
@@ -37,38 +49,4 @@ class Download implements ControllerProviderInterface
|
||||
|
||||
return $controllers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Download a set of documents
|
||||
*
|
||||
* @param Application $app
|
||||
* @param Request $request
|
||||
* @return RedirectResponse
|
||||
*/
|
||||
public function checkDownload(Application $app, Request $request)
|
||||
{
|
||||
$lst = $request->request->get('lst');
|
||||
$ssttid = $request->request->get('ssttid', '');
|
||||
$subdefs = $request->request->get('obj', []);
|
||||
|
||||
$download = new \set_export($app, $lst, $ssttid);
|
||||
|
||||
if (0 === $download->get_total_download()) {
|
||||
$app->abort(403);
|
||||
}
|
||||
|
||||
$list = $download->prepare_export(
|
||||
$app['authentication']->getUser(),
|
||||
$app['filesystem'],
|
||||
$subdefs,
|
||||
$request->request->get('type') === 'title' ? true : false,
|
||||
$request->request->get('businessfields')
|
||||
);
|
||||
|
||||
$list['export_name'] = sprintf('%s.zip', $download->getExportName());
|
||||
$token = $app['manipulator.token']->createDownloadToken($app['authentication']->getUser(), serialize($list));
|
||||
$app['dispatcher']->dispatch(PhraseaEvents::EXPORT_CREATE, new ExportEvent($app['authentication']->getUser(), $ssttid, $lst, $subdefs, $download->getExportName()));
|
||||
|
||||
return $app->redirectPath('prepare_download', ['token' => $token->getValue()]);
|
||||
}
|
||||
}
|
||||
|
@@ -11,373 +11,48 @@
|
||||
|
||||
namespace Alchemy\Phrasea\ControllerProvider\Prod;
|
||||
|
||||
use record_adapter;
|
||||
use Alchemy\Phrasea\Application as PhraseaApplication;
|
||||
use Alchemy\Phrasea\Controller\Prod\EditController;
|
||||
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
|
||||
use Alchemy\Phrasea\Core\Event\RecordEdit;
|
||||
use Alchemy\Phrasea\Core\PhraseaEvents;
|
||||
use Alchemy\Phrasea\Vocabulary\Controller as VocabularyController;
|
||||
use Alchemy\Phrasea\Controller\RecordsRequest;
|
||||
use Silex\Application;
|
||||
use Silex\ControllerProviderInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Silex\ServiceProviderInterface;
|
||||
|
||||
class Edit implements ControllerProviderInterface
|
||||
class Edit implements ControllerProviderInterface, ServiceProviderInterface
|
||||
{
|
||||
use ControllerProviderTrait;
|
||||
|
||||
public function register(Application $app)
|
||||
{
|
||||
$app['controller.prod.edit'] = $app->share(function (PhraseaApplication $app) {
|
||||
return (new EditController($app))
|
||||
->setDispatcherLocator(function () use ($app) {
|
||||
return $app['dispatcher'];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public function boot(Application $app)
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
|
||||
public function connect(Application $app)
|
||||
{
|
||||
$app['controller.prod.edit'] = $this;
|
||||
|
||||
$controllers = $this->createAuthenticatedCollection($app);
|
||||
$firewall = $this->getFirewall($app);
|
||||
|
||||
$controllers->before(function (Request $request) use ($app) {
|
||||
$app['firewall']
|
||||
$controllers->before(function () use ($firewall) {
|
||||
$firewall
|
||||
->requireNotGuest()
|
||||
->requireRight('modifyrecord');
|
||||
});
|
||||
|
||||
$controllers->post('/', function (Application $app, Request $request) {
|
||||
$controllers->post('/', 'controller.prod.edit:submitAction');
|
||||
|
||||
$records = RecordsRequest::fromRequest($app, $request, RecordsRequest::FLATTEN_YES_PRESERVE_STORIES, ['canmodifrecord']);
|
||||
$controllers->get('/vocabulary/{vocabulary}/', 'controller.prod.edit:searchVocabularyAction');
|
||||
|
||||
$thesaurus = false;
|
||||
$status = $ids = $elements = $suggValues = $fields = $JSFields = [];
|
||||
$databox = null;
|
||||
|
||||
$multipleDataboxes = count($records->databoxes()) > 1;
|
||||
|
||||
if (1 === count($records->databoxes())) {
|
||||
$databoxes = $records->databoxes();
|
||||
$databox = array_pop($databoxes);
|
||||
|
||||
/**
|
||||
* generate javascript fields
|
||||
*/
|
||||
foreach ($databox->get_meta_structure() as $meta) {
|
||||
$fields[] = $meta;
|
||||
|
||||
$separator = $meta->get_separator();
|
||||
|
||||
/** @Ignore */
|
||||
$JSFields[$meta->get_id()] = [
|
||||
'meta_struct_id' => $meta->get_id(),
|
||||
'name' => $meta->get_name(),
|
||||
'_status' => 0,
|
||||
'_value' => '',
|
||||
'_sgval' => [],
|
||||
'required' => $meta->is_required(),
|
||||
/** @Ignore */
|
||||
'label' => $meta->get_label($app['locale']),
|
||||
'readonly' => $meta->is_readonly(),
|
||||
'type' => $meta->get_type(),
|
||||
'format' => '',
|
||||
'explain' => '',
|
||||
'tbranch' => $meta->get_tbranch(),
|
||||
'maxLength' => $meta->get_tag()->getMaxLength(),
|
||||
'minLength' => $meta->get_tag()->getMinLength(),
|
||||
'multi' => $meta->is_multi(),
|
||||
'separator' => $separator,
|
||||
'vocabularyControl' => $meta->getVocabularyControl() ? $meta->getVocabularyControl()->getType() : null,
|
||||
'vocabularyRestricted' => $meta->getVocabularyControl() ? $meta->isVocabularyRestricted() : false,
|
||||
];
|
||||
|
||||
if (trim($meta->get_tbranch()) !== '') {
|
||||
$thesaurus = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* generate javascript sugg values
|
||||
*/
|
||||
foreach ($records->collections() as $collection) {
|
||||
/* @var $record record_adapter */
|
||||
|
||||
$suggValues['b' . $collection->get_base_id()] = [];
|
||||
|
||||
if ($sxe = simplexml_load_string($collection->get_prefs())) {
|
||||
$z = $sxe->xpath('/baseprefs/sugestedValues');
|
||||
|
||||
if (!$z || !is_array($z)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($z[0] as $ki => $vi) { // les champs
|
||||
$field = $databox->get_meta_structure()->get_element_by_name($ki);
|
||||
if (!$field || !$vi) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$suggValues['b' . $collection->get_base_id()][$field->get_id()] = [];
|
||||
|
||||
foreach ($vi->value as $oneValue) {
|
||||
$suggValues['b' . $collection->get_base_id()][$field->get_id()][] = (string) $oneValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
unset($collection);
|
||||
}
|
||||
|
||||
/**
|
||||
* generate javascript status
|
||||
*/
|
||||
if ($app['acl']->get($app['authentication']->getUser())->has_right('changestatus')) {
|
||||
$statusStructure = $databox->getStatusStructure();
|
||||
foreach ($statusStructure as $statbit) {
|
||||
$bit = $statbit['bit'];
|
||||
|
||||
$status[$bit] = [];
|
||||
$status[$bit]['label0'] = $statbit['labels_off_i18n'][$app['locale']];
|
||||
$status[$bit]['label1'] = $statbit['labels_on_i18n'][$app['locale']];
|
||||
$status[$bit]['img_off'] = $statbit['img_off'];
|
||||
$status[$bit]['img_on'] = $statbit['img_on'];
|
||||
$status[$bit]['_value'] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* generate javascript elements
|
||||
*/
|
||||
foreach ($databox->get_meta_structure() as $field) {
|
||||
$databox_fields[$field->get_id()] = [
|
||||
'dirty' => false,
|
||||
'meta_struct_id' => $field->get_id(),
|
||||
'values' => []
|
||||
];
|
||||
}
|
||||
|
||||
foreach ($records as $record) {
|
||||
$indice = $record->get_number();
|
||||
$elements[$indice] = [
|
||||
'bid' => $record->get_base_id(),
|
||||
'rid' => $record->get_record_id(),
|
||||
'sselcont_id' => null,
|
||||
'_selected' => false,
|
||||
'fields' => $databox_fields
|
||||
];
|
||||
|
||||
$elements[$indice]['statbits'] = [];
|
||||
if ($app['acl']->get($app['authentication']->getUser())->has_right_on_base($record->get_base_id(), 'chgstatus')) {
|
||||
foreach ($status as $n => $s) {
|
||||
$tmp_val = substr(strrev($record->get_status()), $n, 1);
|
||||
$elements[$indice]['statbits'][$n]['value'] = ($tmp_val == '1') ? '1' : '0';
|
||||
$elements[$indice]['statbits'][$n]['dirty'] = false;
|
||||
}
|
||||
}
|
||||
|
||||
$elements[$indice]['originalname'] = $record->get_original_name();
|
||||
|
||||
foreach ($record->get_caption()->get_fields(null, true) as $field) {
|
||||
$meta_struct_id = $field->get_meta_struct_id();
|
||||
if (!isset($JSFields[$meta_struct_id])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$values = [];
|
||||
foreach ($field->get_values() as $value) {
|
||||
$type = $id = null;
|
||||
|
||||
if ($value->getVocabularyType()) {
|
||||
$type = $value->getVocabularyType()->getType();
|
||||
$id = $value->getVocabularyId();
|
||||
}
|
||||
|
||||
$values[$value->getId()] = [
|
||||
'meta_id' => $value->getId(),
|
||||
'value' => $value->getValue(),
|
||||
'vocabularyId' => $id,
|
||||
'vocabularyType' => $type
|
||||
];
|
||||
}
|
||||
|
||||
$elements[$indice]['fields'][$meta_struct_id] = [
|
||||
'dirty' => false,
|
||||
'meta_struct_id' => $meta_struct_id,
|
||||
'values' => $values
|
||||
];
|
||||
}
|
||||
|
||||
$elements[$indice]['subdefs'] = [];
|
||||
|
||||
$thumbnail = $record->get_thumbnail();
|
||||
|
||||
$elements[$indice]['subdefs']['thumbnail'] = [
|
||||
'url' => (string) $thumbnail->get_url()
|
||||
, 'w' => $thumbnail->get_width()
|
||||
, 'h' => $thumbnail->get_height()
|
||||
];
|
||||
|
||||
$elements[$indice]['preview'] = $app['twig']->render('common/preview.html.twig', ['record' => $record]);
|
||||
|
||||
$elements[$indice]['type'] = $record->get_type();
|
||||
}
|
||||
}
|
||||
|
||||
$params = [
|
||||
'multipleDataboxes' => $multipleDataboxes,
|
||||
'recordsRequest' => $records,
|
||||
'databox' => $databox,
|
||||
'JSonStatus' => json_encode($status),
|
||||
'JSonRecords' => json_encode($elements),
|
||||
'JSonFields' => json_encode($JSFields),
|
||||
'JSonIds' => json_encode(array_keys($elements)),
|
||||
'status' => $status,
|
||||
'fields' => $fields,
|
||||
'JSonSuggValues' => json_encode($suggValues),
|
||||
'thesaurus' => $thesaurus,
|
||||
];
|
||||
|
||||
return $app['twig']->render('prod/actions/edit_default.html.twig', $params);
|
||||
});
|
||||
|
||||
$controllers->get('/vocabulary/{vocabulary}/', function (Application $app, Request $request, $vocabulary) {
|
||||
$datas = ['success' => false, 'message' => '', 'results' => []];
|
||||
|
||||
$sbas_id = (int) $request->query->get('sbas_id');
|
||||
|
||||
try {
|
||||
if ($sbas_id === 0) {
|
||||
throw new \Exception('Invalid sbas_id');
|
||||
}
|
||||
|
||||
$VC = VocabularyController::get($app, $vocabulary);
|
||||
$databox = $app['phraseanet.appbox']->get_databox($sbas_id);
|
||||
} catch (\Exception $e) {
|
||||
$datas['message'] = $app->trans('Vocabulary not found');
|
||||
|
||||
return $app->json($datas);
|
||||
}
|
||||
|
||||
$query = $request->query->get('query');
|
||||
|
||||
$results = $VC->find($query, $app['authentication']->getUser(), $databox);
|
||||
|
||||
$list = [];
|
||||
|
||||
foreach ($results as $Term) {
|
||||
/* @var $Term \Alchemy\Phrasea\Vocabulary\Term */
|
||||
$list[] = [
|
||||
'id' => $Term->getId(),
|
||||
'context' => $Term->getContext(),
|
||||
'value' => $Term->getValue(),
|
||||
];
|
||||
}
|
||||
|
||||
$datas['success'] = true;
|
||||
$datas['results'] = $list;
|
||||
|
||||
return $app->json($datas);
|
||||
});
|
||||
|
||||
$controllers->post('/apply/', function (Application $app, Request $request) {
|
||||
|
||||
$records = RecordsRequest::fromRequest($app, $request, RecordsRequest::FLATTEN_YES_PRESERVE_STORIES, ['canmodifrecord']);
|
||||
|
||||
if (count($records->databoxes()) !== 1) {
|
||||
throw new \Exception('Unable to edit on multiple databoxes');
|
||||
}
|
||||
|
||||
if ($request->request->get('act_option') == 'SAVEGRP'
|
||||
&& $request->request->get('newrepresent')
|
||||
&& $records->isSingleStory()) {
|
||||
try {
|
||||
$reg_record = $records->singleStory();
|
||||
|
||||
$newsubdef_reg = new \record_adapter($app, $reg_record->get_sbas_id(), $request->request->get('newrepresent'));
|
||||
|
||||
foreach ($newsubdef_reg->get_subdefs() as $name => $value) {
|
||||
if (!in_array($name, ['thumbnail', 'preview'])) {
|
||||
continue;
|
||||
}
|
||||
if ($value->get_type() !== \media_subdef::TYPE_IMAGE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$media = $app['mediavorus']->guess($value->get_pathfile());
|
||||
$app['subdef.substituer']->substitute($reg_record, $name, $media);
|
||||
$app['dispatcher']->dispatch(PhraseaEvents::RECORD_EDIT, new RecordEdit($reg_record));
|
||||
$app['phraseanet.logger']($reg_record->get_databox())->log(
|
||||
$reg_record,
|
||||
\Session_Logger::EVENT_SUBSTITUTE,
|
||||
$name == 'document' ? 'HD' : $name,
|
||||
''
|
||||
);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_array($request->request->get('mds'))) {
|
||||
return $app->json(['message' => '', 'error' => false]);
|
||||
}
|
||||
|
||||
$databoxes = $records->databoxes();
|
||||
$databox = array_pop($databoxes);
|
||||
|
||||
$elements = $records->toArray();
|
||||
|
||||
foreach ($request->request->get('mds') as $rec) {
|
||||
try {
|
||||
$record = $databox->get_record($rec['record_id']);
|
||||
} catch (\Exception $e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$key = $record->get_serialize_key();
|
||||
|
||||
if (!array_key_exists($key, $elements)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$statbits = $rec['status'];
|
||||
$editDirty = $rec['edit'];
|
||||
|
||||
if ($editDirty == '0') {
|
||||
$editDirty = false;
|
||||
} else {
|
||||
$editDirty = true;
|
||||
}
|
||||
|
||||
if (isset($rec['metadatas']) && is_array($rec['metadatas'])) {
|
||||
$record->set_metadatas($rec['metadatas']);
|
||||
$app['dispatcher']->dispatch(PhraseaEvents::RECORD_EDIT, new RecordEdit($record));
|
||||
}
|
||||
|
||||
$newstat = $record->get_status();
|
||||
$statbits = ltrim($statbits, 'x');
|
||||
if (!in_array($statbits, ['', 'null'])) {
|
||||
$mask_and = ltrim(str_replace(['x', '0', '1', 'z'], ['1', 'z', '0', '1'], $statbits), '0');
|
||||
if ($mask_and != '') {
|
||||
$newstat = \databox_status::operation_and_not($newstat, $mask_and);
|
||||
}
|
||||
|
||||
$mask_or = ltrim(str_replace('x', '0', $statbits), '0');
|
||||
|
||||
if ($mask_or != '') {
|
||||
$newstat = \databox_status::operation_or($newstat, $mask_or);
|
||||
}
|
||||
|
||||
$record->set_binary_status($newstat);
|
||||
}
|
||||
|
||||
$record
|
||||
->write_metas()
|
||||
->get_collection()
|
||||
->reset_stamp($record->get_record_id());
|
||||
|
||||
if ($statbits != '') {
|
||||
$app['phraseanet.logger']($record->get_databox())
|
||||
->log($record, \Session_Logger::EVENT_STATUS, '', '');
|
||||
}
|
||||
if ($editDirty) {
|
||||
$app['phraseanet.logger']($record->get_databox())
|
||||
->log($record, \Session_Logger::EVENT_EDIT, '', '');
|
||||
}
|
||||
}
|
||||
|
||||
return $app->json(['success' => true]);
|
||||
});
|
||||
$controllers->post('/apply/', 'controller.prod.edit:applyAction');
|
||||
|
||||
return $controllers;
|
||||
}
|
||||
|
@@ -11,30 +11,44 @@
|
||||
|
||||
namespace Alchemy\Phrasea\ControllerProvider\Prod;
|
||||
|
||||
use Alchemy\Phrasea\Application as PhraseaApplication;
|
||||
use Alchemy\Phrasea\Controller\Prod\ExportController;
|
||||
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
|
||||
use Alchemy\Phrasea\Core\Event\ExportFailureEvent;
|
||||
use Alchemy\Phrasea\Core\PhraseaEvents;
|
||||
use Silex\Application;
|
||||
use Silex\ControllerProviderInterface;
|
||||
use Alchemy\Phrasea\Exception\InvalidArgumentException;
|
||||
use Alchemy\Phrasea\Notification\Emitter;
|
||||
use Alchemy\Phrasea\Notification\Receiver;
|
||||
use Alchemy\Phrasea\Notification\Mail\MailRecordsExport;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Silex\ServiceProviderInterface;
|
||||
|
||||
class Export implements ControllerProviderInterface
|
||||
class Export implements ControllerProviderInterface, ServiceProviderInterface
|
||||
{
|
||||
use ControllerProviderTrait;
|
||||
|
||||
public function register(Application $app)
|
||||
{
|
||||
$app['controller.prod.export'] = $app->share(function (PhraseaApplication $app) {
|
||||
return (new ExportController($app))
|
||||
->setDispatcherLocator(function () use ($app) {
|
||||
return $app['dispatcher'];
|
||||
})
|
||||
->setFileSystemLocator(function () use ($app) {
|
||||
return $app['filesystem'];
|
||||
})
|
||||
->setDelivererLocator(function () use ($app) {
|
||||
return $app['notification.deliverer'];
|
||||
})
|
||||
;
|
||||
});
|
||||
}
|
||||
|
||||
public function boot(Application $app)
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function connect(Application $app)
|
||||
{
|
||||
$app['controller.prod.export'] = $this;
|
||||
|
||||
$controllers = $this->createAuthenticatedCollection($app);
|
||||
|
||||
$controllers->post('/multi-export/', 'controller.prod.export:displayMultiExport')
|
||||
@@ -51,207 +65,4 @@ class Export implements ControllerProviderInterface
|
||||
|
||||
return $controllers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display form to export documents
|
||||
*
|
||||
* @param Application $app
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
*/
|
||||
public function displayMultiExport(Application $app, Request $request)
|
||||
{
|
||||
$download = new \set_export(
|
||||
$app,
|
||||
$request->request->get('lst', ''),
|
||||
$request->request->get('ssel', ''),
|
||||
$request->request->get('story')
|
||||
);
|
||||
|
||||
return new Response($app['twig']->render('common/dialog_export.html.twig', [
|
||||
'download' => $download,
|
||||
'ssttid' => $request->request->get('ssel'),
|
||||
'lst' => $download->serialize_list(),
|
||||
'default_export_title' => $app['conf']->get(['registry', 'actions', 'default-export-title']),
|
||||
'choose_export_title' => $app['conf']->get(['registry', 'actions', 'export-title-choice'])
|
||||
]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test a FTP connexion
|
||||
*
|
||||
* @param Application $app
|
||||
* @param Request $request
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function testFtpConnexion(Application $app, Request $request)
|
||||
{
|
||||
if (!$request->isXmlHttpRequest()) {
|
||||
$app->abort(400);
|
||||
}
|
||||
|
||||
$success = false;
|
||||
$msg = _('Error while connecting to FTP');
|
||||
|
||||
try {
|
||||
$ftpClient = $app['phraseanet.ftp.client']($request->request->get('address', ''), 21, 90, !!$request->request->get('ssl'));
|
||||
$ftpClient->login($request->request->get('login', 'anonymous'), $request->request->get('password', 'anonymous'));
|
||||
$ftpClient->close();
|
||||
$msg = $app->trans('Connection to FTP succeed');
|
||||
$success = true;
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
|
||||
return $app->json([
|
||||
'success' => $success,
|
||||
'message' => $msg
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param Application $app
|
||||
* @param Request $request
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function exportFtp(Application $app, Request $request)
|
||||
{
|
||||
$download = new \set_exportftp($app, $request->request->get('lst'), $request->request->get('ssttid'));
|
||||
|
||||
$mandatoryParameters = ['address', 'login', 'obj'];
|
||||
|
||||
foreach ($mandatoryParameters as $parameter) {
|
||||
if (!$request->request->get($parameter)) {
|
||||
$app->abort(400, sprintf('required parameter `%s` is missing', $parameter));
|
||||
}
|
||||
}
|
||||
|
||||
if (count($download->get_display_ftp()) == 0) {
|
||||
return $app->json([
|
||||
'success' => false,
|
||||
'message' => $app->trans("You do not have required rights to send these documents over FTP")
|
||||
]);
|
||||
}
|
||||
|
||||
try {
|
||||
$download->prepare_export(
|
||||
$app['authentication']->getUser(),
|
||||
$app['filesystem'],
|
||||
$request->request->get('obj'),
|
||||
false,
|
||||
$request->request->get('businessfields')
|
||||
);
|
||||
|
||||
$download->export_ftp(
|
||||
$request->request->get('user_dest'),
|
||||
$request->request->get('address'),
|
||||
$request->request->get('login'),
|
||||
$request->request->get('password', ''),
|
||||
$request->request->get('ssl'),
|
||||
$request->request->get('max_retry'),
|
||||
$request->request->get('passive'),
|
||||
$request->request->get('dest_folder'),
|
||||
$request->request->get('prefix_folder'),
|
||||
$request->request->get('logfile')
|
||||
);
|
||||
|
||||
return $app->json([
|
||||
'success' => true,
|
||||
'message' => $app->trans('Export saved in the waiting queue')
|
||||
]);
|
||||
} catch (\Exception $e) {
|
||||
return $app->json([
|
||||
'success' => false,
|
||||
'message' => $app->trans('Something went wrong')
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Export document by mail
|
||||
*
|
||||
* @param Application $app
|
||||
* @param Request $request
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function exportMail(Application $app, Request $request)
|
||||
{
|
||||
set_time_limit(0);
|
||||
session_write_close();
|
||||
ignore_user_abort(true);
|
||||
|
||||
$lst = $request->request->get('lst', '');
|
||||
$ssttid = $request->request->get('ssttid', '');
|
||||
|
||||
//prepare export
|
||||
$download = new \set_export($app, $lst, $ssttid);
|
||||
$list = $download->prepare_export(
|
||||
$app['authentication']->getUser(),
|
||||
$app['filesystem'],
|
||||
(array) $request->request->get('obj'),
|
||||
$request->request->get("type") == "title" ? : false,
|
||||
$request->request->get('businessfields')
|
||||
);
|
||||
|
||||
$separator = preg_split('//', ' ;,', -1, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
|
||||
$separator = '/\\' . implode('|\\', $separator) . '/';
|
||||
|
||||
$list['export_name'] = sprintf("%s.zip", $download->getExportName());
|
||||
$list['email'] = implode(';', preg_split($separator, $request->request->get("destmail", "")));
|
||||
|
||||
$destMails = [];
|
||||
//get destination mails
|
||||
foreach (explode(";", $list['email']) as $mail) {
|
||||
if (filter_var($mail, FILTER_VALIDATE_EMAIL)) {
|
||||
$destMails[] = $mail;
|
||||
} else {
|
||||
$app['dispatcher']->dispatch(PhraseaEvents::EXPORT_MAIL_FAILURE, new ExportFailureEvent($app['authentication']->getUser()->getId(), $ssttid, $lst, \eventsmanager_notify_downloadmailfail::MAIL_NO_VALID, $mail));
|
||||
}
|
||||
}
|
||||
|
||||
$token = $app['manipulator.token']->createEmailExportToken(serialize($list));
|
||||
|
||||
if (count($destMails) > 0) {
|
||||
//zip documents
|
||||
\set_export::build_zip(
|
||||
$app,
|
||||
$token,
|
||||
$list,
|
||||
$app['tmp.download.path'].'/'. $token->getValue() . '.zip'
|
||||
);
|
||||
|
||||
$remaingEmails = $destMails;
|
||||
|
||||
$url = $app->url('prepare_download', ['token' => $token->getValue(), 'anonymous' => false, 'type' => \Session_Logger::EVENT_EXPORTMAIL]);
|
||||
|
||||
$emitter = new Emitter($app['authentication']->getUser()->getDisplayName(), $app['authentication']->getUser()->getEmail());
|
||||
|
||||
foreach ($destMails as $key => $mail) {
|
||||
try {
|
||||
$receiver = new Receiver(null, trim($mail));
|
||||
} catch (InvalidArgumentException $e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$mail = MailRecordsExport::create($app, $receiver, $emitter, $request->request->get('textmail'));
|
||||
$mail->setButtonUrl($url);
|
||||
$mail->setExpiration($token->getExpiration());
|
||||
|
||||
$app['notification.deliverer']->deliver($mail, !!$request->request->get('reading_confirm', false));
|
||||
unset($remaingEmails[$key]);
|
||||
}
|
||||
|
||||
//some mails failed
|
||||
if (count($remaingEmails) > 0) {
|
||||
foreach ($remaingEmails as $mail) {
|
||||
$app['dispatcher']->dispatch(PhraseaEvents::EXPORT_MAIL_FAILURE, new ExportFailureEvent($app['authentication']->getUser()->getId(), $ssttid, $lst, \eventsmanager_notify_downloadmailfail::MAIL_FAIL, $mail));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $app->json([
|
||||
'success' => true,
|
||||
'message' => ''
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@@ -425,7 +425,7 @@ class Lazaret implements ControllerProviderInterface
|
||||
$lazaretThumbFileName = $app['tmp.lazaret.path'].'/'.$lazaretFile->getThumbFilename();
|
||||
|
||||
try {
|
||||
$media = $app['mediavorus']->guess($lazaretFileName);
|
||||
$media = $app->getMediaFromUri($lazaretFileName);
|
||||
|
||||
$record = $lazaretFile->getCollection($app)->get_databox()->get_record($recordId);
|
||||
$app['subdef.substituer']->substitute($record, 'document', $media);
|
||||
|
@@ -93,7 +93,7 @@ class Push implements ControllerProviderInterface
|
||||
if ($value->getVocabularyType()->getType() !== 'User')
|
||||
continue;
|
||||
|
||||
$user = $value->getRessource();
|
||||
$user = $value->getResource();
|
||||
|
||||
$Users->set($user->getId(), $user);
|
||||
}
|
||||
|
@@ -142,7 +142,7 @@ class Tools implements ControllerProviderInterface
|
||||
$request->get('record_id')
|
||||
);
|
||||
|
||||
$media = $app['mediavorus']->guess($tempoFile);
|
||||
$media = $app->getMediaFromUri($tempoFile);
|
||||
|
||||
$app['subdef.substituer']->substitute($record, 'document', $media);
|
||||
$record->insertTechnicalDatas($app['mediavorus']);
|
||||
@@ -202,7 +202,7 @@ class Tools implements ControllerProviderInterface
|
||||
$request->get('record_id')
|
||||
);
|
||||
|
||||
$media = $app['mediavorus']->guess($tempoFile);
|
||||
$media = $app->getMediaFromUri($tempoFile);
|
||||
|
||||
$app['subdef.substituer']->substitute($record, 'thumbnail', $media);
|
||||
$app['phraseanet.logger']($record->get_databox())->log(
|
||||
@@ -265,7 +265,7 @@ class Tools implements ControllerProviderInterface
|
||||
|
||||
file_put_contents($fileName, $dataUri->getData());
|
||||
|
||||
$media = $app['mediavorus']->guess($fileName);
|
||||
$media = $app->getMediaFromUri($fileName);
|
||||
|
||||
$app['subdef.substituer']->substitute($record, 'thumbnail', $media);
|
||||
$app['phraseanet.logger']($record->get_databox())->log(
|
||||
|
@@ -172,7 +172,7 @@ class Upload implements ControllerProviderInterface
|
||||
|
||||
$app['filesystem']->rename($uploadedFilename, $renamedFilename);
|
||||
|
||||
$media = $app['mediavorus']->guess($renamedFilename);
|
||||
$media = $app->getMediaFromUri($renamedFilename);
|
||||
$collection = \collection::get_from_base_id($app, $base_id);
|
||||
|
||||
$lazaretSession = new LazaretSession();
|
||||
@@ -233,7 +233,7 @@ class Upload implements ControllerProviderInterface
|
||||
|
||||
$fileName = $app['temporary-filesystem']->createTemporaryFile('base_64_thumb', null, "png");
|
||||
file_put_contents($fileName, $dataUri->getData());
|
||||
$media = $app['mediavorus']->guess($fileName);
|
||||
$media = $app->getMediaFromUri($fileName);
|
||||
$app['subdef.substituer']->substitute($elementCreated, 'thumbnail', $media);
|
||||
$app['phraseanet.logger']($elementCreated->get_databox())->log(
|
||||
$elementCreated,
|
||||
|
@@ -13,6 +13,7 @@ namespace Alchemy\Phrasea\ControllerProvider\Root;
|
||||
|
||||
use Alchemy\Geonames\Exception\ExceptionInterface as GeonamesExceptionInterface;
|
||||
use Alchemy\Phrasea\Application as PhraseaApplication;
|
||||
use Alchemy\Phrasea\Application\Helper\NotifierAware;
|
||||
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
|
||||
use Alchemy\Phrasea\ControllerProvider\Root\Login;
|
||||
use Alchemy\Phrasea\Exception\InvalidArgumentException;
|
||||
@@ -31,10 +32,14 @@ use Symfony\Component\HttpFoundation\Response;
|
||||
class Account implements ControllerProviderInterface
|
||||
{
|
||||
use ControllerProviderTrait;
|
||||
use NotifierAware;
|
||||
|
||||
public function connect(Application $app)
|
||||
{
|
||||
$app['account.controller'] = $this;
|
||||
$app['account.controller'] = $this
|
||||
->setDelivererLocator(function () use ($app) {
|
||||
return $app['notification.deliverer'];
|
||||
});
|
||||
|
||||
$controllers = $this->createAuthenticatedCollection($app);
|
||||
|
||||
@@ -156,7 +161,7 @@ class Account implements ControllerProviderInterface
|
||||
$mail->setButtonUrl($url);
|
||||
$mail->setExpiration($token->getExpiration());
|
||||
|
||||
$app['notification.deliverer']->deliver($mail);
|
||||
$this->deliver($mail);
|
||||
|
||||
$app->addFlash('info', $app->trans('admin::compte-utilisateur un email de confirmation vient de vous etre envoye. Veuillez suivre les instructions contenue pour continuer'));
|
||||
|
||||
|
@@ -12,6 +12,7 @@
|
||||
namespace Alchemy\Phrasea\ControllerProvider\Root;
|
||||
|
||||
use Alchemy\Phrasea\Application as PhraseaApplication;
|
||||
use Alchemy\Phrasea\Application\Helper\NotifierAware;
|
||||
use Alchemy\Phrasea\Authentication\Exception\NotAuthenticatedException;
|
||||
use Alchemy\Phrasea\Authentication\Exception\AuthenticationException;
|
||||
use Alchemy\Phrasea\Authentication\Context;
|
||||
@@ -52,6 +53,8 @@ use Symfony\Component\Form\FormInterface;
|
||||
|
||||
class Login implements ControllerProviderInterface
|
||||
{
|
||||
use NotifierAware;
|
||||
|
||||
public static function getDefaultTemplateVariables(Application $app)
|
||||
{
|
||||
$items = [];
|
||||
@@ -95,7 +98,10 @@ class Login implements ControllerProviderInterface
|
||||
{
|
||||
$controllers = $app['controllers_factory'];
|
||||
|
||||
$app['login.controller'] = $this;
|
||||
$app['login.controller'] = $this
|
||||
->setDelivererLocator(function () use ($app) {
|
||||
return $app['notification.deliverer'];
|
||||
});
|
||||
|
||||
$controllers->before(function (Request $request) use ($app) {
|
||||
if ($request->getPathInfo() == $app->path('homepage')) {
|
||||
@@ -497,7 +503,7 @@ class Login implements ControllerProviderInterface
|
||||
$mail->setButtonUrl($app->url('login_register_confirm', ['code' => $token->getValue()]));
|
||||
$mail->setExpiration($token->getExpiration());
|
||||
|
||||
$app['notification.deliverer']->deliver($mail);
|
||||
$this->deliver($mail);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -544,12 +550,12 @@ class Login implements ControllerProviderInterface
|
||||
|
||||
if (count($app['acl']->get($user)->get_granted_base()) > 0) {
|
||||
$mail = MailSuccessEmailConfirmationRegistered::create($app, $receiver);
|
||||
$app['notification.deliverer']->deliver($mail);
|
||||
$this->deliver($mail);
|
||||
|
||||
$app->addFlash('success', $app->trans('Account has been unlocked, you can now login.'));
|
||||
} else {
|
||||
$mail = MailSuccessEmailConfirmationUnregistered::create($app, $receiver);
|
||||
$app['notification.deliverer']->deliver($mail);
|
||||
$this->deliver($mail);
|
||||
|
||||
$app->addFlash('info', $app->trans('Account has been unlocked, you still have to wait for admin approval.'));
|
||||
}
|
||||
@@ -626,7 +632,7 @@ class Login implements ControllerProviderInterface
|
||||
$mail->setButtonUrl($url);
|
||||
$mail->setExpiration($expirationDate);
|
||||
|
||||
$app['notification.deliverer']->deliver($mail);
|
||||
$this->deliver($mail);
|
||||
$app->addFlash('info', $app->trans('phraseanet:: Un email vient de vous etre envoye'));
|
||||
|
||||
return $app->redirectPath('login_forgot_password');
|
||||
|
@@ -12,16 +12,22 @@
|
||||
namespace Alchemy\Phrasea\Core\Event\Subscriber;
|
||||
|
||||
use Alchemy\Phrasea\Application;
|
||||
use Alchemy\Phrasea\Application\Helper\NotifierAware;
|
||||
use Alchemy\Phrasea\Model\Entities\User;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
|
||||
abstract class AbstractNotificationSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
use NotifierAware;
|
||||
|
||||
protected $app;
|
||||
|
||||
public function __construct(Application $app)
|
||||
{
|
||||
$this->app = $app;
|
||||
$this->setDelivererLocator(function () use ($app) {
|
||||
return $app['notification.deliverer'];
|
||||
});
|
||||
}
|
||||
|
||||
protected function shouldSendNotificationFor(User $user, $type)
|
||||
|
@@ -45,7 +45,7 @@ class BasketSubscriber extends AbstractNotificationSubscriber
|
||||
$mail->setBasket($basket);
|
||||
$mail->setPusher($user_from);
|
||||
|
||||
$this->app['notification.deliverer']->deliver($mail, $event->hasReceipt());
|
||||
$this->deliver($mail, $event->hasReceipt());
|
||||
|
||||
$mailed = true;
|
||||
}
|
||||
|
@@ -46,7 +46,7 @@ class BridgeSubscriber extends AbstractNotificationSubscriber
|
||||
$mail = MailInfoBridgeUploadFailed::create($this->app, $receiver);
|
||||
$mail->setAdapter($account->get_api()->get_connector()->get_name());
|
||||
$mail->setReason($params['reason']);
|
||||
$this->app['notification.deliverer']->deliver($mail);
|
||||
$this->deliver($mail);
|
||||
$mailed = true;
|
||||
}
|
||||
}
|
||||
|
@@ -74,7 +74,7 @@ class FeedEntrySubscriber extends AbstractNotificationSubscriber
|
||||
$mail->setAuthor($entry->getAuthorName());
|
||||
$mail->setTitle($entry->getTitle());
|
||||
|
||||
$this->app['notification.deliverer']->deliver($mail);
|
||||
$this->deliver($mail);
|
||||
$mailed = true;
|
||||
}
|
||||
}
|
||||
|
@@ -63,7 +63,7 @@ class LazaretSubscriber extends AbstractNotificationSubscriber
|
||||
|
||||
if ($readyToSend) {
|
||||
$mail = MailInfoRecordQuarantined::create($this->app, $receiver);
|
||||
$this->app['notification.deliverer']->deliver($mail);
|
||||
$this->deliver($mail);
|
||||
$mailed = true;
|
||||
}
|
||||
}
|
||||
|
@@ -60,7 +60,7 @@ class OrderSubscriber extends AbstractNotificationSubscriber
|
||||
$mail = MailInfoNewOrder::create($this->app, $receiver);
|
||||
$mail->setUser($orderInitiator);
|
||||
|
||||
$this->app['notification.deliverer']->deliver($mail);
|
||||
$this->deliver($mail);
|
||||
$mailed = true;
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ class OrderSubscriber extends AbstractNotificationSubscriber
|
||||
$mail->setBasket($basket);
|
||||
$mail->setDeliverer($user_from);
|
||||
|
||||
$this->app['notification.deliverer']->deliver($mail);
|
||||
$this->deliver($mail);
|
||||
$mailed = true;
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ class OrderSubscriber extends AbstractNotificationSubscriber
|
||||
$mail->setQuantity($params['n']);
|
||||
$mail->setDeliverer($user_from);
|
||||
|
||||
$this->app['notification.deliverer']->deliver($mail);
|
||||
$this->deliver($mail);
|
||||
|
||||
$mailed = true;
|
||||
}
|
||||
|
@@ -57,7 +57,7 @@ class RegistrationSubscriber extends AbstractNotificationSubscriber
|
||||
$mail = MailInfoUserRegistered::create($this->app, $receiver);
|
||||
$mail->setRegisteredUser($registeredUser);
|
||||
|
||||
$this->app['notification.deliverer']->deliver($mail);
|
||||
$this->deliver($mail);
|
||||
|
||||
$mailed = true;
|
||||
}
|
||||
@@ -122,7 +122,7 @@ class RegistrationSubscriber extends AbstractNotificationSubscriber
|
||||
|
||||
if ($readyToSend) {
|
||||
$mail = MailInfoSomebodyAutoregistered::create($this->app, $receiver, null, $body);
|
||||
$this->app['notification.deliverer']->deliver($mail);
|
||||
$this->deliver($mail);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@@ -57,7 +57,7 @@ class ValidationSubscriber extends AbstractNotificationSubscriber
|
||||
$mail->setTitle($title);
|
||||
$mail->setUser($user_from);
|
||||
|
||||
$this->app['notification.deliverer']->deliver($mail, $event->hasReceipt());
|
||||
$this->deliver($mail, $event->hasReceipt());
|
||||
$mailed = true;
|
||||
}
|
||||
}
|
||||
@@ -100,7 +100,7 @@ class ValidationSubscriber extends AbstractNotificationSubscriber
|
||||
$mail->setTitle($title);
|
||||
$mail->setUser($user_from);
|
||||
|
||||
$this->app['notification.deliverer']->deliver($mail);
|
||||
$this->deliver($mail);
|
||||
$mailed = true;
|
||||
}
|
||||
}
|
||||
@@ -143,7 +143,7 @@ class ValidationSubscriber extends AbstractNotificationSubscriber
|
||||
$mail->setButtonUrl($params['url']);
|
||||
$mail->setTitle($title);
|
||||
|
||||
$this->app['notification.deliverer']->deliver($mail);
|
||||
$this->deliver($mail);
|
||||
$mailed = true;
|
||||
}
|
||||
}
|
||||
|
@@ -74,14 +74,17 @@ class TasksServiceProvider implements ServiceProviderInterface
|
||||
$logger = isset($app['task-manager.logger']) ? $app['task-manager.logger'] : $app['monolog'];
|
||||
|
||||
return [
|
||||
new FtpJob($app['dispatcher'], $logger, $app['translator']),
|
||||
new ArchiveJob($app['dispatcher'], $logger, $app['translator']),
|
||||
new BridgeJob($app['dispatcher'], $logger, $app['translator']),
|
||||
new FtpPullJob($app['dispatcher'], $logger, $app['translator']),
|
||||
new RecordMoverJob($app['dispatcher'], $logger, $app['translator']),
|
||||
new SubdefsJob($app['dispatcher'], $logger, $app['translator']),
|
||||
new WriteMetadataJob($app['dispatcher'], $logger, $app['translator']),
|
||||
new WebhookJob($app['dispatcher'], $logger, $app['translator']),
|
||||
(new FtpJob($app['translator'], $app['dispatcher'], $logger))
|
||||
->setDelivererLocator(function () use ($app) {
|
||||
return $app['notification.deliverer'];
|
||||
}),
|
||||
new ArchiveJob($app['translator'], $app['dispatcher'], $logger),
|
||||
new BridgeJob($app['translator'], $app['dispatcher'], $logger),
|
||||
new FtpPullJob($app['translator'], $app['dispatcher'], $logger),
|
||||
new RecordMoverJob($app['translator'], $app['dispatcher'], $logger),
|
||||
new SubdefsJob($app['translator'], $app['dispatcher'], $logger),
|
||||
new WriteMetadataJob($app['translator'], $app['dispatcher'], $logger),
|
||||
new WebhookJob($app['translator'], $app['dispatcher'], $logger),
|
||||
];
|
||||
});
|
||||
}
|
||||
|
@@ -16,16 +16,10 @@ use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class Helper
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var Application
|
||||
*/
|
||||
/** @var Application */
|
||||
protected $app;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var \Symfony\Component\HttpFoundation\Request
|
||||
*/
|
||||
/** @var Request */
|
||||
protected $request;
|
||||
|
||||
/**
|
||||
@@ -43,10 +37,7 @@ class Helper
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return \Symfony\Component\HttpFoundation\Request
|
||||
*/
|
||||
/** @return Request */
|
||||
public function getRequest()
|
||||
{
|
||||
return $this->request;
|
||||
|
@@ -12,6 +12,7 @@
|
||||
namespace Alchemy\Phrasea\Helper\User;
|
||||
|
||||
use Alchemy\Phrasea\Application;
|
||||
use Alchemy\Phrasea\Application\Helper\NotifierAware;
|
||||
use Alchemy\Phrasea\Exception\InvalidArgumentException;
|
||||
use Alchemy\Phrasea\Model\Entities\User;
|
||||
use Alchemy\Phrasea\Notification\Mail\MailSuccessEmailUpdate;
|
||||
@@ -23,27 +24,23 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
class Edit extends \Alchemy\Phrasea\Helper\Helper
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
use NotifierAware;
|
||||
|
||||
/** @var array */
|
||||
protected $users = [];
|
||||
|
||||
/**
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
/** @var array */
|
||||
protected $users_datas;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
/** @var int */
|
||||
protected $base_id;
|
||||
|
||||
public function __construct(Application $app, Request $Request)
|
||||
{
|
||||
parent::__construct($app, $Request);
|
||||
$this->setDelivererLocator(function () use ($app) {
|
||||
return $app['notification.deliverer'];
|
||||
});
|
||||
|
||||
$this->users = explode(';', $Request->get('users'));
|
||||
|
||||
@@ -663,7 +660,7 @@ class Edit extends \Alchemy\Phrasea\Helper\Helper
|
||||
|
||||
if ($oldReceiver) {
|
||||
$mailOldAddress = MailSuccessEmailUpdate::create($this->app, $oldReceiver, null, $this->app->trans('You will now receive notifications at %new_email%', ['%new_email%' => $new_email]));
|
||||
$this->app['notification.deliverer']->deliver($mailOldAddress);
|
||||
$this->deliver($mailOldAddress);
|
||||
}
|
||||
|
||||
try {
|
||||
@@ -674,7 +671,7 @@ class Edit extends \Alchemy\Phrasea\Helper\Helper
|
||||
|
||||
if ($newReceiver) {
|
||||
$mailNewAddress = MailSuccessEmailUpdate::create($this->app, $newReceiver, null, $this->app->trans('You will no longer receive notifications at %old_email%', ['%old_email%' => $old_email]));
|
||||
$this->app['notification.deliverer']->deliver($mailNewAddress);
|
||||
$this->deliver($mailNewAddress);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -11,33 +11,38 @@
|
||||
|
||||
namespace Alchemy\Phrasea\Helper\User;
|
||||
|
||||
use Alchemy\Phrasea\Application;
|
||||
use Alchemy\Phrasea\Application\Helper\NotifierAware;
|
||||
use Alchemy\Phrasea\Exception\InvalidArgumentException;
|
||||
use Alchemy\Phrasea\Helper\Helper;
|
||||
use Alchemy\Phrasea\Notification\Receiver;
|
||||
use Alchemy\Phrasea\Notification\Mail\MailRequestPasswordSetup;
|
||||
use Alchemy\Phrasea\Notification\Mail\MailRequestEmailConfirmation;
|
||||
use Alchemy\Phrasea\Model\Entities\User;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class Manage extends Helper
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
use NotifierAware;
|
||||
|
||||
/** @var array */
|
||||
protected $results;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
/** @var array */
|
||||
protected $query_parms;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
/** @var int */
|
||||
protected $usr_id;
|
||||
|
||||
public function __construct(Application $app, Request $Request)
|
||||
{
|
||||
parent::__construct($app, $Request);
|
||||
|
||||
$this->setDelivererLocator(function () use ($app) {
|
||||
return $app['notification.deliverer'];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return User[]
|
||||
*/
|
||||
@@ -167,7 +172,7 @@ class Manage extends Helper
|
||||
$url = $this->app->url('login_renew_password', ['token' => $urlToken->getValue()]);
|
||||
$mail = MailRequestPasswordSetup::create($this->app, $receiver, null, '', $url);
|
||||
$mail->setLogin($createdUser->getLogin());
|
||||
$this->app['notification.deliverer']->deliver($mail);
|
||||
$this->deliver($mail);
|
||||
}
|
||||
|
||||
if ($validateMail && $receiver) {
|
||||
@@ -177,7 +182,7 @@ class Manage extends Helper
|
||||
$url = $this->app->url('login_register_confirm', ['code' => $token]);
|
||||
|
||||
$mail = MailRequestEmailConfirmation::create($this->app, $receiver, null, '', $url, $token->getExpiration());
|
||||
$this->app['notification.deliverer']->deliver($mail);
|
||||
$this->deliver($mail);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -76,7 +76,7 @@ class TaskManipulator implements ManipulatorInterface
|
||||
*/
|
||||
public function createEmptyCollectionJob(\collection $collection)
|
||||
{
|
||||
$job = new EmptyCollectionJob(null, null, $this->translator);
|
||||
$job = new EmptyCollectionJob($this->translator);
|
||||
$settings = simplexml_load_string($job->getEditor()->getDefaultSettings());
|
||||
$settings->bas_id = $collection->get_base_id();
|
||||
|
||||
|
@@ -38,7 +38,7 @@ class RecordMoverEditor extends AbstractEditor
|
||||
public function facility(Application $app, Request $request)
|
||||
{
|
||||
$ret = ['tasks' => []];
|
||||
$job = new RecordMoverJob(null, null, $this->translator);
|
||||
$job = new RecordMoverJob($this->translator);
|
||||
switch ($request->get('ACT')) {
|
||||
case 'CALCTEST':
|
||||
$sxml = simplexml_load_string($request->get('xml'));
|
||||
|
@@ -24,7 +24,11 @@ abstract class AbstractJob extends AbstractTMJob implements JobInterface
|
||||
protected $period = 0.05;
|
||||
protected $translator;
|
||||
|
||||
public function __construct(EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null, TranslatorInterface $translator)
|
||||
public function __construct(
|
||||
TranslatorInterface $translator,
|
||||
EventDispatcherInterface $dispatcher = null,
|
||||
LoggerInterface $logger = null
|
||||
)
|
||||
{
|
||||
parent::__construct($dispatcher, $logger);
|
||||
$this->translator = $translator;
|
||||
|
@@ -987,7 +987,7 @@ class ArchiveJob extends AbstractJob
|
||||
{
|
||||
$status = \databox_status::operation_or($stat0, $stat1);
|
||||
|
||||
$media = $app['mediavorus']->guess($pathfile);
|
||||
$media = $app->getMediaFromUri($pathfile);
|
||||
|
||||
$databox = $collection->get_databox();
|
||||
$metadatasStructure = $databox->get_meta_structure();
|
||||
@@ -1035,7 +1035,7 @@ class ArchiveJob extends AbstractJob
|
||||
{
|
||||
$status = \databox_status::operation_or($stat0, $stat1);
|
||||
|
||||
$media = $app['mediavorus']->guess($pathfile);
|
||||
$media = $app->getMediaFromUri($pathfile);
|
||||
|
||||
$databox = $collection->get_databox();
|
||||
$metadatasStructure = $databox->get_meta_structure();
|
||||
|
@@ -47,6 +47,6 @@ class Factory
|
||||
throw new InvalidArgumentException(sprintf('Class `%s` does not implement JobInterface.', $fqn));
|
||||
}
|
||||
|
||||
return new $fqn($this->dispatcher, $this->logger, $this->translator);
|
||||
return new $fqn($this->translator, $this->dispatcher, $this->logger);
|
||||
}
|
||||
}
|
||||
|
@@ -12,6 +12,7 @@
|
||||
namespace Alchemy\Phrasea\TaskManager\Job;
|
||||
|
||||
use Alchemy\Phrasea\Application;
|
||||
use Alchemy\Phrasea\Application\Helper\NotifierAware;
|
||||
use Alchemy\Phrasea\Model\Serializer\CaptionSerializer;
|
||||
use Alchemy\Phrasea\Notification\Mail\MailSuccessFTPReceiver;
|
||||
use Alchemy\Phrasea\TaskManager\Editor\FtpEditor;
|
||||
@@ -24,6 +25,8 @@ use Alchemy\Phrasea\Model\Entities\Task;
|
||||
|
||||
class FtpJob extends AbstractJob
|
||||
{
|
||||
use NotifierAware;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
@@ -385,7 +388,7 @@ class FtpJob extends AbstractJob
|
||||
$receiver = new Receiver(null, $sendermail);
|
||||
$mail = MailSuccessFTPSender::create($app, $receiver, null, $sender_message);
|
||||
$mail->setServer($ftp_server);
|
||||
$app['notification.deliverer']->deliver($mail);
|
||||
$this->deliver($mail);
|
||||
} catch (InvalidArgumentException $e) {
|
||||
}
|
||||
|
||||
@@ -393,7 +396,7 @@ class FtpJob extends AbstractJob
|
||||
$receiver = new Receiver(null, $export->getMail());
|
||||
$mail = MailSuccessFTPReceiver::create($app, $receiver, null, $receiver_message);
|
||||
$mail->setServer($ftp_server);
|
||||
$app['notification.deliverer']->deliver($mail);
|
||||
$this->deliver($mail);
|
||||
} catch (\Exception $e) {
|
||||
$this->log('debug', sprintf('Unable to deliver success message : %s', $e->getMessage()));
|
||||
}
|
||||
|
@@ -33,9 +33,14 @@ class WebhookJob extends AbstractJob
|
||||
{
|
||||
private $httpClient;
|
||||
|
||||
public function __construct(EventDispatcherInterface $dispatcher = null, LoggerInterface $logger = null, TranslatorInterface $translator, GuzzleClient $httpClient = null)
|
||||
public function __construct(
|
||||
TranslatorInterface $translator,
|
||||
EventDispatcherInterface $dispatcher = null,
|
||||
LoggerInterface $logger = null,
|
||||
GuzzleClient $httpClient = null
|
||||
)
|
||||
{
|
||||
parent::__construct($dispatcher, $logger, $translator);
|
||||
parent::__construct($translator, $dispatcher, $logger);
|
||||
|
||||
$this->httpClient = $httpClient ?: new GuzzleClient();
|
||||
$version = new Version();
|
||||
|
@@ -15,17 +15,16 @@ use Alchemy\Phrasea\Model\Entities\User;
|
||||
|
||||
interface ControlProviderInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @return the type of the ControlProvider
|
||||
*
|
||||
* ControlProvider class should be named like {type}Provider
|
||||
* in the ControlProvider namespace
|
||||
*
|
||||
* @return string the type of the ControlProvider
|
||||
*/
|
||||
public static function getType();
|
||||
|
||||
/**
|
||||
* @return stringa simple i18n word to reprsent this vocabullary
|
||||
* @return string a simple i18n word representing this vocabulary
|
||||
*/
|
||||
public function getName();
|
||||
|
||||
@@ -41,19 +40,19 @@ interface ControlProviderInterface
|
||||
public function getValue($id);
|
||||
|
||||
/**
|
||||
* @return mixed returns the actual ressource corresponding to an id
|
||||
* @return mixed returns the actual resource corresponding to an id
|
||||
* @throws \Exception if the $id is invalid
|
||||
*/
|
||||
public function getRessource($id);
|
||||
public function getResource($id);
|
||||
|
||||
/**
|
||||
* Find matching Term in the vocabulary repository
|
||||
*
|
||||
* @param string $query A scalar quaery
|
||||
* @param string $query A scalar query
|
||||
* @param User $for_user The user doing the query
|
||||
* @param \databox $on_databox The databox where vocabulary should be requested
|
||||
*
|
||||
* @return Doctrine\Common\Collections\ArrayCollection
|
||||
* @return \Doctrine\Common\Collections\Collection
|
||||
*/
|
||||
public function find($query, User $for_user, \databox $on_databox);
|
||||
}
|
||||
|
@@ -106,7 +106,7 @@ class UserProvider implements ControlProviderInterface
|
||||
* @param mixed $id
|
||||
* @return string
|
||||
*/
|
||||
public function getRessource($id)
|
||||
public function getResource($id)
|
||||
{
|
||||
return $this->app['repo.users']->find($id);
|
||||
}
|
||||
|
@@ -66,7 +66,7 @@ class appbox extends base
|
||||
//resize collection logo
|
||||
$imageSpec = new ImageSpecification();
|
||||
|
||||
$media = $this->app['mediavorus']->guess($filename);
|
||||
$media = $this->app->getMediaFromUri($filename);
|
||||
|
||||
if ($media->getWidth() > 120 || $media->getHeight() > 24) {
|
||||
$imageSpec->setResizeMode(ImageSpecification::RESIZE_MODE_INBOUND_FIXEDRATIO);
|
||||
|
@@ -14,40 +14,22 @@ use Alchemy\Phrasea\Vocabulary;
|
||||
|
||||
class caption_Field_Value implements cache_cacheableInterface
|
||||
{
|
||||
/**
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
/** @var int */
|
||||
protected $id;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
/** @var string */
|
||||
protected $value;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var type \Alchemy\Phrasea\Vocabulary\ControlProvider\ControlProviderInterface
|
||||
*/
|
||||
/** @var \Alchemy\Phrasea\Vocabulary\ControlProvider\ControlProviderInterface */
|
||||
protected $VocabularyType;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
/** @var int */
|
||||
protected $VocabularyId;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var databox_field
|
||||
*/
|
||||
/** @var databox_field */
|
||||
protected $databox_field;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var record_adapter
|
||||
*/
|
||||
/** @var record_adapter */
|
||||
protected $record;
|
||||
protected $app;
|
||||
|
||||
@@ -59,7 +41,7 @@ class caption_Field_Value implements cache_cacheableInterface
|
||||
*/
|
||||
protected $qjs;
|
||||
|
||||
/**
|
||||
/*
|
||||
* Tells whether the value is matched against a thesaurus value.
|
||||
*/
|
||||
protected $isThesaurusValue;
|
||||
@@ -71,7 +53,7 @@ class caption_Field_Value implements cache_cacheableInterface
|
||||
* @param Application $app
|
||||
* @param databox_field $databox_field
|
||||
* @param record_adapter $record
|
||||
* @param type $id
|
||||
* @param mixed $id
|
||||
* @return \caption_Field_Value
|
||||
*/
|
||||
public function __construct(Application $app, databox_field $databox_field, record_adapter $record, $id)
|
||||
@@ -157,6 +139,9 @@ class caption_Field_Value implements cache_cacheableInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Vocabulary\ControlProvider\ControlProviderInterface
|
||||
*/
|
||||
public function getVocabularyType()
|
||||
{
|
||||
return $this->VocabularyType;
|
||||
@@ -177,9 +162,9 @@ class caption_Field_Value implements cache_cacheableInterface
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
public function getRessource()
|
||||
public function getResource()
|
||||
{
|
||||
return $this->VocabularyType ? $this->VocabularyType->getRessource($this->VocabularyId) : null;
|
||||
return $this->VocabularyType ? $this->VocabularyType->getResource($this->VocabularyId) : null;
|
||||
}
|
||||
|
||||
public function getDatabox_field()
|
||||
|
@@ -684,7 +684,7 @@ class databox extends base
|
||||
|
||||
/**
|
||||
*
|
||||
* @return databox_descriptionStructure
|
||||
* @return databox_descriptionStructure|databox_field[]
|
||||
*/
|
||||
public function get_meta_structure()
|
||||
{
|
||||
|
@@ -80,9 +80,7 @@ class databox_field implements cache_cacheableInterface
|
||||
const TYPE_STRING = "string";
|
||||
const TYPE_NUMBER = "number";
|
||||
|
||||
/**
|
||||
* http://dublincore.org/documents/dces/
|
||||
*/
|
||||
// http://dublincore.org/documents/dces/
|
||||
const DCES_TITLE = 'Title';
|
||||
const DCES_CREATOR = 'Creator';
|
||||
const DCES_SUBJECT = 'Subject';
|
||||
@@ -171,7 +169,7 @@ class databox_field implements cache_cacheableInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @return type \Alchemy\Phrasea\Vocabulary\ControlProvider\ControlProviderInterface
|
||||
* @return ControlProviderInterface
|
||||
*/
|
||||
public function getVocabularyControl()
|
||||
{
|
||||
@@ -908,8 +906,8 @@ class databox_field implements cache_cacheableInterface
|
||||
*
|
||||
* @param \Alchemy\Phrasea\Application $app
|
||||
* @param databox $databox
|
||||
* @param type $name
|
||||
* @param type $multi
|
||||
* @param string $name
|
||||
* @param bool $multi
|
||||
*
|
||||
* @return self
|
||||
*
|
||||
|
@@ -108,7 +108,7 @@ class patch_370alpha7a extends patchAbstract
|
||||
|
||||
}
|
||||
|
||||
$media = $app['mediavorus']->guess($filePath);
|
||||
$media = $app->getMediaFromUri($filePath);
|
||||
|
||||
$collection = \collection::get_from_base_id($app, $row['base_id']);
|
||||
|
||||
|
@@ -915,7 +915,7 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
|
||||
}
|
||||
|
||||
$app['filesystem']->chmod($subdefFile, 0760);
|
||||
$media = $app['mediavorus']->guess($subdefFile);
|
||||
$media = $app->getMediaFromUri($subdefFile);
|
||||
$subdef = media_subdef::create($app, $this, $name, $media);
|
||||
$subdef->set_substituted(true);
|
||||
|
||||
@@ -1274,7 +1274,7 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
|
||||
|
||||
$app['filesystem']->copy($file->getFile()->getRealPath(), $pathhd . $newname, true);
|
||||
|
||||
$media = $app['mediavorus']->guess($pathhd . $newname);
|
||||
$media = $app->getMediaFromUri($pathhd . $newname);
|
||||
media_subdef::create($app, $record, 'document', $media);
|
||||
|
||||
$record->delete_data_from_cache(\record_adapter::CACHE_SUBDEFS);
|
||||
|
@@ -61,7 +61,7 @@ class recordutils_image
|
||||
|
||||
$rotation = null;
|
||||
try {
|
||||
$image = $app['mediavorus']->guess($subdef->get_pathfile());
|
||||
$image = $app->getMediaFromUri($subdef->get_pathfile());
|
||||
if (MediaInterface::TYPE_IMAGE === $image->getType()) {
|
||||
$rotation = $image->getOrientation();
|
||||
}
|
||||
|
@@ -8,6 +8,6 @@ class ArchiveJobTest extends JobTestCase
|
||||
{
|
||||
protected function getJob()
|
||||
{
|
||||
return new ArchiveJob(null, null, $this->createTranslatorMock());
|
||||
return new ArchiveJob($this->createTranslatorMock());
|
||||
}
|
||||
}
|
||||
|
@@ -8,6 +8,6 @@ class BridgeJobTest extends JobTestCase
|
||||
{
|
||||
protected function getJob()
|
||||
{
|
||||
return new BridgeJob(null, null, $this->createTranslatorMock());
|
||||
return new BridgeJob($this->createTranslatorMock());
|
||||
}
|
||||
}
|
||||
|
@@ -8,6 +8,6 @@ class EmptyCollectionJobTest extends JobTestCase
|
||||
{
|
||||
protected function getJob()
|
||||
{
|
||||
return new EmptyCollectionJob(null, null, $this->createTranslatorMock());
|
||||
return new EmptyCollectionJob($this->createTranslatorMock());
|
||||
}
|
||||
}
|
||||
|
@@ -2,12 +2,18 @@
|
||||
|
||||
namespace Alchemy\Tests\Phrasea\TaskManager\Job;
|
||||
|
||||
use Alchemy\Phrasea\Notification\Deliverer;
|
||||
use Alchemy\Phrasea\TaskManager\Job\FtpJob;
|
||||
|
||||
class FtpJobTest extends JobTestCase
|
||||
{
|
||||
protected function getJob()
|
||||
{
|
||||
return new FtpJob(null, null, $this->createTranslatorMock());
|
||||
return (new FtpJob($this->createTranslatorMock()))
|
||||
->setDelivererLocator(function () {
|
||||
$this->getMockBuilder(Deliverer::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -8,6 +8,6 @@ class FtpPullJobTest extends JobTestCase
|
||||
{
|
||||
protected function getJob()
|
||||
{
|
||||
return new FtpPullJob(null, null, $this->createTranslatorMock());
|
||||
return new FtpPullJob($this->createTranslatorMock());
|
||||
}
|
||||
}
|
||||
|
@@ -8,6 +8,6 @@ class NullJobTest extends JobTestCase
|
||||
{
|
||||
protected function getJob()
|
||||
{
|
||||
return new NullJob(null, null, $this->createTranslatorMock());
|
||||
return new NullJob($this->createTranslatorMock());
|
||||
}
|
||||
}
|
||||
|
@@ -8,6 +8,6 @@ class RecordMoverJobTest extends JobTestCase
|
||||
{
|
||||
protected function getJob()
|
||||
{
|
||||
return new RecordMoverJob(null, null, $this->createTranslatorMock());
|
||||
return new RecordMoverJob($this->createTranslatorMock());
|
||||
}
|
||||
}
|
||||
|
@@ -10,7 +10,7 @@ class SubdefsJobTest extends JobTestCase
|
||||
{
|
||||
protected function getJob()
|
||||
{
|
||||
return new SubdefsJob(null, null, $this->createTranslatorMock());
|
||||
return new SubdefsJob($this->createTranslatorMock());
|
||||
}
|
||||
|
||||
public function doTestRun()
|
||||
|
@@ -8,6 +8,6 @@ class WebhookJobTest extends JobTestCase
|
||||
{
|
||||
protected function getJob()
|
||||
{
|
||||
return new WebhookJob(null, null, $this->createTranslatorMock());
|
||||
return new WebhookJob($this->createTranslatorMock(), null, null);
|
||||
}
|
||||
}
|
||||
|
@@ -10,7 +10,7 @@ class WriteMetadataJobTest extends JobTestCase
|
||||
{
|
||||
protected function getJob()
|
||||
{
|
||||
return new WriteMetadataJob(null, null, $this->createTranslatorMock());
|
||||
return new WriteMetadataJob($this->createTranslatorMock());
|
||||
}
|
||||
|
||||
public function doTestRun()
|
||||
|
Reference in New Issue
Block a user