mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-22 17:33:12 +00:00
Merge branch 'master' into PHRAS-3144-install-plugin
This commit is contained in:
@@ -193,17 +193,20 @@ XDEBUG_REMOTE_HOST=host.docker.internal
|
|||||||
Plugins can be installed during build if you set the `PHRASEANET_PLUGINS` env var as follows:
|
Plugins can be installed during build if you set the `PHRASEANET_PLUGINS` env var as follows:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
PHRASEANET_PLUGINS="git@github.com:alchemy-fr/Phraseanet-plugin-webgallery.git"
|
PHRASEANET_PLUGINS="https://github.com/alchemy-fr/Phraseanet-plugin-expose.git"
|
||||||
|
|
||||||
# You can optionally precise the branch to install
|
# You can optionally precise the branch to install
|
||||||
# If not precised, the main branch will be pulled
|
# If not precised, the main branch will be pulled
|
||||||
PHRASEANET_PLUGINS="git@github.com:alchemy-fr/Phraseanet-plugin-webgallery.git(custom-branch)"
|
PHRASEANET_PLUGINS="git@github.com:alchemy-fr/Phraseanet-plugin-webgallery.git(custom-branch)"
|
||||||
|
|
||||||
# Plugins are separated by spaces
|
# Plugins are separated by semicolons
|
||||||
PHRASEANET_PLUGINS="git@github.com:foo/bar.git(branch-1) git@github.com:baz/42.git"
|
PHRASEANET_PLUGINS="git@github.com:foo/bar.git(branch-1);git@github.com:baz/42.git"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
> Prefer the HTTPS URL for public repositories, you will not be required to provide your SSH key.
|
||||||
|
|
||||||
If you install private plugins, make sure you export your SSH private key content in order to allow docker build to access the GIT repository:
|
If you install private plugins, make sure you export your SSH private key content in order to allow docker build to access the GIT repository:
|
||||||
|
Also ensure you're using the SSH URL form (i.e: `git@github.com:alchemy-fr/repo.git`).
|
||||||
```bash
|
```bash
|
||||||
export PHRASEANET_SSH_PRIVATE_KEY=$(cat ~/.ssh/id_rsa)
|
export PHRASEANET_SSH_PRIVATE_KEY=$(cat ~/.ssh/id_rsa)
|
||||||
# or if your private key is protected by a passphrase:
|
# or if your private key is protected by a passphrase:
|
||||||
|
@@ -29,7 +29,7 @@ class InstallCommand extends Command
|
|||||||
mkdir($pluginsDir);
|
mkdir($pluginsDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (explode(' ', $plugins) as $key => $plugin) {
|
foreach (explode(';', $plugins) as $key => $plugin) {
|
||||||
$plugin = trim($plugin);
|
$plugin = trim($plugin);
|
||||||
$repo = $plugin;
|
$repo = $plugin;
|
||||||
$branch = 'master';
|
$branch = 'master';
|
||||||
|
@@ -2093,7 +2093,7 @@ class V1Controller extends Controller
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$collection = \collection::getByBaseId($this->app, $request->get('base_id'));
|
$collection = \collection::getByBaseId($this->app, $request->get('base_id'));
|
||||||
$record->move_to_collection($collection, $this->getApplicationBox());
|
$record->move_to_collection($collection);
|
||||||
|
|
||||||
return Result::create($request, ["record" => $this->listRecord($request, $record)])->createResponse();
|
return Result::create($request, ["record" => $this->listRecord($request, $record)])->createResponse();
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
|
@@ -17,7 +17,7 @@ use Symfony\Component\HttpFoundation\Request;
|
|||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
|
|
||||||
class V3MetadatasController extends Controller
|
class V3RecordController extends Controller
|
||||||
{
|
{
|
||||||
use JsonBodyAware;
|
use JsonBodyAware;
|
||||||
use DispatcherAware;
|
use DispatcherAware;
|
||||||
@@ -32,7 +32,7 @@ class V3MetadatasController extends Controller
|
|||||||
*
|
*
|
||||||
* @return Response
|
* @return Response
|
||||||
*/
|
*/
|
||||||
public function setmetadatasAction(Request $request, $databox_id, $record_id)
|
public function indexAction_patch(Request $request, $databox_id, $record_id)
|
||||||
{
|
{
|
||||||
$struct = $this->findDataboxById($databox_id)->get_meta_structure();
|
$struct = $this->findDataboxById($databox_id)->get_meta_structure();
|
||||||
$record = $this->findDataboxById($databox_id)->get_record($record_id);
|
$record = $this->findDataboxById($databox_id)->get_record($record_id);
|
||||||
@@ -59,7 +59,10 @@ class V3MetadatasController extends Controller
|
|||||||
}
|
}
|
||||||
// do sb ops
|
// do sb ops
|
||||||
if (is_array($b->status)) {
|
if (is_array($b->status)) {
|
||||||
$debug['sb_ops'] = $this->do_status($struct, $record, $b->status);
|
$debug['sb_ops'] = $this->do_status($record, $b->status);
|
||||||
|
}
|
||||||
|
if(!is_null($b->base_id)) {
|
||||||
|
$debug['coll_ops'] = $this->do_collection($record, $b->base_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception $e) {
|
catch (Exception $e) {
|
||||||
@@ -77,13 +80,21 @@ class V3MetadatasController extends Controller
|
|||||||
return Result::create($request, $ret)->createResponse();
|
return Result::create($request, $ret)->createResponse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param record_adapter $record
|
||||||
|
* @param $base_id
|
||||||
|
*/
|
||||||
|
private function do_collection(record_adapter $record, $base_id)
|
||||||
|
{
|
||||||
|
$record->move_to_collection($this->getApplicationBox()->get_collection($base_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////
|
//////////////////////////////////
|
||||||
/// TODO : keep multi-values uniques !
|
/// TODO : keep multi-values uniques !
|
||||||
/// it should be done in record_adapter
|
/// it should be done in record_adapter
|
||||||
//////////////////////////////////
|
//////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param databox_field[] $struct
|
* @param databox_field[] $struct
|
||||||
* @param record_adapter $record
|
* @param record_adapter $record
|
||||||
@@ -94,12 +105,10 @@ class V3MetadatasController extends Controller
|
|||||||
private function do_metadatas($struct, record_adapter $record, $metadatas)
|
private function do_metadatas($struct, record_adapter $record, $metadatas)
|
||||||
{
|
{
|
||||||
$structByKey = [];
|
$structByKey = [];
|
||||||
$nameToStrucId = [];
|
|
||||||
$allStructFields = [];
|
$allStructFields = [];
|
||||||
foreach ($struct as $f) {
|
foreach ($struct as $f) {
|
||||||
$nameToStrucId[$f->get_name()] = $f->get_id();
|
|
||||||
$allStructFields[$f->get_id()] = $f;
|
$allStructFields[$f->get_id()] = $f;
|
||||||
$structByKey[$f->get_id()] = &$allStructFields[$f->get_id()];;
|
$structByKey[$f->get_id()] = &$allStructFields[$f->get_id()];
|
||||||
$structByKey[$f->get_name()] = &$allStructFields[$f->get_id()];
|
$structByKey[$f->get_name()] = &$allStructFields[$f->get_id()];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,6 +132,9 @@ class V3MetadatasController extends Controller
|
|||||||
$fields_list[] = $structByKey[$k]->get_name();
|
$fields_list[] = $structByKey[$k]->get_name();
|
||||||
$struct_fields[$structByKey[$k]->get_id()] = $structByKey[$k];
|
$struct_fields[$structByKey[$k]->get_id()] = $structByKey[$k];
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
throw new Exception(sprintf("unknown field (%s).", $k));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -187,13 +199,12 @@ class V3MetadatasController extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $struct
|
|
||||||
* @param $record
|
* @param $record
|
||||||
* @param $statuses
|
* @param $statuses
|
||||||
* @return array
|
* @return array
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
private function do_status($struct, $record, $statuses)
|
private function do_status(record_adapter $record, $statuses)
|
||||||
{
|
{
|
||||||
$datas = strrev($record->getStatus());
|
$datas = strrev($record->getStatus());
|
||||||
|
|
@@ -115,13 +115,13 @@ class MoveCollectionController extends Controller
|
|||||||
|
|
||||||
foreach ($records as $record) {
|
foreach ($records as $record) {
|
||||||
$oldCollectionId = $record->getCollection()->get_coll_id();
|
$oldCollectionId = $record->getCollection()->get_coll_id();
|
||||||
$record->move_to_collection($collection, $this->getApplicationBox());
|
$record->move_to_collection($collection);
|
||||||
|
|
||||||
if ($request->request->get("chg_coll_son") == "1") {
|
if ($request->request->get("chg_coll_son") == "1") {
|
||||||
/** @var \record_adapter $child */
|
/** @var \record_adapter $child */
|
||||||
foreach ($record->getChildren() as $child) {
|
foreach ($record->getChildren() as $child) {
|
||||||
if ($this->getAclForUser()->has_right_on_base($child->getBaseId(), \ACL::CANDELETERECORD)) {
|
if ($this->getAclForUser()->has_right_on_base($child->getBaseId(), \ACL::CANDELETERECORD)) {
|
||||||
$child->move_to_collection($collection, $this->getApplicationBox());
|
$child->move_to_collection($collection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -242,7 +242,7 @@ class RecordController extends Controller
|
|||||||
$this->getEventDispatcher()->dispatch(RecordEvents::DELETE, new DeleteEvent($record));
|
$this->getEventDispatcher()->dispatch(RecordEvents::DELETE, new DeleteEvent($record));
|
||||||
} else {
|
} else {
|
||||||
// move to trash collection
|
// move to trash collection
|
||||||
$record->move_to_collection($trashCollectionsBySbasId[$sbasId], $this->getApplicationBox());
|
$record->move_to_collection($trashCollectionsBySbasId[$sbasId]);
|
||||||
// disable permalinks
|
// disable permalinks
|
||||||
foreach($record->get_subdefs() as $subdef) {
|
foreach($record->get_subdefs() as $subdef) {
|
||||||
if( ($pl = $subdef->get_permalink()) ) {
|
if( ($pl = $subdef->get_permalink()) ) {
|
||||||
|
@@ -13,6 +13,9 @@ use Alchemy\Phrasea\Application\Helper\DispatcherAware;
|
|||||||
use Alchemy\Phrasea\Controller\Controller;
|
use Alchemy\Phrasea\Controller\Controller;
|
||||||
use Alchemy\Phrasea\Core\Event\Thesaurus as ThesaurusEvent;
|
use Alchemy\Phrasea\Core\Event\Thesaurus as ThesaurusEvent;
|
||||||
use Alchemy\Phrasea\Core\Event\Thesaurus\ThesaurusEvents;
|
use Alchemy\Phrasea\Core\Event\Thesaurus\ThesaurusEvents;
|
||||||
|
use Alchemy\Phrasea\SearchEngine\Elastic\ElasticsearchOptions;
|
||||||
|
use Alchemy\Phrasea\WorkerManager\Event\PopulateIndexEvent;
|
||||||
|
use Alchemy\Phrasea\WorkerManager\Event\WorkerEvents;
|
||||||
use Doctrine\DBAL\Driver\Connection;
|
use Doctrine\DBAL\Driver\Connection;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
@@ -1222,6 +1225,26 @@ class ThesaurusController extends Controller
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Order to populate databox
|
||||||
|
*
|
||||||
|
* @param Request $request
|
||||||
|
* @return \Symfony\Component\HttpFoundation\JsonResponse
|
||||||
|
*/
|
||||||
|
public function populate(Request $request)
|
||||||
|
{
|
||||||
|
$options = $this->getElasticsearchOptions();
|
||||||
|
|
||||||
|
$data['host'] = $options->getHost();
|
||||||
|
$data['port'] = $options->getPort();
|
||||||
|
$data['indexName'] = $options->getIndexName();
|
||||||
|
$data['databoxIds'] = [$request->get('databox_id')];
|
||||||
|
|
||||||
|
$this->getDispatcher()->dispatch(WorkerEvents::POPULATE_INDEX, new PopulateIndexEvent($data));
|
||||||
|
|
||||||
|
return $this->app->json($data);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Request $request
|
* @param Request $request
|
||||||
* @return Response
|
* @return Response
|
||||||
@@ -3031,4 +3054,12 @@ class ThesaurusController extends Controller
|
|||||||
{
|
{
|
||||||
return $this->app['locales.available'];
|
return $this->app['locales.available'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return ElasticsearchOptions
|
||||||
|
*/
|
||||||
|
private function getElasticsearchOptions()
|
||||||
|
{
|
||||||
|
return $this->app['elasticsearch.options'];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,7 @@
|
|||||||
namespace Alchemy\Phrasea\ControllerProvider\Api;
|
namespace Alchemy\Phrasea\ControllerProvider\Api;
|
||||||
|
|
||||||
use Alchemy\Phrasea\Application as PhraseaApplication;
|
use Alchemy\Phrasea\Application as PhraseaApplication;
|
||||||
use Alchemy\Phrasea\Controller\Api\V3\V3MetadatasController;
|
use Alchemy\Phrasea\Controller\Api\V3\V3RecordController;
|
||||||
use Alchemy\Phrasea\Controller\Api\V3\V3ResultHelpers;
|
use Alchemy\Phrasea\Controller\Api\V3\V3ResultHelpers;
|
||||||
use Alchemy\Phrasea\Controller\Api\V3\V3SearchController;
|
use Alchemy\Phrasea\Controller\Api\V3\V3SearchController;
|
||||||
use Alchemy\Phrasea\Controller\Api\V3\V3StoriesController;
|
use Alchemy\Phrasea\Controller\Api\V3\V3StoriesController;
|
||||||
@@ -28,7 +28,7 @@ class V3 extends Api implements ControllerProviderInterface, ServiceProviderInte
|
|||||||
));
|
));
|
||||||
});
|
});
|
||||||
$app['controller.api.v3.metadatas'] = $app->share(function (PhraseaApplication $app) {
|
$app['controller.api.v3.metadatas'] = $app->share(function (PhraseaApplication $app) {
|
||||||
return (new V3MetadatasController($app))
|
return (new V3RecordController($app))
|
||||||
->setJsonBodyHelper($app['json.body_helper'])
|
->setJsonBodyHelper($app['json.body_helper'])
|
||||||
->setDispatcher($app['dispatcher'])
|
->setDispatcher($app['dispatcher'])
|
||||||
;
|
;
|
||||||
@@ -70,9 +70,9 @@ class V3 extends Api implements ControllerProviderInterface, ServiceProviderInte
|
|||||||
$controllers->match('/search/', 'controller.api.v3.search:searchAction');
|
$controllers->match('/search/', 'controller.api.v3.search:searchAction');
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @uses V3MetadatasController::setmetadatasAction()
|
* @uses V3RecordController::indexAction_patch()
|
||||||
*/
|
*/
|
||||||
$controllers->patch('/records/{databox_id}/{record_id}/setmetadatas/', 'controller.api.v3.metadatas:setmetadatasAction')
|
$controllers->patch('/records/{databox_id}/{record_id}/', 'controller.api.v3.metadatas:indexAction_patch')
|
||||||
->before('controller.api.v1:ensureCanAccessToRecord')
|
->before('controller.api.v1:ensureCanAccessToRecord')
|
||||||
->before('controller.api.v1:ensureCanModifyRecord')
|
->before('controller.api.v1:ensureCanModifyRecord')
|
||||||
->assert('databox_id', '\d+')
|
->assert('databox_id', '\d+')
|
||||||
|
@@ -60,6 +60,7 @@ class Thesaurus implements ControllerProviderInterface, ServiceProviderInterface
|
|||||||
$controllers->match('newterm.php', 'controller.thesaurus:newTerm');
|
$controllers->match('newterm.php', 'controller.thesaurus:newTerm');
|
||||||
$controllers->match('properties.php', 'controller.thesaurus:properties');
|
$controllers->match('properties.php', 'controller.thesaurus:properties');
|
||||||
$controllers->match('thesaurus.php', 'controller.thesaurus:thesaurus')->bind('thesaurus_thesaurus');
|
$controllers->match('thesaurus.php', 'controller.thesaurus:thesaurus')->bind('thesaurus_thesaurus');
|
||||||
|
$controllers->match('populate', 'controller.thesaurus:populate')->bind('thesaurus_populate');
|
||||||
|
|
||||||
$controllers->match('xmlhttp/accept.x.php', 'controller.thesaurus:acceptXml');
|
$controllers->match('xmlhttp/accept.x.php', 'controller.thesaurus:acceptXml');
|
||||||
$controllers->match('xmlhttp/acceptcandidates.x.php', 'controller.thesaurus:acceptCandidatesXml');
|
$controllers->match('xmlhttp/acceptcandidates.x.php', 'controller.thesaurus:acceptCandidatesXml');
|
||||||
|
@@ -74,7 +74,6 @@ class RecordMoverJob extends AbstractJob
|
|||||||
|
|
||||||
private function processData(Application $app, $row, $logsql)
|
private function processData(Application $app, $row, $logsql)
|
||||||
{
|
{
|
||||||
/** @var databox $databox */
|
|
||||||
$databox = $app->findDataboxById($row['sbas_id']);
|
$databox = $app->findDataboxById($row['sbas_id']);
|
||||||
$rec = $databox->get_record($row['record_id']);
|
$rec = $databox->get_record($row['record_id']);
|
||||||
|
|
||||||
@@ -83,7 +82,7 @@ class RecordMoverJob extends AbstractJob
|
|||||||
// change collection ?
|
// change collection ?
|
||||||
if (array_key_exists('coll', $row)) {
|
if (array_key_exists('coll', $row)) {
|
||||||
$coll = \collection::getByCollectionId($app, $databox, $row['coll']);
|
$coll = \collection::getByCollectionId($app, $databox, $row['coll']);
|
||||||
$rec->move_to_collection($coll, $app['phraseanet.appbox']);
|
$rec->move_to_collection($coll);
|
||||||
if ($logsql) {
|
if ($logsql) {
|
||||||
$this->log('debug', sprintf("on sbas %s move rid %s to coll %s \n", $row['sbas_id'], $row['record_id'], $coll->get_coll_id()));
|
$this->log('debug', sprintf("on sbas %s move rid %s to coll %s \n", $row['sbas_id'], $row['record_id'], $coll->get_coll_id()));
|
||||||
}
|
}
|
||||||
|
@@ -522,10 +522,11 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param collection $collection
|
* @param collection $collection
|
||||||
* @param appbox $appbox
|
* @param appbox $appbox WTF this parm is useless
|
||||||
* @return record_adapter
|
* @return record_adapter
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public function move_to_collection(collection $collection, appbox $appbox)
|
public function move_to_collection(collection $collection, appbox $appbox = null)
|
||||||
{
|
{
|
||||||
if ($this->getCollection()->get_base_id() === $collection->get_base_id()) {
|
if ($this->getCollection()->get_base_id() === $collection->get_base_id()) {
|
||||||
return $this;
|
return $this;
|
||||||
|
@@ -118,7 +118,7 @@ class OverviewTest extends \PhraseanetAuthenticatedWebTestCase
|
|||||||
public function testDatafilesRouteNotAuthenticatedIsOkInPublicFeed()
|
public function testDatafilesRouteNotAuthenticatedIsOkInPublicFeed()
|
||||||
{
|
{
|
||||||
self::$DI['app']['phraseanet.SE'] = $this->createSearchEngineMock();
|
self::$DI['app']['phraseanet.SE'] = $this->createSearchEngineMock();
|
||||||
self::$DI['record_5']->move_to_collection(self::$DI['collection_no_access'], self::$DI['app']['phraseanet.appbox']);
|
self::$DI['record_5']->move_to_collection(self::$DI['collection_no_access']);
|
||||||
$path = self::$DI['app']['url_generator']->generate('datafile', [
|
$path = self::$DI['app']['url_generator']->generate('datafile', [
|
||||||
'sbas_id' => self::$DI['record_5']->get_sbas_id(),
|
'sbas_id' => self::$DI['record_5']->get_sbas_id(),
|
||||||
'record_id' => self::$DI['record_5']->get_record_id(),
|
'record_id' => self::$DI['record_5']->get_record_id(),
|
||||||
@@ -127,7 +127,7 @@ class OverviewTest extends \PhraseanetAuthenticatedWebTestCase
|
|||||||
|
|
||||||
self::$DI['client']->request('GET', $path);
|
self::$DI['client']->request('GET', $path);
|
||||||
$this->assertTrue(self::$DI['client']->getResponse()->isOk());
|
$this->assertTrue(self::$DI['client']->getResponse()->isOk());
|
||||||
self::$DI['record_5']->move_to_collection(self::$DI['collection'], self::$DI['app']['phraseanet.appbox']);
|
self::$DI['record_5']->move_to_collection(self::$DI['collection']);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testDatafilesRouteNotAuthenticatedUnknownSubdef()
|
public function testDatafilesRouteNotAuthenticatedUnknownSubdef()
|
||||||
|
Reference in New Issue
Block a user