mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-23 18:03:17 +00:00
Merge branch 'master' into PHRAS-2739-incorporate-subdefwebhook
This commit is contained in:
@@ -15,6 +15,7 @@ use Alchemy\Phrasea\Controller\Api\Result;
|
||||
use Alchemy\Phrasea\ControllerProvider\Api\OAuth2;
|
||||
use Alchemy\Phrasea\ControllerProvider\Api\V1;
|
||||
use Alchemy\Phrasea\ControllerProvider\Api\V2;
|
||||
use Alchemy\Phrasea\ControllerProvider\Api\V3;
|
||||
use Alchemy\Phrasea\ControllerProvider\Datafiles;
|
||||
use Alchemy\Phrasea\ControllerProvider\MediaAccessor;
|
||||
use Alchemy\Phrasea\ControllerProvider\Minifier;
|
||||
@@ -36,6 +37,7 @@ class ApiApplicationLoader extends BaseApplicationLoader
|
||||
$app->register(new OAuth2());
|
||||
$app->register(new V1());
|
||||
$app->register(new V2());
|
||||
$app->register(new V3());
|
||||
$app->register(new ApiReportControllerProvider());
|
||||
$app->register(new JsonSchemaServiceProvider());
|
||||
}
|
||||
@@ -119,6 +121,16 @@ class ApiApplicationLoader extends BaseApplicationLoader
|
||||
'access_token' => '/api/oauthv2/token'
|
||||
],
|
||||
],
|
||||
'3' => [
|
||||
'number' => V3::VERSION,
|
||||
'uri' => '/api/v3/',
|
||||
'authenticationProtocol' => 'OAuth2',
|
||||
'authenticationVersion' => 'draft#v9',
|
||||
'authenticationEndPoints' => [
|
||||
'authorization_token' => '/api/oauthv2/authorize',
|
||||
'access_token' => '/api/oauthv2/token'
|
||||
]
|
||||
],
|
||||
]
|
||||
])->createResponse();
|
||||
});
|
||||
@@ -135,6 +147,7 @@ class ApiApplicationLoader extends BaseApplicationLoader
|
||||
$app->mount('/datafiles/', new Datafiles());
|
||||
$app->mount('/api/v1', new V1());
|
||||
$app->mount('/api/v2', new V2());
|
||||
$app->mount('/api/v3', new V3());
|
||||
$app->mount('/api/report', new ApiReportControllerProvider());
|
||||
$app->mount('/permalink/', new Permalink());
|
||||
$app->mount($app['controller.media_accessor.route_prefix'], new MediaAccessor());
|
||||
|
@@ -0,0 +1,86 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Alchemy\Phrasea\Command\Collection;
|
||||
|
||||
use Alchemy\Phrasea\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class ListCollectionCommand extends Command
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct($name = null)
|
||||
{
|
||||
parent::__construct('collection:list');
|
||||
$this->setDescription('List all collection in Phraseanet')
|
||||
->addOption('databox_id', 'd', InputOption::VALUE_REQUIRED, 'The id of the databox to list collection')
|
||||
->addOption('jsonformat', null, InputOption::VALUE_NONE, 'Output in json format')
|
||||
->setHelp('');
|
||||
return $this;
|
||||
}
|
||||
protected function doExecute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
try {
|
||||
$jsonformat = $input->getOption('jsonformat');
|
||||
$databox = $this->container->findDataboxById($input->getOption('databox_id'));
|
||||
$collections = $this->listDataboxCollections($databox);
|
||||
|
||||
if ($jsonformat) {
|
||||
foreach ($collections as $collection) {
|
||||
$collectionList[] = array_combine(['id local for API', 'id distant', 'name','label','status','total records'], $collection);
|
||||
}
|
||||
echo json_encode($collectionList);
|
||||
} else {
|
||||
$table = $this->getHelperSet()->get('table');
|
||||
$table
|
||||
->setHeaders(['id local for API', 'id distant', 'name','label','status','total records'])
|
||||
->setRows($collections)
|
||||
->render($output);
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
$output->writeln("<error>{$e->getMessage()}</error>");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function listDataboxCollections(\databox $databox)
|
||||
{
|
||||
return array_map(function (\collection $collection) {
|
||||
return $this->listCollection($collection);
|
||||
}, array_merge($databox->get_collections(),$this->getUnabledCollection($databox->get_activable_colls())));
|
||||
}
|
||||
|
||||
private function getUnabledCollection($collections)
|
||||
{
|
||||
return array_map(function ($colId){
|
||||
return \collection::getByBaseId($this->container, $colId);
|
||||
},$collections);
|
||||
|
||||
}
|
||||
|
||||
private function listCollection(\collection $collection)
|
||||
{
|
||||
return [
|
||||
$collection->get_base_id(),
|
||||
$collection->get_coll_id(),
|
||||
$collection->get_name(),
|
||||
'en: ' . $collection->get_label('en') .
|
||||
', de: ' . $collection->get_label('de') .
|
||||
', fr: ' . $collection->get_label('fr') .
|
||||
', nl: ' . $collection->get_label('nl'),
|
||||
($collection->is_active()) ? 'enabled' : 'disabled',
|
||||
$collection->get_record_amount()
|
||||
];
|
||||
}
|
||||
}
|
72
lib/Alchemy/Phrasea/Command/Databox/ListDataboxCommand.php
Normal file
72
lib/Alchemy/Phrasea/Command/Databox/ListDataboxCommand.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Command\Databox;
|
||||
|
||||
use Alchemy\Phrasea\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
|
||||
class ListDataboxCommand extends Command
|
||||
{
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct($name = null)
|
||||
{
|
||||
parent::__construct('databox:list');
|
||||
|
||||
$this->setDescription('List all databox in Phraseanet')
|
||||
->addOption('jsonformat', null, InputOption::VALUE_NONE, 'Output in json format')
|
||||
->setHelp('');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function doExecute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
try {
|
||||
$jsonformat = $input->getOption('jsonformat');
|
||||
$databoxes = array_map(function (\databox $databox) {
|
||||
return $this->listDatabox($databox);
|
||||
}, $this->container->getApplicationBox()->get_databoxes());
|
||||
|
||||
if ($jsonformat) {
|
||||
foreach ($databoxes as $databox) {
|
||||
$databoxList[] = array_combine(['id', 'name', 'alias'], $databox);
|
||||
}
|
||||
echo json_encode($databoxList);
|
||||
} else {
|
||||
$table = $this->getHelperSet()->get('table');
|
||||
$table
|
||||
->setHeaders(['id', 'name', 'alias'])
|
||||
->setRows($databoxes)
|
||||
->render($output);
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
$output->writeln('<error>Listing databox failed : '.$e->getMessage().'</error>');
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function listDatabox(\databox $databox)
|
||||
{
|
||||
return [
|
||||
$databox->get_sbas_id(),
|
||||
$databox->get_dbname(),
|
||||
$databox->get_viewname()
|
||||
];
|
||||
}
|
||||
|
||||
}
|
@@ -15,6 +15,7 @@ use Alchemy\Phrasea\Application;
|
||||
use Alchemy\Phrasea\Command\Command;
|
||||
use Alchemy\Phrasea\Exception\RuntimeException;
|
||||
use Alchemy\Phrasea\Model\Entities\User;
|
||||
use Alchemy\Phrasea\Plugin\Plugin;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\HttpKernel\Client;
|
||||
@@ -30,6 +31,15 @@ class JsFixtures extends Command
|
||||
|
||||
protected function doExecute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
/** @var Plugin $plugin */
|
||||
$msg = [];
|
||||
foreach($this->container['plugins.manager']->listPlugins() as $plugin) {
|
||||
$msg[] = sprintf(" bin/setup plugins:remove \"%s\"", $plugin->getName());
|
||||
}
|
||||
if(count($msg) !== 0) {
|
||||
throw new RuntimeException("You must remove plugins first:\n" . join("\n", $msg));
|
||||
}
|
||||
|
||||
if (!file_exists($this->container['db.fixture.info']['path'])) {
|
||||
throw new RuntimeException('You must generate sqlite db first, run "bin/developer phraseanet:regenerate-sqlite" command.');
|
||||
}
|
||||
@@ -104,6 +114,7 @@ class JsFixtures extends Command
|
||||
private function writeResponse(OutputInterface $output, $method, $path, $to, $authenticateUser = false)
|
||||
{
|
||||
$environment = Application::ENV_TEST;
|
||||
/** @var Application $app */
|
||||
$app = require __DIR__ . '/../../Application/Root.php';
|
||||
$app['orm.em'] = $app->extend('orm.em', function($em, $app) {
|
||||
return $app['orm.ems'][$app['db.fixture.hash.key']];
|
||||
|
211
lib/Alchemy/Phrasea/Command/User/UserCreateCommand.php
Normal file
211
lib/Alchemy/Phrasea/Command/User/UserCreateCommand.php
Normal file
@@ -0,0 +1,211 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Command\User;
|
||||
|
||||
use Alchemy\Phrasea\Application\Helper\NotifierAware;
|
||||
use Alchemy\Phrasea\Command\Command;
|
||||
use Alchemy\Phrasea\Core\LazyLocator;
|
||||
use Alchemy\Phrasea\Model\Entities\User;
|
||||
use Alchemy\Phrasea\Notification\Mail\MailRequestPasswordSetup;
|
||||
use Alchemy\Phrasea\Notification\Mail\MailRequestEmailConfirmation;
|
||||
use Alchemy\Phrasea\Notification\Receiver;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
|
||||
class UserCreateCommand extends Command
|
||||
{
|
||||
use NotifierAware;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct($name = null)
|
||||
{
|
||||
parent::__construct('user:create');
|
||||
|
||||
$this->setDescription('Create user in Phraseanet')
|
||||
->addOption('user_login', null, InputOption::VALUE_REQUIRED, 'The desired login for created user.')
|
||||
->addOption('user_mail', null, InputOption::VALUE_OPTIONAL, 'The desired mail for created user.')
|
||||
->addOption('user_password', null, InputOption::VALUE_OPTIONAL, 'The desired password')
|
||||
->addOption('send_mail_confirm', null, InputOption::VALUE_NONE, 'Send an email to user, for validate email.')
|
||||
->addOption('send_mail_password', null, InputOption::VALUE_NONE, 'Send an email to user, for password definition, work only if user_password is not define')
|
||||
->addOption('model_number', null, InputOption::VALUE_OPTIONAL, 'Id of model')
|
||||
->addOption('user_gender', null, InputOption::VALUE_OPTIONAL, 'The gender for created user.')
|
||||
->addOption('user_firstname', null, InputOption::VALUE_OPTIONAL, 'The first name for created user.')
|
||||
->addOption('user_lastname', null, InputOption::VALUE_OPTIONAL, 'The last name for created user.')
|
||||
->addOption('user_compagny', null, InputOption::VALUE_OPTIONAL, 'The compagny for created user.')
|
||||
->addOption('user_job', null, InputOption::VALUE_OPTIONAL, 'The job for created user.')
|
||||
->addOption('user_activitie', null, InputOption::VALUE_OPTIONAL, 'The activitie for created user.')
|
||||
->addOption('user_phone', null, InputOption::VALUE_OPTIONAL, 'The phone number for created user.')
|
||||
->setHelp('');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function doExecute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
|
||||
$userLogin = $input->getOption('user_login');
|
||||
$userMail = $input->getOption('user_mail');
|
||||
$userPassword = $input->getOption('user_password');
|
||||
$sendMailConfirm = $input->getOption('send_mail_confirm');
|
||||
$sendMailPassword = $input->getOption('send_mail_password');
|
||||
$modelNumber = $input->getOption('model_number');
|
||||
$userGender = $input->getOption('user_gender');
|
||||
$userFirstName = $input->getOption('user_firstname');
|
||||
$userLastName = $input->getOption('user_lastname');
|
||||
$userCompagny = $input->getOption('user_compagny');
|
||||
$userJob = $input->getOption('user_job');
|
||||
$userActivity = $input->getOption('user_activitie');
|
||||
$userPhone = $input->getOption('user_phone');
|
||||
|
||||
$userRepository = $this->container['repo.users'];
|
||||
|
||||
if ($userMail) {
|
||||
if (!\Swift_Validate::email($userMail)) {
|
||||
$output->writeln('<error>Invalid mail address</error>');
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (null !== $userRepository->findByEmail($userMail)) {
|
||||
$output->writeln('<error>An user exist with this email.</error>');
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$password = (!is_null($userPassword)) ? $userPassword : $this->container['random.medium']->generateString(128);
|
||||
$userManipulator = $this->container['manipulator.user'];
|
||||
$user = $userManipulator->createUser($userLogin, $password, $userMail);
|
||||
|
||||
if ($userGender) {
|
||||
if (null === $gender = $this->verifyGender($userGender)) {
|
||||
$output->writeln('<bg=yellow;options=bold>Gender '.$userGender.' not exists.</>');
|
||||
}
|
||||
$user->setGender($gender);
|
||||
}
|
||||
|
||||
if($userFirstName) $user->setFirstName($userFirstName);
|
||||
if($userLastName) $user->setLastName($userLastName);
|
||||
if($userCompagny) $user->setCompany($userCompagny);
|
||||
if($userJob) $user->setJob($userJob);
|
||||
if($userActivity) $user->setActivity($userActivity);
|
||||
if($userPhone) $user->setPhone($userPhone);
|
||||
|
||||
if ($sendMailPassword and $userMail and is_null($userPassword)) {
|
||||
$this->sendPasswordSetupMail($user);
|
||||
}
|
||||
|
||||
if ($sendMailConfirm and $userMail) {
|
||||
$user->setMailLocked(true);
|
||||
$this->sendAccountUnlockEmail($user);
|
||||
}
|
||||
|
||||
if ($modelNumber) {
|
||||
$template = $userRepository->find($modelNumber);
|
||||
if (!$template) {
|
||||
$output->writeln('<bg=yellow;options=bold>Model '.$modelNumber.' not found.</>');
|
||||
} else {
|
||||
$base_ids = [];
|
||||
foreach ($this->container->getApplicationBox()->get_databoxes() as $databox) {
|
||||
foreach ($databox->get_collections() as $collection) {
|
||||
$base_ids[] = $collection->get_base_id();
|
||||
}
|
||||
}
|
||||
$this->container->getAclForUser($user)->apply_model($template, $base_ids);
|
||||
}
|
||||
}
|
||||
|
||||
$this->container['orm.em']->flush();
|
||||
|
||||
$output->writeln("<info>Create new user successful !</info>");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get gender for user
|
||||
* @param $type
|
||||
* @return int|null
|
||||
*/
|
||||
private function verifyGender($type)
|
||||
{
|
||||
switch (strtolower($type)) {
|
||||
case "mlle.":
|
||||
case "mlle":
|
||||
case "miss":
|
||||
case "mademoiselle":
|
||||
case "0":
|
||||
$gender = User::GENDER_MISS;
|
||||
break;
|
||||
case "mme":
|
||||
case "madame":
|
||||
case "ms":
|
||||
case "ms.":
|
||||
case "1":
|
||||
$gender = User::GENDER_MRS;
|
||||
break;
|
||||
case "m":
|
||||
case "m.":
|
||||
case "mr":
|
||||
case "mr.":
|
||||
case "monsieur":
|
||||
case "mister":
|
||||
case "2":
|
||||
$gender = User::GENDER_MR;
|
||||
break;
|
||||
default:
|
||||
$gender = null;
|
||||
}
|
||||
return $gender;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send mail for renew password
|
||||
* @param User $user
|
||||
*/
|
||||
public function sendPasswordSetupMail(User $user)
|
||||
{
|
||||
$this->setDelivererLocator(new LazyLocator($this->container, 'notification.deliverer'));
|
||||
$receiver = Receiver::fromUser($user);
|
||||
|
||||
$token = $this->container['manipulator.token']->createResetPasswordToken($user);
|
||||
|
||||
$mail = MailRequestPasswordSetup::create($this->container, $receiver);
|
||||
$servername = $this->container['conf']->get('servername');
|
||||
$mail->setButtonUrl('http://'.$servername.'/login/renew-password/?token='.$token->getValue());
|
||||
$mail->setLogin($user->getLogin());
|
||||
|
||||
$this->deliver($mail);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
*/
|
||||
public function sendAccountUnlockEmail(User $user)
|
||||
{
|
||||
$this->setDelivererLocator(new LazyLocator($this->container, 'notification.deliverer'));
|
||||
$receiver = Receiver::fromUser($user);
|
||||
|
||||
$token = $this->container['manipulator.token']->createAccountUnlockToken($user);
|
||||
|
||||
$mail = MailRequestEmailConfirmation::create($this->container, $receiver);
|
||||
$servername = $this->container['conf']->get('servername');
|
||||
$mail->setButtonUrl('http://'.$servername.'/login/register-confirm/?code='.$token->getValue());
|
||||
$mail->setExpiration($token->getExpiration());
|
||||
|
||||
$this->deliver($mail);
|
||||
}
|
||||
|
||||
}
|
287
lib/Alchemy/Phrasea/Command/User/UserListCommand.php
Normal file
287
lib/Alchemy/Phrasea/Command/User/UserListCommand.php
Normal file
@@ -0,0 +1,287 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Command\User;
|
||||
|
||||
use Alchemy\Phrasea\Command\Command;
|
||||
use Alchemy\Phrasea\Model\Entities\User;
|
||||
use Symfony\Component\Console\Helper\TableCell;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Alchemy\Phrasea\Utilities\NullableDateTime;
|
||||
|
||||
|
||||
class UserListCommand extends Command
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct($name = null)
|
||||
{
|
||||
parent::__construct('user:list');
|
||||
|
||||
$this->setDescription('List of all user (experimental)')
|
||||
->addOption('user_id', null, InputOption::VALUE_OPTIONAL, ' The id of user export only info this user ')
|
||||
->addOption('user_email', null, InputOption::VALUE_OPTIONAL, 'The mail of user export only info this user .')
|
||||
->addOption('database_id', null, InputOption::VALUE_OPTIONAL, 'Id of database.')
|
||||
->addOption('collection_id', null, InputOption::VALUE_OPTIONAL, 'Id of the collection.')
|
||||
->addOption('mail_lock_status', null, InputOption::VALUE_NONE, 'Status by mail locked')
|
||||
->addOption('guest', null, InputOption::VALUE_NONE, 'Only guest user')
|
||||
->addOption('created', null, InputOption::VALUE_OPTIONAL, 'Created at with operator,aaaa-mm-jj hh:mm:ss.')
|
||||
->addOption('updated', null, InputOption::VALUE_OPTIONAL, 'Update at with operator,aaaa-mm-jj hh:mm:ss.')
|
||||
->addOption('application', null, InputOption::VALUE_NONE, 'List application of user work only if --user_id is set')
|
||||
->addOption('right', null, InputOption::VALUE_NONE, 'Show right information')
|
||||
->addOption('adress', null, InputOption::VALUE_NONE, 'Show adress information')
|
||||
->addOption('models', null, InputOption::VALUE_NONE, "Show only defined models, if --user_id is set with --models it's the template owner")
|
||||
->addOption('jsonformat', null, InputOption::VALUE_NONE, 'Output in json format')
|
||||
->setHelp('');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function doExecute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
|
||||
$userId = $input->getOption('user_id');
|
||||
$userEmail = $input->getOption('user_email');
|
||||
$databaseId = $input->getOption('database_id');
|
||||
$collectionId = $input->getOption('collection_id');
|
||||
$lockStatus = $input->getOption('mail_lock_status');
|
||||
$guest = $input->getOption('guest');
|
||||
$application = $input->getOption('application');
|
||||
$withAdress = $input->getOption('adress');
|
||||
$created = $input->getOption('created');
|
||||
$updated = $input->getOption('updated');
|
||||
$withRight = $input->getOption('right');
|
||||
$models = $input->getOption('models');
|
||||
$jsonformat = $input->getOption('jsonformat');
|
||||
|
||||
$query = $this->container['phraseanet.user-query'];
|
||||
|
||||
if($databaseId) $query->on_base_ids([$databaseId]);
|
||||
if($collectionId) $query->on_sbas_ids([$collectionId]);
|
||||
if($created) $this->addFilterDate($created,'created',$query);
|
||||
if($updated) $this->addFilterDate($updated,'updated',$query);
|
||||
if($userId && !$models) $query->addSqlFilter('Users.id = ?' ,[$userId]);
|
||||
if($userEmail && !$models) $query->addSqlFilter('Users.email = ?' ,[$userEmail]);
|
||||
if($lockStatus && !$models) $query->addSqlFilter('Users.mail_locked = 1');
|
||||
if($guest && !$models) $query->include_invite(true)->addSqlFilter('Users.guest = 1');
|
||||
|
||||
if ($application and !$userId) {
|
||||
$output->writeln('<error>You must provide --user_id when using --application option</error>');
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @var UserRepository $userRepository */
|
||||
$userRepository = $this->container['repo.users'];
|
||||
|
||||
if ($models && $userId) {
|
||||
$users = $userRepository->findBy(['templateOwner' => $userId]);
|
||||
} elseif ($models) {
|
||||
$users = $userRepository->findTemplate();
|
||||
} else {
|
||||
$users = $query->execute()->get_results();
|
||||
}
|
||||
|
||||
$userList = [];
|
||||
$showApplication = false;
|
||||
foreach ($users as $key => $user) {
|
||||
if ($userId and $application) {
|
||||
$showApplication = true;
|
||||
}
|
||||
$userList[] = $this->listUser($user, $withAdress, $withRight);
|
||||
|
||||
$userListRaw[] = array_combine($this->headerTable($withAdress, $withRight), $this->listUser($user, $withAdress, $withRight));
|
||||
}
|
||||
|
||||
if ($jsonformat) {
|
||||
echo json_encode($userListRaw);
|
||||
} else {
|
||||
$table = $this->getHelperSet()->get('table');
|
||||
$table
|
||||
->setHeaders($this->headerTable($withAdress, $withRight))
|
||||
->setRows($userList)
|
||||
->render($output);
|
||||
;
|
||||
|
||||
|
||||
if ($showApplication) {
|
||||
$applicationTable = $this->getHelperSet()->get('table');
|
||||
$applicationTable->setHeaders(array(
|
||||
array(new TableCell('Applications', array('colspan' => 5))),
|
||||
['name','callback','client_secret','client_id','token'],
|
||||
))->setRows($this->getApplicationOfUser($users[0]))->render($output);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $withAdress
|
||||
* @param $withRight
|
||||
* @return array
|
||||
*/
|
||||
private function headerTable($withAdress,$withRight)
|
||||
{
|
||||
$defaultHeader = ['id', 'login', 'email','last_model','first_name','last_name','gender','created','updated','status','locale'];
|
||||
$adressHeader = [ 'address', 'zip_code', 'city', 'country', 'phone', 'fax', 'job','position', 'company', 'geoname_id'];
|
||||
$rightHeader = [ 'admin', 'guest', 'mail_notification', 'ldap_created', 'mail_locked'];
|
||||
|
||||
return $this->createInformation($withAdress,$withRight,$defaultHeader,['adress' => $adressHeader,'right' =>$rightHeader]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
* @param $withAdress
|
||||
* @param $withRight
|
||||
* @return array
|
||||
*/
|
||||
private function listUser(User $user,$withAdress,$withRight)
|
||||
{
|
||||
switch ($user->getGender()) {
|
||||
case User::GENDER_MRS:
|
||||
$gender = 'Mrs';
|
||||
break;
|
||||
case User::GENDER_MISS:
|
||||
$gender = 'Miss';
|
||||
break;
|
||||
case User::GENDER_MR:
|
||||
default:
|
||||
$gender = 'Mr';
|
||||
}
|
||||
|
||||
$defaultInfo = [
|
||||
$user->getId(),
|
||||
$user->getLogin() ?: '-',
|
||||
$user->getEmail() ?: '-',
|
||||
$user->getLastAppliedTemplate() ? $user->getLastAppliedTemplate()->getLogin() : '-',
|
||||
$user->getFirstName() ?: '-',
|
||||
$user->getLastName() ?: '-',
|
||||
$gender,
|
||||
NullableDateTime::format($user->getCreated(),'Y-m-d H:i:s'),
|
||||
NullableDateTime::format($user->getUpdated(),'Y-m-d H:i:s'),
|
||||
'status',
|
||||
$user->getLocale() ?: '-',
|
||||
];
|
||||
|
||||
return $this->createInformation($withAdress,$withRight,$defaultInfo,['adress' => $this->userAdress($user),'right' => $this->userRight($user)]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
* @return array
|
||||
*/
|
||||
private function userAdress(User $user)
|
||||
{
|
||||
return [
|
||||
$user->getAddress() ?: '-',
|
||||
$user->getZipCode() ?: '-',
|
||||
$user->getCity() ?: '-',
|
||||
$user->getCountry() ?: '-',
|
||||
$user->getPhone() ?: '-',
|
||||
$user->getFax() ?: '-',
|
||||
$user->getJob() ?: '-',
|
||||
$user->getActivity() ?: '-',
|
||||
$user->getCompany() ?: '-',
|
||||
$user->getGeonameId() ?: '-',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
* @return array
|
||||
*/
|
||||
private function userRight(User $user)
|
||||
{
|
||||
return [
|
||||
$user->isAdmin() ?: false,
|
||||
$user->isGuest() ?: false,
|
||||
$user->hasMailNotificationsActivated() ?: false,
|
||||
$user->hasLdapCreated() ?: false,
|
||||
$user->isMailLocked() ?: false,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
* @return array
|
||||
*/
|
||||
private function getApplicationOfUser(User $user)
|
||||
{
|
||||
$apiRepository = $this->container['repo.api-applications'];
|
||||
$applications = $apiRepository->findByUser($user);
|
||||
|
||||
if (empty($applications)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$accountRepository = $this->container['repo.api-accounts'];
|
||||
$apiOauthRepository = $this->container['repo.api-oauth-tokens'];
|
||||
$usersApplication = [];
|
||||
foreach ($applications as $application) {
|
||||
$account = $accountRepository->findByUserAndApplication($user, $application);
|
||||
$token = $account ? $apiOauthRepository->findDeveloperToken($account) : null;
|
||||
$usersApplication[] = [
|
||||
$application->getName(),
|
||||
$application->getRedirectUri(),
|
||||
$application->getClientSecret(),
|
||||
$application->getClientId(),
|
||||
($token) ? $token->getOauthToken() : '-'
|
||||
];
|
||||
}
|
||||
|
||||
return $usersApplication;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $withAdress
|
||||
* @param $withRight
|
||||
* @param $default
|
||||
* @param $infoToMerge
|
||||
* @return array
|
||||
*/
|
||||
private function createInformation($withAdress,$withRight,$default,$infoToMerge)
|
||||
{
|
||||
if ($withAdress && $withRight) {
|
||||
$information = array_merge($default, $infoToMerge['adress'],$infoToMerge['right']);
|
||||
} elseif ($withAdress && !$withRight) {
|
||||
$information = array_merge($default, $infoToMerge['adress']);
|
||||
} elseif(!$withAdress && $withRight) {
|
||||
$information = array_merge($default, $infoToMerge['right']);
|
||||
} else {
|
||||
$information = $default;
|
||||
}
|
||||
|
||||
return $information;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $date
|
||||
* @param $type
|
||||
* @param $query
|
||||
*/
|
||||
private function addFilterDate($date,$type,$query){
|
||||
|
||||
list($operator,$dateAt) = explode(',', $date);
|
||||
|
||||
if (!in_array($operator,['=','>=','<=','>','<'])) {
|
||||
throw new \InvalidArgumentException(" '=' or '<=' or '>=' or '>' or '<'");
|
||||
}
|
||||
|
||||
$query->addSqlFilter($type.$operator.' ?' ,[$dateAt]);
|
||||
}
|
||||
|
||||
}
|
79
lib/Alchemy/Phrasea/Command/User/UserSetPasswordCommand.php
Normal file
79
lib/Alchemy/Phrasea/Command/User/UserSetPasswordCommand.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Command\User;
|
||||
|
||||
use Alchemy\Phrasea\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
use Symfony\Component\Console\Output\OutputInterface;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
|
||||
|
||||
class UserSetPasswordCommand extends Command
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public function __construct($name = null)
|
||||
{
|
||||
parent::__construct('user:set-password');
|
||||
|
||||
$this->setDescription('Set user password in Phraseanet')
|
||||
->addOption('user_id', null, InputOption::VALUE_REQUIRED, 'The id of user.')
|
||||
->addOption('generate', null, InputOption::VALUE_NONE, 'Generate the password')
|
||||
->addOption('password', null, InputOption::VALUE_OPTIONAL, 'The password')
|
||||
->setHelp('');
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
protected function doExecute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
|
||||
$dialog = $this->getHelperSet()->get('dialog');
|
||||
$userRepository = $this->container['repo.users'];
|
||||
$userManipulator = $this->container['manipulator.user'];
|
||||
$user = $userRepository->find($input->getOption('user_id'));
|
||||
$password = $input->getOption('password');
|
||||
$generate = $input->getOption('generate');
|
||||
|
||||
if ($user === null) {
|
||||
$output->writeln('<info>Not found User.</info>');
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ($generate) {
|
||||
$password = $this->container['random.medium']->generateString(64);
|
||||
} else {
|
||||
if (!$password) {
|
||||
$output->writeln('<error>--password option not specified</error>');
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
do {
|
||||
$continue = mb_strtolower($dialog->ask($output, '<question>Do you want really set password to this user? (y/N)</question>', 'N'));
|
||||
} while (!in_array($continue, ['y', 'n']));
|
||||
|
||||
if ($continue !== 'y') {
|
||||
$output->writeln('Aborting !');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$userManipulator->setPassword($user,$password);
|
||||
$output->writeln('New password: <info>' . $password . '</info>');
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
@@ -13,9 +13,11 @@ namespace Alchemy\Phrasea\Controller\Admin;
|
||||
use Alchemy\Phrasea\Controller\Controller;
|
||||
use Alchemy\Phrasea\SearchEngine\Elastic\ElasticsearchSettingsFormType;
|
||||
use Alchemy\Phrasea\SearchEngine\Elastic\ElasticsearchOptions;
|
||||
use Alchemy\Phrasea\SearchEngine\Elastic\Structure\GlobalStructure;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use databox_descriptionStructure;
|
||||
|
||||
class SearchEngineController extends Controller
|
||||
{
|
||||
@@ -31,7 +33,19 @@ class SearchEngineController extends Controller
|
||||
$form->handleRequest($request);
|
||||
|
||||
if ($form->isValid()) {
|
||||
$this->saveElasticSearchOptions($form->getData());
|
||||
/** @var ElasticsearchOptions $data */
|
||||
$data = $form->getData();
|
||||
// $q = $request->request->get('elasticsearch_settings');
|
||||
$facetNames = []; // rebuild the data "_customValues/facets" list following the form order
|
||||
foreach($request->request->get('elasticsearch_settings') as $name=>$value) {
|
||||
$matches = null;
|
||||
if(preg_match('/^facets:(.+):limit$/', $name, $matches) === 1) {
|
||||
$facetNames[] = $matches[1];
|
||||
}
|
||||
}
|
||||
$data->reorderAggregableFields($facetNames);
|
||||
|
||||
$this->saveElasticSearchOptions($data);
|
||||
|
||||
return $this->app->redirectPath('admin_searchengine_form');
|
||||
}
|
||||
@@ -76,6 +90,16 @@ class SearchEngineController extends Controller
|
||||
*/
|
||||
private function saveElasticSearchOptions(ElasticsearchOptions $configuration)
|
||||
{
|
||||
// save to databoxes fields for backward compatibility (useless ?)
|
||||
foreach($configuration->getAggregableFields() as $fname=>$aggregableField) {
|
||||
foreach ($this->app->getDataboxes() as $databox) {
|
||||
if(!is_null($f = $databox->get_meta_structure()->get_element_by_name($fname, databox_descriptionStructure::STRICT_COMPARE))) {
|
||||
$f->set_aggregable($aggregableField['limit'])->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// save to conf
|
||||
$this->getConf()->set(['main', 'search-engine', 'options'], $configuration->toArray());
|
||||
}
|
||||
|
||||
@@ -85,7 +109,10 @@ class SearchEngineController extends Controller
|
||||
*/
|
||||
private function getConfigurationForm(ElasticsearchOptions $options)
|
||||
{
|
||||
return $this->app->form(new ElasticsearchSettingsFormType(), $options, [
|
||||
/** @var GlobalStructure $g */
|
||||
$g = $this->app['search_engine.structure'];
|
||||
|
||||
return $this->app->form(new ElasticsearchSettingsFormType($g, $options), $options, [
|
||||
'action' => $this->app->url('admin_searchengine_form'),
|
||||
]);
|
||||
}
|
||||
|
@@ -12,6 +12,7 @@
|
||||
namespace Alchemy\Phrasea\Controller\Api;
|
||||
|
||||
use Alchemy\Phrasea\ControllerProvider\Api\V1;
|
||||
use Alchemy\Phrasea\ControllerProvider\Api\V3;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
@@ -268,11 +269,13 @@ class Result
|
||||
public function getVersion()
|
||||
{
|
||||
if (null === $this->version) {
|
||||
if($this->request->attributes->get('api_version')){
|
||||
if ($this->request->attributes->get('api_version')) {
|
||||
$this->version = $this->request->attributes->get('api_version');
|
||||
}elseif(mb_strpos($this->request->getPathInfo(), '/api/v1') !== FALSE){
|
||||
} elseif (mb_strpos($this->request->getPathInfo(), '/api/v1') !== FALSE) {
|
||||
$this->version = V1::VERSION;
|
||||
}else{
|
||||
} elseif (mb_strpos($this->request->getPathInfo(), '/api/v3') !== FALSE) {
|
||||
$this->version = V3::VERSION;
|
||||
} else {
|
||||
$this->version = self::$defaultVersion;
|
||||
}
|
||||
}
|
||||
|
807
lib/Alchemy/Phrasea/Controller/Api/V3Controller.php
Normal file
807
lib/Alchemy/Phrasea/Controller/Api/V3Controller.php
Normal file
@@ -0,0 +1,807 @@
|
||||
<?php
|
||||
|
||||
namespace Alchemy\Phrasea\Controller\Api;
|
||||
|
||||
use Alchemy\Phrasea\Collection\Reference\CollectionReference;
|
||||
use Alchemy\Phrasea\Controller\Controller;
|
||||
use Alchemy\Phrasea\Databox\DataboxGroupable;
|
||||
use Alchemy\Phrasea\Fractal\CallbackTransformer;
|
||||
use Alchemy\Phrasea\Fractal\IncludeResolver;
|
||||
use Alchemy\Phrasea\Fractal\SearchResultTransformerResolver;
|
||||
use Alchemy\Phrasea\Fractal\TraceableArraySerializer;
|
||||
use Alchemy\Phrasea\Model\Manipulator\UserManipulator;
|
||||
use Alchemy\Phrasea\Model\RecordReferenceInterface;
|
||||
use Alchemy\Phrasea\Record\RecordCollection;
|
||||
use Alchemy\Phrasea\Record\RecordReferenceCollection;
|
||||
use Alchemy\Phrasea\Search\CaptionView;
|
||||
use Alchemy\Phrasea\Search\PermalinkTransformer;
|
||||
use Alchemy\Phrasea\Search\PermalinkView;
|
||||
use Alchemy\Phrasea\Search\RecordTransformer;
|
||||
use Alchemy\Phrasea\Search\RecordView;
|
||||
use Alchemy\Phrasea\Search\SearchResultView;
|
||||
use Alchemy\Phrasea\Search\StoryTransformer;
|
||||
use Alchemy\Phrasea\Search\StoryView;
|
||||
use Alchemy\Phrasea\Search\SubdefTransformer;
|
||||
use Alchemy\Phrasea\Search\SubdefView;
|
||||
use Alchemy\Phrasea\Search\TechnicalDataTransformer;
|
||||
use Alchemy\Phrasea\Search\TechnicalDataView;
|
||||
use Alchemy\Phrasea\Search\V1SearchCompositeResultTransformer;
|
||||
use Alchemy\Phrasea\Search\V1SearchResultTransformer;
|
||||
use Alchemy\Phrasea\SearchEngine\SearchEngineInterface;
|
||||
use Alchemy\Phrasea\SearchEngine\SearchEngineLogger;
|
||||
use Alchemy\Phrasea\SearchEngine\SearchEngineOptions;
|
||||
use Alchemy\Phrasea\SearchEngine\SearchEngineResult;
|
||||
use League\Fractal\Resource\Item;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
class V3Controller extends Controller
|
||||
{
|
||||
/**
|
||||
* Return detailed information about one story
|
||||
*
|
||||
* @param Request $request
|
||||
* @param int $databox_id
|
||||
* @param int $record_id
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function getStoryAction(Request $request, $databox_id, $record_id)
|
||||
{
|
||||
try {
|
||||
$story = $this->findDataboxById($databox_id)->get_record($record_id);
|
||||
|
||||
return Result::create($request, ['story' => $this->listStory($request, $story)])->createResponse();
|
||||
} catch (NotFoundHttpException $e) {
|
||||
return Result::createError($request, 404, $this->app->trans('Story Not Found'))->createResponse();
|
||||
} catch (\Exception $e) {
|
||||
return $this->app['controller.api.v1']->getBadRequestAction($request, $this->app->trans('An error occurred'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for results
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return Response
|
||||
*/
|
||||
public function searchAction(Request $request)
|
||||
{
|
||||
$subdefTransformer = new SubdefTransformer($this->app['acl'], $this->getAuthenticatedUser(), new PermalinkTransformer());
|
||||
$technicalDataTransformer = new TechnicalDataTransformer();
|
||||
$recordTransformer = new RecordTransformer($subdefTransformer, $technicalDataTransformer);
|
||||
$storyTransformer = new StoryTransformer($subdefTransformer, $recordTransformer);
|
||||
$compositeTransformer = new V1SearchCompositeResultTransformer($recordTransformer, $storyTransformer);
|
||||
$searchTransformer = new V1SearchResultTransformer($compositeTransformer);
|
||||
|
||||
$transformerResolver = new SearchResultTransformerResolver([
|
||||
'' => $searchTransformer,
|
||||
'results' => $compositeTransformer,
|
||||
'results.stories' => $storyTransformer,
|
||||
'results.stories.thumbnail' => $subdefTransformer,
|
||||
'results.stories.metadatas' => new CallbackTransformer(),
|
||||
'results.stories.caption' => new CallbackTransformer(),
|
||||
'results.stories.records' => $recordTransformer,
|
||||
'results.stories.records.thumbnail' => $subdefTransformer,
|
||||
'results.stories.records.technical_informations' => $technicalDataTransformer,
|
||||
'results.stories.records.subdefs' => $subdefTransformer,
|
||||
'results.stories.records.metadata' => new CallbackTransformer(),
|
||||
'results.stories.records.status' => new CallbackTransformer(),
|
||||
'results.stories.records.caption' => new CallbackTransformer(),
|
||||
'results.records' => $recordTransformer,
|
||||
'results.records.thumbnail' => $subdefTransformer,
|
||||
'results.records.technical_informations' => $technicalDataTransformer,
|
||||
'results.records.subdefs' => $subdefTransformer,
|
||||
'results.records.metadata' => new CallbackTransformer(),
|
||||
'results.records.status' => new CallbackTransformer(),
|
||||
'results.records.caption' => new CallbackTransformer(),
|
||||
]);
|
||||
|
||||
$includeResolver = new IncludeResolver($transformerResolver);
|
||||
|
||||
$fractal = new \League\Fractal\Manager();
|
||||
$fractal->setSerializer(new TraceableArraySerializer($this->app['dispatcher']));
|
||||
$fractal->parseIncludes($this->resolveSearchIncludes($request));
|
||||
|
||||
$result = $this->doSearch($request);
|
||||
|
||||
$story_max_records = null;
|
||||
// if search on story
|
||||
if ($request->get('search_type') == 1) {
|
||||
$story_max_records = (int)$request->get('story_max_records') ?: 10;
|
||||
}
|
||||
|
||||
$searchView = $this->buildSearchView(
|
||||
$result,
|
||||
$includeResolver->resolve($fractal),
|
||||
$this->resolveSubdefUrlTTL($request),
|
||||
$story_max_records
|
||||
);
|
||||
|
||||
$ret = $fractal->createData(new Item($searchView, $searchTransformer))->toArray();
|
||||
|
||||
return Result::create($request, $ret)->createResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve detailed information about one story
|
||||
*
|
||||
* @param Request $request
|
||||
* @param \record_adapter $story
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function listStory(Request $request, \record_adapter $story)
|
||||
{
|
||||
if (!$story->isStory()) {
|
||||
return Result::createError($request, 404, 'Story not found')->createResponse();
|
||||
}
|
||||
|
||||
$per_page = (int)$request->get('per_page')?:10;
|
||||
$page = (int)$request->get('page')?:1;
|
||||
$offset = ($per_page * ($page - 1)) + 1;
|
||||
|
||||
$caption = $story->get_caption();
|
||||
|
||||
$format = function (\caption_record $caption, $dcField) {
|
||||
|
||||
$field = $caption->get_dc_field($dcField);
|
||||
|
||||
if (!$field) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $field->get_serialized_values();
|
||||
};
|
||||
|
||||
return [
|
||||
'@entity@' => V1Controller::OBJECT_TYPE_STORY,
|
||||
'databox_id' => $story->getDataboxId(),
|
||||
'story_id' => $story->getRecordId(),
|
||||
'updated_on' => $story->getUpdated()->format(DATE_ATOM),
|
||||
'created_on' => $story->getCreated()->format(DATE_ATOM),
|
||||
'collection_id' => $story->getCollectionId(),
|
||||
'base_id' => $story->getBaseId(),
|
||||
'thumbnail' => $this->listEmbeddableMedia($request, $story, $story->get_thumbnail()),
|
||||
'uuid' => $story->getUuid(),
|
||||
'metadatas' => [
|
||||
'@entity@' => V1Controller::OBJECT_TYPE_STORY_METADATA_BAG,
|
||||
'dc:contributor' => $format($caption, \databox_Field_DCESAbstract::Contributor),
|
||||
'dc:coverage' => $format($caption, \databox_Field_DCESAbstract::Coverage),
|
||||
'dc:creator' => $format($caption, \databox_Field_DCESAbstract::Creator),
|
||||
'dc:date' => $format($caption, \databox_Field_DCESAbstract::Date),
|
||||
'dc:description' => $format($caption, \databox_Field_DCESAbstract::Description),
|
||||
'dc:format' => $format($caption, \databox_Field_DCESAbstract::Format),
|
||||
'dc:identifier' => $format($caption, \databox_Field_DCESAbstract::Identifier),
|
||||
'dc:language' => $format($caption, \databox_Field_DCESAbstract::Language),
|
||||
'dc:publisher' => $format($caption, \databox_Field_DCESAbstract::Publisher),
|
||||
'dc:relation' => $format($caption, \databox_Field_DCESAbstract::Relation),
|
||||
'dc:rights' => $format($caption, \databox_Field_DCESAbstract::Rights),
|
||||
'dc:source' => $format($caption, \databox_Field_DCESAbstract::Source),
|
||||
'dc:subject' => $format($caption, \databox_Field_DCESAbstract::Subject),
|
||||
'dc:title' => $format($caption, \databox_Field_DCESAbstract::Title),
|
||||
'dc:type' => $format($caption, \databox_Field_DCESAbstract::Type),
|
||||
],
|
||||
'records' => $this->listRecords($request, array_values($story->getChildren($offset, $per_page)->get_elements())),
|
||||
];
|
||||
}
|
||||
|
||||
private function listEmbeddableMedia(Request $request, \record_adapter $record, \media_subdef $media)
|
||||
{
|
||||
if (!$media->is_physically_present()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($this->getAuthenticator()->isAuthenticated()) {
|
||||
$acl = $this->getAclForUser();
|
||||
if ($media->get_name() !== 'document'
|
||||
&& false === $acl->has_access_to_subdef($record, $media->get_name())
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
if ($media->get_name() === 'document'
|
||||
&& !$acl->has_right_on_base($record->getBaseId(), \ACL::CANDWNLDHD)
|
||||
&& !$acl->has_hd_grant($record)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if ($media->get_permalink() instanceof \media_Permalink_Adapter) {
|
||||
$permalink = $this->listPermalink($media->get_permalink());
|
||||
} else {
|
||||
$permalink = null;
|
||||
}
|
||||
|
||||
$urlTTL = (int) $request->get(
|
||||
'subdef_url_ttl',
|
||||
$this->getConf()->get(['registry', 'general', 'default-subdef-url-ttl'])
|
||||
);
|
||||
if ($urlTTL < 0) {
|
||||
$urlTTL = -1;
|
||||
}
|
||||
$issuer = $this->getAuthenticatedUser();
|
||||
|
||||
return [
|
||||
'name' => $media->get_name(),
|
||||
'permalink' => $permalink,
|
||||
'height' => $media->get_height(),
|
||||
'width' => $media->get_width(),
|
||||
'filesize' => $media->get_size(),
|
||||
'devices' => $media->getDevices(),
|
||||
'player_type' => $media->get_type(),
|
||||
'mime_type' => $media->get_mime(),
|
||||
'substituted' => $media->is_substituted(),
|
||||
'created_on' => $media->get_creation_date()->format(DATE_ATOM),
|
||||
'updated_on' => $media->get_modification_date()->format(DATE_ATOM),
|
||||
'url' => $this->app['media_accessor.subdef_url_generator']->generate($issuer, $media, $urlTTL),
|
||||
'url_ttl' => $urlTTL,
|
||||
];
|
||||
}
|
||||
|
||||
private function listPermalink(\media_Permalink_Adapter $permalink)
|
||||
{
|
||||
$downloadUrl = $permalink->get_url();
|
||||
$downloadUrl->getQuery()->set('download', '1');
|
||||
|
||||
return [
|
||||
'created_on' => $permalink->get_created_on()->format(DATE_ATOM),
|
||||
'id' => $permalink->get_id(),
|
||||
'is_activated' => $permalink->get_is_activated(),
|
||||
/** @Ignore */
|
||||
'label' => $permalink->get_label(),
|
||||
'updated_on' => $permalink->get_last_modified()->format(DATE_ATOM),
|
||||
'page_url' => $permalink->get_page(),
|
||||
'download_url' => (string)$downloadUrl,
|
||||
'url' => (string)$permalink->get_url(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param RecordReferenceInterface[]|RecordReferenceCollection $records
|
||||
* @return array
|
||||
*/
|
||||
private function listRecords(Request $request, $records)
|
||||
{
|
||||
if (!$records instanceof RecordReferenceCollection) {
|
||||
$records = new RecordReferenceCollection($records);
|
||||
}
|
||||
|
||||
$technicalData = $this->app['service.technical_data']->fetchRecordsTechnicalData($records);
|
||||
|
||||
$data = [];
|
||||
|
||||
foreach ($records->toRecords($this->getApplicationBox()) as $index => $record) {
|
||||
$record->setTechnicalDataSet($technicalData[$index]);
|
||||
|
||||
$data[$index] = $this->listRecord($request, $record);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve detailed information about one record
|
||||
*
|
||||
* @param Request $request
|
||||
* @param \record_adapter $record
|
||||
* @return array
|
||||
*/
|
||||
private function listRecord(Request $request, \record_adapter $record)
|
||||
{
|
||||
$technicalInformation = [];
|
||||
foreach ($record->get_technical_infos()->getValues() as $name => $value) {
|
||||
$technicalInformation[] = ['name' => $name, 'value' => $value];
|
||||
}
|
||||
|
||||
$data = [
|
||||
'databox_id' => $record->getDataboxId(),
|
||||
'record_id' => $record->getRecordId(),
|
||||
'mime_type' => $record->getMimeType(),
|
||||
'title' => $record->get_title(),
|
||||
'original_name' => $record->get_original_name(),
|
||||
'updated_on' => $record->getUpdated()->format(DATE_ATOM),
|
||||
'created_on' => $record->getCreated()->format(DATE_ATOM),
|
||||
'collection_id' => $record->getCollectionId(),
|
||||
'base_id' => $record->getBaseId(),
|
||||
'sha256' => $record->getSha256(),
|
||||
'thumbnail' => $this->listEmbeddableMedia($request, $record, $record->get_thumbnail()),
|
||||
'technical_informations' => $technicalInformation,
|
||||
'phrasea_type' => $record->getType(),
|
||||
'uuid' => $record->getUuid(),
|
||||
];
|
||||
|
||||
if ($request->attributes->get('_extended', false)) {
|
||||
$data = array_merge($data, [
|
||||
'subdefs' => $this->listRecordEmbeddableMedias($request, $record),
|
||||
'metadata' => $this->listRecordMetadata($record),
|
||||
'status' => $this->listRecordStatus($record),
|
||||
'caption' => $this->listRecordCaption($record),
|
||||
]);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param \record_adapter $record
|
||||
* @return array
|
||||
*/
|
||||
private function listRecordEmbeddableMedias(Request $request, \record_adapter $record)
|
||||
{
|
||||
$subdefs = [];
|
||||
|
||||
foreach ($record->get_embedable_medias([], []) as $name => $media) {
|
||||
if (null !== $subdef = $this->listEmbeddableMedia($request, $record, $media)) {
|
||||
$subdefs[] = $subdef;
|
||||
}
|
||||
}
|
||||
|
||||
return $subdefs;
|
||||
}
|
||||
|
||||
/**
|
||||
* List all fields of given record
|
||||
*
|
||||
* @param \record_adapter $record
|
||||
* @return array
|
||||
*/
|
||||
private function listRecordMetadata(\record_adapter $record)
|
||||
{
|
||||
$includeBusiness = $this->getAclForUser()->can_see_business_fields($record->getDatabox());
|
||||
|
||||
return $this->listRecordCaptionFields($record->get_caption()->get_fields(null, $includeBusiness));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \caption_field[] $fields
|
||||
* @return array
|
||||
*/
|
||||
private function listRecordCaptionFields($fields)
|
||||
{
|
||||
$ret = [];
|
||||
|
||||
foreach ($fields as $field) {
|
||||
$databox_field = $field->get_databox_field();
|
||||
|
||||
$fieldData = [
|
||||
'meta_structure_id' => $field->get_meta_struct_id(),
|
||||
'name' => $field->get_name(),
|
||||
'labels' => [
|
||||
'fr' => $databox_field->get_label('fr'),
|
||||
'en' => $databox_field->get_label('en'),
|
||||
'de' => $databox_field->get_label('de'),
|
||||
'nl' => $databox_field->get_label('nl'),
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($field->get_values() as $value) {
|
||||
$data = [
|
||||
'meta_id' => $value->getId(),
|
||||
'value' => $value->getValue(),
|
||||
];
|
||||
|
||||
$ret[] = $fieldData + $data;
|
||||
}
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve detailed information about one status
|
||||
*
|
||||
* @param \record_adapter $record
|
||||
* @return array
|
||||
*/
|
||||
private function listRecordStatus(\record_adapter $record)
|
||||
{
|
||||
$ret = [];
|
||||
foreach ($record->getStatusStructure() as $bit => $status) {
|
||||
$ret[] = [
|
||||
'bit' => $bit,
|
||||
'state' => \databox_status::bitIsSet($record->getStatusBitField(), $bit),
|
||||
];
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \record_adapter $record
|
||||
* @return array
|
||||
*/
|
||||
private function listRecordCaption(\record_adapter $record)
|
||||
{
|
||||
$includeBusiness = $this->getAclForUser()->can_see_business_fields($record->getDatabox());
|
||||
|
||||
$caption = [];
|
||||
|
||||
foreach ($record->get_caption()->get_fields(null, $includeBusiness) as $field) {
|
||||
$caption[] = [
|
||||
'meta_structure_id' => $field->get_meta_struct_id(),
|
||||
'name' => $field->get_name(),
|
||||
'value' => $field->get_serialized_values(';'),
|
||||
];
|
||||
}
|
||||
|
||||
return $caption;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns requested includes
|
||||
*
|
||||
* @param Request $request
|
||||
* @return string[]
|
||||
*/
|
||||
private function resolveSearchIncludes(Request $request)
|
||||
{
|
||||
$includes = [
|
||||
'results.stories.records'
|
||||
];
|
||||
|
||||
if ($request->attributes->get('_extended', false)) {
|
||||
if ($request->get('search_type') != SearchEngineOptions::RECORD_STORY) {
|
||||
$includes = array_merge($includes, [
|
||||
'results.stories.records.subdefs',
|
||||
'results.stories.records.metadata',
|
||||
'results.stories.records.caption',
|
||||
'results.stories.records.status'
|
||||
]);
|
||||
}
|
||||
else {
|
||||
$includes = [ 'results.stories.caption' ];
|
||||
}
|
||||
|
||||
$includes = array_merge($includes, [
|
||||
'results.records.subdefs',
|
||||
'results.records.metadata',
|
||||
'results.records.caption',
|
||||
'results.records.status'
|
||||
]);
|
||||
}
|
||||
|
||||
return $includes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SearchEngineResult $result
|
||||
* @param string[] $includes
|
||||
* @param int $urlTTL
|
||||
* @param int|null $story_max_records
|
||||
* @return SearchResultView
|
||||
*/
|
||||
private function buildSearchView(SearchEngineResult $result, array $includes, $urlTTL, $story_max_records = null)
|
||||
{
|
||||
$references = new RecordReferenceCollection($result->getResults());
|
||||
|
||||
$records = new RecordCollection();
|
||||
$stories = new RecordCollection();
|
||||
|
||||
foreach ($references->toRecords($this->getApplicationBox()) as $record) {
|
||||
if ($record->isStory()) {
|
||||
$stories[$record->getId()] = $record;
|
||||
} else {
|
||||
$records[$record->getId()] = $record;
|
||||
}
|
||||
}
|
||||
|
||||
$resultView = new SearchResultView($result);
|
||||
|
||||
if ($stories->count() > 0) {
|
||||
$user = $this->getAuthenticatedUser();
|
||||
$children = [];
|
||||
|
||||
foreach ($stories->getDataboxIds() as $databoxId) {
|
||||
$storyIds = $stories->getDataboxRecordIds($databoxId);
|
||||
|
||||
$selections = $this->findDataboxById($databoxId)
|
||||
->getRecordRepository()
|
||||
->findChildren($storyIds, $user,1, $story_max_records);
|
||||
$children[$databoxId] = array_combine($storyIds, $selections);
|
||||
}
|
||||
|
||||
/** @var StoryView[] $storyViews */
|
||||
$storyViews = [];
|
||||
/** @var RecordView[] $childrenViews */
|
||||
$childrenViews = [];
|
||||
|
||||
foreach ($stories as $index => $story) {
|
||||
$storyView = new StoryView($story);
|
||||
|
||||
$selection = $children[$story->getDataboxId()][$story->getRecordId()];
|
||||
|
||||
$childrenView = $this->buildRecordViews($selection);
|
||||
|
||||
foreach ($childrenView as $view) {
|
||||
$childrenViews[spl_object_hash($view)] = $view;
|
||||
}
|
||||
|
||||
$storyView->setChildren($childrenView);
|
||||
|
||||
$storyViews[$index] = $storyView;
|
||||
}
|
||||
|
||||
if (in_array('results.stories.thumbnail', $includes, true)) {
|
||||
$subdefViews = $this->buildSubdefsViews($stories, ['thumbnail'], $urlTTL);
|
||||
|
||||
foreach ($storyViews as $index => $storyView) {
|
||||
$storyView->setSubdefs($subdefViews[$index]);
|
||||
}
|
||||
}
|
||||
|
||||
if (in_array('results.stories.metadatas', $includes, true) ||
|
||||
in_array('results.stories.caption', $includes, true)) {
|
||||
$captions = $this->app['service.caption']->findByReferenceCollection($stories);
|
||||
$canSeeBusiness = $this->retrieveSeeBusinessPerDatabox($stories);
|
||||
|
||||
$this->buildCaptionViews($storyViews, $captions, $canSeeBusiness);
|
||||
}
|
||||
|
||||
$allChildren = new RecordCollection();
|
||||
foreach ($childrenViews as $index => $childrenView) {
|
||||
$allChildren[$index] = $childrenView->getRecord();
|
||||
}
|
||||
|
||||
$names = in_array('results.stories.records.subdefs', $includes, true) ? null : ['thumbnail'];
|
||||
$subdefViews = $this->buildSubdefsViews($allChildren, $names, $urlTTL);
|
||||
$technicalDatasets = $this->app['service.technical_data']->fetchRecordsTechnicalData($allChildren);
|
||||
|
||||
foreach ($childrenViews as $index => $recordView) {
|
||||
$recordView->setSubdefs($subdefViews[$index]);
|
||||
$recordView->setTechnicalDataView(new TechnicalDataView($technicalDatasets[$index]));
|
||||
}
|
||||
|
||||
if (array_intersect($includes, ['results.stories.records.metadata', 'results.stories.records.caption'])) {
|
||||
$captions = $this->app['service.caption']->findByReferenceCollection($allChildren);
|
||||
$canSeeBusiness = $this->retrieveSeeBusinessPerDatabox($allChildren);
|
||||
|
||||
$this->buildCaptionViews($childrenViews, $captions, $canSeeBusiness);
|
||||
}
|
||||
|
||||
$resultView->setStories($storyViews);
|
||||
}
|
||||
|
||||
if ($records->count() > 0) {
|
||||
$names = in_array('results.records.subdefs', $includes, true) ? null : ['thumbnail'];
|
||||
$recordViews = $this->buildRecordViews($records);
|
||||
$subdefViews = $this->buildSubdefsViews($records, $names, $urlTTL);
|
||||
|
||||
$technicalDatasets = $this->app['service.technical_data']->fetchRecordsTechnicalData($records);
|
||||
|
||||
foreach ($recordViews as $index => $recordView) {
|
||||
$recordView->setSubdefs($subdefViews[$index]);
|
||||
$recordView->setTechnicalDataView(new TechnicalDataView($technicalDatasets[$index]));
|
||||
}
|
||||
|
||||
if (array_intersect($includes, ['results.records.metadata', 'results.records.caption'])) {
|
||||
$captions = $this->app['service.caption']->findByReferenceCollection($records);
|
||||
$canSeeBusiness = $this->retrieveSeeBusinessPerDatabox($records);
|
||||
|
||||
$this->buildCaptionViews($recordViews, $captions, $canSeeBusiness);
|
||||
}
|
||||
|
||||
$resultView->setRecords($recordViews);
|
||||
}
|
||||
|
||||
return $resultView;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @return SearchEngineResult
|
||||
*/
|
||||
private function doSearch(Request $request)
|
||||
{
|
||||
$options = SearchEngineOptions::fromRequest($this->app, $request);
|
||||
$options->setFirstResult((int)($request->get('offset_start') ?: 0));
|
||||
$options->setMaxResults((int)$request->get('per_page') ?: 10);
|
||||
|
||||
$this->getSearchEngine()->resetCache();
|
||||
|
||||
$search_result = $this->getSearchEngine()->query((string)$request->get('query'), $options);
|
||||
|
||||
$this->getUserManipulator()->logQuery($this->getAuthenticatedUser(), $search_result->getQueryText());
|
||||
|
||||
// log array of collectionIds (from $options) for each databox
|
||||
$collectionsReferencesByDatabox = $options->getCollectionsReferencesByDatabox();
|
||||
foreach ($collectionsReferencesByDatabox as $sbid => $references) {
|
||||
$databox = $this->findDataboxById($sbid);
|
||||
$collectionsIds = array_map(function(CollectionReference $ref){return $ref->getCollectionId();}, $references);
|
||||
$this->getSearchEngineLogger()->log($databox, $search_result->getQueryText(), $search_result->getTotal(), $collectionsIds);
|
||||
}
|
||||
|
||||
$this->getSearchEngine()->clearCache();
|
||||
|
||||
return $search_result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SearchEngineInterface
|
||||
*/
|
||||
private function getSearchEngine()
|
||||
{
|
||||
return $this->app['phraseanet.SE'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return UserManipulator
|
||||
*/
|
||||
private function getUserManipulator()
|
||||
{
|
||||
return $this->app['manipulator.user'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return SearchEngineLogger
|
||||
*/
|
||||
private function getSearchEngineLogger()
|
||||
{
|
||||
return $this->app['phraseanet.SE.logger'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @return int
|
||||
*/
|
||||
private function resolveSubdefUrlTTL(Request $request)
|
||||
{
|
||||
$urlTTL = $request->query->get('subdef_url_ttl');
|
||||
|
||||
if (null !== $urlTTL) {
|
||||
return (int)$urlTTL;
|
||||
}
|
||||
|
||||
return $this->getConf()->get(['registry', 'general', 'default-subdef-url-ttl']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RecordCollection|\record_adapter[] $references
|
||||
* @return RecordView[]
|
||||
*/
|
||||
private function buildRecordViews($references)
|
||||
{
|
||||
if (!$references instanceof RecordCollection) {
|
||||
$references = new RecordCollection($references);
|
||||
}
|
||||
|
||||
$recordViews = [];
|
||||
|
||||
foreach ($references as $index => $record) {
|
||||
$recordViews[$index] = new RecordView($record);
|
||||
}
|
||||
|
||||
return $recordViews;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RecordReferenceInterface[]|RecordReferenceCollection|DataboxGroupable $references
|
||||
* @param array|null $names
|
||||
* @param int $urlTTL
|
||||
* @return SubdefView[][]
|
||||
*/
|
||||
private function buildSubdefsViews($references, array $names = null, $urlTTL)
|
||||
{
|
||||
$subdefGroups = $this->app['service.media_subdef']
|
||||
->findSubdefsByRecordReferenceFromCollection($references, $names);
|
||||
|
||||
$fakeSubdefs = [];
|
||||
|
||||
foreach ($subdefGroups as $index => $subdefGroup) {
|
||||
if (!isset($subdefGroup['thumbnail'])) {
|
||||
$fakeSubdef = new \media_subdef($this->app, $references[$index], 'thumbnail', true, []);
|
||||
$fakeSubdefs[spl_object_hash($fakeSubdef)] = $fakeSubdef;
|
||||
|
||||
$subdefGroups[$index]['thumbnail'] = $fakeSubdef;
|
||||
}
|
||||
}
|
||||
|
||||
$allSubdefs = $this->mergeGroupsIntoOneList($subdefGroups);
|
||||
$allPermalinks = \media_Permalink_Adapter::getMany(
|
||||
$this->app,
|
||||
array_filter($allSubdefs, function (\media_subdef $subdef) use ($fakeSubdefs) {
|
||||
return !isset($fakeSubdefs[spl_object_hash($subdef)]);
|
||||
})
|
||||
);
|
||||
$urls = $this->app['media_accessor.subdef_url_generator']
|
||||
->generateMany($this->getAuthenticatedUser(), $allSubdefs, $urlTTL);
|
||||
|
||||
$subdefViews = [];
|
||||
|
||||
/** @var \media_subdef $subdef */
|
||||
foreach ($allSubdefs as $index => $subdef) {
|
||||
$subdefView = new SubdefView($subdef);
|
||||
|
||||
if (isset($allPermalinks[$index])) {
|
||||
$subdefView->setPermalinkView(new PermalinkView($allPermalinks[$index]));
|
||||
}
|
||||
|
||||
$subdefView->setUrl($urls[$index]);
|
||||
$subdefView->setUrlTTL($urlTTL);
|
||||
|
||||
$subdefViews[spl_object_hash($subdef)] = $subdefView;
|
||||
}
|
||||
|
||||
$reorderedGroups = [];
|
||||
|
||||
/** @var \media_subdef[] $subdefGroup */
|
||||
foreach ($subdefGroups as $index => $subdefGroup) {
|
||||
$reordered = [];
|
||||
|
||||
foreach ($subdefGroup as $subdef) {
|
||||
$reordered[] = $subdefViews[spl_object_hash($subdef)];
|
||||
}
|
||||
|
||||
$reorderedGroups[$index] = $reordered;
|
||||
}
|
||||
|
||||
return $reorderedGroups;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $groups
|
||||
* @return array|mixed
|
||||
*/
|
||||
private function mergeGroupsIntoOneList(array $groups)
|
||||
{
|
||||
// Strips keys from the internal array
|
||||
array_walk($groups, function (array &$group) {
|
||||
$group = array_values($group);
|
||||
});
|
||||
|
||||
if ($groups) {
|
||||
return call_user_func_array('array_merge', $groups);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RecordReferenceInterface[]|DataboxGroupable $references
|
||||
* @return array<int, bool>
|
||||
*/
|
||||
private function retrieveSeeBusinessPerDatabox($references)
|
||||
{
|
||||
if (!$references instanceof DataboxGroupable) {
|
||||
$references = new RecordReferenceCollection($references);
|
||||
}
|
||||
|
||||
$acl = $this->getAclForUser();
|
||||
|
||||
$canSeeBusiness = [];
|
||||
|
||||
foreach ($references->getDataboxIds() as $databoxId) {
|
||||
$canSeeBusiness[$databoxId] = $acl->can_see_business_fields($this->findDataboxById($databoxId));
|
||||
}
|
||||
|
||||
$rights = [];
|
||||
|
||||
foreach ($references as $index => $reference) {
|
||||
$rights[$index] = $canSeeBusiness[$reference->getDataboxId()];
|
||||
}
|
||||
|
||||
return $rights;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RecordView[] $recordViews
|
||||
* @param \caption_record[] $captions
|
||||
* @param bool[] $canSeeBusiness
|
||||
*/
|
||||
private function buildCaptionViews($recordViews, $captions, $canSeeBusiness)
|
||||
{
|
||||
foreach ($recordViews as $index => $recordView) {
|
||||
$caption = $captions[$index];
|
||||
|
||||
$captionView = new CaptionView($caption);
|
||||
|
||||
$captionView->setFields($caption->get_fields(null, isset($canSeeBusiness[$index]) && (bool)$canSeeBusiness[$index]));
|
||||
|
||||
$recordView->setCaption($captionView);
|
||||
}
|
||||
}
|
||||
}
|
@@ -19,8 +19,10 @@ use Alchemy\Phrasea\Core\PhraseaEvents;
|
||||
use Alchemy\Phrasea\Feed\Aggregate;
|
||||
use Alchemy\Phrasea\Feed\Link\AggregateLinkGenerator;
|
||||
use Alchemy\Phrasea\Feed\Link\FeedLinkGenerator;
|
||||
use Alchemy\Phrasea\Model\Entities\Feed;
|
||||
use Alchemy\Phrasea\Model\Entities\FeedEntry;
|
||||
use Alchemy\Phrasea\Model\Entities\FeedItem;
|
||||
use Alchemy\Phrasea\Model\Entities\FeedPublisher;
|
||||
use Alchemy\Phrasea\Model\Repositories\FeedEntryRepository;
|
||||
use Alchemy\Phrasea\Model\Repositories\FeedItemRepository;
|
||||
use Alchemy\Phrasea\Model\Repositories\FeedPublisherRepository;
|
||||
@@ -46,6 +48,7 @@ class FeedController extends Controller
|
||||
}
|
||||
|
||||
public function createFeedEntryAction(Request $request) {
|
||||
/** @var Feed $feed */
|
||||
$feed = $this->getFeedRepository()->find($request->request->get('feed_id'));
|
||||
|
||||
if (null === $feed) {
|
||||
@@ -53,6 +56,8 @@ class FeedController extends Controller
|
||||
}
|
||||
|
||||
$user = $this->getAuthenticatedUser();
|
||||
|
||||
/** @var FeedPublisher $publisher */
|
||||
$publisher = $this->getFeedPublisherRepository()->findOneBy([
|
||||
'feed' => $feed,
|
||||
'user' => $user,
|
||||
|
@@ -136,6 +136,7 @@ class LanguageController
|
||||
'or' => $translator->trans('or'),
|
||||
'Suppr' => $translator->trans('Suppr'),
|
||||
'Add new range' => $translator->trans('Add new range'),
|
||||
'Save as VTT' => $translator->trans('Save as VTT'),
|
||||
'Export ranges' => $translator->trans('Export ranges'),
|
||||
'Start Range' => $translator->trans('Start Range'),
|
||||
'End Range' => $translator->trans('End Range'),
|
||||
|
@@ -12,7 +12,7 @@ namespace Alchemy\Phrasea\Controller\Prod;
|
||||
use Alchemy\Phrasea\Application\Helper\DataboxLoggerAware;
|
||||
use Alchemy\Phrasea\Controller\Controller;
|
||||
use Alchemy\Phrasea\Helper\Record as RecordHelper;
|
||||
use Alchemy\Phrasea\Out\Module\PDF as PDFExport;
|
||||
use Alchemy\Phrasea\Out\Module\PDFRecords;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
@@ -24,19 +24,27 @@ class PrinterController extends Controller
|
||||
{
|
||||
$printer = new RecordHelper\Printer($this->app, $request);
|
||||
|
||||
return $this->render('prod/actions/printer_default.html.twig', ['printer' => $printer, 'message' => '']);
|
||||
$basketFeedbackId = null;
|
||||
if($printer->is_basket() && ($basket = $printer->get_original_basket()) && ($validation = $basket->getValidation())) {
|
||||
if($validation->getInitiator()->getId() === $this->app->getAuthenticatedUser()->getId()) {
|
||||
$basketFeedbackId = $basket->getId();
|
||||
}
|
||||
}
|
||||
|
||||
return $this->render('prod/actions/printer_default.html.twig', ['printer' => $printer, 'message' => '', 'basketFeedbackId' => $basketFeedbackId]);
|
||||
}
|
||||
|
||||
public function printAction(Request $request)
|
||||
{
|
||||
$printer = new RecordHelper\Printer($this->app, $request);
|
||||
$b = $printer->get_original_basket();
|
||||
|
||||
$layout = $request->request->get('lay');
|
||||
|
||||
foreach ($printer->get_elements() as $record) {
|
||||
$this->getDataboxLogger($record->getDatabox())->log($record, \Session_Logger::EVENT_PRINT, $layout, '');
|
||||
}
|
||||
$PDF = new PDFExport($this->app, $printer->get_elements(), $layout);
|
||||
$PDF = new PDFRecords($this->app, $printer, $layout);
|
||||
|
||||
$response = new Response($PDF->render(), 200, array('Content-Type' => 'application/pdf'));
|
||||
$response->headers->set('Pragma', 'public', true);
|
||||
@@ -44,4 +52,5 @@ class PrinterController extends Controller
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -433,24 +433,15 @@ class QueryController extends Controller
|
||||
|
||||
// populates facets (aggregates)
|
||||
$facets = [];
|
||||
// $facetClauses = [];
|
||||
foreach ($result->getFacets() as $facet) {
|
||||
$facetName = $facet['name'];
|
||||
|
||||
if(array_key_exists($facetName, $fieldsInfosByName)) {
|
||||
|
||||
$f = $fieldsInfosByName[$facetName];
|
||||
|
||||
$facet['label'] = $f['trans_label'];
|
||||
$facet['labels'] = $f['labels'];
|
||||
$facet['type'] = strtoupper($f['type']) . "-AGGREGATE";
|
||||
$facets[] = $facet;
|
||||
|
||||
// $facetClauses[] = [
|
||||
// 'type' => strtoupper($f['type']) . "-AGGREGATE",
|
||||
// 'field' => $f['field'],
|
||||
// 'facet' => $facet
|
||||
// ];
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -458,9 +458,9 @@ class AccountController extends Controller
|
||||
->setZipCode($request->request->get("form_zip"))
|
||||
->setPhone($request->request->get("form_phone"))
|
||||
->setFax($request->request->get("form_fax"))
|
||||
->setJob($request->request->get("form_activity"))
|
||||
->setJob($request->request->get("form_function"))
|
||||
->setCompany($request->request->get("form_company"))
|
||||
->setPosition($request->request->get("form_function"))
|
||||
->setPosition($request->request->get("form_activity"))
|
||||
->setNotifications((Boolean) $request->request->get("mail_notifications"));
|
||||
|
||||
$service->updateAccount($command);
|
||||
|
48
lib/Alchemy/Phrasea/ControllerProvider/Api/V3.php
Normal file
48
lib/Alchemy/Phrasea/ControllerProvider/Api/V3.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace Alchemy\Phrasea\ControllerProvider\Api;
|
||||
|
||||
use Alchemy\Phrasea\Application as PhraseaApplication;
|
||||
use Alchemy\Phrasea\Controller\Api\V3Controller;
|
||||
use Alchemy\Phrasea\Core\Event\Listener\OAuthListener;
|
||||
use Silex\Application;
|
||||
use Silex\ControllerCollection;
|
||||
use Silex\ControllerProviderInterface;
|
||||
use Silex\ServiceProviderInterface;
|
||||
|
||||
class V3 extends Api implements ControllerProviderInterface, ServiceProviderInterface
|
||||
{
|
||||
const VERSION = '3.0.0';
|
||||
|
||||
public function register(Application $app)
|
||||
{
|
||||
$app['controller.api.v3'] = $app->share(function (PhraseaApplication $app) {
|
||||
return (new V3Controller($app));
|
||||
});
|
||||
}
|
||||
|
||||
public function boot(Application $app)
|
||||
{
|
||||
}
|
||||
|
||||
public function connect(Application $app)
|
||||
{
|
||||
if (! $this->isApiEnabled($app)) {
|
||||
return $app['controllers_factory'];
|
||||
}
|
||||
|
||||
/** @var ControllerCollection $controllers */
|
||||
$controllers = $app['controllers_factory'];
|
||||
|
||||
$controllers->before(new OAuthListener());
|
||||
|
||||
$controllers->get('/stories/{databox_id}/{record_id}/', 'controller.api.v3:getStoryAction')
|
||||
->before('controller.api.v1:ensureCanAccessToRecord')
|
||||
->assert('databox_id', '\d+')
|
||||
->assert('record_id', '\d+');
|
||||
|
||||
$controllers->match('/search/', 'controller.api.v3:searchAction');
|
||||
|
||||
return $controllers;
|
||||
}
|
||||
}
|
@@ -20,6 +20,7 @@ class DisplaySettingService
|
||||
const ORDER_BY_ADMIN = "ORDER_BY_ADMIN";
|
||||
const ORDER_BY_BCT = "ORDER_BY_BCT";
|
||||
const ORDER_BY_HITS = "ORDER_BY_HITS";
|
||||
const ORDER_BY_HITS_ASC = "ORDER_BY_HITS_ASC";
|
||||
|
||||
/**
|
||||
* The default user settings.
|
||||
@@ -31,7 +32,7 @@ class DisplaySettingService
|
||||
'images_per_page' => '20',
|
||||
'images_size' => '120',
|
||||
'editing_images_size' => '134',
|
||||
'editing_top_box' => '180px',
|
||||
'editing_top_box' => '120px',
|
||||
'editing_right_box' => '400px',
|
||||
'editing_left_box' => '710px',
|
||||
'basket_sort_field' => 'name',
|
||||
|
@@ -15,6 +15,7 @@ use Alchemy\Phrasea\Authentication\Context;
|
||||
use Alchemy\Phrasea\Controller\Api\Result;
|
||||
use Alchemy\Phrasea\ControllerProvider\Api\V1;
|
||||
use Alchemy\Phrasea\ControllerProvider\Api\V2;
|
||||
use Alchemy\Phrasea\ControllerProvider\Api\V3;
|
||||
use Alchemy\Phrasea\Core\Configuration\PropertyAccess;
|
||||
use Alchemy\Phrasea\Core\Event\ApiOAuth2EndEvent;
|
||||
use Alchemy\Phrasea\Core\Event\ApiOAuth2StartEvent;
|
||||
@@ -76,11 +77,13 @@ class OAuthListener
|
||||
// Sets the Api Version
|
||||
|
||||
$CalledController = $request->attributes->get('_controller');
|
||||
if(mb_strpos($CalledController, 'controller.api.v1') !== FALSE){
|
||||
if (mb_strpos($CalledController, 'controller.api.v1') !== FALSE) {
|
||||
$request->attributes->set('api_version', V1::VERSION);
|
||||
}elseif(mb_strpos($CalledController, 'controller.api.v2') !== FALSE){
|
||||
} elseif(mb_strpos($CalledController, 'controller.api.v2') !== FALSE) {
|
||||
$request->attributes->set('api_version', V2::VERSION);
|
||||
}else{
|
||||
} elseif(mb_strpos($CalledController, 'controller.api.v3') !== FALSE) {
|
||||
$request->attributes->set('api_version', V3::VERSION);
|
||||
} else {
|
||||
$request->attributes->set('api_version', $oAuth2Account->getApiVersion());
|
||||
}
|
||||
|
||||
|
@@ -13,7 +13,9 @@ namespace Alchemy\Phrasea\Core\Event\Subscriber;
|
||||
|
||||
use Alchemy\Phrasea\Core\Event\FeedEntryEvent;
|
||||
use Alchemy\Phrasea\Core\PhraseaEvents;
|
||||
use Alchemy\Phrasea\Model\Entities\User;
|
||||
use Alchemy\Phrasea\Model\Entities\WebhookEvent;
|
||||
use Alchemy\Phrasea\Model\Manipulator\TokenManipulator;
|
||||
use Alchemy\Phrasea\Notification\Receiver;
|
||||
use Alchemy\Phrasea\Notification\Mail\MailInfoNewPublication;
|
||||
|
||||
@@ -53,36 +55,43 @@ class FeedEntrySubscriber extends AbstractNotificationSubscriber
|
||||
do {
|
||||
$results = $Query->limit($start, $perLoop)->execute()->get_results();
|
||||
|
||||
foreach ($results as $user_to_notif) {
|
||||
$mailed = false;
|
||||
$users_emailed = []; // for all users
|
||||
$users_to_email = []; // list only users who must be emailed (=create tokens)
|
||||
|
||||
if ($params['notify_email'] && $this->shouldSendNotificationFor($user_to_notif, 'eventsmanager_notify_feed')) {
|
||||
$readyToSend = false;
|
||||
try {
|
||||
$token = $this->app['manipulator.token']->createFeedEntryToken($user_to_notif, $entry);
|
||||
$url = $this->app->url('lightbox', ['LOG' => $token->getValue()]);
|
||||
|
||||
$receiver = Receiver::fromUser($user_to_notif);
|
||||
$readyToSend = true;
|
||||
} catch (\Exception $e) {
|
||||
|
||||
}
|
||||
|
||||
if ($readyToSend) {
|
||||
$mail = MailInfoNewPublication::create($this->app, $receiver);
|
||||
$mail->setButtonUrl($url);
|
||||
$mail->setAuthor($entry->getAuthorName());
|
||||
$mail->setTitle($entry->getTitle());
|
||||
|
||||
$this->deliver($mail);
|
||||
$mailed = true;
|
||||
}
|
||||
/** @var User $user */
|
||||
foreach ($results as $user) {
|
||||
$users_emailed[$user->getId()] = false;
|
||||
if ($params['notify_email'] && $this->shouldSendNotificationFor($user, 'eventsmanager_notify_feed')) {
|
||||
$users_to_email[$user->getId()] = $user;
|
||||
}
|
||||
|
||||
$this->app['events-manager']->notify($user_to_notif->getId(), 'eventsmanager_notify_feed', $datas, $mailed);
|
||||
}
|
||||
|
||||
// get many tokens in one shot
|
||||
$tokens = $this->getTokenManipulator()->createFeedEntryTokens($users_to_email, $entry);
|
||||
foreach($tokens as $token) {
|
||||
try {
|
||||
$url = $this->app->url('lightbox', ['LOG' => $token->getValue()]);
|
||||
$receiver = Receiver::fromUser($token->getUser());
|
||||
|
||||
$mail = MailInfoNewPublication::create($this->app, $receiver);
|
||||
$mail->setButtonUrl($url);
|
||||
$mail->setAuthor($entry->getAuthorName());
|
||||
$mail->setTitle($entry->getTitle());
|
||||
|
||||
$this->deliver($mail);
|
||||
$users_emailed[$token->getUser()->getId()] = true;
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
// no-op
|
||||
}
|
||||
}
|
||||
foreach($users_emailed as $id => $emailed) {
|
||||
$this->app['events-manager']->notify($id, 'eventsmanager_notify_feed', $datas, $emailed);
|
||||
}
|
||||
|
||||
$start += $perLoop;
|
||||
} while (count($results) > 0);
|
||||
}
|
||||
while (count($results) > 0);
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
@@ -91,4 +100,12 @@ class FeedEntrySubscriber extends AbstractNotificationSubscriber
|
||||
PhraseaEvents::FEED_ENTRY_CREATE => 'onCreate',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TokenManipulator
|
||||
*/
|
||||
private function getTokenManipulator()
|
||||
{
|
||||
return $this->app['manipulator.token'];
|
||||
}
|
||||
}
|
||||
|
@@ -9,6 +9,8 @@ use MediaVorus\MediaVorusServiceProvider;
|
||||
use MP4Box\MP4BoxServiceProvider;
|
||||
use Neutron\Silex\Provider\ImagineServiceProvider;
|
||||
use PHPExiftool\PHPExiftoolServiceProvider;
|
||||
use PHPExiftool\Reader;
|
||||
use PHPExiftool\Writer;
|
||||
use Silex\Application;
|
||||
use Silex\ServiceProviderInterface;
|
||||
|
||||
@@ -48,6 +50,21 @@ class MediaUtilitiesMetaServiceProvider implements ServiceProviderInterface
|
||||
|
||||
public function boot(Application $app)
|
||||
{
|
||||
// no-op
|
||||
if(isset($app['exiftool.reader']) && isset($app['conf'])) {
|
||||
try {
|
||||
$timeout = $app['conf']->get(['main', 'binaries', 'exiftool_timeout'], 60);
|
||||
|
||||
/** @var Reader $exiftoolReader */
|
||||
$exiftoolReader = $app['exiftool.reader'];
|
||||
$exiftoolReader->setTimeout($timeout);
|
||||
|
||||
/** @var Writer $exiftoolWriter */
|
||||
$exiftoolWriter = $app['exiftool.writer'];
|
||||
$exiftoolWriter->setTimeout($timeout);
|
||||
}
|
||||
catch(\Exception $e) {
|
||||
// no-nop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -97,7 +97,7 @@ class SearchEngineServiceProvider implements ServiceProviderInterface
|
||||
});
|
||||
|
||||
$app['elasticsearch.facets_response.factory'] = $app->protect(function (array $response) use ($app) {
|
||||
return new FacetsResponse(new Escaper(), $response, $app['search_engine.structure']);
|
||||
return new FacetsResponse($app['elasticsearch.options'], new Escaper(), $response, $app['search_engine.structure']);
|
||||
});
|
||||
|
||||
return $app;
|
||||
@@ -228,7 +228,8 @@ class SearchEngineServiceProvider implements ServiceProviderInterface
|
||||
});
|
||||
|
||||
$app['elasticsearch.options'] = $app->share(function ($app) {
|
||||
$options = ElasticsearchOptions::fromArray($app['conf']->get(['main', 'search-engine', 'options'], []));
|
||||
$conf = $app['conf']->get(['main', 'search-engine', 'options'], []);
|
||||
$options = ElasticsearchOptions::fromArray($conf);
|
||||
|
||||
if (empty($options->getIndexName())) {
|
||||
$options->setIndexName(strtolower(sprintf('phraseanet_%s', str_replace(
|
||||
|
@@ -16,7 +16,8 @@ class Version
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $number = '4.1.0-alpha.19a';
|
||||
|
||||
private $number = '4.1.0-alpha.23a';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
|
@@ -182,7 +182,7 @@ class LegacyRecordRepository implements RecordRepository
|
||||
return $this->mapRecordsFromResultSet($result);
|
||||
}
|
||||
|
||||
public function findChildren(array $storyIds, $user = null)
|
||||
public function findChildren(array $storyIds, $user = null, $offset = 1, $max_items = null)
|
||||
{
|
||||
if (!$storyIds) {
|
||||
return [];
|
||||
@@ -191,26 +191,73 @@ class LegacyRecordRepository implements RecordRepository
|
||||
$connection = $this->databox->get_connection();
|
||||
|
||||
$selects = $this->getRecordSelects();
|
||||
array_unshift($selects, 's.rid_parent as story_id');
|
||||
|
||||
$builder = $connection->createQueryBuilder();
|
||||
$builder
|
||||
->select($selects)
|
||||
->from('regroup', 's')
|
||||
->innerJoin('s', 'record', 'r', 'r.record_id = s.rid_child')
|
||||
->where(
|
||||
's.rid_parent IN (:storyIds)',
|
||||
'r.parent_record_id = 0'
|
||||
)
|
||||
->orderBy('s.ord', 'ASC')
|
||||
->setParameter('storyIds', $storyIds, Connection::PARAM_INT_ARRAY)
|
||||
;
|
||||
if ($max_items) {
|
||||
array_unshift($selects, 'sr.rid_parent as story_id');
|
||||
|
||||
if (null !== $user) {
|
||||
$this->addUserFilter($builder, $user);
|
||||
$subBuilder = $connection->createQueryBuilder();
|
||||
|
||||
$subBuilder
|
||||
->select('s.*,
|
||||
IF(@old_rid_parent != s.rid_parent, @cpt := 1, @cpt := @cpt+1) AS CPT')
|
||||
->addSelect("IF(@old_rid_parent != s.rid_parent, IF(@old_rid_parent:=s.rid_parent,'NEW PARENT',0), '----------') AS Y")
|
||||
->from('regroup', 's')
|
||||
->where('s.rid_parent IN (:storyIds)')
|
||||
->setParameter('storyIds', $storyIds, Connection::PARAM_INT_ARRAY)
|
||||
->orderBy('s.rid_parent, s.ord')
|
||||
;
|
||||
|
||||
$builder = $subBuilder->getConnection()->createQueryBuilder();
|
||||
|
||||
$builder->select($selects)
|
||||
->from(sprintf('( %s )', $subBuilder->getSQL()), 'sr')
|
||||
->innerJoin('sr', 'record', 'r', 'r.record_id = sr.rid_child')
|
||||
->where('sr.CPT BETWEEN :offset AND :maxresult')
|
||||
->andWhere('r.parent_record_id = 0')
|
||||
->setParameter('offset', $offset)
|
||||
->setParameter('maxresult', ($offset + $max_items -1))
|
||||
->orderBy('story_id, sr.CPT')
|
||||
;
|
||||
|
||||
if (null !== $user) {
|
||||
$this->addUserFilter($builder, $user);
|
||||
}
|
||||
|
||||
$connection->executeQuery('SET @cpt = 1');
|
||||
|
||||
$connection->executeQuery('SET @old_rid_parent = -1');
|
||||
|
||||
|
||||
$data = $connection->fetchAll(
|
||||
$builder->getSQL(),
|
||||
array_merge($subBuilder->getParameters(), $builder->getParameters()),
|
||||
array_merge($subBuilder->getParameterTypes(), $builder->getParameterTypes())
|
||||
);
|
||||
|
||||
} else {
|
||||
array_unshift($selects, 's.rid_parent as story_id');
|
||||
|
||||
$builder = $connection->createQueryBuilder();
|
||||
|
||||
$builder
|
||||
->select($selects)
|
||||
->from('regroup', 's')
|
||||
->innerJoin('s', 'record', 'r', 'r.record_id = s.rid_child')
|
||||
->where(
|
||||
's.rid_parent IN (:storyIds)',
|
||||
'r.parent_record_id = 0'
|
||||
)
|
||||
->orderBy('s.ord', 'ASC')
|
||||
->setParameter('storyIds', $storyIds, Connection::PARAM_INT_ARRAY)
|
||||
;
|
||||
|
||||
if (null !== $user) {
|
||||
$this->addUserFilter($builder, $user);
|
||||
}
|
||||
|
||||
$data = $connection->fetchAll($builder->getSQL(), $builder->getParameters(), $builder->getParameterTypes());
|
||||
}
|
||||
|
||||
$data = $connection->fetchAll($builder->getSQL(), $builder->getParameters(), $builder->getParameterTypes());
|
||||
$records = $this->mapRecordsFromResultSet($data);
|
||||
|
||||
$selections = array_map(
|
||||
|
@@ -57,9 +57,11 @@ interface RecordRepository
|
||||
*
|
||||
* @param int[] $storyIds
|
||||
* @param null|int|User $user
|
||||
* @param int $offset
|
||||
* @param null|int $max_items
|
||||
* @return \set_selection[]
|
||||
*/
|
||||
public function findChildren(array $storyIds, $user = null);
|
||||
public function findChildren(array $storyIds, $user = null, $offset = 1, $max_items = null);
|
||||
|
||||
|
||||
/**
|
||||
|
@@ -657,8 +657,8 @@ class Edit extends \Alchemy\Phrasea\Helper\Helper
|
||||
->setEmail($parm['email'])
|
||||
->setAddress($parm['address'])
|
||||
->setZipCode($parm['zip'])
|
||||
->setActivity($parm['function'])
|
||||
->setJob($parm['activite'])
|
||||
->setActivity($parm['activite'])
|
||||
->setJob($parm['function'])
|
||||
->setCompany($parm['company'])
|
||||
->setPhone($parm['telephone'])
|
||||
->setFax($parm['fax']);
|
||||
|
@@ -456,17 +456,27 @@ class Basket
|
||||
}
|
||||
|
||||
public function hasRecord(Application $app, \record_adapter $record)
|
||||
{
|
||||
return !is_null($this->getElementByRecord($app, $record));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Application $app
|
||||
* @param \record_adapter $record
|
||||
* @return BasketElement
|
||||
*/
|
||||
public function getElementByRecord(Application $app, \record_adapter $record)
|
||||
{
|
||||
foreach ($this->getElements() as $basket_element) {
|
||||
$bask_record = $basket_element->getRecord($app);
|
||||
|
||||
if ($bask_record->getRecordId() == $record->getRecordId()
|
||||
&& $bask_record->getDataboxId() == $record->getDataboxId()) {
|
||||
return true;
|
||||
return $basket_element;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getSize(Application $app)
|
||||
|
@@ -15,7 +15,14 @@ use Doctrine\ORM\Mapping as ORM;
|
||||
use Gedmo\Mapping\Annotation as Gedmo;
|
||||
|
||||
/**
|
||||
* @ORM\Table(name="Tokens")
|
||||
* @ORM\Table(name="Tokens",
|
||||
* indexes={
|
||||
* @ORM\index(name="type", columns={"type"}),
|
||||
* @ORM\index(name="created", columns={"created"}),
|
||||
* @ORM\index(name="updated", columns={"updated"}),
|
||||
* @ORM\index(name="expiration", columns={"expiration"})
|
||||
* }
|
||||
* )
|
||||
* @ORM\Entity(repositoryClass="Alchemy\Phrasea\Model\Repositories\TokenRepository")
|
||||
*/
|
||||
class Token
|
||||
|
@@ -30,7 +30,7 @@ class WebhookEventPayload
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @ORM\OneToOne(targetEntity="WebhookEventDelivery")
|
||||
* @ORM\OneToOne(targetEntity="WebhookEventDelivery", inversedBy="payload")
|
||||
* @ORM\JoinColumn(name="delivery_id", referencedColumnName="id")
|
||||
*/
|
||||
private $delivery;
|
||||
|
@@ -22,7 +22,6 @@ use RandomLib\Generator;
|
||||
class TokenManipulator implements ManipulatorInterface
|
||||
{
|
||||
const LETTERS_AND_NUMBERS = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
const TYPE_FEED_ENTRY = 'FEED_ENTRY';
|
||||
const TYPE_PASSWORD = 'password';
|
||||
const TYPE_ACCOUNT_UNLOCK = 'account-unlock';
|
||||
@@ -126,6 +125,38 @@ class TokenManipulator implements ManipulatorInterface
|
||||
return $this->create($user, self::TYPE_FEED_ENTRY, null, $entry->getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create feedEntryTokens for many users in one shot
|
||||
*
|
||||
* @param User[] $users
|
||||
* @param FeedEntry $entry
|
||||
* @return Token[]
|
||||
* @throws \Doctrine\DBAL\DBALException
|
||||
*/
|
||||
public function createFeedEntryTokens($users, FeedEntry $entry)
|
||||
{
|
||||
// $this->removeExpiredTokens();
|
||||
|
||||
$tokens = [];
|
||||
foreach ($users as $user) {
|
||||
$value = $this->random->generateString(32, self::LETTERS_AND_NUMBERS) . $user->getId();
|
||||
|
||||
$token = new Token();
|
||||
$token->setUser($user)
|
||||
->setType(self::TYPE_FEED_ENTRY)
|
||||
->setValue($value)
|
||||
->setExpiration(null)
|
||||
->setData($entry->getId());
|
||||
$tokens[] = $token;
|
||||
|
||||
$this->om->persist($token);
|
||||
}
|
||||
$this->om->flush();
|
||||
$this->om->clear();
|
||||
|
||||
return $tokens;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $user
|
||||
* @param $data
|
||||
|
@@ -368,7 +368,7 @@ class UserManipulator implements ManipulatorInterface
|
||||
throw new InvalidArgumentException(sprintf('Email %s is not legal.', $email));
|
||||
}
|
||||
|
||||
if (null !== $this->repository->findByEmail($email)) {
|
||||
if (($email !== null) && (null !== $this->repository->findByEmail($email))) {
|
||||
throw new RuntimeException(sprintf('User with email %s already exists.', $email));
|
||||
}
|
||||
|
||||
|
@@ -232,7 +232,7 @@ class BasketRepository extends EntityRepository
|
||||
$dql = "SELECT b\n"
|
||||
. "FROM Phraseanet:Basket b\n"
|
||||
. " JOIN b.elements e\n"
|
||||
. "WHERE b.user = :usr_id AND b.pusher_id IS NOT NULL";
|
||||
. "WHERE b.user = :usr_id AND b.pusher IS NOT NULL";
|
||||
$params = [
|
||||
'usr_id' => $user->getId()
|
||||
];
|
||||
|
@@ -72,4 +72,9 @@ class TokenRepository extends EntityRepository
|
||||
|
||||
return $query->getResult();
|
||||
}
|
||||
|
||||
public function getEntityManager()
|
||||
{
|
||||
return parent::getEntityManager();
|
||||
}
|
||||
}
|
||||
|
@@ -122,4 +122,15 @@ class UserRepository extends EntityRepository
|
||||
{
|
||||
return $this->findBy(['templateOwner' => $user->getId()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds all templates
|
||||
*/
|
||||
public function findTemplate()
|
||||
{
|
||||
$qb = $this->createQueryBuilder('u');
|
||||
$qb->where('u.templateOwner is NOT NULL');
|
||||
|
||||
return $qb->getQuery()->getResult();
|
||||
}
|
||||
}
|
||||
|
@@ -20,6 +20,8 @@ class PDF
|
||||
protected $records;
|
||||
protected $pdf;
|
||||
|
||||
const LAYOUT_FEEDBACK = 'feedback';
|
||||
const LAYOUT_FEEDBACKONLY = 'feedbackOnly';
|
||||
const LAYOUT_PREVIEW = 'preview';
|
||||
const LAYOUT_PREVIEWCAPTION = 'previewCaption';
|
||||
const LAYOUT_PREVIEWCAPTIONTDM = 'previewCaptionTdm';
|
||||
@@ -27,64 +29,10 @@ class PDF
|
||||
const LAYOUT_THUMBNAILGRID = 'thumbnailGrid';
|
||||
const LAYOUT_CAPTION = 'caption';
|
||||
|
||||
public function __construct(Application $app, array $records, $layout)
|
||||
public function __construct(Application $app)
|
||||
{
|
||||
$this->app = $app;
|
||||
|
||||
$list = [];
|
||||
|
||||
foreach ($records as $record) {
|
||||
switch ($layout) {
|
||||
default:
|
||||
throw new \Exception('Unknown layout');
|
||||
break;
|
||||
case self::LAYOUT_PREVIEW:
|
||||
case self::LAYOUT_PREVIEWCAPTION:
|
||||
case self::LAYOUT_PREVIEWCAPTIONTDM:
|
||||
try {
|
||||
$subdef = $record->get_subdef('preview');
|
||||
// fallback to thumbnail ( video, sound, doc ) ..
|
||||
if ($subdef->get_type() !== \media_subdef::TYPE_IMAGE) {
|
||||
$subdef = $record->get_thumbnail();
|
||||
}
|
||||
|
||||
if (!$subdef->is_physically_present()) {
|
||||
continue 2;
|
||||
}
|
||||
|
||||
if ($subdef->get_type() !== \media_subdef::TYPE_IMAGE) {
|
||||
continue 2;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
continue 2;
|
||||
}
|
||||
break;
|
||||
case self::LAYOUT_THUMBNAILLIST:
|
||||
case self::LAYOUT_THUMBNAILGRID:
|
||||
try {
|
||||
$subdef = $record->get_thumbnail();
|
||||
if (!$subdef->is_physically_present()) {
|
||||
continue 2;
|
||||
}
|
||||
|
||||
if ($subdef->get_type() !== \media_subdef::TYPE_IMAGE) {
|
||||
continue 2;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
continue 2;
|
||||
}
|
||||
break;
|
||||
case self::LAYOUT_CAPTION:
|
||||
break;
|
||||
}
|
||||
|
||||
$record->setNumber(count($list) + 1);
|
||||
|
||||
$list[] = $record;
|
||||
}
|
||||
|
||||
$this->records = $list;
|
||||
|
||||
$pdf = new PhraseaPDF("P", "mm", "A4", true, 'UTF-8', false);
|
||||
|
||||
$pdf->SetAuthor("Phraseanet");
|
||||
@@ -92,29 +40,6 @@ class PDF
|
||||
$pdf->SetDisplayMode("fullpage", "single");
|
||||
|
||||
$this->pdf = $pdf;
|
||||
|
||||
switch ($layout) {
|
||||
case self::LAYOUT_PREVIEW:
|
||||
$this->print_preview(false, false);
|
||||
break;
|
||||
case self::LAYOUT_PREVIEWCAPTION:
|
||||
$this->print_preview(false, true);
|
||||
break;
|
||||
case self::LAYOUT_PREVIEWCAPTIONTDM:
|
||||
$this->print_preview(true, true);
|
||||
break;
|
||||
case self::LAYOUT_THUMBNAILLIST:
|
||||
$this->print_thumbnailList();
|
||||
break;
|
||||
case self::LAYOUT_THUMBNAILGRID:
|
||||
$this->print_thumbnailGrid();
|
||||
break;
|
||||
case self::LAYOUT_CAPTION:
|
||||
$this->print_caption();
|
||||
break;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function render()
|
||||
@@ -123,447 +48,4 @@ class PDF
|
||||
|
||||
return $this->pdf->Output('', 'S');
|
||||
}
|
||||
|
||||
protected function print_thumbnailGrid($links = false)
|
||||
{
|
||||
$NDiapoW = 3;
|
||||
$NDiapoH = 4;
|
||||
|
||||
$this->pdf->AddPage();
|
||||
|
||||
$oldMargins = $this->pdf->getMargins();
|
||||
$tmargin = $oldMargins['top'];
|
||||
$lmargin = $oldMargins['left'];
|
||||
$bmargin = $oldMargins['bottom'];
|
||||
$rmargin = $oldMargins['right'];
|
||||
|
||||
$this->pdf->SetLeftMargin($lmargin + 55);
|
||||
|
||||
$clientW = $this->pdf->getPageWidth() - $lmargin - $rmargin;
|
||||
$clientH = $this->pdf->getPageHeight() - $tmargin - $bmargin;
|
||||
|
||||
$DiapoW = floor($clientW / $NDiapoW);
|
||||
$DiapoH = floor($clientH / $NDiapoH);
|
||||
$TitleH = 5;
|
||||
$ImgSize = min($DiapoW, ($DiapoH - $TitleH)) - 5;
|
||||
|
||||
$npages = ceil(count($this->records) / ($NDiapoW * $NDiapoH));
|
||||
|
||||
$irow = $ipage = 0;
|
||||
$icol = -1;
|
||||
foreach ($this->records as $rec) {
|
||||
/* @var \record_adapter $rec */
|
||||
if (++$icol >= $NDiapoW) {
|
||||
$icol = 0;
|
||||
if (++$irow >= $NDiapoH) {
|
||||
$irow = 0;
|
||||
$ipage++;
|
||||
$this->pdf->AddPage();
|
||||
}
|
||||
}
|
||||
$fimg = null;
|
||||
$himg = 0;
|
||||
|
||||
$subdef = $rec->get_subdef('preview');
|
||||
|
||||
if ($subdef->get_type() !== \media_subdef::TYPE_IMAGE) {
|
||||
$subdef = $rec->get_thumbnail();
|
||||
}
|
||||
|
||||
$fimg = $subdef->getRealPath();
|
||||
|
||||
if (!$this->app->getAclForUser($this->app->getAuthenticatedUser())->has_right_on_base($rec->getBaseId(), \ACL::NOWATERMARK)
|
||||
&& $subdef->get_type() == \media_subdef::TYPE_IMAGE) {
|
||||
$fimg = \recordutils_image::watermark($this->app, $subdef);
|
||||
}
|
||||
|
||||
$wimg = $himg = $ImgSize;
|
||||
if ($subdef->get_height() > 0 && $subdef->get_width() > 0) {
|
||||
if ($subdef->get_width() > $subdef->get_height())
|
||||
$himg = $wimg * $subdef->get_height() / $subdef->get_width();
|
||||
else
|
||||
$wimg = $himg * $subdef->get_width() / $subdef->get_height();
|
||||
}
|
||||
|
||||
if ($fimg) {
|
||||
$x = $lmargin + ($icol * $DiapoW);
|
||||
$y = $tmargin + ($irow * $DiapoH);
|
||||
$this->pdf->SetDrawColor(0);
|
||||
$this->pdf->Rect($x, $y, $DiapoW, $DiapoH, "D");
|
||||
|
||||
$this->pdf->SetXY($x, $y + 1);
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, '', 10);
|
||||
$t = $irow . '-' . $x;
|
||||
$t = $rec->get_title();
|
||||
|
||||
if ($links) {
|
||||
$lk = $this->pdf->AddLink();
|
||||
$this->pdf->SetLink($lk, 0, $npages + $rec->getNumber());
|
||||
$this->pdf->Image(
|
||||
$fimg
|
||||
, $x + (($DiapoW - $wimg) / 2)
|
||||
, $TitleH + $y + (($DiapoH - $TitleH - $himg) / 2)
|
||||
, $wimg, $himg
|
||||
, null, $lk
|
||||
);
|
||||
} else {
|
||||
$this->pdf->Image($fimg
|
||||
, $x + (($DiapoW - $wimg) / 2)
|
||||
, $TitleH + $y + (($DiapoH - $TitleH - $himg) / 2)
|
||||
, $wimg, $himg
|
||||
);
|
||||
}
|
||||
|
||||
$this->pdf->MultiCell($DiapoW, $TitleH, $t, '0', 'C', false);
|
||||
}
|
||||
}
|
||||
$this->pdf->SetLeftMargin($oldMargins['left']);
|
||||
}
|
||||
|
||||
protected function print_thumbnailList()
|
||||
{
|
||||
$this->pdf->AddPage();
|
||||
$oldMargins = $this->pdf->getMargins();
|
||||
|
||||
$lmargin = $oldMargins['left'];
|
||||
$rmargin = $oldMargins['right'];
|
||||
|
||||
$this->pdf->SetLeftMargin($lmargin + 55);
|
||||
|
||||
$ndoc = 0;
|
||||
foreach ($this->records as $rec) {
|
||||
/* @var \record_adapter $rec */
|
||||
$subdef = $rec->get_subdef('thumbnail');
|
||||
|
||||
$fimg = $subdef->getRealPath();
|
||||
|
||||
$wimg = $himg = 50;
|
||||
// 1px = 3.77952 mm
|
||||
$finalWidth = round($subdef->get_width() / 3.779528, 2);
|
||||
$finalHeight = round($subdef->get_height() / 3.779528, 2);
|
||||
$aspectH = $finalWidth/$finalHeight;
|
||||
$aspectW = $finalHeight/$finalWidth;
|
||||
|
||||
if ($finalWidth > 0 && $finalHeight > 0) {
|
||||
if ($finalWidth > $finalHeight && $finalWidth > $wimg) {
|
||||
$finalWidth = $wimg;
|
||||
$finalHeight = $wimg * $aspectW;
|
||||
} else if ($finalHeight > $finalWidth && $finalHeight > $himg) {
|
||||
$finalHeight = $himg;
|
||||
$finalWidth = $himg * $aspectH;
|
||||
} else if ($finalHeight == $finalWidth & $finalWidth > $wimg) {
|
||||
$finalHeight = $wimg;
|
||||
$finalWidth = $himg;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->pdf->GetY() > $this->pdf->getPageHeight() - (6 + $finalHeight + 20))
|
||||
$this->pdf->AddPage();
|
||||
|
||||
$title = "record : " . $rec->get_title();
|
||||
|
||||
$y = $this->pdf->GetY();
|
||||
|
||||
$t = \phrasea::bas_labels($rec->getBaseId(), $this->app);
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, '', 10);
|
||||
$this->pdf->SetFillColor(220, 220, 220);
|
||||
$this->pdf->SetLeftMargin($lmargin);
|
||||
$this->pdf->SetRightMargin($rmargin);
|
||||
$this->pdf->SetX($lmargin);
|
||||
$this->pdf->SetY($y);
|
||||
|
||||
$this->pdf->out = false;
|
||||
$this->pdf->MultiCell(140, 4, $title, "LTR", "L", 1);
|
||||
$y2 = $this->pdf->GetY();
|
||||
$h = $y2 - $y;
|
||||
$this->pdf->out = true;
|
||||
$this->pdf->SetX($lmargin);
|
||||
$this->pdf->SetY($y);
|
||||
$this->pdf->Cell(0, $h, "", "LTR", 1, "R", 1);
|
||||
$this->pdf->SetX($lmargin);
|
||||
$this->pdf->SetY($y);
|
||||
$this->pdf->Cell(0, 4, $t, "", 1, "R");
|
||||
$this->pdf->SetX($lmargin);
|
||||
$this->pdf->SetY($y);
|
||||
$this->pdf->MultiCell(140, 4, $title, "", "L");
|
||||
$this->pdf->SetX($lmargin);
|
||||
$this->pdf->SetY($y = $y2);
|
||||
|
||||
$this->pdf->SetLeftMargin($lmargin + 55);
|
||||
$this->pdf->SetY($y + 2);
|
||||
|
||||
if ($fimg) {
|
||||
$y = $this->pdf->GetY();
|
||||
$this->pdf->Image($fimg, $lmargin, $y, $finalWidth, $finalHeight);
|
||||
$this->pdf->SetY($y + 3);
|
||||
}
|
||||
|
||||
$nf = 0;
|
||||
$this->pdf->SetX($lmargin + 55);
|
||||
$p0 = $this->pdf->PageNo();
|
||||
$y0 = $this->pdf->GetY();
|
||||
foreach ($rec->get_caption()->get_fields() as $field) {
|
||||
/* @var $field caption_field */
|
||||
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, 'B', 12);
|
||||
$this->pdf->Write(5, $field->get_name() . " : ");
|
||||
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, '', 12);
|
||||
$this->pdf->Write(5, $field->get_serialized_values());
|
||||
|
||||
$this->pdf->Write(6, "\n");
|
||||
$nf++;
|
||||
}
|
||||
if ($this->pdf->PageNo() == $p0 && ($this->pdf->GetY() - $y0) < $finalHeight)
|
||||
$this->pdf->SetY($y0 + $finalHeight);
|
||||
$ndoc++;
|
||||
}
|
||||
$this->pdf->SetLeftMargin($lmargin);
|
||||
}
|
||||
|
||||
protected function print_caption()
|
||||
{
|
||||
$this->pdf->AddPage();
|
||||
$oldMargins = $this->pdf->getMargins();
|
||||
|
||||
$lmargin = $oldMargins['left'];
|
||||
$rmargin = $oldMargins['right'];
|
||||
|
||||
foreach ($this->records as $rec) {
|
||||
$title = "record : " . $rec->get_title();
|
||||
|
||||
$y = $this->pdf->GetY();
|
||||
if($this->pdf->getPageHeight() - $y < 20){ // height of the footer is 15
|
||||
$this->pdf->AddPage();
|
||||
$y = $oldMargins['top'];
|
||||
}
|
||||
|
||||
$t = \phrasea::bas_labels($rec->getBaseId(), $this->app);
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, '', 10);
|
||||
$this->pdf->SetFillColor(220, 220, 220);
|
||||
$this->pdf->SetLeftMargin($lmargin);
|
||||
$this->pdf->SetRightMargin($rmargin);
|
||||
$this->pdf->SetX($lmargin);
|
||||
$this->pdf->SetY($y);
|
||||
|
||||
$this->pdf->out = false;
|
||||
$this->pdf->MultiCell(140, 4, $title, "LTR", "L", 1);
|
||||
$y2 = $this->pdf->GetY();
|
||||
$h = $y2 - $y;
|
||||
$this->pdf->out = true;
|
||||
$this->pdf->SetX($lmargin);
|
||||
$this->pdf->SetY($y);
|
||||
$this->pdf->Cell(0, $h, "", "LTR", 1, "R", 1);
|
||||
$this->pdf->SetX($lmargin);
|
||||
$this->pdf->SetY($y);
|
||||
$this->pdf->Cell(0, 4, $t, "", 1, "R");
|
||||
$this->pdf->SetX($lmargin);
|
||||
$this->pdf->SetY($y);
|
||||
$this->pdf->MultiCell(140, 4, $title, "", "L");
|
||||
$this->pdf->SetX($lmargin);
|
||||
$this->pdf->SetY($y = $y2);
|
||||
$this->pdf->SetY($y + 2);
|
||||
|
||||
foreach ($rec->get_caption()->get_fields() as $field) {
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, 'B', 12);
|
||||
$this->pdf->Write(5, $field->get_name() . " : ");
|
||||
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, '', 12);
|
||||
$t = str_replace(
|
||||
["<", ">", "&"]
|
||||
, ["<", ">", "&"]
|
||||
, strip_tags($field->get_serialized_values())
|
||||
);
|
||||
$this->pdf->Write(5, $t);
|
||||
|
||||
$this->pdf->Write(6, "\n");
|
||||
}
|
||||
$this->pdf->SetY($this->pdf->GetY() + 10);
|
||||
}
|
||||
}
|
||||
|
||||
protected function print_preview($withtdm, $write_caption)
|
||||
{
|
||||
if ($withtdm === true) {
|
||||
$this->print_thumbnailGrid($this->pdf, $this->records, true);
|
||||
}
|
||||
|
||||
foreach ($this->records as $krec => $rec) {
|
||||
/* @var \record_adapter $rec */
|
||||
|
||||
$this->pdf->AddPage();
|
||||
|
||||
if ($withtdm === "CALCPAGES") {
|
||||
$rec->setNumber($this->pdf->PageNo());
|
||||
}
|
||||
$lmargin = $this->pdf->GetX();
|
||||
$himg = 0;
|
||||
$y = 0;
|
||||
$miniConv = NULL;
|
||||
|
||||
$LEFT__TEXT = "";
|
||||
$LEFT__IMG = NULL;
|
||||
$RIGHT_TEXT = "";
|
||||
$RIGHT_IMG = NULL;
|
||||
|
||||
$LEFT__IMG = $this->app['root.path'] . "/config/minilogos/logopdf_" . $rec->getDataboxId() . ".jpg";
|
||||
|
||||
if (!is_file($LEFT__IMG)) {
|
||||
$databox = $rec->getDatabox();
|
||||
$str = $databox->get_sxml_structure();
|
||||
$vn = (string) ($str->pdfPrintLogo);
|
||||
if (($vn * 1) == 1) {
|
||||
$LEFT__TEXT = $databox->get_label($this->app['locale']);
|
||||
}
|
||||
}
|
||||
|
||||
$collection = \collection::getByBaseId($this->app, $rec->getBaseId());
|
||||
|
||||
$vn = "";
|
||||
if (false !== $str = simplexml_load_string($collection->get_prefs())) {
|
||||
$vn = (string) ($str->pdfPrintappear);
|
||||
}
|
||||
|
||||
if ($vn == "" || $vn == "1") {
|
||||
$RIGHT_TEXT = \phrasea::bas_labels($rec->getBaseId(), $this->app);
|
||||
} elseif ($vn == "2") {
|
||||
$RIGHT_IMG = $this->app['root.path'] . "/config/minilogos/" . $rec->getBaseId();
|
||||
}
|
||||
|
||||
$xtmp = $this->pdf->GetX();
|
||||
$ytmp = $this->pdf->GetY();
|
||||
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, '', 12);
|
||||
$this->pdf->SetFillColor(220, 220, 220);
|
||||
$y = $this->pdf->GetY();
|
||||
$this->pdf->MultiCell(95, 7, $LEFT__TEXT, "LTB", "L", 1);
|
||||
$y2 = $this->pdf->GetY();
|
||||
$h = $y2 - $y;
|
||||
$this->pdf->SetY($y);
|
||||
$this->pdf->SetX(105);
|
||||
$this->pdf->Cell(95, $h, $RIGHT_TEXT, "TBR", 1, "R", 1);
|
||||
|
||||
if ($LEFT__TEXT == "" && is_file($LEFT__IMG)) {
|
||||
if ($size = @getimagesize($LEFT__IMG)) {
|
||||
$wmm = (int) $size[0] * 25.4 / 72;
|
||||
$hmm = (int) $size[1] * 25.4 / 72;
|
||||
if ($hmm > 6) {
|
||||
$coeff = $hmm / 6;
|
||||
$wmm = (int) $wmm / $coeff;
|
||||
$hmm = (int) $hmm / $coeff;
|
||||
}
|
||||
$this->pdf->Image($LEFT__IMG, $xtmp + 0.5, $ytmp + 0.5, $wmm, $hmm);
|
||||
}
|
||||
}
|
||||
|
||||
if ($RIGHT_IMG != NULL && is_file($RIGHT_IMG)) {
|
||||
if ($size = @getimagesize($RIGHT_IMG)) {
|
||||
|
||||
if ($size[2] == '1') {
|
||||
if (!isset($miniConv[$RIGHT_IMG])) {
|
||||
$tmp_filename = tempnam('minilogos/', 'gif4fpdf');
|
||||
$img = imagecreatefromgif($RIGHT_IMG);
|
||||
imageinterlace($img, 0);
|
||||
imagepng($img, $tmp_filename);
|
||||
rename($tmp_filename, $tmp_filename . '.png');
|
||||
$miniConv[$RIGHT_IMG] = $tmp_filename . '.png';
|
||||
$RIGHT_IMG = $tmp_filename . '.png';
|
||||
} else
|
||||
$RIGHT_IMG = $miniConv[$RIGHT_IMG];
|
||||
|
||||
$wmm = (int) $size[0] * 25.4 / 72;
|
||||
$hmm = (int) $size[1] * 25.4 / 72;
|
||||
if ($hmm > 6) {
|
||||
$coeff = $hmm / 6;
|
||||
$wmm = (int) $wmm / $coeff;
|
||||
$hmm = (int) $hmm / $coeff;
|
||||
}
|
||||
$tt = 0;
|
||||
if ($hmm < 6)
|
||||
$tt = (6 - $hmm) / 2;
|
||||
$this->pdf->Image($RIGHT_IMG, 200 - 0.5 - $wmm, $ytmp + 0.5 + $tt);
|
||||
} else {
|
||||
$wmm = (int) $size[0] * 25.4 / 72;
|
||||
$hmm = (int) $size[1] * 25.4 / 72;
|
||||
if ($hmm > 6) {
|
||||
$coeff = $hmm / 6;
|
||||
$wmm = (int) $wmm / $coeff;
|
||||
$hmm = (int) $hmm / $coeff;
|
||||
}
|
||||
$this->pdf->Image($RIGHT_IMG, 200 - 0.5 - $wmm, $ytmp + 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$y = $this->pdf->GetY() + 5;
|
||||
|
||||
$subdef = $rec->get_subdef('preview');
|
||||
|
||||
if ($subdef->get_type() !== \media_subdef::TYPE_IMAGE) {
|
||||
$subdef = $rec->get_thumbnail();
|
||||
}
|
||||
|
||||
$f = $subdef->getRealPath();
|
||||
|
||||
if (!$this->app->getAclForUser($this->app->getAuthenticatedUser())->has_right_on_base($rec->getBaseId(), \ACL::NOWATERMARK)
|
||||
&& $subdef->get_type() == \media_subdef::TYPE_IMAGE)
|
||||
$f = \recordutils_image::watermark($this->app, $subdef);
|
||||
|
||||
// original height / original width x new width = new height
|
||||
$wimg = $himg = 150; // preview dans un carre de 150 mm
|
||||
// 1px = 3.77952 mm
|
||||
$finalWidth = round($subdef->get_width() / 3.779528, 2);
|
||||
$finalHeight = round($subdef->get_height() / 3.779528, 2);
|
||||
$aspectH = $finalWidth/$finalHeight;
|
||||
$aspectW = $finalHeight/$finalWidth;
|
||||
|
||||
if ($finalWidth > 0 && $finalHeight > 0) {
|
||||
if ($finalWidth > $finalHeight && $finalWidth > $wimg) {
|
||||
$finalWidth = $wimg;
|
||||
$finalHeight = $wimg * $aspectW;
|
||||
} else if ($finalHeight > $finalWidth && $finalHeight > $himg) {
|
||||
$finalHeight = $himg;
|
||||
$finalWidth = $himg * $aspectH;
|
||||
} else if ($finalHeight == $finalWidth & $finalWidth > $wimg) {
|
||||
$finalHeight = $wimg;
|
||||
$finalWidth = $himg;
|
||||
}
|
||||
}
|
||||
|
||||
$this->pdf->Image($f, (210 - $finalWidth) / 2, $y, $finalWidth, $finalHeight);
|
||||
|
||||
if ($miniConv != NULL) {
|
||||
foreach ($miniConv as $oneF)
|
||||
unlink($oneF);
|
||||
}
|
||||
$this->pdf->SetXY($lmargin, $y += ( $finalHeight + 5));
|
||||
|
||||
$nf = 0;
|
||||
if ($write_caption) {
|
||||
foreach ($rec->get_caption()->get_fields() as $field) {
|
||||
/* @var $field caption_field */
|
||||
if ($nf > 0) {
|
||||
$this->pdf->Write(6, "\n");
|
||||
}
|
||||
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, 'B', 12);
|
||||
$this->pdf->Write(5, $field->get_name() . " : ");
|
||||
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, '', 12);
|
||||
|
||||
$t = str_replace(
|
||||
["<", ">", "&"]
|
||||
, ["<", ">", "&"]
|
||||
, strip_tags($field->get_serialized_values())
|
||||
);
|
||||
|
||||
$this->pdf->Write(5, $t);
|
||||
|
||||
$nf++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
789
lib/Alchemy/Phrasea/Out/Module/PDFRecords.php
Normal file
789
lib/Alchemy/Phrasea/Out/Module/PDFRecords.php
Normal file
@@ -0,0 +1,789 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Out\Module;
|
||||
|
||||
use Alchemy\Phrasea\Application;
|
||||
use Alchemy\Phrasea\Out\Tool\PhraseaPDF;
|
||||
use Alchemy\Phrasea\Helper\Record\Printer;
|
||||
use Alchemy\Phrasea\Model\Entities\ValidationParticipant;
|
||||
use \IntlDateFormatter as DateFormatter;
|
||||
|
||||
class PDFRecords extends PDF
|
||||
{
|
||||
/** @var Printer */
|
||||
private $printer;
|
||||
|
||||
public function __construct(Application $app, Printer $printer, $layout)
|
||||
{
|
||||
parent::__construct($app);
|
||||
$this->printer = $printer;
|
||||
|
||||
$records = $printer->get_elements();
|
||||
|
||||
$list = [];
|
||||
|
||||
foreach ($records as $record) {
|
||||
switch ($layout) {
|
||||
default:
|
||||
throw new \Exception('Unknown layout');
|
||||
break;
|
||||
case self::LAYOUT_FEEDBACK:
|
||||
case self::LAYOUT_FEEDBACKONLY:
|
||||
case self::LAYOUT_PREVIEW:
|
||||
case self::LAYOUT_PREVIEWCAPTION:
|
||||
case self::LAYOUT_PREVIEWCAPTIONTDM:
|
||||
try {
|
||||
$subdef = $record->get_subdef('preview');
|
||||
// fallback to thumbnail ( video, sound, doc ) ..
|
||||
if ($subdef->get_type() !== \media_subdef::TYPE_IMAGE) {
|
||||
$subdef = $record->get_thumbnail();
|
||||
}
|
||||
|
||||
if (!$subdef->is_physically_present()) {
|
||||
continue 2;
|
||||
}
|
||||
|
||||
if ($subdef->get_type() !== \media_subdef::TYPE_IMAGE) {
|
||||
continue 2;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
continue 2;
|
||||
}
|
||||
break;
|
||||
case self::LAYOUT_THUMBNAILLIST:
|
||||
case self::LAYOUT_THUMBNAILGRID:
|
||||
try {
|
||||
$subdef = $record->get_thumbnail();
|
||||
if (!$subdef->is_physically_present()) {
|
||||
continue 2;
|
||||
}
|
||||
|
||||
if ($subdef->get_type() !== \media_subdef::TYPE_IMAGE) {
|
||||
continue 2;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
continue 2;
|
||||
}
|
||||
break;
|
||||
case self::LAYOUT_CAPTION:
|
||||
break;
|
||||
}
|
||||
|
||||
$record->setNumber(count($list) + 1);
|
||||
|
||||
$list[] = $record;
|
||||
}
|
||||
|
||||
$this->records = $list;
|
||||
|
||||
switch ($layout) {
|
||||
case self::LAYOUT_FEEDBACK:
|
||||
$this->print_preview(false, true, true);
|
||||
break;
|
||||
case self::LAYOUT_FEEDBACKONLY:
|
||||
$this->print_preview(false, false, true);
|
||||
break;
|
||||
case self::LAYOUT_PREVIEW:
|
||||
$this->print_preview(false, false, false);
|
||||
break;
|
||||
case self::LAYOUT_PREVIEWCAPTION:
|
||||
$this->print_preview(false, true, false);
|
||||
break;
|
||||
case self::LAYOUT_PREVIEWCAPTIONTDM:
|
||||
$this->print_preview(true, true, false);
|
||||
break;
|
||||
case self::LAYOUT_THUMBNAILLIST:
|
||||
$this->print_thumbnailList();
|
||||
break;
|
||||
case self::LAYOUT_THUMBNAILGRID:
|
||||
$this->print_thumbnailGrid();
|
||||
break;
|
||||
case self::LAYOUT_CAPTION:
|
||||
$this->print_caption();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected function print_thumbnailGrid($links = false)
|
||||
{
|
||||
$NDiapoW = 3;
|
||||
$NDiapoH = 4;
|
||||
|
||||
$this->pdf->AddPage();
|
||||
|
||||
$oldMargins = $this->pdf->getMargins();
|
||||
$tmargin = $oldMargins['top'];
|
||||
$lmargin = $oldMargins['left'];
|
||||
$bmargin = $oldMargins['bottom'];
|
||||
$rmargin = $oldMargins['right'];
|
||||
|
||||
$this->pdf->SetLeftMargin($lmargin + 55);
|
||||
|
||||
$clientW = $this->pdf->getPageWidth() - $lmargin - $rmargin;
|
||||
$clientH = $this->pdf->getPageHeight() - $tmargin - $bmargin;
|
||||
|
||||
$DiapoW = floor($clientW / $NDiapoW);
|
||||
$DiapoH = floor($clientH / $NDiapoH);
|
||||
$TitleH = 5;
|
||||
$ImgSize = min($DiapoW, ($DiapoH - $TitleH)) - 5;
|
||||
|
||||
$npages = ceil(count($this->records) / ($NDiapoW * $NDiapoH));
|
||||
|
||||
$irow = $ipage = 0;
|
||||
$icol = -1;
|
||||
foreach ($this->records as $rec) {
|
||||
/* @var \record_adapter $rec */
|
||||
if (++$icol >= $NDiapoW) {
|
||||
$icol = 0;
|
||||
if (++$irow >= $NDiapoH) {
|
||||
$irow = 0;
|
||||
$ipage++;
|
||||
$this->pdf->AddPage();
|
||||
}
|
||||
}
|
||||
$fimg = null;
|
||||
$himg = 0;
|
||||
|
||||
$subdef = $rec->get_subdef('preview');
|
||||
|
||||
if ($subdef->get_type() !== \media_subdef::TYPE_IMAGE) {
|
||||
$subdef = $rec->get_thumbnail();
|
||||
}
|
||||
|
||||
$fimg = $subdef->getRealPath();
|
||||
|
||||
if (!$this->app->getAclForUser($this->app->getAuthenticatedUser())->has_right_on_base($rec->getBaseId(), \ACL::NOWATERMARK)
|
||||
&& $subdef->get_type() == \media_subdef::TYPE_IMAGE) {
|
||||
$fimg = \recordutils_image::watermark($this->app, $subdef);
|
||||
}
|
||||
|
||||
$wimg = $himg = $ImgSize;
|
||||
if ($subdef->get_height() > 0 && $subdef->get_width() > 0) {
|
||||
if ($subdef->get_width() > $subdef->get_height())
|
||||
$himg = $wimg * $subdef->get_height() / $subdef->get_width();
|
||||
else
|
||||
$wimg = $himg * $subdef->get_width() / $subdef->get_height();
|
||||
}
|
||||
|
||||
if ($fimg) {
|
||||
$x = $lmargin + ($icol * $DiapoW);
|
||||
$y = $tmargin + ($irow * $DiapoH);
|
||||
$this->pdf->SetDrawColor(0);
|
||||
$this->pdf->Rect($x, $y, $DiapoW, $DiapoH, "D");
|
||||
|
||||
$this->pdf->SetXY($x, $y + 1);
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, '', 10);
|
||||
$t = $irow . '-' . $x;
|
||||
$t = $rec->get_title();
|
||||
|
||||
if ($links) {
|
||||
$lk = $this->pdf->AddLink();
|
||||
$this->pdf->SetLink($lk, 0, $npages + $rec->getNumber());
|
||||
$this->pdf->Image(
|
||||
$fimg
|
||||
, $x + (($DiapoW - $wimg) / 2)
|
||||
, $TitleH + $y + (($DiapoH - $TitleH - $himg) / 2)
|
||||
, $wimg, $himg
|
||||
, null, $lk
|
||||
);
|
||||
} else {
|
||||
$this->pdf->Image($fimg
|
||||
, $x + (($DiapoW - $wimg) / 2)
|
||||
, $TitleH + $y + (($DiapoH - $TitleH - $himg) / 2)
|
||||
, $wimg, $himg
|
||||
);
|
||||
}
|
||||
|
||||
$this->pdf->MultiCell($DiapoW, $TitleH, $t, '0', 'C', false);
|
||||
}
|
||||
}
|
||||
$this->pdf->SetLeftMargin($oldMargins['left']);
|
||||
}
|
||||
|
||||
protected function print_thumbnailList()
|
||||
{
|
||||
$this->pdf->AddPage();
|
||||
$oldMargins = $this->pdf->getMargins();
|
||||
|
||||
$lmargin = $oldMargins['left'];
|
||||
$rmargin = $oldMargins['right'];
|
||||
|
||||
$this->pdf->SetLeftMargin($lmargin + 55);
|
||||
|
||||
$ndoc = 0;
|
||||
foreach ($this->records as $rec) {
|
||||
/* @var \record_adapter $rec */
|
||||
$subdef = $rec->get_subdef('thumbnail');
|
||||
|
||||
$fimg = $subdef->getRealPath();
|
||||
|
||||
$wimg = $himg = 50;
|
||||
// 1px = 3.77952 mm
|
||||
$finalWidth = round($subdef->get_width() / 3.779528, 2);
|
||||
$finalHeight = round($subdef->get_height() / 3.779528, 2);
|
||||
$aspectH = $finalWidth/$finalHeight;
|
||||
$aspectW = $finalHeight/$finalWidth;
|
||||
|
||||
if ($finalWidth > 0 && $finalHeight > 0) {
|
||||
if ($finalWidth > $finalHeight && $finalWidth > $wimg) {
|
||||
$finalWidth = $wimg;
|
||||
$finalHeight = $wimg * $aspectW;
|
||||
} else if ($finalHeight > $finalWidth && $finalHeight > $himg) {
|
||||
$finalHeight = $himg;
|
||||
$finalWidth = $himg * $aspectH;
|
||||
} else if ($finalHeight == $finalWidth & $finalWidth > $wimg) {
|
||||
$finalHeight = $wimg;
|
||||
$finalWidth = $himg;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->pdf->GetY() > $this->pdf->getPageHeight() - (6 + $finalHeight + 20))
|
||||
$this->pdf->AddPage();
|
||||
|
||||
$title = "record : " . $rec->get_title();
|
||||
|
||||
$y = $this->pdf->GetY();
|
||||
|
||||
$t = \phrasea::bas_labels($rec->getBaseId(), $this->app);
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, '', 10);
|
||||
$this->pdf->SetFillColor(220, 220, 220);
|
||||
$this->pdf->SetLeftMargin($lmargin);
|
||||
$this->pdf->SetRightMargin($rmargin);
|
||||
$this->pdf->SetX($lmargin);
|
||||
$this->pdf->SetY($y);
|
||||
|
||||
$this->pdf->out = false;
|
||||
$this->pdf->MultiCell(140, 4, $title, "LTR", "L", 1);
|
||||
$y2 = $this->pdf->GetY();
|
||||
$h = $y2 - $y;
|
||||
$this->pdf->out = true;
|
||||
$this->pdf->SetX($lmargin);
|
||||
$this->pdf->SetY($y);
|
||||
$this->pdf->Cell(0, $h, "", "LTR", 1, "R", 1);
|
||||
$this->pdf->SetX($lmargin);
|
||||
$this->pdf->SetY($y);
|
||||
$this->pdf->Cell(0, 4, $t, "", 1, "R");
|
||||
$this->pdf->SetX($lmargin);
|
||||
$this->pdf->SetY($y);
|
||||
$this->pdf->MultiCell(140, 4, $title, "", "L");
|
||||
$this->pdf->SetX($lmargin);
|
||||
$this->pdf->SetY($y = $y2);
|
||||
|
||||
$this->pdf->SetLeftMargin($lmargin + 55);
|
||||
$this->pdf->SetY($y + 2);
|
||||
|
||||
if ($fimg) {
|
||||
$y = $this->pdf->GetY();
|
||||
$this->pdf->Image($fimg, $lmargin, $y, $finalWidth, $finalHeight);
|
||||
$this->pdf->SetY($y + 3);
|
||||
}
|
||||
|
||||
$nf = 0;
|
||||
$this->pdf->SetX($lmargin + 55);
|
||||
$p0 = $this->pdf->PageNo();
|
||||
$y0 = $this->pdf->GetY();
|
||||
foreach ($rec->get_caption()->get_fields() as $field) {
|
||||
/* @var $field caption_field */
|
||||
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, 'B', 12);
|
||||
$this->pdf->Write(5, $field->get_name() . " : ");
|
||||
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, '', 12);
|
||||
$this->pdf->Write(5, $field->get_serialized_values());
|
||||
|
||||
$this->pdf->Write(6, "\n");
|
||||
$nf++;
|
||||
}
|
||||
if ($this->pdf->PageNo() == $p0 && ($this->pdf->GetY() - $y0) < $finalHeight)
|
||||
$this->pdf->SetY($y0 + $finalHeight);
|
||||
$ndoc++;
|
||||
}
|
||||
$this->pdf->SetLeftMargin($lmargin);
|
||||
}
|
||||
|
||||
protected function print_caption()
|
||||
{
|
||||
$this->pdf->AddPage();
|
||||
$oldMargins = $this->pdf->getMargins();
|
||||
|
||||
$lmargin = $oldMargins['left'];
|
||||
$rmargin = $oldMargins['right'];
|
||||
|
||||
foreach ($this->records as $rec) {
|
||||
$title = "record : " . $rec->get_title();
|
||||
|
||||
$y = $this->pdf->GetY();
|
||||
if($this->pdf->getPageHeight() - $y < 20){ // height of the footer is 15
|
||||
$this->pdf->AddPage();
|
||||
$y = $oldMargins['top'];
|
||||
}
|
||||
|
||||
$t = \phrasea::bas_labels($rec->getBaseId(), $this->app);
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, '', 10);
|
||||
$this->pdf->SetFillColor(220, 220, 220);
|
||||
$this->pdf->SetLeftMargin($lmargin);
|
||||
$this->pdf->SetRightMargin($rmargin);
|
||||
$this->pdf->SetX($lmargin);
|
||||
$this->pdf->SetY($y);
|
||||
|
||||
$this->pdf->out = false;
|
||||
$this->pdf->MultiCell(140, 4, $title, "LTR", "L", 1);
|
||||
$y2 = $this->pdf->GetY();
|
||||
$h = $y2 - $y;
|
||||
$this->pdf->out = true;
|
||||
$this->pdf->SetX($lmargin);
|
||||
$this->pdf->SetY($y);
|
||||
$this->pdf->Cell(0, $h, "", "LTR", 1, "R", 1);
|
||||
$this->pdf->SetX($lmargin);
|
||||
$this->pdf->SetY($y);
|
||||
$this->pdf->Cell(0, 4, $t, "", 1, "R");
|
||||
$this->pdf->SetX($lmargin);
|
||||
$this->pdf->SetY($y);
|
||||
$this->pdf->MultiCell(140, 4, $title, "", "L");
|
||||
$this->pdf->SetX($lmargin);
|
||||
$this->pdf->SetY($y = $y2);
|
||||
$this->pdf->SetY($y + 2);
|
||||
|
||||
foreach ($rec->get_caption()->get_fields() as $field) {
|
||||
if ($field->get_databox_field()->get_gui_visible()) {
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, 'B', 12);
|
||||
$this->pdf->Write(5, $field->get_name() . " : ");
|
||||
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, '', 12);
|
||||
$t = str_replace(
|
||||
["<", ">", "&"]
|
||||
, ["<", ">", "&"]
|
||||
, strip_tags($field->get_serialized_values())
|
||||
);
|
||||
$this->pdf->Write(5, $t);
|
||||
|
||||
$this->pdf->Write(6, "\n");
|
||||
}
|
||||
}
|
||||
$this->pdf->SetY($this->pdf->GetY() + 10);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected function print_preview($withtdm, $write_caption, $withfeedback)
|
||||
{
|
||||
$basket = $validation = null;
|
||||
|
||||
if($this->printer->is_basket()) {
|
||||
$basket = $this->printer->get_original_basket();
|
||||
|
||||
if($withfeedback) {
|
||||
// first page : validation informations
|
||||
$validation = $basket->getValidation();
|
||||
|
||||
$this->pdf->AddPage();
|
||||
|
||||
$this->pdf->SetY(20);
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, 'B', 14);
|
||||
$this->pdf->Cell(0, 0,
|
||||
$this->app->trans("print_feedback:: Feedback on basket %name%", ['%name%'=>$basket->getName()]),
|
||||
'', 1, 'C', false);
|
||||
|
||||
$this->pdf->SetY($this->pdf->GetY()+10);
|
||||
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, 'B', 12);
|
||||
$this->pdf->Write(5, $this->app->trans("print_feedback:: Document generated on : ") . " ");
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, '', 12);
|
||||
$this->pdf->Write(5, $this->formatDate(new \DateTime('now')));
|
||||
$this->pdf->Write(12, "\n");
|
||||
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, 'B', 12);
|
||||
$this->pdf->Write(5, $this->app->trans("print_feedback:: Feedback initiated by : ") . " ");
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, '', 12);
|
||||
$this->pdf->Write(5, $this->getDisplayName($validation->getInitiator()));
|
||||
$this->pdf->Write(6, "\n");
|
||||
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, 'B', 12);
|
||||
$this->pdf->Write(5, $this->app->trans("print_feedback:: Feedback initiated on : ") . " ");
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, '', 12);
|
||||
$this->pdf->Write(5, $this->formatDate($validation->getCreated()));
|
||||
$this->pdf->Write(6, "\n");
|
||||
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, 'B', 12);
|
||||
$this->pdf->Write(5, $this->app->trans("print_feedback:: Feedback expiring on : ") . " ");
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, '', 12);
|
||||
$this->pdf->Write(5, $this->formatDate($validation->getExpires()));
|
||||
$this->pdf->Write(12, "\n");
|
||||
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, 'B', 12);
|
||||
$validation->isFinished() ? $this->pdf->Write(5, $this->app->trans("print_feedback:: Feedback expired")) : $this->pdf->Write(5, $this->app->trans("print_feedback:: Feedback active"));
|
||||
$this->pdf->Write(12, "\n");
|
||||
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, 'B', 12);
|
||||
$this->pdf->Write(5, $this->app->trans("print_feedback:: Participants : "));
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, '', 12);
|
||||
foreach ($validation->getParticipants() as $participant) {
|
||||
$this->pdf->Write(5, "\n - " . $this->getDisplayName($participant->getUser()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($withtdm === true) {
|
||||
$this->print_thumbnailGrid($this->pdf, $this->records, true);
|
||||
}
|
||||
|
||||
foreach ($this->records as $krec => $rec) {
|
||||
/* @var \record_adapter $rec */
|
||||
|
||||
$this->pdf->AddPage();
|
||||
|
||||
if ($withtdm === "CALCPAGES") {
|
||||
$rec->setNumber($this->pdf->PageNo());
|
||||
}
|
||||
$lmargin = $this->pdf->GetX();
|
||||
$himg = 0;
|
||||
$y = 0;
|
||||
$miniConv = NULL;
|
||||
|
||||
$LEFT__TEXT = "";
|
||||
$LEFT__IMG = NULL;
|
||||
$RIGHT_TEXT = "";
|
||||
$RIGHT_IMG = NULL;
|
||||
|
||||
$LEFT__IMG = $this->app['root.path'] . "/config/minilogos/logopdf_" . $rec->getDataboxId() . ".jpg";
|
||||
|
||||
if (!is_file($LEFT__IMG)) {
|
||||
$databox = $rec->getDatabox();
|
||||
$str = $databox->get_sxml_structure();
|
||||
$vn = (string) ($str->pdfPrintLogo);
|
||||
if (($vn * 1) == 1) {
|
||||
$LEFT__TEXT = $databox->get_label($this->app['locale']);
|
||||
}
|
||||
}
|
||||
|
||||
$collection = \collection::getByBaseId($this->app, $rec->getBaseId());
|
||||
|
||||
$vn = "";
|
||||
if (false !== $str = simplexml_load_string($collection->get_prefs())) {
|
||||
$vn = (string) ($str->pdfPrintappear);
|
||||
}
|
||||
|
||||
if ($vn == "" || $vn == "1") {
|
||||
$RIGHT_TEXT = \phrasea::bas_labels($rec->getBaseId(), $this->app);
|
||||
} elseif ($vn == "2") {
|
||||
$RIGHT_IMG = $this->app['root.path'] . "/config/minilogos/" . $rec->getBaseId();
|
||||
}
|
||||
|
||||
$xtmp = $this->pdf->GetX();
|
||||
$ytmp = $this->pdf->GetY();
|
||||
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, '', 12);
|
||||
$this->pdf->SetFillColor(220, 220, 220);
|
||||
$y = $this->pdf->GetY();
|
||||
$this->pdf->MultiCell(95, 7, $LEFT__TEXT, "LTB", "L", 1);
|
||||
$y2 = $this->pdf->GetY();
|
||||
$h = $y2 - $y;
|
||||
$this->pdf->SetY($y);
|
||||
$this->pdf->SetX(105);
|
||||
$this->pdf->Cell(95, $h, $RIGHT_TEXT, "TBR", 1, "R", 1);
|
||||
|
||||
if($basket) {
|
||||
$ord = $basket->getElementByRecord($this->app, $rec)->getOrd();
|
||||
$this->pdf->SetY($y);
|
||||
$this->pdf->SetX(10);
|
||||
$this->pdf->Cell(190, $h, $ord, "", 1, "C", 0);
|
||||
}
|
||||
|
||||
if ($LEFT__TEXT == "" && is_file($LEFT__IMG)) {
|
||||
if ($size = @getimagesize($LEFT__IMG)) {
|
||||
$wmm = (int) $size[0] * 25.4 / 72;
|
||||
$hmm = (int) $size[1] * 25.4 / 72;
|
||||
if ($hmm > 6) {
|
||||
$coeff = $hmm / 6;
|
||||
$wmm = (int) $wmm / $coeff;
|
||||
$hmm = (int) $hmm / $coeff;
|
||||
}
|
||||
$this->pdf->Image($LEFT__IMG, $xtmp + 0.5, $ytmp + 0.5, $wmm, $hmm);
|
||||
}
|
||||
}
|
||||
|
||||
if ($RIGHT_IMG != NULL && is_file($RIGHT_IMG)) {
|
||||
if ($size = @getimagesize($RIGHT_IMG)) {
|
||||
|
||||
if ($size[2] == '1') {
|
||||
if (!isset($miniConv[$RIGHT_IMG])) {
|
||||
$tmp_filename = tempnam('minilogos/', 'gif4fpdf');
|
||||
$img = imagecreatefromgif($RIGHT_IMG);
|
||||
imageinterlace($img, 0);
|
||||
imagepng($img, $tmp_filename);
|
||||
rename($tmp_filename, $tmp_filename . '.png');
|
||||
$miniConv[$RIGHT_IMG] = $tmp_filename . '.png';
|
||||
$RIGHT_IMG = $tmp_filename . '.png';
|
||||
} else
|
||||
$RIGHT_IMG = $miniConv[$RIGHT_IMG];
|
||||
|
||||
$wmm = (int) $size[0] * 25.4 / 72;
|
||||
$hmm = (int) $size[1] * 25.4 / 72;
|
||||
if ($hmm > 6) {
|
||||
$coeff = $hmm / 6;
|
||||
$wmm = (int) $wmm / $coeff;
|
||||
$hmm = (int) $hmm / $coeff;
|
||||
}
|
||||
$tt = 0;
|
||||
if ($hmm < 6)
|
||||
$tt = (6 - $hmm) / 2;
|
||||
$this->pdf->Image($RIGHT_IMG, 200 - 0.5 - $wmm, $ytmp + 0.5 + $tt);
|
||||
} else {
|
||||
$wmm = (int) $size[0] * 25.4 / 72;
|
||||
$hmm = (int) $size[1] * 25.4 / 72;
|
||||
if ($hmm > 6) {
|
||||
$coeff = $hmm / 6;
|
||||
$wmm = (int) $wmm / $coeff;
|
||||
$hmm = (int) $hmm / $coeff;
|
||||
}
|
||||
$this->pdf->Image($RIGHT_IMG, 200 - 0.5 - $wmm, $ytmp + 0.5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$y = $this->pdf->GetY() + 5;
|
||||
|
||||
$subdef = $rec->get_subdef('preview');
|
||||
|
||||
if ($subdef->get_type() !== \media_subdef::TYPE_IMAGE) {
|
||||
$subdef = $rec->get_thumbnail();
|
||||
}
|
||||
|
||||
$f = $subdef->getRealPath();
|
||||
|
||||
if (!$this->app->getAclForUser($this->app->getAuthenticatedUser())->has_right_on_base($rec->getBaseId(), \ACL::NOWATERMARK)
|
||||
&& $subdef->get_type() == \media_subdef::TYPE_IMAGE)
|
||||
$f = \recordutils_image::watermark($this->app, $subdef);
|
||||
|
||||
// original height / original width x new width = new height
|
||||
$wimg = $himg = 150; // preview dans un carre de 150 mm
|
||||
// 1px = 3.77952 mm
|
||||
$finalWidth = round($subdef->get_width() / 3.779528, 2);
|
||||
$finalHeight = round($subdef->get_height() / 3.779528, 2);
|
||||
$aspectH = $finalWidth/$finalHeight;
|
||||
$aspectW = $finalHeight/$finalWidth;
|
||||
|
||||
if ($finalWidth > 0 && $finalHeight > 0) {
|
||||
if ($finalWidth > $finalHeight && $finalWidth > $wimg) {
|
||||
$finalWidth = $wimg;
|
||||
$finalHeight = $wimg * $aspectW;
|
||||
} else if ($finalHeight > $finalWidth && $finalHeight > $himg) {
|
||||
$finalHeight = $himg;
|
||||
$finalWidth = $himg * $aspectH;
|
||||
} else if ($finalHeight == $finalWidth & $finalWidth > $wimg) {
|
||||
$finalHeight = $wimg;
|
||||
$finalWidth = $himg;
|
||||
}
|
||||
}
|
||||
|
||||
$this->pdf->Image($f, (210 - $finalWidth) / 2, $y, $finalWidth, $finalHeight);
|
||||
|
||||
if ($miniConv != NULL) {
|
||||
foreach ($miniConv as $oneF)
|
||||
unlink($oneF);
|
||||
}
|
||||
$this->pdf->SetXY($lmargin, $y += ( $finalHeight + 5));
|
||||
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, 'B', 12);
|
||||
$this->pdf->Write(5, $this->app->trans("print_feedback:: record title: ") . " ");
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, '', 12);
|
||||
$this->pdf->Write(5, $rec->get_title());
|
||||
$this->pdf->Write(6, "\n");
|
||||
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, 'B', 12);
|
||||
$this->pdf->Write(5, $this->app->trans("print_feedback:: record id: ") . " ");
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, '', 12);
|
||||
$this->pdf->Write(5, $rec->getRecordId());
|
||||
$this->pdf->Write(6, "\n");
|
||||
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, 'B', 12);
|
||||
$this->pdf->Write(5, $this->app->trans("print_feedback:: base name: ") . " ");
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, '', 12);
|
||||
$this->pdf->Write(5, $rec->getDatabox()->get_label($this->app['locale']));
|
||||
$this->pdf->Write(6, "\n");
|
||||
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, 'B', 12);
|
||||
$this->pdf->Write(5, $this->app->trans("print_feedback:: originale filename: ") . " ");
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, '', 12);
|
||||
$this->pdf->Write(5, $rec->get_original_name());
|
||||
$this->pdf->Write(6, "\n");
|
||||
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, 'B', 12);
|
||||
$this->pdf->Write(5, $this->app->trans("print_feedback:: document Uuid: ") . " ");
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, '', 12);
|
||||
$this->pdf->Write(5, $rec->getUUID());
|
||||
$this->pdf->Write(6, "\n");
|
||||
|
||||
$nf = 0;
|
||||
if($basket && $validation) {
|
||||
/** @var ValidationParticipant $participant */
|
||||
|
||||
if ($nf > 0) {
|
||||
$this->pdf->Write(6, "\n");
|
||||
}
|
||||
$this->pdf->Write(12, "\n");
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, 'B', 12);
|
||||
$this->pdf->Write(5, $this->app->trans("print_feedback:: Votes :"));
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, '', 12);
|
||||
|
||||
$basketElement = $basket->getElementByRecord($this->app, $rec);
|
||||
|
||||
$iparticipant = 0;
|
||||
foreach ($validation->getParticipants() as $participant) {
|
||||
$this->pdf->Write(6, "\n");
|
||||
if($iparticipant++ > 0) {
|
||||
// $this->pdf->SetY($this->pdf->GetY()+1);
|
||||
}
|
||||
$validationData = $basketElement->getUserValidationDatas($participant->getUser());
|
||||
|
||||
$this->pdf->Write(5, '- ' . $this->getDisplayName($participant->getUser(), true). " : ");
|
||||
|
||||
$r = $validationData->getAgreement();
|
||||
$this->pdf->SetX(100);
|
||||
if ($r === null) {
|
||||
$this->pdf->Write(0, $this->app->trans("print_feedback:: non voté"));
|
||||
}
|
||||
else {
|
||||
if($r) {
|
||||
$this->pdf->SetTextColor(0, 127, 0);
|
||||
$this->pdf->Write(0, $this->app->trans("print_feedback:: Oui"));
|
||||
}
|
||||
else {
|
||||
$this->pdf->SetTextColor(200, 0, 0);
|
||||
$this->pdf->Write(0, $this->app->trans("print_feedback:: Non"));
|
||||
}
|
||||
$this->pdf->SetTextColor(0);
|
||||
$this->pdf->Write(0, " (" . $this->formatDate($validationData->getUpdated()) . ")");
|
||||
}
|
||||
|
||||
if (($note = (string)($validationData->getNote())) !== '') {
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, 'I', 11);
|
||||
$this->pdf->Write(5,"\n");
|
||||
$this->pdf->SetX(100);
|
||||
$this->pdf->MultiCell(95, 0, $note, '', "L", false);
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, '', 12);
|
||||
}
|
||||
|
||||
$nf++;
|
||||
}
|
||||
}
|
||||
|
||||
if ($write_caption) {
|
||||
$this->pdf->Write(12, "\n");
|
||||
foreach ($rec->get_caption()->get_fields() as $field) {
|
||||
/* @var $field caption_field */
|
||||
|
||||
if ($field->get_databox_field()->get_gui_visible()) {
|
||||
if ($nf > 0) {
|
||||
$this->pdf->Write(6, "\n");
|
||||
}
|
||||
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, 'B', 12);
|
||||
$this->pdf->Write(5, $field->get_name() . " : ");
|
||||
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, '', 12);
|
||||
|
||||
$t = str_replace(
|
||||
["<", ">", "&"]
|
||||
, ["<", ">", "&"]
|
||||
, strip_tags($field->get_serialized_values())
|
||||
);
|
||||
|
||||
$this->pdf->Write(5, $t);
|
||||
|
||||
$nf++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
private function formatDate(\DateTime $date)
|
||||
{
|
||||
$locale = $this->app['locale'];
|
||||
|
||||
switch ($locale) {
|
||||
case 'fr':
|
||||
$fmt = new DateFormatter(
|
||||
'fr_FR',
|
||||
DateFormatter::LONG,
|
||||
DateFormatter::NONE
|
||||
);
|
||||
|
||||
$date_formated = $fmt->format($date);
|
||||
break;
|
||||
|
||||
case 'en':
|
||||
$fmt = new DateFormatter(
|
||||
'en_EN',
|
||||
DateFormatter::LONG,
|
||||
DateFormatter::NONE
|
||||
);
|
||||
|
||||
$date_formated = $fmt->format($date);
|
||||
break;
|
||||
|
||||
case 'de':
|
||||
$fmt = new DateFormatter(
|
||||
'de_DE',
|
||||
DateFormatter::LONG,
|
||||
DateFormatter::NONE
|
||||
);
|
||||
|
||||
$date_formated = $fmt->format($date);
|
||||
break;
|
||||
|
||||
default:
|
||||
$fmt = new DateFormatter(
|
||||
'en_EN',
|
||||
DateFormatter::LONG,
|
||||
DateFormatter::NONE ,
|
||||
null,
|
||||
null,
|
||||
'yyyy/mm/dd'
|
||||
);
|
||||
|
||||
$date_formated = $fmt->format($date);
|
||||
break;
|
||||
}
|
||||
|
||||
return $date_formated;
|
||||
}
|
||||
|
||||
private function getDisplayName($user, $short = false)
|
||||
{
|
||||
$displayName = '';
|
||||
|
||||
if (trim($user->getLastName()) !== '' || trim($user->getFirstName()) !== '') {
|
||||
$displayName = $user->getFirstName() . ('' !== $user->getFirstName() && '' !== $user->getLastName() ? ' ' : '') . $user->getLastName() ;
|
||||
|
||||
if ($short) {
|
||||
return $displayName;
|
||||
}
|
||||
}
|
||||
|
||||
$email = trim($user->getEmail());
|
||||
|
||||
if ($email === '') {
|
||||
$email = $user->getLogin();
|
||||
}
|
||||
|
||||
if ($displayName !== '') {
|
||||
return $displayName . ", " . $email;
|
||||
} else {
|
||||
return $email;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -668,17 +668,20 @@ class ElasticSearchEngine implements SearchEngineInterface
|
||||
}
|
||||
// fields aggregates
|
||||
$structure = $this->context_factory->getLimitedStructure($options);
|
||||
foreach ($structure->getFacetFields() as $name => $field) {
|
||||
// 2015-05-26 (mdarse) Removed databox filtering.
|
||||
// It was already done by the ACL filter in the query scope, so no
|
||||
// document that shouldn't be displayed can go this far.
|
||||
$agg = [
|
||||
'terms' => [
|
||||
'field' => $field->getIndexField(true),
|
||||
'size' => $field->getFacetValuesLimit()
|
||||
]
|
||||
];
|
||||
$aggs[$name] = AggregationHelper::wrapPrivateFieldAggregation($field, $agg);
|
||||
foreach($structure->getAllFields() as $name => $field) {
|
||||
$size = $this->options->getAggregableFieldLimit($name);
|
||||
if ($size !== databox_field::FACET_DISABLED) {
|
||||
if ($size === databox_field::FACET_NO_LIMIT) {
|
||||
$size = ESField::FACET_NO_LIMIT;
|
||||
}
|
||||
$agg = [
|
||||
'terms' => [
|
||||
'field' => $field->getIndexField(true),
|
||||
'size' => $size
|
||||
]
|
||||
];
|
||||
$aggs[$name] = AggregationHelper::wrapPrivateFieldAggregation($field, $agg);
|
||||
}
|
||||
}
|
||||
|
||||
return $aggs;
|
||||
|
@@ -9,6 +9,10 @@
|
||||
*/
|
||||
namespace Alchemy\Phrasea\SearchEngine\Elastic;
|
||||
|
||||
use databox_field;
|
||||
use igorw;
|
||||
|
||||
|
||||
class ElasticsearchOptions
|
||||
{
|
||||
const POPULATE_ORDER_RID = "RECORD_ID";
|
||||
@@ -35,7 +39,7 @@ class ElasticsearchOptions
|
||||
private $populateDirection;
|
||||
|
||||
/** @var int[] */
|
||||
private $_customValues;
|
||||
private $_customValues = [];
|
||||
private $activeTab;
|
||||
|
||||
/**
|
||||
@@ -57,14 +61,10 @@ class ElasticsearchOptions
|
||||
'populate_order' => self::POPULATE_ORDER_RID,
|
||||
'populate_direction' => self::POPULATE_DIRECTION_DESC,
|
||||
'activeTab' => null,
|
||||
'facets' => []
|
||||
];
|
||||
|
||||
foreach(self::getAggregableTechnicalFields() as $k => $f) {
|
||||
$defaultOptions[$k.'_limit'] = 0;
|
||||
}
|
||||
$options = array_replace($defaultOptions, $options);
|
||||
|
||||
|
||||
$self = new self();
|
||||
$self->setHost($options['host']);
|
||||
$self->setPort($options['port']);
|
||||
@@ -76,11 +76,10 @@ class ElasticsearchOptions
|
||||
$self->setPopulateOrder($options['populate_order']);
|
||||
$self->setPopulateDirection($options['populate_direction']);
|
||||
$self->setActiveTab($options['activeTab']);
|
||||
foreach(self::getAggregableTechnicalFields() as $k => $f) {
|
||||
$self->setAggregableFieldLimit($k, $options[$k.'_limit']);
|
||||
foreach($options['facets'] as $fieldname=>$attributes) {
|
||||
$self->setAggregableField($fieldname, $attributes);
|
||||
}
|
||||
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
@@ -99,10 +98,11 @@ class ElasticsearchOptions
|
||||
'highlight' => $this->highlight,
|
||||
'populate_order' => $this->populateOrder,
|
||||
'populate_direction' => $this->populateDirection,
|
||||
'activeTab' => $this->activeTab
|
||||
'activeTab' => $this->activeTab,
|
||||
'facets' => []
|
||||
];
|
||||
foreach(self::getAggregableTechnicalFields() as $k => $f) {
|
||||
$ret[$k.'_limit'] = $this->getAggregableFieldLimit($k);
|
||||
foreach($this->getAggregableFields() as $fieldname=>$attributes) {
|
||||
$ret['facets'][$fieldname] = $attributes;
|
||||
}
|
||||
|
||||
return $ret;
|
||||
@@ -222,12 +222,51 @@ class ElasticsearchOptions
|
||||
|
||||
public function setAggregableFieldLimit($key, $value)
|
||||
{
|
||||
$this->_customValues[$key.'_limit'] = $value;
|
||||
if(is_null($this->getAggregableField($key))) {
|
||||
$this->_customValues['facets'][$key] = [];
|
||||
}
|
||||
$this->_customValues['facets'][$key]['limit'] = $value;
|
||||
}
|
||||
|
||||
public function setAggregableField($key, $attributes)
|
||||
{
|
||||
$this->getAggregableFields(); // ensure facets exists
|
||||
$this->_customValues['facets'][$key] = $attributes;
|
||||
}
|
||||
|
||||
public function getAggregableFieldLimit($key)
|
||||
{
|
||||
return $this->_customValues[$key.'_limit'];
|
||||
$facet = $this->getAggregableField($key);
|
||||
return (is_array($facet) && array_key_exists('limit', $facet)) ? $facet['limit'] : databox_field::FACET_DISABLED;
|
||||
}
|
||||
|
||||
public function getAggregableField($key)
|
||||
{
|
||||
$facets = $this->getAggregableFields();
|
||||
return array_key_exists($key, $facets) ? $facets[$key] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getAggregableFields()
|
||||
{
|
||||
if(!array_key_exists('facets', $this->_customValues) || !is_array($this->_customValues['facets'])) {
|
||||
$this->_customValues['facets'] = [];
|
||||
}
|
||||
return $this->_customValues['facets'];
|
||||
}
|
||||
|
||||
// set to change the facets order during admin/form save
|
||||
public function reorderAggregableFields($facetNames)
|
||||
{
|
||||
$newFacets = [];
|
||||
foreach ($facetNames as $name) {
|
||||
if(($facet = $this->getAggregableField($name)) !== null) {
|
||||
$newFacets[$name] = $facet;
|
||||
}
|
||||
}
|
||||
$this->_customValues['facets'] = $newFacets;
|
||||
}
|
||||
|
||||
public function getActiveTab()
|
||||
@@ -241,56 +280,56 @@ class ElasticsearchOptions
|
||||
|
||||
public function __get($key)
|
||||
{
|
||||
if(!array_key_exists($key, $this->_customValues)) {
|
||||
$this->_customValues[$key] = 0;
|
||||
}
|
||||
return $this->_customValues[$key];
|
||||
$keys = explode(':', $key);
|
||||
|
||||
return igorw\get_in($this->_customValues, $keys);
|
||||
}
|
||||
|
||||
public function __set($key, $value)
|
||||
{
|
||||
$this->_customValues[$key] = $value;
|
||||
$keys = explode(':', $key);
|
||||
$this->_customValues = igorw\assoc_in($this->_customValues, $keys, $value);
|
||||
}
|
||||
|
||||
public static function getAggregableTechnicalFields()
|
||||
{
|
||||
return [
|
||||
'base_aggregate' => [
|
||||
'_base' => [
|
||||
'type' => 'string',
|
||||
'label' => 'prod::facet:base_label',
|
||||
'field' => "database",
|
||||
'esfield' => 'databox_name',
|
||||
'query' => 'database:%s',
|
||||
],
|
||||
'collection_aggregate' => [
|
||||
'_collection' => [
|
||||
'type' => 'string',
|
||||
'label' => 'prod::facet:collection_label',
|
||||
'field' => "collection",
|
||||
'esfield' => 'collection_name',
|
||||
'query' => 'collection:%s',
|
||||
],
|
||||
'doctype_aggregate' => [
|
||||
'_doctype' => [
|
||||
'type' => 'string',
|
||||
'label' => 'prod::facet:doctype_label',
|
||||
'field' => "type",
|
||||
'esfield' => 'type',
|
||||
'query' => 'type:%s',
|
||||
],
|
||||
'camera_model_aggregate' => [
|
||||
'_camera_model' => [
|
||||
'type' => 'string',
|
||||
'label' => 'Camera Model',
|
||||
'field' => "meta.CameraModel",
|
||||
'esfield' => 'metadata_tags.CameraModel',
|
||||
'query' => 'meta.CameraModel:%s',
|
||||
],
|
||||
'iso_aggregate' => [
|
||||
'_iso' => [
|
||||
'type' => 'number',
|
||||
'label' => 'ISO',
|
||||
'field' => "meta.ISO",
|
||||
'esfield' => 'metadata_tags.ISO',
|
||||
'query' => 'meta.ISO=%s',
|
||||
],
|
||||
'aperture_aggregate' => [
|
||||
'_aperture' => [
|
||||
'type' => 'number',
|
||||
'label' => 'Aperture',
|
||||
'field' => "meta.Aperture",
|
||||
@@ -300,7 +339,7 @@ class ElasticsearchOptions
|
||||
return round($value, 1);
|
||||
},
|
||||
],
|
||||
'shutterspeed_aggregate' => [
|
||||
'_shutterspeed' => [
|
||||
'type' => 'number',
|
||||
'label' => 'Shutter speed',
|
||||
'field' => "meta.ShutterSpeed",
|
||||
@@ -313,7 +352,7 @@ class ElasticsearchOptions
|
||||
return $value . ' s.';
|
||||
},
|
||||
],
|
||||
'flashfired_aggregate' => [
|
||||
'_flashfired' => [
|
||||
'type' => 'boolean',
|
||||
'label' => 'FlashFired',
|
||||
'field' => "meta.FlashFired",
|
||||
@@ -327,49 +366,49 @@ class ElasticsearchOptions
|
||||
return array_key_exists($value, $map) ? $map[$value] : $value;
|
||||
},
|
||||
],
|
||||
'framerate_aggregate' => [
|
||||
'_framerate' => [
|
||||
'type' => 'number',
|
||||
'label' => 'FrameRate',
|
||||
'field' => "meta.FrameRate",
|
||||
'esfield' => 'metadata_tags.FrameRate',
|
||||
'query' => 'meta.FrameRate=%s',
|
||||
],
|
||||
'audiosamplerate_aggregate' => [
|
||||
'_audiosamplerate' => [
|
||||
'type' => 'number',
|
||||
'label' => 'Audio Samplerate',
|
||||
'field' => "meta.AudioSamplerate",
|
||||
'esfield' => 'metadata_tags.AudioSamplerate',
|
||||
'query' => 'meta.AudioSamplerate=%s',
|
||||
],
|
||||
'videocodec_aggregate' => [
|
||||
'_videocodec' => [
|
||||
'type' => 'string',
|
||||
'label' => 'Video codec',
|
||||
'field' => "meta.VideoCodec",
|
||||
'esfield' => 'metadata_tags.VideoCodec',
|
||||
'query' => 'meta.VideoCodec:%s',
|
||||
],
|
||||
'audiocodec_aggregate' => [
|
||||
'_audiocodec' => [
|
||||
'type' => 'string',
|
||||
'label' => 'Audio codec',
|
||||
'field' => "meta.AudioCodec",
|
||||
'esfield' => 'metadata_tags.AudioCodec',
|
||||
'query' => 'meta.AudioCodec:%s',
|
||||
],
|
||||
'orientation_aggregate' => [
|
||||
'_orientation' => [
|
||||
'type' => 'string',
|
||||
'label' => 'Orientation',
|
||||
'field' => "meta.Orientation",
|
||||
'esfield' => 'metadata_tags.Orientation',
|
||||
'query' => 'meta.Orientation=%s',
|
||||
],
|
||||
'colorspace_aggregate' => [
|
||||
'_colorspace' => [
|
||||
'type' => 'string',
|
||||
'label' => 'Colorspace',
|
||||
'field' => "meta.ColorSpace",
|
||||
'esfield' => 'metadata_tags.ColorSpace',
|
||||
'query' => 'meta.ColorSpace:%s',
|
||||
],
|
||||
'mimetype_aggregate' => [
|
||||
'_mimetype' => [
|
||||
'type' => 'string',
|
||||
'label' => 'MimeType',
|
||||
'field' => "meta.MimeType",
|
||||
|
@@ -9,6 +9,7 @@
|
||||
*/
|
||||
namespace Alchemy\Phrasea\SearchEngine\Elastic;
|
||||
|
||||
use Alchemy\Phrasea\SearchEngine\Elastic\Structure\GlobalStructure;
|
||||
use Symfony\Component\Form\AbstractType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
@@ -17,6 +18,18 @@ use Symfony\Component\Validator\Constraints\Range;
|
||||
|
||||
class ElasticsearchSettingsFormType extends AbstractType
|
||||
{
|
||||
/** @var GlobalStructure */
|
||||
private $globalStructure;
|
||||
|
||||
/** @var ElasticsearchOptions */
|
||||
private $esSettings;
|
||||
|
||||
public function __construct(GlobalStructure $g, ElasticsearchOptions $settings)
|
||||
{
|
||||
$this->globalStructure = $g;
|
||||
$this->esSettings = $settings;
|
||||
}
|
||||
|
||||
public function buildForm(FormBuilderInterface $builder, array $options)
|
||||
{
|
||||
$builder
|
||||
@@ -56,59 +69,89 @@ class ElasticsearchSettingsFormType extends AbstractType
|
||||
->add('minScore', 'integer', [
|
||||
'label' => 'Thesaurus Min score',
|
||||
'constraints' => new Range(['min' => 0]),
|
||||
]);
|
||||
])
|
||||
->add('highlight', 'checkbox', [
|
||||
'label' => 'Activate highlight',
|
||||
'required' => false
|
||||
])
|
||||
// ->add('save', 'submit', [
|
||||
// 'attr' => ['class' => 'btn btn-primary']
|
||||
// ])
|
||||
->add('esSettingFromIndex', 'button', [
|
||||
'label' => 'Get setting form index',
|
||||
'attr' => [
|
||||
'onClick' => 'esSettingFromIndex()',
|
||||
'class' => 'btn'
|
||||
]
|
||||
])
|
||||
->add('dumpField', 'textarea', [
|
||||
'label' => false,
|
||||
'required' => false,
|
||||
'mapped' => false,
|
||||
'attr' => ['class' => 'dumpfield hide']
|
||||
])
|
||||
->add('activeTab', 'hidden');
|
||||
|
||||
foreach(ElasticsearchOptions::getAggregableTechnicalFields() as $k => $f) {
|
||||
if(array_key_exists('choices', $f)) {
|
||||
// choices[] : choice_key => choice_value
|
||||
$choices = $f['choices'];
|
||||
}
|
||||
else {
|
||||
$choices = [
|
||||
"10 values" => 10,
|
||||
"20 values" => 20,
|
||||
"50 values" => 50,
|
||||
"100 values" => 100,
|
||||
"all values" => -1
|
||||
];
|
||||
}
|
||||
// array_unshift($choices, "not aggregated"); // always as first choice
|
||||
$choices = array_merge(["not aggregated" => 0], $choices);
|
||||
$builder
|
||||
->add($k.'_limit', ChoiceType::class, [
|
||||
// 'label' => $f['label'],// . ' ' . 'aggregate limit',
|
||||
'choices_as_values' => true,
|
||||
'choices' => $choices,
|
||||
'attr' => [
|
||||
'class' => 'aggregate'
|
||||
]
|
||||
]);
|
||||
// keep aggregates in configuration order with this intermediate array
|
||||
$aggs = [];
|
||||
|
||||
// helper fct to add aggregate to a tmp list
|
||||
$addAgg = function($k, $label, $help, $disabled=false, $choices=null) use (&$aggs) {
|
||||
if(!$choices) {
|
||||
$choices = [
|
||||
"10 values" => 10,
|
||||
"50 values" => 50,
|
||||
"100 values" => 100,
|
||||
"all values" => -1
|
||||
];
|
||||
}
|
||||
$choices = array_merge(["not aggregated" => 0], $choices); // add this option always as first choice
|
||||
$aggs[$k] = [ // default value will be replaced by hardcoded tech fields & all databoxes fields
|
||||
'label' => $label,
|
||||
'choices_as_values' => true,
|
||||
'choices' => $choices,
|
||||
'attr' => [
|
||||
'class' => 'aggregate'
|
||||
],
|
||||
'disabled' => $disabled,
|
||||
'help_message' => $help // todo : not displayed ?
|
||||
];
|
||||
};
|
||||
|
||||
$builder
|
||||
->add('highlight', 'checkbox', [
|
||||
'label' => 'Activate highlight',
|
||||
'required' => false
|
||||
])
|
||||
// ->add('save', 'submit', [
|
||||
// 'attr' => ['class' => 'btn btn-primary']
|
||||
// ])
|
||||
->add('esSettingFromIndex', 'button', [
|
||||
'label' => 'Get setting form index',
|
||||
'attr' => [
|
||||
'onClick' => 'esSettingFromIndex()',
|
||||
'class' => 'btn'
|
||||
]
|
||||
])
|
||||
->add('dumpField', 'textarea', [
|
||||
'label' => false,
|
||||
'required' => false,
|
||||
'mapped' => false,
|
||||
'attr' => ['class' => 'dumpfield hide']
|
||||
])
|
||||
->add('activeTab', 'hidden');
|
||||
// all fields fron conf
|
||||
foreach($this->esSettings->getAggregableFields() as $k=>$f) {
|
||||
// default value will be replaced by hardcoded tech fields & all databoxes fields
|
||||
$addAgg($k, "/?\\ " . $k, "This field does not exists in current databoxes.", true);
|
||||
}
|
||||
|
||||
// add or replace hardcoded tech fields
|
||||
foreach(ElasticsearchOptions::getAggregableTechnicalFields() as $k => $f) {
|
||||
$choices = array_key_exists('choices', $f) ? $f['choices'] : null; // a tech-field can publish it's own choices
|
||||
$help = null;
|
||||
$label = '#' . $k;
|
||||
if(!array_key_exists($k, $aggs)) {
|
||||
$label = "/!\\ " . $label;
|
||||
$help = "New field, please confirm setting.";
|
||||
}
|
||||
$addAgg($k, $label, $help, false, $choices);
|
||||
}
|
||||
|
||||
// add or replace all databoxes fields (nb: new db field - unknown in conf - will be a the end)
|
||||
foreach($this->globalStructure->getAllFields() as $field) {
|
||||
$k = $label = $field->getName();
|
||||
$help = null;
|
||||
if(!array_key_exists($field->getName(), $aggs)) {
|
||||
$label = "/!\\ " . $label;
|
||||
$help = "New field, please confirm setting.";
|
||||
}
|
||||
$addAgg($k, $label, $help); // default choices
|
||||
}
|
||||
|
||||
// populate aggs to form
|
||||
foreach($aggs as $k=>$agg) {
|
||||
$builder->add('facets:' . $k . ':limit', ChoiceType::class, $agg);
|
||||
}
|
||||
|
||||
;
|
||||
}
|
||||
|
||||
public function getName()
|
||||
|
@@ -15,7 +15,7 @@ class FacetsResponse
|
||||
private $escaper;
|
||||
private $facets = array();
|
||||
|
||||
public function __construct(Escaper $escaper, array $response, GlobalStructure $structure)
|
||||
public function __construct(ElasticsearchOptions $options, Escaper $escaper, array $response, GlobalStructure $structure)
|
||||
{
|
||||
$this->escaper = $escaper;
|
||||
|
||||
@@ -25,7 +25,13 @@ class FacetsResponse
|
||||
|
||||
$atf = ElasticsearchOptions::getAggregableTechnicalFields();
|
||||
|
||||
foreach ($response['aggregations'] as $name => $aggregation) {
|
||||
// sort facets respecting the order defined in options
|
||||
foreach($options->getAggregableFields() as $name=>$foptions) {
|
||||
if(!array_key_exists($name, $response['aggregations'])) {
|
||||
continue;
|
||||
}
|
||||
$aggregation = $response['aggregations'][$name];
|
||||
|
||||
$tf = null;
|
||||
$valueFormatter = function($v){ return $v; }; // default equality formatter
|
||||
|
||||
@@ -78,6 +84,7 @@ class FacetsResponse
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@@ -35,11 +35,6 @@ final class GlobalStructure implements Structure
|
||||
*/
|
||||
private $private = array();
|
||||
|
||||
/**
|
||||
* @var Field[]
|
||||
*/
|
||||
private $facets = array();
|
||||
|
||||
/**
|
||||
* @var Flag[]
|
||||
*/
|
||||
@@ -145,9 +140,11 @@ final class GlobalStructure implements Structure
|
||||
$this->private[$name] = $field;
|
||||
}
|
||||
|
||||
/*
|
||||
if ($field->isFacet() && $field->isSearchable()) {
|
||||
$this->facets[$name] = $field;
|
||||
}
|
||||
*/
|
||||
|
||||
if ($field->hasConceptInference()) {
|
||||
$this->thesaurus_fields[$name] = $field;
|
||||
@@ -183,14 +180,6 @@ final class GlobalStructure implements Structure
|
||||
return $this->private;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Field[]
|
||||
*/
|
||||
public function getFacetFields()
|
||||
{
|
||||
return $this->facets;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Field[]
|
||||
*/
|
||||
|
@@ -47,14 +47,6 @@ final class LimitedStructure implements Structure
|
||||
return $this->limit($this->structure->getPrivateFields());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Field[]
|
||||
*/
|
||||
public function getFacetFields()
|
||||
{
|
||||
return $this->limit($this->structure->getFacetFields());
|
||||
}
|
||||
|
||||
public function getThesaurusEnabledFields()
|
||||
{
|
||||
return $this->limit($this->structure->getThesaurusEnabledFields());
|
||||
|
@@ -33,11 +33,6 @@ interface Structure
|
||||
*/
|
||||
public function getPrivateFields();
|
||||
|
||||
/**
|
||||
* @return Field[]
|
||||
*/
|
||||
public function getFacetFields();
|
||||
|
||||
/**
|
||||
* @return Field[]
|
||||
*/
|
||||
|
@@ -60,7 +60,7 @@ class BinariesRequirements extends RequirementCollection implements RequirementI
|
||||
);
|
||||
}
|
||||
|
||||
$exiftool = __DIR__ . '/../../../../../vendor/phpexiftool/exiftool/exiftool' . (defined('PHP_WINDOWS_VERSION_BUILD') ? '.exe' : '');
|
||||
$exiftool = __DIR__ . '/../../../../../vendor/exiftool/exiftool/exiftool' . (defined('PHP_WINDOWS_VERSION_BUILD') ? '.exe' : '');
|
||||
|
||||
$this->addRequirement(
|
||||
is_file($exiftool) && is_executable($exiftool),
|
||||
|
Reference in New Issue
Block a user