mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-10 11:33:17 +00:00
This is a combination of 33 commits.
- Squashed Pull request #1730 - Squashed Pull request #1741 - Squashed Pull request #1742 - Squash merge branch 4.0 - Squashed Pull request #1744 - Squashed Pull request #1746 - Squashed merge branch 4.0 - Squashed merge branch 4.0 - Squashed merge branch 4.0 - Squashed merge branch 4.0 - Squashed Pull request #1758 - Avoid using imagine/imagine alias as it is causing install issues - Squashed merge branch 4.0 - Squashed Pull request #1763 - Squashed merge branch 4.0 - Squash of 6 commits - Squashed merge branch 4.0 - This is a combination of 2 commits. - Squashed Pull request #1775 - Squashed Pull request #1777 - Squashed Pull request #1779 - Squashed Pull request #1780 - Squashed Pull request #1782 - Adds a Pull request template - Squased Pull request #1783 - Squash Pull request #1786 - Squashed Pull request #1796 - Squashed merge branch 4.0 - Squash Pull request #1791 - Squashed merge branch 4.0 - Squashed Pull request #1808 - Squashed Pull request #1811 - Squashed Pull request #1809
This commit is contained in:
16
PULL_REQUEST_TEMPLATE.md
Normal file
16
PULL_REQUEST_TEMPLATE.md
Normal file
@@ -0,0 +1,16 @@
|
||||
## Changelog
|
||||
### Changed
|
||||
- Breaking change
|
||||
|
||||
### Fixes
|
||||
- PHRAS-XXX: Short description of bug and fix
|
||||
- Short description of bug and fix without issue/ticket
|
||||
|
||||
### Adds
|
||||
- PHRAS-XXX: Short feature description
|
||||
- Short feature description without issue/ticket
|
||||
|
||||
### Removes
|
||||
- PHRAS-XXX: Short feature removal description
|
||||
- Short feature removal description without issue/ticket
|
||||
|
@@ -47,6 +47,7 @@
|
||||
"dailymotion/sdk": "~1.5",
|
||||
"data-uri/data-uri": "~0.1.0",
|
||||
"dflydev/doctrine-orm-service-provider": "~1.0",
|
||||
"doctrine/cache": "^1.6",
|
||||
"doctrine/dbal": "^2.4.0",
|
||||
"doctrine/migrations": "^1.0.0",
|
||||
"doctrine/orm": "^2.4.0",
|
||||
@@ -61,7 +62,7 @@
|
||||
"hoa/dispatcher": "~0.0",
|
||||
"hoa/router": "~2.0",
|
||||
"igorw/get-in": "~1.0",
|
||||
"imagine/imagine": "dev-alchemy-0.6.2 as 0.6.2",
|
||||
"imagine/imagine": "0.6.x-dev",
|
||||
"ircmaxell/random-lib": "~1.0",
|
||||
"jms/serializer": "~0.10",
|
||||
"jms/translation-bundle": "dev-rebase-2015-10-20",
|
||||
@@ -88,7 +89,7 @@
|
||||
"simple-bus/jms-serializer-bridge": "^1.0",
|
||||
"simple-bus/message-bus": "^2.1",
|
||||
"simple-bus/serialization": "^2.0",
|
||||
"sorien/silex-dbal-profiler": "~1.0.0",
|
||||
"sorien/silex-dbal-profiler": "^1.1",
|
||||
"sorien/silex-pimple-dumper": "^1.0",
|
||||
"swiftmailer/swiftmailer": "~5.3.0",
|
||||
"symfony/symfony": "~2.7.10|~2.8.3",
|
||||
|
53
composer.lock
generated
53
composer.lock
generated
@@ -4,8 +4,8 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"hash": "baf4148980adfb15bed6b72c438da7eb",
|
||||
"content-hash": "5d8ffafd15285984d97c82a1e13a697f",
|
||||
"hash": "8db2333764b17b4b04f474a6b9fc2c49",
|
||||
"content-hash": "2961cef34c7a94f9afb11b859781cb65",
|
||||
"packages": [
|
||||
{
|
||||
"name": "alchemy-fr/tcpdf-clone",
|
||||
@@ -1137,33 +1137,33 @@
|
||||
},
|
||||
{
|
||||
"name": "doctrine/cache",
|
||||
"version": "v1.5.1",
|
||||
"version": "v1.6.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/doctrine/cache.git",
|
||||
"reference": "2b9cec5a5e722010cbebc91713d4c11eaa064d5e"
|
||||
"reference": "f8af318d14bdb0eff0336795b428b547bd39ccb6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/doctrine/cache/zipball/2b9cec5a5e722010cbebc91713d4c11eaa064d5e",
|
||||
"reference": "2b9cec5a5e722010cbebc91713d4c11eaa064d5e",
|
||||
"url": "https://api.github.com/repos/doctrine/cache/zipball/f8af318d14bdb0eff0336795b428b547bd39ccb6",
|
||||
"reference": "f8af318d14bdb0eff0336795b428b547bd39ccb6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.2"
|
||||
"php": "~5.5|~7.0"
|
||||
},
|
||||
"conflict": {
|
||||
"doctrine/common": ">2.2,<2.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": ">=3.7",
|
||||
"phpunit/phpunit": "~4.8|~5.0",
|
||||
"predis/predis": "~1.0",
|
||||
"satooshi/php-coveralls": "~0.6"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.5.x-dev"
|
||||
"dev-master": "1.6.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -1203,7 +1203,7 @@
|
||||
"cache",
|
||||
"caching"
|
||||
],
|
||||
"time": "2015-11-02 18:35:48"
|
||||
"time": "2015-12-31 16:37:02"
|
||||
},
|
||||
{
|
||||
"name": "doctrine/collections",
|
||||
@@ -2930,7 +2930,7 @@
|
||||
},
|
||||
{
|
||||
"name": "imagine/imagine",
|
||||
"version": "dev-alchemy-0.6.2",
|
||||
"version": "0.6.x-dev",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/alchemy-fr/Imagine.git",
|
||||
@@ -4744,7 +4744,7 @@
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/dcdeb1d923b981a55f0a4ce6c2ceac14cb8476f8",
|
||||
"url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/438196c8f66647073bcaf99908b543bda7ffd6d4",
|
||||
"reference": "c18abc6df90257ddbbe2654a98cc5cc7be804411",
|
||||
"shasum": ""
|
||||
},
|
||||
@@ -5221,22 +5221,28 @@
|
||||
},
|
||||
{
|
||||
"name": "sorien/silex-dbal-profiler",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/Sorien/silex-dbal-profiler.git",
|
||||
"reference": "8cbbef7a8fae53381d9005163070485471089908"
|
||||
"reference": "4d3f642144e96685270f7ffb1648a081d0c5eb7e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/Sorien/silex-dbal-profiler/zipball/8cbbef7a8fae53381d9005163070485471089908",
|
||||
"reference": "8cbbef7a8fae53381d9005163070485471089908",
|
||||
"url": "https://api.github.com/repos/Sorien/silex-dbal-profiler/zipball/4d3f642144e96685270f7ffb1648a081d0c5eb7e",
|
||||
"reference": "4d3f642144e96685270f7ffb1648a081d0c5eb7e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require-dev": {
|
||||
"silex/silex": "~1.0"
|
||||
"require": {
|
||||
"silex/silex": "~1.0",
|
||||
"silex/web-profiler": "~1.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.1.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Sorien": "src"
|
||||
@@ -5259,7 +5265,7 @@
|
||||
"profiler",
|
||||
"silex"
|
||||
],
|
||||
"time": "2014-02-26 10:01:20"
|
||||
"time": "2015-03-12 09:26:42"
|
||||
},
|
||||
{
|
||||
"name": "sorien/silex-pimple-dumper",
|
||||
@@ -7389,14 +7395,7 @@
|
||||
"time": "2015-06-21 13:59:46"
|
||||
}
|
||||
],
|
||||
"aliases": [
|
||||
{
|
||||
"alias": "0.6.2",
|
||||
"alias_normalized": "0.6.2.0",
|
||||
"version": "dev-alchemy-0.6.2",
|
||||
"package": "imagine/imagine"
|
||||
}
|
||||
],
|
||||
"aliases": [],
|
||||
"minimum-stability": "stable",
|
||||
"stability-flags": {
|
||||
"alchemy/task-manager": 20,
|
||||
|
@@ -73,6 +73,7 @@ use Alchemy\Phrasea\Core\Provider\UnicodeServiceProvider;
|
||||
use Alchemy\Phrasea\Core\Provider\WebhookServiceProvider;
|
||||
use Alchemy\Phrasea\Core\Provider\ZippyServiceProvider;
|
||||
use Alchemy\Phrasea\Core\Provider\WebProfilerServiceProvider as PhraseaWebProfilerServiceProvider;
|
||||
use Alchemy\Phrasea\Databox\Subdef\MediaSubdefServiceProvider;
|
||||
use Alchemy\Phrasea\Exception\InvalidArgumentException;
|
||||
use Alchemy\Phrasea\Filesystem\FilesystemServiceProvider;
|
||||
use Alchemy\Phrasea\Filesystem\ApplicationPathServiceGenerator;
|
||||
@@ -80,6 +81,7 @@ use Alchemy\Phrasea\Form\Extension\HelpTypeExtension;
|
||||
use Alchemy\Phrasea\Media\DatafilesResolver;
|
||||
use Alchemy\Phrasea\Media\MediaAccessorResolver;
|
||||
use Alchemy\Phrasea\Media\PermalinkMediaResolver;
|
||||
use Alchemy\Phrasea\Media\TechnicalDataServiceProvider;
|
||||
use Alchemy\Phrasea\Model\Entities\User;
|
||||
use Doctrine\DBAL\Event\ConnectionEventArgs;
|
||||
use MediaVorus\Media\MediaInterface;
|
||||
@@ -190,6 +192,8 @@ class Application extends SilexApplication
|
||||
$this->register(new NotificationDelivererServiceProvider());
|
||||
$this->register(new RepositoriesServiceProvider());
|
||||
$this->register(new ManipulatorServiceProvider());
|
||||
$this->register(new TechnicalDataServiceProvider());
|
||||
$this->register(new MediaSubdefServiceProvider());
|
||||
$this->register(new InstallerServiceProvider());
|
||||
$this->register(new PhraseaVersionServiceProvider());
|
||||
|
||||
|
@@ -69,7 +69,7 @@ class Story implements AttributeInterface
|
||||
*/
|
||||
public function asString()
|
||||
{
|
||||
return $this->story->get_serialize_key();
|
||||
return $this->story->getId();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -278,7 +278,7 @@ class Manager
|
||||
$file->addAttribute(
|
||||
new MetadataAttr(
|
||||
new Metadata(
|
||||
new TfRecordid(), new MonoValue($element->get_record_id())
|
||||
new TfRecordid(), new MonoValue($element->getRecordId())
|
||||
)
|
||||
)
|
||||
);
|
||||
@@ -314,7 +314,7 @@ class Manager
|
||||
break;
|
||||
case AttributeInterface::NAME_STATUS:
|
||||
/** @var StatusAttr $attribute */
|
||||
$element->set_binary_status(decbin(bindec($element->get_status()) | bindec($attribute->getValue())));
|
||||
$element->setStatus(decbin(bindec($element->getStatus()) | bindec($attribute->getValue())));
|
||||
|
||||
break;
|
||||
case AttributeInterface::NAME_STORY:
|
||||
|
88
lib/Alchemy/Phrasea/Cache/MultiAdapter.php
Normal file
88
lib/Alchemy/Phrasea/Cache/MultiAdapter.php
Normal file
@@ -0,0 +1,88 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Cache;
|
||||
|
||||
use Doctrine\Common\Cache\Cache as DoctrineCache;
|
||||
use Doctrine\Common\Cache\MultiGetCache;
|
||||
use Doctrine\Common\Cache\MultiPutCache;
|
||||
|
||||
class MultiAdapter implements DoctrineCache, MultiGetCache, MultiPutCache
|
||||
{
|
||||
/**
|
||||
* @var DoctrineCache
|
||||
*/
|
||||
private $cache;
|
||||
|
||||
public function __construct(DoctrineCache $cache)
|
||||
{
|
||||
$this->cache = $cache;
|
||||
}
|
||||
|
||||
public function fetch($id)
|
||||
{
|
||||
return $this->cache->fetch($id);
|
||||
}
|
||||
|
||||
public function contains($id)
|
||||
{
|
||||
return $this->cache->contains($id);
|
||||
}
|
||||
|
||||
public function save($id, $data, $lifeTime = 0)
|
||||
{
|
||||
return $this->cache->save($id, $data, $lifeTime);
|
||||
}
|
||||
|
||||
public function delete($id)
|
||||
{
|
||||
return $this->cache->delete($id);
|
||||
}
|
||||
|
||||
public function getStats()
|
||||
{
|
||||
return $this->cache->getStats();
|
||||
}
|
||||
|
||||
public function fetchMultiple(array $keys)
|
||||
{
|
||||
if ($this->cache instanceof MultiGetCache) {
|
||||
return $this->cache->fetchMultiple($keys);
|
||||
}
|
||||
|
||||
// Pass data by reference to avoid copies of whole array on key add.
|
||||
$data = array_reduce($keys, function (array &$data, $key) {
|
||||
$value = $this->fetch($key);
|
||||
|
||||
if (false !== $value || true === $this->contains($key)) {
|
||||
$data[$key] = $value;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}, []);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function saveMultiple(array $keysAndValues, $lifetime = 0)
|
||||
{
|
||||
if ($this->cache instanceof MultiPutCache) {
|
||||
return $this->cache->saveMultiple($keysAndValues, $lifetime);
|
||||
}
|
||||
|
||||
foreach ($keysAndValues as $key => $value) {
|
||||
if (!$this->cache->save($key, $value, $lifetime)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -12,12 +12,8 @@ namespace Alchemy\Phrasea\Collection;
|
||||
|
||||
use Assert\Assertion;
|
||||
|
||||
class CollectionHelper
|
||||
final class CollectionHelper
|
||||
{
|
||||
private function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \collection[] $collections
|
||||
* @return \collection[]
|
||||
@@ -31,7 +27,11 @@ class CollectionHelper
|
||||
}
|
||||
|
||||
usort($collections, function (\collection $left, \collection $right) {
|
||||
return ($left->get_ord() < $right->get_ord()) ? -1 : (($left->get_ord() < $right->get_ord()) ? 1 : 0);
|
||||
if ($left->get_ord() === $right->get_ord()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $left->get_ord() < $right->get_ord() ? -1 : 1;
|
||||
});
|
||||
|
||||
return $collections;
|
||||
|
@@ -179,13 +179,14 @@ class BuildSubdefs extends Command
|
||||
|
||||
if($this->databox !== null) {
|
||||
|
||||
foreach ($this->databox->get_subdef_structure() as $sgname=>$sg) {
|
||||
if (empty($types) || in_array($sgname, $types)) {
|
||||
$this->subdefsNameByType[$sgname] = [];
|
||||
/** @var SubdefGroup $sg */
|
||||
foreach ($this->databox->get_subdef_structure() as $sg) {
|
||||
if (empty($types) || in_array($sg->getName(), $types)) {
|
||||
$this->subdefsNameByType[$sg->getName()] = [];
|
||||
/** @var databox_subdef $sd */
|
||||
foreach ($sg as $sd) {
|
||||
if (empty($names) || in_array($sd->get_name(), $names)) {
|
||||
$this->subdefsNameByType[$sgname][] = $sd->get_name();
|
||||
$this->subdefsNameByType[$sg->getName()][] = $sd->get_name();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -61,7 +61,7 @@ class RecordAdd extends Command
|
||||
if (!$input->getOption('yes')) {
|
||||
do {
|
||||
$continue = strtolower($dialog->ask($output, sprintf("Will add record <info>%s</info> (%s) on collection <info>%s</info>\n<question>Continue ? (y/N)</question>", $file, $media->getType(), $collection->get_label($this->container['locale'])), 'N'));
|
||||
} while ( ! in_array($continue, ['y', 'n']));
|
||||
} while (!in_array($continue, ['y', 'n']));
|
||||
|
||||
if (strtolower($continue) !== 'y') {
|
||||
$output->writeln('Aborted !');
|
||||
@@ -112,7 +112,10 @@ class RecordAdd extends Command
|
||||
if ($elementCreated instanceof \record_adapter) {
|
||||
$output->writeln(
|
||||
sprintf(
|
||||
"Record id <info>%d</info> on collection `%s` (databox `%s`) has been created", $elementCreated->get_record_id(), $elementCreated->get_collection()->get_label($this->container['locale']), $elementCreated->get_databox()->get_label($this->container['locale'])
|
||||
"Record id <info>%d</info> on collection `%s` (databox `%s`) has been created",
|
||||
$elementCreated->getRecordId(),
|
||||
$elementCreated->getCollection()->get_label($this->container['locale']),
|
||||
$elementCreated->getDatabox()->get_label($this->container['locale'])
|
||||
)
|
||||
);
|
||||
} elseif ($elementCreated instanceof LazaretFile) {
|
||||
|
@@ -80,13 +80,13 @@ class Step35 implements DatasUpgraderInterface
|
||||
try {
|
||||
$this->updateMetadatas($record, $row['xml']);
|
||||
} catch (\Exception $e) {
|
||||
$this->app['monolog']->addError(sprintf("Error while upgrading metadatas for record %d on databox %d : %s", $record->get_record_id(), $record->get_sbas_id(), $e->getMessage()));
|
||||
$this->app['monolog']->addError(sprintf("Error while upgrading metadatas for record %d on databox %d : %s", $record->getRecordId(), $record->getDataboxId(), $e->getMessage()));
|
||||
}
|
||||
|
||||
try {
|
||||
$record->set_binary_status($row['status']);
|
||||
$record->setStatus($row['status']);
|
||||
} catch (\Exception $e) {
|
||||
$this->app['monolog']->addError(sprintf("Error while upgrading status for record %d on databox %d : %s", $record->get_record_id(), $record->get_sbas_id(), $e->getMessage()));
|
||||
$this->app['monolog']->addError(sprintf("Error while upgrading status for record %d on databox %d : %s", $record->getRecordId(), $record->getDataboxId(), $e->getMessage()));
|
||||
}
|
||||
unset($record);
|
||||
}
|
||||
@@ -131,7 +131,7 @@ class Step35 implements DatasUpgraderInterface
|
||||
*/
|
||||
protected function updateMetadatas(\record_adapter $record, $xml)
|
||||
{
|
||||
$metas = $record->get_databox()->get_meta_structure();
|
||||
$metas = $record->getDatabox()->get_meta_structure();
|
||||
|
||||
$datas = $metadatas = [];
|
||||
|
||||
|
@@ -62,7 +62,7 @@ abstract class AbstractDelivery
|
||||
private function logView(\record_adapter $record, Request $request)
|
||||
{
|
||||
try {
|
||||
$logger = $this->getDataboxLogger($record->get_databox());
|
||||
$logger = $this->getDataboxLogger($record->getDatabox());
|
||||
$log_id = $logger->get_id();
|
||||
$record->log_view(
|
||||
$log_id,
|
||||
|
@@ -12,8 +12,8 @@ namespace Alchemy\Phrasea\Controller\Admin;
|
||||
|
||||
use Alchemy\Phrasea\Controller\Controller;
|
||||
use Alchemy\Phrasea\Metadata\TagProvider;
|
||||
use Alchemy\Phrasea\Vocabulary\Controller as VocabularyController;
|
||||
use Alchemy\Phrasea\Vocabulary\ControlProvider\ControlProviderInterface;
|
||||
use Assert\Assertion;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
|
||||
@@ -96,24 +96,57 @@ class FieldsController extends Controller
|
||||
|
||||
public function listVocabularies()
|
||||
{
|
||||
$vocabularies = VocabularyController::getAvailable($this->app);
|
||||
return $this->app->json(array_map(
|
||||
[$this, 'getVocabularyAsArray'],
|
||||
$this->fetchVocabularies()
|
||||
));
|
||||
}
|
||||
|
||||
return $this->app->json(array_map(function (ControlProviderInterface $vocabulary) {
|
||||
/**
|
||||
* @return ControlProviderInterface[]
|
||||
*/
|
||||
private function fetchVocabularies()
|
||||
{
|
||||
$vocabularies = $this->getVocabularies();
|
||||
|
||||
$instances = array_map(
|
||||
function ($type) use ($vocabularies) {
|
||||
return $vocabularies[$type];
|
||||
},
|
||||
$vocabularies->keys()
|
||||
);
|
||||
|
||||
Assertion::allIsInstanceOf($instances, ControlProviderInterface::class);
|
||||
|
||||
return $instances;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $type
|
||||
* @return ControlProviderInterface
|
||||
*/
|
||||
private function fetchVocabulary($type)
|
||||
{
|
||||
$vocabularies = $this->getVocabularies();
|
||||
|
||||
$vocabulary = $vocabularies[strtolower($type)];
|
||||
|
||||
Assertion::isInstanceOf($vocabulary, ControlProviderInterface::class);
|
||||
|
||||
return $vocabulary;
|
||||
}
|
||||
|
||||
private function getVocabularyAsArray(ControlProviderInterface $vocabulary)
|
||||
{
|
||||
return [
|
||||
'type' => $vocabulary->getType(),
|
||||
'name' => $vocabulary->getName(),
|
||||
];
|
||||
}, $vocabularies));
|
||||
}
|
||||
|
||||
public function getVocabulary($type)
|
||||
{
|
||||
$vocabulary = VocabularyController::get($this->app, $type);
|
||||
|
||||
return $this->app->json([
|
||||
'type' => $vocabulary->getType(),
|
||||
'name' => $vocabulary->getName(),
|
||||
]);
|
||||
return $this->app->json($this->getVocabularyAsArray($this->fetchVocabulary($type)));
|
||||
}
|
||||
|
||||
public function searchTag(Request $request)
|
||||
@@ -293,11 +326,11 @@ class FieldsController extends Controller
|
||||
}
|
||||
|
||||
try {
|
||||
$vocabulary = VocabularyController::get($this->app, $data['vocabulary-type']);
|
||||
$vocabulary = $this->fetchVocabulary($data['vocabulary-type']);
|
||||
$field->setVocabularyControl($vocabulary);
|
||||
$field->setVocabularyRestricted($data['vocabulary-restricted']);
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
|
||||
// Invalid vocabulary requested
|
||||
}
|
||||
|
||||
if ('' !== $dcesElement = (string) $data['dces-element']) {
|
||||
@@ -347,4 +380,12 @@ class FieldsController extends Controller
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ControlProviderInterface[]|\Pimple
|
||||
*/
|
||||
private function getVocabularies()
|
||||
{
|
||||
return $this->app['vocabularies'];
|
||||
}
|
||||
}
|
||||
|
@@ -38,9 +38,28 @@ class SearchEngineController extends Controller
|
||||
|
||||
return $this->render('admin/search-engine/elastic-search.html.twig', [
|
||||
'form' => $form->createView(),
|
||||
'indexer' => $this->app['elasticsearch.indexer']
|
||||
]);
|
||||
}
|
||||
|
||||
public function dropIndexAction(Request $request)
|
||||
{
|
||||
$indexer = $this->app['elasticsearch.indexer'];
|
||||
if ($indexer->indexExists()) {
|
||||
$indexer->deleteIndex();
|
||||
}
|
||||
return $this->app->redirectPath('admin_searchengine_form');
|
||||
}
|
||||
|
||||
public function createIndexAction(Request $request)
|
||||
{
|
||||
$indexer = $this->app['elasticsearch.indexer'];
|
||||
if (!$indexer->indexExists()) {
|
||||
$indexer->createIndex();
|
||||
}
|
||||
return $this->app->redirectPath('admin_searchengine_form');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ElasticsearchOptions
|
||||
*/
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
/**
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
@@ -49,14 +49,13 @@ class SearchController extends Controller
|
||||
private function searchAndFormatEngineResult(Request $request)
|
||||
{
|
||||
$options = SearchEngineOptions::fromRequest($this->app, $request);
|
||||
|
||||
$offsetStart = (int) ($request->get('offset_start') ?: 0);
|
||||
$perPage = (int) $request->get('per_page') ?: 10;
|
||||
$options->setFirstResult($request->get('offset_start') ?: 0);
|
||||
$options->setMaxResults($request->get('per_page') ?: 10);
|
||||
|
||||
$query = (string) $request->get('query');
|
||||
$this->getSearchEngine()->resetCache();
|
||||
|
||||
$search_result = $this->getSearchEngine()->query($query, $offsetStart, $perPage, $options);
|
||||
$search_result = $this->getSearchEngine()->query($query, $options);
|
||||
|
||||
$this->getUserManipulator()->logQuery($this->getAuthenticatedUser(), $search_result->getQuery());
|
||||
|
||||
@@ -74,8 +73,8 @@ class SearchController extends Controller
|
||||
$this->getSearchEngine()->clearCache();
|
||||
|
||||
$ret = [
|
||||
'offset_start' => $offsetStart,
|
||||
'per_page' => $perPage,
|
||||
'offset_start' => $options->getFirstResult(),
|
||||
'per_page' => $options->getMaxResults(),
|
||||
'available_results' => $search_result->getAvailable(),
|
||||
'total_results' => $search_result->getTotal(),
|
||||
'error' => (string)$search_result->getError(),
|
||||
|
@@ -47,7 +47,7 @@ use Alchemy\Phrasea\Model\Entities\ValidationData;
|
||||
use Alchemy\Phrasea\Model\Entities\ValidationParticipant;
|
||||
use Alchemy\Phrasea\Model\Manipulator\TaskManipulator;
|
||||
use Alchemy\Phrasea\Model\Manipulator\UserManipulator;
|
||||
use Alchemy\Phrasea\Model\Provider\SecretProvider;
|
||||
use Alchemy\Phrasea\Model\RecordReferenceInterface;
|
||||
use Alchemy\Phrasea\Model\Repositories\BasketRepository;
|
||||
use Alchemy\Phrasea\Model\Repositories\FeedEntryRepository;
|
||||
use Alchemy\Phrasea\Model\Repositories\FeedRepository;
|
||||
@@ -61,8 +61,8 @@ use Alchemy\Phrasea\SearchEngine\SearchEngineResult;
|
||||
use Alchemy\Phrasea\SearchEngine\SearchEngineSuggestion;
|
||||
use Alchemy\Phrasea\Status\StatusStructure;
|
||||
use Alchemy\Phrasea\TaskManager\LiveInformation;
|
||||
use Alchemy\Phrasea\Utilities\NullableDateTime;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Firebase\JWT\JWT;
|
||||
use Symfony\Component\Form\Form;
|
||||
use Symfony\Component\HttpFoundation\File\UploadedFile;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
@@ -139,10 +139,10 @@ class V1Controller extends Controller
|
||||
'pid' => $data['process-id'],
|
||||
'jobId' => $task->getJobId(),
|
||||
'period' => $task->getPeriod(),
|
||||
'last_exec_time' => $task->getLastExecution() ? $task->getLastExecution()->format(DATE_ATOM) : null,
|
||||
'last_execution' => $task->getLastExecution() ? $task->getLastExecution()->format(DATE_ATOM) : null,
|
||||
'updated' => $task->getUpdated() ? $task->getUpdated()->format(DATE_ATOM) : null,
|
||||
'created' => $task->getCreated() ? $task->getCreated()->format(DATE_ATOM) : null,
|
||||
'last_exec_time' => NullableDateTime::format($task->getLastExecution()),
|
||||
'last_execution' => NullableDateTime::format($task->getLastExecution()),
|
||||
'updated' => NullableDateTime::format($task->getUpdated()),
|
||||
'created' => NullableDateTime::format($task->getCreated()),
|
||||
'auto_start' => $task->getStatus() === Task::STATUS_STARTED,
|
||||
'crashed' => $task->getCrashed(),
|
||||
];
|
||||
@@ -710,9 +710,9 @@ class V1Controller extends Controller
|
||||
'position' => $user->getActivity() ?: null,
|
||||
'company' => $user->getCompany() ?: null,
|
||||
'geoname_id' => $user->getGeonameId() ?: null,
|
||||
'last_connection' => $user->getLastConnection() ? $user->getLastConnection()->format(DATE_ATOM) : null,
|
||||
'created_on' => $user->getCreated() ? $user->getCreated()->format(DATE_ATOM) : null,
|
||||
'updated_on' => $user->getUpdated() ? $user->getUpdated()->format(DATE_ATOM) : null,
|
||||
'last_connection' => NullableDateTime::format($user->getLastConnection()),
|
||||
'created_on' => NullableDateTime::format($user->getCreated()),
|
||||
'updated_on' => NullableDateTime::format($user->getUpdated()),
|
||||
'locale' => $user->getLocale() ?: null,
|
||||
];
|
||||
}
|
||||
@@ -1003,37 +1003,11 @@ class V1Controller extends Controller
|
||||
'substituted' => $media->is_substituted(),
|
||||
'created_on' => $media->get_creation_date()->format(DATE_ATOM),
|
||||
'updated_on' => $media->get_modification_date()->format(DATE_ATOM),
|
||||
'url' => $this->generateSubDefinitionUrl($issuer, $media, $urlTTL),
|
||||
'url' => $this->app['media_accessor.subdef_url_generator']->generate($issuer, $media, $urlTTL),
|
||||
'url_ttl' => $urlTTL,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $issuer
|
||||
* @param \media_subdef $subdef
|
||||
* @param int $url_ttl
|
||||
* @return string
|
||||
*/
|
||||
private function generateSubDefinitionUrl(User $issuer, \media_subdef $subdef, $url_ttl)
|
||||
{
|
||||
$payload = [
|
||||
'iat' => time(),
|
||||
'iss' => $issuer->getId(),
|
||||
'sdef' => [$subdef->get_sbas_id(), $subdef->get_record_id(), $subdef->get_name()],
|
||||
];
|
||||
if ($url_ttl >= 0) {
|
||||
$payload['exp'] = $payload['iat'] + $url_ttl;
|
||||
}
|
||||
|
||||
/** @var SecretProvider $provider */
|
||||
$provider = $this->app['provider.secrets'];
|
||||
$secret = $provider->getSecretForUser($issuer);
|
||||
|
||||
return $this->app->url('media_accessor', [
|
||||
'token' => JWT::encode($payload, $secret->getToken(), 'HS256', $secret->getId()),
|
||||
]);
|
||||
}
|
||||
|
||||
private function listPermalink(\media_Permalink_Adapter $permalink)
|
||||
{
|
||||
$downloadUrl = $permalink->get_url();
|
||||
@@ -1063,19 +1037,23 @@ class V1Controller extends Controller
|
||||
{
|
||||
list($ret, $search_result) = $this->prepareSearchRequest($request);
|
||||
|
||||
$ret['results'] = ['records' => [], 'stories' => []];
|
||||
$records = [];
|
||||
$stories = [];
|
||||
|
||||
/** @var SearchEngineResult $search_result */
|
||||
$references = new RecordReferenceCollection($search_result->getResults());
|
||||
|
||||
foreach ($references->toRecords($this->getApplicationBox()) as $record) {
|
||||
foreach ($search_result->getResults() as $record) {
|
||||
if ($record->isStory()) {
|
||||
$ret['results']['stories'][] = $this->listStory($request, $record);
|
||||
$stories[] = $record;
|
||||
} else {
|
||||
$ret['results']['records'][] = $this->listRecord($request, $record);
|
||||
$records[] = $record;
|
||||
}
|
||||
}
|
||||
|
||||
$ret['results'] = [
|
||||
'records' => $this->listRecords($request, $records),
|
||||
'stories' => $this->listStories($request, $stories),
|
||||
];
|
||||
|
||||
return Result::create($request, $ret)->createResponse();
|
||||
}
|
||||
|
||||
@@ -1110,13 +1088,13 @@ class V1Controller extends Controller
|
||||
{
|
||||
$options = SearchEngineOptions::fromRequest($this->app, $request);
|
||||
|
||||
$offsetStart = (int) ($request->get('offset_start') ?: 0);
|
||||
$perPage = (int) $request->get('per_page') ?: 10;
|
||||
$options->setFirstResult((int) ($request->get('offset_start') ?: 0));
|
||||
$options->setMaxResults((int) $request->get('per_page') ?: 10);
|
||||
|
||||
$query = (string) $request->get('query');
|
||||
$this->getSearchEngine()->resetCache();
|
||||
|
||||
$search_result = $this->getSearchEngine()->query($query, $offsetStart, $perPage, $options);
|
||||
$search_result = $this->getSearchEngine()->query($query, $options);
|
||||
|
||||
$this->getUserManipulator()->logQuery($this->getAuthenticatedUser(), $search_result->getQuery());
|
||||
|
||||
@@ -1134,8 +1112,8 @@ class V1Controller extends Controller
|
||||
$this->getSearchEngine()->clearCache();
|
||||
|
||||
$ret = [
|
||||
'offset_start' => $offsetStart,
|
||||
'per_page' => $perPage,
|
||||
'offset_start' => $options->getFirstResult(),
|
||||
'per_page' => $options->getMaxResults(),
|
||||
'available_results' => $search_result->getAvailable(),
|
||||
'total_results' => $search_result->getTotal(),
|
||||
'error' => (string)$search_result->getError(),
|
||||
@@ -1154,6 +1132,30 @@ class V1Controller extends Controller
|
||||
return [$ret, $search_result];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param RecordReferenceInterface[]|RecordReferenceCollection $records
|
||||
* @return array
|
||||
*/
|
||||
public 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
|
||||
*
|
||||
@@ -1197,6 +1199,27 @@ class V1Controller extends Controller
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param RecordReferenceInterface[]|RecordReferenceCollection $stories
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function listStories(Request $request, $stories)
|
||||
{
|
||||
if (!$stories instanceof RecordReferenceCollection) {
|
||||
$stories = new RecordReferenceCollection($stories);
|
||||
}
|
||||
|
||||
$data = [];
|
||||
|
||||
foreach ($stories->toRecords($this->getApplicationBox()) as $story) {
|
||||
$data[] = $this->listStory($request, $story);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve detailed information about one story
|
||||
*
|
||||
@@ -1211,10 +1234,6 @@ class V1Controller extends Controller
|
||||
return Result::createError($request, 404, 'Story not found')->createResponse();
|
||||
}
|
||||
|
||||
$records = array_map(function (\record_adapter $record) use ($request) {
|
||||
return $this->listRecord($request, $record);
|
||||
}, array_values($story->get_children()->get_elements()));
|
||||
|
||||
$caption = $story->get_caption();
|
||||
|
||||
$format = function (\caption_record $caption, $dcField) {
|
||||
@@ -1256,7 +1275,7 @@ class V1Controller extends Controller
|
||||
'dc:title' => $format($caption, \databox_Field_DCESAbstract::Title),
|
||||
'dc:type' => $format($caption, \databox_Field_DCESAbstract::Type),
|
||||
],
|
||||
'records' => $records,
|
||||
'records' => $this->listRecords($request, $story->getChildren()->get_elements()),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1448,11 +1467,7 @@ class V1Controller extends Controller
|
||||
];
|
||||
}, iterator_to_array($basket->getValidation()->getParticipants()));
|
||||
|
||||
$expires_on_atom = $basket->getValidation()->getExpires();
|
||||
|
||||
if ($expires_on_atom instanceof \DateTime) {
|
||||
$expires_on_atom = $expires_on_atom->format(DATE_ATOM);
|
||||
}
|
||||
$expires_on_atom = NullableDateTime::format($basket->getValidation()->getExpires());
|
||||
|
||||
$ret = array_merge([
|
||||
'validation_users' => $users,
|
||||
@@ -1530,7 +1545,7 @@ class V1Controller extends Controller
|
||||
|
||||
$status = $request->get('status');
|
||||
|
||||
$datas = strrev($record->get_status());
|
||||
$datas = strrev($record->getStatus());
|
||||
|
||||
if (!is_array($status)) {
|
||||
return $this->getBadRequestAction($request);
|
||||
@@ -1549,7 +1564,7 @@ class V1Controller extends Controller
|
||||
$datas = substr($datas, 0, ($n)) . $value . substr($datas, ($n + 2));
|
||||
}
|
||||
|
||||
$record->set_binary_status(strrev($datas));
|
||||
$record->setStatus(strrev($datas));
|
||||
|
||||
// @todo Move event dispatch inside record_adapter class (keeps things encapsulated)
|
||||
$this->dispatch(PhraseaEvents::RECORD_EDIT, new RecordEdit($record));
|
||||
@@ -2170,7 +2185,7 @@ class V1Controller extends Controller
|
||||
$story->removeChild($record);
|
||||
}
|
||||
|
||||
return $record->get_serialize_key();
|
||||
return $record->getId();
|
||||
}
|
||||
|
||||
public function addRecordsToStoryAction(Request $request, $databox_id, $story_id)
|
||||
@@ -2232,7 +2247,7 @@ class V1Controller extends Controller
|
||||
|
||||
$this->dispatch(PhraseaEvents::RECORD_EDIT, new RecordEdit($story));
|
||||
|
||||
return $record->get_serialize_key();
|
||||
return $record->getId();
|
||||
}
|
||||
|
||||
public function getCurrentUserAction(Request $request)
|
||||
|
@@ -68,7 +68,7 @@ class DatafileController extends AbstractDelivery
|
||||
|
||||
$stamp = false;
|
||||
$watermark = !$this->acl->get($this->authentication->getUser())
|
||||
->has_right_on_base($record->get_base_id(), 'nowatermark');
|
||||
->has_right_on_base($record->getBaseId(), 'nowatermark');
|
||||
|
||||
if ($watermark && !$all_access) {
|
||||
$subdef_class = null;
|
||||
|
@@ -122,7 +122,7 @@ class PermalinkController extends AbstractDelivery
|
||||
$watermark = $stamp = false;
|
||||
|
||||
if ($this->authentication->isAuthenticated()) {
|
||||
$watermark = !$this->acl->get($this->authentication->getUser())->has_right_on_base($record->get_base_id(), 'nowatermark');
|
||||
$watermark = !$this->acl->get($this->authentication->getUser())->has_right_on_base($record->getBaseId(), 'nowatermark');
|
||||
|
||||
if ($watermark) {
|
||||
/** @var BasketElementRepository $repository */
|
||||
@@ -138,7 +138,7 @@ class PermalinkController extends AbstractDelivery
|
||||
return $this->deliverContentWithCaptionLink($request, $record, $subdef, $watermark, $stamp, $token);
|
||||
}
|
||||
|
||||
$collection = \collection::getByBaseId($this->app, $record->get_base_id());
|
||||
$collection = \collection::getByBaseId($this->app, $record->getBaseId());
|
||||
switch ($collection->get_pub_wm()) {
|
||||
default:
|
||||
case 'none':
|
||||
@@ -169,8 +169,8 @@ class PermalinkController extends AbstractDelivery
|
||||
$response = $this->deliverContent($request, $record, $subdef, $watermark, $stamp);
|
||||
|
||||
$response->headers->set('Link', $this->app->url("permalinks_caption", [
|
||||
'sbas_id' => $record->get_sbas_id(),
|
||||
'record_id' => $record->get_record_id(),
|
||||
'sbas_id' => $record->getDataboxId(),
|
||||
'record_id' => $record->getRecordId(),
|
||||
'token' => $token,
|
||||
]));
|
||||
|
||||
|
@@ -20,7 +20,7 @@ use Alchemy\Phrasea\Model\Entities\Preset;
|
||||
use Alchemy\Phrasea\Model\Entities\User;
|
||||
use Alchemy\Phrasea\Model\Manipulator\PresetManipulator;
|
||||
use Alchemy\Phrasea\Model\Repositories\PresetRepository;
|
||||
use Alchemy\Phrasea\Vocabulary\Controller as VocabularyController;
|
||||
use Alchemy\Phrasea\Vocabulary\ControlProvider\ControlProviderInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
@@ -146,17 +146,17 @@ class EditController extends Controller
|
||||
foreach ($records as $record) {
|
||||
$indice = $record->getNumber();
|
||||
$elements[$indice] = [
|
||||
'bid' => $record->get_base_id(),
|
||||
'rid' => $record->get_record_id(),
|
||||
'bid' => $record->getBaseId(),
|
||||
'rid' => $record->getRecordId(),
|
||||
'sselcont_id' => null,
|
||||
'_selected' => false,
|
||||
'fields' => $databox_fields,
|
||||
];
|
||||
|
||||
$elements[$indice]['statbits'] = [];
|
||||
if ($this->getAclForUser()->has_right_on_base($record->get_base_id(), 'chgstatus')) {
|
||||
if ($this->getAclForUser()->has_right_on_base($record->getBaseId(), 'chgstatus')) {
|
||||
foreach ($status as $n => $s) {
|
||||
$tmp_val = substr(strrev($record->get_status()), $n, 1);
|
||||
$tmp_val = substr(strrev($record->getStatus()), $n, 1);
|
||||
$elements[$indice]['statbits'][$n]['value'] = ($tmp_val == '1') ? '1' : '0';
|
||||
$elements[$indice]['statbits'][$n]['dirty'] = false;
|
||||
}
|
||||
@@ -209,7 +209,7 @@ class EditController extends Controller
|
||||
['record' => $record]
|
||||
);
|
||||
|
||||
$elements[$indice]['type'] = $record->get_type();
|
||||
$elements[$indice]['type'] = $record->getType();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -231,7 +231,7 @@ class EditController extends Controller
|
||||
}
|
||||
|
||||
public function searchVocabularyAction(Request $request, $vocabulary) {
|
||||
$datas = ['success' => false, 'message' => '', 'results' => []];
|
||||
$data = ['success' => false, 'message' => '', 'results' => []];
|
||||
|
||||
$sbas_id = (int) $request->query->get('sbas_id');
|
||||
|
||||
@@ -240,33 +240,33 @@ class EditController extends Controller
|
||||
throw new \Exception('Invalid sbas_id');
|
||||
}
|
||||
|
||||
$VC = VocabularyController::get($this->app, $vocabulary);
|
||||
/** @var ControlProviderInterface $vocabularyProvider */
|
||||
$vocabularyProvider = $this->app['vocabularies'][strtolower($vocabulary)];
|
||||
$databox = $this->findDataboxById($sbas_id);
|
||||
} catch (\Exception $e) {
|
||||
$datas['message'] = $this->app->trans('Vocabulary not found');
|
||||
$data['message'] = $this->app->trans('Vocabulary not found');
|
||||
|
||||
return $this->app->json($datas);
|
||||
return $this->app->json($data);
|
||||
}
|
||||
|
||||
$query = $request->query->get('query');
|
||||
|
||||
$results = $VC->find($query, $this->getAuthenticatedUser(), $databox);
|
||||
$results = $vocabularyProvider->find($query, $this->getAuthenticatedUser(), $databox);
|
||||
|
||||
$list = [];
|
||||
|
||||
foreach ($results as $Term) {
|
||||
/* @var \Alchemy\Phrasea\Vocabulary\Term $Term */
|
||||
foreach ($results as $term) {
|
||||
$list[] = [
|
||||
'id' => $Term->getId(),
|
||||
'context' => $Term->getContext(),
|
||||
'value' => $Term->getValue(),
|
||||
'id' => $term->getId(),
|
||||
'context' => $term->getContext(),
|
||||
'value' => $term->getValue(),
|
||||
];
|
||||
}
|
||||
|
||||
$datas['success'] = true;
|
||||
$datas['results'] = $list;
|
||||
$data['success'] = true;
|
||||
$data['results'] = $list;
|
||||
|
||||
return $this->app->json($datas);
|
||||
return $this->app->json($data);
|
||||
}
|
||||
|
||||
public function applyAction(Request $request) {
|
||||
@@ -287,7 +287,7 @@ class EditController extends Controller
|
||||
try {
|
||||
$reg_record = $records->singleStory();
|
||||
|
||||
$newsubdef_reg = new \record_adapter($this->app, $reg_record->get_sbas_id(), $request->request->get('newrepresent'));
|
||||
$newsubdef_reg = new \record_adapter($this->app, $reg_record->getDataboxId(), $request->request->get('newrepresent'));
|
||||
|
||||
foreach ($newsubdef_reg->get_subdefs() as $name => $value) {
|
||||
if (!in_array($name, ['thumbnail', 'preview'])) {
|
||||
@@ -300,7 +300,7 @@ class EditController extends Controller
|
||||
$media = $this->app->getMediaFromUri($value->getRealPath());
|
||||
$this->getSubDefinitionSubstituer()->substitute($reg_record, $name, $media);
|
||||
$this->getDispatcher()->dispatch(PhraseaEvents::RECORD_EDIT, new RecordEdit($reg_record));
|
||||
$this->getDataboxLogger($reg_record->get_databox())->log(
|
||||
$this->getDataboxLogger($reg_record->getDatabox())->log(
|
||||
$reg_record,
|
||||
\Session_Logger::EVENT_SUBSTITUTE,
|
||||
$name == 'document' ? 'HD' : $name,
|
||||
@@ -325,7 +325,7 @@ class EditController extends Controller
|
||||
continue;
|
||||
}
|
||||
|
||||
$key = $record->get_serialize_key();
|
||||
$key = $record->getId();
|
||||
|
||||
if (!array_key_exists($key, $elements)) {
|
||||
continue;
|
||||
@@ -345,7 +345,7 @@ class EditController extends Controller
|
||||
$this->getDispatcher()->dispatch(PhraseaEvents::RECORD_EDIT, new RecordEdit($record));
|
||||
}
|
||||
|
||||
$newstat = $record->get_status();
|
||||
$newstat = $record->getStatus();
|
||||
$statbits = ltrim($statbits, 'x');
|
||||
if (!in_array($statbits, ['', 'null'])) {
|
||||
$mask_and = ltrim(str_replace(['x', '0', '1', 'z'], ['1', 'z', '0', '1'], $statbits), '0');
|
||||
@@ -359,13 +359,13 @@ class EditController extends Controller
|
||||
$newstat = \databox_status::operation_or($newstat, $mask_or);
|
||||
}
|
||||
|
||||
$record->set_binary_status($newstat);
|
||||
$record->setStatus($newstat);
|
||||
}
|
||||
|
||||
$record
|
||||
->write_metas()
|
||||
->get_collection()
|
||||
->reset_stamp($record->get_record_id());
|
||||
->getCollection()
|
||||
->reset_stamp($record->getRecordId());
|
||||
|
||||
if ($statbits != '') {
|
||||
$this->getDataboxLogger($databox)
|
||||
|
@@ -81,8 +81,8 @@ class FeedController extends Controller
|
||||
foreach ($publishing as $record) {
|
||||
$item = new FeedItem();
|
||||
$item->setEntry($entry)
|
||||
->setRecordId($record->get_record_id())
|
||||
->setSbasId($record->get_sbas_id());
|
||||
->setRecordId($record->getRecordId())
|
||||
->setSbasId($record->getDataboxId());
|
||||
$entry->addItem($item);
|
||||
$manager->persist($item);
|
||||
}
|
||||
|
@@ -206,7 +206,7 @@ class LazaretController extends Controller
|
||||
|
||||
//Check if the chosen record is eligible to the substitution
|
||||
foreach ($lazaretFile->getRecordsToSubstitute($this->app) as $record) {
|
||||
if ($record->get_record_id() !== (int) $recordId) {
|
||||
if ($record->getRecordId() !== (int) $recordId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -230,7 +230,7 @@ class LazaretController extends Controller
|
||||
$record = $lazaretFile->getCollection($this->app)->get_databox()->get_record($recordId);
|
||||
$this->getSubDefinitionSubstituer()
|
||||
->substitute($record, 'document', $media);
|
||||
$this->getDataboxLogger($record->get_databox())->log(
|
||||
$this->getDataboxLogger($record->getDatabox())->log(
|
||||
$record,
|
||||
\Session_Logger::EVENT_SUBSTITUTE,
|
||||
'HD',
|
||||
|
@@ -70,8 +70,8 @@ class MoveCollectionController extends Controller
|
||||
|
||||
if ($request->request->get("chg_coll_son") == "1") {
|
||||
/** @var \record_adapter $child */
|
||||
foreach ($record->get_children() as $child) {
|
||||
if ($this->getAclForUser()->has_right_on_base($child->get_base_id(), 'candeleterecord')) {
|
||||
foreach ($record->getChildren() as $child) {
|
||||
if ($this->getAclForUser()->has_right_on_base($child->getBaseId(), 'candeleterecord')) {
|
||||
$child->move_to_collection($collection, $this->getApplicationBox());
|
||||
}
|
||||
}
|
||||
|
@@ -34,7 +34,7 @@ class PrinterController extends Controller
|
||||
$layout = $request->request->get('lay');
|
||||
|
||||
foreach ($printer->get_elements() as $record) {
|
||||
$this->getDataboxLogger($record->get_databox())->log($record, \Session_Logger::EVENT_PRINT, $layout, '');
|
||||
$this->getDataboxLogger($record->getDatabox())->log($record, \Session_Logger::EVENT_PRINT, $layout, '');
|
||||
}
|
||||
$PDF = new PDFExport($this->app, $printer->get_elements(), $layout);
|
||||
|
||||
|
@@ -87,17 +87,17 @@ class PropertyController extends Controller
|
||||
|
||||
foreach ($records as $record) {
|
||||
//perform logic
|
||||
$sbasId = $record->get_databox()->get_sbas_id();
|
||||
$sbasId = $record->getDataboxId();
|
||||
|
||||
if (!isset($recordsType[$sbasId])) {
|
||||
$recordsType[$sbasId] = [];
|
||||
}
|
||||
|
||||
if (!isset($recordsType[$sbasId][$record->get_type()])) {
|
||||
$recordsType[$sbasId][$record->get_type()] = [];
|
||||
if (!isset($recordsType[$sbasId][$record->getType()])) {
|
||||
$recordsType[$sbasId][$record->getType()] = [];
|
||||
}
|
||||
|
||||
$recordsType[$sbasId][$record->get_type()][] = $record;
|
||||
$recordsType[$sbasId][$record->getType()][] = $record;
|
||||
}
|
||||
|
||||
return new Response($this->render('prod/actions/Property/type.html.twig', [
|
||||
@@ -120,18 +120,18 @@ class PropertyController extends Controller
|
||||
$postStatus = (array) $request->request->get('status');
|
||||
|
||||
foreach ($records as $record) {
|
||||
$sbasId = $record->get_databox()->get_sbas_id();
|
||||
$sbasId = $record->getDataboxId();
|
||||
|
||||
//update record
|
||||
if (null !== $updatedStatus = $this->updateRecordStatus($record, $postStatus)) {
|
||||
$updated[$record->get_serialize_key()] = $updatedStatus;
|
||||
$updated[$record->getId()] = $updatedStatus;
|
||||
}
|
||||
|
||||
//update children if current record is a story
|
||||
if (isset($applyStatusToChildren[$sbasId]) && $record->isStory()) {
|
||||
foreach ($record->get_children() as $child) {
|
||||
foreach ($record->getChildren() as $child) {
|
||||
if (null !== $updatedStatus = $this->updateRecordStatus($child, $postStatus)) {
|
||||
$updated[$record->get_serialize_key()] = $updatedStatus;
|
||||
$updated[$record->getId()] = $updatedStatus;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -156,17 +156,17 @@ class PropertyController extends Controller
|
||||
|
||||
foreach ($records as $record) {
|
||||
try {
|
||||
$recordType = !empty($forceType) ? $forceType : (isset($typeLst[$record->get_serialize_key()]) ? $typeLst[$record->get_serialize_key()] : null);
|
||||
$mimeType = isset($mimeLst[$record->get_serialize_key()]) ? $mimeLst[$record->get_serialize_key()] : null;
|
||||
$recordType = !empty($forceType) ? $forceType : (isset($typeLst[$record->getId()]) ? $typeLst[$record->getId()] : null);
|
||||
$mimeType = isset($mimeLst[$record->getId()]) ? $mimeLst[$record->getId()] : null;
|
||||
|
||||
if ($recordType) {
|
||||
$record->set_type($recordType);
|
||||
$updated[$record->get_serialize_key()]['record_type'] = $recordType;
|
||||
$record->setType($recordType);
|
||||
$updated[$record->getId()]['record_type'] = $recordType;
|
||||
}
|
||||
|
||||
if ($mimeType) {
|
||||
$record->set_mime($mimeType);
|
||||
$updated[$record->get_serialize_key()]['mime_type'] = $mimeType;
|
||||
$record->setMimeType($mimeType);
|
||||
$updated[$record->getId()]['mime_type'] = $mimeType;
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
|
||||
@@ -185,18 +185,18 @@ class PropertyController extends Controller
|
||||
*/
|
||||
private function updateRecordStatus(\record_adapter $record, array $postStatus)
|
||||
{
|
||||
$sbasId = $record->get_databox()->get_sbas_id();
|
||||
$sbasId = $record->getDataboxId();
|
||||
|
||||
if (isset($postStatus[$sbasId]) && is_array($postStatus[$sbasId])) {
|
||||
$postStatus = $postStatus[$sbasId];
|
||||
$currentStatus = strrev($record->get_status());
|
||||
$currentStatus = strrev($record->getStatus());
|
||||
|
||||
$newStatus = '';
|
||||
foreach (range(0, 31) as $i) {
|
||||
$newStatus .= isset($postStatus[$i]) ? ($postStatus[$i] ? '1' : '0') : $currentStatus[$i];
|
||||
}
|
||||
|
||||
$record->set_binary_status(strrev($newStatus));
|
||||
$record->setStatus(strrev($newStatus));
|
||||
|
||||
return [
|
||||
'current_status' => $currentStatus,
|
||||
|
@@ -124,7 +124,7 @@ class PushController extends Controller
|
||||
);
|
||||
}
|
||||
|
||||
$this->getDataboxLogger($element->get_databox())->log(
|
||||
$this->getDataboxLogger($element->getDatabox())->log(
|
||||
$element,
|
||||
\Session_Logger::EVENT_VALIDATE,
|
||||
$user_receiver->getId(),
|
||||
@@ -322,7 +322,7 @@ class PushController extends Controller
|
||||
$manager->merge($basketElement);
|
||||
$manager->persist($validationData);
|
||||
|
||||
$this->getDataboxLogger($basketElement->getRecord($this->app)->get_databox())->log(
|
||||
$this->getDataboxLogger($basketElement->getRecord($this->app)->getDatabox())->log(
|
||||
$basketElement->getRecord($this->app),
|
||||
\Session_Logger::EVENT_PUSH,
|
||||
$participantUser->getId(),
|
||||
|
@@ -43,8 +43,6 @@ class QueryController extends Controller
|
||||
|
||||
$options = SearchEngineOptions::fromRequest($this->app, $request);
|
||||
|
||||
$form = $options->serialize();
|
||||
|
||||
$perPage = (int) $this->getSettings()->getUserSetting($this->getAuthenticatedUser(), 'images_per_page');
|
||||
|
||||
$page = (int) $request->request->get('pag');
|
||||
@@ -56,13 +54,15 @@ class QueryController extends Controller
|
||||
$page = 1;
|
||||
}
|
||||
|
||||
$options->setFirstResult(($page - 1) * $perPage);
|
||||
$options->setMaxResults($perPage);
|
||||
|
||||
$user = $this->getAuthenticatedUser();
|
||||
$userManipulator = $this->getUserManipulator();
|
||||
$userManipulator->logQuery($user, $query);
|
||||
|
||||
try {
|
||||
/** @var SearchEngineResult $result */
|
||||
$result = $engine->query($query, (($page - 1) * $perPage), $perPage, $options);
|
||||
$result = $engine->query($query, $options);
|
||||
|
||||
if ($this->getSettings()->getUserSetting($user, 'start_page') === 'LAST_QUERY') {
|
||||
$userManipulator->setUserSetting($user, 'start_page_query', $query);
|
||||
@@ -216,7 +216,7 @@ class QueryController extends Controller
|
||||
$json['total_answers'] = (int) $result->getAvailable();
|
||||
$json['next_page'] = ($page < $npages && $result->getAvailable() > 0) ? ($page + 1) : false;
|
||||
$json['prev_page'] = ($page > 1 && $result->getAvailable() > 0) ? ($page - 1) : false;
|
||||
$json['form'] = $form;
|
||||
$json['form'] = $options->serialize();
|
||||
}
|
||||
catch(\Exception $e) {
|
||||
// we'd like a message from the parser so get all the exceptions messages
|
||||
|
@@ -106,8 +106,8 @@ class RecordController extends Controller
|
||||
]),
|
||||
"pos" => $record->getNumber(),
|
||||
"title" => str_replace(array('[[em]]', '[[/em]]'), array('<em>', '</em>'), $record->get_title($query, $searchEngine)),
|
||||
"collection_name" => $record->get_collection()->get_name(),
|
||||
"collection_logo" => $record->get_collection()->getLogo($record->get_base_id(), $this->app),
|
||||
"collection_name" => $record->getCollection()->get_name(),
|
||||
"collection_logo" => $record->getCollection()->getLogo($record->getBaseId(), $this->app),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -119,7 +119,8 @@ class RecordController extends Controller
|
||||
*/
|
||||
public function doDeleteRecords(Request $request)
|
||||
{
|
||||
$records = RecordsRequest::fromRequest($this->app, $request, !!$request->request->get('del_children'), [
|
||||
$flatten = (bool)($request->request->get('del_children')) ? RecordsRequest::FLATTEN_YES_PRESERVE_STORIES : RecordsRequest::FLATTEN_NO;
|
||||
$records = RecordsRequest::fromRequest($this->app, $request, $flatten, [
|
||||
'candeleterecord'
|
||||
]);
|
||||
|
||||
@@ -135,7 +136,7 @@ class RecordController extends Controller
|
||||
|
||||
foreach ($basketElements as $element) {
|
||||
$manager->remove($element);
|
||||
$deleted[] = $element->getRecord($this->app)->get_serialize_key();
|
||||
$deleted[] = $element->getRecord($this->app)->getId();
|
||||
}
|
||||
|
||||
$attachedStories = $StoryWZRepository->findByRecord($this->app, $record);
|
||||
@@ -144,7 +145,7 @@ class RecordController extends Controller
|
||||
$manager->remove($attachedStory);
|
||||
}
|
||||
|
||||
$deleted[] = $record->get_serialize_key();
|
||||
$deleted[] = $record->getId();
|
||||
$record->delete();
|
||||
} catch (\Exception $e) {
|
||||
|
||||
@@ -186,7 +187,7 @@ class RecordController extends Controller
|
||||
|
||||
$renewed = [];
|
||||
foreach ($records as $record) {
|
||||
$renewed[$record->get_serialize_key()] = (string) $record->get_preview()->renew_url();
|
||||
$renewed[$record->getId()] = (string) $record->get_preview()->renew_url();
|
||||
};
|
||||
|
||||
return $this->app->json($renewed);
|
||||
|
@@ -84,8 +84,8 @@ class StoryController extends Controller
|
||||
'message' => $this->app->trans('Story created'),
|
||||
'WorkZone' => $storyWZ->getId(),
|
||||
'story' => [
|
||||
'sbas_id' => $story->get_sbas_id(),
|
||||
'record_id' => $story->get_record_id(),
|
||||
'sbas_id' => $story->getDataboxId(),
|
||||
'record_id' => $story->getRecordId(),
|
||||
],
|
||||
];
|
||||
|
||||
@@ -109,7 +109,7 @@ class StoryController extends Controller
|
||||
{
|
||||
$Story = new \record_adapter($this->app, $sbas_id, $record_id);
|
||||
|
||||
if (!$this->getAclForUser()->has_right_on_base($Story->get_base_id(), 'canmodifrecord')) {
|
||||
if (!$this->getAclForUser()->has_right_on_base($Story->getBaseId(), 'canmodifrecord')) {
|
||||
throw new AccessDeniedHttpException('You can not add document to this Story');
|
||||
}
|
||||
|
||||
@@ -145,7 +145,7 @@ class StoryController extends Controller
|
||||
$story = new \record_adapter($this->app, $sbas_id, $record_id);
|
||||
$record = new \record_adapter($this->app, $child_sbas_id, $child_record_id);
|
||||
|
||||
if (!$this->getAclForUser()->has_right_on_base($story->get_base_id(), 'canmodifrecord')) {
|
||||
if (!$this->getAclForUser()->has_right_on_base($story->getBaseId(), 'canmodifrecord')) {
|
||||
throw new AccessDeniedHttpException('You can not add document to this Story');
|
||||
}
|
||||
|
||||
@@ -188,17 +188,17 @@ class StoryController extends Controller
|
||||
throw new \Exception('This is not a story');
|
||||
}
|
||||
|
||||
if (!$this->getAclForUser()->has_right_on_base($story->get_base_id(), 'canmodifrecord')) {
|
||||
if (!$this->getAclForUser()->has_right_on_base($story->getBaseId(), 'canmodifrecord')) {
|
||||
throw new ControllerException($this->app->trans('You can not edit this story'));
|
||||
}
|
||||
|
||||
$sql = 'UPDATE regroup SET ord = :ord WHERE rid_parent = :parent_id AND rid_child = :children_id';
|
||||
$stmt = $story->get_databox()->get_connection()->prepare($sql);
|
||||
$stmt = $story->getDatabox()->get_connection()->prepare($sql);
|
||||
|
||||
foreach ($request->request->get('element') as $record_id => $ord) {
|
||||
$params = [
|
||||
':ord' => $ord,
|
||||
':parent_id' => $story->get_record_id(),
|
||||
':parent_id' => $story->getRecordId(),
|
||||
':children_id' => $record_id
|
||||
];
|
||||
$stmt->execute($params);
|
||||
|
@@ -68,7 +68,7 @@ class ToolsController extends Controller
|
||||
continue;
|
||||
}
|
||||
$label = $this->app->trans('prod::tools: document');
|
||||
} elseif (isset($databoxSubdefs[$subdefName])) {
|
||||
} elseif ($databoxSubdefs->hasSubdef($subdefName)) {
|
||||
if (!$acl->has_access_to_subdef($record, $subdefName)) {
|
||||
continue;
|
||||
}
|
||||
@@ -202,7 +202,7 @@ class ToolsController extends Controller
|
||||
$record->insertTechnicalDatas($this->getMediaVorus());
|
||||
$this->getMetadataSetter()->replaceMetadata($this->getMetadataReader() ->read($media), $record);
|
||||
|
||||
$this->getDataboxLogger($record->get_databox())
|
||||
$this->getDataboxLogger($record->getDatabox())
|
||||
->log($record, \Session_Logger::EVENT_SUBSTITUTE, 'HD', '' );
|
||||
|
||||
if ((int) $request->request->get('ccfilename') === 1) {
|
||||
@@ -259,7 +259,7 @@ class ToolsController extends Controller
|
||||
$media = $this->app->getMediaFromUri($tempoFile);
|
||||
|
||||
$this->getSubDefinitionSubstituer()->substitute($record, 'thumbnail', $media);
|
||||
$this->getDataboxLogger($record->get_databox())
|
||||
$this->getDataboxLogger($record->getDatabox())
|
||||
->log($record, \Session_Logger::EVENT_SUBSTITUTE, 'thumbnail', '');
|
||||
|
||||
unlink($tempoFile);
|
||||
@@ -415,7 +415,7 @@ class ToolsController extends Controller
|
||||
{
|
||||
$dataUri = Parser::parse($subDefDataUri);
|
||||
|
||||
$name = sprintf('extractor_thumb_%s', $record->get_serialize_key());
|
||||
$name = sprintf('extractor_thumb_%s', $record->getId());
|
||||
$fileName = sprintf('%s/%s.png', sys_get_temp_dir(), $name);
|
||||
|
||||
file_put_contents($fileName, $dataUri->getData());
|
||||
@@ -423,7 +423,7 @@ class ToolsController extends Controller
|
||||
$media = $this->app->getMediaFromUri($fileName);
|
||||
|
||||
$this->getSubDefinitionSubstituer()->substitute($record, $subDefName, $media);
|
||||
$this->getDataboxLogger($record->get_databox())
|
||||
$this->getDataboxLogger($record->getDatabox())
|
||||
->log($record, \Session_Logger::EVENT_SUBSTITUTE, $subDefName, '');
|
||||
|
||||
unset($media);
|
||||
|
@@ -178,7 +178,7 @@ class UploadController extends Controller
|
||||
}
|
||||
|
||||
if ($elementCreated instanceof \record_adapter) {
|
||||
$id = $elementCreated->get_serialize_key();
|
||||
$id = $elementCreated->getId();
|
||||
$element = 'record';
|
||||
$message = $this->app->trans('The record was successfully created');
|
||||
|
||||
@@ -194,7 +194,7 @@ class UploadController extends Controller
|
||||
$media = $this->app->getMediaFromUri($fileName);
|
||||
|
||||
$this->getSubDefinitionSubstituer()->substitute($elementCreated, 'thumbnail', $media);
|
||||
$this->getDataboxLogger($elementCreated->get_databox())
|
||||
$this->getDataboxLogger($elementCreated->getDatabox())
|
||||
->log($elementCreated, \Session_Logger::EVENT_SUBSTITUTE, 'thumbnail', '');
|
||||
|
||||
unset($media);
|
||||
|
@@ -100,7 +100,7 @@ class WorkzoneController extends Controller
|
||||
throw new \Exception('You can only attach stories');
|
||||
}
|
||||
|
||||
if (!$acl->has_access_to_base($story->get_base_id())) {
|
||||
if (!$acl->has_access_to_base($story->getBaseId())) {
|
||||
throw new AccessDeniedHttpException('You do not have access to this Story');
|
||||
}
|
||||
|
||||
|
@@ -14,6 +14,7 @@ namespace Alchemy\Phrasea\Controller;
|
||||
use Alchemy\Phrasea\Model\Entities\Basket;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Alchemy\Phrasea\Application;
|
||||
use record_adapter;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
|
||||
@@ -46,13 +47,14 @@ class RecordsRequest extends ArrayCollection
|
||||
|
||||
if (self::FLATTEN_NO !== $flatten) {
|
||||
$to_remove = [];
|
||||
/** @var record_adapter $record */
|
||||
foreach ($this as $key => $record) {
|
||||
if ($record->isStory()) {
|
||||
if (self::FLATTEN_YES === $flatten) {
|
||||
$to_remove[] = $key;
|
||||
}
|
||||
foreach ($record->get_children() as $child) {
|
||||
$this->set($child->get_serialize_key(), $child);
|
||||
foreach ($record->getChildren() as $child) {
|
||||
$this->set($child->getId(), $child);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -180,7 +182,7 @@ class RecordsRequest extends ArrayCollection
|
||||
public function serializedList()
|
||||
{
|
||||
if ($this->isSingleStory()) {
|
||||
return $this->singleStory()->get_serialize_key();
|
||||
return $this->singleStory()->getId();
|
||||
}
|
||||
|
||||
$basrec = [];
|
||||
@@ -211,7 +213,7 @@ class RecordsRequest extends ArrayCollection
|
||||
$app['acl.basket']->hasAccess($basket, $app->getAuthenticatedUser());
|
||||
|
||||
foreach ($basket->getElements() as $basket_element) {
|
||||
$received[$basket_element->getRecord($app)->get_serialize_key()] = $basket_element->getRecord($app);
|
||||
$received[$basket_element->getRecord($app)->getId()] = $basket_element->getRecord($app);
|
||||
}
|
||||
} elseif ($request->get('story')) {
|
||||
$repository = $app['repo.story-wz'];
|
||||
@@ -230,7 +232,7 @@ class RecordsRequest extends ArrayCollection
|
||||
}
|
||||
try {
|
||||
$record = new \record_adapter($app, (int) $basrec[0], (int) $basrec[1]);
|
||||
$received[$record->get_serialize_key()] = $record;
|
||||
$received[$record->getId()] = $record;
|
||||
unset($record);
|
||||
} catch (NotFoundHttpException $e) {
|
||||
continue;
|
||||
|
@@ -325,8 +325,8 @@ class InformationController extends Controller
|
||||
|
||||
/** @var \record_adapter $record */
|
||||
$reportArray = $what->buildTabUserWhat(
|
||||
$record->get_base_id(),
|
||||
$record->get_record_id(),
|
||||
$record->getBaseId(),
|
||||
$record->getRecordId(),
|
||||
$config
|
||||
);
|
||||
|
||||
@@ -393,7 +393,7 @@ class InformationController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
$filter->addfilter('record_id', '=', $record->get_record_id());
|
||||
$filter->addfilter('record_id', '=', $record->getRecordId());
|
||||
|
||||
$download->setFilter($filter->getTabFilter());
|
||||
$download->setOrder('ddate', 'DESC');
|
||||
|
@@ -14,6 +14,7 @@ namespace Alchemy\Phrasea\ControllerProvider\Admin;
|
||||
use Alchemy\Phrasea\Application as PhraseaApplication;
|
||||
use Alchemy\Phrasea\Controller\Admin\FieldsController;
|
||||
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
|
||||
use Alchemy\Phrasea\Vocabulary\ControlProvider\UserProvider;
|
||||
use Silex\Application;
|
||||
use Silex\ControllerProviderInterface;
|
||||
use Silex\ServiceProviderInterface;
|
||||
@@ -24,6 +25,15 @@ class Fields implements ControllerProviderInterface, ServiceProviderInterface
|
||||
|
||||
public function register(Application $app)
|
||||
{
|
||||
$app['vocabularies'] = $app->share(function (PhraseaApplication $app) {
|
||||
$vocabularies = new \Pimple();
|
||||
|
||||
$vocabularies['user'] = $vocabularies->share(function () use ($app) {
|
||||
return new UserProvider($app);
|
||||
});
|
||||
|
||||
return $vocabularies;
|
||||
});
|
||||
$app['controller.admin.fields'] = $app->share(function (PhraseaApplication $app) {
|
||||
return new FieldsController($app);
|
||||
});
|
||||
|
@@ -37,6 +37,12 @@ class SearchEngine implements ControllerProviderInterface, ServiceProviderInterf
|
||||
/** @var ControllerCollection $controllers */
|
||||
$controllers = $app['controllers_factory'];
|
||||
|
||||
$controllers->post('/drop_index', 'controller.admin.search-engine:dropIndexAction')
|
||||
->bind("admin_searchengine_drop_index");
|
||||
|
||||
$controllers->post('/create_index', 'controller.admin.search-engine:createIndexAction')
|
||||
->bind("admin_searchengine_create_index");
|
||||
|
||||
$controllers->match('/', 'controller.admin.search-engine:formConfigurationPanelAction')
|
||||
->method('GET|POST')
|
||||
->bind('admin_searchengine_form');
|
||||
|
@@ -13,8 +13,10 @@ use Alchemy\Phrasea\Application as PhraseaApplication;
|
||||
use Alchemy\Phrasea\Controller\Api\BasketController;
|
||||
use Alchemy\Phrasea\Controller\Api\LazaretController;
|
||||
use Alchemy\Phrasea\Controller\Api\SearchController;
|
||||
use Alchemy\Phrasea\Controller\LazyLocator;
|
||||
use Alchemy\Phrasea\ControllerProvider\ControllerProviderTrait;
|
||||
use Alchemy\Phrasea\Core\Event\Listener\OAuthListener;
|
||||
use Alchemy\Phrasea\Order\Controller\ApiOrderController;
|
||||
use Silex\Application;
|
||||
use Silex\Controller;
|
||||
use Silex\ControllerProviderInterface;
|
||||
@@ -48,6 +50,15 @@ class V2 implements ControllerProviderInterface, ServiceProviderInterface
|
||||
return new SearchController($app);
|
||||
}
|
||||
);
|
||||
|
||||
$app['controller.api.v2.orders'] = $app->share(
|
||||
function (PhraseaApplication $app) {
|
||||
return (new ApiOrderController($app))
|
||||
->setDispatcher($app['dispatcher'])
|
||||
->setEntityManagerLocator(new LazyLocator($app, 'orm.em'))
|
||||
->setJsonBodyHelper($app['json.body_helper']);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
public function boot(Application $app)
|
||||
@@ -89,6 +100,22 @@ class V2 implements ControllerProviderInterface, ServiceProviderInterface
|
||||
->bind('api_v2_quarantine_item_add');
|
||||
$this->addQuarantineMiddleware($controller);
|
||||
|
||||
$controllers->post('/orders/', 'controller.api.v2.orders:createAction')
|
||||
->bind('api_v2_orders_create');
|
||||
$controllers->get('/orders/', 'controller.api.v2.orders:indexAction')
|
||||
->bind('api_v2_orders_index');
|
||||
$controllers->get('/orders/{orderId}', 'controller.api.v2.orders:showAction')
|
||||
->assert('orderId', '\d+')
|
||||
->bind('api_v2_orders_show');
|
||||
|
||||
$controllers->post('/orders/{orderId}/accept', 'controller.api.v2.orders:acceptElementsAction')
|
||||
->assert('orderId', '\d+')
|
||||
->bind('api_v2_orders_accept');
|
||||
|
||||
$controllers->post('/orders/{orderId}/deny', 'controller.api.v2.orders:denyElementsAction')
|
||||
->assert('orderId', '\d+')
|
||||
->bind('api_v2_orders_deny');
|
||||
|
||||
return $controllers;
|
||||
}
|
||||
|
||||
|
@@ -10,6 +10,7 @@
|
||||
namespace Alchemy\Phrasea\ControllerProvider;
|
||||
|
||||
use Alchemy\Phrasea\Controller\MediaAccessorController;
|
||||
use Alchemy\Phrasea\Media\MediaSubDefinitionUrlGenerator;
|
||||
use Alchemy\Phrasea\Model\Entities\Secret;
|
||||
use Alchemy\Phrasea\Model\Provider\DefaultSecretProvider;
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
@@ -33,6 +34,13 @@ class MediaAccessor implements ServiceProviderInterface, ControllerProviderInter
|
||||
return new DefaultSecretProvider($app['repo.secrets'], $app['random.medium']);
|
||||
});
|
||||
|
||||
$app['media_accessor.subdef_url_generator'] = $app->share(function (Application $app) {
|
||||
$defaultTTL = (int)$app['conf']->get(['registry', 'general', 'default-subdef-url-ttl'], 0);
|
||||
|
||||
return new MediaSubDefinitionUrlGenerator($app['url_generator'], $app['provider.secrets'], $defaultTTL);
|
||||
});
|
||||
|
||||
|
||||
$app['controller.media_accessor'] = $app->share(function (Application $app) {
|
||||
return (new MediaAccessorController($app))
|
||||
->setAllowedAlgorithms(['HS256'])
|
||||
|
@@ -14,6 +14,7 @@ namespace Alchemy\Phrasea\ControllerProvider;
|
||||
use Alchemy\Phrasea\Application as PhraseaApplication;
|
||||
use Alchemy\Phrasea\Controller\LazyLocator;
|
||||
use Alchemy\Phrasea\Controller\PermalinkController;
|
||||
use Alchemy\Phrasea\Core\Event\Listener\OAuthListener;
|
||||
use Silex\Application;
|
||||
use Silex\ControllerCollection;
|
||||
use Silex\ControllerProviderInterface;
|
||||
@@ -69,6 +70,7 @@ class Permalink implements ControllerProviderInterface, ServiceProviderInterface
|
||||
->bind('permalinks_permaview_old');
|
||||
|
||||
$controllers->get('/v1/{sbas_id}/{record_id}/{subdef}/{label}', 'controller.permalink:deliverPermalink')
|
||||
->before(new OAuthListener(['exit_not_present' => false]))
|
||||
->bind('permalinks_permalink');
|
||||
|
||||
$controllers->match('/v1/{sbas_id}/{record_id}/{subdef}/{label}', 'controller.permalink:getOptionsResponse')
|
||||
|
@@ -212,6 +212,9 @@ class Configuration implements ConfigurationInterface
|
||||
private function writeCacheConfig($content)
|
||||
{
|
||||
$this->dumpFile($this->compiled, $content, 0600);
|
||||
if(function_exists("opcache_invalidate")) {
|
||||
opcache_invalidate($this->compiled);
|
||||
}
|
||||
}
|
||||
|
||||
private function isConfigFresh()
|
||||
|
@@ -1,9 +1,8 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2014 Alchemy
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -16,22 +15,19 @@ use Doctrine\DBAL\DriverManager;
|
||||
|
||||
class ConnectionPoolManager
|
||||
{
|
||||
/** @var Connection[] */
|
||||
/**
|
||||
* @var Connection[]
|
||||
*/
|
||||
private $connections = [];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
$this->closeAll();
|
||||
$this->connections = [];
|
||||
}
|
||||
|
||||
public function closeAll()
|
||||
{
|
||||
foreach ($this->connections as $key => $conn) {
|
||||
foreach ($this->connections as $conn) {
|
||||
$conn->close();
|
||||
}
|
||||
}
|
||||
@@ -88,4 +84,9 @@ class ConnectionPoolManager
|
||||
|
||||
return $this->connections[$key] = DriverManager::getConnection($params);
|
||||
}
|
||||
|
||||
public function all()
|
||||
{
|
||||
return $this->connections;
|
||||
}
|
||||
}
|
||||
|
@@ -26,8 +26,8 @@ class BridgeSubscriber extends AbstractNotificationSubscriber
|
||||
'usr_id' => $user->getId(),
|
||||
'reason' => $event->getReason(),
|
||||
'account_id' => $account->get_id(),
|
||||
'sbas_id' => $event->getElement()->get_record()->get_sbas_id(),
|
||||
'record_id' => $event->getElement()->get_record()->get_record_id(),
|
||||
'sbas_id' => $event->getElement()->get_record()->getDataboxId(),
|
||||
'record_id' => $event->getElement()->get_record()->getRecordId(),
|
||||
];
|
||||
|
||||
$datas = json_encode($params);
|
||||
|
@@ -1,53 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2014 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Core\Event\Subscriber;
|
||||
|
||||
use Alchemy\Phrasea\Application;
|
||||
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
|
||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
|
||||
class DoctrineQueriesLoggerSubscriber implements EventSubscriberInterface
|
||||
{
|
||||
private $app;
|
||||
|
||||
public function __construct(Application $app)
|
||||
{
|
||||
$this->app = $app;
|
||||
}
|
||||
|
||||
public static function getSubscribedEvents()
|
||||
{
|
||||
return [
|
||||
KernelEvents::RESPONSE => [
|
||||
['logQueries', -255],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function logQueries(GetResponseEvent $event)
|
||||
{
|
||||
if (Application::ENV_DEV !== $this->app->getEnvironment()) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($this->app['orm.query.logger']->queries as $query ) {
|
||||
$this->app['orm.sql-logger']->debug($query['sql'], array(
|
||||
'params' => $query['params'],
|
||||
'types' => $query['types'],
|
||||
'time' => $query['executionMS']
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -1,4 +1,12 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Core\MetaProvider;
|
||||
|
||||
@@ -6,6 +14,7 @@ use Alchemy\Phrasea\Application as PhraseaApplication;
|
||||
use Alchemy\Phrasea\Cache\Manager;
|
||||
use Alchemy\Phrasea\Core\Provider\ORMServiceProvider;
|
||||
use Dflydev\Silex\Provider\DoctrineOrm\DoctrineOrmServiceProvider;
|
||||
use Doctrine\Common\EventManager;
|
||||
use Doctrine\DBAL\Events;
|
||||
use Doctrine\ORM\Configuration;
|
||||
use Gedmo\DoctrineExtensions as GedmoExtension;
|
||||
@@ -28,12 +37,14 @@ class DatabaseMetaProvider implements ServiceProviderInterface
|
||||
private function setupDBAL(PhraseaApplication $app)
|
||||
{
|
||||
$app['dbs.config'] = $app->share($app->extend('dbs.config', function ($configs, $app) {
|
||||
if (! $app->isDebug()) {
|
||||
if (!isset($app['dbal.config.register.loggers'])) {
|
||||
return $configs;
|
||||
}
|
||||
|
||||
foreach($configs->keys() as $service) {
|
||||
$app['dbal.config.register.loggers']($configs[$service]);
|
||||
$loggerRegisterCallable = $app['dbal.config.register.loggers'];
|
||||
|
||||
foreach ($configs->keys() as $service) {
|
||||
$loggerRegisterCallable($configs[$service], $service);
|
||||
}
|
||||
|
||||
return $configs;
|
||||
@@ -56,7 +67,7 @@ class DatabaseMetaProvider implements ServiceProviderInterface
|
||||
{
|
||||
// Override "orm.cache.configurer" service provided for benefiting
|
||||
// of "phraseanet.cache-service"
|
||||
$app['orm.cache.configurer'] = $app->protect(function($name, Configuration $config, $options) use ($app) {
|
||||
$app['orm.cache.configurer'] = $app->protect(function ($name, Configuration $config, $options) use ($app) {
|
||||
/** @var Manager $service */
|
||||
$service = $app['phraseanet.cache-service'];
|
||||
|
||||
@@ -74,7 +85,7 @@ class DatabaseMetaProvider implements ServiceProviderInterface
|
||||
);
|
||||
});
|
||||
|
||||
$app['orm.proxies_dir'] = $app['root.path'].'/resources/proxies';
|
||||
$app['orm.proxies_dir'] = $app['root.path'] . '/resources/proxies';
|
||||
$app['orm.auto_generate_proxies'] = $app['debug'];
|
||||
$app['orm.proxies_namespace'] = 'Alchemy\Phrasea\Model\Proxies';
|
||||
|
||||
|
@@ -22,7 +22,6 @@ use Alchemy\Phrasea\Model\NativeQueryProvider;
|
||||
use Doctrine\Common\Annotations\AnnotationReader;
|
||||
use Doctrine\Common\Annotations\CachedReader;
|
||||
use Doctrine\Common\Cache\ArrayCache;
|
||||
use Doctrine\DBAL\Logging\DebugStack;
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use Doctrine\ORM\Configuration as ORMConfig;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
@@ -37,10 +36,11 @@ class ORMServiceProvider implements ServiceProviderInterface
|
||||
public function register(Application $app)
|
||||
{
|
||||
// Provides DSN string using database information
|
||||
$app['db.dsn'] = $app->protect(function(array $params) use ($app) {
|
||||
$app['db.dsn'] = $app->protect(function (array $params) use ($app) {
|
||||
$params = $app['db.info']($params);
|
||||
|
||||
switch ($params['driver']) {
|
||||
switch ($params['driver'])
|
||||
{
|
||||
case 'pdo_mysql':
|
||||
return sprintf('%s://%s:%s@%s:%s/%s',
|
||||
$params['driver'],
|
||||
@@ -61,22 +61,22 @@ class ORMServiceProvider implements ServiceProviderInterface
|
||||
});
|
||||
|
||||
// Hash a DSN string
|
||||
$app['hash.dsn'] = $app->protect(function($dsn) {
|
||||
$app['hash.dsn'] = $app->protect(function ($dsn) {
|
||||
return md5($dsn);
|
||||
});
|
||||
|
||||
// Return database test configuration
|
||||
$app['db.test.info'] = $app->share(function() use ($app) {
|
||||
$app['db.test.info'] = $app->share(function () use ($app) {
|
||||
return $app['conf']->get(['main', 'database-test'], array());
|
||||
});
|
||||
|
||||
// Return application box database configuration
|
||||
$app['db.appbox.info'] = $app->share(function() use ($app) {
|
||||
$app['db.appbox.info'] = $app->share(function () use ($app) {
|
||||
return $app['conf']->get(['main', 'database'], array());
|
||||
});
|
||||
|
||||
// Return database fixture configuration
|
||||
$app['db.fixture.info'] = $app->share(function() use ($app) {
|
||||
$app['db.fixture.info'] = $app->share(function () use ($app) {
|
||||
return [
|
||||
'driver' => 'pdo_sqlite',
|
||||
'path' => sprintf('%s/%s', $app['tmp.path'], 'db-ref.sqlite'),
|
||||
@@ -85,7 +85,7 @@ class ORMServiceProvider implements ServiceProviderInterface
|
||||
});
|
||||
|
||||
// Return databox database configuration
|
||||
$app['db.databox.info'] = $app->share(function() use ($app) {
|
||||
$app['db.databox.info'] = $app->share(function () use ($app) {
|
||||
if (false === $app['phraseanet.configuration']->isSetup()) {
|
||||
return array();
|
||||
}
|
||||
@@ -101,46 +101,46 @@ class ORMServiceProvider implements ServiceProviderInterface
|
||||
});
|
||||
|
||||
// Return unique key for fixture database
|
||||
$app['db.fixture.hash.key'] = $app->share(function() use ($app) {
|
||||
$app['db.fixture.hash.key'] = $app->share(function () use ($app) {
|
||||
$info = $app['db.fixture.info'];
|
||||
|
||||
return $app['hash.dsn']($app['db.dsn']($info));
|
||||
});
|
||||
|
||||
// Return unique key for test database
|
||||
$app['db.test.hash.key'] = $app->share(function() use ($app) {
|
||||
$app['db.test.hash.key'] = $app->share(function () use ($app) {
|
||||
$info = $app['db.test.info'];
|
||||
|
||||
return $app['hash.dsn']($app['db.dsn']($info));
|
||||
});
|
||||
|
||||
// Return unique for appbox database
|
||||
$app['db.appbox.hash.key'] = $app->share(function() use ($app) {
|
||||
$app['db.appbox.hash.key'] = $app->share(function () use ($app) {
|
||||
$info = $app['db.appbox.info'];
|
||||
|
||||
return $app['hash.dsn']($app['db.dsn']($info));
|
||||
});
|
||||
|
||||
// Return configuration option for test database in DoctrineServiceProvider
|
||||
$app['db.test.options'] = $app->share(function() use ($app) {
|
||||
$app['db.test.options'] = $app->share(function () use ($app) {
|
||||
return array($app['db.test.hash.key'] => $app['db.test.info']);
|
||||
});
|
||||
|
||||
// Return configuration option for test database in DoctrineServiceProvider
|
||||
$app['db.fixture.options'] = $app->share(function() use ($app) {
|
||||
$app['db.fixture.options'] = $app->share(function () use ($app) {
|
||||
return array($app['db.fixture.hash.key'] => $app['db.fixture.info']);
|
||||
});
|
||||
|
||||
// Return configuration option for appbox database in DoctrineServiceProvider
|
||||
$app['db.appbox.options'] = $app->share(function() use ($app) {
|
||||
$app['db.appbox.options'] = $app->share(function () use ($app) {
|
||||
return array($app['db.appbox.hash.key'] => $app['db.appbox.info']);
|
||||
});
|
||||
|
||||
// Return configuration option for databox databases in DoctrineServiceProvider
|
||||
$app['dbs.databox.options'] = $app->share(function() use ($app) {
|
||||
$app['dbs.databox.options'] = $app->share(function () use ($app) {
|
||||
$options = array();
|
||||
|
||||
foreach($app['db.databox.info'] as $info) {
|
||||
foreach ($app['db.databox.info'] as $info) {
|
||||
$info = $app['db.info']($info);
|
||||
|
||||
$key = $app['hash.dsn']($app['db.dsn']($info));
|
||||
@@ -153,7 +153,7 @@ class ORMServiceProvider implements ServiceProviderInterface
|
||||
|
||||
// Return DoctrineServiceProvider database options, it merges all previous
|
||||
// set database configuration
|
||||
$app['dbs.options'] = $app->share(function() use ($app) {
|
||||
$app['dbs.options'] = $app->share(function () use ($app) {
|
||||
if (false === $app['phraseanet.configuration']->isSetup()) {
|
||||
return [];
|
||||
}
|
||||
@@ -167,7 +167,7 @@ class ORMServiceProvider implements ServiceProviderInterface
|
||||
});
|
||||
|
||||
// Return DoctrineORMServiceProvider information for a database from its parameters
|
||||
$app['orm.em.options.from_info'] = $app->protect(function(array $info) use ($app) {
|
||||
$app['orm.em.options.from_info'] = $app->protect(function (array $info) use ($app) {
|
||||
$info = $app['db.info']($info);
|
||||
|
||||
$key = $app['hash.dsn']($app['db.dsn']($info));
|
||||
@@ -176,7 +176,7 @@ class ORMServiceProvider implements ServiceProviderInterface
|
||||
});
|
||||
|
||||
//Return DoctrineServiceProvider information for a database from its parameters
|
||||
$app['db.options.from_info'] = $app->protect(function(array $info) use ($app) {
|
||||
$app['db.options.from_info'] = $app->protect(function (array $info) use ($app) {
|
||||
$info = $app['db.info']($info);
|
||||
|
||||
$key = $app['hash.dsn']($app['db.dsn']($info));
|
||||
@@ -188,7 +188,7 @@ class ORMServiceProvider implements ServiceProviderInterface
|
||||
* Add orm on the fly, used only when a new databox is mounted.
|
||||
* This allow to use new EM instance right after the database is mounted.
|
||||
*/
|
||||
$app['orm.add'] = $app->protect(function($info) use ($app) {
|
||||
$app['orm.add'] = $app->protect(function ($info) use ($app) {
|
||||
$info = $app['db.info']($info);
|
||||
|
||||
$key = $app['hash.dsn']($app['db.dsn']($info));
|
||||
@@ -200,7 +200,7 @@ class ORMServiceProvider implements ServiceProviderInterface
|
||||
$app['dbs.config'][$key] = new Configuration();
|
||||
|
||||
$app['dbs'][$key] = $app['dbs']->share(function () use ($app, $info, $key) {
|
||||
return DriverManager::getConnection($info,$app['dbs.config'][$key] ,$app['dbs.event_manager'][$key]);
|
||||
return DriverManager::getConnection($info, $app['dbs.config'][$key], $app['dbs.event_manager'][$key]);
|
||||
});
|
||||
|
||||
$options = $app['orm.options']($key);
|
||||
@@ -230,7 +230,7 @@ class ORMServiceProvider implements ServiceProviderInterface
|
||||
return new \SplObjectStorage();
|
||||
});
|
||||
|
||||
$app['dbal.evm.register.listeners'] = $app->protect(function(EventManager $evm) use ($app) {
|
||||
$app['dbal.evm.register.listeners'] = $app->protect(function (EventManager $evm) use ($app) {
|
||||
$evm->addEventSubscriber(new TimestampableListener());
|
||||
/** @var \SplObjectStorage $listeners */
|
||||
$listeners = $app['dbal.evm.listeners'];
|
||||
@@ -239,23 +239,17 @@ class ORMServiceProvider implements ServiceProviderInterface
|
||||
}
|
||||
});
|
||||
|
||||
$app['dbal.config.register.loggers'] = $app->protect(function(Configuration $config) use ($app) {
|
||||
if ($app->getEnvironment() === PhraseaApplication::ENV_DEV) {
|
||||
$config->setSQLLogger($app['orm.query.logger']);
|
||||
}
|
||||
});
|
||||
|
||||
$app['orm.annotation.register'] = $app->protect(function($key) use($app) {
|
||||
$app['orm.annotation.register'] = $app->protect(function ($key) use($app) {
|
||||
$driver = new AnnotationDriver($app['orm.annotation.reader'], array(
|
||||
$app['root.path'].'/vendor/gedmo/doctrine-extensions/lib/Gedmo/Translatable/Entity/MappedSuperclass',
|
||||
$app['root.path'].'/vendor/gedmo/doctrine-extensions/lib/Gedmo/Loggable/Entity/MappedSuperclass',
|
||||
$app['root.path'].'/vendor/gedmo/doctrine-extensions/lib/Gedmo/Tree/Entity/MappedSuperclass',
|
||||
$app['root.path'] . '/vendor/gedmo/doctrine-extensions/lib/Gedmo/Translatable/Entity/MappedSuperclass',
|
||||
$app['root.path'] . '/vendor/gedmo/doctrine-extensions/lib/Gedmo/Loggable/Entity/MappedSuperclass',
|
||||
$app['root.path'] . '/vendor/gedmo/doctrine-extensions/lib/Gedmo/Tree/Entity/MappedSuperclass',
|
||||
));
|
||||
|
||||
$app['orm.add_mapping_driver']($driver, 'Gedmo', $key);
|
||||
});
|
||||
|
||||
$app['dbal.type.register'] = $app->protect(function(Connection $connection, $types) {
|
||||
$app['dbal.type.register'] = $app->protect(function (Connection $connection, $types) {
|
||||
$platform = $connection->getDatabasePlatform();
|
||||
|
||||
foreach (array_keys((array) $types) as $type) {
|
||||
@@ -263,7 +257,7 @@ class ORMServiceProvider implements ServiceProviderInterface
|
||||
}
|
||||
});
|
||||
|
||||
$app['orm.config.new'] = $app->protect(function($key, $options) use($app) {
|
||||
$app['orm.config.new'] = $app->protect(function ($key, $options) use($app) {
|
||||
$config = new ORMConfig();
|
||||
$app['orm.cache.configurer']($key, $config, $options);
|
||||
|
||||
@@ -287,7 +281,7 @@ class ORMServiceProvider implements ServiceProviderInterface
|
||||
|
||||
$chain = $app['orm.mapping_driver_chain.locator']($key);
|
||||
|
||||
foreach ((array)$options['mappings'] as $entity) {
|
||||
foreach ((array) $options['mappings'] as $entity) {
|
||||
if (!is_array($entity)) {
|
||||
throw new \InvalidArgumentException(
|
||||
"The 'orm.em.options' option 'mappings' should be an array of arrays."
|
||||
@@ -302,7 +296,8 @@ class ORMServiceProvider implements ServiceProviderInterface
|
||||
$config->addEntityNamespace($entity['alias'], $entity['namespace']);
|
||||
}
|
||||
|
||||
switch ($entity['type']) {
|
||||
switch ($entity['type'])
|
||||
{
|
||||
case 'annotation':
|
||||
$useSimpleAnnotationReader =
|
||||
isset($entity['use_simple_annotation_reader'])
|
||||
@@ -349,7 +344,7 @@ class ORMServiceProvider implements ServiceProviderInterface
|
||||
return $config;
|
||||
});
|
||||
|
||||
$app['orm.ems.options'] = $app->share(function() use ($app) {
|
||||
$app['orm.ems.options'] = $app->share(function () use ($app) {
|
||||
if (false === $app['phraseanet.configuration']->isSetup()) {
|
||||
return [];
|
||||
}
|
||||
@@ -366,7 +361,7 @@ class ORMServiceProvider implements ServiceProviderInterface
|
||||
/**
|
||||
* Check database connection information
|
||||
*/
|
||||
$app['db.info'] = $app->protect(function(array $info){
|
||||
$app['db.info'] = $app->protect(function (array $info) {
|
||||
if (!isset($info['driver'])) {
|
||||
$info['driver'] = 'pdo_mysql';
|
||||
}
|
||||
@@ -375,7 +370,8 @@ class ORMServiceProvider implements ServiceProviderInterface
|
||||
$info['charset'] = 'utf8';
|
||||
}
|
||||
|
||||
switch ($info['driver']) {
|
||||
switch ($info['driver'])
|
||||
{
|
||||
case 'pdo_mysql':
|
||||
foreach (array('user', 'password', 'host', 'dbname', 'port') as $param) {
|
||||
if (!array_key_exists($param, $info)) {
|
||||
@@ -396,7 +392,7 @@ class ORMServiceProvider implements ServiceProviderInterface
|
||||
/**
|
||||
* Return configuration option for appbox database in DoctrineORMServiceProvider
|
||||
*/
|
||||
$app['orm.em.appbox.options'] = $app->share(function() use ($app) {
|
||||
$app['orm.em.appbox.options'] = $app->share(function () use ($app) {
|
||||
$key = $app['db.appbox.hash.key'];
|
||||
|
||||
return array($key => $app['orm.options']($key));
|
||||
@@ -405,7 +401,7 @@ class ORMServiceProvider implements ServiceProviderInterface
|
||||
/**
|
||||
* Return configuration option for fixture database in DoctrineORMServiceProvider
|
||||
*/
|
||||
$app['orm.em.fixture.options'] = $app->share(function() use ($app) {
|
||||
$app['orm.em.fixture.options'] = $app->share(function () use ($app) {
|
||||
$key = $app['db.fixture.hash.key'];
|
||||
|
||||
return array($key => $app['orm.options']($key));
|
||||
@@ -414,7 +410,7 @@ class ORMServiceProvider implements ServiceProviderInterface
|
||||
/**
|
||||
* Return configuration option for test database in DoctrineORMServiceProvider
|
||||
*/
|
||||
$app['orm.em.test.options'] = $app->share(function() use ($app) {
|
||||
$app['orm.em.test.options'] = $app->share(function () use ($app) {
|
||||
$key = $app['db.test.hash.key'];
|
||||
|
||||
return array($key => $app['orm.options']($key));
|
||||
@@ -423,7 +419,7 @@ class ORMServiceProvider implements ServiceProviderInterface
|
||||
/**
|
||||
* Return configuration option for databox databases in DoctrineORMServiceProvider
|
||||
*/
|
||||
$app['orm.ems.databox.options'] = $app->share(function() use ($app) {
|
||||
$app['orm.ems.databox.options'] = $app->share(function () use ($app) {
|
||||
$options = array();
|
||||
|
||||
foreach ($app['db.databox.info'] as $base) {
|
||||
@@ -444,13 +440,13 @@ class ORMServiceProvider implements ServiceProviderInterface
|
||||
"alias" => "Phraseanet",
|
||||
"use_simple_annotation_reader" => false,
|
||||
"namespace" => 'Alchemy\Phrasea\Model\Entities',
|
||||
"path" => $app['root.path'].'/lib/Alchemy/Phrasea/Model/Entities',
|
||||
"path" => $app['root.path'] . '/lib/Alchemy/Phrasea/Model/Entities',
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
// Return orm configuration for a connection given its unique id
|
||||
$app['orm.options'] = $app->protect(function($connection) use ($app) {
|
||||
$app['orm.options'] = $app->protect(function ($connection) use ($app) {
|
||||
return array(
|
||||
"connection" => $connection,
|
||||
"mappings" => $app['orm.options.mappings'],
|
||||
@@ -469,7 +465,7 @@ class ORMServiceProvider implements ServiceProviderInterface
|
||||
* Path to doctrine log file
|
||||
*/
|
||||
$app['orm.monolog.handler.file'] = $app->share(function (Application $app) {
|
||||
return $app['log.path'].'/doctrine.log';
|
||||
return $app['log.path'] . '/doctrine.log';
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -480,7 +476,7 @@ class ORMServiceProvider implements ServiceProviderInterface
|
||||
/**
|
||||
* Monolog handler for doctrine
|
||||
*/
|
||||
$app['orm.monolog.handler'] = $app->share(function(Application $app) {
|
||||
$app['orm.monolog.handler'] = $app->share(function (Application $app) {
|
||||
return new RotatingFileHandler($app['orm.monolog.handler.file'], $app['orm.monolog.handler.file.max-files']);
|
||||
});
|
||||
|
||||
@@ -495,13 +491,6 @@ class ORMServiceProvider implements ServiceProviderInterface
|
||||
return $logger;
|
||||
});
|
||||
|
||||
/**
|
||||
* Doctrine query logger
|
||||
*/
|
||||
$app['orm.query.logger'] = $app->share(function () {
|
||||
return new DebugStack();
|
||||
});
|
||||
|
||||
/**
|
||||
* Return cache driver
|
||||
*/
|
||||
@@ -548,7 +537,7 @@ class ORMServiceProvider implements ServiceProviderInterface
|
||||
return $manager->get($info);
|
||||
});
|
||||
|
||||
$app['connection.pool.manager'] = $app->share(function() {
|
||||
$app['connection.pool.manager'] = $app->share(function () {
|
||||
return new ConnectionPoolManager();
|
||||
});
|
||||
|
||||
@@ -563,7 +552,7 @@ class ORMServiceProvider implements ServiceProviderInterface
|
||||
/**
|
||||
* Return an instance of annotation cache reader
|
||||
*/
|
||||
$app['orm.annotation.reader'] = $app->share(function() use ($app) {
|
||||
$app['orm.annotation.reader'] = $app->share(function () use ($app) {
|
||||
$cache = new ArrayCache();
|
||||
if ($app->getEnvironment() !== PhraseaApplication::ENV_DEV) {
|
||||
$cache = $app['phraseanet.cache-service']->factory(
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
/**
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
|
@@ -1,9 +1,8 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2014 Alchemy
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -11,6 +10,7 @@
|
||||
|
||||
namespace Alchemy\Phrasea\Core\Provider;
|
||||
|
||||
use Alchemy\Phrasea\Controller\LazyLocator;
|
||||
use Alchemy\Phrasea\Model\Serializer\CaptionSerializer;
|
||||
use Alchemy\Phrasea\Model\Serializer\ESRecordSerializer;
|
||||
use Silex\Application;
|
||||
@@ -21,15 +21,16 @@ class SerializerServiceProvider implements ServiceProviderInterface
|
||||
public function register(Application $app)
|
||||
{
|
||||
$app['serializer.caption'] = $app->share(function (Application $app) {
|
||||
return new CaptionSerializer();
|
||||
return new CaptionSerializer(new LazyLocator($app, 'service.technical_data'));
|
||||
});
|
||||
|
||||
$app['serializer.es-record'] = $app->share(function (Application $app) {
|
||||
$app['serializer.es-record'] = $app->share(function () {
|
||||
return new ESRecordSerializer();
|
||||
});
|
||||
}
|
||||
|
||||
public function boot(Application $app)
|
||||
{
|
||||
// No-op
|
||||
}
|
||||
}
|
||||
|
@@ -2,11 +2,13 @@
|
||||
|
||||
namespace Alchemy\Phrasea\Core\Provider;
|
||||
|
||||
use Alchemy\Phrasea\Controller\LazyLocator;
|
||||
use Alchemy\Phrasea\Core\Event\Subscriber\CacheStatisticsSubscriber;
|
||||
use Alchemy\Phrasea\Core\Profiler\CacheDataCollector;
|
||||
use Alchemy\Phrasea\Core\Profiler\TraceableCache;
|
||||
use Alchemy\Phrasea\Utilities\LazyArrayAccess;
|
||||
use Doctrine\Common\Cache\Cache;
|
||||
use Doctrine\DBAL\Connection;
|
||||
use Doctrine\DBAL\Configuration;
|
||||
use Doctrine\DBAL\Logging\DebugStack;
|
||||
use Doctrine\DBAL\Logging\LoggerChain;
|
||||
use Silex\Application;
|
||||
@@ -47,19 +49,33 @@ class WebProfilerServiceProvider implements ServiceProviderInterface
|
||||
return $templates;
|
||||
}));
|
||||
|
||||
$app['data_collectors'] = $app->share($app->extend('data_collectors', function ($collectors) use ($app) {
|
||||
$collectors['ajax'] = function () {
|
||||
$app['data_collectors'] = $app->share($app->extend('data_collectors', function (array $collectors, $app) {
|
||||
$collectors['ajax'] = $app->share(function () {
|
||||
return new AjaxDataCollector();
|
||||
};
|
||||
});
|
||||
|
||||
return $collectors;
|
||||
}));
|
||||
}
|
||||
|
||||
$app['dbal.config.register.loggers'] = $app->protect(function (Configuration $config, $name) use ($app) {
|
||||
$debugLogger = new DebugStack();
|
||||
|
||||
$loggerChain = new LoggerChain();
|
||||
$loggerChain->addLogger($debugLogger);
|
||||
$loggerChain->addLogger($app['data_collectors.doctrine.logger']);
|
||||
|
||||
$app['data_collectors.doctrine']->addLogger($name, $debugLogger);
|
||||
|
||||
$config->setSQLLogger($loggerChain);
|
||||
});
|
||||
|
||||
$app['data_collectors.doctrine.logger'] = $app->share(function ($app) {
|
||||
return new DbalLogger($app['logger'], $app['stopwatch']);
|
||||
});
|
||||
|
||||
$app['data_collectors.doctrine'] = $app->share(function ($app) {
|
||||
/** @var Connection $db */
|
||||
$db = $app['db'];
|
||||
return new DoctrineDataCollector($db);
|
||||
return new DoctrineDataCollector(new LazyArrayAccess(new LazyLocator($app, 'dbs')));
|
||||
});
|
||||
|
||||
$app['cache'] = $app->share($app->extend('cache', function (Cache $cache, $app) {
|
||||
@@ -75,24 +91,9 @@ class WebProfilerServiceProvider implements ServiceProviderInterface
|
||||
return new CacheStatisticsSubscriber($app['cache']);
|
||||
});
|
||||
|
||||
$app['data_collectors'] = $app->share($app->extend('data_collectors', function ($collectors) use ($app) {
|
||||
$app['data_collectors'] = $app->share($app->extend('data_collectors', function (array $collectors, $app) {
|
||||
$collectors['db'] = $app->share(function ($app) {
|
||||
/** @var DoctrineDataCollector $collector */
|
||||
$collector = $app['data_collectors.doctrine'];
|
||||
|
||||
$loggerChain = new LoggerChain();
|
||||
$logger = new DebugStack();
|
||||
|
||||
$loggerChain->addLogger($logger);
|
||||
$loggerChain->addLogger(new DbalLogger($app['logger'], $app['stopwatch']));
|
||||
|
||||
/** @var Connection $db */
|
||||
$db = $app['db'];
|
||||
$db->getConfiguration()->setSQLLogger($loggerChain);
|
||||
|
||||
$collector->addLogger($logger);
|
||||
|
||||
return $collector;
|
||||
return $app['data_collectors.doctrine'];
|
||||
});
|
||||
|
||||
$collectors['cache'] = $app->share(function ($app) {
|
||||
|
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Databox;
|
||||
|
||||
interface DataboxBoundRepositoryFactory
|
||||
{
|
||||
/**
|
||||
* Creates a Repository bounded to given Databox
|
||||
*
|
||||
* @param $databoxId
|
||||
* @return object
|
||||
*/
|
||||
public function createRepositoryFor($databoxId);
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Databox;
|
||||
|
||||
class DataboxBoundRepositoryProvider
|
||||
{
|
||||
/**
|
||||
* Repositories indexed by databox id
|
||||
*
|
||||
* @var object[]
|
||||
*/
|
||||
private $repositories = [];
|
||||
|
||||
/**
|
||||
* @var DataboxBoundRepositoryFactory
|
||||
*/
|
||||
private $factory;
|
||||
|
||||
public function __construct(DataboxBoundRepositoryFactory $factory)
|
||||
{
|
||||
$this->factory = $factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $databoxId
|
||||
* @return object
|
||||
*/
|
||||
public function getRepositoryForDatabox($databoxId)
|
||||
{
|
||||
if (!isset($this->repositories[$databoxId])) {
|
||||
$this->repositories[$databoxId] = $this->factory->createRepositoryFor($databoxId);
|
||||
}
|
||||
|
||||
return $this->repositories[$databoxId];
|
||||
}
|
||||
}
|
@@ -1,10 +1,20 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Databox;
|
||||
|
||||
class DataboxConnectionProvider
|
||||
{
|
||||
|
||||
/**
|
||||
* @var \appbox
|
||||
*/
|
||||
private $applicationBox;
|
||||
|
||||
public function __construct(\appbox $applicationBox)
|
||||
@@ -13,7 +23,7 @@ class DataboxConnectionProvider
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $databoxId
|
||||
* @param int $databoxId
|
||||
* @return \Doctrine\DBAL\Connection
|
||||
*/
|
||||
public function getConnection($databoxId)
|
||||
|
@@ -125,7 +125,8 @@ class LegacyRecordRepository implements RecordRepository
|
||||
$connection->quoteIdentifier('type'),
|
||||
'originalname AS originalName',
|
||||
'sha256',
|
||||
'mime'
|
||||
'mime',
|
||||
'LPAD(BIN(status), 32, \'0\') as status'
|
||||
)
|
||||
->from('record', 'r');
|
||||
}
|
||||
|
@@ -0,0 +1,244 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Databox\Subdef;
|
||||
|
||||
use Alchemy\Phrasea\Cache\MultiAdapter;
|
||||
use Doctrine\Common\Cache\Cache;
|
||||
use Doctrine\Common\Cache\MultiGetCache;
|
||||
use Doctrine\Common\Cache\MultiPutCache;
|
||||
|
||||
class CachedMediaSubdefDataRepository implements MediaSubdefDataRepository
|
||||
{
|
||||
/**
|
||||
* @var MediaSubdefDataRepository
|
||||
*/
|
||||
private $decorated;
|
||||
|
||||
/**
|
||||
* @var Cache|MultiGetCache|MultiPutCache
|
||||
*/
|
||||
private $cache;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $baseKey;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $lifeTime = 0;
|
||||
|
||||
/**
|
||||
* @param MediaSubdefDataRepository $decorated
|
||||
* @param Cache $cache
|
||||
* @param string $baseKey
|
||||
*/
|
||||
public function __construct(MediaSubdefDataRepository $decorated, Cache $cache, $baseKey)
|
||||
{
|
||||
$this->decorated = $decorated;
|
||||
$this->cache = $cache instanceof MultiGetCache && $cache instanceof MultiPutCache
|
||||
? $cache
|
||||
: new MultiAdapter($cache);
|
||||
$this->baseKey = $baseKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getLifeTime()
|
||||
{
|
||||
return $this->lifeTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $lifeTime
|
||||
*/
|
||||
public function setLifeTime($lifeTime)
|
||||
{
|
||||
$this->lifeTime = (int)$lifeTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $recordIds
|
||||
* @param string[]|null $names
|
||||
* @return array
|
||||
*/
|
||||
public function findByRecordIdsAndNames(array $recordIds, array $names = null)
|
||||
{
|
||||
$keys = $this->computeKeys($recordIds, $names);
|
||||
|
||||
if ($keys) {
|
||||
$data = $this->cache->fetchMultiple($keys);
|
||||
|
||||
if (count($keys) === count($data)) {
|
||||
return $this->filterNonNull($data);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->fetchAndSave($recordIds, $names, $keys);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
private function filterNonNull(array $data)
|
||||
{
|
||||
return array_values(array_filter($data, function ($value) {
|
||||
return null !== $value;
|
||||
}));
|
||||
}
|
||||
|
||||
public function delete(array $subdefIds)
|
||||
{
|
||||
$deleted = $this->decorated->delete($subdefIds);
|
||||
|
||||
$keys = array_map([$this, 'dataToKey'], $subdefIds);
|
||||
|
||||
$this->cache->saveMultiple(array_fill_keys($keys, null), $this->lifeTime);
|
||||
|
||||
return $deleted;
|
||||
}
|
||||
|
||||
public function save(array $data)
|
||||
{
|
||||
$this->decorated->save($data);
|
||||
|
||||
// all saved keys are now stalled. decorated repository could modify values on store (update time for example)
|
||||
$recordIds = [];
|
||||
|
||||
foreach ($data as $item) {
|
||||
$recordIds[] = $item['record_id'];
|
||||
}
|
||||
|
||||
$keys = array_merge(array_map([$this, 'dataToKey'], $data), $this->generateAllCacheKeys($recordIds));
|
||||
|
||||
array_walk($keys, [$this->cache, 'delete']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @return string
|
||||
*/
|
||||
private function dataToKey(array $data)
|
||||
{
|
||||
return $this->getCacheKey($data['record_id'], $data['name']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $recordId
|
||||
* @param string|null $name
|
||||
* @return string
|
||||
*/
|
||||
private function getCacheKey($recordId, $name = null)
|
||||
{
|
||||
return $this->baseKey . 'media_subdef' . json_encode([(int)$recordId, $name]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $recordIds
|
||||
* @param string[] $names
|
||||
* @return string[]
|
||||
*/
|
||||
private function generateCacheKeys(array $recordIds, array $names)
|
||||
{
|
||||
$namesCount = count($names);
|
||||
|
||||
$keys = array_map(function ($recordId) use ($namesCount, $names) {
|
||||
return array_map([$this, 'getCacheKey'], array_fill(0, $namesCount, $recordId), $names);
|
||||
}, $recordIds);
|
||||
|
||||
return $keys ? call_user_func_array('array_merge', $keys) : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $recordIds
|
||||
* @return string[]
|
||||
*/
|
||||
private function generateAllCacheKeys(array $recordIds)
|
||||
{
|
||||
$recordIds = array_unique($recordIds);
|
||||
|
||||
return array_map([$this, 'getCacheKey'], $recordIds, array_fill(0, count($recordIds), null));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $recordIds
|
||||
* @param string[]|null $names
|
||||
* @param string[] $keys Known keys supposed to be fetched
|
||||
* @return array
|
||||
*/
|
||||
private function fetchAndSave(array $recordIds, array $names = null, array $keys = [])
|
||||
{
|
||||
$retrieved = $this->decorated->findByRecordIdsAndNames($recordIds, $names);
|
||||
|
||||
$data = $this->normalizeRetrievedData($retrieved, $keys);
|
||||
|
||||
$toCache = null === $names ? $this->appendCacheExtraData($data, $retrieved, $recordIds) : $data;
|
||||
|
||||
$this->cache->saveMultiple($toCache, $this->lifeTime);
|
||||
|
||||
return $this->filterNonNull($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $recordIds
|
||||
* @param string[]|null $names
|
||||
* @return string[]
|
||||
*/
|
||||
private function computeKeys(array $recordIds, array $names = null)
|
||||
{
|
||||
if (!$recordIds) {
|
||||
return [];
|
||||
} elseif (null !== $names) {
|
||||
return $this->generateCacheKeys($recordIds, $names);
|
||||
}
|
||||
|
||||
$keys = $this->generateAllCacheKeys($recordIds);
|
||||
$data = $this->cache->fetchMultiple($keys);
|
||||
|
||||
return count($keys) === count($data) ? call_user_func_array('array_merge', $data) : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $retrieved
|
||||
* @param array $keys
|
||||
* @return array
|
||||
*/
|
||||
private function normalizeRetrievedData(array $retrieved, array $keys)
|
||||
{
|
||||
$data = array_fill_keys($keys, null);
|
||||
|
||||
foreach ($retrieved as $item) {
|
||||
$data[$this->dataToKey($item)] = $item;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @param array $retrieved
|
||||
* @param array $recordIds
|
||||
* @return array
|
||||
*/
|
||||
private function appendCacheExtraData(array $data, array $retrieved, array $recordIds)
|
||||
{
|
||||
$extra = array_fill_keys($this->generateAllCacheKeys($recordIds), []);
|
||||
|
||||
foreach ($retrieved as $item) {
|
||||
$extra[$this->getCacheKey($item['record_id'])][] = $this->getCacheKey($item['record_id'], $item['name']);
|
||||
}
|
||||
|
||||
return array_merge($data, $extra);
|
||||
}
|
||||
}
|
@@ -0,0 +1,280 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Databox\Subdef;
|
||||
|
||||
use Doctrine\DBAL\Connection;
|
||||
use Doctrine\DBAL\DBALException;
|
||||
use Doctrine\DBAL\Exception\DriverException;
|
||||
|
||||
class DbalMediaSubdefDataRepository implements MediaSubdefDataRepository
|
||||
{
|
||||
/**
|
||||
* @var Connection
|
||||
*/
|
||||
private $connection;
|
||||
|
||||
public function __construct(Connection $connection)
|
||||
{
|
||||
$this->connection = $connection;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $recordIds
|
||||
* @param string[]|null $names
|
||||
* @return array[]
|
||||
*/
|
||||
public function findByRecordIdsAndNames(array $recordIds, array $names = null)
|
||||
{
|
||||
if (!$recordIds || (null !== $names && !$names)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$sql = $this->getSelectSQL() . ' WHERE record_id IN (:recordIds)';
|
||||
$params = ['recordIds' => $recordIds];
|
||||
$types = ['recordIds' => Connection::PARAM_INT_ARRAY];
|
||||
|
||||
if ($names) {
|
||||
$sql .= ' AND name IN (:names)';
|
||||
$params['names'] = $names;
|
||||
$types['names'] = Connection::PARAM_STR_ARRAY;
|
||||
}
|
||||
|
||||
return array_map([$this, 'sqlToPhp'], $this->connection->fetchAll($sql, $params, $types));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array[] $subdefIds
|
||||
* @return int The number of affected rows
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function delete(array $subdefIds)
|
||||
{
|
||||
if (!$subdefIds) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$statement = $this->connection->prepare('DELETE FROM subdef WHERE record_id = :record_id AND name = :name');
|
||||
|
||||
$this->connection->beginTransaction();
|
||||
|
||||
try {
|
||||
$deleted = array_reduce($subdefIds, function ($carry, $data) use ($statement) {
|
||||
$carry += $statement->execute([
|
||||
'record_id' => $data['record_id'],
|
||||
'name' => $data['name'],
|
||||
]);
|
||||
|
||||
return $carry;
|
||||
}, 0);
|
||||
|
||||
$this->connection->commit();
|
||||
} catch (\Exception $exception) {
|
||||
$this->connection->rollBack();
|
||||
|
||||
throw $exception;
|
||||
}
|
||||
|
||||
return $deleted;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function save(array $data)
|
||||
{
|
||||
$this->connection->transactional(function () use ($data) {
|
||||
$partitions = $this->partitionInsertAndUpdate($data);
|
||||
|
||||
$updateNeeded = $this->createMissing($partitions['insert']);
|
||||
|
||||
$this->updatePresent($partitions['update'] + $updateNeeded);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
private function partitionInsertAndUpdate(array $data)
|
||||
{
|
||||
$partitions = [
|
||||
'insert' => [],
|
||||
'update' => [],
|
||||
];
|
||||
|
||||
foreach ($data as $index => $item) {
|
||||
$partitions[isset($item['subdef_id']) ? 'update' : 'insert'][$index] = $item;
|
||||
}
|
||||
|
||||
return $partitions;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $toInsert
|
||||
* @return array
|
||||
* @throws DBALException
|
||||
*/
|
||||
private function createMissing(array $toInsert)
|
||||
{
|
||||
if (!$toInsert) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$statement = $this->connection->prepare($this->getInsertSql());
|
||||
|
||||
$updateNeeded = [];
|
||||
|
||||
foreach ($toInsert as $index => $data) {
|
||||
try {
|
||||
$statement->execute($this->phpToSql($data));
|
||||
} catch (DriverException $exception) {
|
||||
$updateNeeded[$index] = $data;
|
||||
}
|
||||
}
|
||||
|
||||
return $updateNeeded;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $toUpdate
|
||||
* @throws DBALException
|
||||
*/
|
||||
private function updatePresent(array $toUpdate)
|
||||
{
|
||||
if (!$toUpdate) {
|
||||
return;
|
||||
}
|
||||
|
||||
$statement = $this->connection->prepare($this->getUpdateSql());
|
||||
|
||||
foreach ($toUpdate as $data) {
|
||||
$statement->execute($this->phpToSql($data));
|
||||
}
|
||||
}
|
||||
|
||||
private function getSelectSQL()
|
||||
{
|
||||
return <<<'SQL'
|
||||
SELECT subdef_id, record_id, name, path, file, width, height, mime, size, substit, etag, created_on, updated_on
|
||||
FROM subdef
|
||||
SQL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @return array
|
||||
*/
|
||||
private function phpToSql(array $data)
|
||||
{
|
||||
return [
|
||||
'record_id' => $data['record_id'],
|
||||
'name' => $data['name'],
|
||||
'path' => $data['path'],
|
||||
'file' => $data['file'],
|
||||
'width' => $data['width'],
|
||||
'height' => $data['height'],
|
||||
'mime' => $data['mime'],
|
||||
'size' => $data['size'],
|
||||
'substit' => $data['is_substituted'],
|
||||
'etag' => $data['etag'],
|
||||
];
|
||||
}
|
||||
|
||||
private function sqlToPhp(array $data)
|
||||
{
|
||||
return [
|
||||
'subdef_id' => (int)$data['subdef_id'],
|
||||
'record_id' => (int)$data['record_id'],
|
||||
'name' => $data['name'],
|
||||
'path' => $data['path'],
|
||||
'file' => $data['file'],
|
||||
'width' => (int)$data['width'],
|
||||
'height' => (int)$data['height'],
|
||||
'mime' => $data['mime'],
|
||||
'size' => (int)$data['size'],
|
||||
'is_substituted' => (bool)$data['substit'],
|
||||
'etag' => $data['etag'],
|
||||
'created_on' => $data['created_on'],
|
||||
'updated_on' => $data['updated_on'],
|
||||
'physically_present' => true,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private function getInsertSql()
|
||||
{
|
||||
static $sql;
|
||||
|
||||
if (null !== $sql) {
|
||||
return $sql;
|
||||
}
|
||||
|
||||
$values = [
|
||||
'record_id' => ':record_id',
|
||||
'name' => ':name',
|
||||
'path' => ':path',
|
||||
'file' => ':file',
|
||||
'width' => ':width',
|
||||
'height' => ':height',
|
||||
'mime' => ':mime',
|
||||
'size' => ':size',
|
||||
'substit' => ':substit',
|
||||
'etag' => ':etag',
|
||||
'created_on' => 'NOW()',
|
||||
'updated_on' => 'NOW()',
|
||||
'dispatched' => '1',
|
||||
];
|
||||
|
||||
$sql = sprintf(
|
||||
'INSERT INTO subdef (%s) VALUES (%s)',
|
||||
implode(', ', array_keys($values)),
|
||||
implode(', ', array_values($values))
|
||||
);
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private function getUpdateSql()
|
||||
{
|
||||
static $sql;
|
||||
|
||||
if (null !== $sql) {
|
||||
return $sql;
|
||||
}
|
||||
|
||||
$values = [
|
||||
'path = :path',
|
||||
'file = :file',
|
||||
'width = :width',
|
||||
'height = :height',
|
||||
'mime = :mime',
|
||||
'size = :size',
|
||||
'substit = :substit',
|
||||
'etag = :etag',
|
||||
'updated_on = NOW()',
|
||||
];
|
||||
|
||||
$where = [
|
||||
'record_id = :record_id',
|
||||
'name = :name',
|
||||
];
|
||||
|
||||
$sql = sprintf('UPDATE subdef SET %s WHERE %s', implode(', ', $values), implode(' AND ', $where));
|
||||
|
||||
return $sql;
|
||||
}
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Databox\Subdef;
|
||||
|
||||
interface MediaSubdefDataRepository
|
||||
{
|
||||
/**
|
||||
* @param int[] $recordIds
|
||||
* @param string[]|null $names null means to look for all available names
|
||||
* @return array[]
|
||||
*/
|
||||
public function findByRecordIdsAndNames(array $recordIds, array $names = null);
|
||||
|
||||
/**
|
||||
* @param array[] $subdefIds (should be a list of associative arrays with record_id and name keys)
|
||||
* @return int The number of affected rows
|
||||
*/
|
||||
public function delete(array $subdefIds);
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @return void
|
||||
*/
|
||||
public function save(array $data);
|
||||
}
|
49
lib/Alchemy/Phrasea/Databox/Subdef/MediaSubdefHydrator.php
Normal file
49
lib/Alchemy/Phrasea/Databox/Subdef/MediaSubdefHydrator.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Databox\Subdef;
|
||||
|
||||
use Alchemy\Phrasea\Hydration\Hydrator;
|
||||
use Assert\Assertion;
|
||||
|
||||
class MediaSubdefHydrator implements Hydrator
|
||||
{
|
||||
/**
|
||||
* @param \media_subdef $instance
|
||||
* @param array $data
|
||||
* @throws \Assert\AssertionFailedException
|
||||
*/
|
||||
public function hydrate($instance, array $data)
|
||||
{
|
||||
Assertion::isInstanceOf($instance, \media_subdef::class);
|
||||
|
||||
$closure = \Closure::bind(function (array $data) {
|
||||
$this->loadFromArray($data);
|
||||
}, $instance, \media_subdef::class);
|
||||
|
||||
$closure($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \media_subdef $instance
|
||||
* @return array
|
||||
* @throws \Assert\AssertionFailedException
|
||||
*/
|
||||
public function extract($instance)
|
||||
{
|
||||
Assertion::isInstanceOf($instance, \media_subdef::class);
|
||||
|
||||
$closure = \Closure::bind(function () {
|
||||
return $this->toArray();
|
||||
}, $instance, \media_subdef::class);
|
||||
|
||||
return $closure();
|
||||
}
|
||||
}
|
138
lib/Alchemy/Phrasea/Databox/Subdef/MediaSubdefRepository.php
Normal file
138
lib/Alchemy/Phrasea/Databox/Subdef/MediaSubdefRepository.php
Normal file
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Databox\Subdef;
|
||||
|
||||
use Alchemy\Phrasea\Hydration\Hydrator;
|
||||
use Assert\Assertion;
|
||||
|
||||
class MediaSubdefRepository
|
||||
{
|
||||
/**
|
||||
* @var MediaSubdefDataRepository
|
||||
*/
|
||||
private $repository;
|
||||
|
||||
/**
|
||||
* @var \media_subdef[]
|
||||
*/
|
||||
private $idMap = [];
|
||||
|
||||
/**
|
||||
* @var callable
|
||||
*/
|
||||
private $subdefFactory;
|
||||
|
||||
/**
|
||||
* @var Hydrator
|
||||
*/
|
||||
private $hydrator;
|
||||
|
||||
public function __construct(MediaSubdefDataRepository $repository, callable $subdefFactory, Hydrator $hydrator = null)
|
||||
{
|
||||
$this->repository = $repository;
|
||||
$this->subdefFactory = $subdefFactory;
|
||||
$this->hydrator = $hydrator ?: new MediaSubdefHydrator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $recordId
|
||||
* @param string $name
|
||||
* @return \media_subdef|null
|
||||
*/
|
||||
public function findOneByRecordIdAndName($recordId, $name)
|
||||
{
|
||||
$subdefs = $this->repository->findByRecordIdsAndNames([$recordId], [$name]);
|
||||
|
||||
if (!$subdefs) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$instances = $this->hydrateAll($subdefs);
|
||||
|
||||
return reset($instances);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $recordIds
|
||||
* @param string[] $names
|
||||
* @return \media_subdef[]
|
||||
*/
|
||||
public function findByRecordIdsAndNames(array $recordIds, array $names = null)
|
||||
{
|
||||
if (!$recordIds) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$data = $this->repository->findByRecordIdsAndNames($recordIds, $names);
|
||||
|
||||
return $this->hydrateAll($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \media_subdef|\media_subdef[] $subdefs
|
||||
*/
|
||||
public function save($subdefs)
|
||||
{
|
||||
if (!is_array($subdefs) || !$subdefs instanceof \Traversable) {
|
||||
$subdefs = [$subdefs];
|
||||
} elseif ($subdefs instanceof \Traversable) {
|
||||
$subdefs = iterator_to_array($subdefs);
|
||||
}
|
||||
Assertion::allIsInstanceOf($subdefs, \media_subdef::class);
|
||||
|
||||
$data = array_map([$this->hydrator, 'extract'], $subdefs);
|
||||
|
||||
$this->repository->save($data);
|
||||
}
|
||||
|
||||
public function clear()
|
||||
{
|
||||
$this->idMap = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $index
|
||||
* @param array $data
|
||||
* @return \media_subdef
|
||||
*/
|
||||
private function hydrate($index, array $data)
|
||||
{
|
||||
if (isset($this->idMap[$index])) {
|
||||
$this->hydrator->hydrate($this->idMap[$index], $data);
|
||||
|
||||
return $this->idMap[$index];
|
||||
}
|
||||
|
||||
$factory = $this->subdefFactory;
|
||||
|
||||
$instance = $factory($data);
|
||||
Assertion::isInstanceOf($instance, \media_subdef::class);
|
||||
|
||||
$this->idMap[$index] = $instance;
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @return \media_subdef[]
|
||||
*/
|
||||
private function hydrateAll(array $data)
|
||||
{
|
||||
$instances = [];
|
||||
|
||||
foreach ($data as $item) {
|
||||
$instances[] = $this->hydrate(json_encode([$item['record_id'], $item['name']]), $item);
|
||||
}
|
||||
|
||||
return $instances;
|
||||
}
|
||||
}
|
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Databox\Subdef;
|
||||
|
||||
use Alchemy\Phrasea\Databox\DataboxBoundRepositoryFactory;
|
||||
use Alchemy\Phrasea\Databox\DataboxConnectionProvider;
|
||||
use Doctrine\Common\Cache\Cache;
|
||||
|
||||
class MediaSubdefRepositoryFactory implements DataboxBoundRepositoryFactory
|
||||
{
|
||||
/**
|
||||
* @var DataboxConnectionProvider
|
||||
*/
|
||||
private $connectionProvider;
|
||||
|
||||
/**
|
||||
* @var Cache
|
||||
*/
|
||||
private $cache;
|
||||
|
||||
/**
|
||||
* @var callable
|
||||
*/
|
||||
private $mediaSubdefFactoryProvider;
|
||||
|
||||
public function __construct(DataboxConnectionProvider $connectionProvider, Cache $cache, callable $mediaSubdefFactoryProvider)
|
||||
{
|
||||
$this->connectionProvider = $connectionProvider;
|
||||
$this->cache = $cache;
|
||||
$this->mediaSubdefFactoryProvider = $mediaSubdefFactoryProvider;
|
||||
}
|
||||
|
||||
public function createRepositoryFor($databoxId)
|
||||
{
|
||||
$connection = $this->connectionProvider->getConnection($databoxId);
|
||||
|
||||
$dbalRepository = new DbalMediaSubdefDataRepository($connection);
|
||||
$dataRepository = new CachedMediaSubdefDataRepository($dbalRepository, $this->cache, sprintf('databox%d:', $databoxId));
|
||||
|
||||
$provider = $this->mediaSubdefFactoryProvider;
|
||||
$factory = $provider($databoxId);
|
||||
|
||||
if (!is_callable($factory)) {
|
||||
throw new \UnexpectedValueException(sprintf(
|
||||
'Media subdef factory is expected to be callable, got %s',
|
||||
is_object($factory) ? get_class($factory) : gettype($factory)
|
||||
));
|
||||
}
|
||||
|
||||
return new MediaSubdefRepository($dataRepository, $factory);
|
||||
}
|
||||
}
|
120
lib/Alchemy/Phrasea/Databox/Subdef/MediaSubdefService.php
Normal file
120
lib/Alchemy/Phrasea/Databox/Subdef/MediaSubdefService.php
Normal file
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Databox\Subdef;
|
||||
|
||||
use Alchemy\Phrasea\Databox\DataboxBoundRepositoryProvider;
|
||||
use Alchemy\Phrasea\Model\RecordReferenceInterface;
|
||||
use Alchemy\Phrasea\Record\RecordReferenceCollection;
|
||||
|
||||
class MediaSubdefService
|
||||
{
|
||||
/**
|
||||
* @var DataboxBoundRepositoryProvider
|
||||
*/
|
||||
private $repositoryProvider;
|
||||
|
||||
public function __construct(DataboxBoundRepositoryProvider $repositoryProvider)
|
||||
{
|
||||
$this->repositoryProvider = $repositoryProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all available subdefs grouped by each record reference and by its name
|
||||
*
|
||||
* @param RecordReferenceInterface[]|RecordReferenceCollection $records
|
||||
* @return \media_subdef[][]
|
||||
*/
|
||||
public function findSubdefsByRecordReferenceFromCollection($records)
|
||||
{
|
||||
$subdefs = $this->reduceRecordReferenceCollection(
|
||||
$records,
|
||||
function (array &$carry, array $subdefs, array $indexes) {
|
||||
/** @var \media_subdef $subdef */
|
||||
foreach ($subdefs as $subdef) {
|
||||
$index = $indexes[$subdef->get_record_id()];
|
||||
|
||||
$carry[$index][$subdef->get_name()] = $subdef;
|
||||
}
|
||||
},
|
||||
array_fill_keys(array_keys(iterator_to_array($records)), [])
|
||||
);
|
||||
|
||||
ksort($subdefs);
|
||||
|
||||
return $subdefs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RecordReferenceInterface[]|RecordReferenceCollection $records
|
||||
* @return \media_subdef[]
|
||||
*/
|
||||
public function findSubdefsFromRecordReferenceCollection($records)
|
||||
{
|
||||
$groups = $this->reduceRecordReferenceCollection(
|
||||
$records,
|
||||
function (array &$carry, array $subdefs) {
|
||||
$carry[] = $subdefs;
|
||||
|
||||
return $carry;
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
||||
if ($groups) {
|
||||
return call_user_func_array('array_merge', $groups);
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RecordReferenceInterface[]|RecordReferenceCollection $records
|
||||
* @param callable $process
|
||||
* @param mixed $initialValue
|
||||
* @return mixed
|
||||
*/
|
||||
private function reduceRecordReferenceCollection($records, callable $process, $initialValue)
|
||||
{
|
||||
$records = $this->normalizeRecordCollection($records);
|
||||
|
||||
$carry = $initialValue;
|
||||
|
||||
foreach ($records->groupPerDataboxId() as $databoxId => $indexes) {
|
||||
$subdefs = $this->getRepositoryForDatabox($databoxId)->findByRecordIdsAndNames(array_keys($indexes));
|
||||
|
||||
$carry = $process($carry, $subdefs, $indexes, $databoxId);
|
||||
}
|
||||
|
||||
return $carry;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $databoxId
|
||||
* @return MediaSubdefRepository
|
||||
*/
|
||||
private function getRepositoryForDatabox($databoxId)
|
||||
{
|
||||
return $this->repositoryProvider->getRepositoryForDatabox($databoxId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RecordReferenceInterface[]|RecordReferenceCollection $records
|
||||
* @return RecordReferenceCollection
|
||||
*/
|
||||
private function normalizeRecordCollection($records)
|
||||
{
|
||||
if ($records instanceof RecordReferenceCollection) {
|
||||
return $records;
|
||||
}
|
||||
|
||||
return new RecordReferenceCollection($records);
|
||||
}
|
||||
}
|
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Databox\Subdef;
|
||||
|
||||
use Alchemy\Phrasea\Databox\DataboxBoundRepositoryProvider;
|
||||
use Alchemy\Phrasea\Databox\DataboxConnectionProvider;
|
||||
use Alchemy\Phrasea\Record\RecordReference;
|
||||
use Silex\Application;
|
||||
use Silex\ServiceProviderInterface;
|
||||
|
||||
class MediaSubdefServiceProvider implements ServiceProviderInterface
|
||||
{
|
||||
public function register(Application $app)
|
||||
{
|
||||
$app['provider.factory.media_subdef'] = $app->protect(function ($databoxId) use ($app) {
|
||||
return function (array $data) use ($app, $databoxId) {
|
||||
$recordReference = RecordReference::createFromDataboxIdAndRecordId($databoxId, $data['record_id']);
|
||||
|
||||
return new \media_subdef($app, $recordReference, $data['name'], false, $data);
|
||||
};
|
||||
});
|
||||
|
||||
$app['provider.repo.media_subdef'] = $app->share(function (Application $app) {
|
||||
$connectionProvider = new DataboxConnectionProvider($app['phraseanet.appbox']);
|
||||
$factoryProvider = $app['provider.factory.media_subdef'];
|
||||
|
||||
$repositoryFactory = new MediaSubdefRepositoryFactory($connectionProvider, $app['cache'], $factoryProvider);
|
||||
|
||||
return new DataboxBoundRepositoryProvider($repositoryFactory);
|
||||
});
|
||||
|
||||
$app['service.media_subdef'] = $app->share(function (Application $app) {
|
||||
return new MediaSubdefService($app['provider.repo.media_subdef']);
|
||||
});
|
||||
}
|
||||
|
||||
public function boot(Application $app)
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
}
|
@@ -17,6 +17,7 @@ use Alchemy\Phrasea\Feed\FeedInterface;
|
||||
use Alchemy\Phrasea\Feed\Link\FeedLink;
|
||||
use Alchemy\Phrasea\Feed\Link\LinkGeneratorCollection;
|
||||
use Alchemy\Phrasea\Model\Entities\User;
|
||||
use Alchemy\Phrasea\Utilities\NullableDateTime;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class AtomFormatter extends FeedFormatterAbstract implements FeedFormatterInterface
|
||||
@@ -48,8 +49,6 @@ class AtomFormatter extends FeedFormatterAbstract implements FeedFormatterInterf
|
||||
*/
|
||||
public function format(FeedInterface $feed, $page, User $user = null, $generator = 'Phraseanet', Application $app = null)
|
||||
{
|
||||
$updated_on = $feed->getUpdatedOn();
|
||||
|
||||
$document = new \DOMDocument('1.0', 'UTF-8');
|
||||
$document->formatOutput = true;
|
||||
$document->standalone = true;
|
||||
@@ -59,8 +58,7 @@ class AtomFormatter extends FeedFormatterAbstract implements FeedFormatterInterf
|
||||
$root->setAttribute('xmlns:media', 'http://search.yahoo.com/mrss/');
|
||||
|
||||
$this->addTag($document, $root, 'title', $feed->getTitle());
|
||||
if ($updated_on instanceof \DateTime) {
|
||||
$updated_on = $updated_on->format(DATE_ATOM);
|
||||
if (null !== $updated_on = NullableDateTime::format($feed->getUpdatedOn())) {
|
||||
$this->addTag($document, $root, 'updated', $updated_on);
|
||||
}
|
||||
|
||||
|
@@ -19,6 +19,7 @@ use Alchemy\Phrasea\Model\Entities\FeedEntry;
|
||||
use Alchemy\Phrasea\Model\Entities\FeedItem;
|
||||
use Alchemy\Phrasea\Feed\Link\LinkGeneratorCollection;
|
||||
use Alchemy\Phrasea\Model\Entities\User;
|
||||
use Alchemy\Phrasea\Utilities\NullableDateTime;
|
||||
use DateTime;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
@@ -52,8 +53,6 @@ class CoolirisFormatter extends FeedFormatterAbstract implements FeedFormatterIn
|
||||
*/
|
||||
public function format(FeedInterface $feed, $page, User $user = null, $generator = 'Phraseanet', Application $app = null)
|
||||
{
|
||||
$updated_on = $feed->getUpdatedOn();
|
||||
|
||||
$doc = new \DOMDocument('1.0', 'UTF-8');
|
||||
$doc->formatOutput = true;
|
||||
$doc->standalone = true;
|
||||
@@ -89,8 +88,7 @@ class CoolirisFormatter extends FeedFormatterAbstract implements FeedFormatterIn
|
||||
$this->addTag($doc, $channel, 'managingEditor', $this->managingEditor);
|
||||
if (isset($this->webMaster))
|
||||
$this->addTag($doc, $channel, 'webMaster', $this->webMaster);
|
||||
if ($updated_on instanceof DateTime) {
|
||||
$updated_on = $updated_on->format(DATE_RFC2822);
|
||||
if (null !== $updated_on = NullableDateTime::format($feed->getUpdatedOn(), DATE_RFC2822)) {
|
||||
$this->addTag($doc, $channel, 'pubDate', $updated_on);
|
||||
}
|
||||
if (isset($this->lastBuildDate) && $this->lastBuildDate instanceof DateTime) {
|
||||
@@ -191,7 +189,7 @@ class CoolirisFormatter extends FeedFormatterAbstract implements FeedFormatterIn
|
||||
$thumbnail_sd = $content->getRecord($app)->get_thumbnail();
|
||||
$thumbnail_permalink = $thumbnail_sd->get_permalink();
|
||||
|
||||
$medium = strtolower($content->getRecord($app)->get_type());
|
||||
$medium = strtolower($content->getRecord($app)->getType());
|
||||
|
||||
if ( ! in_array($medium, ['image', 'audio', 'video'])) {
|
||||
return $this;
|
||||
|
@@ -52,7 +52,7 @@ abstract class FeedFormatterAbstract
|
||||
$thumbnail_sd = $content->getRecord($app)->get_thumbnail();
|
||||
$thumbnail_permalink = $thumbnail_sd->get_permalink();
|
||||
|
||||
$medium = strtolower($content->getRecord($app)->get_type());
|
||||
$medium = strtolower($content->getRecord($app)->getType());
|
||||
|
||||
if ( ! in_array($medium, ['image', 'audio', 'video'])) {
|
||||
return $this;
|
||||
|
@@ -17,6 +17,7 @@ use Alchemy\Phrasea\Feed\Link\FeedLink;
|
||||
use Alchemy\Phrasea\Feed\Link\LinkGeneratorCollection;
|
||||
use Alchemy\Phrasea\Feed\RSS\FeedRSSImage;
|
||||
use Alchemy\Phrasea\Model\Entities\User;
|
||||
use Alchemy\Phrasea\Utilities\NullableDateTime;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Alchemy\Phrasea\Model\Entities\FeedEntry;
|
||||
use Alchemy\Phrasea\Feed\Link\FeedLinkGenerator;
|
||||
@@ -51,8 +52,6 @@ class RssFormatter extends FeedFormatterAbstract implements FeedFormatterInterfa
|
||||
*/
|
||||
public function format(FeedInterface $feed, $page, User $user = null, $generator = 'Phraseanet', Application $app = null)
|
||||
{
|
||||
$updated_on = $feed->getUpdatedOn();
|
||||
|
||||
$next = $prev = null;
|
||||
|
||||
if ($feed->hasPage($page + 1, self::PAGE_SIZE)) {
|
||||
@@ -104,11 +103,10 @@ class RssFormatter extends FeedFormatterAbstract implements FeedFormatterInterfa
|
||||
$this->addTag($doc, $channel, 'managingEditor', $this->managingEditor);
|
||||
if (isset($this->webMaster))
|
||||
$this->addTag($doc, $channel, 'webMaster', $this->webMaster);
|
||||
if ($updated_on instanceof \DateTime) {
|
||||
$updated_on = $updated_on->format(DATE_RFC2822);
|
||||
if (null !== $updated_on = NullableDateTime::format($feed->getUpdatedOn(), DATE_RFC2822)) {
|
||||
$this->addTag($doc, $channel, 'pubDate', $updated_on);
|
||||
}
|
||||
if (isset($this->lastBuildDate) && $this->lastBuildDate instanceof DateTime) {
|
||||
if (isset($this->lastBuildDate) && $this->lastBuildDate instanceof \DateTime) {
|
||||
$last_build = $this->lastBuildDate->format(DATE_RFC2822);
|
||||
$this->addTag($doc, $channel, 'lastBuildDate', $last_build);
|
||||
}
|
||||
|
@@ -284,7 +284,7 @@ class Helper extends \Alchemy\Phrasea\Helper\Helper
|
||||
public function get_serialize_list()
|
||||
{
|
||||
if ($this->is_single_grouping()) {
|
||||
return $this->get_grouping_head()->get_serialize_key();
|
||||
return $this->get_grouping_head()->getId();
|
||||
} else {
|
||||
return $this->selection->serialize_list();
|
||||
}
|
||||
|
31
lib/Alchemy/Phrasea/Hydration/Hydrator.php
Normal file
31
lib/Alchemy/Phrasea/Hydration/Hydrator.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Hydration;
|
||||
|
||||
interface Hydrator
|
||||
{
|
||||
/**
|
||||
* Hydrate an instance with provided data
|
||||
*
|
||||
* @param object $instance
|
||||
* @param array $data
|
||||
* @return void
|
||||
*/
|
||||
public function hydrate($instance, array $data);
|
||||
|
||||
/**
|
||||
* Extracts data from an instance
|
||||
*
|
||||
* @param object $instance
|
||||
* @return array
|
||||
*/
|
||||
public function extract($instance);
|
||||
}
|
114
lib/Alchemy/Phrasea/Hydration/IdentityMap.php
Normal file
114
lib/Alchemy/Phrasea/Hydration/IdentityMap.php
Normal file
@@ -0,0 +1,114 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Hydration;
|
||||
|
||||
use Assert\Assertion;
|
||||
|
||||
class IdentityMap implements \ArrayAccess, \IteratorAggregate, \Countable
|
||||
{
|
||||
/**
|
||||
* @var object[]
|
||||
*/
|
||||
private $entities;
|
||||
|
||||
/**
|
||||
* @var Hydrator
|
||||
*/
|
||||
private $hydrator;
|
||||
|
||||
/**
|
||||
* @var object
|
||||
*/
|
||||
private $prototype;
|
||||
|
||||
/**
|
||||
* @param Hydrator $hydrator
|
||||
* @param object $prototype A clonable prototype of objects in idMap
|
||||
*/
|
||||
public function __construct(Hydrator $hydrator, $prototype)
|
||||
{
|
||||
$this->hydrator = $hydrator;
|
||||
$this->prototype = $prototype;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|int $index
|
||||
* @param array $data
|
||||
* @return object
|
||||
*/
|
||||
public function hydrate($index, array $data)
|
||||
{
|
||||
if (!isset($this->entities[$index])) {
|
||||
$this->entities[$index] = clone $this->prototype;
|
||||
}
|
||||
|
||||
$instance = $this->entities[$index];
|
||||
|
||||
$this->hydrator->hydrate($instance, $data);
|
||||
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array[] $data
|
||||
* @return object[]
|
||||
*/
|
||||
public function hydrateAll(array $data)
|
||||
{
|
||||
Assertion::allIsArray($data);
|
||||
|
||||
$instances = [];
|
||||
|
||||
foreach ($data as $index => $item) {
|
||||
$instances[$index] = $this->hydrate($index, $item);
|
||||
}
|
||||
|
||||
return $instances;
|
||||
}
|
||||
|
||||
public function clear()
|
||||
{
|
||||
$this->entities = [];
|
||||
}
|
||||
|
||||
public function getIterator()
|
||||
{
|
||||
return new \ArrayIterator($this->entities);
|
||||
}
|
||||
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return isset($this->entities[$offset]);
|
||||
}
|
||||
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return $this->entities[$offset];
|
||||
}
|
||||
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
Assertion::notNull($offset);
|
||||
Assertion::isArray($value);
|
||||
|
||||
$this->hydrate($offset, $value);
|
||||
}
|
||||
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
unset($this->entities[$offset]);
|
||||
}
|
||||
|
||||
public function count()
|
||||
{
|
||||
return count($this->entities);
|
||||
}
|
||||
}
|
130
lib/Alchemy/Phrasea/Hydration/ReflectionHydrator.php
Normal file
130
lib/Alchemy/Phrasea/Hydration/ReflectionHydrator.php
Normal file
@@ -0,0 +1,130 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Hydration;
|
||||
|
||||
use Assert\Assertion;
|
||||
|
||||
class ReflectionHydrator implements Hydrator
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $className;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
private $properties;
|
||||
|
||||
/**
|
||||
* @var null|\ReflectionClass
|
||||
*/
|
||||
private $reflectionClass;
|
||||
/**
|
||||
* @var null|\ReflectionProperty[]
|
||||
*/
|
||||
private $reflectionProperties;
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
* @param string[] $properties
|
||||
*/
|
||||
public function __construct($className, array $properties)
|
||||
{
|
||||
$this->className = $className;
|
||||
$this->properties = $properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @param object $instance
|
||||
* @throws \Assert\AssertionFailedException
|
||||
*/
|
||||
public function hydrate($instance, array $data)
|
||||
{
|
||||
Assertion::isInstanceOf($instance, $this->className);
|
||||
|
||||
foreach ($data as $key => $value) {
|
||||
$this->getReflectionProperty($key)->setValue($instance, $value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param object $instance
|
||||
* @return array
|
||||
* @throws \Assert\AssertionFailedException
|
||||
*/
|
||||
public function extract($instance)
|
||||
{
|
||||
Assertion::isInstanceOf($instance, $this->className);
|
||||
|
||||
$data = [];
|
||||
|
||||
foreach ($this->getReflectionProperties() as $name => $property) {
|
||||
$data[$name] = $property->getValue($instance);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \ReflectionClass
|
||||
*/
|
||||
private function getReflectionClass()
|
||||
{
|
||||
if (null === $this->reflectionClass) {
|
||||
$this->reflectionClass = new \ReflectionClass($this->className);
|
||||
}
|
||||
|
||||
return $this->reflectionClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @return \ReflectionProperty
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
private function getReflectionProperty($name)
|
||||
{
|
||||
$this->loadReflectionProperties();
|
||||
|
||||
return $this->reflectionProperties[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \ReflectionProperty[]
|
||||
*/
|
||||
private function getReflectionProperties()
|
||||
{
|
||||
$this->loadReflectionProperties();
|
||||
|
||||
return $this->reflectionProperties;
|
||||
}
|
||||
|
||||
private function loadReflectionProperties()
|
||||
{
|
||||
if (null !== $this->reflectionProperties) {
|
||||
return;
|
||||
}
|
||||
|
||||
$class = $this->getReflectionClass();
|
||||
$properties = [];
|
||||
|
||||
foreach ($this->properties as $name) {
|
||||
$property = $class->getProperty($name);
|
||||
$property->setAccessible(true);
|
||||
|
||||
$properties[$name] = $property;
|
||||
}
|
||||
|
||||
$this->reflectionProperties = $properties;
|
||||
}
|
||||
}
|
@@ -11,22 +11,20 @@ namespace Alchemy\Phrasea\Media;
|
||||
|
||||
use Assert\Assertion;
|
||||
|
||||
final class ArrayTechnicalDataSet implements \IteratorAggregate, TechnicalDataSet
|
||||
class ArrayTechnicalDataSet implements \IteratorAggregate, TechnicalDataSet
|
||||
{
|
||||
/** @var TechnicalData[] */
|
||||
private $data;
|
||||
private $data = [];
|
||||
|
||||
/**
|
||||
* @param TechnicalData[] $data
|
||||
*/
|
||||
public function __construct($data = [])
|
||||
{
|
||||
Assertion::allIsInstanceOf($data, TechnicalData::class);
|
||||
|
||||
$this->data = [];
|
||||
Assertion::isTraversable($data);
|
||||
|
||||
foreach ($data as $technicalData) {
|
||||
$this->data[$technicalData->getName()] = $technicalData;
|
||||
$this[] = $technicalData;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +39,7 @@ final class ArrayTechnicalDataSet implements \IteratorAggregate, TechnicalDataSe
|
||||
$offset = $offset->getName();
|
||||
}
|
||||
|
||||
return isset($this->data[$offset]) || array_key_exists($offset, $this->data);
|
||||
return isset($this->data[$offset]);
|
||||
}
|
||||
|
||||
public function offsetGet($offset)
|
||||
@@ -50,7 +48,7 @@ final class ArrayTechnicalDataSet implements \IteratorAggregate, TechnicalDataSe
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $offset
|
||||
* @param null|string $offset
|
||||
* @param TechnicalData $value
|
||||
*/
|
||||
public function offsetSet($offset, $value)
|
||||
@@ -58,6 +56,7 @@ final class ArrayTechnicalDataSet implements \IteratorAggregate, TechnicalDataSe
|
||||
Assertion::isInstanceOf($value, TechnicalData::class);
|
||||
|
||||
$name = $value->getName();
|
||||
|
||||
if (null !== $offset) {
|
||||
Assertion::eq($name, $offset);
|
||||
}
|
||||
@@ -82,6 +81,7 @@ final class ArrayTechnicalDataSet implements \IteratorAggregate, TechnicalDataSe
|
||||
public function getValues()
|
||||
{
|
||||
$values = [];
|
||||
|
||||
foreach ($this->data as $key => $value) {
|
||||
$values[$key] = $value->getValue();
|
||||
}
|
||||
|
36
lib/Alchemy/Phrasea/Media/Factory/DbalRepositoryFactory.php
Normal file
36
lib/Alchemy/Phrasea/Media/Factory/DbalRepositoryFactory.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Media\Factory;
|
||||
|
||||
use Alchemy\Phrasea\Databox\DataboxConnectionProvider;
|
||||
use Alchemy\Phrasea\Media\RecordTechnicalDataSetRepositoryFactory;
|
||||
use Alchemy\Phrasea\Media\Repository\DbalRecordTechnicalDataSetRepository;
|
||||
|
||||
class DbalRepositoryFactory implements RecordTechnicalDataSetRepositoryFactory
|
||||
{
|
||||
/**
|
||||
* @var DataboxConnectionProvider
|
||||
*/
|
||||
private $connectionProvider;
|
||||
|
||||
public function __construct(DataboxConnectionProvider $connectionProvider)
|
||||
{
|
||||
$this->connectionProvider = $connectionProvider;
|
||||
}
|
||||
|
||||
public function createRepositoryForDatabox($databoxId)
|
||||
{
|
||||
return new DbalRecordTechnicalDataSetRepository(
|
||||
$this->connectionProvider->getConnection($databoxId),
|
||||
new TechnicalDataFactory()
|
||||
);
|
||||
}
|
||||
}
|
35
lib/Alchemy/Phrasea/Media/Factory/TechnicalDataFactory.php
Normal file
35
lib/Alchemy/Phrasea/Media/Factory/TechnicalDataFactory.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Media\Factory;
|
||||
|
||||
use Alchemy\Phrasea\Media\FloatTechnicalData;
|
||||
use Alchemy\Phrasea\Media\IntegerTechnicalData;
|
||||
use Alchemy\Phrasea\Media\StringTechnicalData;
|
||||
use Alchemy\Phrasea\Media\TechnicalData;
|
||||
|
||||
class TechnicalDataFactory
|
||||
{
|
||||
/**
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
* @return TechnicalData
|
||||
*/
|
||||
public function createFromNameAndValue($name, $value)
|
||||
{
|
||||
if (ctype_digit($value)) {
|
||||
return new IntegerTechnicalData($name, $value);
|
||||
} elseif (preg_match('/[0-9]?\.[0-9]+/', $value)) {
|
||||
return new FloatTechnicalData($name, $value);
|
||||
}
|
||||
|
||||
return new StringTechnicalData($name, $value);
|
||||
}
|
||||
}
|
116
lib/Alchemy/Phrasea/Media/MediaSubDefinitionUrlGenerator.php
Normal file
116
lib/Alchemy/Phrasea/Media/MediaSubDefinitionUrlGenerator.php
Normal file
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Media;
|
||||
|
||||
use Alchemy\Phrasea\Model\Entities\User;
|
||||
use Alchemy\Phrasea\Model\Provider\SecretProvider;
|
||||
use Assert\Assertion;
|
||||
use Firebase\JWT\JWT;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
|
||||
class MediaSubDefinitionUrlGenerator
|
||||
{
|
||||
/**
|
||||
* @var UrlGeneratorInterface
|
||||
*/
|
||||
private $urlGenerator;
|
||||
/**
|
||||
* @var SecretProvider
|
||||
*/
|
||||
private $secretProvider;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $defaultTTL;
|
||||
|
||||
public function __construct(UrlGeneratorInterface $urlGenerator, SecretProvider $secretProvider, $defaultTTL = 0)
|
||||
{
|
||||
Assertion::integer($defaultTTL);
|
||||
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
$this->secretProvider = $secretProvider;
|
||||
$this->defaultTTL = (int)$defaultTTL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getDefaultTTL()
|
||||
{
|
||||
return $this->defaultTTL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $issuer
|
||||
* @param \media_subdef $subdef
|
||||
* @param int $url_ttl
|
||||
* @return string
|
||||
*/
|
||||
public function generate(User $issuer, \media_subdef $subdef, $url_ttl = null)
|
||||
{
|
||||
$url_ttl = $url_ttl ?: $this->defaultTTL;
|
||||
|
||||
$payload = [
|
||||
'iat' => time(),
|
||||
'iss' => $issuer->getId(),
|
||||
'sdef' => [$subdef->get_sbas_id(), $subdef->get_record_id(), $subdef->get_name()],
|
||||
];
|
||||
|
||||
if ($url_ttl > 0) {
|
||||
$payload['exp'] = $payload['iat'] + $url_ttl;
|
||||
}
|
||||
|
||||
$secret = $this->secretProvider->getSecretForUser($issuer);
|
||||
|
||||
return $this->urlGenerator->generate('media_accessor', [
|
||||
'token' => JWT::encode($payload, $secret->getToken(), 'HS256', $secret->getId()),
|
||||
], UrlGeneratorInterface::ABSOLUTE_URL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $issuer
|
||||
* @param \media_subdef[] $subdefs
|
||||
* @param int $url_ttl
|
||||
* @return string[]
|
||||
*/
|
||||
public function generateMany(User $issuer, $subdefs, $url_ttl = null)
|
||||
{
|
||||
Assertion::allIsInstanceOf($subdefs, \media_subdef::class);
|
||||
$url_ttl = $url_ttl ?: $this->defaultTTL;
|
||||
|
||||
$payloads = [];
|
||||
|
||||
$payload = [
|
||||
'iat' => time(),
|
||||
'iss' => $issuer->getId(),
|
||||
'sdef' => null,
|
||||
];
|
||||
|
||||
if ($url_ttl > 0) {
|
||||
$payload['exp'] = $payload['iat'] + $url_ttl;
|
||||
}
|
||||
|
||||
foreach ($subdefs as $index => $subdef) {
|
||||
$payload['sdef'] = [$subdef->get_sbas_id(), $subdef->get_record_id(), $subdef->get_name()];
|
||||
|
||||
$payloads[$index] = $payload;
|
||||
}
|
||||
|
||||
$secret = $this->secretProvider->getSecretForUser($issuer);
|
||||
|
||||
return array_map(function ($payload) use ($secret) {
|
||||
return $this->urlGenerator->generate('media_accessor', [
|
||||
'token' => JWT::encode($payload, $secret->getToken(), 'HS256', $secret->getId()),
|
||||
], UrlGeneratorInterface::ABSOLUTE_URL);
|
||||
}, $payloads);
|
||||
}
|
||||
}
|
37
lib/Alchemy/Phrasea/Media/RecordTechnicalDataSet.php
Normal file
37
lib/Alchemy/Phrasea/Media/RecordTechnicalDataSet.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Media;
|
||||
|
||||
class RecordTechnicalDataSet extends ArrayTechnicalDataSet
|
||||
{
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $recordId;
|
||||
|
||||
/**
|
||||
* @param int $recordId
|
||||
* @param TechnicalData[] $technicalData
|
||||
*/
|
||||
public function __construct($recordId, $technicalData = [])
|
||||
{
|
||||
$this->recordId = (int)$recordId;
|
||||
parent::__construct($technicalData);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getRecordId()
|
||||
{
|
||||
return $this->recordId;
|
||||
}
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Media;
|
||||
|
||||
interface RecordTechnicalDataSetRepository
|
||||
{
|
||||
/**
|
||||
* @param int[] $recordIds
|
||||
* @return RecordTechnicalDataSet[]
|
||||
*/
|
||||
public function findByRecordIds(array $recordIds);
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Media;
|
||||
|
||||
interface RecordTechnicalDataSetRepositoryFactory
|
||||
{
|
||||
/**
|
||||
* @param int $databoxId
|
||||
* @return RecordTechnicalDataSetRepository
|
||||
*/
|
||||
public function createRepositoryForDatabox($databoxId);
|
||||
}
|
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Media;
|
||||
|
||||
class RecordTechnicalDataSetRepositoryProvider
|
||||
{
|
||||
/**
|
||||
* @var RecordTechnicalDataSetRepository[]
|
||||
*/
|
||||
private $repositories = [];
|
||||
|
||||
/**
|
||||
* @var RecordTechnicalDataSetRepositoryFactory
|
||||
*/
|
||||
private $factory;
|
||||
|
||||
public function __construct(RecordTechnicalDataSetRepositoryFactory $factory)
|
||||
{
|
||||
$this->factory = $factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $databoxId
|
||||
* @return RecordTechnicalDataSetRepository
|
||||
*/
|
||||
public function getRepositoryFor($databoxId)
|
||||
{
|
||||
if (!isset($this->repositories[$databoxId])) {
|
||||
$this->repositories[$databoxId] = $this->factory->createRepositoryForDatabox($databoxId);
|
||||
}
|
||||
|
||||
return $this->repositories[$databoxId];
|
||||
}
|
||||
}
|
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Media\Repository;
|
||||
|
||||
use Alchemy\Phrasea\Media\Factory\TechnicalDataFactory;
|
||||
use Alchemy\Phrasea\Media\RecordTechnicalDataSet;
|
||||
use Alchemy\Phrasea\Media\RecordTechnicalDataSetRepository;
|
||||
use Doctrine\DBAL\Connection;
|
||||
|
||||
class DbalRecordTechnicalDataSetRepository implements RecordTechnicalDataSetRepository
|
||||
{
|
||||
/**
|
||||
* @var Connection
|
||||
*/
|
||||
private $connection;
|
||||
|
||||
/**
|
||||
* @var TechnicalDataFactory
|
||||
*/
|
||||
private $dataFactory;
|
||||
|
||||
public function __construct(Connection $connection, TechnicalDataFactory $dataFactory)
|
||||
{
|
||||
$this->connection = $connection;
|
||||
$this->dataFactory = $dataFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int[] $recordIds
|
||||
* @return RecordTechnicalDataSet[]
|
||||
*/
|
||||
public function findByRecordIds(array $recordIds)
|
||||
{
|
||||
if (empty($recordIds)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$data = $this->connection->fetchAll(
|
||||
'SELECT record_id, name, value FROM technical_datas WHERE record_id IN (:recordIds)',
|
||||
['recordIds' => $recordIds],
|
||||
['recordIds' => Connection::PARAM_INT_ARRAY]
|
||||
);
|
||||
|
||||
return $this->mapSetsFromDatabaseResult($recordIds, $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $recordIds
|
||||
* @param array $data
|
||||
* @return RecordTechnicalDataSet[]
|
||||
*/
|
||||
private function mapSetsFromDatabaseResult(array $recordIds, array $data)
|
||||
{
|
||||
$groups = [];
|
||||
|
||||
foreach ($recordIds as $recordId) {
|
||||
$groups[$recordId] = new RecordTechnicalDataSet($recordId);
|
||||
}
|
||||
|
||||
foreach ($data as $item) {
|
||||
$group =& $groups[$item['record_id']];
|
||||
$group[] = $this->dataFactory->createFromNameAndValue($item['name'], $item['value']);
|
||||
}
|
||||
|
||||
return array_values($groups);
|
||||
}
|
||||
}
|
52
lib/Alchemy/Phrasea/Media/TechnicalDataService.php
Normal file
52
lib/Alchemy/Phrasea/Media/TechnicalDataService.php
Normal file
@@ -0,0 +1,52 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Media;
|
||||
|
||||
use Alchemy\Phrasea\Record\RecordReference;
|
||||
use Alchemy\Phrasea\Record\RecordReferenceCollection;
|
||||
|
||||
class TechnicalDataService
|
||||
{
|
||||
/**
|
||||
* @var RecordTechnicalDataSetRepositoryProvider
|
||||
*/
|
||||
private $provider;
|
||||
|
||||
public function __construct(RecordTechnicalDataSetRepositoryProvider $provider)
|
||||
{
|
||||
$this->provider = $provider;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param RecordReference[] $references
|
||||
* @return RecordTechnicalDataSet[]
|
||||
*/
|
||||
public function fetchRecordsTechnicalData($references)
|
||||
{
|
||||
if (!$references instanceof RecordReferenceCollection) {
|
||||
$references = new RecordReferenceCollection($references);
|
||||
}
|
||||
|
||||
$sets = [];
|
||||
|
||||
foreach ($references->groupPerDataboxId() as $databoxId => $indexes) {
|
||||
foreach ($this->provider->getRepositoryFor($databoxId)->findByRecordIds(array_keys($indexes)) as $set) {
|
||||
$index = $indexes[$set->getRecordId()];
|
||||
|
||||
$sets[$index] = $set;
|
||||
}
|
||||
}
|
||||
|
||||
ksort($sets);
|
||||
|
||||
return $sets;
|
||||
}
|
||||
}
|
34
lib/Alchemy/Phrasea/Media/TechnicalDataServiceProvider.php
Normal file
34
lib/Alchemy/Phrasea/Media/TechnicalDataServiceProvider.php
Normal file
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Media;
|
||||
|
||||
use Alchemy\Phrasea\Databox\DataboxConnectionProvider;
|
||||
use Alchemy\Phrasea\Media\Factory\DbalRepositoryFactory;
|
||||
use Silex\Application;
|
||||
use Silex\ServiceProviderInterface;
|
||||
|
||||
class TechnicalDataServiceProvider implements ServiceProviderInterface
|
||||
{
|
||||
public function register(Application $app)
|
||||
{
|
||||
$app['service.technical_data'] = $app->share(function (Application $app) {
|
||||
$connectionProvider = new DataboxConnectionProvider($app['phraseanet.appbox']);
|
||||
$repositoryFactory = new DbalRepositoryFactory($connectionProvider);
|
||||
|
||||
return new TechnicalDataService(new RecordTechnicalDataSetRepositoryProvider($repositoryFactory));
|
||||
});
|
||||
}
|
||||
|
||||
public function boot(Application $app)
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
}
|
@@ -460,8 +460,8 @@ class Basket
|
||||
foreach ($this->getElements() as $basket_element) {
|
||||
$bask_record = $basket_element->getRecord($app);
|
||||
|
||||
if ($bask_record->get_record_id() == $record->get_record_id()
|
||||
&& $bask_record->get_sbas_id() == $record->get_sbas_id()) {
|
||||
if ($bask_record->getRecordId() == $record->getRecordId()
|
||||
&& $bask_record->getDataboxId() == $record->getDataboxId()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@@ -138,8 +138,8 @@ class BasketElement
|
||||
|
||||
public function setRecord(\record_adapter $record)
|
||||
{
|
||||
$this->setRecordId($record->get_record_id());
|
||||
$this->setSbasId($record->get_sbas_id());
|
||||
$this->setRecordId($record->getRecordId());
|
||||
$this->setSbasId($record->getDataboxId());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -259,7 +259,7 @@ class FeedEntry
|
||||
/**
|
||||
* Get items
|
||||
*
|
||||
* @return \Doctrine\Common\Collections\Collection
|
||||
* @return FeedItem[]|\Doctrine\Common\Collections\Collection
|
||||
*/
|
||||
public function getItems()
|
||||
{
|
||||
|
@@ -80,7 +80,7 @@ class OrderElement
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* @return User|null
|
||||
*/
|
||||
public function getOrderMaster()
|
||||
{
|
||||
|
@@ -116,8 +116,8 @@ class StoryWZ
|
||||
|
||||
public function setRecord(\record_adapter $record)
|
||||
{
|
||||
$this->setRecordId($record->get_record_id());
|
||||
$this->setSbasId($record->get_sbas_id());
|
||||
$this->setRecordId($record->getRecordId());
|
||||
$this->setSbasId($record->getDataboxId());
|
||||
}
|
||||
/**
|
||||
* @param User $user
|
||||
|
@@ -8,6 +8,7 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Alchemy\Phrasea\Model\Manipulator;
|
||||
|
||||
use Alchemy\Phrasea\Application;
|
||||
use Alchemy\Phrasea\Border;
|
||||
use Alchemy\Phrasea\Border\Attribute\AttributeInterface;
|
||||
@@ -17,6 +18,8 @@ use Doctrine\ORM\EntityRepository;
|
||||
use PHPExiftool\Driver\Metadata\Metadata;
|
||||
use Symfony\Component\Filesystem\Exception\IOException;
|
||||
use Symfony\Component\Filesystem\Filesystem;
|
||||
|
||||
|
||||
class LazaretManipulator
|
||||
{
|
||||
/** @var Application */
|
||||
@@ -31,6 +34,7 @@ class LazaretManipulator
|
||||
* @var EntityManager
|
||||
*/
|
||||
private $entityManager;
|
||||
|
||||
public function __construct(Application $app, EntityRepository $repository, Filesystem $fileSystem, EntityManager $entityManager)
|
||||
{
|
||||
$this->app = $app;
|
||||
@@ -38,23 +42,29 @@ class LazaretManipulator
|
||||
$this->fileSystem = $fileSystem;
|
||||
$this->entityManager = $entityManager;
|
||||
}
|
||||
|
||||
public function deny($lazaret_id)
|
||||
{
|
||||
$ret = ['success' => false, 'message' => '', 'result' => []];
|
||||
|
||||
/** @var LazaretFile $lazaretFile */
|
||||
$lazaretFile = $this->repository->find($lazaret_id);
|
||||
if (null === $lazaretFile) {
|
||||
$ret['message'] = $this->app->trans('File is not present in quarantine anymore, please refresh');
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
try {
|
||||
$this->denyLazaretFile($lazaretFile);
|
||||
$ret['success'] = true;
|
||||
} catch (\Exception $e) {
|
||||
// No-op
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty lazaret
|
||||
*
|
||||
@@ -74,14 +84,17 @@ class LazaretManipulator
|
||||
'max' => '',
|
||||
)
|
||||
);
|
||||
|
||||
if( $maxTodo <= 0) {
|
||||
$maxTodo = -1; // all
|
||||
}
|
||||
$ret['result']['max'] = $maxTodo;
|
||||
|
||||
$ret['result']['tobedone'] = (int) $this->repository->createQueryBuilder('id')
|
||||
->select('COUNT(id)')
|
||||
->getQuery()
|
||||
->getSingleScalarResult();
|
||||
|
||||
if($maxTodo == -1) {
|
||||
// all
|
||||
$lazaretFiles = $this->repository->findAll();
|
||||
@@ -89,7 +102,9 @@ class LazaretManipulator
|
||||
// limit maxTodo
|
||||
$lazaretFiles = $this->repository->findBy(array(), null, $maxTodo);
|
||||
}
|
||||
|
||||
$this->entityManager->beginTransaction();
|
||||
|
||||
try {
|
||||
foreach ($lazaretFiles as $lazaretFile) {
|
||||
$this->denyLazaretFile($lazaretFile);
|
||||
@@ -102,20 +117,28 @@ class LazaretManipulator
|
||||
$ret['message'] = $this->app->trans('An error occured');
|
||||
}
|
||||
$ret['result']['todo'] = $ret['result']['tobedone'] - $ret['result']['done'];
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
|
||||
public function add($file_id, $keepAttributes=true, Array $attributesToKeep=[])
|
||||
{
|
||||
$ret = ['success' => false, 'message' => '', 'result' => []];
|
||||
|
||||
/* @var LazaretFile $lazaretFile */
|
||||
$lazaretFile = $this->repository->find($file_id);
|
||||
|
||||
if (null === $lazaretFile) {
|
||||
$ret['message'] = $this->app->trans('File is not present in quarantine anymore, please refresh');
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
$path = $this->app['tmp.lazaret.path'];
|
||||
$lazaretFileName = $path .'/'.$lazaretFile->getFilename();
|
||||
$lazaretThumbFileName = $path .'/'.$lazaretFile->getThumbFilename();
|
||||
|
||||
try {
|
||||
$borderFile = Border\File::buildFromPathfile(
|
||||
$lazaretFileName,
|
||||
@@ -123,12 +146,14 @@ class LazaretManipulator
|
||||
$this->app,
|
||||
$lazaretFile->getOriginalName()
|
||||
);
|
||||
|
||||
//Post record creation
|
||||
/** @var \record_adapter $record */
|
||||
$record = null;
|
||||
$callBack = function ($element) use (&$record) {
|
||||
$record = $element;
|
||||
};
|
||||
|
||||
//Force creation record
|
||||
$this->getBorderManager()->process(
|
||||
$lazaretFile->getSession(),
|
||||
@@ -136,10 +161,13 @@ class LazaretManipulator
|
||||
$callBack,
|
||||
Border\Manager::FORCE_RECORD
|
||||
);
|
||||
|
||||
if ($keepAttributes) {
|
||||
//add attribute
|
||||
|
||||
$metaFields = new Border\MetaFieldsBag();
|
||||
$metadataBag = new Border\MetadataBag();
|
||||
|
||||
foreach ($lazaretFile->getAttributes() as $attr) {
|
||||
//Check which ones to keep
|
||||
if (!!count($attributesToKeep)) {
|
||||
@@ -147,11 +175,13 @@ class LazaretManipulator
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$attribute = Border\Attribute\Factory::getFileAttribute($this->app, $attr->getName(), $attr->getValue());
|
||||
} catch (\InvalidArgumentException $e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch ($attribute->getName()) {
|
||||
case AttributeInterface::NAME_METADATA:
|
||||
/** @var Metadata $value */
|
||||
@@ -164,7 +194,7 @@ class LazaretManipulator
|
||||
$value->appendChild($record);
|
||||
break;
|
||||
case AttributeInterface::NAME_STATUS:
|
||||
$record->set_binary_status($attribute->getValue());
|
||||
$record->setStatus($attribute->getValue());
|
||||
break;
|
||||
case AttributeInterface::NAME_METAFIELD:
|
||||
/** @var Border\Attribute\MetaField $attribute */
|
||||
@@ -172,25 +202,32 @@ class LazaretManipulator
|
||||
break;
|
||||
}
|
||||
}
|
||||
$data = $metadataBag->toMetadataArray($record->get_databox()->get_meta_structure());
|
||||
|
||||
$data = $metadataBag->toMetadataArray($record->getDatabox()->get_meta_structure());
|
||||
$record->set_metadatas($data);
|
||||
$fields = $metaFields->toMetadataArray($record->get_databox()->get_meta_structure());
|
||||
|
||||
$fields = $metaFields->toMetadataArray($record->getDatabox()->get_meta_structure());
|
||||
$record->set_metadatas($fields);
|
||||
}
|
||||
|
||||
//Delete lazaret file
|
||||
$this->entityManager->remove($lazaretFile);
|
||||
$this->entityManager->flush();
|
||||
|
||||
$ret['success'] = true;
|
||||
} catch (\Exception $e) {
|
||||
$ret['message'] = $this->app->trans('An error occured');
|
||||
}
|
||||
|
||||
try {
|
||||
$this->fileSystem->remove([$lazaretFileName, $lazaretThumbFileName]);
|
||||
} catch (IOException $e) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Border\Manager
|
||||
*/
|
||||
@@ -198,19 +235,24 @@ class LazaretManipulator
|
||||
{
|
||||
return $this->app['border-manager'];
|
||||
}
|
||||
|
||||
protected function denyLazaretFile(LazaretFile $lazaretFile)
|
||||
{
|
||||
$path = $this->app['tmp.lazaret.path'];
|
||||
$lazaretFileName = $path .'/'.$lazaretFile->getFilename();
|
||||
$lazaretThumbFileName = $path .'/'.$lazaretFile->getThumbFilename();
|
||||
|
||||
$this->entityManager->remove($lazaretFile);
|
||||
$this->entityManager->flush();
|
||||
|
||||
try {
|
||||
$this->fileSystem->remove([$lazaretFileName, $lazaretThumbFileName]);
|
||||
} catch (IOException $e) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@@ -196,7 +196,7 @@ class BasketRepository extends EntityRepository
|
||||
AND b.user = :usr_id';
|
||||
|
||||
$params = [
|
||||
'record_id' => $record->get_record_id(),
|
||||
'record_id' => $record->getRecordId(),
|
||||
'usr_id' => $user->getId()
|
||||
];
|
||||
|
||||
|
@@ -99,8 +99,8 @@ class StoryWZRepository extends EntityRepository
|
||||
{
|
||||
$story = $this->findOneBy([
|
||||
'user' => $user->getId(),
|
||||
'sbas_id' => $Story->get_sbas_id(),
|
||||
'record_id' => $Story->get_record_id(),
|
||||
'sbas_id' => $Story->getDataboxId(),
|
||||
'record_id' => $Story->getRecordId(),
|
||||
]);
|
||||
|
||||
if ($story) {
|
||||
@@ -129,8 +129,8 @@ class StoryWZRepository extends EntityRepository
|
||||
|
||||
$query = $this->_em->createQuery($dql);
|
||||
$query->setParameters([
|
||||
'sbas_id' => $Story->get_sbas_id(),
|
||||
'record_id' => $Story->get_record_id(),
|
||||
'sbas_id' => $Story->getDataboxId(),
|
||||
'record_id' => $Story->getRecordId(),
|
||||
]);
|
||||
|
||||
/** @var StoryWZ[] $stories */
|
||||
|
@@ -1,9 +1,8 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2014 Alchemy
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
@@ -11,6 +10,7 @@
|
||||
|
||||
namespace Alchemy\Phrasea\Model\Serializer;
|
||||
|
||||
use Alchemy\Phrasea\Media\TechnicalDataService;
|
||||
use Symfony\Component\Yaml\Dumper as YamlDumper;
|
||||
|
||||
class CaptionSerializer extends AbstractSerializer
|
||||
@@ -19,21 +19,46 @@ class CaptionSerializer extends AbstractSerializer
|
||||
const SERIALIZE_YAML = 'yaml';
|
||||
const SERIALIZE_JSON = 'json';
|
||||
|
||||
/**
|
||||
* @var TechnicalDataService|callable
|
||||
*/
|
||||
private $technicalDataService;
|
||||
|
||||
/**
|
||||
* @param callable|TechnicalDataService $technicalDataService
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function __construct($technicalDataService)
|
||||
{
|
||||
if (!$technicalDataService instanceof TechnicalDataService && !is_callable($technicalDataService)) {
|
||||
throw new \InvalidArgumentException(sprintf(
|
||||
'Expects a callable or %s, got %s',
|
||||
TechnicalDataService::class,
|
||||
is_object($technicalDataService) ? get_class($technicalDataService) : gettype($technicalDataService)
|
||||
));
|
||||
}
|
||||
|
||||
$this->technicalDataService = $technicalDataService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \caption_record $caption
|
||||
* @param string $format
|
||||
* @param bool $includeBusinessFields
|
||||
* @return string
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function serialize(\caption_record $caption, $format, $includeBusinessFields = false)
|
||||
{
|
||||
switch ($format) {
|
||||
case self::SERIALIZE_XML:
|
||||
return $this->serializeXML($caption, (Boolean) $includeBusinessFields);
|
||||
break;
|
||||
return $this->serializeXML($caption, (bool) $includeBusinessFields);
|
||||
case self::SERIALIZE_YAML:
|
||||
return $this->serializeYAML($caption, (Boolean) $includeBusinessFields);
|
||||
break;
|
||||
return $this->serializeYAML($caption, (bool) $includeBusinessFields);
|
||||
case self::SERIALIZE_JSON:
|
||||
return $this->serializeJSON($caption, (Boolean) $includeBusinessFields);
|
||||
break;
|
||||
return $this->serializeJSON($caption, (bool) $includeBusinessFields);
|
||||
default:
|
||||
throw new \Exception(sprintf('Unknown format %s', $format));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +72,11 @@ class CaptionSerializer extends AbstractSerializer
|
||||
return \p4string::jsonencode($this->toArray($caption, $includeBusinessFields));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \caption_record $caption
|
||||
* @param bool $includeBusinessFields
|
||||
* @return array
|
||||
*/
|
||||
public function toArray(\caption_record $caption, $includeBusinessFields)
|
||||
{
|
||||
$buffer = [];
|
||||
@@ -77,7 +107,7 @@ class CaptionSerializer extends AbstractSerializer
|
||||
$dom_doc->standalone = true;
|
||||
|
||||
$record = $dom_doc->createElement('record');
|
||||
$record->setAttribute('record_id', $caption->get_record()->get_record_id());
|
||||
$record->setAttribute('record_id', $caption->getRecordReference()->getRecordId());
|
||||
$dom_doc->appendChild($record);
|
||||
$description = $dom_doc->createElement('description');
|
||||
$record->appendChild($description);
|
||||
@@ -96,7 +126,8 @@ class CaptionSerializer extends AbstractSerializer
|
||||
|
||||
$doc = $dom_doc->createElement('doc');
|
||||
|
||||
$tc_datas = $caption->get_record()->get_technical_infos()->getValues();
|
||||
$technicalData = $this->getTechnicalDataService()->fetchRecordsTechnicalData([$caption->getRecordReference()]);
|
||||
$tc_datas = $technicalData[0]->getValues();
|
||||
|
||||
foreach ($tc_datas as $key => $data) {
|
||||
$doc->setAttribute($key, $data);
|
||||
@@ -106,4 +137,27 @@ class CaptionSerializer extends AbstractSerializer
|
||||
|
||||
return $dom_doc->saveXML();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return TechnicalDataService
|
||||
* @throws \UnexpectedValueException
|
||||
*/
|
||||
private function getTechnicalDataService()
|
||||
{
|
||||
if (!$this->technicalDataService instanceof TechnicalDataService) {
|
||||
$instance = call_user_func($this->technicalDataService);
|
||||
|
||||
if (!$instance instanceof TechnicalDataService) {
|
||||
throw new \UnexpectedValueException(sprintf(
|
||||
'Expected a %s instance, got %s.',
|
||||
TechnicalDataService::class,
|
||||
is_object($instance) ? get_class($instance) : gettype($instance)
|
||||
));
|
||||
}
|
||||
|
||||
$this->technicalDataService = $instance;
|
||||
}
|
||||
|
||||
return $this->technicalDataService;
|
||||
}
|
||||
}
|
||||
|
@@ -50,7 +50,7 @@ class ESRecordSerializer extends AbstractSerializer
|
||||
}
|
||||
|
||||
$i = 0;
|
||||
foreach (preg_split('//', strrev($record->get_status()), -1, PREG_SPLIT_NO_EMPTY) as $val) {
|
||||
foreach (preg_split('//', strrev($record->getStatus()), -1, PREG_SPLIT_NO_EMPTY) as $val) {
|
||||
$status['status-'.$i] = (int) $val;
|
||||
$i++;
|
||||
}
|
||||
|
260
lib/Alchemy/Phrasea/Order/Controller/ApiOrderController.php
Normal file
260
lib/Alchemy/Phrasea/Order/Controller/ApiOrderController.php
Normal file
@@ -0,0 +1,260 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Order\Controller;
|
||||
|
||||
use Alchemy\Phrasea\Application\Helper\JsonBodyAware;
|
||||
use Alchemy\Phrasea\Controller\Api\Result;
|
||||
use Alchemy\Phrasea\Controller\RecordsRequest;
|
||||
use Alchemy\Phrasea\Core\Event\OrderEvent;
|
||||
use Alchemy\Phrasea\Core\PhraseaEvents;
|
||||
use Alchemy\Phrasea\Model\Entities\BasketElement;
|
||||
use Alchemy\Phrasea\Model\Entities\Order;
|
||||
use Alchemy\Phrasea\Model\Entities\OrderElement;
|
||||
use Alchemy\Phrasea\Model\RecordReferenceInterface;
|
||||
use Alchemy\Phrasea\Order\OrderElementTransformer;
|
||||
use Alchemy\Phrasea\Order\OrderElementView;
|
||||
use Alchemy\Phrasea\Order\OrderFiller;
|
||||
use Alchemy\Phrasea\Order\OrderTransformer;
|
||||
use Alchemy\Phrasea\Order\OrderView;
|
||||
use Alchemy\Phrasea\Order\OrderViewBuilder;
|
||||
use Alchemy\Phrasea\Record\RecordReference;
|
||||
use Alchemy\Phrasea\Record\RecordReferenceCollection;
|
||||
use Assert\Assertion;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Pagination\PagerfantaPaginatorAdapter;
|
||||
use League\Fractal\Resource\Collection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Resource\ResourceInterface;
|
||||
use Pagerfanta\Adapter\DoctrineORMAdapter;
|
||||
use Pagerfanta\Pagerfanta;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
||||
|
||||
class ApiOrderController extends BaseOrderController
|
||||
{
|
||||
use JsonBodyAware;
|
||||
|
||||
public function createAction(Request $request)
|
||||
{
|
||||
$data = $this->decodeJsonBody($request, 'orders.json#/definitions/order_request');
|
||||
|
||||
$availableRecords = $this->toRequestedRecords($data->data->records);
|
||||
$records = $this->filterOrderableRecords($availableRecords);
|
||||
|
||||
$recordRequest = new RecordsRequest($records, new ArrayCollection($availableRecords), null, RecordsRequest::FLATTEN_YES);
|
||||
|
||||
$filler = new OrderFiller($this->app['repo.collection-references'], $this->app['orm.em']);
|
||||
|
||||
$filler->assertAllRecordsHaveOrderMaster($recordRequest);
|
||||
|
||||
$order = new Order();
|
||||
$order->setUser($this->getAuthenticatedUser());
|
||||
$order->setDeadline(new \DateTime($data->data->deadline, new \DateTimeZone('UTC')));
|
||||
$order->setOrderUsage($data->data->usage);
|
||||
|
||||
$filler->fillOrder($order, $recordRequest);
|
||||
|
||||
$this->dispatch(PhraseaEvents::ORDER_CREATE, new OrderEvent($order));
|
||||
|
||||
$resource = new Item($order, $this->getOrderTransformer());
|
||||
|
||||
return $this->returnResourceResponse($request, ['elements'], $resource);
|
||||
}
|
||||
|
||||
public function indexAction(Request $request)
|
||||
{
|
||||
$page = max((int) $request->get('page', '1'), 1);
|
||||
$perPage = min(max((int)$request->get('per_page', '10'), 1), 100);
|
||||
$fractal = $this->buildFractalManager($request->get('includes', []));
|
||||
|
||||
$routeGenerator = function ($page) use ($perPage) {
|
||||
return $this->app->path('api_v2_orders_index', [
|
||||
'page' => $page,
|
||||
'per_page' => $perPage,
|
||||
]);
|
||||
};
|
||||
|
||||
$builder = $this->app['repo.orders']->createQueryBuilder('o');
|
||||
$builder
|
||||
->where($builder->expr()->eq('o.user', $this->getAuthenticatedUser()->getId()))
|
||||
;
|
||||
|
||||
if (in_array('elements', $fractal->getRequestedIncludes(), false)) {
|
||||
$builder
|
||||
->addSelect('e')
|
||||
->leftJoin('o.elements', 'e')
|
||||
;
|
||||
}
|
||||
|
||||
$collection = $this->getViewBuilder()->buildViews(
|
||||
$builder->getQuery()->getResult(),
|
||||
$fractal->getRequestedIncludes()
|
||||
);
|
||||
|
||||
$resource = new Collection($collection, $this->getOrderTransformer());
|
||||
|
||||
$pager = new Pagerfanta(new DoctrineORMAdapter($builder, false));
|
||||
$pager->setCurrentPage($page);
|
||||
$pager->setMaxPerPage($perPage);
|
||||
|
||||
$resource->setPaginator(new PagerfantaPaginatorAdapter($pager, $routeGenerator));
|
||||
|
||||
return $this->returnResourceResponse($request, $fractal, $resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param int $orderId
|
||||
* @return Response
|
||||
*/
|
||||
public function showAction(Request $request, $orderId)
|
||||
{
|
||||
$order = $this->findOr404($orderId);
|
||||
|
||||
$fractal = $this->buildFractalManager($request->get('includes', []));
|
||||
|
||||
if ($order->getUser()->getId() !== $this->getAuthenticatedUser()->getId()) {
|
||||
throw new AccessDeniedHttpException(sprintf('Cannot access order "%d"', $order->getId()));
|
||||
}
|
||||
|
||||
$model = $this->getViewBuilder()->buildView($order, $fractal->getRequestedIncludes());
|
||||
$resource = new Item($model, $this->getOrderTransformer());
|
||||
|
||||
return $this->returnResourceResponse($request, $fractal, $resource);
|
||||
}
|
||||
|
||||
public function acceptElementsAction(Request $request, $orderId)
|
||||
{
|
||||
$elementIds = $this->fetchElementIdsFromRequest($request);
|
||||
|
||||
$elements = $this->doAcceptElements($orderId, $elementIds, $this->getAuthenticatedUser());
|
||||
|
||||
$resource = new Collection($elements, function (BasketElement $element) {
|
||||
return [
|
||||
'id' => $element->getId(),
|
||||
'created' => $element->getCreated(),
|
||||
'databox_id' => $element->getSbasId(),
|
||||
'record_id' => $element->getRecordId(),
|
||||
'index' => $element->getOrd(),
|
||||
];
|
||||
});
|
||||
|
||||
return $this->returnResourceResponse($request, [], $resource);
|
||||
}
|
||||
|
||||
public function denyElementsAction(Request $request, $orderId)
|
||||
{
|
||||
$elementIds = $this->fetchElementIdsFromRequest($request);
|
||||
|
||||
$this->doDenyElements($orderId, $elementIds, $this->getAuthenticatedUser());
|
||||
|
||||
return Result::create($request, [])->createResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $records
|
||||
* @return \record_adapter[]
|
||||
*/
|
||||
private function toRequestedRecords(array $records)
|
||||
{
|
||||
$requestedRecords = [];
|
||||
|
||||
foreach ($records as $item) {
|
||||
$requestedRecords[] = [
|
||||
'databox_id' => $item->databox_id,
|
||||
'record_id' => $item->record_id,
|
||||
];
|
||||
}
|
||||
|
||||
return RecordReferenceCollection::fromArrayOfArray($requestedRecords)->toRecords($this->getApplicationBox());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \record_adapter[] $records
|
||||
* @return \record_adapter[]
|
||||
*/
|
||||
private function filterOrderableRecords(array $records)
|
||||
{
|
||||
$acl = $this->getAclForUser();
|
||||
|
||||
$filtered = [];
|
||||
|
||||
foreach ($records as $index => $record) {
|
||||
if ($acl->has_right_on_base($record->getBaseId(), 'cancmd')) {
|
||||
$filtered[$index] = $record;
|
||||
}
|
||||
}
|
||||
|
||||
return $filtered;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return OrderTransformer
|
||||
*/
|
||||
private function getOrderTransformer()
|
||||
{
|
||||
return new OrderTransformer(new OrderElementTransformer($this->app['media_accessor.subdef_url_generator']));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|array $includes
|
||||
* @return Manager
|
||||
*/
|
||||
private function buildFractalManager($includes)
|
||||
{
|
||||
$fractal = new Manager();
|
||||
|
||||
$fractal->parseIncludes($includes ?: []);
|
||||
|
||||
return $fractal;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param string|array|Manager $includes
|
||||
* @param ResourceInterface $resource
|
||||
* @return Response
|
||||
*/
|
||||
private function returnResourceResponse(Request $request, $includes, ResourceInterface $resource)
|
||||
{
|
||||
$fractal = $includes instanceof Manager ? $includes : $this->buildFractalManager($includes);
|
||||
|
||||
return Result::create($request, $fractal->createData($resource)->toArray())->createResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @return array
|
||||
*/
|
||||
private function fetchElementIdsFromRequest(Request $request)
|
||||
{
|
||||
$data = $this->decodeJsonBody($request, 'orders.json#/definitions/order_element_collection');
|
||||
|
||||
$elementIds = [];
|
||||
|
||||
foreach ($data as $elementId) {
|
||||
$elementIds[] = $elementId->id;
|
||||
}
|
||||
|
||||
return $elementIds;
|
||||
}
|
||||
|
||||
private function getViewBuilder()
|
||||
{
|
||||
return new OrderViewBuilder(
|
||||
$this->app,
|
||||
$this->getApplicationBox(),
|
||||
$this->app['service.media_subdef']
|
||||
);
|
||||
}
|
||||
}
|
@@ -189,10 +189,12 @@ class BaseOrderController extends Controller
|
||||
|
||||
$references = new RecordReferenceCollection();
|
||||
|
||||
foreach ($elements as $element) {
|
||||
$reference = RecordReference::createFromDataboxIdAndRecordId($element->getSbasId(), $element->getRecordId());
|
||||
$basket->getElements()->forAll(function (BasketElement $element) use ($references) {
|
||||
$references->addRecordReference($element->getSbasId(), $element->getRecordId());
|
||||
});
|
||||
|
||||
$references->addRecordReference($reference);
|
||||
foreach ($elements as $element) {
|
||||
$references->addRecordReference($element->getSbasId(), $element->getRecordId());
|
||||
}
|
||||
|
||||
$groups = $references->groupPerDataboxId();
|
||||
|
108
lib/Alchemy/Phrasea/Order/OrderElementTransformer.php
Normal file
108
lib/Alchemy/Phrasea/Order/OrderElementTransformer.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Order;
|
||||
|
||||
use Alchemy\Phrasea\Media\MediaSubDefinitionUrlGenerator;
|
||||
use League\Fractal\ParamBag;
|
||||
use League\Fractal\TransformerAbstract;
|
||||
|
||||
class OrderElementTransformer extends TransformerAbstract
|
||||
{
|
||||
protected $availableIncludes = ['resource_links'];
|
||||
|
||||
private $validParams = ['ttl'];
|
||||
|
||||
/**
|
||||
* @var MediaSubDefinitionUrlGenerator
|
||||
*/
|
||||
private $urlGenerator;
|
||||
|
||||
public function __construct(MediaSubDefinitionUrlGenerator $urlGenerator)
|
||||
{
|
||||
$this->urlGenerator = $urlGenerator;
|
||||
}
|
||||
|
||||
public function transform(OrderElementView $model)
|
||||
{
|
||||
$element = $model->getElement();
|
||||
$record = $model->getRecordReference();
|
||||
|
||||
$data = [
|
||||
'id' => $element->getId(),
|
||||
'record' => [
|
||||
'databox_id' => $record->getDataboxId(),
|
||||
'record_id' => $record->getRecordId(),
|
||||
],
|
||||
];
|
||||
|
||||
$data['status'] = 'pending';
|
||||
|
||||
if (null !== $element->getOrderMaster()) {
|
||||
$data['validator_id'] = $element->getOrderMaster()->getId();
|
||||
$data['status'] = $element->getDeny() ? 'rejected' : 'accepted';
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function includeResourceLinks(OrderElementView $model, ParamBag $params = null)
|
||||
{
|
||||
$parameterArray = $this->extractParamBagValues($params);
|
||||
$usedParams = array_keys(array_filter($parameterArray));
|
||||
|
||||
if (array_diff($usedParams, $this->validParams)) {
|
||||
throw new \RuntimeException(sprintf(
|
||||
'Invalid param(s): "%s". Valid param(s): "%s"',
|
||||
implode(', ', $usedParams),
|
||||
implode(', ', $this->validParams)
|
||||
));
|
||||
}
|
||||
|
||||
list ($ttl) = $parameterArray['ttl'];
|
||||
|
||||
if (null === $ttl) {
|
||||
$ttl = $this->urlGenerator->getDefaultTTL();
|
||||
}
|
||||
|
||||
$subdefs = $model->getOrderableMediaSubdefs();
|
||||
$urls = $this->urlGenerator->generateMany($model->getAuthenticatedUser(), $subdefs, $ttl);
|
||||
|
||||
$data = array_map(null, $subdefs, $urls);
|
||||
|
||||
return $this->collection($data, function (array $data) use ($ttl) {
|
||||
/** @var \media_subdef $subdef */
|
||||
list($subdef, $url) = $data;
|
||||
|
||||
return [
|
||||
'name' => $subdef->get_name(),
|
||||
'url' => $url,
|
||||
'url_ttl' => $ttl,
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ParamBag|null $params
|
||||
* @return array
|
||||
*/
|
||||
private function extractParamBagValues(ParamBag $params = null)
|
||||
{
|
||||
$array = array_fill_keys($this->validParams, null);
|
||||
|
||||
if ($params) {
|
||||
array_walk($array, function (&$value, $key) use ($params) {
|
||||
$value = $params[$key];
|
||||
});
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
}
|
95
lib/Alchemy/Phrasea/Order/OrderElementView.php
Normal file
95
lib/Alchemy/Phrasea/Order/OrderElementView.php
Normal file
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Order;
|
||||
|
||||
use Alchemy\Phrasea\Model\Entities\OrderElement;
|
||||
use Alchemy\Phrasea\Model\Entities\User;
|
||||
use Alchemy\Phrasea\Model\RecordReferenceInterface;
|
||||
use Assert\Assertion;
|
||||
|
||||
class OrderElementView
|
||||
{
|
||||
/**
|
||||
* @var OrderElement
|
||||
*/
|
||||
private $element;
|
||||
|
||||
/**
|
||||
* @var RecordReferenceInterface
|
||||
*/
|
||||
private $record;
|
||||
|
||||
/**
|
||||
* @var User
|
||||
*/
|
||||
private $user;
|
||||
|
||||
/**
|
||||
* @var \media_subdef[]
|
||||
*/
|
||||
private $subdefs = [];
|
||||
|
||||
/**
|
||||
* OrderElementViewModel constructor.
|
||||
*
|
||||
* @param OrderElement $element
|
||||
* @param RecordReferenceInterface $record
|
||||
* @param User $user
|
||||
*/
|
||||
public function __construct(OrderElement $element, RecordReferenceInterface $record, User $user)
|
||||
{
|
||||
$this->element = $element;
|
||||
$this->record = $record;
|
||||
$this->user = $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return OrderElement
|
||||
*/
|
||||
public function getElement()
|
||||
{
|
||||
return $this->element;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return RecordReferenceInterface
|
||||
*/
|
||||
public function getRecordReference()
|
||||
{
|
||||
return $this->record;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return User
|
||||
*/
|
||||
public function getAuthenticatedUser()
|
||||
{
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \media_subdef[] $subdefs
|
||||
*/
|
||||
public function setOrderableMediaSubdefs($subdefs)
|
||||
{
|
||||
Assertion::allIsInstanceOf($subdefs, \media_subdef::class);
|
||||
|
||||
$this->subdefs = $subdefs instanceof \Traversable ? iterator_to_array($subdefs) : $subdefs;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \media_subdef[]
|
||||
*/
|
||||
public function getOrderableMediaSubdefs()
|
||||
{
|
||||
return $this->subdefs;
|
||||
}
|
||||
}
|
56
lib/Alchemy/Phrasea/Order/OrderTransformer.php
Normal file
56
lib/Alchemy/Phrasea/Order/OrderTransformer.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Order;
|
||||
|
||||
use League\Fractal\TransformerAbstract;
|
||||
|
||||
class OrderTransformer extends TransformerAbstract
|
||||
{
|
||||
protected $availableIncludes = [
|
||||
'elements',
|
||||
];
|
||||
|
||||
/**
|
||||
* @var OrderElementTransformer
|
||||
*/
|
||||
private $elementTransformer;
|
||||
|
||||
public function __construct(OrderElementTransformer $elementTransformer)
|
||||
{
|
||||
$this->elementTransformer = $elementTransformer;
|
||||
}
|
||||
|
||||
public function transform(OrderView $view)
|
||||
{
|
||||
$order = $view->getOrder();
|
||||
|
||||
$data = [
|
||||
'id' => (int)$order->getId(),
|
||||
'owner_id' => (int)$order->getUser()->getId(),
|
||||
'created' => $order->getCreatedOn()->format(DATE_ATOM),
|
||||
'usage' => $order->getOrderUsage(),
|
||||
'status' => 0 === $order->getTodo() ? 'finished' : 'pending'
|
||||
];
|
||||
|
||||
if ($order->getDeadline()) {
|
||||
$data['deadline'] = $order->getDeadline()->format(DATE_ATOM);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function includeElements(OrderView $order)
|
||||
{
|
||||
$elements = $order->getElements();
|
||||
|
||||
return $this->collection($elements, $this->elementTransformer);
|
||||
}
|
||||
}
|
@@ -137,7 +137,7 @@ class OrderValidator
|
||||
throw new \RuntimeException('At least one collection was not found.');
|
||||
}
|
||||
|
||||
$references->addRecordReference(RecordReference::createFromDataboxIdAndRecordId(
|
||||
$references->add(RecordReference::createFromDataboxIdAndRecordId(
|
||||
$databoxIdMap[$orderElement->getBaseId()],
|
||||
$orderElement->getRecordId()
|
||||
));
|
||||
|
61
lib/Alchemy/Phrasea/Order/OrderView.php
Normal file
61
lib/Alchemy/Phrasea/Order/OrderView.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Order;
|
||||
|
||||
use Alchemy\Phrasea\Model\Entities\Order;
|
||||
use Assert\Assertion;
|
||||
|
||||
class OrderView
|
||||
{
|
||||
/**
|
||||
* @var Order
|
||||
*/
|
||||
private $order;
|
||||
|
||||
/**
|
||||
* @var OrderElementView[]
|
||||
*/
|
||||
private $viewElements = [];
|
||||
|
||||
/**
|
||||
* @param Order $order
|
||||
*/
|
||||
public function __construct(Order $order)
|
||||
{
|
||||
$this->order = $order;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OrderElementView[] $viewElements
|
||||
*/
|
||||
public function setViewElements($viewElements)
|
||||
{
|
||||
Assertion::allIsInstanceOf($viewElements, OrderElementView::class);
|
||||
|
||||
$this->viewElements = $viewElements instanceof \Traversable ? iterator_to_array($viewElements) : $viewElements;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Order
|
||||
*/
|
||||
public function getOrder()
|
||||
{
|
||||
return $this->order;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return OrderElementView[]
|
||||
*/
|
||||
public function getElements()
|
||||
{
|
||||
return $this->viewElements;
|
||||
}
|
||||
}
|
221
lib/Alchemy/Phrasea/Order/OrderViewBuilder.php
Normal file
221
lib/Alchemy/Phrasea/Order/OrderViewBuilder.php
Normal file
@@ -0,0 +1,221 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of alchemy/pipeline-component.
|
||||
*
|
||||
* (c) Alchemy <info@alchemy.fr>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace Alchemy\Phrasea\Order;
|
||||
|
||||
use Alchemy\Phrasea\Application;
|
||||
use Alchemy\Phrasea\Databox\Subdef\MediaSubdefService;
|
||||
use Alchemy\Phrasea\Model\Entities\Order;
|
||||
use Alchemy\Phrasea\Model\Entities\OrderElement;
|
||||
use Alchemy\Phrasea\Model\RecordReferenceInterface;
|
||||
use Alchemy\Phrasea\Record\RecordReference;
|
||||
use Alchemy\Phrasea\Record\RecordReferenceCollection;
|
||||
use Assert\Assertion;
|
||||
|
||||
class OrderViewBuilder
|
||||
{
|
||||
|
||||
/**
|
||||
* @var Application
|
||||
*/
|
||||
private $application;
|
||||
|
||||
/**
|
||||
* @var \appbox
|
||||
*/
|
||||
private $applicationBox;
|
||||
|
||||
/**
|
||||
* @var MediaSubdefService
|
||||
*/
|
||||
private $mediaSubdefService;
|
||||
|
||||
/**
|
||||
* @param Application $application
|
||||
* @param \appbox $appbox
|
||||
* @param MediaSubdefService $subdefService
|
||||
*/
|
||||
public function __construct(Application $application, \appbox $appbox, MediaSubdefService $subdefService)
|
||||
{
|
||||
$this->application = $application;
|
||||
$this->applicationBox = $appbox;
|
||||
$this->mediaSubdefService = $subdefService;
|
||||
}
|
||||
|
||||
public function buildView(Order $order, array $includes)
|
||||
{
|
||||
$view = new OrderView($order);
|
||||
|
||||
$this->fillViews([$view], $includes);
|
||||
|
||||
return $view;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Order[] $orders
|
||||
* @param string[] $includes
|
||||
* @return OrderView[]
|
||||
*/
|
||||
public function buildViews(array $orders, array $includes)
|
||||
{
|
||||
Assertion::allIsInstanceOf($orders, Order::class);
|
||||
|
||||
$views = array_map(function (Order $order) {
|
||||
return new OrderView($order);
|
||||
}, $orders);
|
||||
|
||||
$this->fillViews($views, $includes);
|
||||
|
||||
return $views;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OrderView[] $views
|
||||
* @param array $includes
|
||||
* @return void
|
||||
*/
|
||||
private function fillViews(array $views, array $includes)
|
||||
{
|
||||
if (!in_array('elements', $includes, true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$elements = $this->gatherElements($views);
|
||||
|
||||
$allElements = $elements ? call_user_func_array('array_merge', $elements) : [];
|
||||
$allElements = array_combine(
|
||||
array_map(function (OrderElement $element) {
|
||||
return $element->getId();
|
||||
}, $allElements),
|
||||
$allElements
|
||||
);
|
||||
|
||||
if (!$allElements) {
|
||||
return;
|
||||
}
|
||||
|
||||
$collectionToDataboxMap = $this->mapBaseIdToDataboxId($allElements);
|
||||
|
||||
$records = RecordReferenceCollection::fromListExtractor(
|
||||
$allElements,
|
||||
function (OrderElement $element) use ($collectionToDataboxMap) {
|
||||
return isset($collectionToDataboxMap[$element->getBaseId()])
|
||||
? [$collectionToDataboxMap[$element->getBaseId()], $element->getRecordId()]
|
||||
: null;
|
||||
},
|
||||
function (array $data) {
|
||||
list ($databoxId, $recordId) = $data;
|
||||
|
||||
return RecordReference::createFromDataboxIdAndRecordId($databoxId, $recordId);
|
||||
}
|
||||
);
|
||||
|
||||
$this->createOrderElementViews($views, $elements, $records);
|
||||
|
||||
if (!in_array('elements.resource_links', $includes, true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Load all records
|
||||
$records->toRecords($this->applicationBox);
|
||||
|
||||
// Load all subdefs
|
||||
$subdefs = $this->mediaSubdefService->findSubdefsFromRecordReferenceCollection($records);
|
||||
\media_Permalink_Adapter::getMany($this->application, $subdefs);
|
||||
|
||||
$orderableSubdefs = [];
|
||||
|
||||
foreach ($subdefs as $subdef) {
|
||||
$databoxId = $subdef->get_sbas_id();
|
||||
$recordId = $subdef->get_record_id();
|
||||
|
||||
if (!isset($orderableSubdefs[$databoxId][$recordId])) {
|
||||
$orderableSubdefs[$databoxId][$recordId] = [];
|
||||
}
|
||||
|
||||
$orderableSubdefs[$databoxId][$recordId][] = $subdef;
|
||||
}
|
||||
|
||||
foreach ($views as $model) {
|
||||
foreach ($model->getElements() as $element) {
|
||||
$databoxId = $collectionToDataboxMap[$element->getElement()->getBaseId()];
|
||||
$recordId = $element->getElement()->getRecordId();
|
||||
|
||||
if (isset($orderableSubdefs[$databoxId][$recordId])) {
|
||||
$element->setOrderableMediaSubdefs($orderableSubdefs[$databoxId][$recordId]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param OrderView[] $orderViews
|
||||
* @return OrderElement[][]
|
||||
*/
|
||||
private function gatherElements(array $orderViews)
|
||||
{
|
||||
Assertion::allIsInstanceOf($orderViews, OrderView::class);
|
||||
|
||||
$elements = [];
|
||||
|
||||
foreach ($orderViews as $index => $orderView) {
|
||||
$elements[$index] = $orderView->getOrder()->getElements()->toArray();
|
||||
}
|
||||
|
||||
return $elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OrderElement[] $elements
|
||||
* @return array
|
||||
*/
|
||||
private function mapBaseIdToDataboxId(array $elements)
|
||||
{
|
||||
$baseIds = array_keys(array_reduce($elements, function (array &$baseIds, OrderElement $element) {
|
||||
$baseIds[$element->getBaseId()] = true;
|
||||
|
||||
return $baseIds;
|
||||
}, []));
|
||||
|
||||
$collectionToDataboxMap = [];
|
||||
|
||||
foreach ($this->application['repo.collection-references']->findMany($baseIds) as $collectionReference) {
|
||||
$collectionToDataboxMap[$collectionReference->getBaseId()] = $collectionReference->getDataboxId();
|
||||
}
|
||||
|
||||
return $collectionToDataboxMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param OrderView[] $orderViews
|
||||
* @param OrderElement[][] $elements
|
||||
* @param RecordReferenceInterface[]|RecordReferenceCollection $records
|
||||
* @return void
|
||||
*/
|
||||
private function createOrderElementViews(array $orderViews, $elements, $records)
|
||||
{
|
||||
$user = $this->application->getAuthenticatedUser();
|
||||
|
||||
foreach ($orderViews as $index => $model) {
|
||||
$models = [];
|
||||
|
||||
/** @var OrderElement $element */
|
||||
foreach ($elements[$index] as $elementIndex => $element) {
|
||||
if (isset($records[$element->getId()])) {
|
||||
$models[$elementIndex] = new OrderElementView($element, $records[$element->getId()], $user);
|
||||
}
|
||||
}
|
||||
|
||||
$model->setViewElements($models);
|
||||
}
|
||||
}
|
||||
}
|
@@ -166,7 +166,7 @@ class PDF
|
||||
|
||||
$fimg = $subdef->getRealPath();
|
||||
|
||||
if (!$this->app->getAclForUser($this->app->getAuthenticatedUser())->has_right_on_base($rec->get_base_id(), "nowatermark")
|
||||
if (!$this->app->getAclForUser($this->app->getAuthenticatedUser())->has_right_on_base($rec->getBaseId(), "nowatermark")
|
||||
&& $subdef->get_type() == \media_subdef::TYPE_IMAGE) {
|
||||
$fimg = \recordutils_image::watermark($this->app, $subdef);
|
||||
}
|
||||
@@ -258,7 +258,7 @@ class PDF
|
||||
|
||||
$y = $this->pdf->GetY();
|
||||
|
||||
$t = \phrasea::bas_labels($rec->get_base_id(), $this->app);
|
||||
$t = \phrasea::bas_labels($rec->getBaseId(), $this->app);
|
||||
$this->pdf->SetFont(PhraseaPDF::FONT, '', 10);
|
||||
$this->pdf->SetFillColor(220, 220, 220);
|
||||
$this->pdf->SetLeftMargin($lmargin);
|
||||
@@ -339,10 +339,10 @@ class PDF
|
||||
$RIGHT_TEXT = "";
|
||||
$RIGHT_IMG = NULL;
|
||||
|
||||
$LEFT__IMG = $this->app['root.path'] . "/config/minilogos/logopdf_" . $rec->get_sbas_id() . ".jpg";
|
||||
$LEFT__IMG = $this->app['root.path'] . "/config/minilogos/logopdf_" . $rec->getDataboxId() . ".jpg";
|
||||
|
||||
if (!is_file($LEFT__IMG)) {
|
||||
$databox = $rec->get_databox();
|
||||
$databox = $rec->getDatabox();
|
||||
$str = $databox->get_sxml_structure();
|
||||
$vn = (string) ($str->pdfPrintLogo);
|
||||
if (($vn * 1) == 1) {
|
||||
@@ -350,7 +350,7 @@ class PDF
|
||||
}
|
||||
}
|
||||
|
||||
$collection = \collection::getByBaseId($this->app, $rec->get_base_id());
|
||||
$collection = \collection::getByBaseId($this->app, $rec->getBaseId());
|
||||
|
||||
$vn = "";
|
||||
if (false !== $str = simplexml_load_string($collection->get_prefs())) {
|
||||
@@ -358,9 +358,9 @@ class PDF
|
||||
}
|
||||
|
||||
if ($vn == "" || $vn == "1") {
|
||||
$RIGHT_TEXT = \phrasea::bas_labels($rec->get_base_id(), $this->app);
|
||||
$RIGHT_TEXT = \phrasea::bas_labels($rec->getBaseId(), $this->app);
|
||||
} elseif ($vn == "2") {
|
||||
$RIGHT_IMG = $this->app['root.path'] . "/config/minilogos/" . $rec->get_base_id();
|
||||
$RIGHT_IMG = $this->app['root.path'] . "/config/minilogos/" . $rec->getBaseId();
|
||||
}
|
||||
|
||||
$xtmp = $this->pdf->GetX();
|
||||
@@ -438,7 +438,7 @@ class PDF
|
||||
|
||||
$f = $subdef->getRealPath();
|
||||
|
||||
if (!$this->app->getAclForUser($this->app->getAuthenticatedUser())->has_right_on_base($rec->get_base_id(), "nowatermark")
|
||||
if (!$this->app->getAclForUser($this->app->getAuthenticatedUser())->has_right_on_base($rec->getBaseId(), "nowatermark")
|
||||
&& $subdef->get_type() == \media_subdef::TYPE_IMAGE)
|
||||
$f = \recordutils_image::watermark($this->app, $subdef);
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
/**
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
@@ -13,7 +13,7 @@ namespace Alchemy\Phrasea\Record;
|
||||
use Alchemy\Phrasea\Model\RecordReferenceInterface;
|
||||
use Assert\Assertion;
|
||||
|
||||
class RecordReferenceCollection implements \IteratorAggregate
|
||||
class RecordReferenceCollection implements \IteratorAggregate, \ArrayAccess
|
||||
{
|
||||
/**
|
||||
* @param array<int|string,array> $records
|
||||
@@ -28,7 +28,7 @@ class RecordReferenceCollection implements \IteratorAggregate
|
||||
foreach ($records as $index => $record) {
|
||||
if (isset($record['id'])) {
|
||||
$references[$index] = RecordReference::createFromRecordReference($record['id']);
|
||||
} elseif (isset($record['databox_id']) && isset($record['record_id'])) {
|
||||
} elseif (isset($record['databox_id'], $record['record_id'])) {
|
||||
$references[$index] = RecordReference::createFromDataboxIdAndRecordId($record['databox_id'], $record['record_id']);
|
||||
}
|
||||
}
|
||||
@@ -36,6 +36,43 @@ class RecordReferenceCollection implements \IteratorAggregate
|
||||
return new self($references);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append all RecordReferences extracted via call to extractor on each element
|
||||
*
|
||||
* @param array|\Traversable $list List of elements to process
|
||||
* @param callable $extractor Extracts data from each element or return null if unavailable
|
||||
* @param callable $creator Creates Reference from extracted data. no-op when null
|
||||
* @return RecordReferenceCollection
|
||||
*/
|
||||
public static function fromListExtractor($list, callable $extractor, callable $creator = null)
|
||||
{
|
||||
Assertion::isTraversable($list);
|
||||
|
||||
$references = [];
|
||||
|
||||
if (null === $creator) {
|
||||
$creator = function ($data) {
|
||||
return $data;
|
||||
};
|
||||
}
|
||||
|
||||
foreach ($list as $index => $item) {
|
||||
$data = $extractor($item);
|
||||
|
||||
if (null === $data) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$reference = $creator($data);
|
||||
|
||||
if ($reference instanceof RecordReferenceInterface) {
|
||||
$references[$index] = $reference;
|
||||
}
|
||||
}
|
||||
|
||||
return new self($references);
|
||||
}
|
||||
|
||||
/**
|
||||
* @var RecordReferenceInterface[]
|
||||
*/
|
||||
@@ -53,13 +90,35 @@ class RecordReferenceCollection implements \IteratorAggregate
|
||||
{
|
||||
Assertion::allIsInstanceOf($references, RecordReferenceInterface::class);
|
||||
|
||||
$this->references = $references instanceof \Traversable ? iterator_to_array($references) : $references;
|
||||
$this->references = $references instanceof \Traversable ? iterator_to_array($references, true) : $references;
|
||||
}
|
||||
|
||||
public function addRecordReference(RecordReferenceInterface $reference)
|
||||
/**
|
||||
* @param RecordReferenceInterface $reference
|
||||
* @param null|string|int $index
|
||||
*/
|
||||
public function add(RecordReferenceInterface $reference, $index = null)
|
||||
{
|
||||
$this->references[] = $reference;
|
||||
$this->groups = null;
|
||||
|
||||
if (null === $index) {
|
||||
$this->references[] = $reference;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->references[$index] = $reference;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $databoxId
|
||||
* @param int $recordId
|
||||
* @param null|string|int $index
|
||||
* @return void
|
||||
*/
|
||||
public function addRecordReference($databoxId, $recordId, $index = null)
|
||||
{
|
||||
$this->add(RecordReference::createFromDataboxIdAndRecordId($databoxId, $recordId), $index);
|
||||
}
|
||||
|
||||
public function getIterator()
|
||||
@@ -115,8 +174,48 @@ class RecordReferenceCollection implements \IteratorAggregate
|
||||
}
|
||||
}
|
||||
|
||||
ksort($records);
|
||||
$indexes = array_flip(array_keys($this->references));
|
||||
|
||||
return array_values($records);
|
||||
uksort($records, function ($keyA, $keyB) use ($indexes) {
|
||||
$indexA = $indexes[$keyA];
|
||||
$indexB = $indexes[$keyB];
|
||||
|
||||
if ($indexA < $indexB) {
|
||||
return -1;
|
||||
} elseif ($indexA > $indexB) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
});
|
||||
|
||||
return $records;
|
||||
}
|
||||
|
||||
public function offsetExists($offset)
|
||||
{
|
||||
return isset($this->references[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $offset
|
||||
* @return RecordReferenceInterface
|
||||
*/
|
||||
public function offsetGet($offset)
|
||||
{
|
||||
return $this->references[$offset];
|
||||
}
|
||||
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
Assertion::isInstanceOf($value, RecordReferenceInterface::class);
|
||||
|
||||
$this->add($value, $offset);
|
||||
}
|
||||
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
unset($this->references[$offset]);
|
||||
$this->groups = null;
|
||||
}
|
||||
}
|
||||
|
@@ -268,7 +268,7 @@ class ElasticSearchEngine implements SearchEngineInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function query($string, $offset, $perPage, SearchEngineOptions $options = null)
|
||||
public function query($string, SearchEngineOptions $options = null)
|
||||
{
|
||||
$options = $options ?: new SearchEngineOptions();
|
||||
$context = $this->context_factory->createContext($options);
|
||||
@@ -282,13 +282,15 @@ class ElasticSearchEngine implements SearchEngineInterface
|
||||
// ask ES to return field _version (incremental version number of document)
|
||||
$params['body']['version'] = true;
|
||||
|
||||
$params['body']['from'] = $offset;
|
||||
$params['body']['size'] = $perPage;
|
||||
$params['body']['from'] = $options->getFirstResult();
|
||||
$params['body']['size'] = $options->getMaxResults();
|
||||
if($this->options->getHighlight()) {
|
||||
$params['body']['highlight'] = $this->buildHighlightRules($context);
|
||||
}
|
||||
|
||||
if ($aggs = $this->getAggregationQueryParams($options)) {
|
||||
$aggs = $this->getAggregationQueryParams($options);
|
||||
|
||||
if ($aggs) {
|
||||
$params['body']['aggs'] = $aggs;
|
||||
}
|
||||
|
||||
@@ -314,7 +316,7 @@ class ElasticSearchEngine implements SearchEngineInterface
|
||||
$results, // ArrayCollection of results
|
||||
json_encode($query),
|
||||
$res['took'], // duration
|
||||
$offset, // offset start
|
||||
$options->getFirstResult(),
|
||||
$res['hits']['total'], // available
|
||||
$res['hits']['total'], // total
|
||||
null, // error
|
||||
@@ -369,16 +371,6 @@ class ElasticSearchEngine implements SearchEngineInterface
|
||||
throw new RuntimeException('Elasticsearch engine currently does not support auto-complete.');
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function excerpt($query, $fields, \record_adapter $record, SearchEngineOptions $options = null)
|
||||
{
|
||||
//@todo implements
|
||||
|
||||
return array();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
|
@@ -30,6 +30,14 @@ class ElasticsearchSettingsFormType extends AbstractType
|
||||
'label' => 'ElasticSearch index name',
|
||||
'constraints' => new NotBlank(),
|
||||
])
|
||||
->add('esSettingsDropIndexButton', 'button', [
|
||||
'label' => "Drop index",
|
||||
'attr' => ['data-id' => "esSettingsDropIndexButton"]
|
||||
])
|
||||
->add('esSettingsCreateIndexButton', 'button', [
|
||||
'label' => "Create index",
|
||||
'attr' => ['data-id' => "esSettingsCreateIndexButton"]
|
||||
])
|
||||
->add('shards', 'integer', [
|
||||
'label' => 'Number of shards',
|
||||
'constraints' => new Range(['min' => 1]),
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user