Merge remote-tracking branch 'origin/feature/controller-as-service'

This commit is contained in:
Benoît Burnichon
2015-05-13 10:19:38 +02:00
78 changed files with 2269 additions and 1762 deletions

View File

@@ -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

View 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);
}
}

View 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;
}
}

View 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);
}
}

View File

@@ -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());

View File

@@ -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));
}

View File

@@ -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);

View File

@@ -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'];

View File

@@ -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');

View File

@@ -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();

View File

@@ -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);
}
}
}

View File

@@ -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');

View File

@@ -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
*/

View File

@@ -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);

View 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'];
}
}

View 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())]));
}
}

View 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'];
}
}

View 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'];
}
}

View 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'];
}
}

View 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'];
}
}

View File

@@ -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()
{

View File

@@ -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'];
});
});
}

View File

@@ -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'];
});
});
}

View File

@@ -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'];
});
});
}

View File

@@ -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'];
});
});
}

View File

@@ -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'];
});
});
}

View File

@@ -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'];
});
});
}

View File

@@ -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');
}
}

View 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;
}
}

View File

@@ -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())]));
}
}

View File

@@ -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' => ''
]);
}
}

View File

@@ -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()]);
}
}

View File

@@ -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;
}

View File

@@ -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' => ''
]);
}
}

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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(

View File

@@ -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,

View File

@@ -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'));

View File

@@ -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');

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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;
}
}

View File

@@ -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),
];
});
}

View File

@@ -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;

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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();

View File

@@ -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'));

View File

@@ -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;

View File

@@ -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();

View File

@@ -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);
}
}

View File

@@ -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()));
}

View File

@@ -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();

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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()

View File

@@ -684,7 +684,7 @@ class databox extends base
/**
*
* @return databox_descriptionStructure
* @return databox_descriptionStructure|databox_field[]
*/
public function get_meta_structure()
{

View File

@@ -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
*

View File

@@ -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']);

View File

@@ -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);

View File

@@ -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();
}

View File

@@ -8,6 +8,6 @@ class ArchiveJobTest extends JobTestCase
{
protected function getJob()
{
return new ArchiveJob(null, null, $this->createTranslatorMock());
return new ArchiveJob($this->createTranslatorMock());
}
}

View File

@@ -8,6 +8,6 @@ class BridgeJobTest extends JobTestCase
{
protected function getJob()
{
return new BridgeJob(null, null, $this->createTranslatorMock());
return new BridgeJob($this->createTranslatorMock());
}
}

View File

@@ -8,6 +8,6 @@ class EmptyCollectionJobTest extends JobTestCase
{
protected function getJob()
{
return new EmptyCollectionJob(null, null, $this->createTranslatorMock());
return new EmptyCollectionJob($this->createTranslatorMock());
}
}

View File

@@ -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();
});
}
}

View File

@@ -8,6 +8,6 @@ class FtpPullJobTest extends JobTestCase
{
protected function getJob()
{
return new FtpPullJob(null, null, $this->createTranslatorMock());
return new FtpPullJob($this->createTranslatorMock());
}
}

View File

@@ -8,6 +8,6 @@ class NullJobTest extends JobTestCase
{
protected function getJob()
{
return new NullJob(null, null, $this->createTranslatorMock());
return new NullJob($this->createTranslatorMock());
}
}

View File

@@ -8,6 +8,6 @@ class RecordMoverJobTest extends JobTestCase
{
protected function getJob()
{
return new RecordMoverJob(null, null, $this->createTranslatorMock());
return new RecordMoverJob($this->createTranslatorMock());
}
}

View File

@@ -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()

View File

@@ -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);
}
}

View File

@@ -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()