mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-23 09:53:15 +00:00
Merge branch 'master' of https://github.com/alchemy-fr/Phraseanet into PHRAS-2741-worker-service-part1
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());
|
||||
|
@@ -34,6 +34,11 @@ abstract class AbstractChecker implements CheckerInterface
|
||||
*/
|
||||
protected $collections = [];
|
||||
|
||||
/**
|
||||
* @var \collection[]
|
||||
*/
|
||||
protected $compareIgnoreCollections = [];
|
||||
|
||||
public function __construct(Application $app)
|
||||
{
|
||||
$this->app = $app;
|
||||
@@ -44,7 +49,7 @@ abstract class AbstractChecker implements CheckerInterface
|
||||
* Warning, you can not restrict on both databoxes and collections
|
||||
*
|
||||
* @param \databox[] $databoxes A databox or an array of databoxes
|
||||
* @return bool
|
||||
* @return \databox[]
|
||||
*
|
||||
* @throws \LogicException If already restricted to collections
|
||||
* @throws \InvalidArgumentException In case invalid databoxes are provided
|
||||
@@ -72,7 +77,7 @@ abstract class AbstractChecker implements CheckerInterface
|
||||
* Warning, you can not restrict on both databoxes and collections
|
||||
*
|
||||
* @param \collection[] $collections
|
||||
* @return bool
|
||||
* @return \collection[]
|
||||
*
|
||||
* @throws \LogicException If already restricted to databoxes
|
||||
* @throws \InvalidArgumentException In case invalid collections are provided
|
||||
@@ -95,6 +100,11 @@ abstract class AbstractChecker implements CheckerInterface
|
||||
return $this->collections;
|
||||
}
|
||||
|
||||
public function setCompareIgnoreCollections($collections)
|
||||
{
|
||||
$this->compareIgnoreCollections = $collections;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the checker should be executed against the current file
|
||||
*
|
||||
|
@@ -45,8 +45,18 @@ class Filename extends AbstractChecker
|
||||
*/
|
||||
public function check(EntityManager $em, File $file)
|
||||
{
|
||||
$boolean = empty(\record_adapter::get_records_by_originalname(
|
||||
$file->getCollection()->get_databox(), $file->getOriginalName(), $this->sensitive, 0, 1
|
||||
$excludedCollIds = [];
|
||||
if (!empty($this->compareIgnoreCollections)) {
|
||||
foreach ($this->compareIgnoreCollections as $collection) {
|
||||
// use only collection in the same databox and retrieve the coll_id
|
||||
if ($collection->get_sbas_id() === $file->getCollection()->get_sbas_id()) {
|
||||
$excludedCollIds[] = $collection->get_coll_id();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$boolean = empty(\record_adapter::getRecordsByOriginalnameWithExcludedCollIds(
|
||||
$file->getCollection()->get_databox(), $file->getOriginalName(), $this->sensitive, 0, 1, $excludedCollIds
|
||||
));
|
||||
|
||||
return new Response($boolean, $this);
|
||||
|
@@ -34,7 +34,17 @@ class Sha256 extends AbstractChecker
|
||||
*/
|
||||
public function check(EntityManager $em, File $file)
|
||||
{
|
||||
$boolean = empty($file->getCollection()->get_databox()->getRecordRepository()->findBySha256($file->getSha256()));
|
||||
$excludedCollIds = [];
|
||||
if (!empty($this->compareIgnoreCollections)) {
|
||||
foreach ($this->compareIgnoreCollections as $collection) {
|
||||
// use only collection in the same databox and retrieve the coll_id
|
||||
if ($collection->get_sbas_id() === $file->getCollection()->get_sbas_id()) {
|
||||
$excludedCollIds[] = $collection->get_coll_id();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$boolean = empty($file->getCollection()->get_databox()->getRecordRepository()->findBySha256WithExcludedCollIds($file->getSha256(), $excludedCollIds));
|
||||
|
||||
return new Response($boolean, $this);
|
||||
}
|
||||
|
@@ -33,7 +33,17 @@ class UUID extends AbstractChecker
|
||||
*/
|
||||
public function check(EntityManager $em, File $file)
|
||||
{
|
||||
$boolean = empty($file->getCollection()->get_databox()->getRecordRepository()->findByUuid($file->getUUID()));
|
||||
$excludedCollIds = [];
|
||||
if (!empty($this->compareIgnoreCollections)) {
|
||||
foreach ($this->compareIgnoreCollections as $collection) {
|
||||
// use only collection in the same databox and retrieve the coll_id
|
||||
if ($collection->get_sbas_id() === $file->getCollection()->get_sbas_id()) {
|
||||
$excludedCollIds[] = $collection->get_coll_id();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$boolean = empty($file->getCollection()->get_databox()->getRecordRepository()->findByUuidWithExcludedCollIds($file->getUUID(), $excludedCollIds));
|
||||
|
||||
return new Response($boolean, $this);
|
||||
}
|
||||
|
@@ -73,7 +73,7 @@ class RedisCache extends CacheProvider implements Cache
|
||||
*/
|
||||
protected function doDelete($id)
|
||||
{
|
||||
return $this->_redis->delete($id);
|
||||
return $this->_redis->del($id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -13,6 +13,7 @@ namespace Alchemy\Phrasea\Command\Setup;
|
||||
|
||||
use Alchemy\Phrasea\Command\Command;
|
||||
use Alchemy\Phrasea\Core\Configuration\StructureTemplate;
|
||||
use Alchemy\Phrasea\SearchEngine\Elastic\ElasticsearchOptions;
|
||||
use Doctrine\DBAL\Driver\Connection;
|
||||
use Symfony\Component\Console\Helper\DialogHelper;
|
||||
use Symfony\Component\Console\Input\ArrayInput;
|
||||
@@ -51,7 +52,9 @@ class Install extends Command
|
||||
->addOption('db-template', null, InputOption::VALUE_OPTIONAL, 'Databox template (' . $this->structureTemplate->toString() . ')', null)
|
||||
->addOption('data-path', null, InputOption::VALUE_OPTIONAL, 'Path to data repository', realpath(__DIR__ . '/../../../../../datas'))
|
||||
->addOption('server-name', null, InputOption::VALUE_OPTIONAL, 'Server name')
|
||||
->addOption('indexer', null, InputOption::VALUE_OPTIONAL, 'Path to Phraseanet Indexer', 'auto')
|
||||
->addOption('es-host', null, InputOption::VALUE_OPTIONAL, 'ElasticSearch server HTTP host', 'localhost')
|
||||
->addOption('es-port', null, InputOption::VALUE_OPTIONAL, 'ElasticSearch server HTTP port', 9200)
|
||||
->addOption('es-index', null, InputOption::VALUE_OPTIONAL, 'ElasticSearch index name', null)
|
||||
->addOption('yes', 'y', InputOption::VALUE_NONE, 'Answer yes to all questions');
|
||||
|
||||
return $this;
|
||||
@@ -121,6 +124,21 @@ class Install extends Command
|
||||
list($email, $password) = $this->getCredentials($input, $output, $dialog);
|
||||
$dataPath = $this->getDataPath($input, $output, $dialog);
|
||||
|
||||
if (! $input->getOption('yes')) {
|
||||
$output->writeln("<info>--- ElasticSearch connection settings ---</info>");
|
||||
}
|
||||
|
||||
list($esHost, $esPort) = $this->getESHost($input, $output, $dialog);
|
||||
$esIndexName = $this->getESIndexName($input, $output, $dialog);
|
||||
|
||||
$esOptions = ElasticsearchOptions::fromArray([
|
||||
'host' => $esHost,
|
||||
'port' => $esPort,
|
||||
'index' => $esIndexName
|
||||
]);
|
||||
|
||||
$output->writeln('');
|
||||
|
||||
if (!$input->getOption('yes')) {
|
||||
$continue = $dialog->askConfirmation($output, "<question>Phraseanet is going to be installed, continue ? (N/y)</question>", false);
|
||||
|
||||
@@ -132,6 +150,7 @@ class Install extends Command
|
||||
}
|
||||
|
||||
$this->container['phraseanet.installer']->install($email, $password, $abConn, $serverName, $dataPath, $dbConn, $templateName, $this->detectBinaries());
|
||||
$this->container['conf']->set(['main', 'search-engine', 'options'], $esOptions->toArray());
|
||||
|
||||
if (null !== $this->getApplication()) {
|
||||
$command = $this->getApplication()->find('crossdomain:generate');
|
||||
@@ -339,6 +358,35 @@ class Install extends Command
|
||||
return $serverName;
|
||||
}
|
||||
|
||||
private function getESHost(InputInterface $input, OutputInterface $output, DialogHelper $dialog)
|
||||
{
|
||||
$host = $input->getOption('es-host');
|
||||
$port = (int) $input->getOption('es-port');
|
||||
|
||||
if (! $input->getOption('yes')) {
|
||||
while (! $host) {
|
||||
$host = $dialog->ask($output, 'ElasticSearch server host : ', null);
|
||||
};
|
||||
|
||||
while ($port <= 0 || $port >= 65535) {
|
||||
$port = (int) $dialog->ask($output, 'ElasticSearch server port : ', null);
|
||||
};
|
||||
}
|
||||
|
||||
return [ $host, $port ];
|
||||
}
|
||||
|
||||
private function getESIndexName(InputInterface $input, OutputInterface $output, DialogHelper $dialog)
|
||||
{
|
||||
$index = $input->getOption('es-index');
|
||||
|
||||
if (! $input->getOption('yes')) {
|
||||
$index = $dialog->ask($output, 'ElasticSearch server index name (blank to autogenerate) : ', null);
|
||||
}
|
||||
|
||||
return $index;
|
||||
}
|
||||
|
||||
private function detectBinaries()
|
||||
{
|
||||
return [
|
||||
|
@@ -314,6 +314,9 @@ class FieldsController extends Controller
|
||||
->set_readonly($data['readonly'])
|
||||
->set_type($data['type'])
|
||||
->set_tbranch($data['tbranch'])
|
||||
->set_generate_cterms($data['generate_cterms'])
|
||||
->set_gui_editable($data['gui_editable'])
|
||||
->set_gui_visible($data['gui_visible'])
|
||||
->set_report($data['report'])
|
||||
->setVocabularyControl(null)
|
||||
->setVocabularyRestricted(false);
|
||||
@@ -349,7 +352,7 @@ class FieldsController extends Controller
|
||||
{
|
||||
return [
|
||||
'name', 'multi', 'thumbtitle', 'tag', 'business', 'indexable', 'aggregable',
|
||||
'required', 'separator', 'readonly', 'type', 'tbranch', 'report',
|
||||
'required', 'separator', 'readonly', 'gui_editable', 'gui_visible' , 'type', 'tbranch', 'generate_cterms', 'report',
|
||||
'vocabulary-type', 'vocabulary-restricted', 'dces-element', 'labels'
|
||||
];
|
||||
}
|
||||
|
@@ -354,7 +354,7 @@ class SubdefsController extends Controller
|
||||
Subdef::TYPE_VIDEO => [
|
||||
"definitions" => [
|
||||
"video codec H264" => null,
|
||||
"144P H264 128 kbps ACC 128kbps" => [
|
||||
"144P H264 128 kbps MP3 128kbps" => [
|
||||
Video::OPTION_AUDIOBITRATE => "128",
|
||||
Video::OPTION_AUDIOSAMPLERATE => "44100",
|
||||
Video::OPTION_BITRATE => "128",
|
||||
@@ -362,10 +362,10 @@ class SubdefsController extends Controller
|
||||
Video::OPTION_SIZE => "256",
|
||||
Video::OPTION_FRAMERATE => "25",
|
||||
Video::OPTION_VCODEC => "libx264",
|
||||
Video::OPTION_ACODEC => "libfaac",
|
||||
Video::OPTION_ACODEC => "libmp3lame",
|
||||
Subdef::OPTION_DEVICE => ["all"]
|
||||
],
|
||||
"240P H264 256 kbps ACC 128kbps" => [
|
||||
"240P H264 256 kbps MP3 128kbps" => [
|
||||
Video::OPTION_AUDIOBITRATE => "128",
|
||||
Video::OPTION_AUDIOSAMPLERATE => "44100",
|
||||
Video::OPTION_BITRATE => "256",
|
||||
@@ -373,10 +373,10 @@ class SubdefsController extends Controller
|
||||
Video::OPTION_SIZE => "426",
|
||||
Video::OPTION_FRAMERATE => "25",
|
||||
Video::OPTION_VCODEC => "libx264",
|
||||
Video::OPTION_ACODEC => "libfaac",
|
||||
Video::OPTION_ACODEC => "libmp3lame",
|
||||
Subdef::OPTION_DEVICE => ["all"]
|
||||
],
|
||||
"360P H264 576 kbps ACC 128kbps" => [
|
||||
"360P H264 576 kbps MP3 128kbps" => [
|
||||
Video::OPTION_AUDIOBITRATE => "128",
|
||||
Video::OPTION_AUDIOSAMPLERATE => "44100",
|
||||
Video::OPTION_BITRATE => "576",
|
||||
@@ -384,10 +384,10 @@ class SubdefsController extends Controller
|
||||
Video::OPTION_SIZE => "480",
|
||||
Video::OPTION_FRAMERATE => "25",
|
||||
Video::OPTION_VCODEC => "libtheora",
|
||||
Video::OPTION_ACODEC => "libfaac",
|
||||
Video::OPTION_ACODEC => "libmp3lame",
|
||||
Subdef::OPTION_DEVICE => ["all"]
|
||||
],
|
||||
"480P H264 750 kbps ACC 128kbps" => [
|
||||
"480P H264 750 kbps MP3 128kbps" => [
|
||||
Video::OPTION_AUDIOBITRATE => "128",
|
||||
Video::OPTION_AUDIOSAMPLERATE => "44100",
|
||||
Video::OPTION_BITRATE => "750",
|
||||
@@ -395,10 +395,10 @@ class SubdefsController extends Controller
|
||||
Video::OPTION_SIZE => "854",
|
||||
Video::OPTION_FRAMERATE => "25",
|
||||
Video::OPTION_VCODEC => "libx264",
|
||||
Video::OPTION_ACODEC => "libfaac",
|
||||
Video::OPTION_ACODEC => "libmp3lame",
|
||||
Subdef::OPTION_DEVICE => ["all"]
|
||||
],
|
||||
"720P H264 1492 kbps ACC 128kbps" => [
|
||||
"720P H264 1492 kbps MP3 128kbps" => [
|
||||
Video::OPTION_AUDIOBITRATE => "128",
|
||||
Video::OPTION_AUDIOSAMPLERATE => "44100",
|
||||
Video::OPTION_BITRATE => "1492",
|
||||
@@ -406,10 +406,10 @@ class SubdefsController extends Controller
|
||||
Video::OPTION_SIZE => "1280",
|
||||
Video::OPTION_FRAMERATE => "25",
|
||||
Video::OPTION_VCODEC => "libx264",
|
||||
Video::OPTION_ACODEC => "libfaac",
|
||||
Video::OPTION_ACODEC => "libmp3lame",
|
||||
Subdef::OPTION_DEVICE => ["all"]
|
||||
],
|
||||
"1080P H264 2420 kbps ACC 128kbps" => [
|
||||
"1080P H264 2420 kbps MP3 128kbps" => [
|
||||
Video::OPTION_AUDIOBITRATE => "128",
|
||||
Video::OPTION_AUDIOSAMPLERATE => "44100",
|
||||
Video::OPTION_BITRATE => "2420",
|
||||
@@ -417,11 +417,77 @@ class SubdefsController extends Controller
|
||||
Video::OPTION_SIZE => "1920",
|
||||
Video::OPTION_FRAMERATE => "25",
|
||||
Video::OPTION_VCODEC => "libx264",
|
||||
Video::OPTION_ACODEC => "libfaac",
|
||||
Video::OPTION_ACODEC => "libmp3lame",
|
||||
Subdef::OPTION_DEVICE => ["all"]
|
||||
],
|
||||
"144P H264 128 kbps AAC 128kbps" => [
|
||||
Video::OPTION_AUDIOBITRATE => "128",
|
||||
Video::OPTION_AUDIOSAMPLERATE => "44100",
|
||||
Video::OPTION_BITRATE => "128",
|
||||
Video::OPTION_GOPSIZE => "25",
|
||||
Video::OPTION_SIZE => "256",
|
||||
Video::OPTION_FRAMERATE => "25",
|
||||
Video::OPTION_VCODEC => "libx264",
|
||||
Video::OPTION_ACODEC => "libfdk_aac",
|
||||
Subdef::OPTION_DEVICE => ["all"]
|
||||
],
|
||||
"240P H264 256 kbps AAC 128kbps" => [
|
||||
Video::OPTION_AUDIOBITRATE => "128",
|
||||
Video::OPTION_AUDIOSAMPLERATE => "44100",
|
||||
Video::OPTION_BITRATE => "256",
|
||||
Video::OPTION_GOPSIZE => "25",
|
||||
Video::OPTION_SIZE => "426",
|
||||
Video::OPTION_FRAMERATE => "25",
|
||||
Video::OPTION_VCODEC => "libx264",
|
||||
Video::OPTION_ACODEC => "libfdk_aac",
|
||||
Subdef::OPTION_DEVICE => ["all"]
|
||||
],
|
||||
"360P H264 576 kbps AAC 128kbps" => [
|
||||
Video::OPTION_AUDIOBITRATE => "128",
|
||||
Video::OPTION_AUDIOSAMPLERATE => "44100",
|
||||
Video::OPTION_BITRATE => "576",
|
||||
Video::OPTION_GOPSIZE => "25",
|
||||
Video::OPTION_SIZE => "480",
|
||||
Video::OPTION_FRAMERATE => "25",
|
||||
Video::OPTION_VCODEC => "libtheora",
|
||||
Video::OPTION_ACODEC => "libfdk_aac",
|
||||
Subdef::OPTION_DEVICE => ["all"]
|
||||
],
|
||||
"480P H264 750 kbps AAC 128kbps" => [
|
||||
Video::OPTION_AUDIOBITRATE => "128",
|
||||
Video::OPTION_AUDIOSAMPLERATE => "44100",
|
||||
Video::OPTION_BITRATE => "750",
|
||||
Video::OPTION_GOPSIZE => "25",
|
||||
Video::OPTION_SIZE => "854",
|
||||
Video::OPTION_FRAMERATE => "25",
|
||||
Video::OPTION_VCODEC => "libx264",
|
||||
Video::OPTION_ACODEC => "libfdk_aac",
|
||||
Subdef::OPTION_DEVICE => ["all"]
|
||||
],
|
||||
"720P H264 1492 kbps AAC 128kbps" => [
|
||||
Video::OPTION_AUDIOBITRATE => "128",
|
||||
Video::OPTION_AUDIOSAMPLERATE => "44100",
|
||||
Video::OPTION_BITRATE => "1492",
|
||||
Video::OPTION_GOPSIZE => "25",
|
||||
Video::OPTION_SIZE => "1280",
|
||||
Video::OPTION_FRAMERATE => "25",
|
||||
Video::OPTION_VCODEC => "libx264",
|
||||
Video::OPTION_ACODEC => "libfdk_aac",
|
||||
Subdef::OPTION_DEVICE => ["all"]
|
||||
],
|
||||
"1080P H264 2420 kbps AAC 128kbps" => [
|
||||
Video::OPTION_AUDIOBITRATE => "128",
|
||||
Video::OPTION_AUDIOSAMPLERATE => "44100",
|
||||
Video::OPTION_BITRATE => "2420",
|
||||
Video::OPTION_GOPSIZE => "25",
|
||||
Video::OPTION_SIZE => "1920",
|
||||
Video::OPTION_FRAMERATE => "25",
|
||||
Video::OPTION_VCODEC => "libx264",
|
||||
Video::OPTION_ACODEC => "libfdk_aac",
|
||||
Subdef::OPTION_DEVICE => ["all"]
|
||||
],
|
||||
"video codec libvpx" => null,
|
||||
"144P webm 128 kbps ACC 128kbps" => [
|
||||
"144P webm 128 kbps MP3 128kbps" => [
|
||||
Video::OPTION_AUDIOBITRATE => "128",
|
||||
Video::OPTION_AUDIOSAMPLERATE => "44100",
|
||||
Video::OPTION_BITRATE => "128",
|
||||
@@ -429,10 +495,10 @@ class SubdefsController extends Controller
|
||||
Video::OPTION_SIZE => "256",
|
||||
Video::OPTION_FRAMERATE => "25",
|
||||
Video::OPTION_VCODEC => "libvpx",
|
||||
Video::OPTION_ACODEC => "libfaac",
|
||||
Video::OPTION_ACODEC => "libmp3lame",
|
||||
Subdef::OPTION_DEVICE => ["all"]
|
||||
],
|
||||
"240P webm 256 kbps ACC 128kbps" => [
|
||||
"240P webm 256 kbps MP3 128kbps" => [
|
||||
Video::OPTION_AUDIOBITRATE => "128",
|
||||
Video::OPTION_AUDIOSAMPLERATE => "44100",
|
||||
Video::OPTION_BITRATE => "256",
|
||||
@@ -440,10 +506,10 @@ class SubdefsController extends Controller
|
||||
Video::OPTION_SIZE => "426",
|
||||
Video::OPTION_FRAMERATE => "25",
|
||||
Video::OPTION_VCODEC => "libvpx",
|
||||
Video::OPTION_ACODEC => "libfaac",
|
||||
Video::OPTION_ACODEC => "libmp3lame",
|
||||
Subdef::OPTION_DEVICE => ["all"]
|
||||
],
|
||||
"360P webm 576 kbps ACC 128kbps" => [
|
||||
"360P webm 576 kbps MP3 128kbps" => [
|
||||
Video::OPTION_AUDIOBITRATE => "128",
|
||||
Video::OPTION_AUDIOSAMPLERATE => "44100",
|
||||
Video::OPTION_BITRATE => "576",
|
||||
@@ -451,10 +517,10 @@ class SubdefsController extends Controller
|
||||
Video::OPTION_SIZE => "480",
|
||||
Video::OPTION_FRAMERATE => "25",
|
||||
Video::OPTION_VCODEC => "libvpx",
|
||||
Video::OPTION_ACODEC => "libfaac",
|
||||
Video::OPTION_ACODEC => "libmp3lame",
|
||||
Subdef::OPTION_DEVICE => ["all"]
|
||||
],
|
||||
"480P webm 750 kbps ACC 128kbps" => [
|
||||
"480P webm 750 kbps MP3 128kbps" => [
|
||||
Video::OPTION_AUDIOBITRATE => "128",
|
||||
Video::OPTION_AUDIOSAMPLERATE => "44100",
|
||||
Video::OPTION_BITRATE => "750",
|
||||
@@ -462,10 +528,10 @@ class SubdefsController extends Controller
|
||||
Video::OPTION_SIZE => "854",
|
||||
Video::OPTION_FRAMERATE => "25",
|
||||
Video::OPTION_VCODEC => "libvpx",
|
||||
Video::OPTION_ACODEC => "libfaac",
|
||||
Video::OPTION_ACODEC => "libmp3lame",
|
||||
Subdef::OPTION_DEVICE => ["all"]
|
||||
],
|
||||
"720P webm 1492 kbps ACC 128kbps" => [
|
||||
"720P webm 1492 kbps MP3 128kbps" => [
|
||||
Video::OPTION_AUDIOBITRATE => "128",
|
||||
Video::OPTION_AUDIOSAMPLERATE => "44100",
|
||||
Video::OPTION_BITRATE => "1492",
|
||||
@@ -473,10 +539,10 @@ class SubdefsController extends Controller
|
||||
Video::OPTION_SIZE => "1280",
|
||||
Video::OPTION_FRAMERATE => "25",
|
||||
Video::OPTION_VCODEC => "libvpx",
|
||||
Video::OPTION_ACODEC => "libfaac",
|
||||
Video::OPTION_ACODEC => "libmp3lame",
|
||||
Subdef::OPTION_DEVICE => ["all"]
|
||||
],
|
||||
"1080P webm 2420 kbps ACC 128kbps" => [
|
||||
"1080P webm 2420 kbps MP3 128kbps" => [
|
||||
Video::OPTION_AUDIOBITRATE => "128",
|
||||
Video::OPTION_AUDIOSAMPLERATE => "44100",
|
||||
Video::OPTION_BITRATE => "2420",
|
||||
@@ -484,7 +550,73 @@ class SubdefsController extends Controller
|
||||
Video::OPTION_SIZE => "1920",
|
||||
Video::OPTION_FRAMERATE => "25",
|
||||
Video::OPTION_VCODEC => "libvpx",
|
||||
Video::OPTION_ACODEC => "libfaac",
|
||||
Video::OPTION_ACODEC => "libmp3lame",
|
||||
Subdef::OPTION_DEVICE => ["all"]
|
||||
],
|
||||
"144P webm 128 kbps AAC 128kbps" => [
|
||||
Video::OPTION_AUDIOBITRATE => "128",
|
||||
Video::OPTION_AUDIOSAMPLERATE => "44100",
|
||||
Video::OPTION_BITRATE => "128",
|
||||
Video::OPTION_GOPSIZE => "25",
|
||||
Video::OPTION_SIZE => "256",
|
||||
Video::OPTION_FRAMERATE => "25",
|
||||
Video::OPTION_VCODEC => "libvpx",
|
||||
Video::OPTION_ACODEC => "libfdk_aac",
|
||||
Subdef::OPTION_DEVICE => ["all"]
|
||||
],
|
||||
"240P webm 256 kbps AAC 128kbps" => [
|
||||
Video::OPTION_AUDIOBITRATE => "128",
|
||||
Video::OPTION_AUDIOSAMPLERATE => "44100",
|
||||
Video::OPTION_BITRATE => "256",
|
||||
Video::OPTION_GOPSIZE => "25",
|
||||
Video::OPTION_SIZE => "426",
|
||||
Video::OPTION_FRAMERATE => "25",
|
||||
Video::OPTION_VCODEC => "libvpx",
|
||||
Video::OPTION_ACODEC => "libfdk_aac",
|
||||
Subdef::OPTION_DEVICE => ["all"]
|
||||
],
|
||||
"360P webm 576 kbps AAC 128kbps" => [
|
||||
Video::OPTION_AUDIOBITRATE => "128",
|
||||
Video::OPTION_AUDIOSAMPLERATE => "44100",
|
||||
Video::OPTION_BITRATE => "576",
|
||||
Video::OPTION_GOPSIZE => "25",
|
||||
Video::OPTION_SIZE => "480",
|
||||
Video::OPTION_FRAMERATE => "25",
|
||||
Video::OPTION_VCODEC => "libvpx",
|
||||
Video::OPTION_ACODEC => "libfdk_aac",
|
||||
Subdef::OPTION_DEVICE => ["all"]
|
||||
],
|
||||
"480P webm 750 kbps AAC 128kbps" => [
|
||||
Video::OPTION_AUDIOBITRATE => "128",
|
||||
Video::OPTION_AUDIOSAMPLERATE => "44100",
|
||||
Video::OPTION_BITRATE => "750",
|
||||
Video::OPTION_GOPSIZE => "25",
|
||||
Video::OPTION_SIZE => "854",
|
||||
Video::OPTION_FRAMERATE => "25",
|
||||
Video::OPTION_VCODEC => "libvpx",
|
||||
Video::OPTION_ACODEC => "libfdk_aac",
|
||||
Subdef::OPTION_DEVICE => ["all"]
|
||||
],
|
||||
"720P webm 1492 kbps AAC 128kbps" => [
|
||||
Video::OPTION_AUDIOBITRATE => "128",
|
||||
Video::OPTION_AUDIOSAMPLERATE => "44100",
|
||||
Video::OPTION_BITRATE => "1492",
|
||||
Video::OPTION_GOPSIZE => "25",
|
||||
Video::OPTION_SIZE => "1280",
|
||||
Video::OPTION_FRAMERATE => "25",
|
||||
Video::OPTION_VCODEC => "libvpx",
|
||||
Video::OPTION_ACODEC => "libfdk_aac",
|
||||
Subdef::OPTION_DEVICE => ["all"]
|
||||
],
|
||||
"1080P webm 2420 kbps AAC 128kbps" => [
|
||||
Video::OPTION_AUDIOBITRATE => "128",
|
||||
Video::OPTION_AUDIOSAMPLERATE => "44100",
|
||||
Video::OPTION_BITRATE => "2420",
|
||||
Video::OPTION_GOPSIZE => "25",
|
||||
Video::OPTION_SIZE => "1920",
|
||||
Video::OPTION_FRAMERATE => "25",
|
||||
Video::OPTION_VCODEC => "libvpx",
|
||||
Video::OPTION_ACODEC => "libfdk_aac",
|
||||
Subdef::OPTION_DEVICE => ["all"]
|
||||
],
|
||||
],
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -594,6 +594,9 @@ class V1Controller extends Controller
|
||||
],
|
||||
'separator' => $databox_field->get_separator(),
|
||||
'thesaurus_branch' => $databox_field->get_tbranch(),
|
||||
'generate_cterms' => $databox_field->get_generate_cterms(),
|
||||
'gui_editable' => $databox_field->get_gui_editable(),
|
||||
'gui_visible' => $databox_field->get_gui_visible(),
|
||||
'type' => $databox_field->get_type(),
|
||||
'indexable' => $databox_field->is_indexable(),
|
||||
'multivalue' => $databox_field->is_multi(),
|
||||
|
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);
|
||||
}
|
||||
}
|
||||
}
|
@@ -75,6 +75,9 @@ class EditController extends Controller
|
||||
'format' => '',
|
||||
'explain' => '',
|
||||
'tbranch' => $meta->get_tbranch(),
|
||||
'generate_cterms' => $meta->get_generate_cterms(),
|
||||
'gui_editable' => $meta->get_gui_editable(),
|
||||
'gui_visible' => $meta->get_gui_visible(),
|
||||
'maxLength' => $meta->get_tag()
|
||||
->getMaxLength(),
|
||||
'minLength' => $meta->get_tag()
|
||||
|
@@ -70,7 +70,7 @@ class LazaretController extends Controller
|
||||
public function getElement($file_id)
|
||||
{
|
||||
$ret = ['success' => false, 'message' => '', 'result' => []];
|
||||
|
||||
|
||||
/* @var LazaretFile $lazaretFile */
|
||||
$lazaretFile = $this->getLazaretFileRepository()->find($file_id);
|
||||
|
||||
@@ -126,6 +126,16 @@ class LazaretController extends Controller
|
||||
|
||||
$ret = $lazaretManipulator->add($file_id, $keepAttributes, $attributesToKeep);
|
||||
|
||||
try{
|
||||
// get the new record
|
||||
$record = \Collection::getByBaseId($this->app, $request->request->get('bas_id'))->get_databox()->get_record($ret['result']['record_id']);
|
||||
$postStatus = (array) $request->request->get('status');
|
||||
// update status
|
||||
$this->updateRecordStatus($record, $postStatus);
|
||||
}catch(\Exception $e){
|
||||
$ret['message'] = $this->app->trans('An error occured when wanting to change status!');
|
||||
}
|
||||
|
||||
return $this->app->json($ret);
|
||||
}
|
||||
|
||||
@@ -216,6 +226,7 @@ class LazaretController extends Controller
|
||||
|
||||
return $this->app->json($ret);
|
||||
}
|
||||
$postStatus = (array) $request->request->get('status');
|
||||
|
||||
$path = $this->app['tmp.lazaret.path'] . '/';
|
||||
$lazaretFileName = $path .$lazaretFile->getFilename();
|
||||
@@ -233,6 +244,9 @@ class LazaretController extends Controller
|
||||
''
|
||||
);
|
||||
|
||||
// update status
|
||||
$this->updateRecordStatus($record, $postStatus);
|
||||
|
||||
//Delete lazaret file
|
||||
$manager = $this->getEntityManager();
|
||||
$manager->remove($lazaretFile);
|
||||
@@ -278,6 +292,35 @@ class LazaretController extends Controller
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param $databox_id
|
||||
* @param $record_id
|
||||
* @return \Symfony\Component\HttpFoundation\JsonResponse
|
||||
*/
|
||||
public function getDestinationStatus(Request $request, $databox_id, $record_id)
|
||||
{
|
||||
if (!$request->isXmlHttpRequest()) {
|
||||
$this->app->abort(400);
|
||||
}
|
||||
$record = new \record_adapter($this->app, (int) $databox_id, (int) $record_id);
|
||||
$databox = $this->findDataboxById($databox_id);
|
||||
$statusStructure = $databox->getStatusStructure();
|
||||
$recordsStatuses = [];
|
||||
foreach ($statusStructure as $status) {
|
||||
// make the key as a string for the json usage in javascript
|
||||
$bit = "'".$status['bit']."'";
|
||||
if (!isset($recordsStatuses[$bit])) {
|
||||
$recordsStatuses[$bit] = $status;
|
||||
}
|
||||
$statusSet = \databox_status::bitIsSet($record->getStatusBitField(), $status['bit']);
|
||||
if (!isset($recordsStatuses[$bit]['flag'])) {
|
||||
$recordsStatuses[$bit]['flag'] = (int) $statusSet;
|
||||
}
|
||||
}
|
||||
return $this->app->json(['status' => $recordsStatuses]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return LazaretFileRepository
|
||||
*/
|
||||
@@ -293,4 +336,32 @@ class LazaretController extends Controller
|
||||
{
|
||||
return $this->app['border-manager'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set new status to selected record
|
||||
*
|
||||
* @param \record_adapter $record
|
||||
* @param array $postStatus
|
||||
* @return array|null
|
||||
*/
|
||||
private function updateRecordStatus(\record_adapter $record, array $postStatus)
|
||||
{
|
||||
$sbasId = $record->getDataboxId();
|
||||
if (isset($postStatus[$sbasId]) && is_array($postStatus[$sbasId])) {
|
||||
$postStatus = $postStatus[$sbasId];
|
||||
$currentStatus = strrev($record->getStatus());
|
||||
$newStatus = '';
|
||||
foreach (range(0, 31) as $i) {
|
||||
$newStatus .= isset($postStatus[$i]) ? ($postStatus[$i] ? '1' : '0') : $currentStatus[$i];
|
||||
}
|
||||
$record->setStatus(strrev($newStatus));
|
||||
$this->getDataboxLogger($record->getDatabox())
|
||||
->log($record, \Session_Logger::EVENT_STATUS, '', '');
|
||||
return [
|
||||
'current_status' => $currentStatus,
|
||||
'new_status' => $newStatus,
|
||||
];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@@ -193,7 +193,7 @@ class PushController extends Controller
|
||||
'Validation from %user%', [
|
||||
'%user%' => $this->getAuthenticatedUser()->getDisplayName(),
|
||||
]));
|
||||
$validation_description = $request->request->get('validation_description');
|
||||
$validation_description = $request->request->get('message');
|
||||
|
||||
$participants = $request->request->get('participants');
|
||||
|
||||
|
@@ -341,10 +341,20 @@ class QueryController extends Controller
|
||||
|
||||
if ($result->getTotal() === 0) {
|
||||
$template = 'prod/results/help.html.twig';
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
$template = 'prod/results/records.html.twig';
|
||||
}
|
||||
$json['results'] = $this->render($template, ['results'=> $result]);
|
||||
|
||||
/** @var \Closure $filter */
|
||||
$filter = $this->app['plugin.filter_by_authorization'];
|
||||
|
||||
$plugins = [
|
||||
'workzone' => $filter('workzone'),
|
||||
'actionbar' => $filter('actionbar'),
|
||||
];
|
||||
|
||||
$json['results'] = $this->render($template, ['results'=> $result, 'plugins'=>$plugins]);
|
||||
|
||||
|
||||
// add technical fields
|
||||
@@ -382,7 +392,6 @@ class QueryController extends Controller
|
||||
'labels' => $field->get_labels(),
|
||||
'type' => $field->get_type(),
|
||||
'field' => $field->get_name(),
|
||||
'query' => "field." . $field->get_name() . ":%s",
|
||||
'trans_label' => $field->get_label($this->app['locale']),
|
||||
];
|
||||
$field->get_label($this->app['locale']);
|
||||
|
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;
|
||||
}
|
||||
}
|
@@ -82,6 +82,11 @@ class Lazaret implements ControllerProviderInterface, ServiceProviderInterface
|
||||
->assert('file_id', '\d+')
|
||||
->bind('lazaret_thumbnail');
|
||||
|
||||
$controllers->get('/{databox_id}/{record_id}/status', 'controller.prod.lazaret:getDestinationStatus')
|
||||
->assert('databox_id', '\d+')
|
||||
->assert('record_id', '\d+')
|
||||
->bind('lazaret_destination_status');
|
||||
|
||||
return $controllers;
|
||||
}
|
||||
}
|
||||
|
@@ -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());
|
||||
}
|
||||
|
||||
|
@@ -78,6 +78,20 @@ class BorderManagerServiceProvider implements ServiceProviderInterface
|
||||
|
||||
$checkerObj->restrictToCollections($collections);
|
||||
}
|
||||
|
||||
if (isset($checker['compare-ignore-collections'])) {
|
||||
$collections = [];
|
||||
foreach ($checker['compare-ignore-collections'] as $base_id) {
|
||||
try {
|
||||
$collections[] = \collection::getByBaseId($app, $base_id);
|
||||
} catch (\Exception $e) {
|
||||
throw new \InvalidArgumentException('Invalid collection option');
|
||||
}
|
||||
}
|
||||
|
||||
$checkerObj->setCompareIgnoreCollections($collections);
|
||||
}
|
||||
|
||||
$registeredCheckers[] = $checkerObj;
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
$app['monolog']->error(
|
||||
|
@@ -16,7 +16,7 @@ class Version
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $number = '4.1.0-alpha.15a';
|
||||
private $number = '4.1.0-alpha.19a';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
|
@@ -36,6 +36,9 @@ final class DbalDataboxFieldRepository implements DataboxFieldRepository
|
||||
'label_fr',
|
||||
'label_de',
|
||||
'label_nl',
|
||||
'generate_cterms',
|
||||
'gui_editable',
|
||||
'gui_visible',
|
||||
];
|
||||
|
||||
/** @var DataboxFieldFactory */
|
||||
|
@@ -82,6 +82,34 @@ class LegacyRecordRepository implements RecordRepository
|
||||
return $this->mapRecordsFromResultSet($result);
|
||||
}
|
||||
|
||||
public function findBySha256WithExcludedCollIds($sha256, $excludedCollIds = [])
|
||||
{
|
||||
static $sql;
|
||||
|
||||
if (!$sql) {
|
||||
$qb = $this->createSelectBuilder()
|
||||
->where('sha256 = :sha256');
|
||||
|
||||
if (!empty($excludedCollIds)) {
|
||||
$qb->andWhere($qb->expr()->notIn('coll_id', ':coll_id'));
|
||||
}
|
||||
|
||||
$sql = $qb->getSQL();
|
||||
}
|
||||
|
||||
$result = $this->databox->get_connection()->fetchAll($sql,
|
||||
[
|
||||
'sha256' => $sha256,
|
||||
'coll_id' => $excludedCollIds
|
||||
],
|
||||
[
|
||||
':coll_id' => Connection::PARAM_INT_ARRAY
|
||||
]
|
||||
);
|
||||
|
||||
return $this->mapRecordsFromResultSet($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $uuid
|
||||
* @return \record_adapter[]
|
||||
@@ -99,6 +127,40 @@ class LegacyRecordRepository implements RecordRepository
|
||||
return $this->mapRecordsFromResultSet($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $uuid
|
||||
* @param array $excludedCollIds
|
||||
* @return \record_adapter[]
|
||||
*/
|
||||
public function findByUuidWithExcludedCollIds($uuid, $excludedCollIds = [])
|
||||
{
|
||||
static $sql;
|
||||
|
||||
if (!$sql) {
|
||||
$qb = $this->createSelectBuilder()
|
||||
->where('uuid = :uuid')
|
||||
;
|
||||
|
||||
if (!empty($excludedCollIds)) {
|
||||
$qb->andWhere($qb->expr()->notIn('coll_id', ':coll_id'));
|
||||
}
|
||||
|
||||
$sql = $qb->getSQL();
|
||||
}
|
||||
|
||||
$result = $this->databox->get_connection()->fetchAll($sql,
|
||||
[
|
||||
'uuid' => $uuid,
|
||||
'coll_id' => $excludedCollIds
|
||||
],
|
||||
[
|
||||
':coll_id' => Connection::PARAM_INT_ARRAY
|
||||
]
|
||||
);
|
||||
|
||||
return $this->mapRecordsFromResultSet($result);
|
||||
}
|
||||
|
||||
public function findByRecordIds(array $recordIds)
|
||||
{
|
||||
static $sql;
|
||||
@@ -120,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 [];
|
||||
@@ -129,25 +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'
|
||||
)
|
||||
->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(
|
||||
|
@@ -26,12 +26,26 @@ interface RecordRepository
|
||||
*/
|
||||
public function findBySha256($sha256);
|
||||
|
||||
/**
|
||||
* @param string $sha256
|
||||
* @param array $excludedCollIds
|
||||
* @return \record_adapter[]
|
||||
*/
|
||||
public function findBySha256WithExcludedCollIds($sha256, $excludedCollIds = []);
|
||||
|
||||
/**
|
||||
* @param string $uuid
|
||||
* @return \record_adapter[]
|
||||
*/
|
||||
public function findByUuid($uuid);
|
||||
|
||||
/**
|
||||
* @param string $uuid
|
||||
* @param array $excludedCollIds
|
||||
* @return \record_adapter[]
|
||||
*/
|
||||
public function findByUuidWithExcludedCollIds($uuid, $excludedCollIds = []);
|
||||
|
||||
/**
|
||||
* @param array $recordIds
|
||||
* @return \record_adapter[]
|
||||
@@ -43,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);
|
||||
|
||||
|
||||
/**
|
||||
|
@@ -33,7 +33,7 @@ class Video extends Audio
|
||||
$this->registerOption(new OptionType\Range($this->translator->trans('Frame Rate'), self::OPTION_FRAMERATE, 1, 200, 20));
|
||||
$this->registerOption(new OptionType\Enum($this->translator->trans('Video Codec'), self::OPTION_VCODEC, ['libx264', 'libvpx', 'libtheora'], 'libx264'));
|
||||
$this->unregisterOption(self::OPTION_ACODEC);
|
||||
$this->registerOption(new OptionType\Enum($this->translator->trans('Audio Codec'), self::OPTION_ACODEC, ['libfaac', 'libvo_aacenc', 'libmp3lame', 'libvorbis'], 'libfaac'));
|
||||
$this->registerOption(new OptionType\Enum($this->translator->trans('Audio Codec'), self::OPTION_ACODEC, ['libfaac', 'libvo_aacenc', 'libmp3lame', 'libvorbis', 'libfdk_aac'], 'libmp3lame'));
|
||||
}
|
||||
|
||||
public function getType()
|
||||
|
@@ -12,6 +12,7 @@
|
||||
namespace Alchemy\Phrasea\Model\Entities;
|
||||
|
||||
use Alchemy\Phrasea\Application;
|
||||
use Alchemy\Phrasea\Border\Attribute\AttributeInterface;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Gedmo\Mapping\Annotation as Gedmo;
|
||||
use \record_adapter;
|
||||
@@ -474,4 +475,32 @@ class LazaretFile
|
||||
return $merged;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Application $app
|
||||
* @return array|null
|
||||
*/
|
||||
public function getStatus(Application $app)
|
||||
{
|
||||
/**@var LazaretAttribute $atribute*/
|
||||
foreach ($this->attributes as $atribute) {
|
||||
if ($atribute->getName() == AttributeInterface::NAME_STATUS) {
|
||||
$databox = $this->getCollection($app)->get_databox();
|
||||
$statusStructure = $databox->getStatusStructure();
|
||||
$recordsStatuses = [];
|
||||
foreach ($statusStructure as $status) {
|
||||
$bit = $status['bit'];
|
||||
if (!isset($recordsStatuses[$bit])) {
|
||||
$recordsStatuses[$bit] = $status;
|
||||
}
|
||||
$statusSet = \databox_status::bitIsSet(bindec($atribute->getValue()), $bit);
|
||||
if (!isset($recordsStatuses[$bit]['flag'])) {
|
||||
$recordsStatuses[$bit]['flag'] = (int) $statusSet;
|
||||
}
|
||||
}
|
||||
return $recordsStatuses;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -226,6 +226,8 @@ class LazaretManipulator
|
||||
$this->entityManager->remove($lazaretFile);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$ret['result']['record_id'] = $record->getRecordId();
|
||||
|
||||
$ret['success'] = true;
|
||||
} catch (\Exception $e) {
|
||||
$ret['message'] = $this->app->trans('An error occured');
|
||||
|
@@ -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()
|
||||
];
|
||||
|
@@ -45,6 +45,9 @@ class TextNode extends AbstractTermNode implements ContextAbleInterface
|
||||
foreach ($context->localizeField($field) as $f) {
|
||||
$index_fields[] = $f;
|
||||
}
|
||||
foreach ($context->truncationField($field) as $f) {
|
||||
$index_fields[] = $f;
|
||||
}
|
||||
}
|
||||
if (!$index_fields) {
|
||||
return null;
|
||||
|
@@ -323,7 +323,7 @@ class ElasticsearchOptions
|
||||
"aggregated (2 values: fired = 0 or 1)" => -1,
|
||||
],
|
||||
'output_formatter' => function($value) {
|
||||
static $map = ['0'=>"No flash", '1'=>"Flash"];
|
||||
static $map = ["false"=>"No flash", "true"=>"Flash", '0'=>"No flash", '1'=>"Flash"];
|
||||
return array_key_exists($value, $map) ? $map[$value] : $value;
|
||||
},
|
||||
],
|
||||
|
@@ -90,6 +90,16 @@ class Index
|
||||
// TODO Maybe replace nfkc_normalizer + asciifolding with icu_folding
|
||||
'filter' => ['nfkc_normalizer', 'asciifolding']
|
||||
],
|
||||
'truncation_analyzer' => [
|
||||
'type' => 'custom',
|
||||
'tokenizer' => 'truncation_tokenizer',
|
||||
'filter' => ['lowercase', 'stop', 'kstem']
|
||||
],
|
||||
'truncation_analyzer#search' => [
|
||||
'type' => 'custom',
|
||||
'tokenizer' => 'truncation_tokenizer',
|
||||
'filter' => ['lowercase', 'stop', 'kstem']
|
||||
],
|
||||
// Lang specific
|
||||
'fr_full' => [
|
||||
'type' => 'custom',
|
||||
@@ -145,6 +155,12 @@ class Index
|
||||
]
|
||||
],
|
||||
'tokenizer' => [
|
||||
'truncation_tokenizer' => [
|
||||
"type" => "edgeNGram",
|
||||
"min_gram" => "2",
|
||||
"max_gram" => "15",
|
||||
"token_chars" => [ "letter", "digit", "punctuation", "symbol" ]
|
||||
],
|
||||
'thesaurus_path' => [
|
||||
'type' => 'path_hierarchy'
|
||||
]
|
||||
|
@@ -13,6 +13,7 @@ namespace Alchemy\Phrasea\SearchEngine\Elastic\Indexer\Record\Hydrator;
|
||||
|
||||
use Alchemy\Phrasea\SearchEngine\Elastic\Exception\Exception;
|
||||
use Alchemy\Phrasea\SearchEngine\Elastic\RecordHelper;
|
||||
use Alchemy\Phrasea\SearchEngine\Elastic\Structure\GlobalStructure;
|
||||
use Alchemy\Phrasea\SearchEngine\Elastic\Thesaurus;
|
||||
use Alchemy\Phrasea\SearchEngine\Elastic\Thesaurus\CandidateTerms;
|
||||
use Alchemy\Phrasea\SearchEngine\Elastic\Thesaurus\Concept;
|
||||
@@ -27,7 +28,7 @@ class ThesaurusHydrator implements HydratorInterface
|
||||
private $thesaurus;
|
||||
private $candidate_terms;
|
||||
|
||||
public function __construct(Structure $structure, Thesaurus $thesaurus, CandidateTerms $candidate_terms)
|
||||
public function __construct(GlobalStructure $structure, Thesaurus $thesaurus, CandidateTerms $candidate_terms)
|
||||
{
|
||||
$this->structure = $structure;
|
||||
$this->thesaurus = $thesaurus;
|
||||
@@ -42,7 +43,7 @@ class ThesaurusHydrator implements HydratorInterface
|
||||
$fields = [];
|
||||
$index_fields = [];
|
||||
foreach ($structure as $name => $field) {
|
||||
$fields[$name] = $field->getThesaurusRoots();
|
||||
$fields[$name] = $field; // ->getThesaurusRoots();
|
||||
$index_fields[$name] = $field->getIndexField();
|
||||
}
|
||||
// Hydrate records with concepts
|
||||
@@ -51,7 +52,13 @@ class ThesaurusHydrator implements HydratorInterface
|
||||
}
|
||||
}
|
||||
|
||||
private function hydrate(array &$record, array $fields, array $index_fields)
|
||||
/**
|
||||
* @param array $record
|
||||
* @param Field[] $fields
|
||||
* @param array $index_fields
|
||||
* @throws Exception
|
||||
*/
|
||||
private function hydrate(array &$record, $fields, array $index_fields)
|
||||
{
|
||||
if (!isset($record['databox_id'])) {
|
||||
throw new Exception('Expected a record with the "databox_id" key set.');
|
||||
@@ -61,7 +68,14 @@ class ThesaurusHydrator implements HydratorInterface
|
||||
$terms = array();
|
||||
$filters = array();
|
||||
$field_names = array();
|
||||
foreach ($fields as $name => $root_concepts) {
|
||||
/** @var Field[] $dbFields */
|
||||
$dbFields = $this->structure->getAllFieldsByDatabox($record['databox_id']);
|
||||
foreach ($fields as $name => $field) {
|
||||
if(!array_key_exists($name, $dbFields) || !$dbFields[$name]->get_generate_cterms()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$root_concepts = $field->getThesaurusRoots();
|
||||
// Loop through all values to prepare bulk query
|
||||
$field_values = \igorw\get_in($record, explode('.', $index_fields[$name]));
|
||||
if ($field_values !== null) {
|
||||
@@ -84,12 +98,13 @@ class ThesaurusHydrator implements HydratorInterface
|
||||
$bulk = $this->thesaurus->findConceptsBulk($terms, null, $filters, true);
|
||||
|
||||
foreach ($bulk as $offset => $item_concepts) {
|
||||
$name = $field_names[$offset];
|
||||
if ($item_concepts && is_array($item_concepts) && count($item_concepts)>0) {
|
||||
$name = $field_names[$offset];
|
||||
foreach ($item_concepts as $concept) {
|
||||
$record['concept_path'][$name][] = $concept->getPath();
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
$this->candidate_terms->insert($field_names[$offset], $values[$offset]);
|
||||
}
|
||||
}
|
||||
|
@@ -55,8 +55,13 @@ class StringFieldMapping extends ComplexFieldMapping
|
||||
{
|
||||
$child = new StringFieldMapping('light');
|
||||
$child->setAnalyzer('general_light');
|
||||
|
||||
$this->addChild($child);
|
||||
|
||||
$child = new StringFieldMapping('truncated');
|
||||
$child->setAnalyzer('truncation_analyzer', 'indexing');
|
||||
$child->setAnalyzer('truncation_analyzer#search', 'searching');
|
||||
$this->addChild($child);
|
||||
|
||||
$this->addLocalizedChildren($locales);
|
||||
|
||||
return $this;
|
||||
|
@@ -4,6 +4,11 @@ namespace Alchemy\Phrasea\SearchEngine\Elastic\Search;
|
||||
|
||||
class Escaper
|
||||
{
|
||||
public function quoteWord($value)
|
||||
{
|
||||
return '"' . $this->escapeRaw($value) . '"';
|
||||
}
|
||||
|
||||
public function escapeWord($value)
|
||||
{
|
||||
// Strip double quotes from values to prevent broken queries
|
||||
|
@@ -46,22 +46,23 @@ class FacetsResponse
|
||||
if (!isset($bucket['key']) || !isset($bucket['doc_count'])) {
|
||||
$this->throwAggregationResponseError();
|
||||
}
|
||||
$key = array_key_exists('key_as_string', $bucket) ? $bucket['key_as_string'] : $bucket['key'];
|
||||
if($tf) {
|
||||
// the field is one of the hardcoded tech fields
|
||||
$value = [
|
||||
'value' => $valueFormatter($bucket['key']),
|
||||
'raw_value' => $bucket['key'],
|
||||
'value' => $valueFormatter($key),
|
||||
'raw_value' => $key,
|
||||
'count' => $bucket['doc_count'],
|
||||
'query' => sprintf($tf['query'], $this->escaper->escapeWord($bucket['key']))
|
||||
'query' => sprintf($tf['query'], $this->escaper->escapeWord($key))
|
||||
];
|
||||
}
|
||||
else {
|
||||
// the field is a normal field
|
||||
$value = [
|
||||
'value' => $bucket['key'],
|
||||
'raw_value' => $bucket['key'],
|
||||
'value' => $key,
|
||||
'raw_value' => $key,
|
||||
'count' => $bucket['doc_count'],
|
||||
'query' => sprintf('field.%s:%s', $this->escaper->escapeWord($name), $this->escaper->escapeWord($bucket['key']))
|
||||
'query' => sprintf('field.%s=%s', $this->escaper->escapeWord($name), $this->escaper->quoteWord($key))
|
||||
];
|
||||
}
|
||||
|
||||
|
@@ -9,6 +9,7 @@ use Alchemy\Phrasea\SearchEngine\Elastic\Structure\Field;
|
||||
use Alchemy\Phrasea\SearchEngine\Elastic\AST\Field as ASTField;
|
||||
use Alchemy\Phrasea\SearchEngine\Elastic\AST\Flag;
|
||||
use Alchemy\Phrasea\SearchEngine\Elastic\Structure\Structure;
|
||||
use Alchemy\Phrasea\SearchEngine\SearchEngineOptions;
|
||||
|
||||
/**
|
||||
* @todo Check for private fields and only search on them if allowed
|
||||
@@ -23,13 +24,23 @@ class QueryContext
|
||||
private $queryLocale;
|
||||
/** @var array */
|
||||
private $fields;
|
||||
/** @var SearchEngineOptions */
|
||||
private $options;
|
||||
|
||||
public function __construct(Structure $structure, array $locales, $queryLocale, array $fields = null)
|
||||
/**
|
||||
* @param SearchEngineOptions|null $options
|
||||
* @param Structure $structure
|
||||
* @param array $locales
|
||||
* @param $queryLocale
|
||||
* @param array $fields
|
||||
*/
|
||||
public function __construct($options, Structure $structure, array $locales, $queryLocale, array $fields = null)
|
||||
{
|
||||
$this->structure = $structure;
|
||||
$this->locales = $locales;
|
||||
$this->queryLocale = $queryLocale;
|
||||
$this->fields = $fields;
|
||||
$this->options = $options;
|
||||
}
|
||||
|
||||
public function narrowToFields(array $fields)
|
||||
@@ -43,7 +54,7 @@ class QueryContext
|
||||
}
|
||||
}
|
||||
|
||||
return new static($this->structure, $this->locales, $this->queryLocale, $fields);
|
||||
return new static($this->options, $this->structure, $this->locales, $this->queryLocale, $fields);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,6 +142,16 @@ class QueryContext
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public function truncationField(Field $field)
|
||||
{
|
||||
if($this->options && $this->options->useTruncation()) {
|
||||
return [sprintf('%s.truncated', $field->getIndexField())];
|
||||
}
|
||||
else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
private function localizeFieldName($field)
|
||||
{
|
||||
$fields = array();
|
||||
|
@@ -23,7 +23,7 @@ class QueryContextFactory
|
||||
? $this->getLimitedStructure($options)
|
||||
: $this->structure;
|
||||
|
||||
$context = new QueryContext($structure, $this->locales, $this->current_locale);
|
||||
$context = new QueryContext($options, $structure, $this->locales, $this->current_locale);
|
||||
|
||||
if ($options) {
|
||||
$fields = $this->getSearchedFields($options);
|
||||
|
@@ -63,4 +63,26 @@ class StringUtils
|
||||
|
||||
return self::$transliterator->transliterate($string);
|
||||
}
|
||||
|
||||
/**
|
||||
* replace bad chars (ascii 0...31 except 9,10,13)
|
||||
*
|
||||
* @param $s
|
||||
* @param string $replace
|
||||
* @return mixed
|
||||
*/
|
||||
public static function substituteCtrlCharacters($s, $replace = '_')
|
||||
{
|
||||
static $bad_chars = null;
|
||||
if($bad_chars === null) {
|
||||
$bad_chars = [];
|
||||
for($i=0; $i<32; $i++) {
|
||||
if($i != 9 && $i != 10 && $i != 13) {
|
||||
$bad_chars[] = chr($i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return str_replace($bad_chars, $replace, $s);
|
||||
}
|
||||
}
|
||||
|
@@ -24,6 +24,11 @@ class Field implements Typed
|
||||
*/
|
||||
private $name;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $databox_id;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
@@ -43,6 +48,8 @@ class Field implements Typed
|
||||
|
||||
private $thesaurus_roots;
|
||||
|
||||
private $generate_cterms;
|
||||
|
||||
private $used_by_collections;
|
||||
|
||||
public static function createFromLegacyField(databox_field $field, $with = Structure::WITH_EVERYTHING)
|
||||
@@ -71,10 +78,12 @@ class Field implements Typed
|
||||
}
|
||||
|
||||
return new self($field->get_name(), $type, [
|
||||
'databox_id' => $databox->get_sbas_id(),
|
||||
'searchable' => $field->is_indexable(),
|
||||
'private' => $field->isBusiness(),
|
||||
'facet' => $facet,
|
||||
'thesaurus_roots' => $roots,
|
||||
'generate_cterms' => $field->get_generate_cterms(),
|
||||
'used_by_collections' => $databox->get_collection_unique_ids()
|
||||
]);
|
||||
}
|
||||
@@ -99,10 +108,12 @@ class Field implements Typed
|
||||
{
|
||||
$this->name = (string) $name;
|
||||
$this->type = $type;
|
||||
$this->databox_id = \igorw\get_in($options, ['databox_id'], 0);
|
||||
$this->is_searchable = \igorw\get_in($options, ['searchable'], true);
|
||||
$this->is_private = \igorw\get_in($options, ['private'], false);
|
||||
$this->facet = \igorw\get_in($options, ['facet']);
|
||||
$this->thesaurus_roots = \igorw\get_in($options, ['thesaurus_roots'], null);
|
||||
$this->generate_cterms = \igorw\get_in($options, ['generate_cterms'], false);
|
||||
$this->used_by_collections = \igorw\get_in($options, ['used_by_collections'], []);
|
||||
|
||||
Assertion::boolean($this->is_searchable);
|
||||
@@ -122,10 +133,12 @@ class Field implements Typed
|
||||
public function withOptions(array $options)
|
||||
{
|
||||
return new self($this->name, $this->type, $options + [
|
||||
'databox_id' => $this->databox_id,
|
||||
'searchable' => $this->is_searchable,
|
||||
'private' => $this->is_private,
|
||||
'facet' => $this->facet,
|
||||
'thesaurus_roots' => $this->thesaurus_roots,
|
||||
'generate_cterms' => $this->generate_cterms,
|
||||
'used_by_collections' => $this->used_by_collections
|
||||
]);
|
||||
}
|
||||
@@ -150,6 +163,11 @@ class Field implements Typed
|
||||
return sprintf('concept_path.%s', $this->name);
|
||||
}
|
||||
|
||||
public function get_databox_id()
|
||||
{
|
||||
return $this->databox_id;
|
||||
}
|
||||
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
@@ -190,6 +208,11 @@ class Field implements Typed
|
||||
return $this->thesaurus_roots;
|
||||
}
|
||||
|
||||
public function get_generate_cterms()
|
||||
{
|
||||
return $this->generate_cterms;
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge with another field, returning the new instance
|
||||
*
|
||||
|
@@ -14,6 +14,12 @@ final class GlobalStructure implements Structure
|
||||
*/
|
||||
private $fields = array();
|
||||
|
||||
|
||||
/**
|
||||
* @var Field[][]
|
||||
*/
|
||||
private $fieldsByDatabox = [];
|
||||
|
||||
/**
|
||||
* @var Field[]
|
||||
* */
|
||||
@@ -119,6 +125,10 @@ final class GlobalStructure implements Structure
|
||||
|
||||
public function add(Field $field)
|
||||
{
|
||||
// store info for each field, not still merged by databox
|
||||
$this->fieldsByDatabox[$field->get_databox_id()][$field->getName()] = $field;
|
||||
|
||||
// store merged infos (same field name)
|
||||
$name = $field->getName();
|
||||
|
||||
if (isset($this->fields[$name])) {
|
||||
@@ -152,6 +162,11 @@ final class GlobalStructure implements Structure
|
||||
return $this->fields;
|
||||
}
|
||||
|
||||
public function getAllFieldsByDatabox($databox_id)
|
||||
{
|
||||
return $this->fieldsByDatabox[$databox_id];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Field[]
|
||||
*/
|
||||
|
@@ -32,6 +32,7 @@ class CandidateTerms
|
||||
|
||||
public function insert($field, $value)
|
||||
{
|
||||
$value = StringUtils::substituteCtrlCharacters($value, '');
|
||||
$this->ensureVisitorSetup();
|
||||
if (!$this->visitor->hasTerm($field, $value)) {
|
||||
$this->new_candidates[$value] = $field;
|
||||
|
@@ -71,6 +71,8 @@ class SearchEngineOptions
|
||||
protected $i18n;
|
||||
/** @var bool */
|
||||
protected $stemming = true;
|
||||
/** @var bool */
|
||||
protected $use_truncation = false;
|
||||
/** @var string */
|
||||
protected $sort_by;
|
||||
|
||||
@@ -105,7 +107,8 @@ class SearchEngineOptions
|
||||
'sort_ord',
|
||||
'business_fields',
|
||||
'max_results',
|
||||
'first_result'
|
||||
'first_result',
|
||||
'use_truncation',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -217,6 +220,29 @@ class SearchEngineOptions
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tells whether to use truncation or not
|
||||
*
|
||||
* @param boolean $boolean
|
||||
* @return $this
|
||||
*/
|
||||
public function setUseTruncation($boolean)
|
||||
{
|
||||
$this->use_truncation = !!$boolean;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return wheter the use of truncation is enabled or not
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function useTruncation()
|
||||
{
|
||||
return $this->use_truncation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return wheter the use of stemming is enabled or not
|
||||
*
|
||||
@@ -542,6 +568,8 @@ class SearchEngineOptions
|
||||
$options->setFields($databoxFields);
|
||||
$options->setDateFields($databoxDateFields);
|
||||
|
||||
$options->setUseTruncation((Boolean) $request->get('truncation'));
|
||||
|
||||
return $options;
|
||||
}
|
||||
|
||||
@@ -628,6 +656,7 @@ class SearchEngineOptions
|
||||
}
|
||||
},
|
||||
'stemming' => $optionSetter('setStemming'),
|
||||
'use_truncation' => $optionSetter('setUseTruncation'),
|
||||
'date_fields' => function ($value, SearchEngineOptions $options) use ($fieldNormalizer) {
|
||||
$options->setDateFields($fieldNormalizer($value));
|
||||
},
|
||||
|
@@ -48,6 +48,7 @@ class PhraseanetExtension extends \Twig_Extension
|
||||
new \Twig_SimpleFunction('border_checker_from_fqcn', array($this, 'getCheckerFromFQCN')),
|
||||
new \Twig_SimpleFunction('caption_field', array($this, 'getCaptionField')),
|
||||
new \Twig_SimpleFunction('caption_field_label', array($this, 'getCaptionFieldLabel')),
|
||||
new \Twig_SimpleFunction('caption_field_gui_visible', array($this, 'getCaptionFieldGuiVisible')),
|
||||
new \Twig_SimpleFunction('caption_field_order', array($this, 'getCaptionFieldOrder')),
|
||||
|
||||
new \Twig_SimpleFunction('flag_slugify', array(Flag::class, 'normalizeName')),
|
||||
@@ -77,6 +78,29 @@ class PhraseanetExtension extends \Twig_Extension
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* get localized field's gui_visible
|
||||
* @param RecordInterface $record
|
||||
* @param $fieldName
|
||||
* @return string - the name gui_visible
|
||||
*/
|
||||
public function getCaptionFieldGuiVisible(RecordInterface $record, $fieldName)
|
||||
{
|
||||
if ($record) {
|
||||
/** @var \appbox $appbox */
|
||||
$appbox = $this->app['phraseanet.appbox'];
|
||||
$databox = $appbox->get_databox($record->getDataboxId());
|
||||
foreach ($databox->get_meta_structure() as $meta) {
|
||||
/** @var \databox_field $meta */
|
||||
if ($meta->get_name() === $fieldName) {
|
||||
return $meta->get_gui_visible($this->app['locale']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public function getCaptionField(RecordInterface $record, $field, $value)
|
||||
{
|
||||
if ($record instanceof ElasticsearchRecord) {
|
||||
|
@@ -80,7 +80,7 @@ class RedisSessionHandler implements \SessionHandlerInterface
|
||||
*/
|
||||
public function destroy($sessionId)
|
||||
{
|
||||
return 1 === $this->redis->delete($this->prefix.$sessionId);
|
||||
return 1 === $this->redis->del($this->prefix.$sessionId);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -462,6 +462,9 @@ class databox extends base implements ThumbnailedElement
|
||||
->set_aggregable((isset($field['aggregable']) ? (string) $field['aggregable'] : 0))
|
||||
->set_type($type)
|
||||
->set_tbranch(isset($field['tbranch']) ? (string) $field['tbranch'] : '')
|
||||
->set_generate_cterms((isset($field['generate_cterms']) && (string) $field['generate_cterms'] == 1))
|
||||
->set_gui_editable((!isset($field['gui_editable']) || (isset($field['gui_editable']) && (string) $field['gui_editable'] == 1)))
|
||||
->set_gui_visible((!isset($field['gui_visible']) || (isset($field['gui_visible']) && (string) $field['gui_visible'] == 1)))
|
||||
->set_thumbtitle(isset($field['thumbtitle']) ? (string) $field['thumbtitle'] : (isset($field['thumbTitle']) ? $field['thumbTitle'] : '0'))
|
||||
->set_report(isset($field['report']) ? (string) $field['report'] : '1')
|
||||
->save();
|
||||
@@ -1214,21 +1217,40 @@ class databox extends base implements ThumbnailedElement
|
||||
$domct = $this->get_dom_cterms();
|
||||
|
||||
if ($domct !== false) {
|
||||
$changed = false;
|
||||
$nodesToDel = [];
|
||||
// loop on first level : "fields"
|
||||
for($n = $domct->documentElement->firstChild; $n; $n = $n->nextSibling) {
|
||||
if($n->nodeType == XML_ELEMENT_NODE && !($n->getAttribute('delbranch'))){
|
||||
$nodesToDel[] = $n;
|
||||
$nodesToDel2 = [];
|
||||
// loop on 2nd level : "terms"
|
||||
for($n2 = $n->firstChild; $n2; $n2 = $n2->nextSibling) {
|
||||
// do not remove "rejected" candidates
|
||||
if(substr($n2->getAttribute('id'), 0, 1) != 'R') {
|
||||
$nodesToDel2[] = $n2;
|
||||
}
|
||||
}
|
||||
foreach($nodesToDel2 as $n2) {
|
||||
$n->removeChild($n2);
|
||||
$changed = true;
|
||||
}
|
||||
// if a field has no more candidates, we can remove it
|
||||
if(!($n->firstChild)) {
|
||||
$nodesToDel[] = $n;
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach($nodesToDel as $n) {
|
||||
$n->parentNode->removeChild($n);
|
||||
$changed = true;
|
||||
}
|
||||
if(!empty($nodesToDel)) {
|
||||
if($changed) {
|
||||
$this->saveCterms($domct);
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
|
||||
}
|
||||
catch (\Exception $e) {
|
||||
// no-op
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -43,6 +43,9 @@ class databox_field implements cache_cacheableInterface
|
||||
protected $report;
|
||||
protected $type;
|
||||
protected $tbranch;
|
||||
protected $generate_cterms;
|
||||
protected $gui_editable;
|
||||
protected $gui_visible;
|
||||
protected $separator;
|
||||
protected $thumbtitle;
|
||||
|
||||
@@ -166,6 +169,9 @@ class databox_field implements cache_cacheableInterface
|
||||
$this->position = (int)$row['sorter'];
|
||||
$this->type = $row['type'] ?: self::TYPE_STRING;
|
||||
$this->tbranch = $row['tbranch'];
|
||||
$this->generate_cterms = (bool)$row['generate_cterms'];
|
||||
$this->gui_editable = (bool)$row['gui_editable'];
|
||||
$this->gui_visible = (bool)$row['gui_visible'];
|
||||
$this->VocabularyType = $row['VocabularyControlType'];
|
||||
$this->VocabularyRestriction = (bool)$row['RestrictToVocabularyControl'];
|
||||
|
||||
@@ -306,6 +312,9 @@ class databox_field implements cache_cacheableInterface
|
||||
`report` = :report,
|
||||
`type` = :type,
|
||||
`tbranch` = :tbranch,
|
||||
`generate_cterms` = :generate_cterms,
|
||||
`gui_editable` = :gui_editable,
|
||||
`gui_visible` = :gui_visible,
|
||||
`sorter` = :position,
|
||||
`thumbtitle` = :thumbtitle,
|
||||
`VocabularyControlType` = :VocabularyControlType,
|
||||
@@ -329,6 +338,9 @@ class databox_field implements cache_cacheableInterface
|
||||
':report' => $this->report ? '1' : '0',
|
||||
':type' => $this->type,
|
||||
':tbranch' => $this->tbranch,
|
||||
':generate_cterms' => $this->generate_cterms ? '1' : '0',
|
||||
':gui_editable' => $this->gui_editable ? '1' : '0',
|
||||
':gui_visible' => $this->gui_visible ? '1' : '0',
|
||||
':position' => $this->position,
|
||||
':thumbtitle' => $this->thumbtitle,
|
||||
':VocabularyControlType' => $this->getVocabularyControl() ? $this->getVocabularyControl()->getType() : null,
|
||||
@@ -380,6 +392,9 @@ class databox_field implements cache_cacheableInterface
|
||||
$meta->setAttribute('aggregable', $this->aggregable);
|
||||
$meta->setAttribute('type', $this->type);
|
||||
$meta->setAttribute('tbranch', $this->tbranch);
|
||||
$meta->setAttribute('generate_cterms', $this->generate_cterms ? '1' : '0');
|
||||
$meta->setAttribute('gui_editable', $this->gui_editable ? '1' : '0');
|
||||
$meta->setAttribute('gui_visible', $this->gui_visible ? '1' : '0');
|
||||
if ($this->multi) {
|
||||
$meta->setAttribute('separator', $this->separator);
|
||||
}
|
||||
@@ -711,6 +726,39 @@ class databox_field implements cache_cacheableInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param boolean $generate_cterms
|
||||
* @return databox_field
|
||||
*/
|
||||
public function set_generate_cterms($generate_cterms)
|
||||
{
|
||||
$this->generate_cterms = $generate_cterms;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param boolean $gui_editable
|
||||
* @return databox_field
|
||||
*/
|
||||
public function set_gui_editable($gui_editable)
|
||||
{
|
||||
$this->gui_editable = $gui_editable;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param boolean $gui_visible
|
||||
* @return databox_field
|
||||
*/
|
||||
public function set_gui_visible($gui_visible)
|
||||
{
|
||||
$this->gui_visible = $gui_visible;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $separator
|
||||
@@ -795,6 +843,33 @@ class databox_field implements cache_cacheableInterface
|
||||
return $this->tbranch;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function get_generate_cterms()
|
||||
{
|
||||
return $this->generate_cterms;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function get_gui_editable()
|
||||
{
|
||||
return $this->gui_editable;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function get_gui_visible()
|
||||
{
|
||||
return $this->gui_visible;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Boolean $all If set to false, returns a one-char separator to use for serialiation
|
||||
*
|
||||
@@ -905,6 +980,9 @@ class databox_field implements cache_cacheableInterface
|
||||
'sorter' => $this->position,
|
||||
'thumbtitle' => $this->thumbtitle,
|
||||
'tbranch' => $this->tbranch,
|
||||
'generate_cterms' => $this->generate_cterms,
|
||||
'gui_editable' => $this->gui_editable,
|
||||
'gui_visible' => $this->gui_visible,
|
||||
'separator' => $this->separator,
|
||||
'required' => $this->required,
|
||||
'report' => $this->report,
|
||||
@@ -943,10 +1021,10 @@ class databox_field implements cache_cacheableInterface
|
||||
}
|
||||
|
||||
$sql = "INSERT INTO metadatas_structure
|
||||
(`id`, `name`, `src`, `readonly`, `required`, `indexable`, `type`, `tbranch`,
|
||||
(`id`, `name`, `src`, `readonly`, `gui_editable`,`gui_visible`, `required`, `indexable`, `type`, `tbranch`, `generate_cterms`,
|
||||
`thumbtitle`, `multi`, `business`, `aggregable`,
|
||||
`report`, `sorter`, `separator`)
|
||||
VALUES (null, :name, '', 0, 0, 1, 'string', '',
|
||||
VALUES (null, :name, '', 0, 1, 1, 0, 1, 'string', '', 1,
|
||||
null, 0, 0, 0,
|
||||
1, :sorter, '')";
|
||||
|
||||
|
67
lib/classes/patch/410alpha17a.php
Normal file
67
lib/classes/patch/410alpha17a.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?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.
|
||||
*/
|
||||
|
||||
use Alchemy\Phrasea\Application;
|
||||
|
||||
class patch_410alpha17a implements patchInterface
|
||||
{
|
||||
/** @var string */
|
||||
private $release = '4.1.0-alpha.17a';
|
||||
|
||||
/** @var array */
|
||||
private $concern = [base::DATA_BOX];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function get_release()
|
||||
{
|
||||
return $this->release;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDoctrineMigrations()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function require_all_upgrades()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function concern()
|
||||
{
|
||||
return $this->concern;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function apply(base $databox, Application $app)
|
||||
{
|
||||
// -- done by xml schema --
|
||||
// $sql = "ALTER TABLE `metadatas_structure` ADD `generate_cterms` INT(1) UNSIGNED NOT NULL DEFAULT '0' AFTER `tbranch`";
|
||||
// $databox->get_connection()->executeQuery($sql);
|
||||
// $sql = "ALTER TABLE `metadatas_structure` ADD `gui_editable` INT(1) UNSIGNED NOT NULL DEFAULT '0' AFTER `readonly`";
|
||||
// $databox->get_connection()->executeQuery($sql);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
69
lib/classes/patch/410alpha19a.php
Normal file
69
lib/classes/patch/410alpha19a.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2019 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Alchemy\Phrasea\Application;
|
||||
|
||||
class patch_410alpha19a implements patchInterface
|
||||
{
|
||||
/** @var string */
|
||||
private $release = '4.1.0-alpha.19a';
|
||||
|
||||
/** @var array */
|
||||
private $concern = [base::APPLICATION_BOX];
|
||||
|
||||
/**
|
||||
* Returns the release version.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_release()
|
||||
{
|
||||
return $this->release;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function concern()
|
||||
{
|
||||
return $this->concern;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function require_all_upgrades()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getDoctrineMigrations()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function apply(base $appbox, Application $app)
|
||||
{
|
||||
// remove all and last in default query
|
||||
$sql = "UPDATE UserSettings SET value = '' WHERE name = 'start_page_query' AND lower(trim(value)) in ('all','last')";
|
||||
$stmt = $appbox->get_connection()->prepare($sql);
|
||||
$stmt->execute();
|
||||
$stmt->closeCursor();
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -1685,6 +1685,43 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
|
||||
return $records;
|
||||
}
|
||||
|
||||
public static function getRecordsByOriginalnameWithExcludedCollIds(databox $databox, $original_name, $caseSensitive = false, $offset_start = 0, $how_many = 10, $excludedCollIds = [])
|
||||
{
|
||||
$offset_start = max(0, (int)$offset_start);
|
||||
$how_many = max(1, (int)$how_many);
|
||||
$collate = $caseSensitive ? 'utf8_bin' : 'utf8_unicode_ci';
|
||||
|
||||
$qb = $databox->get_connection()->createQueryBuilder()
|
||||
->select('record_id')
|
||||
->from('record')
|
||||
->where('originalname = :original_name COLLATE :collate')
|
||||
;
|
||||
|
||||
$params = ['original_name' => $original_name, 'collate' => $collate];
|
||||
$types = [];
|
||||
|
||||
if (!empty($excludedCollIds)) {
|
||||
$qb->andWhere($qb->expr()->notIn('coll_id', ':coll_id'));
|
||||
|
||||
$params['coll_id'] = $excludedCollIds;
|
||||
$types[':coll_id'] = Connection::PARAM_INT_ARRAY;
|
||||
}
|
||||
|
||||
$sql = $qb->setFirstResult($offset_start)
|
||||
->setMaxResults($how_many)
|
||||
->getSQL()
|
||||
;
|
||||
|
||||
$rs = $databox->get_connection()->fetchAll($sql, $params, $types);
|
||||
|
||||
$records = [];
|
||||
foreach ($rs as $row) {
|
||||
$records[] = $databox->get_record($row['record_id']);
|
||||
}
|
||||
|
||||
return $records;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return set_selection|record_adapter[]
|
||||
* @throws Exception
|
||||
@@ -1697,17 +1734,20 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $offset
|
||||
* @param null|int $max_items
|
||||
*
|
||||
* @return set_selection|record_adapter[]
|
||||
* @throws Exception
|
||||
* @throws \Doctrine\DBAL\DBALException
|
||||
*/
|
||||
public function getChildren()
|
||||
public function getChildren($offset = 1, $max_items = null)
|
||||
{
|
||||
if (!$this->isStory()) {
|
||||
throw new Exception('This record is not a grouping');
|
||||
}
|
||||
|
||||
$selections = $this->getDatabox()->getRecordRepository()->findChildren([$this->getRecordId()]);
|
||||
$selections = $this->getDatabox()->getRecordRepository()->findChildren([$this->getRecordId()], null, $offset, $max_items);
|
||||
|
||||
return reset($selections);
|
||||
}
|
||||
|
@@ -2033,6 +2033,30 @@
|
||||
<default></default>
|
||||
<comment></comment>
|
||||
</field>
|
||||
<field>
|
||||
<name>generate_cterms</name>
|
||||
<type>int(1) unsigned</type>
|
||||
<null></null>
|
||||
<extra></extra>
|
||||
<default>1</default>
|
||||
<comment></comment>
|
||||
</field>
|
||||
<field>
|
||||
<name>gui_editable</name>
|
||||
<type>int(1) unsigned</type>
|
||||
<null></null>
|
||||
<extra></extra>
|
||||
<default>1</default>
|
||||
<comment></comment>
|
||||
</field>
|
||||
<field>
|
||||
<name>gui_visible</name>
|
||||
<type>int(1) unsigned</type>
|
||||
<null></null>
|
||||
<extra></extra>
|
||||
<default>1</default>
|
||||
<comment></comment>
|
||||
</field>
|
||||
</fields>
|
||||
<indexes>
|
||||
<index>
|
||||
|
@@ -79,7 +79,7 @@
|
||||
<size>748</size>
|
||||
<mediatype>video</mediatype>
|
||||
<writeDatas>yes</writeDatas>
|
||||
<acodec>libfaac</acodec>
|
||||
<acodec>libmp3lame</acodec>
|
||||
<vcodec>libx264</vcodec>
|
||||
<devices>screen</devices>
|
||||
<bitrate>1000</bitrate>
|
||||
|
@@ -79,7 +79,7 @@
|
||||
<size>748</size>
|
||||
<mediatype>video</mediatype>
|
||||
<writeDatas>yes</writeDatas>
|
||||
<acodec>libfaac</acodec>
|
||||
<acodec>libmp3lame</acodec>
|
||||
<vcodec>libx264</vcodec>
|
||||
<devices>screen</devices>
|
||||
<bitrate>1000</bitrate>
|
||||
|
@@ -79,7 +79,7 @@
|
||||
<size>748</size>
|
||||
<mediatype>video</mediatype>
|
||||
<writeDatas>yes</writeDatas>
|
||||
<acodec>libfaac</acodec>
|
||||
<acodec>libmp3lame</acodec>
|
||||
<vcodec>libx264</vcodec>
|
||||
<devices>screen</devices>
|
||||
<bitrate>1000</bitrate>
|
||||
|
Reference in New Issue
Block a user