diff --git a/composer.json b/composer.json index dc4f2b0ffd..62ecab7dfb 100644 --- a/composer.json +++ b/composer.json @@ -5,6 +5,29 @@ "config": { "bin-dir" : "bin/" }, + "repositories": [ + { + "type": "vcs", + "url": "https://github.com/alchemy-fr/tcpdf-clone" + }, + { + "type": "git", + "url": "https://github.com/romainneutron/ProcessManager.git" + }, + { + "type": "vcs", + "url": "https://github.com/nlegoff/PHP-FFmpeg" + }, + { + "type": "vcs", + "url": "https://github.com/nlegoff/Mediavorus" + }, + { + "type": "vcs", + "url": "https://github.com/nlegoff/Media-Alchemyst" + } + ], + "minimum-stability" : "dev", "require": { "php" : ">=5.4", "alchemy/oauth2php" : "1.0.0", @@ -28,8 +51,8 @@ "jms/serializer" : "~0.10", "jms/translation-bundle" : "~1.1", "justinrainbow/json-schema" : "~1.3", - "mediavorus/mediavorus" : "~0.4.0", - "media-alchemyst/media-alchemyst" : "~0.4, >=0.4.4", + "mediavorus/mediavorus" : "dev-fix-video-dim as 0.4.3", + "media-alchemyst/media-alchemyst" : "0.4.x@dev", "monolog/monolog" : "~1.3", "mrclay/minify" : "~2.1.6", "neutron/process-manager" : "2.0.x-dev@dev", @@ -38,7 +61,7 @@ "neutron/sphinxsearch-api" : "~2.0.6", "neutron/recaptcha" : "~0.1.0", "neutron/temporary-filesystem" : "~2.1", - "php-ffmpeg/php-ffmpeg" : "~0.4, >=0.4.3", + "php-ffmpeg/php-ffmpeg" : "dev-fix-aspect-ratio as 0.4.4", "php-xpdf/php-xpdf" : "~0.2.1", "phpexiftool/phpexiftool" : "~0.3", "react/zmq" : "~0.2", @@ -70,10 +93,6 @@ { "type": "git", "url": "https://github.com/alchemy-fr/tcpdf-clone" - }, - { - "type": "git", - "url": "https://github.com/romainneutron/ProcessManager.git" } ], "autoload": { diff --git a/composer.lock b/composer.lock index ee3ca8c62d..13ffb9420e 100644 --- a/composer.lock +++ b/composer.lock @@ -1,9 +1,10 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file" + "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" ], - "hash": "2b68364c4ebb09b6f5c3902e0afdcc1a", + "hash": "6dbba3e72a44255a6292ee8fedbce88e", "packages": [ { "name": "alchemy-fr/tcpdf-clone", @@ -2018,26 +2019,26 @@ }, { "name": "media-alchemyst/media-alchemyst", - "version": "0.4.4", + "version": "dev-master", "source": { "type": "git", - "url": "https://github.com/alchemy-fr/Media-Alchemyst.git", - "reference": "067599fd669b86ff3a1cfb344730014b4a339b7e" + "url": "https://github.com/nlegoff/Media-Alchemyst.git", + "reference": "e812e631b74ebb0c7b3dd5f4e981d84a7b3c4029" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/alchemy-fr/Media-Alchemyst/zipball/067599fd669b86ff3a1cfb344730014b4a339b7e", - "reference": "067599fd669b86ff3a1cfb344730014b4a339b7e", + "url": "https://api.github.com/repos/nlegoff/Media-Alchemyst/zipball/e812e631b74ebb0c7b3dd5f4e981d84a7b3c4029", + "reference": "e812e631b74ebb0c7b3dd5f4e981d84a7b3c4029", "shasum": "" }, "require": { "alchemy/ghostscript": "~0.4.0", "imagine/imagine": "0.6.x@dev", - "mediavorus/mediavorus": "~0.4.2", + "mediavorus/mediavorus": "dev-fix-video-dim as 0.4.3", "monolog/monolog": "~1.0", "neutron/temporary-filesystem": "~2.1", "php": ">=5.3.3", - "php-ffmpeg/php-ffmpeg": "~0.4.2", + "php-ffmpeg/php-ffmpeg": "dev-fix-aspect-ratio as 0.4.4", "php-mp4box/php-mp4box": "~0.3.0", "php-unoconv/php-unoconv": "~0.3.0", "pimple/pimple": "~1.0", @@ -2062,7 +2063,6 @@ "MediaAlchemyst": "src" } }, - "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -2087,20 +2087,23 @@ "video", "video processing" ], - "time": "2014-01-31 11:32:50" + "support": { + "source": "https://github.com/nlegoff/Media-Alchemyst/tree/master" + }, + "time": "2014-06-10 13:51:13" }, { "name": "mediavorus/mediavorus", - "version": "0.4.3", + "version": "dev-fix-video-dim", "source": { "type": "git", - "url": "https://github.com/romainneutron/MediaVorus.git", - "reference": "7cc8c0b8d3440eaff9aa68fff2185216fd72bd75" + "url": "https://github.com/nlegoff/Mediavorus.git", + "reference": "f11cd2453d5acbc6ac52421dc4edd760433b1515" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/romainneutron/MediaVorus/zipball/7cc8c0b8d3440eaff9aa68fff2185216fd72bd75", - "reference": "7cc8c0b8d3440eaff9aa68fff2185216fd72bd75", + "url": "https://api.github.com/repos/nlegoff/Mediavorus/zipball/f11cd2453d5acbc6ac52421dc4edd760433b1515", + "reference": "f11cd2453d5acbc6ac52421dc4edd760433b1515", "shasum": "" }, "require": { @@ -2133,7 +2136,6 @@ "MediaVorus": "src" } }, - "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -2148,7 +2150,10 @@ "keywords": [ "metadata" ], - "time": "2014-01-06 15:45:32" + "support": { + "source": "https://github.com/nlegoff/Mediavorus/tree/fix-video-dim" + }, + "time": "2014-06-10 14:03:47" }, { "name": "monolog/monolog", @@ -2597,16 +2602,16 @@ }, { "name": "php-ffmpeg/php-ffmpeg", - "version": "0.4.4", + "version": "dev-fix-aspect-ratio", "source": { "type": "git", - "url": "https://github.com/alchemy-fr/PHP-FFmpeg.git", - "reference": "8dfaf1815802614352bbd10eac7299a100bf9757" + "url": "https://github.com/nlegoff/PHP-FFmpeg.git", + "reference": "c2ea1ca7ab0a4da0e876e36c8cddbfa4d92dbba6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/alchemy-fr/PHP-FFmpeg/zipball/8dfaf1815802614352bbd10eac7299a100bf9757", - "reference": "8dfaf1815802614352bbd10eac7299a100bf9757", + "url": "https://api.github.com/repos/nlegoff/PHP-FFmpeg/zipball/c2ea1ca7ab0a4da0e876e36c8cddbfa4d92dbba6", + "reference": "c2ea1ca7ab0a4da0e876e36c8cddbfa4d92dbba6", "shasum": "" }, "require": { @@ -2627,7 +2632,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "0.4-dev" + "dev-master": "0.5-dev" } }, "autoload": { @@ -2635,7 +2640,6 @@ "FFMpeg": "src" } }, - "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], @@ -2662,7 +2666,10 @@ "video", "video processing" ], - "time": "2013-12-17 16:54:46" + "support": { + "source": "https://github.com/nlegoff/PHP-FFmpeg/tree/fix-aspect-ratio" + }, + "time": "2014-06-10 10:27:04" }, { "name": "php-mp4box/php-mp4box", @@ -4900,9 +4907,20 @@ } ], "aliases": [ - + { + "alias": "0.4.3", + "alias_normalized": "0.4.3.0", + "version": "dev-fix-video-dim", + "package": "mediavorus/mediavorus" + }, + { + "alias": "0.4.4", + "alias_normalized": "0.4.4.0", + "version": "dev-fix-aspect-ratio", + "package": "php-ffmpeg/php-ffmpeg" + } ], - "minimum-stability": "stable", + "minimum-stability": "dev", "stability-flags": { "alchemy/task-manager": 20, "alchemy/zippy": 20, @@ -4913,6 +4931,10 @@ "doctrine/migrations": 20, "behat/behat": 20, "behat/gherkin": 20 + "mediavorus/mediavorus": 20, + "media-alchemyst/media-alchemyst": 20, + "php-ffmpeg/php-ffmpeg": 20, + "doctrine/data-fixtures": 20 }, "platform": { "php": ">=5.4" diff --git a/config/configuration.sample.yml b/config/configuration.sample.yml index 1aa6447925..1cd3d7c1f7 100644 --- a/config/configuration.sample.yml +++ b/config/configuration.sample.yml @@ -4,6 +4,8 @@ languages: default: 'fr' main: maintenance: false + languages: [] + key: '' database: host: 127.0.0.1 port: 3306 @@ -169,6 +171,9 @@ registration-fields: - name: company required: true + - + name: lastname + required: true - name: firstname required: true @@ -184,3 +189,15 @@ h264-pseudo-streaming: type: nginx mapping: [] plugins: [] +api_cors: + enabled: false + allow_credentials: false + allow_origin: [] + allow_headers: [] + allow_methods: [] + expose_headers: [] + max_age: 0 + hosts: [] +session: + idle: 0 + lifetime: 604800 # 1 week diff --git a/lib/Alchemy/Phrasea/Application.php b/lib/Alchemy/Phrasea/Application.php index 8dc85e9913..675930e302 100644 --- a/lib/Alchemy/Phrasea/Application.php +++ b/lib/Alchemy/Phrasea/Application.php @@ -67,8 +67,6 @@ use Alchemy\Phrasea\Controller\Root\Session; use Alchemy\Phrasea\Controller\Setup as SetupController; use Alchemy\Phrasea\Controller\Thesaurus\Thesaurus; use Alchemy\Phrasea\Controller\Thesaurus\Xmlhttp as ThesaurusXMLHttp; -use Alchemy\Phrasea\Controller\Utils\ConnectionTest; -use Alchemy\Phrasea\Controller\Utils\PathFileTest; use Alchemy\Phrasea\Controller\User\Notifications; use Alchemy\Phrasea\Controller\User\Preferences; use Alchemy\Phrasea\Core\PhraseaExceptionHandler; @@ -101,6 +99,7 @@ use Alchemy\Phrasea\Core\Provider\LocaleServiceProvider; use Alchemy\Phrasea\Core\Provider\ManipulatorServiceProvider; use Alchemy\Phrasea\Core\Provider\NotificationDelivererServiceProvider; use Alchemy\Phrasea\Core\Provider\ORMServiceProvider; +use Alchemy\Phrasea\Core\Provider\PhraseaEventServiceProvider; use Alchemy\Phrasea\Core\Provider\PhraseanetServiceProvider; use Alchemy\Phrasea\Core\Provider\PluginServiceProvider; use Alchemy\Phrasea\Core\Provider\PhraseaVersionServiceProvider; @@ -121,6 +120,7 @@ use Alchemy\Phrasea\Exception\InvalidArgumentException; use Alchemy\Phrasea\Model\Entities\User; use Alchemy\Phrasea\Form\Extension\HelpTypeExtension; use Alchemy\Phrasea\Twig\JSUniqueID; +use Alchemy\Phrasea\Twig\Fit; use Alchemy\Phrasea\Twig\Camelize; use Alchemy\Phrasea\Twig\BytesConverter; use Alchemy\Phrasea\Utilities\CachedTranslator; @@ -155,8 +155,8 @@ use XPDF\XPDFServiceProvider; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpFoundation\RedirectResponse; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Routing\Generator\UrlGenerator; use Symfony\Component\Form\FormFactory; use Symfony\Component\Form\FormTypeInterface; @@ -317,8 +317,10 @@ class Application extends SilexApplication $this->register(new SessionHandlerServiceProvider()); $this->register(new SessionServiceProvider(), [ - 'session.test' => $this->getEnvironment() === static::ENV_TEST + 'session.test' => $this->getEnvironment() === static::ENV_TEST, + 'session.storage.options' => array('cookie_lifetime' => 0) ]); + $this['session.storage.test'] = $this->share(function ($app) { return new MockArraySessionStorage(); }); @@ -378,6 +380,7 @@ class Application extends SilexApplication $this->register(new FileServeServiceProvider()); $this->register(new ManipulatorServiceProvider()); $this->register(new PluginServiceProvider()); + $this->register(new PhraseaEventServiceProvider()); $this['phraseanet.exception_handler'] = $this->share(function ($app) { $handler = PhraseaExceptionHandler::register($app['debug']); @@ -471,12 +474,12 @@ class Application extends SilexApplication $this['dispatcher'] = $this->share( $this->extend('dispatcher', function ($dispatcher, Application $app) { - $dispatcher->addListener(KernelEvents::REQUEST, [$app, 'initSession'], 254); - $dispatcher->addListener(KernelEvents::RESPONSE, [$app, 'addUTF8Charset'], -128); - $dispatcher->addSubscriber(new LogoutSubscriber()); - $dispatcher->addSubscriber(new PhraseaLocaleSubscriber($app)); - $dispatcher->addSubscriber(new MaintenanceSubscriber($app)); - $dispatcher->addSubscriber(new CookiesDisablerSubscriber($app)); + $dispatcher->addListener(KernelEvents::RESPONSE, array($app, 'addUTF8Charset'), -128); + $dispatcher->addSubscriber($app['phraseanet.logout-subscriber']); + $dispatcher->addSubscriber($app['phraseanet.locale-subscriber']); + $dispatcher->addSubscriber($app['phraseanet.maintenance-subscriber']); + $dispatcher->addSubscriber($app['phraseanet.cookie-disabler-subscriber']); + $dispatcher->addSubscriber($app['phraseanet.session-manager-subscriber']); $dispatcher->addSubscriber(new PhraseaInstallSubscriber($app)); return $dispatcher; @@ -557,25 +560,6 @@ class Application extends SilexApplication return $this->redirect($this->url($route, $parameters)); } - public function initSession(GetResponseEvent $event) - { - if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) { - return; - } - - if (false !== stripos($event->getRequest()->server->get('HTTP_USER_AGENT'), 'flash') - && $event->getRequest()->getRequestUri() === '/prod/upload/') { - - if (null !== $sessionId = $event->getRequest()->request->get('php_session_id')) { - - $request = $event->getRequest(); - $request->cookies->set($this['session']->getName(), $sessionId); - - return $request; - } - } - } - public function addUTF8Charset(FilterResponseEvent $event) { if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) { @@ -642,6 +626,7 @@ class Application extends SilexApplication // add filters truncate, wordwrap, nl2br $twig->addExtension(new \Twig_Extensions_Extension_Text()); $twig->addExtension(new JSUniqueID()); + $twig->addExtension(new Fit()); $twig->addExtension(new Camelize()); $twig->addExtension(new BytesConverter()); @@ -667,23 +652,32 @@ class Application extends SilexApplication return ConnectedUsers::appName($app['translator'], $value); })); $twig->addFilter(new \Twig_SimpleFilter('escapeSimpleQuote', function ($value) { - $ret = str_replace("'", "\\'", $value); - - return $ret; + return str_replace("'", "\\'", $value); })); - $twig->addFilter(new \Twig_SimpleFilter('thesaurus', function (\Twig_Environment $twig, $value) { - if (!$value instanceof \ThesaurusValue) { - return str_replace(['[[em]]', '[[/em]]'], ['', ''], twig_escape_filter($twig, $value)); - } - return "getField()->get_databox()->get_sbas_id() . "','" - . str_replace("'", "\\'", $value->getQuery()) - . "', '" - . str_replace("'", "\\'", $value->getField()->get_name()) - . "');return(false);\">" - . str_replace(['[[em]]', '[[/em]]'], ['', ''], twig_escape_filter($twig, $value->getValue())) - . ""; - }, ['needs_environment' => true, 'is_safe' => ['html']])); + $twig->addFilter(new \Twig_SimpleFilter('highlight', function (\Twig_Environment $twig, $string) { + return str_replace(array('[[em]]', '[[/em]]'), array('', ''), $string); + }, array('needs_environment' => true,'is_safe' => array('html')))); + + $twig->addFilter(new \Twig_SimpleFilter('linkify', function (\Twig_Environment $twig, $string) { + return preg_replace( + "(([^']{1})((https?|file):((/{2,4})|(\\{2,4}))[\w:#%/;$()~_?/\-=\\\.&]*)([^']{1}))" + , '$1 $2  $7' + , $string + ); + }, array('needs_environment' => true, 'is_safe' => array('html')))); + + $twig->addFilter(new \Twig_SimpleFilter('bounce', function (\Twig_Environment $twig, $fieldValue, $fieldName, $searchRequest, $sbasId) { + // bounce value if it is present in thesaurus as well + return "" + . $fieldValue + . ""; + + }, array('needs_environment' => true, 'is_safe' => array('html')))); $twig->addFilter(new \Twig_SimpleFilter('escapeDoubleQuote', function ($value) { return str_replace('"', '\"', $value); @@ -843,8 +837,6 @@ class Application extends SilexApplication $this->mount('/admin/fields', new Fields()); $this->mount('/admin/task-manager', new TaskManager()); $this->mount('/admin/subdefs', new Subdefs()); - $this->mount('/admin/tests/connection', new ConnectionTest()); - $this->mount('/admin/tests/pathurl', new PathFileTest()); $this->mount('/client/', new ClientRoot()); $this->mount('/client/baskets', new ClientBasket()); @@ -881,8 +873,6 @@ class Application extends SilexApplication $this->mount('/session/', new Session()); $this->mount('/setup', new SetupController()); - $this->mount('/setup/connection_test/', new ConnectionTest()); - $this->mount('/setup/test/', new PathFileTest()); $this->mount('/report/', new ReportRoot()); $this->mount('/report/activity', new ReportActivity()); diff --git a/lib/Alchemy/Phrasea/Application/Api.php b/lib/Alchemy/Phrasea/Application/Api.php index 72d6ce0895..e962ab1df7 100644 --- a/lib/Alchemy/Phrasea/Application/Api.php +++ b/lib/Alchemy/Phrasea/Application/Api.php @@ -12,13 +12,14 @@ namespace Alchemy\Phrasea\Application; use Alchemy\Phrasea\Application as PhraseaApplication; +use Alchemy\Phrasea\Core\Event\Subscriber\ApiCorsSubscriber; +use Alchemy\Phrasea\Core\PhraseaEvents; use Alchemy\Phrasea\Controller\Api\Oauth2; use Alchemy\Phrasea\Controller\Api\Result; use Alchemy\Phrasea\Controller\Api\V1; use Alchemy\Phrasea\Core\Event\ApiResultEvent; use Alchemy\Phrasea\Core\Event\Subscriber\ApiOauth2ErrorsSubscriber; use Alchemy\Phrasea\Core\Event\Subscriber\ApiExceptionHandlerSubscriber; -use Alchemy\Phrasea\Core\PhraseaEvents; use Monolog\Logger; use Monolog\Processor\WebProcessor; use Silex\Application as SilexApplication; @@ -71,6 +72,8 @@ return call_user_func(function ($environment = PhraseaApplication::ENV_PROD) { $app->after(function (Request $request, Response $response) use ($app) { $app['dispatcher']->dispatch(PhraseaEvents::API_RESULT, new ApiResultEvent($request, $response)); }); + $app['dispatcher']->addSubscriber(new ApiCorsSubscriber($app)); + $app['dispatcher']->dispatch(PhraseaEvents::API_LOAD_END, new ApiLoadEndEvent()); return $app; }, isset($environment) ? $environment : PhraseaApplication::ENV_PROD); diff --git a/lib/Alchemy/Phrasea/Border/Manager.php b/lib/Alchemy/Phrasea/Border/Manager.php index cdfda37873..ff31a90754 100644 --- a/lib/Alchemy/Phrasea/Border/Manager.php +++ b/lib/Alchemy/Phrasea/Border/Manager.php @@ -15,6 +15,8 @@ use Alchemy\Phrasea\Border\Checker\CheckerInterface; use Alchemy\Phrasea\Border\Attribute\AttributeInterface; use Alchemy\Phrasea\Metadata\Tag\TfArchivedate; use Alchemy\Phrasea\Metadata\Tag\TfQuarantine; +use Alchemy\Phrasea\Metadata\Tag\TfBasename; +use Alchemy\Phrasea\Metadata\Tag\TfFilename; use Alchemy\Phrasea\Metadata\Tag\TfRecordid; use Alchemy\Phrasea\Border\Attribute\Metadata as MetadataAttr; use Alchemy\Phrasea\Model\Entities\LazaretAttribute; @@ -242,20 +244,37 @@ class Manager ) ) ); + $file->addAttribute( + new MetadataAttr( + new Metadata( + new TfBasename(), new MonoValue(pathinfo($file->getOriginalName(), PATHINFO_BASENAME)) + ) + ) + ); + $file->addAttribute( + new MetadataAttr( + new Metadata( + new TfFilename(), new MonoValue(pathinfo($file->getOriginalName(), PATHINFO_FILENAME)) + ) + ) + ); $newMetadata = $file->getMedia()->getMetadatas()->toArray(); - foreach ($file->getAttributes() as $attribute) { switch ($attribute->getName()) { - - /** - * @todo implement METATAG aka metadata by fieldname (where as - * current metadata is metadata by source. - */ case AttributeInterface::NAME_METAFIELD: $values = $attribute->getValue(); $value = $attribute->getField()->is_multi() ? new Multi($values) : new MonoValue(array_pop($values)); - $newMetadata[] = new Metadata($attribute->getField()->get_tag(), $value); + + $tag = $attribute->getField()->get_tag(); + + if ($tag instanceof \Alchemy\Phrasea\Metadata\Tag\Nosource) { + $tag->setTagname($attribute->getField()->get_name()); + $_meta = new Metadata($tag, $value); + } else { + $_meta = new Metadata($attribute->getField()->get_tag(), $value); + } + $newMetadata[] = $_meta; break; case AttributeInterface::NAME_METADATA: @@ -342,7 +361,6 @@ class Manager $attribute->setName($fileAttribute->getName()); $attribute->setValue($fileAttribute->asString()); $attribute->setLazaretFile($lazaretFile); - $lazaretFile->addAttribute($attribute); $this->app['EM']->persist($attribute); diff --git a/lib/Alchemy/Phrasea/Border/MimeGuesserConfiguration.php b/lib/Alchemy/Phrasea/Border/MimeGuesserConfiguration.php index ba8395ffc3..cfda50f3e9 100644 --- a/lib/Alchemy/Phrasea/Border/MimeGuesserConfiguration.php +++ b/lib/Alchemy/Phrasea/Border/MimeGuesserConfiguration.php @@ -16,7 +16,6 @@ use MediaVorus\Utils\AudioMimeTypeGuesser; use MediaVorus\Utils\PostScriptMimeTypeGuesser; use MediaVorus\Utils\RawImageMimeTypeGuesser; use MediaVorus\Utils\VideoMimeTypeGuesser; -use Symfony\Component\HttpFoundation\File\MimeType\FileBinaryMimeTypeGuesser; use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser; class MimeGuesserConfiguration @@ -36,7 +35,6 @@ class MimeGuesserConfiguration { $guesser = MimeTypeGuesser::getInstance(); - $guesser->register(new FileBinaryMimeTypeGuesser()); $guesser->register(new RawImageMimeTypeGuesser()); $guesser->register(new PostScriptMimeTypeGuesser()); $guesser->register(new AudioMimeTypeGuesser()); diff --git a/lib/Alchemy/Phrasea/Controller/Admin/Collection.php b/lib/Alchemy/Phrasea/Controller/Admin/Collection.php index 4cb73b1f04..9464111cc3 100644 --- a/lib/Alchemy/Phrasea/Controller/Admin/Collection.php +++ b/lib/Alchemy/Phrasea/Controller/Admin/Collection.php @@ -254,11 +254,11 @@ class Collection implements ControllerProviderInterface } if ('json' === $app['request']->getRequestFormat()) { - return $app->json([ - 'success' => $success, - 'msg' => $msg, - 'bas_id' => $collection->get_base_id() - ]); + return $app->json(array( + 'success' => $success, + 'msg' => $msg, + 'bas_id' => $collection->get_base_id() + )); } return $app->redirectPath('admin_display_collection', [ diff --git a/lib/Alchemy/Phrasea/Controller/Admin/Root.php b/lib/Alchemy/Phrasea/Controller/Admin/Root.php index 14044eadb3..bb3dc8955a 100644 --- a/lib/Alchemy/Phrasea/Controller/Admin/Root.php +++ b/lib/Alchemy/Phrasea/Controller/Admin/Root.php @@ -12,6 +12,8 @@ namespace Alchemy\Phrasea\Controller\Admin; use Alchemy\Phrasea\Exception\SessionNotFound; +use Alchemy\Phrasea\Helper\DatabaseHelper; +use Alchemy\Phrasea\Helper\PathHelper; use Silex\Application; use Silex\ControllerProviderInterface; use Symfony\Component\HttpFoundation\Request; @@ -24,7 +26,6 @@ class Root implements ControllerProviderInterface $app['controller.admin.root'] = $this; $controllers = $app['controllers_factory']; - $app['firewall']->addMandatoryAuthentication($controllers); $controllers->before(function (Request $request) use ($app) { @@ -447,6 +448,24 @@ class Root implements ControllerProviderInterface ->assert('bit', '\d+') ->bind('database_submit_statusbit'); + $controllers->get('/tests/connection/mysql/', function (Application $app, Request $request) { + $dbHelper = new DatabaseHelper($app, $request); + + return $app->json($dbHelper->checkConnection()); + }); + + $controllers->get('/tests/pathurl/path/', function (Application $app, Request $request) { + $pathHelper = new PathHelper($app, $request); + + return $app->json($pathHelper->checkPath()); + }); + + $controllers->get('/tests/pathurl/url/', function (Application $app, Request $request) { + $pathHelper = new PathHelper($app, $request); + + return $app->json($pathHelper->checkUrl()); + }); + return $controllers; } } diff --git a/lib/Alchemy/Phrasea/Controller/Admin/Users.php b/lib/Alchemy/Phrasea/Controller/Admin/Users.php index 5e51e9deee..5d61aa41fc 100644 --- a/lib/Alchemy/Phrasea/Controller/Admin/Users.php +++ b/lib/Alchemy/Phrasea/Controller/Admin/Users.php @@ -194,7 +194,7 @@ class Users implements ControllerProviderInterface } $filename = sprintf('user_export_%s.csv', date('Ymd')); - $response = new CSVFileResponse($filename, function() use ($app, $userTable) { + $response = new CSVFileResponse($filename, function () use ($app, $userTable) { $app['csv.exporter']->export('php://output', $userTable); }); @@ -341,7 +341,7 @@ class Users implements ControllerProviderInterface } while (count($results) > 0); $filename = sprintf('user_export_%s.csv', date('Ymd')); - $response = new CSVFileResponse($filename, function() use ($app, $buffer) { + $response = new CSVFileResponse($filename, function () use ($app, $buffer) { $app['csv.exporter']->export('php://output', $buffer); }); @@ -521,7 +521,7 @@ class Users implements ControllerProviderInterface return $app->redirectPath('users_display_import_file', ['error' => 'file-invalid']); } - $equivalenceToMysqlField = self::getEquivalenceToMysqlField(); + $equivalenceToMysqlField = Users::getEquivalenceToMysqlField(); $loginDefined = $pwdDefined = $mailDefined = false; $loginNew = []; $out = [ @@ -531,7 +531,7 @@ class Users implements ControllerProviderInterface $nbUsrToAdd = 0; $lines = array(); - $app['csv.interpreter']->addObserver(function(array $row) use (&$lines) { + $app['csv.interpreter']->addObserver(function (array $row) use (&$lines) { $lines[] = $row; }); $app['csv.lexer']->parse($file->getPathname(), $app['csv.interpreter']); diff --git a/lib/Alchemy/Phrasea/Controller/Prod/DoDownload.php b/lib/Alchemy/Phrasea/Controller/Prod/DoDownload.php index 7ae2b21ad4..aa2ae7b5fe 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/DoDownload.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/DoDownload.php @@ -97,7 +97,8 @@ class DoDownload implements ControllerProviderInterface 'list' => $list, 'records' => $records, 'token' => $token, - 'anonymous' => $request->query->get('anonymous', false) + 'anonymous' => $request->query->get('anonymous', false), + 'type' => $request->query->get('type', \Session_Logger::EVENT_EXPORTDOWNLOAD) ])); } @@ -143,12 +144,12 @@ class DoDownload implements ControllerProviderInterface $app->abort(404, 'Download file not found'); } - $app['dispatcher']->addListener(KernelEvents::TERMINATE, function (PostResponseEvent $event) use ($list, $app) { + $app['dispatcher']->addListener(KernelEvents::RESPONSE, function (PostResponseEvent $event) use ($list, $app) { \set_export::log_download( $app, $list, - $event->getRequest()->request->get('type'), - (null !== $event->getRequest()->request->get('anonymous') ? true : false), + $event->getRequest()->get('type'), + !!$event->getRequest->get('anonymous', false), (isset($list['email']) ? $list['email'] : '') ); }); diff --git a/lib/Alchemy/Phrasea/Controller/Prod/Edit.php b/lib/Alchemy/Phrasea/Controller/Prod/Edit.php index 7389611c28..c0ddc149c7 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/Edit.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/Edit.php @@ -345,7 +345,7 @@ class Edit implements ControllerProviderInterface $editDirty = true; } - if (is_array($rec['metadatas'])) { + if (isset($rec['metadatas']) && is_array($rec['metadatas'])) { $record->set_metadatas($rec['metadatas']); } diff --git a/lib/Alchemy/Phrasea/Controller/Prod/Export.php b/lib/Alchemy/Phrasea/Controller/Prod/Export.php index d97f8f47b0..6385e482f3 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/Export.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/Export.php @@ -228,7 +228,7 @@ class Export implements ControllerProviderInterface $remaingEmails = $destMails; - $url = $app->url('prepare_download', ['token' => $token->getValue(), 'anonymous']); + $url = $app->url('prepare_download', ['token' => $token->getValue(), 'anonymous' => false, 'type' => \Session_Logger::EVENT_EXPORTMAIL]); $emitter = new Emitter($app['authentication']->getUser()->getDisplayName(), $app['authentication']->getUser()->getEmail()); diff --git a/lib/Alchemy/Phrasea/Controller/Prod/Language.php b/lib/Alchemy/Phrasea/Controller/Prod/Language.php index 6c5fa73802..0700729108 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/Language.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/Language.php @@ -22,8 +22,9 @@ class Language implements ControllerProviderInterface $controller = $app['controllers_factory']; - $controller->get("/", function (Application $app) { + $app['firewall']->addMandatoryAuthentication($controller); + $controller->get("/", function (Application $app) { $out = []; $out['thesaurusBasesChanged'] = $app->trans('prod::recherche: Attention : la liste des bases selectionnees pour la recherche a ete changee.'); $out['confirmDel'] = $app->trans('paniers::Vous etes sur le point de supprimer ce panier. Cette action est irreversible. Souhaitez-vous continuer ?'); diff --git a/lib/Alchemy/Phrasea/Controller/Prod/Push.php b/lib/Alchemy/Phrasea/Controller/Prod/Push.php index a92379c7a4..a4fdc54c87 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/Push.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/Push.php @@ -32,7 +32,7 @@ class Push implements ControllerProviderInterface protected function getUserFormatter(Application $app) { return function (User $user) use ($app) { - $subtitle = array_filter([$user->getJob(), $user->getCompany()]); + $subtitle = array_filter([$user->getPosition(), $user->getCompany()]); return [ 'type' => 'USER', @@ -217,12 +217,17 @@ class Push implements ControllerProviderInterface $app['EM']->flush(); - $url = $app->url('lightbox_compare', [ - 'basket' => $Basket->getId(), - 'LOG' => $app['manipulator.token']->createBasketAccessToken($Basket, $user_receiver), - ]); + $arguments = array( + 'ssel_id' => $Basket->getId(), + ); - $receipt = $request->get('recept') ? $app['authentication']->getUser()->getEmail() : ''; + if (!$app['phraseanet.registry']->get('GV_force_push_authentication') || !$request->get('force_authentication')) { + $arguments['LOG'] = $app['manipulator.token']->createBasketAccessToken($Basket, $user_receiver); + } + + $url = $app->url('lightbox_compare', $arguments); + + $receipt = $request->get('recept') ? $app['authentication']->getUser()->get_email() : ''; $params = [ 'from' => $app['authentication']->getUser()->getId(), diff --git a/lib/Alchemy/Phrasea/Controller/Prod/Tooltip.php b/lib/Alchemy/Phrasea/Controller/Prod/Tooltip.php index ff06b8c1b3..f2047b7e14 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/Tooltip.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/Tooltip.php @@ -99,12 +99,10 @@ class Tooltip implements ControllerProviderInterface public function displayPreview(Application $app, $sbas_id, $record_id) { - $record = new \record_adapter($app, $sbas_id, $record_id); - - return $app['twig']->render( - 'prod/Tooltip/Preview.html.twig' - , ['record' => $record, 'not_wrapped' => true] - ); + return $app['twig']->render('prod/Tooltip/Preview.html.twig', array( + 'record' => new \record_adapter($app, $sbas_id, $record_id), + 'not_wrapped' => true + )); } public function displayCaption(Application $app, $sbas_id, $record_id, $context) diff --git a/lib/Alchemy/Phrasea/Controller/Report/Activity.php b/lib/Alchemy/Phrasea/Controller/Report/Activity.php index daa452bc82..031195c6bf 100644 --- a/lib/Alchemy/Phrasea/Controller/Report/Activity.php +++ b/lib/Alchemy/Phrasea/Controller/Report/Activity.php @@ -309,8 +309,6 @@ class Activity implements ControllerProviderInterface $activity->setConfig(false); - - if ($request->request->get('printcsv') == 'on') { $activity->setHasLimit(false); $activity->setPrettyString(false); @@ -862,13 +860,13 @@ class Activity implements ControllerProviderInterface $result = $report->getResult(); array_unshift($result, $headers); - $collection = new CallbackCollection($result, function($row) use ($report) { + $collection = new CallbackCollection($result, function ($row) use ($report) { // restrict to displayed fields return array_map('strip_tags', array_intersect_key($row, $report->getDisplay())); }); $filename = sprintf('report_export_%s_%s.csv', $type, date('Ymd')); - $response = new CSVFileResponse($filename, function() use ($app, $collection) { + $response = new CSVFileResponse($filename, function () use ($app, $collection) { $app['csv.exporter']->export('php://output', $collection); }); diff --git a/lib/Alchemy/Phrasea/Controller/Report/Informations.php b/lib/Alchemy/Phrasea/Controller/Report/Informations.php index 1dafb005ce..85fdc46895 100644 --- a/lib/Alchemy/Phrasea/Controller/Report/Informations.php +++ b/lib/Alchemy/Phrasea/Controller/Report/Informations.php @@ -520,13 +520,13 @@ class Informations implements ControllerProviderInterface $result = $report->getResult(); array_unshift($result, $headers); - $collection = new CallbackCollection($result, function($row) use ($report) { + $collection = new CallbackCollection($result, function ($row) use ($report) { // restrict fields to the displayed ones return array_map('strip_tags', array_intersect_key($row, $report->getDisplay())); }); $filename = sprintf('report_export_%s_%s.csv', $type, date('Ymd')); - $response = new CSVFileResponse($filename, function() use ($app, $collection) { + $response = new CSVFileResponse($filename, function () use ($app, $collection) { $app['csv.exporter']->export('php://output', $collection); }); diff --git a/lib/Alchemy/Phrasea/Controller/Report/Root.php b/lib/Alchemy/Phrasea/Controller/Report/Root.php index 5b0b84e954..dbf5b0ac76 100644 --- a/lib/Alchemy/Phrasea/Controller/Report/Root.php +++ b/lib/Alchemy/Phrasea/Controller/Report/Root.php @@ -18,7 +18,6 @@ use Silex\ControllerProviderInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\JsonResponse; -use Symfony\Component\HttpFoundation\ResponseHeaderBag; class Root implements ControllerProviderInterface { @@ -486,28 +485,28 @@ class Root implements ControllerProviderInterface $result = array(); $result[] = array_keys($conf_nav); - foreach($report['nav']['result'] as $row) { + foreach ($report['nav']['result'] as $row) { $result[] = array_values($row); }; $result[] = array_keys($conf_os); - foreach($report['os']['result'] as $row) { + foreach ($report['os']['result'] as $row) { $result[] = array_values($row); }; $result[] = array_keys($conf_res); - foreach($report['res']['result'] as $row) { + foreach ($report['res']['result'] as $row) { $result[] = array_values($row); }; $result[] = array_keys($conf_mod); - foreach($report['mod']['result'] as $row) { + foreach ($report['mod']['result'] as $row) { $result[] = array_values($row); }; $result[] = array_keys($conf_combo); - foreach($report['combo']['result'] as $row) { + foreach ($report['combo']['result'] as $row) { $result[] = array_values($row); }; $filename = sprintf('report_export_info_%s.csv', date('Ymd')); - $response = new CSVFileResponse($filename, function() use ($app, $result) { + $response = new CSVFileResponse($filename, function () use ($app, $result) { $app['csv.exporter']->export('php://output', $result); }); @@ -686,13 +685,13 @@ class Root implements ControllerProviderInterface $result = $report->getResult(); array_unshift($result, $headers); - $collection = new CallbackCollection($result, function($row) use ($report) { + $collection = new CallbackCollection($result, function ($row) use ($report) { // restrict fields to the displayed ones return array_map('strip_tags', array_intersect_key($row, $report->getDisplay())); }); $filename = sprintf('report_export_%s_%s.csv', $type, date('Ymd')); - $response = new CSVFileResponse($filename, function() use ($app, $collection) { + $response = new CSVFileResponse($filename, function () use ($app, $collection) { $app['csv.exporter']->export('php://output', $collection); }); diff --git a/lib/Alchemy/Phrasea/Controller/Root/Developers.php b/lib/Alchemy/Phrasea/Controller/Root/Developers.php index 9406b7cc6f..f3e8643572 100644 --- a/lib/Alchemy/Phrasea/Controller/Root/Developers.php +++ b/lib/Alchemy/Phrasea/Controller/Root/Developers.php @@ -64,6 +64,10 @@ class Developers implements ControllerProviderInterface ->assert('application', '\d+') ->bind('submit_application_callback'); + $controllers->post('/application/{id}/webhook/', $this->call('renewAppWebhook')) + ->assert('id', '\d+') + ->bind('submit_application_webhook'); + return $controllers; } @@ -111,6 +115,30 @@ class Developers implements ControllerProviderInterface return $app->json(['success' => true]); } + + /** + * Change application webhook + * + * @param Application $app A Silex application where the controller is mounted on + * @param Request $request The current request + * @param integer $id The application id + * @return JsonResponse + */ + public function renewAppWebhook(Application $app, Request $request, $id) + { + if (!$request->isXmlHttpRequest() || !array_key_exists($request->getMimeType('json'), array_flip($request->getAcceptableContentTypes()))) { + $app->abort(400, _('Bad request format, only JSON is allowed')); + } + + if (null !== $request->request->get("webhook")) { + $app['manipulator.api-application']->setWebhook($request->request->get("webhook")); + } else { + return $app->json(['success' => false]); + } + + return $app->json(array('success' => true)); + } + /** * Authorize application to use a grant password type. * diff --git a/lib/Alchemy/Phrasea/Controller/Root/Login.php b/lib/Alchemy/Phrasea/Controller/Root/Login.php index 546403921b..8b4e8ca2e6 100644 --- a/lib/Alchemy/Phrasea/Controller/Root/Login.php +++ b/lib/Alchemy/Phrasea/Controller/Root/Login.php @@ -284,6 +284,12 @@ class Login implements ControllerProviderInterface unset($requestData['geonameid-completer']); } + // Remove multiselect field for validation this field is added client side + // with bootstrap multiselect plugin + if (isset($requestData['multiselect'])) { + unset($requestData['multiselect']); + } + $form->bind($requestData); $data = $form->getData(); @@ -717,7 +723,7 @@ class Login implements ControllerProviderInterface $feeds = $app['repo.feeds']->findBy(['public' => true], ['updatedOn' => 'DESC']); - $form = $app->form(new PhraseaAuthenticationForm()); + $form = $app->form(new PhraseaAuthenticationForm($app)); $form->setData([ 'redirect' => $request->query->get('redirect') ]); @@ -739,7 +745,7 @@ class Login implements ControllerProviderInterface */ public function authenticate(PhraseaApplication $app, Request $request) { - $form = $app->form(new PhraseaAuthenticationForm()); + $form = $app->form(new PhraseaAuthenticationForm($app)); $redirector = function (array $params = []) use ($app) { return $app->redirectPath('homepage', $params); }; @@ -1027,7 +1033,7 @@ class Login implements ControllerProviderInterface $session->setToken($token)->setNonce($nonce); - $response->headers->setCookie(new Cookie('persistent', $token)); + $response->headers->setCookie(new Cookie('persistent', $token, time() + $app['phraseanet.configuration']['session']['lifetime'])); $app['EM']->persist($session); $app['EM']->flush(); diff --git a/lib/Alchemy/Phrasea/Controller/Root/Session.php b/lib/Alchemy/Phrasea/Controller/Root/Session.php index 5386cfc027..123f1d32da 100644 --- a/lib/Alchemy/Phrasea/Controller/Root/Session.php +++ b/lib/Alchemy/Phrasea/Controller/Root/Session.php @@ -28,6 +28,9 @@ class Session implements ControllerProviderInterface $controllers->post('/update/', 'controller.session:updateSession') ->bind('update_session'); + $controllers->post('/notifications/', 'controller.session:getNotifications') + ->bind('list_notifications'); + $controller = $controllers->post('/delete/{id}', 'controller.session:deleteSession') ->bind('delete_session'); @@ -36,6 +39,76 @@ class Session implements ControllerProviderInterface return $controllers; } + /** + * Check things to notify + * + * @param Application $app + * @param Request $request + * @return JsonResponse + */ + public function getNotifications(Application $app, Request $request) + { + if (!$request->isXmlHttpRequest()) { + $app->abort(400); + } + + $ret = array( + 'status' => 'unknown', + 'message' => '', + 'notifications' => false, + 'changed' => array() + ); + + if ($app['authentication']->isAuthenticated()) { + $usr_id = $app['authentication']->getUser()->get_id(); + if ($usr_id != $request->request->get('usr')) { // I logged with another user + $ret['status'] = 'disconnected'; + + return $app->json($ret); + } + } else { + $ret['status'] = 'disconnected'; + + return $app->json($ret); + } + + try { + $app['phraseanet.appbox']->get_connection(); + } catch (\Exception $e) { + return $app->json($ret); + } + + if (1 > $moduleId = (int) $request->request->get('module')) { + $ret['message'] = 'Missing or Invalid `module` parameter'; + + return $app->json($ret); + } + + $ret['status'] = 'ok'; + + $ret['notifications'] = $app['twig']->render('prod/notifications.html.twig', array( + 'notifications' => $app['events-manager']->get_notifications() + )); + + $baskets = $app['EM']->getRepository('\Entities\Basket')->findUnreadActiveByUser($app['authentication']->getUser()); + + foreach ($baskets as $basket) { + $ret['changed'][] = $basket->getId(); + } + + if (in_array($app['session']->get('phraseanet.message'), array('1', null))) { + if ($app['phraseanet.configuration']['main']['maintenance']) { + $ret['message'] .= _('The application is going down for maintenance, please logout.'); + } + + if ($app['phraseanet.registry']->get('GV_message_on')) { + $ret['message'] .= strip_tags($app['phraseanet.registry']->get('GV_message')); + } + } + + return $app->json($ret); + } + /** * Check session state * diff --git a/lib/Alchemy/Phrasea/Controller/Setup.php b/lib/Alchemy/Phrasea/Controller/Setup.php index f800a0b140..043affcf01 100644 --- a/lib/Alchemy/Phrasea/Controller/Setup.php +++ b/lib/Alchemy/Phrasea/Controller/Setup.php @@ -12,6 +12,8 @@ namespace Alchemy\Phrasea\Controller; use Alchemy\Phrasea\Application; +use Alchemy\Phrasea\Helper\DatabaseHelper; +use Alchemy\Phrasea\Helper\PathHelper; use Alchemy\Phrasea\Setup\Requirements\BinariesRequirements; use Alchemy\Phrasea\Setup\Requirements\FilesystemRequirements; use Alchemy\Phrasea\Setup\Requirements\LocalesRequirements; @@ -46,6 +48,24 @@ class Setup implements ControllerProviderInterface $controllers->post('/installer/install/', 'controller.setup:doInstall') ->bind('install_do_install'); + $controllers->get('/connection_test/mysql/', function (Application $app, Request $request) { + $dbHelper = new DatabaseHelper($app, $request); + + return $app->json($dbHelper->checkConnection()); + }); + + $controllers->get('/test/path/', function (Application $app, Request $request) { + $pathHelper = new PathHelper($app, $request); + + return $app->json($pathHelper->checkPath()); + }); + + $controllers->get('/test/url/', function (Application $app, Request $request) { + $pathHelper = new PathHelper($app, $request); + + return $app->json($pathHelper->checkUrl()); + }); + return $controllers; } diff --git a/lib/Alchemy/Phrasea/Controller/Thesaurus/Xmlhttp.php b/lib/Alchemy/Phrasea/Controller/Thesaurus/Xmlhttp.php index 8bd0c4e692..8ce1462e8b 100644 --- a/lib/Alchemy/Phrasea/Controller/Thesaurus/Xmlhttp.php +++ b/lib/Alchemy/Phrasea/Controller/Thesaurus/Xmlhttp.php @@ -739,7 +739,7 @@ class Xmlhttp implements ControllerProviderInterface public function OpenBranchJson(Application $app, Request $request) { - if (null === $lng = $request->get('lng')) { + if (null === ($lng = $request->get('lng'))) { $data = explode('_', $app['locale']); if (count($data) > 0) { $lng = $data[0]; @@ -750,6 +750,15 @@ class Xmlhttp implements ControllerProviderInterface $sbid = (int) $request->get('sbid'); + $lcoll = ''; + $collections = $app['authentication']->getUser()->ACL() + ->get_granted_base(array(), array($sbid)); // array(), $sbid); + foreach ($collections as $collection) { + $lcoll .= ($lcoll?",":"") . $collection->get_coll_id(); + } + $site = $app['phraseanet.configuration']['main']['key']; + $usr_id = $app['authentication']->getUser()->get_id(); + $tids = explode('.', $request->get('id')); $thid = implode('.', $tids); @@ -765,11 +774,14 @@ class Xmlhttp implements ControllerProviderInterface if ($lthid == 1) { $dthid = str_replace('.', 'd', $thid); - $sql = 'SELECT COUNT(DISTINCT record_id) AS n - FROM thit WHERE value LIKE :like '; + $sql = 'SELECT COUNT(DISTINCT r.record_id) AS n + FROM (thit AS t INNER JOIN record AS r USING(record_id)) + INNER JOIN collusr AS c ON c.site=:site AND c.usr_id=:usr_id AND r.coll_id=c.coll_id + WHERE t.value LIKE :like AND r.coll_id IN('.$lcoll.') AND (r.status^c.mask_xor)&c.mask_and=0'; + $sqlparm = array(':like' => $dthid . '%', ':site'=>$site, ':usr_id'=>$usr_id); $stmt = $connbas->prepare($sql); - $stmt->execute([':like' => $dthid . '%']); + $stmt->execute($sqlparm); $rs = $stmt->fetchAll(\PDO::FETCH_ASSOC); $stmt->closeCursor(); @@ -778,14 +790,16 @@ class Xmlhttp implements ControllerProviderInterface } $sql = 'SELECT - SUBSTRING_INDEX(SUBSTR(value, ' . ($lthid + 1) . '), "d", 1) AS k , - COUNT(DISTINCT record_id) AS n - FROM thit - WHERE value LIKE :like + SUBSTRING_INDEX(SUBSTR(t.value, ' . ($lthid + 1) . '), "d", 1) AS k , + COUNT(DISTINCT t.record_id) AS n + FROM (thit AS t INNER JOIN record AS r USING(record_id)) + INNER JOIN collusr AS c ON c.site=:site AND c.usr_id=:usr_id AND r.coll_id=c.coll_id + WHERE t.value LIKE :like AND r.coll_id IN('.$lcoll.') AND (r.status^c.mask_xor)&c.mask_and=0 GROUP BY k'; + $sqlparm = array(':like' => $dthid . '%', ':site'=>$site, ':usr_id'=>$usr_id); $stmt = $connbas->prepare($sql); - $stmt->execute([':like' => $dthid . '%']); + $stmt->execute(array(':like' => $dthid . '%')); $rs = $stmt->fetchAll(\PDO::FETCH_ASSOC); $stmt->closeCursor(); @@ -795,14 +809,16 @@ class Xmlhttp implements ControllerProviderInterface } elseif (strlen($thid) > 1) { $dthid = str_replace('.', 'd', $thid); $sql = 'SELECT - SUBSTRING_INDEX(SUBSTR(value, ' . ($lthid) . '), \'d\', 1) AS k , - COUNT(DISTINCT record_id) AS n - FROM thit - WHERE value LIKE :like + SUBSTRING_INDEX(SUBSTR(t.value, ' . ($lthid) . '), \'d\', 1) AS k , + COUNT(DISTINCT t.record_id) AS n + FROM (thit AS t INNER JOIN record AS r USING(record_id)) + INNER JOIN collusr AS c ON c.site=:site AND c.usr_id=:usr_id AND r.coll_id=c.coll_id + WHERE t.value LIKE :like AND r.coll_id IN('.$lcoll.') AND (r.status^c.mask_xor)&c.mask_and=0 GROUP BY k'; + $sqlparm = array(':like' => $dthid . '%', ':site'=>$site, ':usr_id'=>$usr_id); $stmt = $connbas->prepare($sql); - $stmt->execute([':like' => $dthid . '%']); + $stmt->execute($sqlparm); $rs = $stmt->fetchAll(\PDO::FETCH_ASSOC); $stmt->closeCursor(); @@ -811,14 +827,16 @@ class Xmlhttp implements ControllerProviderInterface } $sql = 'SELECT - SUBSTRING_INDEX(SUBSTR(value, ' . ($lthid + 2) . '), \'d\', 1) AS k , - COUNT(DISTINCT record_id) AS n - FROM thit - WHERE value LIKE :like + SUBSTRING_INDEX(SUBSTR(t.value, ' . ($lthid + 2) . '), \'d\', 1) AS k , + COUNT(DISTINCT t.record_id) AS n + FROM (thit AS t INNER JOIN record AS r USING(record_id)) + INNER JOIN collusr AS c ON c.site=:site AND c.usr_id=:usr_id AND r.coll_id=c.coll_id + WHERE t.value LIKE :like AND r.coll_id IN('.$lcoll.') AND (r.status^c.mask_xor)&c.mask_and=0 GROUP BY k'; + $sqlparm = array(':like' => $dthid . '%', ':site'=>$site, ':usr_id'=>$usr_id); $stmt = $connbas->prepare($sql); - $stmt->execute([':like' => $dthid . '%']); + $stmt->execute($sqlparm); $rs = $stmt->fetchAll(\PDO::FETCH_ASSOC); $stmt->closeCursor(); @@ -905,7 +923,7 @@ class Xmlhttp implements ControllerProviderInterface $html .= ' diff --git a/templates/web/client/index.html.twig b/templates/web/client/index.html.twig index e35625cc3e..63a083c94b 100644 --- a/templates/web/client/index.html.twig +++ b/templates/web/client/index.html.twig @@ -1,7 +1,7 @@ {{ app['conf'].get(['registry', 'general', 'title']) }} Client - +