mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-15 05:53:13 +00:00
Merge branch 4.0
This commit is contained in:
37
.travis.yml
37
.travis.yml
@@ -1,11 +1,5 @@
|
||||
language: php
|
||||
sudo: require
|
||||
env:
|
||||
- TEST_SUITE=1
|
||||
- TEST_SUITE=2
|
||||
php:
|
||||
- 5.5
|
||||
- 5.6
|
||||
|
||||
branches:
|
||||
except:
|
||||
@@ -14,14 +8,33 @@ branches:
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
allow_failures:
|
||||
- php: 7.0
|
||||
env: TEST_SUITE=1
|
||||
- php: 7.0
|
||||
env: TEST_SUITE=2
|
||||
include:
|
||||
- php: 5.5
|
||||
env: TEST_SUITE=1
|
||||
- php: 5.6
|
||||
env: TEST_SUITE=1
|
||||
- php: 7.0
|
||||
env: TEST_SUITE=1
|
||||
- php: 5.5
|
||||
env: TEST_SUITE=2
|
||||
- php: 5.6
|
||||
env: TEST_SUITE=2
|
||||
- php: 7.0
|
||||
env: TEST_SUITE=2
|
||||
|
||||
services:
|
||||
- mysql
|
||||
- memcached
|
||||
- redis
|
||||
- rabbitmq
|
||||
|
||||
before_install:
|
||||
- nvm install 0.12.0
|
||||
- nvm install stable
|
||||
- phpenv config-rm xdebug.ini
|
||||
- composer self-update --no-progress --no-interaction
|
||||
- sudo apt-get purge elasticsearch
|
||||
@@ -30,12 +43,15 @@ before_install:
|
||||
- sudo service elasticsearch start
|
||||
- echo 'session.cache_limiter = ""' >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini
|
||||
- echo 'extension="redis.so"' >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini
|
||||
- echo 'extension="memcache.so"' >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini
|
||||
- if [[ $TRAVIS_PHP_VERSION = 5.* ]];then echo 'extension="memcache.so"' >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini; fi;
|
||||
- echo 'extension="memcached.so"' >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini
|
||||
- echo "extension=zmq.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/conf.d/travis.ini
|
||||
- yes | pecl install imagick
|
||||
- yes | pecl install imagick-beta
|
||||
- sudo apt-get install librabbitmq-dev
|
||||
- pecl install amqp-1.4.0
|
||||
install:
|
||||
- travis_retry composer install --no-progress --no-interaction --optimize-autoloader
|
||||
- if [[ $TRAVIS_PHP_VERSION = 5.* ]];then travis_retry composer install --no-progress --no-interaction --optimize-autoloader; fi;
|
||||
- if [[ $TRAVIS_PHP_VERSION = 7.* ]];then travis_retry composer update --no-progress --no-interaction --optimize-autoloader; fi;
|
||||
- travis_retry npm install
|
||||
before_script:
|
||||
- mysql -e 'CREATE DATABASE update39_test;CREATE DATABASE ab_test;CREATE DATABASE db_test;SET @@global.sql_mode=STRICT_ALL_TABLES;SET @@global.max_allowed_packet=33554432;SET @@global.wait_timeout=999999;'
|
||||
@@ -51,7 +67,6 @@ before_script:
|
||||
- "./bin/developer phraseanet:generate-js-fixtures"
|
||||
|
||||
script:
|
||||
- "./node_modules/.bin/gulp test"
|
||||
- |
|
||||
echo "$TEST_SUITE";
|
||||
case "$TEST_SUITE" in
|
||||
|
@@ -30,7 +30,3 @@ See https://docs.phraseanet.com/Devel/
|
||||
#License :
|
||||
|
||||
Phraseanet is licensed under GPL-v3 license.
|
||||
|
||||
|
||||
[](https://bitdeli.com/free "Bitdeli Badge")
|
||||
|
||||
|
34
bin/console
34
bin/console
@@ -11,15 +11,22 @@
|
||||
|
||||
namespace KonsoleKommander;
|
||||
|
||||
use Alchemy\Phrasea\CLI;
|
||||
use Alchemy\Phrasea\Command\BuildMissingSubdefs;
|
||||
use Alchemy\Phrasea\Command\BuildSubdefs;
|
||||
use Alchemy\Phrasea\Command\CheckConfig;
|
||||
use Alchemy\Phrasea\Command\Compile\Configuration;
|
||||
use Alchemy\Phrasea\Command\CreateCollection;
|
||||
use Alchemy\Phrasea\Command\MailTest;
|
||||
use Alchemy\Phrasea\Command\Plugin\AddPlugin;
|
||||
use Alchemy\Phrasea\Command\Plugin\ListPlugin;
|
||||
use Alchemy\Phrasea\Command\Setup\H264ConfigurationDumper;
|
||||
use Alchemy\Phrasea\Command\Setup\H264MappingGenerator;
|
||||
use Alchemy\Phrasea\Command\Plugin\RemovePlugin;
|
||||
use Alchemy\Phrasea\Command\RecordAdd;
|
||||
use Alchemy\Phrasea\Command\RescanTechnicalDatas;
|
||||
use Alchemy\Phrasea\Command\SearchEngine\Debug\QueryParseCommand;
|
||||
use Alchemy\Phrasea\Command\SearchEngine\Debug\QuerySampleCommand;
|
||||
use Alchemy\Phrasea\Command\SearchEngine\IndexCreateCommand;
|
||||
use Alchemy\Phrasea\Command\SearchEngine\IndexDropCommand;
|
||||
use Alchemy\Phrasea\Command\SearchEngine\MappingUpdateCommand;
|
||||
use Alchemy\Phrasea\Command\SearchEngine\IndexPopulateCommand;
|
||||
use Alchemy\Phrasea\Command\Thesaurus\FindConceptsCommand;
|
||||
use Alchemy\Phrasea\Command\WebsocketServer;
|
||||
@@ -37,17 +44,23 @@ use Alchemy\Phrasea\Command\Plugin\AddPlugin;
|
||||
use Alchemy\Phrasea\Command\Plugin\RemovePlugin;
|
||||
use Alchemy\Phrasea\Command\CheckConfig;
|
||||
use Alchemy\Phrasea\Command\Setup\XSendFileMappingGenerator;
|
||||
use Alchemy\Phrasea\Command\SearchEngine\MappingUpdateCommand;
|
||||
use Alchemy\Phrasea\Command\Setup\H264ConfigurationDumper;
|
||||
use Alchemy\Phrasea\Command\Setup\H264MappingGenerator;
|
||||
use Alchemy\Phrasea\Command\Setup\XSendFileConfigurationDumper;
|
||||
use Alchemy\Phrasea\Command\Task\SchedulerResumeTasks;
|
||||
use Alchemy\Phrasea\Command\Task\SchedulerState;
|
||||
use Alchemy\Phrasea\Command\Setup\XSendFileMappingGenerator;
|
||||
use Alchemy\Phrasea\Command\Task\SchedulerPauseTasks;
|
||||
use Alchemy\Phrasea\Command\Task\SchedulerResumeTasks;
|
||||
use Alchemy\Phrasea\Command\Task\SchedulerRun;
|
||||
use Alchemy\Phrasea\Command\Task\SchedulerState;
|
||||
use Alchemy\Phrasea\Command\Task\TaskList;
|
||||
use Alchemy\Phrasea\Command\Task\TaskRun;
|
||||
use Alchemy\Phrasea\Command\Task\TaskStart;
|
||||
use Alchemy\Phrasea\Command\Task\TaskStop;
|
||||
use Alchemy\Phrasea\Command\Task\TaskState;
|
||||
use Alchemy\Phrasea\SearchEngine\SearchEngineInterface;
|
||||
use Alchemy\Phrasea\Command\Task\TaskStop;
|
||||
use Alchemy\Phrasea\Command\Thesaurus\FindConceptsCommand;
|
||||
use Alchemy\Phrasea\Command\UpgradeDBDatas;
|
||||
use Alchemy\Phrasea\Core\Version;
|
||||
|
||||
require_once __DIR__ . '/../lib/autoload.php';
|
||||
|
||||
@@ -73,6 +86,7 @@ $cli = new CLI("
|
||||
if (!$cli['phraseanet.configuration-tester']->isInstalled()) {
|
||||
throw new \RuntimeException('Phraseanet is not installed, use setup command instead');
|
||||
}
|
||||
|
||||
if (!$cli['phraseanet.configuration-tester']->isUpToDate()) {
|
||||
throw new \RuntimeException('Phraseanet is not up-to-date, use setup command instead');
|
||||
}
|
||||
@@ -132,6 +146,10 @@ $cli->command(new QueryParseCommand());
|
||||
$cli->command(new QuerySampleCommand());
|
||||
$cli->command(new FindConceptsCommand());
|
||||
|
||||
$cli->command($cli['alchemy_worker.commands.run_dispatcher_command']);
|
||||
$cli->command($cli['alchemy_worker.commands.run_worker_command']);
|
||||
$cli->command($cli['alchemy_worker.commands.show_configuration']);
|
||||
|
||||
$cli->loadPlugins();
|
||||
|
||||
exit(is_int($cli->run()) ? : 1);
|
||||
$cli->run();
|
||||
|
@@ -122,4 +122,4 @@ if ($cli['configuration.store']->isSetup()) {
|
||||
}
|
||||
}
|
||||
|
||||
exit(is_int($cli->run()) ? : 1);
|
||||
$cli->run();
|
||||
|
@@ -79,4 +79,4 @@ $app->command(new CrossDomainGenerator());
|
||||
|
||||
$app['phraseanet.setup_mode'] = true;
|
||||
|
||||
exit(is_int($app->run()) ? : 1);
|
||||
$app->run();
|
||||
|
@@ -27,7 +27,7 @@
|
||||
"bootstrap-sass": "v2.3.2.2",
|
||||
"jquery.lazyload": "~1.9.7",
|
||||
"jquery-treeview": "~1.4.2",
|
||||
"alchemy-embed-medias": "~0.3.2"
|
||||
"html5shiv": "^3.7.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"mocha": "latest",
|
||||
|
@@ -9,11 +9,12 @@ machine:
|
||||
php:
|
||||
version: 5.5.21
|
||||
node:
|
||||
version: 0.12.0
|
||||
version: stable
|
||||
services:
|
||||
- memcached
|
||||
- redis
|
||||
- mysql
|
||||
- rabbitmq-server
|
||||
|
||||
dependencies:
|
||||
cache_directories:
|
||||
@@ -21,10 +22,13 @@ dependencies:
|
||||
- node_modules
|
||||
- ~/.composer
|
||||
pre:
|
||||
- sudo apt-get install librabbitmq-dev
|
||||
- pecl install amqp-1.4.0
|
||||
- yes '' | pecl install imagick
|
||||
- pecl install json
|
||||
- yes '' | pecl install zmq-beta
|
||||
- sed -i 's/^\(session.cache_limiter = \).*/\1""/' ~/.phpenv/versions/$(phpenv global)/etc/php.ini
|
||||
- npm rebuild node-sass
|
||||
override:
|
||||
- composer install --no-progress --no-interaction --optimize-autoloader
|
||||
post:
|
||||
@@ -32,7 +36,6 @@ dependencies:
|
||||
- if [[ ! -e elasticsearch-1.6.0 ]]; then wget --no-check-certificate https://download.elastic.co/elasticsearch/elasticsearch/elasticsearch-1.6.0.tar.gz && tar -xvf elasticsearch-1.6.0.tar.gz && elasticsearch-1.6.0/bin/plugin install elasticsearch/elasticsearch-analysis-icu/2.6.0; fi
|
||||
- elasticsearch-1.6.0/bin/elasticsearch: {background: true}
|
||||
|
||||
|
||||
database:
|
||||
override:
|
||||
- mysql -u ubuntu -e 'CREATE DATABASE update39_test;CREATE DATABASE ab_test;CREATE DATABASE db_test;SET @@global.sql_mode=STRICT_ALL_TABLES;SET @@global.max_allowed_packet=33554432;SET @@global.wait_timeout=999999;';
|
||||
@@ -46,5 +49,5 @@ database:
|
||||
|
||||
test:
|
||||
override:
|
||||
- case $CIRCLE_NODE_INDEX in 0) EXIT=0; php -d memory_limit=-1 bin/phpunit --log-junit $CIRCLE_TEST_REPORTS/phpunit/junit-unit.xml --exclude-group legacy || EXIT=$?; ./node_modules/.bin/gulp test || EXIT=$?; php -d memory_limit=-1 bin/phpunit --log-junit $CIRCLE_TEST_REPORTS/phpunit/junit-legacy-no-web.xml --group legacy --exclude-group web || EXIT=$?; exit $EXIT;; 1) php -d memory_limit=-1 bin/phpunit --log-junit $CIRCLE_TEST_REPORTS/phpunit/junit-legacy-web.xml --group web ;; esac:
|
||||
- case $CIRCLE_NODE_INDEX in 0) EXIT=0; php -d memory_limit=-1 bin/phpunit --log-junit $CIRCLE_TEST_REPORTS/phpunit/junit-unit.xml --exclude-group legacy || EXIT=$?; php -d memory_limit=-1 bin/phpunit --log-junit $CIRCLE_TEST_REPORTS/phpunit/junit-legacy-no-web.xml --group legacy --exclude-group web || EXIT=$?; exit $EXIT;; 1) php -d memory_limit=-1 bin/phpunit --log-junit $CIRCLE_TEST_REPORTS/phpunit/junit-legacy-web.xml --group web ;; esac:
|
||||
parallel: true
|
||||
|
@@ -22,10 +22,6 @@
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/alchemy-fr/JMSTranslationBundle"
|
||||
},
|
||||
{
|
||||
"type": "vcs",
|
||||
"url": "https://github.com/alchemy-fr/embed-bundle.git"
|
||||
},
|
||||
{
|
||||
"type": "git",
|
||||
"url": "https://github.com/bburnichon/fractal.git"
|
||||
@@ -35,7 +31,7 @@
|
||||
"php": ">=5.5.9",
|
||||
"ext-intl": "*",
|
||||
"alchemy-fr/tcpdf-clone": "~6.0",
|
||||
"alchemy/embed-bundle": "^0.3.2",
|
||||
"alchemy/embed-bundle": "^0.4.1",
|
||||
"alchemy/geonames-api-consumer": "~0.1.0",
|
||||
"alchemy/google-plus-api-client": "~0.6.2",
|
||||
"alchemy/mediavorus": "^0.4.4",
|
||||
@@ -104,11 +100,13 @@
|
||||
"vierbergenlars/php-semver": "~2.1",
|
||||
"webmozart/json": "^1.1",
|
||||
"willdurand/negotiation": "^2.0.0-alpha1",
|
||||
"zend/gdata": "~1.12.1"
|
||||
"zend/gdata": "~1.12.1",
|
||||
"alchemy/worker-bundle": "^0.1.5",
|
||||
"alchemy/queue-bundle": "^0.1.5"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.5",
|
||||
"mikey179/vfsStream": "~1.5"
|
||||
"mikey179/vfsStream": "~1.5",
|
||||
"phpunit/phpunit": "^4.8|^5.0"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
@@ -119,7 +117,7 @@
|
||||
"include-path": ["vendor/zend/gdata/library"],
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "4.0.x-dev"
|
||||
"dev-master": "4.1.x-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
1206
composer.lock
generated
1206
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -236,3 +236,16 @@ embed_bundle:
|
||||
document:
|
||||
player: flexpaper
|
||||
enable-pdfjs: true
|
||||
geocoding-providers:
|
||||
-
|
||||
name: 'mapBox'
|
||||
public-key: ''
|
||||
workers:
|
||||
queue:
|
||||
worker-queue:
|
||||
registry: alchemy_worker.queue_registry
|
||||
host: localhost
|
||||
port: 5672
|
||||
user: guest
|
||||
password: guest
|
||||
vhost: /
|
||||
|
@@ -73,6 +73,7 @@ use Alchemy\Phrasea\Core\Provider\TasksServiceProvider;
|
||||
use Alchemy\Phrasea\Core\Provider\TokensServiceProvider;
|
||||
use Alchemy\Phrasea\Core\Provider\UnicodeServiceProvider;
|
||||
use Alchemy\Phrasea\Core\Provider\WebhookServiceProvider;
|
||||
use Alchemy\Phrasea\Core\Provider\WorkerConfigurationServiceProvider;
|
||||
use Alchemy\Phrasea\Core\Provider\ZippyServiceProvider;
|
||||
use Alchemy\Phrasea\Core\Provider\WebProfilerServiceProvider as PhraseaWebProfilerServiceProvider;
|
||||
use Alchemy\Phrasea\Databox\Caption\CaptionServiceProvider;
|
||||
@@ -86,6 +87,8 @@ use Alchemy\Phrasea\Media\MediaAccessorResolver;
|
||||
use Alchemy\Phrasea\Media\PermalinkMediaResolver;
|
||||
use Alchemy\Phrasea\Media\TechnicalDataServiceProvider;
|
||||
use Alchemy\Phrasea\Model\Entities\User;
|
||||
use Alchemy\QueueProvider\QueueServiceProvider;
|
||||
use Alchemy\WorkerProvider\WorkerServiceProvider;
|
||||
use Doctrine\DBAL\Event\ConnectionEventArgs;
|
||||
use MediaVorus\Media\MediaInterface;
|
||||
use MediaVorus\MediaVorus;
|
||||
@@ -243,6 +246,10 @@ class Application extends SilexApplication
|
||||
$this->setupEventDispatcher();
|
||||
|
||||
$this->register(new DataboxServiceProvider());
|
||||
$this->register(new QueueServiceProvider());
|
||||
$this->register(new WorkerServiceProvider());
|
||||
$this->register(new WorkerConfigurationServiceProvider());
|
||||
|
||||
$this->register(new OrderServiceProvider());
|
||||
$this->register(new WebhookServiceProvider());
|
||||
|
||||
|
@@ -178,7 +178,7 @@ class GooglePlus extends AbstractProvider
|
||||
$token = @json_decode($this->client->getAccessToken(), true);
|
||||
|
||||
if (JSON_ERROR_NONE !== json_last_error()) {
|
||||
throw new NotAuthenticatedException('Unable to parse Google+ JSON', $e->getCode(), $e);
|
||||
throw new NotAuthenticatedException('Unable to parse Google+ JSON');
|
||||
}
|
||||
|
||||
$ticket = $this->client->verifyIdToken($token['id_token']);
|
||||
|
@@ -23,6 +23,7 @@ use Alchemy\Phrasea\Core\CLIProvider\DoctrineMigrationServiceProvider;
|
||||
use Alchemy\Phrasea\Core\CLIProvider\PluginServiceProvider;
|
||||
use Alchemy\Phrasea\Core\CLIProvider\SignalHandlerServiceProvider;
|
||||
use Alchemy\Phrasea\Core\CLIProvider\TaskManagerServiceProvider;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Debug\ErrorHandler;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
|
||||
@@ -72,6 +73,10 @@ class CLI extends Application
|
||||
|
||||
$this->bindRoutes();
|
||||
|
||||
$this['logger'] = $this->extend('logger', function () {
|
||||
return new Console\Logger\ConsoleLogger(new Console\Output\ConsoleOutput(Console\Output\ConsoleOutput::VERBOSITY_DEBUG));
|
||||
});
|
||||
|
||||
error_reporting(-1);
|
||||
ErrorHandler::register();
|
||||
PhraseaCLIExceptionHandler::register();
|
||||
@@ -87,6 +92,7 @@ class CLI extends Application
|
||||
$this->boot();
|
||||
|
||||
$app = $this['console'];
|
||||
|
||||
if ($interactive) {
|
||||
$app = new Console\Shell($app);
|
||||
}
|
||||
@@ -115,11 +121,14 @@ class CLI extends Application
|
||||
*
|
||||
* If a command with the same name already exists, it will be overridden.
|
||||
*
|
||||
* @param CommandInterface $command A Command object
|
||||
* @param Command|CommandInterface $command A Command object
|
||||
*/
|
||||
public function command(CommandInterface $command)
|
||||
public function command($command)
|
||||
{
|
||||
if ($command instanceof CommandInterface) {
|
||||
$command->setContainer($this);
|
||||
}
|
||||
|
||||
$this['console']->add($command);
|
||||
}
|
||||
|
||||
|
@@ -139,7 +139,6 @@ class CollectionService
|
||||
. "WHERE r.coll_id = :coll_id\n"
|
||||
. "AND r.type='image' AND s.name IN ('preview', 'document')";
|
||||
|
||||
|
||||
$params = [':coll_id' => $collection->getCollectionId()];
|
||||
|
||||
if ($record_id) {
|
||||
|
@@ -24,6 +24,8 @@ interface CommandInterface
|
||||
|
||||
/**
|
||||
* Factory for the command.
|
||||
*
|
||||
* @deprecated Will be removed in a future release.
|
||||
*/
|
||||
public static function create();
|
||||
}
|
||||
|
@@ -26,7 +26,7 @@ class Configuration extends Command
|
||||
protected function doExecute(InputInterface $input, OutputInterface $output)
|
||||
{
|
||||
$this->container['configuration.store']->compileAndWrite();
|
||||
$output->writeln("Confguration compiled.");
|
||||
$output->writeln("Configuration compiled.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -210,7 +210,7 @@ class FieldsController extends Controller
|
||||
$this->validateTagField($data);
|
||||
|
||||
try {
|
||||
$field = \databox_field::create($this->app, $databox, $data['name'], $data['multi']);
|
||||
$field = \databox_field::create($this->app, $databox, $data['name']);
|
||||
$this->updateFieldWithData($field, $data);
|
||||
$field->save();
|
||||
} catch (\Exception $e) {
|
||||
@@ -308,6 +308,7 @@ class FieldsController extends Controller
|
||||
->set_business($data['business'])
|
||||
->set_aggregable($data['aggregable'])
|
||||
->set_indexable($data['indexable'])
|
||||
->set_multi($data['multi'])
|
||||
->set_required($data['required'])
|
||||
->set_separator($data['separator'])
|
||||
->set_readonly($data['readonly'])
|
||||
|
@@ -11,6 +11,7 @@
|
||||
namespace Alchemy\Phrasea\Controller\Admin;
|
||||
|
||||
use Alchemy\Phrasea\Controller\Controller;
|
||||
use Alchemy\Phrasea\Databox\SubdefGroup;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
@@ -25,7 +26,7 @@ class SubdefsController extends Controller
|
||||
|
||||
return $this->render('admin/subdefs.html.twig', [
|
||||
'databox' => $databox,
|
||||
'subdefs' => $databox->get_subdef_structure()
|
||||
'subdefs' => $databox->get_subdef_structure(),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -70,6 +71,8 @@ class SubdefsController extends Controller
|
||||
} else {
|
||||
$subdefs = $databox->get_subdef_structure();
|
||||
|
||||
$this->updateSubdefGroups($subdefs, $request);
|
||||
|
||||
foreach ($Parmsubdefs as $post_sub) {
|
||||
$options = [];
|
||||
|
||||
@@ -80,6 +83,7 @@ class SubdefsController extends Controller
|
||||
|
||||
$class = $request->request->get($post_sub . '_class');
|
||||
$downloadable = $request->request->get($post_sub . '_downloadable');
|
||||
$orderable = $request->request->get($post_sub . '_orderable');
|
||||
|
||||
$defaults = ['path', 'meta', 'mediatype'];
|
||||
|
||||
@@ -107,7 +111,7 @@ class SubdefsController extends Controller
|
||||
|
||||
$labels = $request->request->get($post_sub . '_label', []);
|
||||
|
||||
$subdefs->set_subdef($group, $name, $class, $downloadable, $options, $labels);
|
||||
$subdefs->set_subdef($group, $name, $class, $downloadable, $options, $labels, $orderable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,4 +119,37 @@ class SubdefsController extends Controller
|
||||
'sbas_id' => $databox->get_sbas_id(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update Databox subdefsStructure DOM according to defined groups.
|
||||
*
|
||||
* @param \databox_subdefsStructure $subdefs
|
||||
* @param Request $request
|
||||
*/
|
||||
private function updateSubdefGroups(\databox_subdefsStructure $subdefs, Request $request)
|
||||
{
|
||||
$subdefsGroups = $request->request->get('subdefsgroups', []);
|
||||
$changedGroups = [];
|
||||
|
||||
/** @var SubdefGroup $subdefsGroup */
|
||||
foreach ($subdefs as $groupName => $subdefsGroup) {
|
||||
$documentOrderable = isset($subdefsGroups[$groupName]['document_orderable'])
|
||||
? \p4field::isyes($subdefsGroups[$groupName]['document_orderable'])
|
||||
: false;
|
||||
|
||||
if ($subdefsGroup->isDocumentOrderable() !== $documentOrderable) {
|
||||
if ($documentOrderable) {
|
||||
$subdefsGroup->allowDocumentOrdering();
|
||||
} else {
|
||||
$subdefsGroup->disallowDocumentOrdering();
|
||||
}
|
||||
|
||||
$changedGroups[] = $subdefsGroup;
|
||||
}
|
||||
}
|
||||
|
||||
if ($changedGroups) {
|
||||
$subdefs->updateSubdefGroups($changedGroups);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -8,10 +8,12 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
namespace Alchemy\Phrasea\Controller\Api;
|
||||
|
||||
use Alchemy\Phrasea\Controller\Controller;
|
||||
use Alchemy\Phrasea\Model\Manipulator\LazaretManipulator;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class LazaretController extends Controller
|
||||
{
|
||||
/**
|
||||
@@ -23,7 +25,9 @@ class LazaretController extends Controller
|
||||
{
|
||||
/** @var LazaretManipulator $lazaretManipulator */
|
||||
$lazaretManipulator = $this->app['manipulator.lazaret'];
|
||||
|
||||
$ret = $lazaretManipulator->deny($lazaret_id);
|
||||
|
||||
return Result::create($request, $ret)->createResponse();
|
||||
}
|
||||
|
||||
@@ -31,7 +35,9 @@ class LazaretController extends Controller
|
||||
{
|
||||
/** @var LazaretManipulator $lazaretManipulator */
|
||||
$lazaretManipulator = $this->app['manipulator.lazaret'];
|
||||
|
||||
$ret = $lazaretManipulator->add($lazaret_id);
|
||||
|
||||
return Result::create($request, $ret)->createResponse();
|
||||
}
|
||||
|
||||
@@ -44,9 +50,12 @@ class LazaretController extends Controller
|
||||
if( $maxTodo <= 0) {
|
||||
$maxTodo = -1; // all
|
||||
}
|
||||
|
||||
/** @var LazaretManipulator $lazaretManipulator */
|
||||
$lazaretManipulator = $this->app['manipulator.lazaret'];
|
||||
|
||||
$ret = $lazaretManipulator->clear($maxTodo);
|
||||
|
||||
return Result::create($request, $ret)->createResponse();
|
||||
}
|
||||
}
|
@@ -85,6 +85,7 @@ use Alchemy\Phrasea\Status\StatusStructure;
|
||||
use Alchemy\Phrasea\TaskManager\LiveInformation;
|
||||
use Alchemy\Phrasea\Utilities\NullableDateTime;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
|
||||
use JMS\TranslationBundle\Annotation\Ignore;
|
||||
use League\Fractal\Resource\Item;
|
||||
use Symfony\Component\Form\Form;
|
||||
|
@@ -42,11 +42,7 @@ class LightboxController extends Controller
|
||||
$repository->findActiveValidationByUser($this->getAuthenticatedUser())
|
||||
);
|
||||
|
||||
$template = $this->isBrowserNewGenerationOrMobile()
|
||||
? 'lightbox/index.html.twig'
|
||||
: 'lightbox/IE6/index.html.twig';
|
||||
|
||||
return $this->renderResponse($template, [
|
||||
return $this->renderResponse('lightbox/index.html.twig', [
|
||||
'baskets_collection' => $basket_collection,
|
||||
'module_name' => 'Lightbox',
|
||||
'module' => 'lightbox',
|
||||
@@ -92,7 +88,6 @@ class LightboxController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
$isNewGenerationBrowser = $this->app['browser']->isNewGeneration();
|
||||
$basket = $basketElement->getBasket();
|
||||
|
||||
$ret = [];
|
||||
@@ -104,11 +99,11 @@ class LightboxController extends Controller
|
||||
['record' => $basketElement->getRecord($this->app), 'not_wrapped' => true]
|
||||
);
|
||||
$ret['options_html'] = $this->render(
|
||||
$isNewGenerationBrowser ? 'lightbox/sc_options_box.html.twig' : 'lightbox/IE6/sc_options_box.html.twig',
|
||||
'lightbox/sc_options_box.html.twig',
|
||||
['basket_element' => $basketElement]
|
||||
);
|
||||
$ret['agreement_html'] = $this->render(
|
||||
$isNewGenerationBrowser ? 'lightbox/agreement_box.html.twig' : 'lightbox/IE6/agreement_box.html.twig',
|
||||
'lightbox/agreement_box.html.twig',
|
||||
['basket' => $basket, 'basket_element' => $basketElement]
|
||||
);
|
||||
$ret['selector_html'] = $this->render('lightbox/selector_box.html.twig', ['basket_element' => $basketElement]);
|
||||
@@ -149,10 +144,7 @@ class LightboxController extends Controller
|
||||
'record' => $record,
|
||||
'not_wrapped' => true,
|
||||
]);
|
||||
$template_options = $browser->isNewGeneration()
|
||||
? 'lightbox/feed_options_box.html.twig'
|
||||
: 'lightbox/IE6/feed_options_box.html.twig';
|
||||
$ret['options_html'] = $this->render($template_options, ['feed_element' => $item]);
|
||||
$ret['options_html'] = $this->render('lightbox/feed_options_box.html.twig', ['feed_element' => $item]);
|
||||
$ret['caption'] = $this->render(
|
||||
'common/caption.html.twig', [
|
||||
'view' => 'preview',
|
||||
@@ -242,24 +234,12 @@ class LightboxController extends Controller
|
||||
return $basket;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
private function isBrowserNewGenerationOrMobile()
|
||||
{
|
||||
/** @var \Browser $browser */
|
||||
$browser = $this->app['browser'];
|
||||
return $browser->isNewGeneration() || $browser->isMobile();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
private function getValidationTemplate()
|
||||
{
|
||||
return $this->isBrowserNewGenerationOrMobile()
|
||||
? 'lightbox/validate.html.twig'
|
||||
: 'lightbox/IE6/validate.html.twig';
|
||||
return 'lightbox/validate.html.twig';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -300,14 +280,10 @@ class LightboxController extends Controller
|
||||
/** @var FeedEntry $feed_entry */
|
||||
$feed_entry = $app['repo.feed-entries']->find($entry_id);
|
||||
|
||||
$template = $this->isBrowserNewGenerationOrMobile()
|
||||
? 'lightbox/feed.html.twig'
|
||||
: 'lightbox/IE6/feed.html.twig';
|
||||
|
||||
$content = $feed_entry->getItems();
|
||||
$first = $content->first();
|
||||
|
||||
$response = $this->renderResponse($template, [
|
||||
$response = $this->renderResponse('lightbox/feed.html.twig', [
|
||||
'feed_entry' => $feed_entry,
|
||||
'first_item' => $first,
|
||||
'local_title' => $feed_entry->getTitle(),
|
||||
|
@@ -22,6 +22,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\Twig\PhraseanetExtension;
|
||||
use Alchemy\Phrasea\Vocabulary\ControlProvider\ControlProviderInterface;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
@@ -156,7 +157,9 @@ class EditController extends Controller
|
||||
];
|
||||
|
||||
$elements[$indice]['statbits'] = [];
|
||||
$elements[$indice]['editableStatus'] = false;
|
||||
if ($this->getAclForUser()->has_right_on_base($record->getBaseId(), 'chgstatus')) {
|
||||
$elements[$indice]['editableStatus'] = true;
|
||||
foreach ($status as $n => $s) {
|
||||
$tmp_val = substr(strrev($record->getStatus()), $n, 1);
|
||||
$elements[$indice]['statbits'][$n]['value'] = ($tmp_val == '1') ? '1' : '0';
|
||||
@@ -206,18 +209,21 @@ class EditController extends Controller
|
||||
'h' => $thumbnail->get_height(),
|
||||
];
|
||||
|
||||
$elements[$indice]['preview'] = $this->render(
|
||||
$elements[$indice]['template'] = $this->render(
|
||||
'common/preview.html.twig',
|
||||
['record' => $record]
|
||||
['record' => $record, 'not_wrapped' => true]
|
||||
);
|
||||
|
||||
$elements[$indice]['data'] = $this->getRecordElementData($record);
|
||||
|
||||
$elements[$indice]['type'] = $record->getType();
|
||||
}
|
||||
}
|
||||
|
||||
$conf = $this->getConf();
|
||||
$params = [
|
||||
'multipleDataboxes' => $multipleDataboxes,
|
||||
'recordsRequest' => $records,
|
||||
'videoEditorConfig' => $conf->get(['video-editor']),
|
||||
'databox' => $databox,
|
||||
'JSonStatus' => json_encode($status),
|
||||
'JSonRecords' => json_encode($elements),
|
||||
@@ -529,4 +535,35 @@ class EditController extends Controller
|
||||
return $this->app['manipulator.preset'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \record_adapter $record
|
||||
* @return array
|
||||
*/
|
||||
private function getRecordElementData($record) {
|
||||
$helpers = new PhraseanetExtension($this->app);
|
||||
$recordData = [
|
||||
'databoxId' => $record->getBaseId(),
|
||||
'id' => $record->getId(),
|
||||
'isGroup' => $record->isStory(),
|
||||
'url' => (string)$helpers->getThumbnailUrl($record),
|
||||
];
|
||||
$userHaveAccess = $this->app->getAclForUser($this->getAuthenticatedUser())->has_access_to_subdef($record, 'preview');
|
||||
if ($userHaveAccess) {
|
||||
$recordPreview = $record->get_preview();
|
||||
} else {
|
||||
$recordPreview = $record->get_thumbnail();
|
||||
}
|
||||
|
||||
$recordData['preview'] = [
|
||||
'width' => $recordPreview->get_width(),
|
||||
'height' => $recordPreview->get_height(),
|
||||
'url' => $this->app->url('alchemy_embed_view', [
|
||||
'url' => (string)($this->getAuthenticatedUser() ? $recordPreview->get_url() : $recordPreview->get_permalink()->get_url()),
|
||||
'autoplay' => false
|
||||
])
|
||||
];
|
||||
|
||||
return $recordData;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -148,7 +148,7 @@ class FeedController extends Controller
|
||||
$entry->setFeed($new_feed);
|
||||
}
|
||||
|
||||
$items = explode(';', $request->request->get('sorted_lst'));
|
||||
$items = explode(';', $request->request->get('lst'));
|
||||
|
||||
$item_repository = $this->getFeedItemRepository();
|
||||
$manager = $this->getEntityManager();
|
||||
@@ -167,7 +167,7 @@ class FeedController extends Controller
|
||||
|
||||
return $this->app->json([
|
||||
'error' => false,
|
||||
'message' => 'succes',
|
||||
'message' => 'success',
|
||||
'datas' => $this->render('prod/results/entry.html.twig', ['entry' => $entry]),
|
||||
]);
|
||||
}
|
||||
|
@@ -111,6 +111,39 @@ class LanguageController
|
||||
'toolbox' => $translator->trans('Tool box'),
|
||||
'print' => $translator->trans('Print'),
|
||||
'attention' => $translator->trans('Attention !'),
|
||||
'mapMarkerEdit' => $translator->trans('Edit position'),
|
||||
'mapMarkerAdd' => $translator->trans('Add a position'),
|
||||
'mapMarkerMoveLabel' => $translator->trans('Drag and drop the pin to move position'),
|
||||
'mapMarkerEditCancel' => $translator->trans('Cancel'),
|
||||
'mapMarkerEditSubmit' => $translator->trans('Submit'),
|
||||
'Keyboard shortcuts' => $translator->trans('Keyboard shortcuts'),
|
||||
'Play' => $translator->trans('Play'),
|
||||
'Change play speed' => $translator->trans('Change play speed'),
|
||||
'Pause' => $translator->trans('Pause'),
|
||||
'One frame forward' => $translator->trans('One frame forward'),
|
||||
'One frame backward' => $translator->trans('One frame backward'),
|
||||
'Add an entry point' => $translator->trans('Add an entry point'),
|
||||
'Add an end point' => $translator->trans('Add an end point'),
|
||||
'Navigate to entry point' => $translator->trans('Navigate to entry point'),
|
||||
'Navigate to end point' => $translator->trans('Navigate to end point'),
|
||||
'Delete current' => $translator->trans('Delete current'),
|
||||
'Toggle loop' => $translator->trans('Toggle loop'),
|
||||
'Shift' => $translator->trans('Shift'),
|
||||
'Ctrl' => $translator->trans('Ctrl'),
|
||||
'Space bar' => $translator->trans('Space bar'),
|
||||
'or' => $translator->trans('or'),
|
||||
'Suppr' => $translator->trans('Suppr'),
|
||||
'Add new range' => $translator->trans('Add new range'),
|
||||
'Export ranges' => $translator->trans('Export ranges'),
|
||||
'Start Range' => $translator->trans('Start Range'),
|
||||
'End Range' => $translator->trans('End Range'),
|
||||
'Remove current Range' => $translator->trans('Remove current Range'),
|
||||
'Go to start point' => $translator->trans('Go to start point'),
|
||||
'Go 1 frame backward' => $translator->trans('Go 1 frame backward'),
|
||||
'Go 1 frame forward' => $translator->trans('Go 1 frame forward'),
|
||||
'Go to end point' => $translator->trans('Go to end point'),
|
||||
'Move up range' => $translator->trans('Move up range'),
|
||||
'Move down range' => $translator->trans('Move down range'),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
@@ -16,14 +16,11 @@ use Alchemy\Phrasea\Application\Helper\EntityManagerAware;
|
||||
use Alchemy\Phrasea\Application\Helper\FilesystemAware;
|
||||
use Alchemy\Phrasea\Application\Helper\SubDefinitionSubstituerAware;
|
||||
use Alchemy\Phrasea\Border;
|
||||
use Alchemy\Phrasea\Border\Attribute\AttributeInterface;
|
||||
use Alchemy\Phrasea\Controller\Controller;
|
||||
use Alchemy\Phrasea\Http\DeliverDataInterface;
|
||||
use Alchemy\Phrasea\Media\SubdefSubstituer;
|
||||
use Alchemy\Phrasea\Model\Entities\LazaretFile;
|
||||
use Alchemy\Phrasea\Model\Manipulator\LazaretManipulator;
|
||||
use Alchemy\Phrasea\Model\Repositories\LazaretFileRepository;
|
||||
use PHPExiftool\Driver\Metadata\Metadata;
|
||||
use Symfony\Component\Filesystem\Exception\IOException;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
@@ -23,15 +23,34 @@ class MoveCollectionController extends Controller
|
||||
return $databox->get_sbas_id();
|
||||
}, $records->databoxes());
|
||||
|
||||
$message = '';
|
||||
$template = '';
|
||||
$collections = $this->getAclForUser()->get_granted_base(['canaddrecord'], $sbas_ids);
|
||||
|
||||
if (count($records->databoxes()) > 1) {
|
||||
$success = false;
|
||||
$message = $this->app->trans('prod::Les enregistrements ne provienent pas tous de la meme base et ne peuvent donc etre traites ensemble');
|
||||
} elseif (count($records) == 0) {
|
||||
$success = false;
|
||||
$message = $this->app->trans('prod::Vous n\'avez le droit d\'effectuer l\'operation sur aucun document');
|
||||
} else {
|
||||
// is able to move:
|
||||
$success = true;
|
||||
$parameters = [
|
||||
'records' => $records,
|
||||
'message' => '',
|
||||
'collections' => $collections,
|
||||
];
|
||||
$template = $this->render('prod/actions/collection_default.html.twig', $parameters);
|
||||
}
|
||||
|
||||
return $this->render('prod/actions/collection_default.html.twig', $parameters);
|
||||
$datas = [
|
||||
'success' => $success,
|
||||
'message' => $message,
|
||||
'template' => $template
|
||||
];
|
||||
|
||||
return $this->app->json($datas);
|
||||
}
|
||||
|
||||
public function apply(Request $request)
|
||||
|
@@ -97,41 +97,41 @@ class QueryController extends Controller
|
||||
}
|
||||
for ($i = 1; ($i <= 4 && (($i <= $npages) === true)); $i++) {
|
||||
if ($i == $page)
|
||||
$string .= '<input onkeypress="if(event.keyCode == 13 && !isNaN(parseInt(this.value)))gotopage(parseInt(this.value))" type="text" value="' . $i . '" size="' . (strlen((string) $i)) . '" class="btn btn-mini" />';
|
||||
$string .= '<input type="text" value="' . $i . '" size="' . (strlen((string) $i)) . '" class="btn btn-mini search-navigate-input-action" data-initial-value="' . $i . '" data-total-pages="'.$npages.'"/>';
|
||||
else
|
||||
$string .= "<a onclick='gotopage(" . $i . ");return false;' class='btn btn-primary btn-mini'>" . $i . "</a>";
|
||||
$string .= '<a class="btn btn-primary btn-mini search-navigate-action" data-page="'.$i.'">' . $i . '</a>';
|
||||
}
|
||||
if ($npages > 4)
|
||||
$string .= "<a id='NEXT_PAGE' class='btn btn-primary btn-mini'></a>";
|
||||
$string .= "<a onclick='gotopage(" . ($npages) . ");return false;' class='btn btn-primary btn-mini' id='last'></a>";
|
||||
$string .= '<a href="#" class="btn btn-primary btn-mini search-navigate-action" data-page="' . $npages . '" id="last"></a>';
|
||||
} else {
|
||||
$start = $npages - 4;
|
||||
if (($start) > 0){
|
||||
$string .= "<a onclick='gotopage(1);return false;' class='btn btn-primary btn-mini' id='first'></a>";
|
||||
$string .= "<a id='PREV_PAGE' class='btn btn-primary btn-mini'></a>";
|
||||
$string .= '<a class="btn btn-primary btn-mini search-navigate-action" data-page="1" id="first"></a>';
|
||||
$string .= '<a id="PREV_PAGE" class="btn btn-primary btn-mini"></a>';
|
||||
}else
|
||||
$start = 1;
|
||||
for ($i = ($start); $i <= $npages; $i++) {
|
||||
if ($i == $page)
|
||||
$string .= '<input onkeypress="if(event.keyCode == 13 && !isNaN(parseInt(this.value)))gotopage(parseInt(this.value))" type="text" value="' . $i . '" size="' . (strlen((string) $i)) . '" class="btn btn-mini" />';
|
||||
$string .= '<input type="text" value="' . $i . '" size="' . (strlen((string) $i)) . '" class="btn btn-mini search-navigate-input-action" data-initial-value="' . $i . '" data-total-pages="'.$npages.'" />';
|
||||
else
|
||||
$string .= "<a onclick='gotopage(" . $i . ");return false;' class='btn btn-primary btn-mini'>" . $i . "</a>";
|
||||
$string .= '<a class="btn btn-primary btn-mini search-navigate-action" data-page="'.$i.'">' . $i . '</a>';
|
||||
}
|
||||
if($page < $npages){
|
||||
$string .= "<a id='NEXT_PAGE' class='btn btn-primary btn-mini'></a>";
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$string .= "<a onclick='gotopage(1);return false;' class='btn btn-primary btn-mini' id='first'></a>";
|
||||
$string .= '<a class="btn btn-primary btn-mini btn-mini search-navigate-action" data-page="1" id="first"></a>';
|
||||
|
||||
for ($i = ($page - 2); $i <= ($page + 2); $i++) {
|
||||
if ($i == $page)
|
||||
$string .= '<input onkeypress="if(event.keyCode == 13 && !isNaN(parseInt(this.value)))gotopage(parseInt(this.value))" type="text" value="' . $i . '" size="' . (strlen((string) $i)) . '" class="btn btn-mini" />';
|
||||
$string .= '<input type="text" value="' . $i . '" size="' . (strlen((string) $i)) . '" class="btn btn-mini search-navigate-input-action" data-initial-value="' . $i . '" data-total-pages="'.$npages.'" />';
|
||||
else
|
||||
$string .= "<a onclick='gotopage(" . $i . ");return false;' class='btn btn-primary btn-mini'>" . $i . "</a>";
|
||||
$string .= '<a class="btn btn-primary btn-mini search-navigate-action" data-page="'.$i.'">' . $i . '</a>';
|
||||
}
|
||||
|
||||
$string .= "<a onclick='gotopage(" . ($npages) . ");return false;' class='btn btn-primary btn-mini' id='last'></a>";
|
||||
$string .= '<a href="#" class="btn btn-primary btn-mini search-navigate-action" data-page="' . $npages . '" id="last"></a>';
|
||||
}
|
||||
}
|
||||
$string .= '<div style="display:none;"><div id="NEXT_PAGE"></div><div id="PREV_PAGE"></div></div>';
|
||||
@@ -152,7 +152,7 @@ class QueryController extends Controller
|
||||
|
||||
$infoResult = '<div id="docInfo">'
|
||||
. $this->app->trans('%number% documents<br/>selectionnes', ['%number%' => '<span id="nbrecsel"></span>'])
|
||||
. '</div><a href="#" class="infoDialog" infos="' . str_replace('"', '"', $explain) . '">'
|
||||
. '</div><a href="#" class="infoDialog search-display-info" data-infos="' . str_replace('"', '"', $explain) . '">'
|
||||
. $this->app->trans('%total% reponses', ['%total%' => '<span>'.$result->getTotal().'</span>']) . '</a>';
|
||||
|
||||
$json['infos'] = $infoResult;
|
||||
|
@@ -14,9 +14,12 @@ use Alchemy\Phrasea\Application\Helper\EntityManagerAware;
|
||||
use Alchemy\Phrasea\Application\Helper\SearchEngineAware;
|
||||
use Alchemy\Phrasea\Controller\Controller;
|
||||
use Alchemy\Phrasea\Controller\RecordsRequest;
|
||||
use Alchemy\Phrasea\Model\Entities\BasketElement;
|
||||
use Alchemy\Phrasea\Model\Repositories\BasketElementRepository;
|
||||
use Alchemy\Phrasea\Model\Repositories\StoryWZRepository;
|
||||
use Alchemy\Phrasea\SearchEngine\SearchEngineOptions;
|
||||
use Alchemy\Phrasea\Twig\Fit;
|
||||
use Alchemy\Phrasea\Twig\PhraseanetExtension;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
@@ -68,16 +71,20 @@ class RecordController extends Controller
|
||||
$options
|
||||
);
|
||||
|
||||
$currentRecord = $this->getContainerResult($record);
|
||||
|
||||
if ($record->is_from_reg()) {
|
||||
$train = $this->render('prod/preview/reg_train.html.twig', ['record' => $record]);
|
||||
}
|
||||
|
||||
if ($record->is_from_basket() && $reloadTrain) {
|
||||
} else if ($record->is_from_basket() && $reloadTrain) {
|
||||
$train = $this->render('prod/preview/basket_train.html.twig', ['record' => $record]);
|
||||
} else if ($record->is_from_feed()) {
|
||||
$train = $this->render('prod/preview/feed_train.html.twig', ['record' => $record]);
|
||||
}
|
||||
|
||||
if ($record->is_from_feed()) {
|
||||
$train = $this->render('prod/preview/feed_train.html.twig', ['record' => $record]);
|
||||
$recordCaptions = [];
|
||||
foreach ($record->get_caption()->get_fields(null, true) as $field) {
|
||||
// get field's values
|
||||
$recordCaptions[$field->get_name()] = $field->get_serialized_values();
|
||||
}
|
||||
|
||||
return $this->app->json([
|
||||
@@ -87,6 +94,7 @@ class RecordController extends Controller
|
||||
'searchEngine' => $searchEngine,
|
||||
'searchOptions' => $options,
|
||||
]),
|
||||
"recordCaptions"=> $recordCaptions,
|
||||
"html_preview" => $this->render('common/preview.html.twig', [
|
||||
'record' => $record
|
||||
]),
|
||||
@@ -95,6 +103,7 @@ class RecordController extends Controller
|
||||
'baskets' => $record->get_container_baskets($this->getEntityManager(), $this->getAuthenticatedUser()),
|
||||
]),
|
||||
"current" => $train,
|
||||
"record" => $currentRecord,
|
||||
"history" => $this->render('prod/preview/short_history.html.twig', [
|
||||
'record' => $record,
|
||||
]),
|
||||
@@ -209,4 +218,38 @@ class RecordController extends Controller
|
||||
{
|
||||
return $this->app['repo.story-wz'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \record_preview $recordContainer
|
||||
* @return array
|
||||
*/
|
||||
private function getContainerResult(\record_preview $recordContainer)
|
||||
{
|
||||
/* @var $recordPreview \media_subdef */
|
||||
$helpers = new PhraseanetExtension($this->app);
|
||||
|
||||
$recordData = [
|
||||
'databoxId' => $recordContainer->getBaseId(),
|
||||
'id' => $recordContainer->getId(),
|
||||
'isGroup' => $recordContainer->isStory(),
|
||||
'url' => (string)$helpers->getThumbnailUrl($recordContainer),
|
||||
];
|
||||
$userHaveAccess = $this->app->getAclForUser($this->getAuthenticatedUser())->has_access_to_subdef($recordContainer, 'preview');
|
||||
if ($userHaveAccess) {
|
||||
$recordPreview = $recordContainer->get_preview();
|
||||
} else {
|
||||
$recordPreview = $recordContainer->get_thumbnail();
|
||||
}
|
||||
|
||||
$recordData['preview'] = [
|
||||
'width' => $recordPreview->get_width(),
|
||||
'height' => $recordPreview->get_height(),
|
||||
'url' => $this->app->url('alchemy_embed_view', [
|
||||
'url' => (string)($this->getAuthenticatedUser() ? $recordPreview->get_url() : $recordPreview->get_permalink()->get_url()),
|
||||
'autoplay' => false
|
||||
])
|
||||
];
|
||||
|
||||
return $recordData;
|
||||
}
|
||||
}
|
||||
|
@@ -45,29 +45,12 @@ class RootController extends Controller
|
||||
return $this->app->redirectPath('logout');
|
||||
}
|
||||
|
||||
$cssPath = $this->app['root.path'] . '/www/assets/prod/skins';
|
||||
|
||||
$css = [];
|
||||
|
||||
$finder = new Finder();
|
||||
/** @var SplFileInfo[] $iterator */
|
||||
$iterator = $finder
|
||||
->directories()
|
||||
->depth(0)
|
||||
->filter(function (\SplFileInfo $fileinfo) {
|
||||
return ctype_xdigit($fileinfo->getBasename());
|
||||
})
|
||||
->in($cssPath);
|
||||
|
||||
foreach ($iterator as $dir) {
|
||||
$baseName = $dir->getBaseName();
|
||||
$css[$baseName] = $baseName;
|
||||
}
|
||||
|
||||
$user = $this->getAuthenticatedUser();
|
||||
$cssfile = $this->getSettings()->getUserSetting($user, 'css');
|
||||
|
||||
if (!$cssfile && isset($css['000000'])) {
|
||||
if (!$cssfile) {
|
||||
$cssfile = '000000';
|
||||
}
|
||||
|
||||
@@ -76,14 +59,7 @@ class RootController extends Controller
|
||||
|
||||
$thjslist = "";
|
||||
|
||||
$queries_topics = '';
|
||||
|
||||
$conf = $this->getConf();
|
||||
if ($conf->get(['registry', 'classic', 'render-topics']) == 'popups') {
|
||||
$queries_topics = \queries::dropdown_topics($this->app['translator'], $this->app['locale']);
|
||||
} elseif ($conf->get(['registry', 'classic', 'render-topics']) == 'tree') {
|
||||
$queries_topics = \queries::tree_topics($this->app['locale']);
|
||||
}
|
||||
|
||||
$sbas = $bas2sbas = [];
|
||||
|
||||
@@ -126,13 +102,11 @@ class RootController extends Controller
|
||||
'GV_multiAndReport' => $conf->get(['registry', 'modules', 'stories']),
|
||||
'GV_thesaurus' => $conf->get(['registry', 'modules', 'thesaurus']),
|
||||
'cgus_agreement' => \databox_cgu::askAgreement($this->app),
|
||||
'css' => $css,
|
||||
'feeds' => $feeds,
|
||||
'aggregate' => $aggregate,
|
||||
'GV_google_api' => $conf->get(['registry', 'webservices', 'google-charts-enabled']),
|
||||
'queries_topics' => $queries_topics,
|
||||
'geocodingProviders' => $conf->get(['geocoding-providers']),
|
||||
'search_status' => \databox_status::getSearchStatus($this->app),
|
||||
'queries_history' => \queries::history($this->app, $user->getId()),
|
||||
'thesau_js_list' => $thjslist,
|
||||
'thesau_json_sbas' => json_encode($sbas),
|
||||
'thesau_json_bas2sbas' => json_encode($bas2sbas),
|
||||
|
@@ -95,10 +95,12 @@ class ToolsController extends Controller
|
||||
}
|
||||
}
|
||||
}
|
||||
$conf = $this->getConf();
|
||||
|
||||
return $this->render('prod/actions/Tools/index.html.twig', [
|
||||
'records' => $records,
|
||||
'record' => $record,
|
||||
'videoEditorConfig' => $conf->get(['video-editor']),
|
||||
'recordSubdefs' => $recordAccessibleSubdefs,
|
||||
'metadatas' => $metadata,
|
||||
]);
|
||||
|
@@ -19,6 +19,7 @@ use Alchemy\Phrasea\Model\Manipulator\ApiOauthTokenManipulator;
|
||||
use Alchemy\Phrasea\Model\Repositories\ApiAccountRepository;
|
||||
use Alchemy\Phrasea\Model\Repositories\ApiApplicationRepository;
|
||||
use Alchemy\Phrasea\Model\Repositories\ApiOauthTokenRepository;
|
||||
use Alchemy\Phrasea\Model\Repositories\WebhookEventDeliveryRepository;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
@@ -244,8 +245,12 @@ class DeveloperController extends Controller
|
||||
throw new AccessDeniedHttpException();
|
||||
}
|
||||
|
||||
$deliveries = $this->getWebhookDeliveryRepository()
|
||||
->findLastDeliveries($account->getApplication(), 10);
|
||||
|
||||
return $this->render('developers/application.html.twig', [
|
||||
"application" => $application,
|
||||
"deliveries" => $deliveries,
|
||||
"user" => $user,
|
||||
"token" => $token,
|
||||
]);
|
||||
@@ -298,4 +303,12 @@ class DeveloperController extends Controller
|
||||
{
|
||||
return $this->app['repo.api-applications'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return WebhookEventDeliveryRepository
|
||||
*/
|
||||
private function getWebhookDeliveryRepository()
|
||||
{
|
||||
return $this->app['webhook.delivery_repository'];
|
||||
}
|
||||
}
|
||||
|
@@ -1294,6 +1294,8 @@ class ThesaurusXmlHttpController extends Controller
|
||||
|
||||
public function replaceCandidateJson(Request $request)
|
||||
{
|
||||
$tsbas = [];
|
||||
|
||||
$ret = [
|
||||
'ctermsDeleted' => [],
|
||||
'maxRecsUpdatable' => self::SEARCH_REPLACE_MAXREC,
|
||||
@@ -1302,48 +1304,158 @@ class ThesaurusXmlHttpController extends Controller
|
||||
'msg' => ''
|
||||
];
|
||||
|
||||
// group ids by base
|
||||
$tsbas = [];
|
||||
foreach ($request->get('id') as $id) {
|
||||
$id = explode('.', $id);
|
||||
$sbas_id = array_shift($id);
|
||||
if (!array_key_exists($sbas_id, $tsbas)) {
|
||||
$tsbas[$sbas_id] = [];
|
||||
if (!array_key_exists('b' . $sbas_id, $tsbas)) {
|
||||
$tsbas['b' . $sbas_id] = [
|
||||
'sbas_id' => (int) $sbas_id,
|
||||
'tids' => [],
|
||||
'domct' => null,
|
||||
'tvals' => [],
|
||||
'lid' => '',
|
||||
'trids' => []
|
||||
];
|
||||
}
|
||||
$tsbas[$sbas_id][] = implode('.', $id);
|
||||
$tsbas['b' . $sbas_id]['tids'][] = implode('.', $id);
|
||||
}
|
||||
|
||||
// loop on bases
|
||||
foreach ($tsbas as $sbas_id => $sbas) {
|
||||
// first, count the number of records to update
|
||||
foreach ($tsbas as $ksbas => $sbas) {
|
||||
try {
|
||||
$databox = $this->findDataboxById($sbas_id);
|
||||
$domct = $databox->get_dom_cterms();
|
||||
$databox = $this->findDataboxById($sbas['sbas_id']);
|
||||
$connbas = $databox->get_connection();
|
||||
$tsbas[$ksbas]['domct'] = $databox->get_dom_cterms();
|
||||
} catch (\Exception $e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!$domct) {
|
||||
if (!$tsbas[$ksbas]['domct']) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$domct_changed = false;
|
||||
$xpathct = new \DOMXPath($domct);
|
||||
$lids = [];
|
||||
$xpathct = new \DOMXPath($tsbas[$ksbas]['domct']);
|
||||
|
||||
foreach ($sbas as $tid) {
|
||||
foreach ($sbas['tids'] as $tid) {
|
||||
$xp = '//te[@id="' . $tid . '"]/sy';
|
||||
$nodes = $xpathct->query($xp);
|
||||
if ($nodes->length == 1) {
|
||||
$sy = $nodes->item(0);
|
||||
$te = $sy->parentNode;
|
||||
$ret['ctermsDeleted'][] = $sbas_id . '.' . $te->getAttribute('id');
|
||||
$te->parentNode->removeChild($te);
|
||||
$domct_changed = true;
|
||||
$syid = str_replace('.', 'd', $sy->getAttribute('id')) . 'd';
|
||||
$lids[] = $syid;
|
||||
$field = $sy->parentNode->parentNode->getAttribute('field');
|
||||
|
||||
if (!array_key_exists($field, $tsbas[$ksbas]['tvals'])) {
|
||||
$tsbas[$ksbas]['tvals'][$field] = [];
|
||||
}
|
||||
$tsbas[$ksbas]['tvals'][$field][] = $sy;
|
||||
}
|
||||
}
|
||||
|
||||
if ($domct_changed && !$request->get('debug')) {
|
||||
$databox->saveCterms($domct);
|
||||
if (empty($lids)) {
|
||||
// no cterm was found
|
||||
continue;
|
||||
}
|
||||
$tsbas[$ksbas]['lid'] = "'" . implode("','", $lids) . "'";
|
||||
|
||||
// count records
|
||||
$sql = 'SELECT DISTINCT record_id AS r'
|
||||
. ' FROM thit WHERE value IN (:lids)'
|
||||
. ' ORDER BY record_id';
|
||||
$stmt = $connbas->prepare($sql);
|
||||
$stmt->execute(['lids' => $lids]);
|
||||
$tsbas[$ksbas]['trids'] = $stmt->fetchAll(\PDO::FETCH_COLUMN, 0);
|
||||
$stmt->closeCursor();
|
||||
|
||||
$ret['nRecsToUpdate'] += count($tsbas[$ksbas]['trids']);
|
||||
}
|
||||
|
||||
if ($ret['nRecsToUpdate'] <= self::SEARCH_REPLACE_MAXREC) {
|
||||
foreach ($tsbas as $sbas) {
|
||||
|
||||
try {
|
||||
$databox = $this->findDataboxById($sbas['sbas_id']);
|
||||
} catch (\Exception $e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// fix caption of records
|
||||
foreach ($sbas['trids'] as $rid) {
|
||||
try {
|
||||
$record = $databox->get_record($rid);
|
||||
|
||||
$metadatask = []; // datas to keep
|
||||
$metadatasd = []; // datas to delete
|
||||
|
||||
/* @var $field caption_field */
|
||||
foreach ($record->get_caption()->get_fields(null, true) as $field) {
|
||||
$meta_struct_id = $field->get_meta_struct_id();
|
||||
/* @var $v caption_Field_Value */
|
||||
$fname = $field->get_name();
|
||||
if (!array_key_exists($fname, $sbas['tvals'])) {
|
||||
foreach ($field->get_values() as $v) {
|
||||
$metadatask[] = [
|
||||
'meta_struct_id' => $meta_struct_id,
|
||||
'meta_id' => $v->getId(),
|
||||
'value' => $v->getValue()
|
||||
];
|
||||
}
|
||||
} else {
|
||||
foreach ($field->get_values() as $v) {
|
||||
$keep = true;
|
||||
$vtxt = $this->getUnicode()->remove_indexer_chars($v->getValue());
|
||||
/** @var DOMElement $sy */
|
||||
foreach ($sbas['tvals'][$fname] as $sy) {
|
||||
if ($sy->getAttribute('w') == $vtxt) {
|
||||
$keep = false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($keep) {
|
||||
$metadatask[] = [
|
||||
'meta_struct_id' => $meta_struct_id,
|
||||
'meta_id' => $v->getId(),
|
||||
'value' => $v->getValue()
|
||||
];
|
||||
} else {
|
||||
$metadatasd[] = [
|
||||
'meta_struct_id' => $meta_struct_id,
|
||||
'meta_id' => $v->getId(),
|
||||
'value' => $request->get('t') ? $request->get('t') : ''
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (count($metadatasd) > 0) {
|
||||
if (!$request->get('debug')) {
|
||||
$record->set_metadatas($metadatasd, true);
|
||||
$ret['nRecsUpdated']++;
|
||||
}
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($sbas['tvals'] as $tval) {
|
||||
foreach ($tval as $sy) {
|
||||
// remove candidate from cterms
|
||||
$te = $sy->parentNode;
|
||||
$te->parentNode->removeChild($te);
|
||||
$ret['ctermsDeleted'][] = $sbas['sbas_id'] . '.' . $te->getAttribute('id');
|
||||
}
|
||||
}
|
||||
if (!$request->get('debug')) {
|
||||
$databox->saveCterms($sbas['domct']);
|
||||
}
|
||||
}
|
||||
$ret['msg'] = $this->app->trans('prod::thesaurusTab:dlg:%number% record(s) updated', ['%number%' => $ret['nRecsUpdated']]);
|
||||
} else {
|
||||
// too many records to update
|
||||
$ret['msg'] = $this->app->trans('prod::thesaurusTab:dlg:too many (%number%) records to update (limit=%maximum%)', ['%number%' => $ret['nRecsToUpdate'], '%maximum%' => self::SEARCH_REPLACE_MAXREC]);
|
||||
}
|
||||
|
||||
return $this->app->json($ret);
|
||||
@@ -1397,12 +1509,12 @@ class ThesaurusXmlHttpController extends Controller
|
||||
$t = $this->splitTermAndContext($request->get('t'));
|
||||
$unicode = $this->getUnicode();
|
||||
$q2 = 'starts-with(@w, \'' . \thesaurus::xquery_escape($unicode->remove_indexer_chars($t[0])) . '\')';
|
||||
if ($t[1])
|
||||
$q2 .= ' and starts-with(@k, \'' . \thesaurus::xquery_escape(
|
||||
$unicode->remove_indexer_chars($t[1])) . '\')';
|
||||
$q2 = '//sy[' . $q2 . ' and @lng=\'' . $lng . '\']';
|
||||
if ($t[1]) {
|
||||
$q2 .= ' and starts-with(@k, \'' . \thesaurus::xquery_escape($unicode->remove_indexer_chars($t[1])) . '\')';
|
||||
}
|
||||
|
||||
$q .= $q2;
|
||||
$q2 .= ' and @lng=\'' . \thesaurus::xquery_escape($lng) . '\'';
|
||||
$q .= ('//sy[' . $q2 . ']');
|
||||
|
||||
$nodes = $xpath->query($q);
|
||||
|
||||
|
@@ -39,7 +39,6 @@ class V2 extends Api implements ControllerProviderInterface, ServiceProviderInte
|
||||
->setJsonBodyHelper($app['json.body_helper']);
|
||||
}
|
||||
);
|
||||
|
||||
$app['controller.api.v2.lazaret'] = $app->share(
|
||||
function (PhraseaApplication $app) {
|
||||
return (new LazaretController($app));
|
||||
|
37
lib/Alchemy/Phrasea/Core/Event/AuthenticationEvent.php
Normal file
37
lib/Alchemy/Phrasea/Core/Event/AuthenticationEvent.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\Core\Event;
|
||||
|
||||
use Alchemy\Phrasea\Authentication\Context;
|
||||
use Symfony\Component\EventDispatcher\Event;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class AuthenticationEvent extends Event
|
||||
{
|
||||
private $request;
|
||||
private $context;
|
||||
|
||||
public function __construct(Request $request, Context $context)
|
||||
{
|
||||
$this->request = $request;
|
||||
$this->context = $context;
|
||||
}
|
||||
|
||||
public function getRequest()
|
||||
{
|
||||
return $this->request;
|
||||
}
|
||||
|
||||
public function getContext()
|
||||
{
|
||||
return $this->context;
|
||||
}
|
||||
}
|
@@ -15,21 +15,18 @@ use Alchemy\Phrasea\Authentication\Context;
|
||||
use Alchemy\Phrasea\Model\Entities\User;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\EventDispatcher\Event as SfEvent;
|
||||
|
||||
class PostAuthenticate extends SfEvent
|
||||
class PostAuthenticate extends AuthenticationEvent
|
||||
{
|
||||
private $context;
|
||||
private $user;
|
||||
private $request;
|
||||
private $response;
|
||||
|
||||
public function __construct(Request $request, Response $response, User $user, Context $context)
|
||||
{
|
||||
$this->request = $request;
|
||||
parent::__construct($request, $context);
|
||||
|
||||
$this->response = $response;
|
||||
$this->user = $user;
|
||||
$this->context = $context;
|
||||
}
|
||||
|
||||
public function getUser()
|
||||
@@ -37,11 +34,6 @@ class PostAuthenticate extends SfEvent
|
||||
return $this->user;
|
||||
}
|
||||
|
||||
public function getRequest()
|
||||
{
|
||||
return $this->request;
|
||||
}
|
||||
|
||||
public function getResponse()
|
||||
{
|
||||
return $this->response;
|
||||
@@ -51,9 +43,4 @@ class PostAuthenticate extends SfEvent
|
||||
{
|
||||
$this->response = $response;
|
||||
}
|
||||
|
||||
public function getContext()
|
||||
{
|
||||
return $this->context;
|
||||
}
|
||||
}
|
||||
|
@@ -11,28 +11,6 @@
|
||||
|
||||
namespace Alchemy\Phrasea\Core\Event;
|
||||
|
||||
use Alchemy\Phrasea\Authentication\Context;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\EventDispatcher\Event as SfEvent;
|
||||
|
||||
class PreAuthenticate extends SfEvent
|
||||
class PreAuthenticate extends AuthenticationEvent
|
||||
{
|
||||
private $request;
|
||||
private $context;
|
||||
|
||||
public function __construct(Request $request, Context $context)
|
||||
{
|
||||
$this->request = $request;
|
||||
$this->context = $context;
|
||||
}
|
||||
|
||||
public function getRequest()
|
||||
{
|
||||
return $this->request;
|
||||
}
|
||||
|
||||
public function getContext()
|
||||
{
|
||||
return $this->context;
|
||||
}
|
||||
}
|
||||
|
@@ -108,7 +108,11 @@ class ManipulatorServiceProvider implements ServiceProviderInterface
|
||||
});
|
||||
|
||||
$app['manipulator.webhook-event'] = $app->share(function (Application $app) {
|
||||
return new WebhookEventManipulator($app['orm.em'], $app['repo.webhook-event']);
|
||||
return new WebhookEventManipulator(
|
||||
$app['orm.em'],
|
||||
$app['repo.webhook-event'],
|
||||
$app['webhook.publisher']
|
||||
);
|
||||
});
|
||||
|
||||
$app['manipulator.webhook-delivery'] = $app->share(function (Application $app) {
|
||||
@@ -122,6 +126,7 @@ class ManipulatorServiceProvider implements ServiceProviderInterface
|
||||
$app['manipulator.lazaret'] = $app->share(function (Application $app) {
|
||||
return new LazaretManipulator($app, $app['repo.lazaret-files'], $app['filesystem'], $app['orm.em']);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
public function boot(SilexApplication $app)
|
||||
|
@@ -219,7 +219,7 @@ class SearchEngineServiceProvider implements ServiceProviderInterface
|
||||
|
||||
$clientBuilder = ClientBuilder::create()
|
||||
->setHosts($clientParams['hosts']);
|
||||
if (array_key_exists('logObject', $clientParams)) {
|
||||
if(array_key_exists('logObject', $clientParams)) {
|
||||
$clientBuilder->setLogger($clientParams['logObject']);
|
||||
}
|
||||
|
||||
|
@@ -3,6 +3,11 @@
|
||||
namespace Alchemy\Phrasea\Core\Provider;
|
||||
|
||||
use Alchemy\Phrasea\Webhook\EventProcessorFactory;
|
||||
use Alchemy\Phrasea\Webhook\EventProcessorWorker;
|
||||
use Alchemy\Phrasea\Webhook\WebhookInvoker;
|
||||
use Alchemy\Phrasea\Webhook\WebhookPublisher;
|
||||
use Alchemy\Worker\CallableWorkerFactory;
|
||||
use Alchemy\Worker\TypeBasedWorkerResolver;
|
||||
use Silex\Application;
|
||||
use Silex\ServiceProviderInterface;
|
||||
|
||||
@@ -11,9 +16,55 @@ class WebhookServiceProvider implements ServiceProviderInterface
|
||||
|
||||
public function register(Application $app)
|
||||
{
|
||||
$this->createAlias($app, 'webhook.event_repository', 'repo.webhook-event');
|
||||
$this->createAlias($app, 'webhook.event_manipulator', 'manipulator.webhook-event');
|
||||
$this->createAlias($app, 'webhook.delivery_repository', 'repo.webhook-delivery');
|
||||
$this->createAlias($app, 'webhook.delivery_manipulator', 'manipulator.webhook-delivery');
|
||||
|
||||
$app['webhook.delivery_payload_repository'] = $app->share(function ($app) {
|
||||
return $app['orm.em']->getRepository('Phraseanet:WebhookEventPayload');
|
||||
});
|
||||
|
||||
$app['webhook.processor_factory'] = $app->share(function ($app) {
|
||||
return new EventProcessorFactory($app);
|
||||
});
|
||||
|
||||
$app['webhook.invoker'] = $app->share(function ($app) {
|
||||
return new WebhookInvoker(
|
||||
$app['repo.api-applications'],
|
||||
$app['webhook.processor_factory'],
|
||||
$app['webhook.event_repository'],
|
||||
$app['webhook.event_manipulator'],
|
||||
$app['webhook.delivery_repository'],
|
||||
$app['webhook.delivery_manipulator'],
|
||||
$app['webhook.delivery_payload_repository']
|
||||
);
|
||||
});
|
||||
|
||||
$app['webhook.publisher'] = $app->share(function ($app) {
|
||||
return new WebhookPublisher($app['alchemy_worker.queue_registry'], $app['alchemy_worker.queue_name']);
|
||||
});
|
||||
|
||||
$app['alchemy_worker.worker_resolver'] = $app->extend(
|
||||
'alchemy_worker.type_based_worker_resolver',
|
||||
function (TypeBasedWorkerResolver $resolver, Application $app) {
|
||||
$resolver->setFactory('webhook', new CallableWorkerFactory(function () use ($app) {
|
||||
return new EventProcessorWorker(
|
||||
$app['webhook.event_repository'],
|
||||
$app['webhook.invoker']
|
||||
);
|
||||
}));
|
||||
|
||||
return $resolver;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private function createAlias(Application $app, $alias, $targetServiceKey)
|
||||
{
|
||||
$app[$alias] = $app->share(function () use ($app, $targetServiceKey) {
|
||||
return $app[$targetServiceKey];
|
||||
});
|
||||
}
|
||||
|
||||
public function boot(Application $app)
|
||||
|
@@ -0,0 +1,81 @@
|
||||
<?php
|
||||
|
||||
namespace Alchemy\Phrasea\Core\Provider;
|
||||
|
||||
use Alchemy\Phrasea\Core\Configuration\PropertyAccess;
|
||||
use Alchemy\Phrasea\Exception\RuntimeException;
|
||||
use Alchemy\Worker\CallableWorkerFactory;
|
||||
use Alchemy\Worker\TypeBasedWorkerResolver;
|
||||
use Silex\Application;
|
||||
use Silex\ServiceProviderInterface;
|
||||
|
||||
class WorkerConfigurationServiceProvider implements ServiceProviderInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Registers services on the given app.
|
||||
*
|
||||
* This method should only be used to configure services and parameters.
|
||||
* It should not get services.
|
||||
*/
|
||||
public function register(Application $app)
|
||||
{
|
||||
// Define the first defined queue as the worker queue
|
||||
$app['alchemy_worker.queue_name'] = $app->share(function (Application $app) {
|
||||
$queues = $app['alchemy_queues.queues'];
|
||||
|
||||
reset($queues);
|
||||
|
||||
return key($queues);
|
||||
});
|
||||
|
||||
$app['alchemy_queues.queues'] = $app->share(function (Application $app) {
|
||||
$defaultConfiguration = [
|
||||
'worker-queue' => [
|
||||
'registry' => 'alchemy_worker.queue_registry',
|
||||
'host' => 'localhost',
|
||||
'port' => 5672,
|
||||
'user' => 'guest',
|
||||
'vhost' => '/'
|
||||
]
|
||||
];
|
||||
|
||||
try {
|
||||
/** @var PropertyAccess $configuration */
|
||||
$configuration = $app['conf'];
|
||||
|
||||
$queueConfigurations = $configuration->get(['workers', 'queue'], $defaultConfiguration);
|
||||
|
||||
$queueConfiguration = reset($queueConfigurations);
|
||||
$queueKey = key($queueConfigurations);
|
||||
|
||||
if (! isset($queueConfiguration['name'])) {
|
||||
if (! is_string($queueKey)) {
|
||||
throw new \RuntimeException('Invalid queue configuration: configuration has no key or name.');
|
||||
}
|
||||
|
||||
$queueConfiguration['name'] = $queueKey;
|
||||
}
|
||||
|
||||
$config = [ $queueConfiguration['name'] => $queueConfiguration ];
|
||||
|
||||
return $config;
|
||||
}
|
||||
catch (RuntimeException $exception) {
|
||||
return [];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstraps the application.
|
||||
*
|
||||
* This method is called after all services are registered
|
||||
* and should be used for "dynamic" configuration (whenever
|
||||
* a service must be requested).
|
||||
*/
|
||||
public function boot(Application $app)
|
||||
{
|
||||
// No-op
|
||||
}
|
||||
}
|
@@ -56,6 +56,16 @@ class SubdefGroup implements \IteratorAggregate, \Countable
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
public function allowDocumentOrdering()
|
||||
{
|
||||
$this->isDocumentOrderable = true;
|
||||
}
|
||||
|
||||
public function disallowDocumentOrdering()
|
||||
{
|
||||
$this->isDocumentOrderable = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
|
@@ -62,7 +62,7 @@ class PhraseaRegisterForm extends AbstractType
|
||||
'label' => 'Terms of Use',
|
||||
'mapped' => false,
|
||||
"constraints" => [
|
||||
new Assert\True([
|
||||
new Assert\IsTrue([
|
||||
"message" => "Please accept the Terms and conditions in order to register."
|
||||
])],
|
||||
]);
|
||||
|
@@ -56,6 +56,11 @@ class WebhookEventDelivery
|
||||
*/
|
||||
private $created;
|
||||
|
||||
/**
|
||||
* @ORM\OneToOne(targetEntity="WebhookEventPayload", mappedBy="delivery")
|
||||
*/
|
||||
private $payload;
|
||||
|
||||
/**
|
||||
* @param \DateTime $created
|
||||
*
|
||||
@@ -163,4 +168,12 @@ class WebhookEventDelivery
|
||||
{
|
||||
return $this->event;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return WebhookEventPayload
|
||||
*/
|
||||
public function getPayload()
|
||||
{
|
||||
return $this->payload;
|
||||
}
|
||||
}
|
||||
|
127
lib/Alchemy/Phrasea/Model/Entities/WebhookEventPayload.php
Normal file
127
lib/Alchemy/Phrasea/Model/Entities/WebhookEventPayload.php
Normal file
@@ -0,0 +1,127 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of phrasea-4.1.
|
||||
*
|
||||
* (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\Model\Entities;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
|
||||
/**
|
||||
* @ORM\Table(name="WebhookEventPayloads")
|
||||
* @ORM\Entity(repositoryClass="Alchemy\Phrasea\Model\Repositories\WebhookEventPayloadRepository")
|
||||
*/
|
||||
class WebhookEventPayload
|
||||
{
|
||||
/**
|
||||
* @ORM\Column(type="guid")
|
||||
* @ORM\Id
|
||||
* @ORM\GeneratedValue(strategy="NONE")
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @ORM\OneToOne(targetEntity="WebhookEventDelivery")
|
||||
* @ORM\JoinColumn(name="delivery_id", referencedColumnName="id")
|
||||
*/
|
||||
private $delivery;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="text", name="request")
|
||||
* @var string
|
||||
*/
|
||||
private $requestPayload;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="text", name="response")
|
||||
* @var string
|
||||
*/
|
||||
private $responsePayload;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="integer", name="status")
|
||||
* @var int
|
||||
*/
|
||||
private $statusCode;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="text")
|
||||
* @var string
|
||||
*/
|
||||
private $headers;
|
||||
|
||||
/**
|
||||
* @param WebhookEventDelivery $eventDelivery
|
||||
* @param string $requestPayload
|
||||
* @param string $responsePayload
|
||||
* @param int $statusCode
|
||||
* @param string $headers
|
||||
*/
|
||||
public function __construct(WebhookEventDelivery $eventDelivery, $requestPayload, $responsePayload, $statusCode, $headers)
|
||||
{
|
||||
$this->id = Uuid::uuid4()->toString();
|
||||
|
||||
$this->delivery = $eventDelivery;
|
||||
$this->requestPayload = $requestPayload;
|
||||
$this->responsePayload = $responsePayload;
|
||||
$this->statusCode = $statusCode;
|
||||
$this->headers = $headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getId()
|
||||
{
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return WebhookEventDelivery
|
||||
*/
|
||||
public function getDelivery()
|
||||
{
|
||||
return $this->delivery;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getRequestPayload()
|
||||
{
|
||||
return $this->requestPayload;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getResponsePayload()
|
||||
{
|
||||
return $this->responsePayload;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getStatusCode()
|
||||
{
|
||||
return $this->statusCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getResponseHeaders()
|
||||
{
|
||||
return $this->headers;
|
||||
}
|
||||
}
|
@@ -147,7 +147,8 @@ class LazaretManipulator
|
||||
$this->app,
|
||||
$lazaretFile->getOriginalName()
|
||||
);
|
||||
} catch (\Exception $e) {
|
||||
}
|
||||
catch(\Exception $e) {
|
||||
// the file is not in tmp anymore ?
|
||||
// delete the quarantine item
|
||||
$this->denyLazaretFile($lazaretFile);
|
||||
@@ -196,6 +197,7 @@ class LazaretManipulator
|
||||
case AttributeInterface::NAME_METADATA:
|
||||
/** @var Metadata $value */
|
||||
$value = $attribute->getValue();
|
||||
// $metadataBag->set($value->getTag()->getTagname(), new Metadata($value->getTag(), $value->getValue()));
|
||||
$metadataBag->set($value->getTag()->getTagname(), $value);
|
||||
break;
|
||||
case AttributeInterface::NAME_STORY:
|
||||
|
@@ -35,21 +35,52 @@ use Alchemy\Phrasea\Core\Event\User\DeletedEvent;
|
||||
*/
|
||||
class UserManipulator implements ManipulatorInterface
|
||||
{
|
||||
/** @var PasswordEncoderInterface */
|
||||
/**
|
||||
* @var PasswordEncoderInterface
|
||||
*/
|
||||
protected $passwordEncoder;
|
||||
/** @var UserManager */
|
||||
|
||||
/**
|
||||
* @var UserManager
|
||||
*/
|
||||
private $manager;
|
||||
/** @var GeonamesConnector */
|
||||
|
||||
/**
|
||||
* @var GeonamesConnector
|
||||
*/
|
||||
private $geonamesConnector;
|
||||
/** @var Generator */
|
||||
|
||||
/**
|
||||
* @var Generator
|
||||
*/
|
||||
private $generator;
|
||||
/** @var EntityRepository */
|
||||
|
||||
/**
|
||||
* @var EntityRepository
|
||||
*/
|
||||
private $repository;
|
||||
/** @var EventDispatcherInterface */
|
||||
|
||||
/**
|
||||
* @var EventDispatcherInterface
|
||||
*/
|
||||
private $dispatcher;
|
||||
|
||||
|
||||
public function __construct(UserManager $manager, PasswordEncoderInterface $passwordEncoder, GeonamesConnector $connector, EntityRepository $repo, Generator $generator, EventDispatcherInterface $dispatcher)
|
||||
/**
|
||||
* @param UserManager $manager
|
||||
* @param PasswordEncoderInterface $passwordEncoder
|
||||
* @param GeonamesConnector $connector
|
||||
* @param EntityRepository $repo
|
||||
* @param Generator $generator
|
||||
* @param EventDispatcherInterface $dispatcher
|
||||
*/
|
||||
public function __construct(
|
||||
UserManager $manager,
|
||||
PasswordEncoderInterface $passwordEncoder,
|
||||
GeonamesConnector $connector,
|
||||
EntityRepository $repo,
|
||||
Generator $generator,
|
||||
EventDispatcherInterface $dispatcher
|
||||
)
|
||||
{
|
||||
$this->manager = $manager;
|
||||
$this->generator = $generator;
|
||||
|
@@ -12,29 +12,46 @@
|
||||
namespace Alchemy\Phrasea\Model\Manipulator;
|
||||
|
||||
use Alchemy\Phrasea\Model\Entities\WebhookEvent;
|
||||
use Alchemy\Phrasea\Webhook\WebhookPublisher;
|
||||
use Doctrine\Common\Persistence\ObjectManager;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
|
||||
class WebhookEventManipulator implements ManipulatorInterface
|
||||
{
|
||||
/**
|
||||
* @var ObjectManager
|
||||
*/
|
||||
private $om;
|
||||
|
||||
/**
|
||||
* @var EntityRepository
|
||||
*/
|
||||
private $repository;
|
||||
|
||||
public function __construct(ObjectManager $om, EntityRepository $repo)
|
||||
/**
|
||||
* @var WebhookPublisher
|
||||
*/
|
||||
private $publisher;
|
||||
|
||||
public function __construct(ObjectManager $om, EntityRepository $repo, WebhookPublisher $publisher)
|
||||
{
|
||||
$this->om = $om;
|
||||
$this->repository = $repo;
|
||||
$this->publisher = $publisher;
|
||||
}
|
||||
|
||||
public function create($eventName, $type, array $data)
|
||||
{
|
||||
$event = new WebhookEvent();
|
||||
|
||||
$event->setName($eventName);
|
||||
$event->setType($type);
|
||||
$event->setData($data);
|
||||
|
||||
$this->update($event);
|
||||
|
||||
$this->publisher->publishWebhookEvent($event);
|
||||
|
||||
return $event;
|
||||
}
|
||||
|
||||
|
@@ -11,6 +11,7 @@
|
||||
|
||||
namespace Alchemy\Phrasea\Model\Repositories;
|
||||
|
||||
use Alchemy\Phrasea\Model\Entities\ApiApplication;
|
||||
use Alchemy\Phrasea\Model\Entities\WebhookEventDelivery;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
|
||||
@@ -22,6 +23,10 @@ use Doctrine\ORM\EntityRepository;
|
||||
*/
|
||||
class WebhookEventDeliveryRepository extends EntityRepository
|
||||
{
|
||||
|
||||
/**
|
||||
* @return WebhookEventDelivery[]
|
||||
*/
|
||||
public function findUndeliveredEvents()
|
||||
{
|
||||
$qb = $this->createQueryBuilder('e');
|
||||
@@ -34,4 +39,22 @@ class WebhookEventDeliveryRepository extends EntityRepository
|
||||
|
||||
return $qb->getQuery()->getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ApiApplication $apiApplication
|
||||
* @param int $count
|
||||
* @return WebhookEventDelivery[]
|
||||
*/
|
||||
public function findLastDeliveries(ApiApplication $apiApplication, $count = 10)
|
||||
{
|
||||
$qb = $this->createQueryBuilder('e');
|
||||
|
||||
$qb
|
||||
->where('e.application = :app')
|
||||
->setMaxResults(max(0, (int) $count))
|
||||
->orderBy('e.created', 'DESC')
|
||||
->setParameters([ 'app' => $apiApplication ]);
|
||||
|
||||
return $qb->getQuery()->getResult();
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of phrasea-4.1.
|
||||
*
|
||||
* (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\Model\Repositories;
|
||||
|
||||
use Alchemy\Phrasea\Model\Entities\WebhookEventPayload;
|
||||
use Doctrine\ORM\EntityRepository;
|
||||
|
||||
class WebhookEventPayloadRepository extends EntityRepository
|
||||
{
|
||||
|
||||
public function save(WebhookEventPayload $payload)
|
||||
{
|
||||
$this->_em->persist($payload);
|
||||
$this->_em->persist($payload->getDelivery());
|
||||
|
||||
$this->_em->flush([ $payload, $payload->getDelivery() ]);
|
||||
}
|
||||
}
|
@@ -242,7 +242,7 @@ class ApiOrderController extends BaseOrderController
|
||||
$filtered = [];
|
||||
|
||||
foreach ($records as $index => $record) {
|
||||
if ($acl->has_right_on_base($record->getBaseId(), 'cancmd')) {
|
||||
if (!$record->isStory() && $acl->has_right_on_base($record->getBaseId(), 'cancmd')) {
|
||||
$filtered[$index] = $record;
|
||||
}
|
||||
}
|
||||
|
@@ -287,7 +287,6 @@ class ElasticSearchEngine implements SearchEngineInterface
|
||||
}
|
||||
|
||||
$aggs = $this->getAggregationQueryParams($options);
|
||||
|
||||
if ($aggs) {
|
||||
$params['body']['aggs'] = $aggs;
|
||||
}
|
||||
|
@@ -139,6 +139,8 @@ class Indexer
|
||||
// everything ready to search
|
||||
$bulk->flush();
|
||||
$this->client->indices()->refresh();
|
||||
$this->client->indices()->clearCache();
|
||||
$this->client->indices()->flushSynced();
|
||||
}
|
||||
|
||||
if ($what & self::RECORDS) {
|
||||
|
@@ -78,7 +78,9 @@ class ThesaurusHydrator implements HydratorInterface
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(empty($terms)) {
|
||||
return;
|
||||
}
|
||||
$bulk = $this->thesaurus->findConceptsBulk($terms, null, $filters, true);
|
||||
|
||||
foreach ($bulk as $offset => $item_concepts) {
|
||||
|
@@ -79,19 +79,138 @@ class Thesaurus
|
||||
* @return Concept[] Matching concepts
|
||||
*/
|
||||
public function findConcepts($term, $lang = null, Filter $filter = null, $strict = false)
|
||||
{
|
||||
return $strict ?
|
||||
$this->findConceptsStrict($term, $lang, $filter)
|
||||
:
|
||||
$this->findConceptsFuzzy($term, $lang, $filter)
|
||||
;
|
||||
}
|
||||
|
||||
private function findConceptsStrict($term, $lang = null, Filter $filter = null)
|
||||
{
|
||||
if (!($term instanceof TermInterface)) {
|
||||
$term = new Term($term);
|
||||
}
|
||||
|
||||
$this->logger->info(sprintf('Searching for term %s', $term), array(
|
||||
'strict' => $strict,
|
||||
'strict' => true,
|
||||
'lang' => $lang
|
||||
));
|
||||
|
||||
if ($strict) {
|
||||
$field_suffix = '.strict';
|
||||
} elseif ($lang) {
|
||||
$must = [];
|
||||
$filters = [];
|
||||
|
||||
$must[] = [
|
||||
'match' => [
|
||||
'value.strict' => [
|
||||
'query' => $term->getValue(),
|
||||
'operator' => 'and',
|
||||
],
|
||||
],
|
||||
];
|
||||
if ($term->hasContext()) {
|
||||
$must[] = [
|
||||
'match' => [
|
||||
'context.strict' => [
|
||||
'query' => $term->getContext(),
|
||||
'operator' => 'and',
|
||||
],
|
||||
],
|
||||
];
|
||||
} else {
|
||||
$filters[] = [
|
||||
'missing' => [
|
||||
'field' => 'context'
|
||||
]
|
||||
];
|
||||
}
|
||||
if ($lang) {
|
||||
$filters[] = [
|
||||
'term' => [
|
||||
'lang' => $lang
|
||||
]
|
||||
];
|
||||
}
|
||||
if ($filter) {
|
||||
$filters = array_merge($filters, $filter->getQueryFilters());
|
||||
}
|
||||
if(!empty($filters)) {
|
||||
if (count($filters) > 1) {
|
||||
$must[] = [
|
||||
'constant_score' => [
|
||||
'filter' => [
|
||||
'and' => $filters
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
else {
|
||||
$must[] = [
|
||||
'constant_score' => [
|
||||
'filter' => $filters[0]
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
if(count($must) > 1) {
|
||||
$query = [
|
||||
'bool' => [
|
||||
'must' => $must
|
||||
]
|
||||
];
|
||||
}
|
||||
else {
|
||||
$query = $must[0];
|
||||
}
|
||||
|
||||
// Path deduplication
|
||||
$aggs = array();
|
||||
$aggs['dedup']['terms']['field'] = 'path.raw';
|
||||
|
||||
// Search request
|
||||
$params = array();
|
||||
$params['index'] = $this->options->getIndexName();
|
||||
$params['type'] = TermIndexer::TYPE_NAME;
|
||||
$params['body']['query'] = $query;
|
||||
$params['body']['aggs'] = $aggs;
|
||||
// No need to get any hits since we extract data from aggs
|
||||
$params['body']['size'] = 0;
|
||||
|
||||
$this->logger->debug('Sending search', $params['body']);
|
||||
$response = $this->client->search($params);
|
||||
|
||||
// Extract concept paths from response
|
||||
$concepts = array();
|
||||
$buckets = \igorw\get_in($response, ['aggregations', 'dedup', 'buckets'], []);
|
||||
$keys = array();
|
||||
foreach ($buckets as $bucket) {
|
||||
if (isset($bucket['key'])) {
|
||||
$keys[] = $bucket['key'];
|
||||
$concepts[] = new Concept($bucket['key']);
|
||||
}
|
||||
}
|
||||
|
||||
$this->logger->info(sprintf('Found %d matching concepts', count($concepts)),
|
||||
array('concepts' => $keys)
|
||||
);
|
||||
|
||||
return $concepts;
|
||||
}
|
||||
|
||||
private function findConceptsFuzzy($term, $lang = null, Filter $filter = null)
|
||||
{
|
||||
if (!($term instanceof TermInterface)) {
|
||||
$term = new Term($term);
|
||||
}
|
||||
|
||||
$this->logger->info(sprintf('Searching for term %s', $term), array(
|
||||
'strict' => false,
|
||||
'lang' => $lang
|
||||
));
|
||||
|
||||
if($lang) {
|
||||
$field_suffix = sprintf('.%s', $lang);
|
||||
} else {
|
||||
$field_suffix = '';
|
||||
@@ -114,10 +233,6 @@ class Thesaurus
|
||||
$query = array();
|
||||
$query['bool']['must'][0] = $value_query;
|
||||
$query['bool']['must'][1] = $context_query;
|
||||
} elseif ($strict) {
|
||||
$context_filter = array();
|
||||
$context_filter['missing']['field'] = 'context';
|
||||
$query = self::applyQueryFilter($query, $context_filter);
|
||||
}
|
||||
|
||||
if ($lang) {
|
||||
|
@@ -46,4 +46,34 @@ class Filter
|
||||
|
||||
return $filter;
|
||||
}
|
||||
|
||||
public function getQueryFilters()
|
||||
{
|
||||
$filters = [
|
||||
[
|
||||
'term' => [
|
||||
'databox_id' => $this->databox_id
|
||||
]
|
||||
]
|
||||
];
|
||||
if(!empty($this->paths)) {
|
||||
if (count($this->paths) == 1) {
|
||||
$filters[] = [
|
||||
'term' => [
|
||||
'path' => $this->paths[0]
|
||||
]
|
||||
];
|
||||
}
|
||||
else {
|
||||
$filters[] = [
|
||||
'terms' => [
|
||||
'path' => $this->paths
|
||||
]
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $filters;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace Alchemy\Phrasea\Setup\DoctrineMigrations;
|
||||
|
||||
use Doctrine\DBAL\Schema\Schema;
|
||||
|
||||
/**
|
||||
* Auto-generated Migration: Please modify to your needs!
|
||||
*/
|
||||
class Version20161013115559 extends AbstractMigration
|
||||
{
|
||||
|
||||
public function isAlreadyApplied()
|
||||
{
|
||||
return $this->tableExists('Orders');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Schema $schema
|
||||
*/
|
||||
public function doUpSql(Schema $schema)
|
||||
{
|
||||
// this up() migration is auto-generated, please modify it to your needs
|
||||
$this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.');
|
||||
|
||||
$this->addSql("CREATE TABLE WebhookEventPayloads (id CHAR(36) NOT NULL COMMENT '(DC2Type:guid)', delivery_id INT DEFAULT NULL, request LONGTEXT NOT NULL, response LONGTEXT NOT NULL, status INT NOT NULL, headers LONGTEXT NOT NULL, UNIQUE INDEX UNIQ_B949629612136921 (delivery_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;");
|
||||
$this->addSql("ALTER TABLE WebhookEventPayloads ADD CONSTRAINT FK_B949629612136921 FOREIGN KEY (delivery_id) REFERENCES WebhookEventDeliveries (id);");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Schema $schema
|
||||
*/
|
||||
public function doDownSql(Schema $schema)
|
||||
{
|
||||
// this down() migration is auto-generated, please modify it to your needs
|
||||
$this->abortIf($this->connection->getDatabasePlatform()->getName() != 'mysql', 'Migration can only be executed safely on \'mysql\'.');
|
||||
|
||||
$this->addSql('DROP TABLE WebhookEventPayloads');
|
||||
}
|
||||
}
|
@@ -12,21 +12,11 @@
|
||||
namespace Alchemy\Phrasea\TaskManager\Job;
|
||||
|
||||
use Alchemy\Phrasea\Core\Version;
|
||||
use Alchemy\Phrasea\Model\Entities\WebhookEvent;
|
||||
use Alchemy\Phrasea\Model\Entities\WebhookEventDelivery;
|
||||
use Alchemy\Phrasea\Model\Entities\ApiApplication;
|
||||
use Alchemy\Phrasea\TaskManager\Editor\DefaultEditor;
|
||||
use Alchemy\Phrasea\Webhook\EventProcessorFactory;
|
||||
use Guzzle\Http\Client as GuzzleClient;
|
||||
use Guzzle\Batch\BatchBuilder;
|
||||
use Guzzle\Http\Message\Request;
|
||||
use Silex\Application;
|
||||
use Guzzle\Common\Event;
|
||||
use Guzzle\Plugin\Backoff\BackoffPlugin;
|
||||
use Guzzle\Plugin\Backoff\TruncatedBackoffStrategy;
|
||||
use Guzzle\Plugin\Backoff\CallbackBackoffStrategy;
|
||||
use Guzzle\Plugin\Backoff\CurlBackoffStrategy;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Silex\Application;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
|
||||
@@ -34,15 +24,12 @@ class WebhookJob extends AbstractJob
|
||||
{
|
||||
private $httpClient;
|
||||
|
||||
private $firstRun = true;
|
||||
|
||||
public function __construct(
|
||||
TranslatorInterface $translator,
|
||||
EventDispatcherInterface $dispatcher = null,
|
||||
LoggerInterface $logger = null,
|
||||
GuzzleClient $httpClient = null
|
||||
)
|
||||
{
|
||||
) {
|
||||
parent::__construct($translator, $dispatcher, $logger);
|
||||
|
||||
$this->httpClient = $httpClient ?: new GuzzleClient();
|
||||
@@ -89,57 +76,6 @@ class WebhookJob extends AbstractJob
|
||||
{
|
||||
$app = $data->getApplication();
|
||||
$thirdPartyApplications = $app['repo.api-applications']->findWithDefinedWebhookCallback();
|
||||
$that = $this;
|
||||
|
||||
if ($this->firstRun) {
|
||||
$this->httpClient->getEventDispatcher()->addListener('request.error', function (Event $event) {
|
||||
// override guzzle default behavior of throwing exceptions
|
||||
// when 4xx & 5xx responses are encountered
|
||||
$event->stopPropagation();
|
||||
}, -254);
|
||||
|
||||
// Set callback which logs success or failure
|
||||
$subscriber = new CallbackBackoffStrategy(function ($retries, Request $request, $response, $e) use ($app, $that) {
|
||||
$retry = true;
|
||||
if ($response && (null !== $deliverId = parse_url($request->getUrl(), PHP_URL_FRAGMENT))) {
|
||||
$delivery = $app['repo.webhook-delivery']->find($deliverId);
|
||||
|
||||
$logContext = [ 'host' => $request->getHost() ];
|
||||
|
||||
if ($response->isSuccessful()) {
|
||||
$app['manipulator.webhook-delivery']->deliverySuccess($delivery);
|
||||
|
||||
$logType = 'info';
|
||||
$logEntry = sprintf('Deliver success event "%d:%s" for app "%s"',
|
||||
$delivery->getWebhookEvent()->getId(), $delivery->getWebhookEvent()->getName(),
|
||||
$delivery->getThirdPartyApplication()->getName()
|
||||
);
|
||||
|
||||
$retry = false;
|
||||
} else {
|
||||
$app['manipulator.webhook-delivery']->deliveryFailure($delivery);
|
||||
|
||||
$logType = 'error';
|
||||
$logEntry = sprintf('Deliver failure event "%d:%s" for app "%s"',
|
||||
$delivery->getWebhookEvent()->getId(), $delivery->getWebhookEvent()->getName(),
|
||||
$delivery->getThirdPartyApplication()->getName()
|
||||
);
|
||||
}
|
||||
|
||||
$that->log($logType, $logEntry, $logContext);
|
||||
|
||||
return $retry;
|
||||
}
|
||||
}, true, new CurlBackoffStrategy());
|
||||
|
||||
// set max retries
|
||||
$subscriber = new TruncatedBackoffStrategy(WebhookEventDelivery::MAX_DELIVERY_TRIES, $subscriber);
|
||||
$subscriber = new BackoffPlugin($subscriber);
|
||||
|
||||
$this->httpClient->addSubscriber($subscriber);
|
||||
|
||||
$this->firstRun = false;
|
||||
}
|
||||
|
||||
/** @var EventProcessorFactory $eventFactory */
|
||||
$eventFactory = $app['webhook.processor_factory'];
|
||||
@@ -155,41 +91,4 @@ class WebhookJob extends AbstractJob
|
||||
$this->deliverEvent($eventFactory, $app, $thirdPartyApplications, $event);
|
||||
}
|
||||
}
|
||||
|
||||
private function deliverEvent(EventProcessorFactory $eventFactory, Application $app, array $thirdPartyApplications, WebhookEvent $event)
|
||||
{
|
||||
if (count($thirdPartyApplications) === 0) {
|
||||
$this->log('info', sprintf('No applications defined to listen for webhook events'));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// format event data
|
||||
$eventProcessor = $eventFactory->get($event);
|
||||
$data = $eventProcessor->process($event);
|
||||
|
||||
// batch requests
|
||||
$batch = BatchBuilder::factory()
|
||||
->transferRequests(10)
|
||||
->build();
|
||||
|
||||
foreach ($thirdPartyApplications as $thirdPartyApplication) {
|
||||
$delivery = $app['manipulator.webhook-delivery']->create($thirdPartyApplication, $event);
|
||||
|
||||
// append delivery id as url anchor
|
||||
$uniqueUrl = $this->getUrl($thirdPartyApplication, $delivery);
|
||||
|
||||
// create http request with data as request body
|
||||
$batch->add($this->httpClient->createRequest('POST', $uniqueUrl, [
|
||||
'Content-Type' => 'application/vnd.phraseanet.event+json'
|
||||
], json_encode($data)));
|
||||
}
|
||||
|
||||
$batch->flush();
|
||||
}
|
||||
|
||||
private function getUrl(ApiApplication $application, WebhookEventDelivery $delivery)
|
||||
{
|
||||
return sprintf('%s#%s', $application->getWebhookUrl(), $delivery->getId());
|
||||
}
|
||||
}
|
||||
|
@@ -16,7 +16,7 @@ class EventProcessorFactory
|
||||
{
|
||||
|
||||
/**
|
||||
* @var ProcessorFactory
|
||||
* @var ProcessorFactory[]
|
||||
*/
|
||||
private $processorFactories = [];
|
||||
|
||||
@@ -59,10 +59,20 @@ class EventProcessorFactory
|
||||
/**
|
||||
* @param WebhookEvent $event
|
||||
* @return Processor\ProcessorInterface
|
||||
* @deprecated Use getProcessor() instead
|
||||
*/
|
||||
public function get(WebhookEvent $event)
|
||||
{
|
||||
if (! isset($this->processorFactories[$event->getType()])) {
|
||||
return $this->getProcessor($event);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WebhookEvent $event
|
||||
* @return ProcessorInterface
|
||||
*/
|
||||
public function getProcessor(WebhookEvent $event)
|
||||
{
|
||||
if (!isset($this->processorFactories[$event->getType()])) {
|
||||
throw new \RuntimeException(sprintf('No processor found for %s', $event->getType()));
|
||||
}
|
||||
|
||||
|
57
lib/Alchemy/Phrasea/Webhook/EventProcessorWorker.php
Normal file
57
lib/Alchemy/Phrasea/Webhook/EventProcessorWorker.php
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of phrasea-4.1.
|
||||
*
|
||||
* (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\Webhook;
|
||||
|
||||
use Alchemy\Phrasea\Model\Entities\WebhookEvent;
|
||||
use Alchemy\Phrasea\Model\Repositories\WebhookEventRepository;
|
||||
use Alchemy\Worker\Worker;
|
||||
|
||||
class EventProcessorWorker implements Worker
|
||||
{
|
||||
|
||||
/**
|
||||
* @var WebhookEventRepository
|
||||
*/
|
||||
private $eventRepository;
|
||||
|
||||
/**
|
||||
* @var WebhookInvoker
|
||||
*/
|
||||
private $invoker;
|
||||
|
||||
/**
|
||||
* @param WebhookEventRepository $eventRepository
|
||||
* @param WebhookInvoker $invoke
|
||||
*/
|
||||
public function __construct(WebhookEventRepository $eventRepository, WebhookInvoker $invoke)
|
||||
{
|
||||
$this->eventRepository = $eventRepository;
|
||||
$this->invoker = $invoke;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $payload
|
||||
* @return void
|
||||
*/
|
||||
public function process(array $payload)
|
||||
{
|
||||
$eventId = $payload['id'];
|
||||
/** @var WebhookEvent $event */
|
||||
$event = $this->eventRepository->find($eventId);
|
||||
|
||||
if ($event === null || $event->isProcessed()) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->invoker->invoke($event);
|
||||
}
|
||||
}
|
292
lib/Alchemy/Phrasea/Webhook/WebhookInvoker.php
Normal file
292
lib/Alchemy/Phrasea/Webhook/WebhookInvoker.php
Normal file
@@ -0,0 +1,292 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of phrasea-4.1.
|
||||
*
|
||||
* (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\Webhook;
|
||||
|
||||
use Alchemy\Phrasea\Model\Entities\ApiApplication;
|
||||
use Alchemy\Phrasea\Model\Entities\WebhookEvent;
|
||||
use Alchemy\Phrasea\Model\Entities\WebhookEventDelivery;
|
||||
use Alchemy\Phrasea\Model\Entities\WebhookEventPayload;
|
||||
use Alchemy\Phrasea\Model\Manipulator\WebhookEventDeliveryManipulator;
|
||||
use Alchemy\Phrasea\Model\Manipulator\WebhookEventManipulator;
|
||||
use Alchemy\Phrasea\Model\Repositories\ApiApplicationRepository;
|
||||
use Alchemy\Phrasea\Model\Repositories\WebhookEventDeliveryRepository;
|
||||
use Alchemy\Phrasea\Model\Repositories\WebhookEventPayloadRepository;
|
||||
use Alchemy\Phrasea\Model\Repositories\WebhookEventRepository;
|
||||
use Guzzle\Common\Event;
|
||||
use Guzzle\Http\Client;
|
||||
use Guzzle\Http\Message\EntityEnclosingRequestInterface;
|
||||
use Guzzle\Http\Message\Request;
|
||||
use Guzzle\Http\Message\Response;
|
||||
use Guzzle\Plugin\Backoff\BackoffPlugin;
|
||||
use Guzzle\Plugin\Backoff\CallbackBackoffStrategy;
|
||||
use Guzzle\Plugin\Backoff\CurlBackoffStrategy;
|
||||
use Guzzle\Plugin\Backoff\TruncatedBackoffStrategy;
|
||||
use Psr\Log\LoggerAwareInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Psr\Log\NullLogger;
|
||||
|
||||
/**
|
||||
* Class WebhookInvoker invokes remote endpoints with webhook event data
|
||||
* @package Alchemy\Phrasea\Webhook
|
||||
*/
|
||||
class WebhookInvoker implements LoggerAwareInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* @var ApiApplicationRepository
|
||||
*/
|
||||
private $applicationRepository;
|
||||
|
||||
/**
|
||||
* @var WebhookEventDeliveryManipulator
|
||||
*/
|
||||
private $eventDeliveryManipulator;
|
||||
|
||||
/**
|
||||
* @var WebhookEventDeliveryRepository
|
||||
*/
|
||||
private $eventDeliveryRepository;
|
||||
|
||||
/**
|
||||
* @var Client
|
||||
*/
|
||||
private $client;
|
||||
|
||||
/**
|
||||
* @var LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* @var EventProcessorFactory
|
||||
*/
|
||||
private $processorFactory;
|
||||
|
||||
/**
|
||||
* @var WebhookEventRepository
|
||||
*/
|
||||
private $eventRepository;
|
||||
|
||||
/**
|
||||
* @var WebhookEventManipulator
|
||||
*/
|
||||
private $eventManipulator;
|
||||
|
||||
/**
|
||||
* @var WebhookEventPayloadRepository
|
||||
*/
|
||||
private $eventPayloadRepository;
|
||||
|
||||
/**
|
||||
* @param ApiApplicationRepository $applicationRepository
|
||||
* @param EventProcessorFactory $processorFactory
|
||||
* @param WebhookEventRepository $eventRepository
|
||||
* @param WebhookEventManipulator $eventManipulator
|
||||
* @param WebhookEventDeliveryRepository $eventDeliveryRepository
|
||||
* @param WebhookEventDeliveryManipulator $eventDeliveryManipulator
|
||||
* @param WebhookEventPayloadRepository $eventPayloadRepository
|
||||
* @param Client $client
|
||||
*
|
||||
* @todo Extract classes to reduce number of required dependencies
|
||||
*/
|
||||
public function __construct(
|
||||
ApiApplicationRepository $applicationRepository,
|
||||
EventProcessorFactory $processorFactory,
|
||||
WebhookEventRepository $eventRepository,
|
||||
WebhookEventManipulator $eventManipulator,
|
||||
WebhookEventDeliveryRepository $eventDeliveryRepository,
|
||||
WebhookEventDeliveryManipulator $eventDeliveryManipulator,
|
||||
WebhookEventPayloadRepository $eventPayloadRepository,
|
||||
Client $client = null
|
||||
) {
|
||||
$this->applicationRepository = $applicationRepository;
|
||||
$this->processorFactory = $processorFactory;
|
||||
$this->eventRepository = $eventRepository;
|
||||
$this->eventManipulator = $eventManipulator;
|
||||
$this->eventDeliveryManipulator = $eventDeliveryManipulator;
|
||||
$this->eventDeliveryRepository = $eventDeliveryRepository;
|
||||
$this->eventPayloadRepository = $eventPayloadRepository;
|
||||
|
||||
$this->client = $client ?: new Client();
|
||||
$this->logger = new NullLogger();
|
||||
|
||||
$this->configureClient();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a logger instance on the object.
|
||||
*
|
||||
* @param LoggerInterface $logger
|
||||
*
|
||||
* @return null
|
||||
*/
|
||||
public function setLogger(LoggerInterface $logger)
|
||||
{
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
public function invoke(WebhookEvent $event)
|
||||
{
|
||||
$this->doInvoke($event, $this->applicationRepository->findWithDefinedWebhookCallback());
|
||||
}
|
||||
|
||||
public function invokeUnprocessedEvents()
|
||||
{
|
||||
$targetApplications = $this->applicationRepository->findWithDefinedWebhookCallback();
|
||||
|
||||
foreach ($this->eventRepository->getUnprocessedEventIterator() as $row) {
|
||||
/** @var WebhookEvent $event */
|
||||
$event = $row[0];
|
||||
|
||||
$this->doInvoke($event, $targetApplications);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WebhookEvent $event
|
||||
* @param ApiApplication[] $targets
|
||||
*/
|
||||
private function doInvoke(WebhookEvent $event, array $targets)
|
||||
{
|
||||
$this->eventManipulator->processed($event);
|
||||
$this->logger->info(sprintf('Processing event "%s" with id %d', $event->getName(), $event->getId()));
|
||||
|
||||
// send requests
|
||||
$this->doHttpDelivery($event, $targets);
|
||||
}
|
||||
|
||||
private function configureClient()
|
||||
{
|
||||
$this->client->getEventDispatcher()->addListener('request.error', function (Event $event) {
|
||||
// Override guzzle default behavior of throwing exceptions
|
||||
// when 4xx & 5xx responses are encountered
|
||||
$event->stopPropagation();
|
||||
}, -254);
|
||||
|
||||
// Set callback which logs success or failure
|
||||
$subscriber = new CallbackBackoffStrategy(function ($retries, Request $request, $response, $e) {
|
||||
$retry = true;
|
||||
if ($response && (null !== $deliverId = parse_url($request->getUrl(), PHP_URL_FRAGMENT))) {
|
||||
$delivery = $this->eventDeliveryRepository->find($deliverId);
|
||||
|
||||
$logContext = ['host' => $request->getHost()];
|
||||
|
||||
if ($response->isSuccessful()) {
|
||||
$this->eventDeliveryManipulator->deliverySuccess($delivery);
|
||||
|
||||
$logType = 'info';
|
||||
$logEntry = sprintf('Deliver success event "%d:%s" for app "%s"',
|
||||
$delivery->getWebhookEvent()->getId(), $delivery->getWebhookEvent()->getName(),
|
||||
$delivery->getThirdPartyApplication()->getName()
|
||||
);
|
||||
|
||||
$retry = false;
|
||||
} else {
|
||||
$this->eventDeliveryManipulator->deliveryFailure($delivery);
|
||||
|
||||
$logType = 'error';
|
||||
$logEntry = sprintf('Deliver failure event "%d:%s" for app "%s"',
|
||||
$delivery->getWebhookEvent()->getId(), $delivery->getWebhookEvent()->getName(),
|
||||
$delivery->getThirdPartyApplication()->getName()
|
||||
);
|
||||
}
|
||||
|
||||
$this->logger->log($logType, $logEntry, $logContext);
|
||||
|
||||
return $retry;
|
||||
}
|
||||
}, true, new CurlBackoffStrategy());
|
||||
|
||||
// Set max retries
|
||||
$subscriber = new TruncatedBackoffStrategy(WebhookEventDelivery::MAX_DELIVERY_TRIES, $subscriber);
|
||||
$subscriber = new BackoffPlugin($subscriber);
|
||||
|
||||
$this->client->addSubscriber($subscriber);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WebhookEvent $event
|
||||
* @param ApiApplication[] $targets
|
||||
*/
|
||||
private function doHttpDelivery(
|
||||
WebhookEvent $event,
|
||||
array $targets
|
||||
) {
|
||||
if (count($targets) === 0) {
|
||||
$this->logger->info(sprintf('No applications defined to listen for webhook events'));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Format event data
|
||||
$eventProcessor = $this->processorFactory->getProcessor($event);
|
||||
$data = $eventProcessor->process($event);
|
||||
|
||||
foreach ($targets as $thirdPartyApplication) {
|
||||
$delivery = $this->eventDeliveryManipulator->create($thirdPartyApplication, $event);
|
||||
// Append delivery id as url anchor
|
||||
$uniqueUrl = $this->buildUrl($thirdPartyApplication, $delivery);
|
||||
|
||||
// Create http request with data as request body
|
||||
$request = $this->client->createRequest('POST', $uniqueUrl, [
|
||||
'Content-Type' => 'application/vnd.phraseanet.event+json'
|
||||
], json_encode($data));
|
||||
|
||||
$requestBody = $request instanceof EntityEnclosingRequestInterface ? $request->getBody() : '';
|
||||
|
||||
try {
|
||||
$response = $request->send();
|
||||
|
||||
$responseBody = $response->getBody(true);
|
||||
$statusCode = $response->getStatusCode();
|
||||
$headers = $this->extractResponseHeaders($response);
|
||||
}
|
||||
catch (\Exception $exception) {
|
||||
$responseBody = $exception->getMessage();
|
||||
$statusCode = -1;
|
||||
$headers = '';
|
||||
}
|
||||
|
||||
$deliveryPayload = new WebhookEventPayload(
|
||||
$delivery,
|
||||
$requestBody,
|
||||
$responseBody,
|
||||
$statusCode,
|
||||
$headers
|
||||
);
|
||||
|
||||
$this->eventPayloadRepository->save($deliveryPayload);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ApiApplication $application
|
||||
* @param WebhookEventDelivery $delivery
|
||||
* @return string
|
||||
*/
|
||||
private function buildUrl(ApiApplication $application, WebhookEventDelivery $delivery)
|
||||
{
|
||||
return sprintf('%s#%s', $application->getWebhookUrl(), $delivery->getId());
|
||||
}
|
||||
|
||||
private function extractResponseHeaders(Response $response)
|
||||
{
|
||||
$headerCollection = $response->getHeaders()->toArray();
|
||||
$headers = '';
|
||||
|
||||
foreach ($headerCollection as $name => $value) {
|
||||
$headers .= sprintf('%s: %s', $name, $value) . PHP_EOL;
|
||||
}
|
||||
|
||||
return trim($headers);
|
||||
}
|
||||
}
|
57
lib/Alchemy/Phrasea/Webhook/WebhookPublisher.php
Normal file
57
lib/Alchemy/Phrasea/Webhook/WebhookPublisher.php
Normal file
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of phrasea-4.1.
|
||||
*
|
||||
* (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\Webhook;
|
||||
|
||||
use Alchemy\Phrasea\Model\Entities\WebhookEvent;
|
||||
use Alchemy\Queue\Message;
|
||||
use Alchemy\Queue\MessageQueueRegistry;
|
||||
|
||||
/**
|
||||
* Class WebhookPublisher publishes webhook event notifications in message queues
|
||||
* @package Alchemy\Phrasea\Webhook
|
||||
*/
|
||||
class WebhookPublisher
|
||||
{
|
||||
/**
|
||||
* @var MessageQueueRegistry
|
||||
*/
|
||||
private $queueRegistry;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $queueName;
|
||||
|
||||
/**
|
||||
* @param MessageQueueRegistry $queueRegistry
|
||||
* @param $queueName
|
||||
*/
|
||||
public function __construct(MessageQueueRegistry $queueRegistry, $queueName)
|
||||
{
|
||||
$this->queueRegistry = $queueRegistry;
|
||||
$this->queueName = $queueName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param WebhookEvent $event
|
||||
*/
|
||||
public function publishWebhookEvent(WebhookEvent $event)
|
||||
{
|
||||
$queue = $this->queueRegistry->getQueue($this->queueName);
|
||||
$payload = [
|
||||
'message_type' => 'webhook',
|
||||
'payload' => [ 'id' => $event->getId() ]
|
||||
];
|
||||
|
||||
$queue->publish(new Message(json_encode($payload)));
|
||||
}
|
||||
}
|
@@ -1,95 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Alchemy\Phrasea\Exception\RuntimeException;
|
||||
|
||||
class API_Webhook
|
||||
{
|
||||
const NEW_FEED_ENTRY = "new_feed_entry";
|
||||
|
||||
protected $appbox;
|
||||
protected $id;
|
||||
protected $type;
|
||||
protected $data;
|
||||
protected $created;
|
||||
|
||||
public function __construct(appbox $appbox, $id)
|
||||
{
|
||||
$this->appbox = $appbox;
|
||||
$this->id = $id;
|
||||
$sql = 'SELECT `type`, `data`, created
|
||||
FROM api_webhooks
|
||||
WHERE id = :id';
|
||||
$stmt = $this->appbox->get_connection()->prepare($sql);
|
||||
$stmt->execute([':id' => $id]);
|
||||
$row = $stmt->fetch(\PDO::FETCH_ASSOC);
|
||||
|
||||
if (!$row) {
|
||||
throw new RuntimeException('Webhooks not found');
|
||||
}
|
||||
|
||||
$stmt->closeCursor();
|
||||
|
||||
$this->type = $row['type'];
|
||||
$this->data = json_decode($row['data']);
|
||||
$this->created = new \DateTime($row['created']);
|
||||
}
|
||||
|
||||
public function delete()
|
||||
{
|
||||
$sql = 'DELETE FROM api_webhooks WHERE id = :id';
|
||||
|
||||
$stmt = $this->appbox->get_connection()->prepare($sql);
|
||||
$stmt->execute([':id' => $this->id]);
|
||||
$stmt->closeCursor();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
public static function create(appbox $appbox, $type, array $data)
|
||||
{
|
||||
$sql = 'INSERT INTO api_webhooks (id, `type`, `data`, created)
|
||||
VALUES (null, :type, :data, NOW())';
|
||||
|
||||
$stmt = $appbox->get_connection()->prepare($sql);
|
||||
$stmt->execute([
|
||||
'type' => $type,
|
||||
'data' => json_encode($data),
|
||||
]);
|
||||
$stmt->closeCursor();
|
||||
|
||||
return new API_Webhook($appbox, $appbox->get_connection()->lastInsertId());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \DateTime
|
||||
*/
|
||||
public function getCreated()
|
||||
{
|
||||
return $this->created;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getData()
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getType()
|
||||
{
|
||||
return $this->type;
|
||||
}
|
||||
}
|
@@ -523,22 +523,16 @@ class Bridge_Api_Dailymotion extends Bridge_Api_Abstract implements Bridge_Api_I
|
||||
switch ($connector_status) {
|
||||
case self::UPLOAD_STATE_DELETED:
|
||||
return $this->translator->trans('La video a ete supprimee');
|
||||
break;
|
||||
case self::UPLOAD_STATE_REJECTED:
|
||||
return $this->translator->trans('La video a ete rejetee');
|
||||
break;
|
||||
case self::UPLOAD_STATE_ENCODING_ERROR:
|
||||
return $this->translator->trans('Erreur d\'encodage');
|
||||
break;
|
||||
case self::UPLOAD_STATE_PROCESSING:
|
||||
return $this->translator->trans('En cours d\'encodage');
|
||||
break;
|
||||
default:
|
||||
return '';
|
||||
break;
|
||||
case self::UPLOAD_STATE_DONE:
|
||||
return $this->translator->trans('OK');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -484,11 +484,9 @@ class Bridge_Api_Flickr extends Bridge_Api_Abstract implements Bridge_Api_Interf
|
||||
switch ($connector_status) {
|
||||
case self::UPLOAD_STATE_FAILED:
|
||||
return $this->translator->trans('L\'upload a echoue');
|
||||
break;
|
||||
default:
|
||||
case self::UPLOAD_STATE_DONE:
|
||||
return '';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -17,6 +17,7 @@ use Alchemy\Phrasea\Core\Thumbnail\ThumbnailedElement;
|
||||
use Alchemy\Phrasea\Core\Version\DataboxVersionRepository;
|
||||
use Alchemy\Phrasea\Databox\DataboxRepository;
|
||||
use Alchemy\Phrasea\Databox\Record\RecordRepository;
|
||||
use Alchemy\Phrasea\Databox\SubdefGroup;
|
||||
use Alchemy\Phrasea\Exception\InvalidArgumentException;
|
||||
use Alchemy\Phrasea\Model\Entities\User;
|
||||
use Alchemy\Phrasea\Status\StatusStructure;
|
||||
@@ -450,8 +451,9 @@ class databox extends base implements ThumbnailedElement
|
||||
|
||||
$multi = isset($field['multi']) ? (Boolean) (string) $field['multi'] : false;
|
||||
|
||||
$meta_struct_field = databox_field::create($this->app, $this, $fname, $multi);
|
||||
$meta_struct_field = databox_field::create($this->app, $this, $fname);
|
||||
$meta_struct_field
|
||||
->set_multi($multi)
|
||||
->set_readonly(isset($field['readonly']) ? (string) $field['readonly'] : 0)
|
||||
->set_indexable(isset($field['index']) ? (string) $field['index'] : '1')
|
||||
->set_separator(isset($field['separator']) ? (string) $field['separator'] : '')
|
||||
@@ -892,7 +894,7 @@ class databox extends base implements ThumbnailedElement
|
||||
}
|
||||
|
||||
/**
|
||||
* @return databox_subdefsStructure|\Alchemy\Phrasea\Databox\SubdefGroup[]|databox_subdef[][]
|
||||
* @return databox_subdefsStructure|SubdefGroup[]
|
||||
*/
|
||||
public function get_subdef_structure()
|
||||
{
|
||||
|
@@ -564,6 +564,18 @@ class databox_field implements cache_cacheableInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param boolean $bool
|
||||
* @return databox_field
|
||||
*/
|
||||
public function set_multi($bool)
|
||||
{
|
||||
$this->multi = (bool)$bool;
|
||||
$this->separator = self::checkMultiSeparator($this->separator, $this->multi);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a vocabulary
|
||||
*
|
||||
@@ -892,7 +904,7 @@ class databox_field implements cache_cacheableInterface
|
||||
*
|
||||
* @throws \Exception_InvalidArgument
|
||||
*/
|
||||
public static function create(Application $app, databox $databox, $name, $multi)
|
||||
public static function create(Application $app, databox $databox, $name)
|
||||
{
|
||||
$sorter = 0;
|
||||
|
||||
@@ -911,8 +923,8 @@ class databox_field implements cache_cacheableInterface
|
||||
`thumbtitle`, `multi`, `business`, `aggregable`,
|
||||
`report`, `sorter`, `separator`)
|
||||
VALUES (null, :name, '', 0, 0, 1, 'string', '',
|
||||
null, :multi,
|
||||
0, 0, 1, :sorter, '')";
|
||||
null, 0, 0, 0,
|
||||
1, :sorter, '')";
|
||||
|
||||
$name = self::generateName($name);
|
||||
|
||||
@@ -920,10 +932,8 @@ class databox_field implements cache_cacheableInterface
|
||||
throw new \Exception_InvalidArgument();
|
||||
}
|
||||
|
||||
$multi = $multi ? 1 : 0;
|
||||
|
||||
$stmt = $databox->get_connection()->prepare($sql);
|
||||
$stmt->execute([':name' => $name, ':sorter' => $sorter, ':multi' => $multi]);
|
||||
$stmt->execute([':name' => $name, ':sorter' => $sorter]);
|
||||
$id = $databox->get_connection()->lastInsertId();
|
||||
$stmt->closeCursor();
|
||||
|
||||
|
@@ -1,5 +1,4 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
@@ -9,18 +8,37 @@
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Alchemy\Phrasea\Media\Subdef\Image;
|
||||
use Alchemy\Phrasea\Media\Subdef\Audio;
|
||||
use Alchemy\Phrasea\Media\Subdef\Video;
|
||||
use Alchemy\Phrasea\Media\Subdef\FlexPaper;
|
||||
use Alchemy\Phrasea\Media\Subdef\Gif;
|
||||
use Alchemy\Phrasea\Media\Subdef\Image;
|
||||
use Alchemy\Phrasea\Media\Subdef\Subdef as SubdefSpecs;
|
||||
use Alchemy\Phrasea\Media\Subdef\Video;
|
||||
use Alchemy\Phrasea\Media\Type\Type as SubdefType;
|
||||
use MediaAlchemyst\Specification\SpecificationInterface;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
|
||||
class databox_subdef
|
||||
{
|
||||
const CLASS_THUMBNAIL = 'thumbnail';
|
||||
const CLASS_PREVIEW = 'preview';
|
||||
const CLASS_DOCUMENT = 'document';
|
||||
|
||||
const DEVICE_ALL = 'all';
|
||||
const DEVICE_HANDHELD = 'handheld';
|
||||
const DEVICE_PRINT = 'print';
|
||||
const DEVICE_PROJECTION = 'projection';
|
||||
const DEVICE_SCREEN = 'screen';
|
||||
const DEVICE_TV = 'tv';
|
||||
|
||||
protected static $mediaTypeToSubdefTypes = [
|
||||
SubdefType::TYPE_AUDIO => [SubdefSpecs::TYPE_IMAGE, SubdefSpecs::TYPE_AUDIO],
|
||||
SubdefType::TYPE_DOCUMENT => [SubdefSpecs::TYPE_IMAGE, SubdefSpecs::TYPE_FLEXPAPER],
|
||||
SubdefType::TYPE_FLASH => [SubdefSpecs::TYPE_IMAGE],
|
||||
SubdefType::TYPE_IMAGE => [SubdefSpecs::TYPE_IMAGE],
|
||||
SubdefType::TYPE_VIDEO => [SubdefSpecs::TYPE_IMAGE, SubdefSpecs::TYPE_VIDEO, SubdefSpecs::TYPE_ANIMATION],
|
||||
];
|
||||
|
||||
/**
|
||||
* The class type of the subdef
|
||||
* Is null or one of the CLASS_* constants
|
||||
@@ -33,37 +51,23 @@ class databox_subdef
|
||||
protected $path;
|
||||
protected $subdef_group;
|
||||
protected $labels = [];
|
||||
protected $downloadable;
|
||||
protected $translator;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $requiresMetadataUpdate;
|
||||
protected $downloadable;
|
||||
protected $translator;
|
||||
protected static $mediaTypeToSubdefTypes = [
|
||||
SubdefType::TYPE_AUDIO => [SubdefSpecs::TYPE_IMAGE, SubdefSpecs::TYPE_AUDIO],
|
||||
SubdefType::TYPE_DOCUMENT => [SubdefSpecs::TYPE_IMAGE, SubdefSpecs::TYPE_FLEXPAPER],
|
||||
SubdefType::TYPE_FLASH => [SubdefSpecs::TYPE_IMAGE],
|
||||
SubdefType::TYPE_IMAGE => [SubdefSpecs::TYPE_IMAGE],
|
||||
SubdefType::TYPE_VIDEO => [SubdefSpecs::TYPE_IMAGE, SubdefSpecs::TYPE_VIDEO, SubdefSpecs::TYPE_ANIMATION],
|
||||
];
|
||||
|
||||
const CLASS_THUMBNAIL = 'thumbnail';
|
||||
const CLASS_PREVIEW = 'preview';
|
||||
const CLASS_DOCUMENT = 'document';
|
||||
const DEVICE_ALL = 'all';
|
||||
const DEVICE_HANDHELD = 'handheld';
|
||||
const DEVICE_PRINT = 'print';
|
||||
const DEVICE_PROJECTION = 'projection';
|
||||
const DEVICE_SCREEN = 'screen';
|
||||
const DEVICE_TV = 'tv';
|
||||
|
||||
/**
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $orderable;
|
||||
|
||||
/**
|
||||
* @param SubdefType $type
|
||||
* @param SimpleXMLElement $sd
|
||||
*
|
||||
* @return databox_subdef
|
||||
* @param TranslatorInterface $translator
|
||||
*/
|
||||
public function __construct(SubdefType $type, SimpleXMLElement $sd, TranslatorInterface $translator)
|
||||
{
|
||||
@@ -77,6 +81,7 @@ class databox_subdef
|
||||
|
||||
$this->name = strtolower($sd->attributes()->name);
|
||||
$this->downloadable = p4field::isyes($sd->attributes()->downloadable);
|
||||
$this->orderable = isset($sd->attributes()->orderable) ? p4field::isyes($sd->attributes()->orderable) : true;
|
||||
$this->path = trim($sd->path) !== '' ? p4string::addEndSlash(trim($sd->path)) : '';
|
||||
|
||||
$this->requiresMetadataUpdate = p4field::isyes((string) $sd->meta);
|
||||
@@ -110,7 +115,130 @@ class databox_subdef
|
||||
}
|
||||
|
||||
/**
|
||||
* Build Image Subdef object depending the SimpleXMLElement
|
||||
*
|
||||
* @param SimpleXMLElement $sd
|
||||
* @return Image
|
||||
*/
|
||||
protected function buildImageSubdef(SimpleXMLElement $sd)
|
||||
{
|
||||
$image = new Image($this->translator);
|
||||
|
||||
if ($sd->icodec) {
|
||||
$image->setOptionValue(Image::OPTION_ICODEC, (string) $sd->icodec);
|
||||
}
|
||||
if ($sd->size) {
|
||||
$image->setOptionValue(Image::OPTION_SIZE, (int) $sd->size);
|
||||
}
|
||||
if ($sd->quality) {
|
||||
$image->setOptionValue(Image::OPTION_QUALITY, (int) $sd->quality);
|
||||
}
|
||||
if ($sd->strip) {
|
||||
$image->setOptionValue(Image::OPTION_STRIP, p4field::isyes($sd->strip));
|
||||
}
|
||||
if ($sd->dpi) {
|
||||
$image->setOptionValue(Image::OPTION_RESOLUTION, (int) $sd->dpi);
|
||||
}
|
||||
if ($sd->flatten) {
|
||||
$image->setOptionValue(Image::OPTION_FLATTEN, p4field::isyes($sd->flatten));
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build Audio Subdef object depending the SimpleXMLElement
|
||||
*
|
||||
* @param SimpleXMLElement $sd
|
||||
* @return Audio
|
||||
*/
|
||||
protected function buildAudioSubdef(SimpleXMLElement $sd)
|
||||
{
|
||||
$audio = new Audio($this->translator);
|
||||
|
||||
if ($sd->acodec) {
|
||||
$audio->setOptionValue(Audio::OPTION_ACODEC, (string) $sd->acodec);
|
||||
}
|
||||
if ($sd->audiobitrate) {
|
||||
$audio->setOptionValue(Audio::OPTION_AUDIOBITRATE, (int) $sd->audiobitrate);
|
||||
}
|
||||
if ($sd->audiosamplerate) {
|
||||
$audio->setOptionValue(Audio::OPTION_AUDIOSAMPLERATE, (int) $sd->audiosamplerate);
|
||||
}
|
||||
|
||||
return $audio;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build Video Subdef object depending the SimpleXMLElement
|
||||
*
|
||||
* @param SimpleXMLElement $sd
|
||||
* @return Video
|
||||
*/
|
||||
protected function buildVideoSubdef(SimpleXMLElement $sd)
|
||||
{
|
||||
$video = new Video($this->translator);
|
||||
|
||||
if ($sd->size) {
|
||||
$video->setOptionValue(Video::OPTION_SIZE, (int) $sd->size);
|
||||
}
|
||||
if ($sd->acodec) {
|
||||
$video->setOptionValue(Video::OPTION_ACODEC, (string) $sd->acodec);
|
||||
}
|
||||
if ($sd->vcodec) {
|
||||
$video->setOptionValue(Video::OPTION_VCODEC, (string) $sd->vcodec);
|
||||
}
|
||||
if ($sd->fps) {
|
||||
$video->setOptionValue(Video::OPTION_FRAMERATE, (int) $sd->fps);
|
||||
}
|
||||
if ($sd->bitrate) {
|
||||
$video->setOptionValue(Video::OPTION_BITRATE, (int) $sd->bitrate);
|
||||
}
|
||||
if ($sd->audiobitrate) {
|
||||
$video->setOptionValue(Video::OPTION_AUDIOBITRATE, (int) $sd->audiobitrate);
|
||||
}
|
||||
if ($sd->audiosamplerate) {
|
||||
$video->setOptionValue(Video::OPTION_AUDIOSAMPLERATE, (int) $sd->audiosamplerate);
|
||||
}
|
||||
if ($sd->GOPsize) {
|
||||
$video->setOptionValue(Video::OPTION_GOPSIZE, (int) $sd->GOPsize);
|
||||
}
|
||||
|
||||
return $video;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build GIF Subdef object depending the SimpleXMLElement
|
||||
*
|
||||
* @param SimpleXMLElement $sd
|
||||
* @return Gif
|
||||
*/
|
||||
protected function buildGifSubdef(SimpleXMLElement $sd)
|
||||
{
|
||||
$gif = new Gif($this->translator);
|
||||
|
||||
if ($sd->size) {
|
||||
$gif->setOptionValue(Gif::OPTION_SIZE, (int) $sd->size);
|
||||
}
|
||||
if ($sd->delay) {
|
||||
$gif->setOptionValue(Gif::OPTION_DELAY, (int) $sd->delay);
|
||||
}
|
||||
|
||||
return $gif;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build Flexpaper Subdef object depending the SimpleXMLElement
|
||||
*
|
||||
* @param SimpleXMLElement $sd
|
||||
* @return FlexPaper
|
||||
*/
|
||||
protected function buildFlexPaperSubdef(SimpleXMLElement $sd)
|
||||
{
|
||||
return new FlexPaper($this->translator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function get_class()
|
||||
@@ -119,7 +247,6 @@ class databox_subdef
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_path()
|
||||
@@ -130,7 +257,7 @@ class databox_subdef
|
||||
/**
|
||||
* The devices matching this subdefinition
|
||||
*
|
||||
* @return Array
|
||||
* @return array
|
||||
*/
|
||||
public function getDevices()
|
||||
{
|
||||
@@ -140,7 +267,7 @@ class databox_subdef
|
||||
/**
|
||||
* The current SubdefType the subdef converts documents
|
||||
*
|
||||
* @return Alchemy\Phrasea\Media\Subdef\Subdef
|
||||
* @return \Alchemy\Phrasea\Media\Subdef\Subdef
|
||||
*/
|
||||
public function getSubdefType()
|
||||
{
|
||||
@@ -160,7 +287,7 @@ class databox_subdef
|
||||
/**
|
||||
* An associative label ; keys are i18n languages
|
||||
*
|
||||
* @return Array
|
||||
* @return array
|
||||
*/
|
||||
public function get_labels()
|
||||
{
|
||||
@@ -179,15 +306,31 @@ class databox_subdef
|
||||
}
|
||||
|
||||
/**
|
||||
* boolean
|
||||
* The name of the subdef
|
||||
*
|
||||
* @return type
|
||||
* @return string
|
||||
*/
|
||||
public function is_downloadable()
|
||||
public function get_name()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isDownloadable()
|
||||
{
|
||||
return $this->downloadable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isOrderable()
|
||||
{
|
||||
return $this->orderable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an array of Alchemy\Phrasea\Media\Subdef\Subdef available for the current Media Type
|
||||
*
|
||||
@@ -254,16 +397,6 @@ class databox_subdef
|
||||
return $this->requiresMetadataUpdate;
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of the subdef
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function get_name()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the MediaAlchemyst specs for the current subdef
|
||||
*
|
||||
@@ -283,128 +416,4 @@ class databox_subdef
|
||||
{
|
||||
return $this->subdef_type->getOptions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build Image Subdef object depending the SimpleXMLElement
|
||||
*
|
||||
* @param SimpleXMLElement $sd
|
||||
* @return Image
|
||||
*/
|
||||
protected function buildImageSubdef(SimpleXMLElement $sd)
|
||||
{
|
||||
$image = new Image($this->translator);
|
||||
|
||||
if ($sd->icodec) {
|
||||
$image->setOptionValue(Image::OPTION_ICODEC, (string) $sd->icodec);
|
||||
}
|
||||
if ($sd->size) {
|
||||
$image->setOptionValue(Image::OPTION_SIZE, (int) $sd->size);
|
||||
}
|
||||
if ($sd->quality) {
|
||||
$image->setOptionValue(Image::OPTION_QUALITY, (int) $sd->quality);
|
||||
}
|
||||
if ($sd->strip) {
|
||||
$image->setOptionValue(Image::OPTION_STRIP, p4field::isyes($sd->strip));
|
||||
}
|
||||
if ($sd->dpi) {
|
||||
$image->setOptionValue(Image::OPTION_RESOLUTION, (int) $sd->dpi);
|
||||
}
|
||||
if ($sd->flatten) {
|
||||
$image->setOptionValue(Image::OPTION_FLATTEN, p4field::isyes($sd->flatten));
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build Audio Subdef object depending the SimpleXMLElement
|
||||
*
|
||||
* @param SimpleXMLElement $sd
|
||||
* @return Audio
|
||||
*/
|
||||
protected function buildAudioSubdef(SimpleXMLElement $sd)
|
||||
{
|
||||
$audio = new Audio($this->translator);
|
||||
|
||||
if ($sd->acodec) {
|
||||
$audio->setOptionValue(Audio::OPTION_ACODEC, (string) $sd->acodec);
|
||||
}
|
||||
if ($sd->audiobitrate) {
|
||||
$audio->setOptionValue(Audio::OPTION_AUDIOBITRATE, (int) $sd->audiobitrate);
|
||||
}
|
||||
if ($sd->audiosamplerate) {
|
||||
$audio->setOptionValue(Audio::OPTION_AUDIOSAMPLERATE, (int) $sd->audiosamplerate);
|
||||
}
|
||||
|
||||
return $audio;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build Flexpaper Subdef object depending the SimpleXMLElement
|
||||
*
|
||||
* @param SimpleXMLElement $sd
|
||||
* @return \Alchemy\Phrasea\Media\Subdef\Video
|
||||
*/
|
||||
protected function buildFlexPaperSubdef(SimpleXMLElement $sd)
|
||||
{
|
||||
return new FlexPaper($this->translator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build GIF Subdef object depending the SimpleXMLElement
|
||||
*
|
||||
* @param SimpleXMLElement $sd
|
||||
* @return Gif
|
||||
*/
|
||||
protected function buildGifSubdef(SimpleXMLElement $sd)
|
||||
{
|
||||
$gif = new Gif($this->translator);
|
||||
|
||||
if ($sd->size) {
|
||||
$gif->setOptionValue(Gif::OPTION_SIZE, (int) $sd->size);
|
||||
}
|
||||
if ($sd->delay) {
|
||||
$gif->setOptionValue(Gif::OPTION_DELAY, (int) $sd->delay);
|
||||
}
|
||||
|
||||
return $gif;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build Video Subdef object depending the SimpleXMLElement
|
||||
*
|
||||
* @param SimpleXMLElement $sd
|
||||
* @return Video
|
||||
*/
|
||||
protected function buildVideoSubdef(SimpleXMLElement $sd)
|
||||
{
|
||||
$video = new Video($this->translator);
|
||||
|
||||
if ($sd->size) {
|
||||
$video->setOptionValue(Video::OPTION_SIZE, (int) $sd->size);
|
||||
}
|
||||
if ($sd->acodec) {
|
||||
$video->setOptionValue(Video::OPTION_ACODEC, (string) $sd->acodec);
|
||||
}
|
||||
if ($sd->vcodec) {
|
||||
$video->setOptionValue(Video::OPTION_VCODEC, (string) $sd->vcodec);
|
||||
}
|
||||
if ($sd->fps) {
|
||||
$video->setOptionValue(Video::OPTION_FRAMERATE, (int) $sd->fps);
|
||||
}
|
||||
if ($sd->bitrate) {
|
||||
$video->setOptionValue(Video::OPTION_BITRATE, (int) $sd->bitrate);
|
||||
}
|
||||
if ($sd->audiobitrate) {
|
||||
$video->setOptionValue(Video::OPTION_AUDIOBITRATE, (int) $sd->audiobitrate);
|
||||
}
|
||||
if ($sd->audiosamplerate) {
|
||||
$video->setOptionValue(Video::OPTION_AUDIOSAMPLERATE, (int) $sd->audiosamplerate);
|
||||
}
|
||||
if ($sd->GOPsize) {
|
||||
$video->setOptionValue(Video::OPTION_GOPSIZE, (int) $sd->GOPsize);
|
||||
}
|
||||
|
||||
return $video;
|
||||
}
|
||||
}
|
||||
|
@@ -10,6 +10,7 @@
|
||||
|
||||
use Alchemy\Phrasea\Databox\SubdefGroup;
|
||||
use Alchemy\Phrasea\Media\MediaTypeFactory;
|
||||
use Assert\Assertion;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
|
||||
class databox_subdefsStructure implements IteratorAggregate, Countable
|
||||
@@ -215,6 +216,25 @@ class databox_subdefsStructure implements IteratorAggregate, Countable
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param SubdefGroup[] $groups
|
||||
*/
|
||||
public function updateSubdefGroups($groups)
|
||||
{
|
||||
Assertion::allIsInstanceOf($groups, SubdefGroup::class);
|
||||
|
||||
$dom_xp = $this->databox->get_xpath_structure();
|
||||
|
||||
foreach ($groups as $group) {
|
||||
$nodes = $dom_xp->query('//record/subdefs/subdefgroup[@name="' . $group->getName() . '"]');
|
||||
|
||||
/** @var DOMElement $node */
|
||||
foreach ($nodes as $node) {
|
||||
$node->setAttribute('document_orderable', ($group->isDocumentOrderable() ? 'true' : 'false'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $group
|
||||
* @param string $name
|
||||
@@ -222,10 +242,11 @@ class databox_subdefsStructure implements IteratorAggregate, Countable
|
||||
* @param boolean $downloadable
|
||||
* @param array $options
|
||||
* @param array $labels
|
||||
* @param bool $orderable
|
||||
* @return databox_subdefsStructure
|
||||
* @throws Exception
|
||||
*/
|
||||
public function set_subdef($group, $name, $class, $downloadable, $options, $labels)
|
||||
public function set_subdef($group, $name, $class, $downloadable, $options, $labels, $orderable = true)
|
||||
{
|
||||
$dom_struct = $this->databox->get_dom_structure();
|
||||
|
||||
@@ -233,6 +254,7 @@ class databox_subdefsStructure implements IteratorAggregate, Countable
|
||||
$subdef->setAttribute('class', $class);
|
||||
$subdef->setAttribute('name', mb_strtolower($name));
|
||||
$subdef->setAttribute('downloadable', ($downloadable ? 'true' : 'false'));
|
||||
$subdef->setAttribute('orderable', ($orderable ? 'true' : 'false'));
|
||||
|
||||
foreach ($labels as $code => $label) {
|
||||
$child = $dom_struct->createElement('label');
|
||||
|
@@ -165,7 +165,7 @@ class eventsmanager_broker
|
||||
}
|
||||
|
||||
if (((int) $page + 1) * $n < $total) {
|
||||
$data['next'] = '<a href="#" onclick="print_notifications(' . ((int) $page + 1) . ');return false;">' . $this->app->trans('charger d\'avantages de notifications') . '</a>';
|
||||
$data['next'] = '<a href="#" class="notification__print-action" data-page="' . ((int) $page + 1) . '">' . $this->app->trans('charger d\'avantages de notifications') . '</a>';
|
||||
}
|
||||
|
||||
return $data;
|
||||
|
@@ -39,8 +39,11 @@ class eventsmanager_notify_push extends eventsmanager_notifyAbstract
|
||||
$sender = $user->getDisplayName();
|
||||
|
||||
$ret = [
|
||||
'text' => $this->app->trans('%user% vous a envoye un %before_link% panier %after_link%', ['%user%' => $sender, '%before_link%' => '<a href="#" onclick="openPreview(this, \'BASK\',1,\''
|
||||
. $data['ssel_id'] . '\');return false;">', '%after_link%' => '</a>'])
|
||||
'text' => $this->app->trans('%user% vous a envoye un %before_link% panier %after_link%', ['%user%' => $sender, '%before_link%' => '<a href="#"
|
||||
data-kind="BASK"
|
||||
data-position="1"
|
||||
data-id="'. $data['ssel_id'] . '"
|
||||
class="open-preview-action">', '%after_link%' => '</a>'])
|
||||
, 'class' => ($unread == 1 ? 'reload_baskets' : '')
|
||||
];
|
||||
|
||||
|
@@ -53,8 +53,7 @@ class eventsmanager_notify_validationreminder extends eventsmanager_notifyAbstra
|
||||
$basket_name = $this->app->trans('Une selection');
|
||||
}
|
||||
|
||||
$bask_link = '<a href="#" onclick="openPreview(this, \'BASK\',1,\''
|
||||
. $ssel_id . '\');return false;">'
|
||||
$bask_link = '<a href="#" data-kind="BASK" data-position="1" data-id="'. $ssel_id . '" class="open-preview-action">'
|
||||
. $basket_name . '</a>';
|
||||
|
||||
$ret = [
|
||||
|
@@ -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,7 +10,6 @@
|
||||
|
||||
class p4field
|
||||
{
|
||||
|
||||
public static function isyes($v)
|
||||
{
|
||||
$v = mb_strtolower(trim($v));
|
||||
|
@@ -108,7 +108,7 @@ class patch_370alpha6a extends patchAbstract
|
||||
$options['meta'] = $subdef->isMetadataUpdateRequired() ? 'yes' : 'no';
|
||||
$options['devices'] = [databox_subdef::DEVICE_SCREEN];
|
||||
|
||||
$root->set_subdef($groupname, $subdef->get_name(), $subdef->get_class(), $subdef->is_downloadable(), $options, []);
|
||||
$root->set_subdef($groupname, $subdef->get_name(), $subdef->get_class(), $subdef->isDownloadable(), $options, []);
|
||||
}
|
||||
|
||||
protected function addMobileSubdefVideo($root, $baseSubdef, $groupname)
|
||||
|
@@ -77,7 +77,7 @@ class patch_390alpha13a implements patchInterface
|
||||
|
||||
foreach ($rs as $row) {
|
||||
try {
|
||||
$user = $em->createQuery('SELECT PARTIAL u.{id} FROM Phraseanet:User s WHERE u.id = :id')
|
||||
$user = $em->createQuery('SELECT PARTIAL u.{id} FROM Phraseanet:User u WHERE u.id = :id')
|
||||
->setParameters(['id' => $row['usr_id']])
|
||||
->setHint(Query::HINT_FORCE_PARTIAL_LOAD, true)
|
||||
->getSingleResult();
|
||||
|
@@ -122,18 +122,18 @@ class patch_390alpha6a extends patchAbstract
|
||||
$stmt->execute(['export_id' => $row['id']]);
|
||||
$rs = $stmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||
|
||||
foreach ($rs as $element) {
|
||||
foreach ($rs as $element_row) {
|
||||
$element = new FtpExportElement();
|
||||
$element->setBaseId($row['base_id'])
|
||||
->setRecordId($row['record_id'])
|
||||
->setBusinessfields($row['businessfields'])
|
||||
$element->setBaseId($element_row['base_id'])
|
||||
->setRecordId($element_row['record_id'])
|
||||
->setBusinessfields($element_row['businessfields'])
|
||||
->setCreated(new \DateTime($row['date']))
|
||||
->setUpdated(new \DateTime($row['date']))
|
||||
->setDone(!!$row['done'])
|
||||
->setError(!!$row['error'])
|
||||
->setFilename($row['filename'])
|
||||
->setFolder($row['folder'])
|
||||
->setSubdef($row['subdef'])
|
||||
->setDone(!!$element_row['done'])
|
||||
->setError(!!$element_row['error'])
|
||||
->setFilename($element_row['filename'])
|
||||
->setFolder($element_row['folder'])
|
||||
->setSubdef($element_row['subdef'])
|
||||
->setExport($export);
|
||||
|
||||
$export->addElement($element);
|
||||
|
@@ -1,286 +0,0 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Phraseanet
|
||||
*
|
||||
* (c) 2005-2016 Alchemy
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Alchemy\Phrasea\Application;
|
||||
use Symfony\Component\Translation\TranslatorInterface;
|
||||
|
||||
class queries
|
||||
{
|
||||
public static function tree_topics($I18N)
|
||||
{
|
||||
$out = '';
|
||||
|
||||
$xmlTopics = null;
|
||||
$sxTopics = null;
|
||||
|
||||
if (file_exists(__DIR__ . '/../../config/topics/topics_' . $I18N . '.xml'))
|
||||
$xmlTopics = __DIR__ . '/../../config/topics/topics_' . $I18N . '.xml';
|
||||
|
||||
if (! $xmlTopics) {
|
||||
if (file_exists(__DIR__ . '/../../config/topics/topics.xml')) {
|
||||
$xmlTopics = __DIR__ . '/../../config/topics/topics.xml';
|
||||
}
|
||||
}
|
||||
|
||||
$cssTopics = '';
|
||||
if ($xmlTopics && false !== $sxTopics = simplexml_load_file($xmlTopics)) {
|
||||
$cssTopics = (string) $sxTopics->display->css;
|
||||
}
|
||||
|
||||
$out .= '<style type="text/css">
|
||||
' . $cssTopics . '
|
||||
</style>';
|
||||
|
||||
$out .='<div class="searchZone" >
|
||||
<div class="linktopics1" >';
|
||||
|
||||
if ($sxTopics) {
|
||||
$defaultview = mb_strtolower($sxTopics->display->defaultview);
|
||||
if ( ! $defaultview)
|
||||
$defaultview = 'static';
|
||||
$out .= ( "<ul id='TOPIC_UL' class='nobox'>\n");
|
||||
$out .= self::drawTopics($sxTopics->topics, 0, '', $defaultview);
|
||||
$out .= ( "\n</ul>\n");
|
||||
}
|
||||
|
||||
$out .= '</div>
|
||||
</div>';
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
public static function topics_exists($I18n)
|
||||
{
|
||||
if (file_exists(__DIR__ . '/../../config/topics/topics_' . $I18n . '.xml')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (file_exists(__DIR__ . '/../../config/topics/topics.xml')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static function dropdown_topics(TranslatorInterface $translator, $I18n)
|
||||
{
|
||||
$out = '';
|
||||
|
||||
$xmlTopics = '';
|
||||
$sxTopics = null;
|
||||
|
||||
if (file_exists(__DIR__ . '/../../config/topics/topics_' . $I18n . '.xml'))
|
||||
$xmlTopics = __DIR__ . '/../../config/topics/topics_' . $I18n . '.xml';
|
||||
|
||||
if ($xmlTopics == '') {
|
||||
if (file_exists(__DIR__ . '/../../config/topics/topics.xml')) {
|
||||
$xmlTopics = __DIR__ . '/../../config/topics/topics.xml';
|
||||
}
|
||||
}
|
||||
|
||||
if ($xmlTopics == '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
$jsTopics = 'null';
|
||||
$maxdepth = 0;
|
||||
if (false !== $sxTopics = simplexml_load_file($xmlTopics)) {
|
||||
$jsTopics = self::topicsAsJS($sxTopics->topics, 0, $maxdepth);
|
||||
}
|
||||
|
||||
$out .= ' <script type="text/javascript">
|
||||
var maxdepth = ' . ($maxdepth + 1) . ';
|
||||
var topics = ' . $jsTopics . ';
|
||||
var current_popqry = "";
|
||||
|
||||
function doSearchTopPop(qry)
|
||||
{
|
||||
var qft = document.forms["pops"].qry.value;
|
||||
if(qft != "" && current_popqry != "")
|
||||
qry = "("+qft+") AND ("+current_popqry+")";
|
||||
else
|
||||
qry = qft+current_popqry;
|
||||
|
||||
if(qry=="")
|
||||
qry = "all";
|
||||
|
||||
doSpecialSearch(qry,true);
|
||||
|
||||
return;
|
||||
}
|
||||
function chgPopTopic(ipop)
|
||||
{
|
||||
if(ipop > ' . ($maxdepth + 1) . ')
|
||||
|
||||
return;
|
||||
var i,j;
|
||||
var _topics = topics;
|
||||
var zpop;
|
||||
current_popqry = "";
|
||||
for (i=0; _topics && i<ipop; i++) {
|
||||
zpop = document.forms["pops"]["popTopic_"+i];
|
||||
if((j = zpop.selectedIndex) > 0)
|
||||
current_popqry = zpop.options[j].value;
|
||||
j--;
|
||||
if(_topics[j] && _topics[j].topics)
|
||||
_topics = _topics[j].topics;
|
||||
else
|
||||
_topics = null;
|
||||
}
|
||||
if(ipop == ' . ($maxdepth + 1) . ')
|
||||
|
||||
return;
|
||||
zpop = document.forms["pops"]["popTopic_"+ipop];
|
||||
if (_topics) {
|
||||
while(zpop.options[0])
|
||||
zpop.options[0] = null;
|
||||
zpop.options[0] = new Option("All", "");
|
||||
for(j=0; j<_topics.length; j++)
|
||||
zpop.options[j+1] = new Option(_topics[j].label, _topics[j].query);
|
||||
zpop.selectedIndex = 0;
|
||||
document.getElementById("divTopic_"+ipop).style.display = "";
|
||||
} else {
|
||||
document.getElementById("divTopic_"+ipop).style.display = "none";
|
||||
}
|
||||
while (++ipop <= ' . $maxdepth . ') {
|
||||
document.getElementById("divTopic_"+ipop).style.display = "none";
|
||||
}
|
||||
}
|
||||
</script>';
|
||||
|
||||
$out .= '<div class="searchZonePop" onload="chgPopTopic(0);">
|
||||
<div class="linktopics1">
|
||||
<form name="pops" onsubmit="return(false);" style="margin:0px; margin-left:5px; margin-right:5px">
|
||||
<table>
|
||||
<tr>
|
||||
<td colspan="2">' . $translator->trans('boutton::chercher') . ' :
|
||||
<input style="width:180px" type="text" name="qry"></td>
|
||||
</tr>
|
||||
</table>
|
||||
' . $translator->trans('client::recherche: dans les categories') . '<br/>';
|
||||
|
||||
for ($i = 0; $i <= $maxdepth; $i ++) {
|
||||
$out .= '<p id="divTopic_' . $i . '" style="margin:0px;margin-bottom:5px;" >
|
||||
<select style="width:100%;" id="popTopic_' . $i . '" name="popTopic_' . $i . '" onchange="chgPopTopic(' . ($i + 1) . ');">
|
||||
</select>
|
||||
</p>';
|
||||
}
|
||||
$out .= '<div style="text-align:right;">
|
||||
<input type="submit" value="' . $translator->trans('boutton::chercher') . '" onclick="doSearchTopPop();" />
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<script>chgPopTopic(0);</script>';
|
||||
|
||||
return $out;
|
||||
}
|
||||
|
||||
public static function history(Application $app, $usrId)
|
||||
{
|
||||
$history = '<ul>';
|
||||
|
||||
$queries = $app['repo.user-queries']->findBy(['user' => $usrId], ['created' => 'ASC'], 25, 0);
|
||||
|
||||
foreach ($queries as $query) {
|
||||
$history .= '<li onclick="doSpecialSearch(\'' . str_replace(["'", '"'], ["\'", '"'], $query->getQuery()) . '\')">' . $query->getQuery() . '</li>';
|
||||
}
|
||||
|
||||
$history .= '<ul>';
|
||||
|
||||
return $history;
|
||||
}
|
||||
|
||||
private static function hastopics(&$topics)
|
||||
{
|
||||
foreach ($topics->topics as $subtopic) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static function topicsAsJS($topics, $depth, &$maxdepth)
|
||||
{
|
||||
if ($depth > $maxdepth)
|
||||
$maxdepth = $depth;
|
||||
$t = '';
|
||||
$tab = str_repeat("\t", $depth);
|
||||
foreach ($topics->topic as $subtopic) {
|
||||
$t .= $t ? "$tab, " : "$tab ";
|
||||
$t .= '{ ';
|
||||
$t .= 'label:"' . p4string::MakeString(utf8_decode($subtopic->label), 'js') . '"';
|
||||
if ($q = $subtopic->query) {
|
||||
$q = str_replace(["\\", "'", "\r", "\n"], ["\\\\", "\\'", "\\r", "\\n"], $subtopic->query);
|
||||
$t .= ", query:'" . $q . "'";
|
||||
} else {
|
||||
$t .= ', query:null';
|
||||
}
|
||||
if (self::hastopics($subtopic)) {
|
||||
$t .= ', topics:' . "\n" . self::topicsAsJS($subtopic->topics, $depth + 1, $maxdepth); //, $fullquery) ;
|
||||
} else {
|
||||
$t .= ', topics:null';
|
||||
}
|
||||
$t .= " }\n";
|
||||
}
|
||||
|
||||
return("$tab" . "[\n" . $t . "\n$tab]");
|
||||
}
|
||||
|
||||
private static function drawTopics($topics, $depth = 0, $triid = '', $defaultview)
|
||||
{
|
||||
$n = 0;
|
||||
$out = '';
|
||||
foreach ($topics->topic as $subtopic) {
|
||||
$tid = $triid . '_' . $n;
|
||||
$s = $subtopic->label;
|
||||
$l = p4string::MakeString($s, 'html');
|
||||
$l = '<span class=\'topic_' . $depth . '\'>' . $l . '</span>';
|
||||
if ($subtopic->query) {
|
||||
$q = str_replace(["\\", "\"", "'", "\r", "\n"], ["\\\\", """, "\\'", "\\r", "\\n"], $subtopic->query);
|
||||
$q = '<a href="javascript:void();" onClick="doSpecialSearch(\'' . $q . '\',true);">' . $l . '</a>';
|
||||
} else {
|
||||
$q = $l;
|
||||
}
|
||||
if (self::hastopics($subtopic)) {
|
||||
$view = mb_strtolower($subtopic['view']);
|
||||
if ( ! $view)
|
||||
$view = $defaultview;
|
||||
switch ($view) {
|
||||
case 'opened':
|
||||
$out .= ( '<li><a id=\'TOPIC_TRI' . $tid . '\' class="opened" href="javascript:void();" onclick="clktri(\'' . $tid . '\');return(false);"></a> ' . $q . '</li>' . "\n");
|
||||
$out .= ( "<ul id='TOPIC_UL$tid' class='opened'>\n");
|
||||
$out .= self::drawTopics($subtopic->topics, $depth + 1, $tid, $defaultview);
|
||||
$out .= ( "</ul>\n<div style='height:1px;'></div>\n");
|
||||
break;
|
||||
case 'closed':
|
||||
$out .= ( '<li><a id=\'TOPIC_TRI' . $tid . '\' class="closed" href="javascript:void();" onclick="clktri(\'' . $tid . '\');return(false);"></a> ' . $q . '</li>' . "\n");
|
||||
$out .= ( "<ul id='TOPIC_UL$tid' class='closed'>\n");
|
||||
$out .= self::drawTopics($subtopic->topics, $depth + 1, $tid, $defaultview);
|
||||
$out .= ( "</ul>\n<div style='height:1px;'></div>\n");
|
||||
break;
|
||||
case 'static':
|
||||
default:
|
||||
$out .= ( '<li><span id=\'TOPIC_TRI' . $tid . '\' class="static"> </span> ' . $q . '</li>' . "\n");
|
||||
$out .= ( "<ul id='TOPIC_UL$tid' class='static'>\n");
|
||||
$out .= self::drawTopics($subtopic->topics, $depth + 1, $tid, $defaultview);
|
||||
$out .= ( "</ul>\n<div style='height:1px;'></div>\n");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
$out .= ( '<li><span id=\'TOPIC_TRI' . $tid . '\' class="none"> </span> ' . $q . '</li>' . "\n");
|
||||
}
|
||||
$n ++;
|
||||
}
|
||||
|
||||
return $out;
|
||||
}
|
||||
}
|
@@ -1334,6 +1334,7 @@ class record_adapter implements RecordInterface, cache_cacheableInterface
|
||||
while ($row = $stmt->fetch(\PDO::FETCH_ASSOC)) {
|
||||
@unlink(\p4string::addEndSlash($row['path']) . 'stamp_' . $row['file']);
|
||||
}
|
||||
|
||||
$stmt->closeCursor();
|
||||
|
||||
return $this;
|
||||
|
@@ -170,7 +170,7 @@ class record_exportElement extends record_adapter
|
||||
|
||||
$downloadable[$name] = false;
|
||||
|
||||
$downloadable_settings = $subdef->is_downloadable();
|
||||
$downloadable_settings = $subdef->isDownloadable();
|
||||
|
||||
if (! $downloadable_settings || $go_dl[$class] === false) {
|
||||
continue;
|
||||
|
@@ -212,3 +212,31 @@ embed_bundle:
|
||||
document:
|
||||
player: flexpaper
|
||||
enable-pdfjs: true
|
||||
geocoding-providers:
|
||||
-
|
||||
name: 'mapBox'
|
||||
enabled: true
|
||||
public-key: ''
|
||||
default-position:
|
||||
- 2.335062
|
||||
- 48.879162
|
||||
default-zoom: 2
|
||||
marker-default-zoom: 11
|
||||
position-fields:
|
||||
-
|
||||
name: GpsCompositePosition
|
||||
type: latlng
|
||||
# -
|
||||
# name: Longitude
|
||||
# type: lng
|
||||
# -
|
||||
# name: Latitude
|
||||
# type: lat
|
||||
video-editor:
|
||||
vttFieldName: VideoTextTrackChapters
|
||||
seekBackwardStep: 1000 # in ms
|
||||
seekForwardStep: 1000 # in ms
|
||||
playbackRates:
|
||||
- 1
|
||||
- '1.5'
|
||||
- 3
|
||||
|
@@ -25,11 +25,16 @@
|
||||
"tmp": "0.0.23",
|
||||
"wrench": "^1.5.8"
|
||||
},
|
||||
"engines" : {
|
||||
"node" : ">=0.12"
|
||||
"engines": {
|
||||
"node": ">=5.8"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "./node_modules/.bin/gulp sync;",
|
||||
"build": "./node_modules/.bin/gulp build;",
|
||||
"postinstall": "./node_modules/.bin/gulp install;"
|
||||
},
|
||||
"dependencies": {
|
||||
"alchemy-embed-medias": "^0.4.4",
|
||||
"phraseanet-production-client": "~0.19.23"
|
||||
}
|
||||
}
|
||||
|
@@ -9,6 +9,7 @@
|
||||
- nginx
|
||||
- mariadb
|
||||
- elasticsearch
|
||||
- rabbitmq
|
||||
- php
|
||||
- xdebug
|
||||
- composer
|
||||
|
@@ -7,4 +7,4 @@
|
||||
- name: Install specific nodejs version
|
||||
become: yes
|
||||
become_user: vagrant
|
||||
shell: export NVM_DIR="$HOME/.nvm" &&. ~/.nvm/nvm.sh && nvm install 0.12.0 && nvm alias default 0.12.0
|
||||
shell: export NVM_DIR="$HOME/.nvm" &&. ~/.nvm/nvm.sh && nvm install 0.12.16 && nvm alias default 0.12.16
|
||||
|
27
resources/ansible/roles/rabbitmq/tasks/main.yml
Executable file
27
resources/ansible/roles/rabbitmq/tasks/main.yml
Executable file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
- name: Add package repository
|
||||
sudo: yes
|
||||
shell: echo 'deb http://www.rabbitmq.com/debian/ testing main' > /etc/apt/sources.list.d/rabbitmq.list
|
||||
|
||||
- name: Install package repository key
|
||||
sudo: yes
|
||||
shell: wget https://www.rabbitmq.com/rabbitmq-signing-key-public.asc && apt-key add rabbitmq-signing-key-public.asc
|
||||
|
||||
- name: Remove signing key
|
||||
sudo: yes
|
||||
shell: rm rabbitmq-signing-key-public.asc
|
||||
|
||||
- name: Update apt
|
||||
sudo: yes
|
||||
apt: update_cache=yes
|
||||
|
||||
- name: Install server and libraries
|
||||
sudo: yes
|
||||
apt: pkg={{ item }} state=latest allow_unauthenticated=yes
|
||||
with_items:
|
||||
- rabbitmq-server
|
||||
- librabbitmq-dev
|
||||
|
||||
- name: Enable management plugin
|
||||
sudo: yes
|
||||
shell: rabbitmq-plugins enable rabbitmq_management
|
@@ -59,6 +59,7 @@ php:
|
||||
packages: [php5-cli, php5-intl, php5-mcrypt, php5-enchant, php5-gd, php5-imagick, php5-memcache, php5-memcached, php5-curl, php5-mysql, php5-sqlite]
|
||||
pecl_packages:
|
||||
- {name: zmq, package: zmq-beta}
|
||||
- {name: amqp, package: amqp-1.4.0}
|
||||
xdebug:
|
||||
install: '1'
|
||||
composer:
|
||||
|
@@ -26,16 +26,15 @@ gulp.task('build', ['build-vendors'], function(){
|
||||
|
||||
// standalone vendors used across application
|
||||
gulp.task('build-vendors', [
|
||||
'build-alchemy-embed',
|
||||
'build-alchemy-embed-medias',
|
||||
'build-phraseanet-production-client',
|
||||
'build-bootstrap',
|
||||
'build-colorpicker',
|
||||
'build-html5shiv',
|
||||
'build-jquery',
|
||||
'build-jquery-ui', // will build themes too
|
||||
'build-jquery-mobile',
|
||||
'build-jquery-galleria',
|
||||
'build-jquery-file-upload',
|
||||
// 'build-jquery-image-enhancer', //bundled in prod only
|
||||
'build-json2',
|
||||
'build-modernizr',
|
||||
'build-zxcvbn',
|
||||
|
@@ -13,19 +13,6 @@ gulp.task('build-account-css', function(){
|
||||
], 'account', 'account/css/', debugMode);
|
||||
});
|
||||
|
||||
gulp.task('build-account-js', function(){
|
||||
var accountGroup = [
|
||||
config.paths.vendors + 'requirejs/require.js',
|
||||
config.paths.src + 'account/js/account.js'
|
||||
];
|
||||
return utils.buildJsGroup(accountGroup, 'account', 'account/js', debugMode);
|
||||
});
|
||||
|
||||
gulp.task('watch-account-js', function() {
|
||||
debugMode = true;
|
||||
return gulp.watch(config.paths.src + 'account/**/*.js', ['build-account-js']);
|
||||
});
|
||||
|
||||
gulp.task('watch-account-css', function() {
|
||||
debugMode = true;
|
||||
gulp.watch(config.paths.src + 'account/**/*.scss', ['build-account-css']);
|
||||
@@ -33,5 +20,5 @@ gulp.task('watch-account-css', function() {
|
||||
|
||||
gulp.task('build-account', ['copy-account-images', 'build-account-css'], function(){
|
||||
debugMode = false;
|
||||
return gulp.start('build-account-js');
|
||||
return gulp.start('build-account-css');
|
||||
});
|
@@ -26,6 +26,8 @@ gulp.task('build-common-css', ['build-common-font-css'],function(){
|
||||
|
||||
gulp.task('build-common-js', function(){
|
||||
var commonGroup = [
|
||||
config.paths.src + 'common/js/components/utils.js',
|
||||
config.paths.src + 'common/js/components/user.js',
|
||||
// config.paths.dist + 'assets/bootstrap/js/bootstrap.js', // should append no conflict
|
||||
config.paths.src + 'vendors/jquery-mousewheel/js/jquery.mousewheel.js',
|
||||
// jquery ui date picker langs
|
||||
@@ -37,9 +39,9 @@ gulp.task('build-common-js', function(){
|
||||
config.paths.vendors + 'jquery-ui/ui/i18n/jquery.ui.datepicker-en-GB.js',
|
||||
config.paths.vendors + 'jquery.cookie/jquery.cookie.js',
|
||||
config.paths.src + 'vendors/jquery-contextmenu/js/jquery.contextmenu_custom.js',
|
||||
config.paths.src + 'common/js/jquery.common.js',
|
||||
config.paths.src + 'common/js/jquery.tooltip.js',
|
||||
config.paths.src + 'common/js/jquery.Dialog.js'
|
||||
config.paths.src + 'common/js/components/common.js',
|
||||
config.paths.src + 'common/js/components/tooltip.js',
|
||||
config.paths.src + 'common/js/components/dialog.js'
|
||||
];
|
||||
return utils.buildJsGroup(commonGroup, 'common', 'common/js', debugMode);
|
||||
});
|
||||
|
@@ -14,48 +14,18 @@ gulp.task('build-lightbox-mobile-css', function(){
|
||||
], 'lightbox-mobile', 'lightbox/css/', debugMode);
|
||||
});
|
||||
|
||||
gulp.task('build-lightbox-mobile-js', function(){
|
||||
|
||||
return utils.buildJsGroup([
|
||||
config.paths.src + 'lightbox/js/jquery.validator.mobile.js'
|
||||
], 'lightbox-mobile', 'lightbox/js', debugMode);
|
||||
});
|
||||
|
||||
gulp.task('build-lightbox-ie6-css', function(){
|
||||
return utils.buildCssGroup([
|
||||
config.paths.src + 'lightbox/styles/main-ie6.scss'
|
||||
], 'lightbox-ie6', 'lightbox/css/', debugMode)
|
||||
});
|
||||
|
||||
gulp.task('build-lightbox-css', ['build-lightbox-mobile-css', 'build-lightbox-ie6-css'], function(){
|
||||
gulp.task('build-lightbox-css', ['build-lightbox-mobile-css'], function(){
|
||||
return utils.buildCssGroup([
|
||||
config.paths.src + 'lightbox/styles/main.scss'
|
||||
], 'lightbox', 'lightbox/css/', debugMode)
|
||||
});
|
||||
|
||||
gulp.task('build-lightbox-js', ['build-lightbox-mobile-js'], function(){
|
||||
var lightboxGroup = [
|
||||
config.paths.src + 'lightbox/js/jquery.lightbox.js'
|
||||
];
|
||||
|
||||
var lightboxIE6Group = [
|
||||
config.paths.src + 'lightbox/js/jquery.lightbox.ie6.js'
|
||||
];
|
||||
utils.buildJsGroup(lightboxIE6Group, 'lightboxIe6', 'lightbox/js', debugMode);
|
||||
return utils.buildJsGroup(lightboxGroup, 'lightbox', 'lightbox/js', debugMode);
|
||||
});
|
||||
|
||||
gulp.task('watch-lightbox-js', function() {
|
||||
debugMode = true;
|
||||
return gulp.watch(config.paths.src + 'lightbox/**/*.js', ['build-lightbox-js']);
|
||||
});
|
||||
|
||||
gulp.task('watch-lightbox-css', function() {
|
||||
debugMode = true;
|
||||
gulp.watch(config.paths.src + 'lightbox/**/*.scss', ['build-lightbox-css']);
|
||||
});
|
||||
|
||||
gulp.task('build-lightbox', ['copy-lightbox-images', 'build-lightbox-css'], function(){
|
||||
gulp.task('build-lightbox', ['copy-lightbox-images'], function(){
|
||||
debugMode = false;
|
||||
return gulp.start('build-lightbox-js');
|
||||
return gulp.start('build-lightbox-css');
|
||||
});
|
@@ -14,107 +14,17 @@ gulp.task('build-uploadFlash', function(){
|
||||
return utils.buildJsGroup(uploadFlashGroup, 'uploadFlash', 'upload/js');
|
||||
});
|
||||
|
||||
gulp.task('copy-prod-skin-black-images', function(){
|
||||
return gulp.src([
|
||||
config.paths.src + 'prod/skins/000000/images/**/*'
|
||||
])
|
||||
.pipe(gulp.dest( config.paths.build + 'prod/skins/000000/images'));
|
||||
});
|
||||
|
||||
gulp.task('copy-prod-skin-grey-images', function(){
|
||||
return gulp.src([
|
||||
config.paths.src + 'prod/skins/959595/images/**/*'
|
||||
])
|
||||
.pipe(gulp.dest( config.paths.build + 'prod/skins/959595/images'));
|
||||
});
|
||||
|
||||
gulp.task('copy-prod-skin-white-images', function(){
|
||||
return gulp.src([
|
||||
config.paths.src + 'prod/skins/FFFFFF/images/**/*'
|
||||
])
|
||||
.pipe(gulp.dest( config.paths.build + 'prod/skins/FFFFFF/images'));
|
||||
});
|
||||
|
||||
gulp.task('copy-prod-images', function(){
|
||||
return gulp.src([config.paths.src + 'prod/images/**/*'])
|
||||
.pipe(gulp.dest( config.paths.build + 'prod/images'));
|
||||
});
|
||||
|
||||
gulp.task('build-prod-skin-black', ['copy-prod-skin-black-images'], function(){
|
||||
return utils.buildCssGroup([
|
||||
config.paths.src + 'prod/skins/000000/skin-000000.scss'
|
||||
], 'skin-000000', 'prod/skins/000000/', debugMode);
|
||||
});
|
||||
|
||||
gulp.task('build-prod-skin-grey', ['copy-prod-skin-grey-images'], function(){
|
||||
return utils.buildCssGroup([
|
||||
config.paths.src + 'prod/skins/959595/skin-959595.scss'
|
||||
], 'skin-959595', 'prod/skins/959595/', debugMode);
|
||||
});
|
||||
|
||||
gulp.task('build-prod-skin-white', ['copy-prod-skin-white-images'], function(){
|
||||
return utils.buildCssGroup([
|
||||
config.paths.src + 'prod/skins/FFFFFF/skin-FFFFFF.scss'
|
||||
], 'skin-FFFFFF', 'prod/skins/FFFFFF/', debugMode);
|
||||
});
|
||||
|
||||
gulp.task('build-prod-css', ['build-prod-skin-black', 'build-prod-skin-grey', 'build-prod-skin-white'], function(){
|
||||
return utils.buildCssGroup([
|
||||
config.paths.src + 'prod/styles/main.scss'
|
||||
], 'prod', 'prod/css/', debugMode);
|
||||
});
|
||||
gulp.task('build-prod-js', function(){
|
||||
var prodGroup = [
|
||||
config.paths.vendors + 'underscore-amd/underscore.js',
|
||||
config.paths.src + 'vendors/colorpicker/js/colorpicker.js',
|
||||
config.paths.vendors + 'jquery.lazyload/jquery.lazyload.js',
|
||||
config.paths.vendors + 'humane-js/humane.js', // @TODO > extra files
|
||||
config.paths.vendors + 'blueimp-load-image/js/load-image.js', // @TODO > extra files
|
||||
config.paths.vendors + 'jquery-file-upload/js/jquery.iframe-transport.js',
|
||||
config.paths.vendors + 'jquery-file-upload/js/jquery.fileupload.js',
|
||||
config.paths.vendors + 'geonames-server-jquery-plugin/jquery.geonames.js',
|
||||
config.paths.src + 'prod/js/components/publication.js',
|
||||
config.paths.src + 'prod/js/jquery.form.2.49.js',
|
||||
config.paths.src + 'prod/js/jquery.Selection.js',
|
||||
config.paths.src + 'prod/js/jquery.Edit.js',
|
||||
config.paths.src + 'prod/js/jquery.lists.js',
|
||||
config.paths.src + 'prod/js/jquery.Prod.js',
|
||||
config.paths.src + 'prod/js/jquery.Feedback.js',
|
||||
config.paths.src + 'prod/js/jquery.Results.js',
|
||||
config.paths.src + 'prod/js/jquery.main-prod.js',
|
||||
config.paths.src + 'prod/js/jquery.WorkZone.js',
|
||||
config.paths.src + 'prod/js/jquery.Alerts.js',
|
||||
config.paths.src + 'prod/js/jquery.Upload.js',
|
||||
config.paths.src + 'prod/js/ThumbExtractor.js',
|
||||
config.paths.src + 'prod/js/publicator.js',
|
||||
config.paths.src + 'vendors/jquery-sprintf/js/jquery.sprintf.1.0.3.js',
|
||||
config.paths.src + 'prod/js/jquery.p4.preview.js',
|
||||
config.paths.src + 'prod/js/record.editor.js',
|
||||
config.paths.src + 'prod/js/jquery.color.animation.js',
|
||||
config.paths.src + 'vendors/jquery-image-enhancer/js/jquery.image_enhancer.js',
|
||||
config.paths.vendors + 'jquery-treeview/jquery.treeview.js',
|
||||
config.paths.vendors + 'jquery-treeview/jquery.treeview.async.js',
|
||||
config.paths.vendors + 'fancytree/dist/jquery.fancytree-all.min.js'
|
||||
];
|
||||
return utils.buildJsGroup(prodGroup, 'prod', 'prod/js', debugMode);
|
||||
});
|
||||
|
||||
gulp.task('test-prod', function () {
|
||||
return gulp.src(config.paths.src + 'prod/js/tests/*.html')
|
||||
.pipe(qunit());
|
||||
});
|
||||
|
||||
gulp.task('watch-prod-js', function() {
|
||||
debugMode = true;
|
||||
return gulp.watch(config.paths.src + 'prod/**/*.js', ['build-prod-js']);
|
||||
});
|
||||
|
||||
gulp.task('watch-prod-css', function() {
|
||||
debugMode = true;
|
||||
return gulp.watch(config.paths.src + 'prod/**/*.scss', ['build-prod-css']);
|
||||
});
|
||||
|
||||
gulp.task('build-prod', ['copy-prod-images', 'build-prod-css'], function(){
|
||||
gulp.task('build-prod', [], function(){
|
||||
debugMode = false;
|
||||
return gulp.start('build-prod-js');
|
||||
return gulp.start('copy-prod-images');
|
||||
});
|
||||
|
@@ -17,9 +17,7 @@ gulp.task('build-thesaurus-js', function(){
|
||||
var thesaurusGroup = [
|
||||
config.paths.src + 'vendors/jquery-sprintf/js/jquery.sprintf.1.0.3.js',
|
||||
config.paths.src + 'thesaurus/js/win.js',
|
||||
config.paths.src + 'thesaurus/js/xmlhttp.js',
|
||||
config.paths.src + 'thesaurus/js/thesaurus.js',
|
||||
config.paths.src + 'thesaurus/js/sprintf.js'
|
||||
config.paths.src + 'thesaurus/js/xmlhttp.js'
|
||||
];
|
||||
return utils.buildJsGroup(thesaurusGroup, 'thesaurus', 'thesaurus/js', debugMode);
|
||||
});
|
||||
|
@@ -4,25 +4,22 @@ var utils = require('../../utils.js');
|
||||
var debugMode = false;
|
||||
|
||||
// for dev purposes
|
||||
gulp.task('copy-alchemy-embed-debug', function(){
|
||||
gulp.task('copy-alchemy-embed-medias-debug', function(){
|
||||
debugMode = true;
|
||||
gulp.start('copy-alchemy-embed');
|
||||
gulp.start('copy-alchemy-embed-medias');
|
||||
});
|
||||
|
||||
gulp.task('copy-alchemy-embed', function(){
|
||||
gulp.task('copy-alchemy-embed-medias', function(){
|
||||
// copy all dist folder:
|
||||
if( debugMode === true) {
|
||||
return gulp.src('vendor/alchemy/embed-bundle/dist/**/*')
|
||||
.pipe(gulp.dest( config.paths.build + 'vendors/alchemy-embed-medias'));
|
||||
}
|
||||
return gulp.src(config.paths.vendors + 'alchemy-embed-medias/dist/**/*')
|
||||
|
||||
return gulp.src('node_modules/alchemy-embed-medias/dist/**/*')
|
||||
.pipe(gulp.dest( config.paths.build + 'vendors/alchemy-embed-medias'));
|
||||
});
|
||||
gulp.task('watch-alchemy-embed-js', function() {
|
||||
gulp.task('watch-alchemy-embed-medias-js', function() {
|
||||
debugMode = true;
|
||||
// in dev mode, watch composer's vendor path:
|
||||
return gulp.watch('vendor/alchemy/embed-bundle/dist/**/*', ['copy-alchemy-embed']);
|
||||
return gulp.watch('node_modules/alchemy-embed-medias/dist/**/*', ['copy-alchemy-embed-medias']);
|
||||
});
|
||||
gulp.task('build-alchemy-embed', function(){
|
||||
gulp.start('copy-alchemy-embed');
|
||||
gulp.task('build-alchemy-embed-medias', function(){
|
||||
gulp.start('copy-alchemy-embed-medias');
|
||||
});
|
25
resources/gulp/components/vendors/alchemy-phraseanet-production-client.js
vendored
Normal file
25
resources/gulp/components/vendors/alchemy-phraseanet-production-client.js
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
var gulp = require('gulp');
|
||||
var config = require('../../config.js');
|
||||
var utils = require('../../utils.js');
|
||||
var debugMode = false;
|
||||
|
||||
// for dev purposes
|
||||
gulp.task('copy-phraseanet-production-client-debug', function(){
|
||||
debugMode = true;
|
||||
gulp.start('copy-phraseanet-production-client');
|
||||
});
|
||||
|
||||
gulp.task('copy-phraseanet-production-client', function(){
|
||||
// copy all dist folder:
|
||||
|
||||
return gulp.src('node_modules/phraseanet-production-client/dist/**/*')
|
||||
.pipe(gulp.dest( config.paths.build + 'production'));
|
||||
});
|
||||
gulp.task('watch-phraseanet-production-client-js', function() {
|
||||
debugMode = true;
|
||||
// in dev mode, watch composer's vendor path:
|
||||
return gulp.watch('node_modules/phraseanet-production-client/dist/**/*', ['copy-phraseanet-production-client']);
|
||||
});
|
||||
gulp.task('build-phraseanet-production-client', function(){
|
||||
gulp.start('copy-phraseanet-production-client');
|
||||
});
|
20
resources/gulp/components/vendors/colorpicker.js
vendored
20
resources/gulp/components/vendors/colorpicker.js
vendored
@@ -1,20 +0,0 @@
|
||||
var gulp = require('gulp');
|
||||
var config = require('../../config.js');
|
||||
var utils = require('../../utils.js');
|
||||
|
||||
gulp.task('copy-colorpicker-images', function(){
|
||||
return gulp.src([config.paths.src + 'vendors/colorpicker/images/**/*'])
|
||||
.pipe(gulp.dest( config.paths.build + 'vendors/colorpicker/images'));
|
||||
});
|
||||
|
||||
gulp.task('build-colorpicker-css', function(){
|
||||
return utils.buildCssGroup([
|
||||
config.paths.src + 'vendors/colorpicker/styles/colorpicker.scss'
|
||||
], 'colorpicker', 'vendors/colorpicker');
|
||||
});
|
||||
|
||||
gulp.task('build-colorpicker', ['build-colorpicker-css', 'copy-colorpicker-images'], function(){
|
||||
return utils.buildJsGroup([
|
||||
config.paths.src + 'vendors/colorpicker/js/colorpicker.js'
|
||||
], 'colorpicker', 'vendors/colorpicker');
|
||||
});
|
@@ -1,17 +0,0 @@
|
||||
var gulp = require('gulp');
|
||||
var config = require('../../config.js');
|
||||
var utils = require('../../utils.js');
|
||||
|
||||
|
||||
|
||||
gulp.task('build-jquery-image-enhancer-css', function(){
|
||||
return utils.buildCssGroup([
|
||||
config.paths.src + 'vendors/jquery-image-enhancer/styles/jquery.image_enhancer.scss'
|
||||
], 'jquery-image-enhancer', 'vendors/jquery-image-enhancer');
|
||||
});
|
||||
|
||||
gulp.task('build-jquery-image-enhancer', ['build-jquery-image-enhancer-css'], function(){
|
||||
return utils.buildJsGroup([
|
||||
config.paths.src + 'vendors/jquery-image-enhancer/js/jquery.image_enhancer.js'
|
||||
], 'jquery-image-enhancer', 'vendors/jquery-image-enhancer');
|
||||
});
|
@@ -35,7 +35,7 @@ exports.buildJsGroup = function(srcGroup, name, dest, debugMode){
|
||||
compress: {
|
||||
drop_console: true
|
||||
}
|
||||
}).on('error', config.errorHandler('UGLIFY ERROR'))) //util.log))
|
||||
}).on('error', config.errorHandler('UGLIFY ERROR')))
|
||||
.pipe(rename({ extname: '.min.js' }))
|
||||
.pipe(gulp.dest( config.paths.build + dest))
|
||||
};
|
||||
|
@@ -8,7 +8,6 @@ var utils = require('./utils.js');
|
||||
gulp.task('watch-css', function(){
|
||||
gulp.start('watch-common-css');
|
||||
gulp.start('watch-oauth-css');
|
||||
gulp.start('watch-prod-css');
|
||||
gulp.start('watch-thesaurus-css');
|
||||
//gulp.start('watch-uploadFlash');
|
||||
gulp.start('watch-lightbox-css');
|
||||
@@ -23,17 +22,15 @@ gulp.task('watch-css', function(){
|
||||
gulp.task('watch-js', function(){
|
||||
gulp.start('watch-common-js');
|
||||
// gulp.start('watch-oauth-js');
|
||||
gulp.start('watch-prod-js');
|
||||
gulp.start('watch-thesaurus-js');
|
||||
//gulp.start('watch-uploadFlash');
|
||||
gulp.start('watch-lightbox-js');
|
||||
gulp.start('watch-admin-js');
|
||||
gulp.start('watch-report-js');
|
||||
gulp.start('watch-account-js');
|
||||
// gulp.start('watch-permaview');
|
||||
gulp.start('watch-setup-js');
|
||||
gulp.start('watch-authentication-js');
|
||||
gulp.start('watch-alchemy-embed-js');
|
||||
gulp.start('watch-alchemy-embed-medias-js');
|
||||
gulp.start('watch-phraseanet-production-client-js');
|
||||
});
|
||||
|
||||
gulp.task('watch', function(){
|
||||
@@ -46,7 +43,7 @@ var browserSync = require('browser-sync').create();
|
||||
gulp.task('sync', ['watch'], function(){
|
||||
// will open browser in http://localhost:3000/
|
||||
browserSync.init({
|
||||
proxy: "phraseanet-php55-nginx"
|
||||
proxy: "dev.phraseanet.vb"
|
||||
});
|
||||
gulp.watch(config.paths.build + '**/*.css').on('change', browserSync.reload);
|
||||
gulp.watch(config.paths.build + '**/*.js').on('change', browserSync.reload);
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user