diff --git a/composer.json b/composer.json index 47635b0e47..7497b86823 100644 --- a/composer.json +++ b/composer.json @@ -84,7 +84,7 @@ "league/flysystem": "^1.0", "league/flysystem-aws-s3-v2": "^1.0", "league/fractal": "dev-webgalleries#af1acc0275438571bc8c1d08a05a4b5af92c9f97 as 0.13.0", - "media-alchemyst/media-alchemyst": "^0.5", + "media-alchemyst/media-alchemyst": "^0.5.5", "monolog/monolog": "~1.3", "mrclay/minify": "~2.1.6", "neutron/process-manager": "2.0.x-dev@dev", diff --git a/composer.lock b/composer.lock index 482cce9daf..7c347581f1 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "e5bed7b0b8cb8b45ffffc4965a7689db", - "content-hash": "f3b1fc0a30bf14b05e57ce673550d9c0", + "content-hash": "d0c8742d02e8d51c702c26ecb5502b30", "packages": [ { "name": "alchemy-fr/tcpdf-clone", @@ -71,7 +70,7 @@ "source": "https://github.com/alchemy-fr/tcpdf-clone/tree/6.0.039", "issues": "https://github.com/alchemy-fr/tcpdf-clone/issues" }, - "time": "2013-10-13 16:11:17" + "time": "2013-10-13T16:11:17+00:00" }, { "name": "alchemy/binary-driver", @@ -128,7 +127,7 @@ "binary", "driver" ], - "time": "2016-03-02 13:49:15" + "time": "2016-03-02T13:49:15+00:00" }, { "name": "alchemy/embed-bundle", @@ -172,7 +171,7 @@ } ], "description": "Embed resources bundle", - "time": "2019-10-09 14:34:23" + "time": "2019-10-09T14:34:23+00:00" }, { "name": "alchemy/geonames-api-consumer", @@ -210,7 +209,7 @@ "keywords": [ "geonames" ], - "time": "2014-02-05 15:29:39" + "time": "2014-02-05T15:29:39+00:00" }, { "name": "alchemy/ghostscript", @@ -262,7 +261,7 @@ "ghostscript", "pdf" ], - "time": "2013-06-25 09:12:58" + "time": "2013-06-25T09:12:58+00:00" }, { "name": "alchemy/mediavorus", @@ -324,7 +323,7 @@ "keywords": [ "metadata" ], - "time": "2019-01-22 11:23:34" + "time": "2019-01-22T11:23:34+00:00" }, { "name": "alchemy/oauth2php", @@ -347,7 +346,7 @@ ] }, "notification-url": "https://packagist.org/downloads/", - "time": "2019-01-17 14:34:10" + "time": "2019-01-17T14:34:10+00:00" }, { "name": "alchemy/phlickr", @@ -370,7 +369,7 @@ } }, "notification-url": "https://packagist.org/downloads/", - "time": "2014-12-15 14:27:57" + "time": "2014-12-15T14:27:57+00:00" }, { "name": "alchemy/phpexiftool", @@ -443,7 +442,7 @@ "exiftool", "metadata" ], - "time": "2019-02-13 13:06:43" + "time": "2019-02-13T13:06:43+00:00" }, { "name": "alchemy/queue-bundle", @@ -491,7 +490,7 @@ } ], "description": "Symfony bundle for alchemy/queue-component", - "time": "2016-10-04 14:19:39" + "time": "2016-10-04T14:19:39+00:00" }, { "name": "alchemy/queue-component", @@ -536,7 +535,7 @@ "MIT" ], "description": "Message queue component", - "time": "2016-10-05 10:41:36" + "time": "2016-10-05T10:41:36+00:00" }, { "name": "alchemy/rest-bundle", @@ -588,7 +587,7 @@ } ], "description": "Simple REST utility bundle", - "time": "2016-05-16 09:37:34" + "time": "2016-05-16T09:37:34+00:00" }, { "name": "alchemy/symfony-cors", @@ -635,7 +634,7 @@ } ], "description": "A library that adds CORS services to Silex/Symfony Applications", - "time": "2015-12-17 15:34:43" + "time": "2015-12-17T15:34:43+00:00" }, { "name": "alchemy/task-manager", @@ -698,7 +697,7 @@ "parallel", "process" ], - "time": "2016-11-30 13:34:30" + "time": "2016-11-30T13:34:30+00:00" }, { "name": "alchemy/worker-bundle", @@ -747,7 +746,7 @@ } ], "description": "Symfony bundle for alchemy/worker-component", - "time": "2016-12-06 10:39:58" + "time": "2016-12-06T10:39:58+00:00" }, { "name": "alchemy/worker-component", @@ -793,7 +792,7 @@ "MIT" ], "description": "Message queue worker component", - "time": "2016-11-14 16:41:16" + "time": "2016-11-14T16:41:16+00:00" }, { "name": "alchemy/zippy", @@ -855,7 +854,7 @@ "tar", "zip" ], - "time": "2016-02-15 22:46:40" + "time": "2016-02-15T22:46:40+00:00" }, { "name": "aws/aws-sdk-php", @@ -918,7 +917,7 @@ "s3", "sdk" ], - "time": "2016-07-25 18:03:20" + "time": "2016-07-25T18:03:20+00:00" }, { "name": "beberlei/assert", @@ -973,7 +972,7 @@ "assertion", "validation" ], - "time": "2017-01-24 15:14:39" + "time": "2017-01-24T15:14:39+00:00" }, { "name": "behat/transliterator", @@ -1013,7 +1012,7 @@ "slug", "transliterator" ], - "time": "2015-09-28 16:26:35" + "time": "2015-09-28T16:26:35+00:00" }, { "name": "box/spout", @@ -1081,7 +1080,7 @@ "write", "xlsx" ], - "time": "2017-09-25 19:44:35" + "time": "2017-09-25T19:44:35+00:00" }, { "name": "cocur/slugify", @@ -1145,7 +1144,7 @@ "slug", "slugify" ], - "time": "2016-08-09 20:10:17" + "time": "2016-08-09T20:10:17+00:00" }, { "name": "czproject/git-php", @@ -1187,7 +1186,7 @@ "keywords": [ "git" ], - "time": "2019-02-09 13:11:36" + "time": "2019-02-09T13:11:36+00:00" }, { "name": "dailymotion/sdk", @@ -1220,7 +1219,7 @@ "dailymotion", "sdk" ], - "time": "2015-11-20 11:18:32" + "time": "2015-11-20T11:18:32+00:00" }, { "name": "data-uri/data-uri", @@ -1265,7 +1264,7 @@ "data-uri", "uri" ], - "time": "2014-08-22 15:01:57" + "time": "2014-08-22T15:01:57+00:00" }, { "name": "dflydev/doctrine-orm-service-provider", @@ -1327,7 +1326,7 @@ "pimple", "silex" ], - "time": "2015-09-07 12:16:54" + "time": "2015-09-07T12:16:54+00:00" }, { "name": "doctrine/annotations", @@ -1395,7 +1394,7 @@ "docblock", "parser" ], - "time": "2015-08-31 12:32:49" + "time": "2015-08-31T12:32:49+00:00" }, { "name": "doctrine/cache", @@ -1407,7 +1406,7 @@ }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/cache/zipball/eb152c5100571c7a45470ff2a35095ab3f3b900b", + "url": "https://api.github.com/repos/doctrine/cache/zipball/b6f544a20f4807e81f7044d31e679ccbb1866dc3", "reference": "b6f544a20f4807e81f7044d31e679ccbb1866dc3", "shasum": "" }, @@ -1465,7 +1464,7 @@ "cache", "caching" ], - "time": "2016-10-29 11:16:17" + "time": "2016-10-29T11:16:17+00:00" }, { "name": "doctrine/collections", @@ -1531,7 +1530,7 @@ "collections", "iterator" ], - "time": "2015-04-14 22:21:58" + "time": "2015-04-14T22:21:58+00:00" }, { "name": "doctrine/common", @@ -1604,7 +1603,7 @@ "persistence", "spl" ], - "time": "2016-11-30 16:50:46" + "time": "2016-11-30T16:50:46+00:00" }, { "name": "doctrine/dbal", @@ -1675,7 +1674,7 @@ "persistence", "queryobject" ], - "time": "2017-01-23 23:17:10" + "time": "2017-01-23T23:17:10+00:00" }, { "name": "doctrine/inflector", @@ -1742,7 +1741,7 @@ "singularize", "string" ], - "time": "2015-11-06 14:35:42" + "time": "2015-11-06T14:35:42+00:00" }, { "name": "doctrine/instantiator", @@ -1796,7 +1795,7 @@ "constructor", "instantiate" ], - "time": "2015-06-14 21:17:01" + "time": "2015-06-14T21:17:01+00:00" }, { "name": "doctrine/lexer", @@ -1850,7 +1849,7 @@ "lexer", "parser" ], - "time": "2014-09-09 13:34:57" + "time": "2014-09-09T13:34:57+00:00" }, { "name": "doctrine/migrations", @@ -1924,7 +1923,7 @@ "database", "migrations" ], - "time": "2016-12-25 22:54:00" + "time": "2016-12-25T22:54:00+00:00" }, { "name": "doctrine/orm", @@ -2000,7 +1999,7 @@ "database", "orm" ], - "time": "2016-12-18 15:42:34" + "time": "2016-12-18T15:42:34+00:00" }, { "name": "elasticsearch/elasticsearch", @@ -2054,7 +2053,7 @@ "elasticsearch", "search" ], - "time": "2016-11-30 17:15:05" + "time": "2016-11-30T17:15:05+00:00" }, { "name": "evenement/evenement", @@ -2094,7 +2093,7 @@ "keywords": [ "event-dispatcher" ], - "time": "2012-05-30 15:01:08" + "time": "2012-05-30T15:01:08+00:00" }, { "name": "facebook/graph-sdk", @@ -2152,7 +2151,7 @@ "facebook", "sdk" ], - "time": "2017-08-16 17:28:07" + "time": "2017-08-16T17:28:07+00:00" }, { "name": "firebase/php-jwt", @@ -2195,7 +2194,7 @@ ], "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", "homepage": "https://github.com/firebase/php-jwt", - "time": "2015-07-22 18:31:08" + "time": "2015-07-22T18:31:08+00:00" }, { "name": "gedmo/doctrine-extensions", @@ -2273,7 +2272,7 @@ "tree", "uploadable" ], - "time": "2015-02-24 21:41:37" + "time": "2015-02-24T21:41:37+00:00" }, { "name": "goodby/csv", @@ -2330,7 +2329,7 @@ "export", "import" ], - "time": "2015-06-29 10:28:19" + "time": "2015-06-29T10:28:19+00:00" }, { "name": "google/apiclient", @@ -2389,7 +2388,7 @@ "keywords": [ "google" ], - "time": "2017-11-03 01:19:53" + "time": "2017-11-03T01:19:53+00:00" }, { "name": "google/apiclient-services", @@ -2426,7 +2425,7 @@ "keywords": [ "google" ], - "time": "2017-11-25 00:23:12" + "time": "2017-11-25T00:23:12+00:00" }, { "name": "google/auth", @@ -2471,7 +2470,7 @@ "google", "oauth2" ], - "time": "2017-10-10 17:01:45" + "time": "2017-10-10T17:01:45+00:00" }, { "name": "google/recaptcha", @@ -2516,7 +2515,7 @@ "recaptcha", "spam" ], - "time": "2017-03-09 18:44:34" + "time": "2017-03-09T18:44:34+00:00" }, { "name": "guzzle/guzzle", @@ -2612,7 +2611,7 @@ "web service" ], "abandoned": "guzzlehttp/guzzle", - "time": "2015-03-18 18:23:50" + "time": "2015-03-18T18:23:50+00:00" }, { "name": "guzzlehttp/guzzle", @@ -2677,7 +2676,7 @@ "rest", "web service" ], - "time": "2017-06-22 18:50:49" + "time": "2017-06-22T18:50:49+00:00" }, { "name": "guzzlehttp/promises", @@ -2728,7 +2727,7 @@ "keywords": [ "promise" ], - "time": "2016-12-20 10:07:11" + "time": "2016-12-20T10:07:11+00:00" }, { "name": "guzzlehttp/psr7", @@ -2793,7 +2792,7 @@ "uri", "url" ], - "time": "2017-03-20 17:10:46" + "time": "2017-03-20T17:10:46+00:00" }, { "name": "guzzlehttp/ringphp", @@ -2844,7 +2843,7 @@ } ], "description": "Provides a simple API and specification that abstracts away the details of HTTP into a single PHP function.", - "time": "2015-05-20 03:37:09" + "time": "2015-05-20T03:37:09+00:00" }, { "name": "guzzlehttp/streams", @@ -2894,7 +2893,7 @@ "Guzzle", "stream" ], - "time": "2014-10-12 19:18:40" + "time": "2014-10-12T19:18:40+00:00" }, { "name": "hoa/compiler", @@ -2974,7 +2973,7 @@ "trace", "uniform" ], - "time": "2015-10-29 21:35:12" + "time": "2015-10-29T21:35:12+00:00" }, { "name": "hoa/console", @@ -3046,7 +3045,7 @@ "tput", "window" ], - "time": "2015-07-27 07:52:10" + "time": "2015-07-27T07:52:10+00:00" }, { "name": "hoa/core", @@ -3114,7 +3113,7 @@ "protocol" ], "abandoned": "hoa/consistency", - "time": "2015-11-09 06:51:06" + "time": "2015-11-09T06:51:06+00:00" }, { "name": "hoa/dispatcher", @@ -3174,7 +3173,7 @@ "kit", "library" ], - "time": "2015-11-09 06:52:08" + "time": "2015-11-09T06:52:08+00:00" }, { "name": "hoa/file", @@ -3234,7 +3233,7 @@ "link", "temporary" ], - "time": "2015-11-09 06:55:20" + "time": "2015-11-09T06:55:20+00:00" }, { "name": "hoa/iterator", @@ -3287,7 +3286,7 @@ "iterator", "library" ], - "time": "2015-10-29 21:37:16" + "time": "2015-10-29T21:37:16+00:00" }, { "name": "hoa/math", @@ -3349,7 +3348,7 @@ "sampler", "set" ], - "time": "2015-10-26 15:22:52" + "time": "2015-10-26T15:22:52+00:00" }, { "name": "hoa/regex", @@ -3403,7 +3402,7 @@ "library", "regex" ], - "time": "2015-08-13 06:48:47" + "time": "2015-08-13T06:48:47+00:00" }, { "name": "hoa/router", @@ -3455,7 +3454,7 @@ "library", "router" ], - "time": "2015-10-21 14:12:51" + "time": "2015-10-21T14:12:51+00:00" }, { "name": "hoa/stream", @@ -3513,7 +3512,7 @@ "stream", "wrapper" ], - "time": "2015-10-26 12:21:43" + "time": "2015-10-26T12:21:43+00:00" }, { "name": "hoa/ustring", @@ -3572,7 +3571,7 @@ "string", "unicode" ], - "time": "2015-11-09 06:44:33" + "time": "2015-11-09T06:44:33+00:00" }, { "name": "hoa/visitor", @@ -3627,7 +3626,7 @@ "visit", "visitor" ], - "time": "2015-08-17 06:30:58" + "time": "2015-08-17T06:30:58+00:00" }, { "name": "igorw/get-in", @@ -3672,7 +3671,7 @@ "assoc-array", "hash-map" ], - "time": "2014-12-15 23:03:51" + "time": "2014-12-15T23:03:51+00:00" }, { "name": "imagine/imagine", @@ -3731,7 +3730,7 @@ "support": { "source": "https://github.com/alchemy-fr/Imagine/tree/alchemy-0.6.2" }, - "time": "2015-01-13 18:12:26" + "time": "2015-01-13T18:12:26+00:00" }, { "name": "ircmaxell/password-compat", @@ -3773,7 +3772,7 @@ "hashing", "password" ], - "time": "2014-11-20 16:49:30" + "time": "2014-11-20T16:49:30+00:00" }, { "name": "ircmaxell/security-lib", @@ -3819,7 +3818,7 @@ ], "description": "A Base Security Library", "homepage": "https://github.com/ircmaxell/SecurityLib", - "time": "2015-03-20 14:31:23" + "time": "2015-03-20T14:31:23+00:00" }, { "name": "jms/metadata", @@ -3870,7 +3869,7 @@ "xml", "yaml" ], - "time": "2016-12-05 10:18:33" + "time": "2016-12-05T10:18:33+00:00" }, { "name": "jms/parser-lib", @@ -3905,7 +3904,7 @@ "Apache2" ], "description": "A library for easily creating recursive-descent parsers.", - "time": "2012-11-18 18:08:43" + "time": "2012-11-18T18:08:43+00:00" }, { "name": "jms/serializer", @@ -3975,7 +3974,7 @@ "serialization", "xml" ], - "time": "2014-03-18 08:39:00" + "time": "2014-03-18T08:39:00+00:00" }, { "name": "jms/translation-bundle", @@ -4051,7 +4050,7 @@ "support": { "source": "https://github.com/alchemy-fr/JMSTranslationBundle/tree/rebase-2015-10-20" }, - "time": "2015-11-04 15:09:44" + "time": "2015-11-04T15:09:44+00:00" }, { "name": "justinrainbow/json-schema", @@ -4117,7 +4116,7 @@ "json", "schema" ], - "time": "2016-05-10 20:38:51" + "time": "2016-05-10T20:38:51+00:00" }, { "name": "league/flysystem", @@ -4200,7 +4199,7 @@ "sftp", "storage" ], - "time": "2017-01-30 17:41:17" + "time": "2017-01-30T17:41:17+00:00" }, { "name": "league/flysystem-aws-s3-v2", @@ -4247,7 +4246,7 @@ } ], "description": "Flysystem adapter for AWS S3 SDK v2", - "time": "2015-10-15 15:55:48" + "time": "2015-10-15T15:55:48+00:00" }, { "name": "league/fractal", @@ -4308,20 +4307,20 @@ "league", "rest" ], - "time": "2016-12-02 14:55:48" + "time": "2016-12-02T14:55:48+00:00" }, { "name": "media-alchemyst/media-alchemyst", - "version": "0.5.2", + "version": "0.5.5", "source": { "type": "git", "url": "https://github.com/alchemy-fr/Media-Alchemyst.git", - "reference": "5d2fe6dd95215804202ecf0466fd9cfaeedd0140" + "reference": "3bd3204b69882f495adfb617383a077face92ed0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/alchemy-fr/Media-Alchemyst/zipball/5d2fe6dd95215804202ecf0466fd9cfaeedd0140", - "reference": "5d2fe6dd95215804202ecf0466fd9cfaeedd0140", + "url": "https://api.github.com/repos/alchemy-fr/Media-Alchemyst/zipball/3bd3204b69882f495adfb617383a077face92ed0", + "reference": "3bd3204b69882f495adfb617383a077face92ed0", "shasum": "" }, "require": { @@ -4333,7 +4332,7 @@ "php": ">=5.3.3", "php-ffmpeg/php-ffmpeg": ">=0.4.2,<0.6", "php-mp4box/php-mp4box": "~0.3.0", - "php-unoconv/php-unoconv": "~0.3.0", + "php-unoconv/php-unoconv": "~0.3.1", "pimple/pimple": "~1.0", "swftools/swftools": "~0.3.0", "symfony/console": "^2.1|^3.0", @@ -4382,7 +4381,7 @@ "video", "video processing" ], - "time": "2019-01-25 12:09:11" + "time": "2019-12-11T07:20:45+00:00" }, { "name": "monolog/monolog", @@ -4460,7 +4459,7 @@ "logging", "psr-3" ], - "time": "2016-11-26 00:15:39" + "time": "2016-11-26T00:15:39+00:00" }, { "name": "mrclay/minify", @@ -4500,7 +4499,7 @@ ], "description": "Minify is a PHP5 app that helps you follow several rules for client-side performance. It combines multiple CSS or Javascript files, removes unnecessary whitespace and comments, and serves them with gzip encoding and optimal client-side cache headers", "homepage": "http://code.google.com/p/minify/", - "time": "2013-07-23 19:58:28" + "time": "2013-07-23T19:58:28+00:00" }, { "name": "neutron/process-manager", @@ -4539,7 +4538,7 @@ "homepage": "http://www.lickmychip.com/" } ], - "time": "2014-02-13 20:27:33" + "time": "2014-02-13T20:27:33+00:00" }, { "name": "neutron/recaptcha", @@ -4583,7 +4582,7 @@ } ], "description": "ReCaptcha Client", - "time": "2013-02-14 13:42:00" + "time": "2013-02-14T13:42:00+00:00" }, { "name": "neutron/signal-handler", @@ -4626,7 +4625,7 @@ "keywords": [ "signal" ], - "time": "2014-01-15 17:24:13" + "time": "2014-01-15T17:24:13+00:00" }, { "name": "neutron/silex-filesystem-provider", @@ -4670,7 +4669,7 @@ "silex", "temporary-filesystem" ], - "time": "2012-11-08 21:07:08" + "time": "2012-11-08T21:07:08+00:00" }, { "name": "neutron/silex-imagine-provider", @@ -4717,7 +4716,7 @@ "imagine", "silex" ], - "time": "2013-05-03 18:48:51" + "time": "2013-05-03T18:48:51+00:00" }, { "name": "neutron/temporary-filesystem", @@ -4757,7 +4756,7 @@ } ], "description": "Symfony filesystem extension to handle temporary files", - "time": "2016-03-05 10:22:50" + "time": "2016-03-05T10:22:50+00:00" }, { "name": "nikic/php-parser", @@ -4802,7 +4801,7 @@ "parser", "php" ], - "time": "2015-09-19 14:15:08" + "time": "2015-09-19T14:15:08+00:00" }, { "name": "ocramius/proxy-manager", @@ -4865,7 +4864,7 @@ "proxy pattern", "service proxies" ], - "time": "2015-08-09 04:28:19" + "time": "2015-08-09T04:28:19+00:00" }, { "name": "pagerfanta/pagerfanta", @@ -4932,7 +4931,7 @@ "paginator", "paging" ], - "time": "2016-11-28 09:17:04" + "time": "2016-11-28T09:17:04+00:00" }, { "name": "paragonie/random-lib", @@ -4994,7 +4993,7 @@ "random-numbers", "random-strings" ], - "time": "2017-10-06 23:34:21" + "time": "2017-10-06T23:34:21+00:00" }, { "name": "paragonie/random_compat", @@ -5042,7 +5041,7 @@ "pseudorandom", "random" ], - "time": "2016-11-07 23:38:38" + "time": "2016-11-07T23:38:38+00:00" }, { "name": "paragonie/sodium_compat", @@ -5124,7 +5123,7 @@ "secret-key cryptography", "side-channel resistant" ], - "time": "2019-03-20 17:19:05" + "time": "2019-03-20T17:19:05+00:00" }, { "name": "php-ffmpeg/php-ffmpeg", @@ -5193,7 +5192,7 @@ "video", "video processing" ], - "time": "2014-08-26 08:46:56" + "time": "2014-08-26T08:46:56+00:00" }, { "name": "php-mp4box/php-mp4box", @@ -5244,20 +5243,20 @@ "gpac", "mp4box" ], - "time": "2013-06-25 10:13:06" + "time": "2013-06-25T10:13:06+00:00" }, { "name": "php-unoconv/php-unoconv", - "version": "0.3.0", + "version": "0.3.1", "source": { "type": "git", "url": "https://github.com/alchemy-fr/PHP-Unoconv.git", - "reference": "6d1e14a7467b5d637741396549529dc4d5f9f355" + "reference": "8fa666972f6c13fe9703dfe894cd311a61f89f33" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/alchemy-fr/PHP-Unoconv/zipball/6d1e14a7467b5d637741396549529dc4d5f9f355", - "reference": "6d1e14a7467b5d637741396549529dc4d5f9f355", + "url": "https://api.github.com/repos/alchemy-fr/PHP-Unoconv/zipball/8fa666972f6c13fe9703dfe894cd311a61f89f33", + "reference": "8fa666972f6c13fe9703dfe894cd311a61f89f33", "shasum": "" }, "require": { @@ -5294,7 +5293,7 @@ "keywords": [ "unoconv" ], - "time": "2013-06-25 10:09:59" + "time": "2019-09-16T09:54:30+00:00" }, { "name": "php-xpdf/php-xpdf", @@ -5346,7 +5345,7 @@ "pdf", "xpdf" ], - "time": "2016-07-04 07:30:16" + "time": "2016-07-04T07:30:16+00:00" }, { "name": "phpcollection/phpcollection", @@ -5394,7 +5393,7 @@ "sequence", "set" ], - "time": "2015-05-17 12:39:23" + "time": "2015-05-17T12:39:23+00:00" }, { "name": "phpexiftool/exiftool", @@ -5427,7 +5426,7 @@ "exiftool", "metadatas" ], - "time": "2016-01-25 11:10:14" + "time": "2016-01-25T11:10:14+00:00" }, { "name": "phpoption/phpoption", @@ -5477,7 +5476,7 @@ "php", "type" ], - "time": "2015-07-25 16:39:46" + "time": "2015-07-25T16:39:46+00:00" }, { "name": "phpseclib/phpseclib", @@ -5569,7 +5568,7 @@ "x.509", "x509" ], - "time": "2017-10-23 05:04:54" + "time": "2017-10-23T05:04:54+00:00" }, { "name": "pimple/pimple", @@ -5615,7 +5614,7 @@ "container", "dependency injection" ], - "time": "2013-11-22 08:30:29" + "time": "2013-11-22T08:30:29+00:00" }, { "name": "psr/cache", @@ -5661,7 +5660,7 @@ "psr", "psr-6" ], - "time": "2016-08-06 20:24:11" + "time": "2016-08-06T20:24:11+00:00" }, { "name": "psr/http-message", @@ -5711,7 +5710,7 @@ "request", "response" ], - "time": "2016-08-06 14:39:51" + "time": "2016-08-06T14:39:51+00:00" }, { "name": "psr/log", @@ -5758,7 +5757,7 @@ "psr", "psr-3" ], - "time": "2016-10-10 12:19:37" + "time": "2016-10-10T12:19:37+00:00" }, { "name": "ramsey/uuid", @@ -5840,7 +5839,7 @@ "identifier", "uuid" ], - "time": "2016-11-22 19:21:44" + "time": "2016-11-22T19:21:44+00:00" }, { "name": "react/promise", @@ -5883,7 +5882,7 @@ "promise", "promises" ], - "time": "2016-12-22 14:09:01" + "time": "2016-12-22T14:09:01+00:00" }, { "name": "roave/security-advisories", @@ -6008,7 +6007,7 @@ } ], "description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it", - "time": "2017-01-24 18:32:04" + "time": "2017-01-24T18:32:04+00:00" }, { "name": "seld/jsonlint", @@ -6054,7 +6053,7 @@ "parser", "validator" ], - "time": "2016-11-14 17:59:58" + "time": "2016-11-14T17:59:58+00:00" }, { "name": "silex/silex", @@ -6132,7 +6131,7 @@ "microframework" ], "abandoned": "symfony/flex", - "time": "2016-01-06 14:59:35" + "time": "2016-01-06T14:59:35+00:00" }, { "name": "silex/web-profiler", @@ -6178,7 +6177,7 @@ "description": "A WebProfiler for Silex", "homepage": "http://silex.sensiolabs.org/", "abandoned": true, - "time": "2016-01-10 11:39:13" + "time": "2016-01-10T11:39:13+00:00" }, { "name": "simple-bus/doctrine-orm-bridge", @@ -6232,7 +6231,7 @@ "doctrine", "event bus" ], - "time": "2015-04-29 12:27:27" + "time": "2015-04-29T12:27:27+00:00" }, { "name": "simple-bus/jms-serializer-bridge", @@ -6281,7 +6280,7 @@ "message", "serialization" ], - "time": "2015-07-29 07:48:42" + "time": "2015-07-29T07:48:42+00:00" }, { "name": "simple-bus/message-bus", @@ -6331,7 +6330,7 @@ "message", "message bus" ], - "time": "2016-02-12 08:35:53" + "time": "2016-02-12T08:35:53+00:00" }, { "name": "simple-bus/serialization", @@ -6379,7 +6378,7 @@ "messages", "serialization" ], - "time": "2015-05-08 13:34:17" + "time": "2015-05-08T13:34:17+00:00" }, { "name": "sorien/silex-dbal-profiler", @@ -6427,7 +6426,7 @@ "profiler", "silex" ], - "time": "2016-10-26 11:08:02" + "time": "2016-10-26T11:08:02+00:00" }, { "name": "sorien/silex-pimple-dumper", @@ -6469,7 +6468,7 @@ "plugin", "silex" ], - "time": "2015-11-11 07:16:28" + "time": "2015-11-11T07:16:28+00:00" }, { "name": "swftools/swftools", @@ -6523,7 +6522,7 @@ "flash", "swf" ], - "time": "2013-07-03 13:11:36" + "time": "2013-07-03T13:11:36+00:00" }, { "name": "swiftmailer/swiftmailer", @@ -6577,7 +6576,7 @@ "mail", "mailer" ], - "time": "2016-12-29 10:02:40" + "time": "2016-12-29T10:02:40+00:00" }, { "name": "symfony/polyfill-apcu", @@ -6630,7 +6629,7 @@ "portable", "shim" ], - "time": "2016-11-14 01:06:16" + "time": "2016-11-14T01:06:16+00:00" }, { "name": "symfony/polyfill-intl-icu", @@ -6688,7 +6687,7 @@ "portable", "shim" ], - "time": "2016-11-14 01:06:16" + "time": "2016-11-14T01:06:16+00:00" }, { "name": "symfony/polyfill-mbstring", @@ -6747,7 +6746,7 @@ "portable", "shim" ], - "time": "2016-11-14 01:06:16" + "time": "2016-11-14T01:06:16+00:00" }, { "name": "symfony/polyfill-php54", @@ -6805,7 +6804,7 @@ "portable", "shim" ], - "time": "2016-11-14 01:06:16" + "time": "2016-11-14T01:06:16+00:00" }, { "name": "symfony/polyfill-php55", @@ -6861,7 +6860,7 @@ "portable", "shim" ], - "time": "2016-11-14 01:06:16" + "time": "2016-11-14T01:06:16+00:00" }, { "name": "symfony/polyfill-php56", @@ -6917,7 +6916,7 @@ "portable", "shim" ], - "time": "2016-11-14 01:06:16" + "time": "2016-11-14T01:06:16+00:00" }, { "name": "symfony/polyfill-php70", @@ -6976,7 +6975,7 @@ "portable", "shim" ], - "time": "2016-11-14 01:06:16" + "time": "2016-11-14T01:06:16+00:00" }, { "name": "symfony/polyfill-util", @@ -7028,7 +7027,7 @@ "polyfill", "shim" ], - "time": "2016-11-14 01:06:16" + "time": "2016-11-14T01:06:16+00:00" }, { "name": "symfony/security-acl", @@ -7089,7 +7088,7 @@ ], "description": "Symfony Security Component - ACL (Access Control List)", "homepage": "https://symfony.com", - "time": "2015-12-28 09:39:46" + "time": "2015-12-28T09:39:46+00:00" }, { "name": "symfony/symfony", @@ -7224,7 +7223,7 @@ "keywords": [ "framework" ], - "time": "2017-01-12 20:27:46" + "time": "2017-01-12T20:27:46+00:00" }, { "name": "themattharris/tmhoauth", @@ -7266,7 +7265,7 @@ "oauth", "twitter" ], - "time": "2014-08-06 22:29:35" + "time": "2014-08-06T22:29:35+00:00" }, { "name": "twig/extensions", @@ -7318,7 +7317,7 @@ "i18n", "text" ], - "time": "2016-10-25 17:34:14" + "time": "2016-10-25T17:34:14+00:00" }, { "name": "twig/twig", @@ -7379,7 +7378,7 @@ "keywords": [ "templating" ], - "time": "2017-01-11 19:36:15" + "time": "2017-01-11T19:36:15+00:00" }, { "name": "vierbergenlars/php-semver", @@ -7427,7 +7426,7 @@ "semver", "versioning" ], - "time": "2013-09-20 10:41:27" + "time": "2013-09-20T10:41:27+00:00" }, { "name": "webmozart/assert", @@ -7477,7 +7476,7 @@ "check", "validate" ], - "time": "2016-11-23 20:04:58" + "time": "2016-11-23T20:04:58+00:00" }, { "name": "webmozart/json", @@ -7526,7 +7525,7 @@ } ], "description": "A robust JSON decoder/encoder with support for schema validation.", - "time": "2016-01-14 12:11:46" + "time": "2016-01-14T12:11:46+00:00" }, { "name": "webmozart/path-util", @@ -7572,7 +7571,7 @@ } ], "description": "A robust cross-platform utility for normalizing, comparing and modifying file paths.", - "time": "2015-12-17 08:42:14" + "time": "2015-12-17T08:42:14+00:00" }, { "name": "willdurand/negotiation", @@ -7624,7 +7623,7 @@ "header", "negotiation" ], - "time": "2016-10-14 09:17:47" + "time": "2016-10-14T09:17:47+00:00" }, { "name": "zend/gdata", @@ -7665,7 +7664,7 @@ "gdata", "zend" ], - "time": "2013-01-30 15:31:21" + "time": "2013-01-30T15:31:21+00:00" }, { "name": "zendframework/zend-code", @@ -7717,7 +7716,7 @@ "code", "zf2" ], - "time": "2016-04-20 17:26:42" + "time": "2016-04-20T17:26:42+00:00" }, { "name": "zendframework/zend-eventmanager", @@ -7771,7 +7770,7 @@ "events", "zf2" ], - "time": "2016-02-18 20:53:00" + "time": "2016-02-18T20:53:00+00:00" } ], "packages-dev": [ @@ -7819,7 +7818,7 @@ ], "description": "Virtual file system to mock the real file system in unit tests.", "homepage": "http://vfs.bovigo.org/", - "time": "2016-07-18 14:02:57" + "time": "2016-07-18T14:02:57+00:00" }, { "name": "phpdocumentor/reflection-common", @@ -7873,7 +7872,7 @@ "reflection", "static analysis" ], - "time": "2015-12-27 11:43:31" + "time": "2015-12-27T11:43:31+00:00" }, { "name": "phpdocumentor/reflection-docblock", @@ -7918,7 +7917,7 @@ } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2016-09-30 07:12:33" + "time": "2016-09-30T07:12:33+00:00" }, { "name": "phpdocumentor/type-resolver", @@ -7965,7 +7964,7 @@ "email": "me@mikevanriel.com" } ], - "time": "2016-11-25 06:54:22" + "time": "2016-11-25T06:54:22+00:00" }, { "name": "phpspec/prophecy", @@ -8028,7 +8027,7 @@ "spy", "stub" ], - "time": "2016-11-21 14:58:47" + "time": "2016-11-21T14:58:47+00:00" }, { "name": "phpunit/php-code-coverage", @@ -8090,7 +8089,7 @@ "testing", "xunit" ], - "time": "2015-10-06 15:47:00" + "time": "2015-10-06T15:47:00+00:00" }, { "name": "phpunit/php-file-iterator", @@ -8137,7 +8136,7 @@ "filesystem", "iterator" ], - "time": "2016-10-03 07:40:28" + "time": "2016-10-03T07:40:28+00:00" }, { "name": "phpunit/php-text-template", @@ -8178,7 +8177,7 @@ "keywords": [ "template" ], - "time": "2015-06-21 13:50:34" + "time": "2015-06-21T13:50:34+00:00" }, { "name": "phpunit/php-timer", @@ -8222,7 +8221,7 @@ "keywords": [ "timer" ], - "time": "2016-05-12 18:03:57" + "time": "2016-05-12T18:03:57+00:00" }, { "name": "phpunit/php-token-stream", @@ -8271,7 +8270,7 @@ "keywords": [ "tokenizer" ], - "time": "2016-11-15 14:06:22" + "time": "2016-11-15T14:06:22+00:00" }, { "name": "phpunit/phpunit", @@ -8343,7 +8342,7 @@ "testing", "xunit" ], - "time": "2017-01-26 16:15:36" + "time": "2017-01-26T16:15:36+00:00" }, { "name": "phpunit/phpunit-mock-objects", @@ -8400,7 +8399,7 @@ "xunit" ], "abandoned": true, - "time": "2015-10-02 06:51:40" + "time": "2015-10-02T06:51:40+00:00" }, { "name": "sebastian/comparator", @@ -8464,7 +8463,7 @@ "compare", "equality" ], - "time": "2017-01-29 09:50:25" + "time": "2017-01-29T09:50:25+00:00" }, { "name": "sebastian/diff", @@ -8516,7 +8515,7 @@ "keywords": [ "diff" ], - "time": "2015-12-08 07:14:41" + "time": "2015-12-08T07:14:41+00:00" }, { "name": "sebastian/environment", @@ -8566,7 +8565,7 @@ "environment", "hhvm" ], - "time": "2016-08-18 05:49:44" + "time": "2016-08-18T05:49:44+00:00" }, { "name": "sebastian/exporter", @@ -8633,7 +8632,7 @@ "export", "exporter" ], - "time": "2016-06-17 09:04:28" + "time": "2016-06-17T09:04:28+00:00" }, { "name": "sebastian/global-state", @@ -8684,7 +8683,7 @@ "keywords": [ "global state" ], - "time": "2015-10-12 03:26:01" + "time": "2015-10-12T03:26:01+00:00" }, { "name": "sebastian/recursion-context", @@ -8737,7 +8736,7 @@ ], "description": "Provides functionality to recursively process PHP variables", "homepage": "http://www.github.com/sebastianbergmann/recursion-context", - "time": "2015-11-11 19:50:13" + "time": "2015-11-11T19:50:13+00:00" }, { "name": "sebastian/version", @@ -8772,7 +8771,7 @@ ], "description": "Library that helps with managing the version number of Git-hosted PHP projects", "homepage": "https://github.com/sebastianbergmann/version", - "time": "2015-06-21 13:59:46" + "time": "2015-06-21T13:59:46+00:00" } ], "aliases": [ diff --git a/lib/Alchemy/Phrasea/Application/ApiApplicationLoader.php b/lib/Alchemy/Phrasea/Application/ApiApplicationLoader.php index 490554c95e..ca47f16baa 100644 --- a/lib/Alchemy/Phrasea/Application/ApiApplicationLoader.php +++ b/lib/Alchemy/Phrasea/Application/ApiApplicationLoader.php @@ -15,6 +15,7 @@ use Alchemy\Phrasea\Controller\Api\Result; use Alchemy\Phrasea\ControllerProvider\Api\OAuth2; use Alchemy\Phrasea\ControllerProvider\Api\V1; use Alchemy\Phrasea\ControllerProvider\Api\V2; +use Alchemy\Phrasea\ControllerProvider\Api\V3; use Alchemy\Phrasea\ControllerProvider\Datafiles; use Alchemy\Phrasea\ControllerProvider\MediaAccessor; use Alchemy\Phrasea\ControllerProvider\Minifier; @@ -36,6 +37,7 @@ class ApiApplicationLoader extends BaseApplicationLoader $app->register(new OAuth2()); $app->register(new V1()); $app->register(new V2()); + $app->register(new V3()); $app->register(new ApiReportControllerProvider()); $app->register(new JsonSchemaServiceProvider()); } @@ -119,6 +121,16 @@ class ApiApplicationLoader extends BaseApplicationLoader 'access_token' => '/api/oauthv2/token' ], ], + '3' => [ + 'number' => V3::VERSION, + 'uri' => '/api/v3/', + 'authenticationProtocol' => 'OAuth2', + 'authenticationVersion' => 'draft#v9', + 'authenticationEndPoints' => [ + 'authorization_token' => '/api/oauthv2/authorize', + 'access_token' => '/api/oauthv2/token' + ] + ], ] ])->createResponse(); }); @@ -135,6 +147,7 @@ class ApiApplicationLoader extends BaseApplicationLoader $app->mount('/datafiles/', new Datafiles()); $app->mount('/api/v1', new V1()); $app->mount('/api/v2', new V2()); + $app->mount('/api/v3', new V3()); $app->mount('/api/report', new ApiReportControllerProvider()); $app->mount('/permalink/', new Permalink()); $app->mount($app['controller.media_accessor.route_prefix'], new MediaAccessor()); diff --git a/lib/Alchemy/Phrasea/Border/Checker/AbstractChecker.php b/lib/Alchemy/Phrasea/Border/Checker/AbstractChecker.php index 8b4de0fb58..de6f4c25d6 100644 --- a/lib/Alchemy/Phrasea/Border/Checker/AbstractChecker.php +++ b/lib/Alchemy/Phrasea/Border/Checker/AbstractChecker.php @@ -34,6 +34,11 @@ abstract class AbstractChecker implements CheckerInterface */ protected $collections = []; + /** + * @var \collection[] + */ + protected $compareIgnoreCollections = []; + public function __construct(Application $app) { $this->app = $app; @@ -44,7 +49,7 @@ abstract class AbstractChecker implements CheckerInterface * Warning, you can not restrict on both databoxes and collections * * @param \databox[] $databoxes A databox or an array of databoxes - * @return bool + * @return \databox[] * * @throws \LogicException If already restricted to collections * @throws \InvalidArgumentException In case invalid databoxes are provided @@ -72,7 +77,7 @@ abstract class AbstractChecker implements CheckerInterface * Warning, you can not restrict on both databoxes and collections * * @param \collection[] $collections - * @return bool + * @return \collection[] * * @throws \LogicException If already restricted to databoxes * @throws \InvalidArgumentException In case invalid collections are provided @@ -95,6 +100,11 @@ abstract class AbstractChecker implements CheckerInterface return $this->collections; } + public function setCompareIgnoreCollections($collections) + { + $this->compareIgnoreCollections = $collections; + } + /** * Returns true if the checker should be executed against the current file * diff --git a/lib/Alchemy/Phrasea/Border/Checker/Filename.php b/lib/Alchemy/Phrasea/Border/Checker/Filename.php index ec4f0b0be4..ea1c25a7a6 100644 --- a/lib/Alchemy/Phrasea/Border/Checker/Filename.php +++ b/lib/Alchemy/Phrasea/Border/Checker/Filename.php @@ -45,8 +45,18 @@ class Filename extends AbstractChecker */ public function check(EntityManager $em, File $file) { - $boolean = empty(\record_adapter::get_records_by_originalname( - $file->getCollection()->get_databox(), $file->getOriginalName(), $this->sensitive, 0, 1 + $excludedCollIds = []; + if (!empty($this->compareIgnoreCollections)) { + foreach ($this->compareIgnoreCollections as $collection) { + // use only collection in the same databox and retrieve the coll_id + if ($collection->get_sbas_id() === $file->getCollection()->get_sbas_id()) { + $excludedCollIds[] = $collection->get_coll_id(); + } + } + } + + $boolean = empty(\record_adapter::getRecordsByOriginalnameWithExcludedCollIds( + $file->getCollection()->get_databox(), $file->getOriginalName(), $this->sensitive, 0, 1, $excludedCollIds )); return new Response($boolean, $this); diff --git a/lib/Alchemy/Phrasea/Border/Checker/Sha256.php b/lib/Alchemy/Phrasea/Border/Checker/Sha256.php index d17b28e5b9..5116e35dfd 100644 --- a/lib/Alchemy/Phrasea/Border/Checker/Sha256.php +++ b/lib/Alchemy/Phrasea/Border/Checker/Sha256.php @@ -34,7 +34,17 @@ class Sha256 extends AbstractChecker */ public function check(EntityManager $em, File $file) { - $boolean = empty($file->getCollection()->get_databox()->getRecordRepository()->findBySha256($file->getSha256())); + $excludedCollIds = []; + if (!empty($this->compareIgnoreCollections)) { + foreach ($this->compareIgnoreCollections as $collection) { + // use only collection in the same databox and retrieve the coll_id + if ($collection->get_sbas_id() === $file->getCollection()->get_sbas_id()) { + $excludedCollIds[] = $collection->get_coll_id(); + } + } + } + + $boolean = empty($file->getCollection()->get_databox()->getRecordRepository()->findBySha256WithExcludedCollIds($file->getSha256(), $excludedCollIds)); return new Response($boolean, $this); } diff --git a/lib/Alchemy/Phrasea/Border/Checker/UUID.php b/lib/Alchemy/Phrasea/Border/Checker/UUID.php index c3857fbe76..cdacf973a5 100644 --- a/lib/Alchemy/Phrasea/Border/Checker/UUID.php +++ b/lib/Alchemy/Phrasea/Border/Checker/UUID.php @@ -33,7 +33,17 @@ class UUID extends AbstractChecker */ public function check(EntityManager $em, File $file) { - $boolean = empty($file->getCollection()->get_databox()->getRecordRepository()->findByUuid($file->getUUID())); + $excludedCollIds = []; + if (!empty($this->compareIgnoreCollections)) { + foreach ($this->compareIgnoreCollections as $collection) { + // use only collection in the same databox and retrieve the coll_id + if ($collection->get_sbas_id() === $file->getCollection()->get_sbas_id()) { + $excludedCollIds[] = $collection->get_coll_id(); + } + } + } + + $boolean = empty($file->getCollection()->get_databox()->getRecordRepository()->findByUuidWithExcludedCollIds($file->getUUID(), $excludedCollIds)); return new Response($boolean, $this); } diff --git a/lib/Alchemy/Phrasea/Controller/Admin/SubdefsController.php b/lib/Alchemy/Phrasea/Controller/Admin/SubdefsController.php index e30aa03946..106a60b1d8 100644 --- a/lib/Alchemy/Phrasea/Controller/Admin/SubdefsController.php +++ b/lib/Alchemy/Phrasea/Controller/Admin/SubdefsController.php @@ -354,7 +354,7 @@ class SubdefsController extends Controller Subdef::TYPE_VIDEO => [ "definitions" => [ "video codec H264" => null, - "144P H264 128 kbps ACC 128kbps" => [ + "144P H264 128 kbps MP3 128kbps" => [ Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_BITRATE => "128", @@ -362,10 +362,10 @@ class SubdefsController extends Controller Video::OPTION_SIZE => "256", Video::OPTION_FRAMERATE => "25", Video::OPTION_VCODEC => "libx264", - Video::OPTION_ACODEC => "libfaac", + Video::OPTION_ACODEC => "libmp3lame", Subdef::OPTION_DEVICE => ["all"] ], - "240P H264 256 kbps ACC 128kbps" => [ + "240P H264 256 kbps MP3 128kbps" => [ Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_BITRATE => "256", @@ -373,10 +373,10 @@ class SubdefsController extends Controller Video::OPTION_SIZE => "426", Video::OPTION_FRAMERATE => "25", Video::OPTION_VCODEC => "libx264", - Video::OPTION_ACODEC => "libfaac", + Video::OPTION_ACODEC => "libmp3lame", Subdef::OPTION_DEVICE => ["all"] ], - "360P H264 576 kbps ACC 128kbps" => [ + "360P H264 576 kbps MP3 128kbps" => [ Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_BITRATE => "576", @@ -384,10 +384,10 @@ class SubdefsController extends Controller Video::OPTION_SIZE => "480", Video::OPTION_FRAMERATE => "25", Video::OPTION_VCODEC => "libtheora", - Video::OPTION_ACODEC => "libfaac", + Video::OPTION_ACODEC => "libmp3lame", Subdef::OPTION_DEVICE => ["all"] ], - "480P H264 750 kbps ACC 128kbps" => [ + "480P H264 750 kbps MP3 128kbps" => [ Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_BITRATE => "750", @@ -395,10 +395,10 @@ class SubdefsController extends Controller Video::OPTION_SIZE => "854", Video::OPTION_FRAMERATE => "25", Video::OPTION_VCODEC => "libx264", - Video::OPTION_ACODEC => "libfaac", + Video::OPTION_ACODEC => "libmp3lame", Subdef::OPTION_DEVICE => ["all"] ], - "720P H264 1492 kbps ACC 128kbps" => [ + "720P H264 1492 kbps MP3 128kbps" => [ Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_BITRATE => "1492", @@ -406,10 +406,10 @@ class SubdefsController extends Controller Video::OPTION_SIZE => "1280", Video::OPTION_FRAMERATE => "25", Video::OPTION_VCODEC => "libx264", - Video::OPTION_ACODEC => "libfaac", + Video::OPTION_ACODEC => "libmp3lame", Subdef::OPTION_DEVICE => ["all"] ], - "1080P H264 2420 kbps ACC 128kbps" => [ + "1080P H264 2420 kbps MP3 128kbps" => [ Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_BITRATE => "2420", @@ -417,11 +417,77 @@ class SubdefsController extends Controller Video::OPTION_SIZE => "1920", Video::OPTION_FRAMERATE => "25", Video::OPTION_VCODEC => "libx264", - Video::OPTION_ACODEC => "libfaac", + Video::OPTION_ACODEC => "libmp3lame", + Subdef::OPTION_DEVICE => ["all"] + ], + "144P H264 128 kbps AAC 128kbps" => [ + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "128", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "256", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libx264", + Video::OPTION_ACODEC => "libfdk_aac", + Subdef::OPTION_DEVICE => ["all"] + ], + "240P H264 256 kbps AAC 128kbps" => [ + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "256", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "426", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libx264", + Video::OPTION_ACODEC => "libfdk_aac", + Subdef::OPTION_DEVICE => ["all"] + ], + "360P H264 576 kbps AAC 128kbps" => [ + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "576", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "480", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libtheora", + Video::OPTION_ACODEC => "libfdk_aac", + Subdef::OPTION_DEVICE => ["all"] + ], + "480P H264 750 kbps AAC 128kbps" => [ + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "750", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "854", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libx264", + Video::OPTION_ACODEC => "libfdk_aac", + Subdef::OPTION_DEVICE => ["all"] + ], + "720P H264 1492 kbps AAC 128kbps" => [ + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "1492", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "1280", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libx264", + Video::OPTION_ACODEC => "libfdk_aac", + Subdef::OPTION_DEVICE => ["all"] + ], + "1080P H264 2420 kbps AAC 128kbps" => [ + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "2420", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "1920", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libx264", + Video::OPTION_ACODEC => "libfdk_aac", Subdef::OPTION_DEVICE => ["all"] ], "video codec libvpx" => null, - "144P webm 128 kbps ACC 128kbps" => [ + "144P webm 128 kbps MP3 128kbps" => [ Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_BITRATE => "128", @@ -429,10 +495,10 @@ class SubdefsController extends Controller Video::OPTION_SIZE => "256", Video::OPTION_FRAMERATE => "25", Video::OPTION_VCODEC => "libvpx", - Video::OPTION_ACODEC => "libfaac", + Video::OPTION_ACODEC => "libmp3lame", Subdef::OPTION_DEVICE => ["all"] ], - "240P webm 256 kbps ACC 128kbps" => [ + "240P webm 256 kbps MP3 128kbps" => [ Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_BITRATE => "256", @@ -440,10 +506,10 @@ class SubdefsController extends Controller Video::OPTION_SIZE => "426", Video::OPTION_FRAMERATE => "25", Video::OPTION_VCODEC => "libvpx", - Video::OPTION_ACODEC => "libfaac", + Video::OPTION_ACODEC => "libmp3lame", Subdef::OPTION_DEVICE => ["all"] ], - "360P webm 576 kbps ACC 128kbps" => [ + "360P webm 576 kbps MP3 128kbps" => [ Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_BITRATE => "576", @@ -451,10 +517,10 @@ class SubdefsController extends Controller Video::OPTION_SIZE => "480", Video::OPTION_FRAMERATE => "25", Video::OPTION_VCODEC => "libvpx", - Video::OPTION_ACODEC => "libfaac", + Video::OPTION_ACODEC => "libmp3lame", Subdef::OPTION_DEVICE => ["all"] ], - "480P webm 750 kbps ACC 128kbps" => [ + "480P webm 750 kbps MP3 128kbps" => [ Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_BITRATE => "750", @@ -462,10 +528,10 @@ class SubdefsController extends Controller Video::OPTION_SIZE => "854", Video::OPTION_FRAMERATE => "25", Video::OPTION_VCODEC => "libvpx", - Video::OPTION_ACODEC => "libfaac", + Video::OPTION_ACODEC => "libmp3lame", Subdef::OPTION_DEVICE => ["all"] ], - "720P webm 1492 kbps ACC 128kbps" => [ + "720P webm 1492 kbps MP3 128kbps" => [ Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_BITRATE => "1492", @@ -473,10 +539,10 @@ class SubdefsController extends Controller Video::OPTION_SIZE => "1280", Video::OPTION_FRAMERATE => "25", Video::OPTION_VCODEC => "libvpx", - Video::OPTION_ACODEC => "libfaac", + Video::OPTION_ACODEC => "libmp3lame", Subdef::OPTION_DEVICE => ["all"] ], - "1080P webm 2420 kbps ACC 128kbps" => [ + "1080P webm 2420 kbps MP3 128kbps" => [ Video::OPTION_AUDIOBITRATE => "128", Video::OPTION_AUDIOSAMPLERATE => "44100", Video::OPTION_BITRATE => "2420", @@ -484,7 +550,73 @@ class SubdefsController extends Controller Video::OPTION_SIZE => "1920", Video::OPTION_FRAMERATE => "25", Video::OPTION_VCODEC => "libvpx", - Video::OPTION_ACODEC => "libfaac", + Video::OPTION_ACODEC => "libmp3lame", + Subdef::OPTION_DEVICE => ["all"] + ], + "144P webm 128 kbps AAC 128kbps" => [ + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "128", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "256", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libvpx", + Video::OPTION_ACODEC => "libfdk_aac", + Subdef::OPTION_DEVICE => ["all"] + ], + "240P webm 256 kbps AAC 128kbps" => [ + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "256", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "426", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libvpx", + Video::OPTION_ACODEC => "libfdk_aac", + Subdef::OPTION_DEVICE => ["all"] + ], + "360P webm 576 kbps AAC 128kbps" => [ + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "576", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "480", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libvpx", + Video::OPTION_ACODEC => "libfdk_aac", + Subdef::OPTION_DEVICE => ["all"] + ], + "480P webm 750 kbps AAC 128kbps" => [ + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "750", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "854", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libvpx", + Video::OPTION_ACODEC => "libfdk_aac", + Subdef::OPTION_DEVICE => ["all"] + ], + "720P webm 1492 kbps AAC 128kbps" => [ + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "1492", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "1280", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libvpx", + Video::OPTION_ACODEC => "libfdk_aac", + Subdef::OPTION_DEVICE => ["all"] + ], + "1080P webm 2420 kbps AAC 128kbps" => [ + Video::OPTION_AUDIOBITRATE => "128", + Video::OPTION_AUDIOSAMPLERATE => "44100", + Video::OPTION_BITRATE => "2420", + Video::OPTION_GOPSIZE => "25", + Video::OPTION_SIZE => "1920", + Video::OPTION_FRAMERATE => "25", + Video::OPTION_VCODEC => "libvpx", + Video::OPTION_ACODEC => "libfdk_aac", Subdef::OPTION_DEVICE => ["all"] ], ], diff --git a/lib/Alchemy/Phrasea/Controller/Api/Result.php b/lib/Alchemy/Phrasea/Controller/Api/Result.php index 15624e1f6e..c7c45b4d0f 100644 --- a/lib/Alchemy/Phrasea/Controller/Api/Result.php +++ b/lib/Alchemy/Phrasea/Controller/Api/Result.php @@ -12,6 +12,7 @@ namespace Alchemy\Phrasea\Controller\Api; use Alchemy\Phrasea\ControllerProvider\Api\V1; +use Alchemy\Phrasea\ControllerProvider\Api\V3; use Symfony\Component\HttpFoundation\JsonResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -268,11 +269,13 @@ class Result public function getVersion() { if (null === $this->version) { - if($this->request->attributes->get('api_version')){ + if ($this->request->attributes->get('api_version')) { $this->version = $this->request->attributes->get('api_version'); - }elseif(mb_strpos($this->request->getPathInfo(), '/api/v1') !== FALSE){ + } elseif (mb_strpos($this->request->getPathInfo(), '/api/v1') !== FALSE) { $this->version = V1::VERSION; - }else{ + } elseif (mb_strpos($this->request->getPathInfo(), '/api/v3') !== FALSE) { + $this->version = V3::VERSION; + } else { $this->version = self::$defaultVersion; } } diff --git a/lib/Alchemy/Phrasea/Controller/Api/V3Controller.php b/lib/Alchemy/Phrasea/Controller/Api/V3Controller.php new file mode 100644 index 0000000000..4dcab291fe --- /dev/null +++ b/lib/Alchemy/Phrasea/Controller/Api/V3Controller.php @@ -0,0 +1,807 @@ +findDataboxById($databox_id)->get_record($record_id); + + return Result::create($request, ['story' => $this->listStory($request, $story)])->createResponse(); + } catch (NotFoundHttpException $e) { + return Result::createError($request, 404, $this->app->trans('Story Not Found'))->createResponse(); + } catch (\Exception $e) { + return $this->app['controller.api.v1']->getBadRequestAction($request, $this->app->trans('An error occurred')); + } + } + + /** + * Search for results + * + * @param Request $request + * + * @return Response + */ + public function searchAction(Request $request) + { + $subdefTransformer = new SubdefTransformer($this->app['acl'], $this->getAuthenticatedUser(), new PermalinkTransformer()); + $technicalDataTransformer = new TechnicalDataTransformer(); + $recordTransformer = new RecordTransformer($subdefTransformer, $technicalDataTransformer); + $storyTransformer = new StoryTransformer($subdefTransformer, $recordTransformer); + $compositeTransformer = new V1SearchCompositeResultTransformer($recordTransformer, $storyTransformer); + $searchTransformer = new V1SearchResultTransformer($compositeTransformer); + + $transformerResolver = new SearchResultTransformerResolver([ + '' => $searchTransformer, + 'results' => $compositeTransformer, + 'results.stories' => $storyTransformer, + 'results.stories.thumbnail' => $subdefTransformer, + 'results.stories.metadatas' => new CallbackTransformer(), + 'results.stories.caption' => new CallbackTransformer(), + 'results.stories.records' => $recordTransformer, + 'results.stories.records.thumbnail' => $subdefTransformer, + 'results.stories.records.technical_informations' => $technicalDataTransformer, + 'results.stories.records.subdefs' => $subdefTransformer, + 'results.stories.records.metadata' => new CallbackTransformer(), + 'results.stories.records.status' => new CallbackTransformer(), + 'results.stories.records.caption' => new CallbackTransformer(), + 'results.records' => $recordTransformer, + 'results.records.thumbnail' => $subdefTransformer, + 'results.records.technical_informations' => $technicalDataTransformer, + 'results.records.subdefs' => $subdefTransformer, + 'results.records.metadata' => new CallbackTransformer(), + 'results.records.status' => new CallbackTransformer(), + 'results.records.caption' => new CallbackTransformer(), + ]); + + $includeResolver = new IncludeResolver($transformerResolver); + + $fractal = new \League\Fractal\Manager(); + $fractal->setSerializer(new TraceableArraySerializer($this->app['dispatcher'])); + $fractal->parseIncludes($this->resolveSearchIncludes($request)); + + $result = $this->doSearch($request); + + $story_max_records = null; + // if search on story + if ($request->get('search_type') == 1) { + $story_max_records = (int)$request->get('story_max_records') ?: 10; + } + + $searchView = $this->buildSearchView( + $result, + $includeResolver->resolve($fractal), + $this->resolveSubdefUrlTTL($request), + $story_max_records + ); + + $ret = $fractal->createData(new Item($searchView, $searchTransformer))->toArray(); + + return Result::create($request, $ret)->createResponse(); + } + + /** + * Retrieve detailed information about one story + * + * @param Request $request + * @param \record_adapter $story + * @return array + * @throws \Exception + */ + private function listStory(Request $request, \record_adapter $story) + { + if (!$story->isStory()) { + return Result::createError($request, 404, 'Story not found')->createResponse(); + } + + $per_page = (int)$request->get('per_page')?:10; + $page = (int)$request->get('page')?:1; + $offset = ($per_page * ($page - 1)) + 1; + + $caption = $story->get_caption(); + + $format = function (\caption_record $caption, $dcField) { + + $field = $caption->get_dc_field($dcField); + + if (!$field) { + return null; + } + + return $field->get_serialized_values(); + }; + + return [ + '@entity@' => V1Controller::OBJECT_TYPE_STORY, + 'databox_id' => $story->getDataboxId(), + 'story_id' => $story->getRecordId(), + 'updated_on' => $story->getUpdated()->format(DATE_ATOM), + 'created_on' => $story->getCreated()->format(DATE_ATOM), + 'collection_id' => $story->getCollectionId(), + 'base_id' => $story->getBaseId(), + 'thumbnail' => $this->listEmbeddableMedia($request, $story, $story->get_thumbnail()), + 'uuid' => $story->getUuid(), + 'metadatas' => [ + '@entity@' => V1Controller::OBJECT_TYPE_STORY_METADATA_BAG, + 'dc:contributor' => $format($caption, \databox_Field_DCESAbstract::Contributor), + 'dc:coverage' => $format($caption, \databox_Field_DCESAbstract::Coverage), + 'dc:creator' => $format($caption, \databox_Field_DCESAbstract::Creator), + 'dc:date' => $format($caption, \databox_Field_DCESAbstract::Date), + 'dc:description' => $format($caption, \databox_Field_DCESAbstract::Description), + 'dc:format' => $format($caption, \databox_Field_DCESAbstract::Format), + 'dc:identifier' => $format($caption, \databox_Field_DCESAbstract::Identifier), + 'dc:language' => $format($caption, \databox_Field_DCESAbstract::Language), + 'dc:publisher' => $format($caption, \databox_Field_DCESAbstract::Publisher), + 'dc:relation' => $format($caption, \databox_Field_DCESAbstract::Relation), + 'dc:rights' => $format($caption, \databox_Field_DCESAbstract::Rights), + 'dc:source' => $format($caption, \databox_Field_DCESAbstract::Source), + 'dc:subject' => $format($caption, \databox_Field_DCESAbstract::Subject), + 'dc:title' => $format($caption, \databox_Field_DCESAbstract::Title), + 'dc:type' => $format($caption, \databox_Field_DCESAbstract::Type), + ], + 'records' => $this->listRecords($request, array_values($story->getChildren($offset, $per_page)->get_elements())), + ]; + } + + private function listEmbeddableMedia(Request $request, \record_adapter $record, \media_subdef $media) + { + if (!$media->is_physically_present()) { + return null; + } + + if ($this->getAuthenticator()->isAuthenticated()) { + $acl = $this->getAclForUser(); + if ($media->get_name() !== 'document' + && false === $acl->has_access_to_subdef($record, $media->get_name()) + ) { + return null; + } + if ($media->get_name() === 'document' + && !$acl->has_right_on_base($record->getBaseId(), \ACL::CANDWNLDHD) + && !$acl->has_hd_grant($record) + ) { + return null; + } + } + + if ($media->get_permalink() instanceof \media_Permalink_Adapter) { + $permalink = $this->listPermalink($media->get_permalink()); + } else { + $permalink = null; + } + + $urlTTL = (int) $request->get( + 'subdef_url_ttl', + $this->getConf()->get(['registry', 'general', 'default-subdef-url-ttl']) + ); + if ($urlTTL < 0) { + $urlTTL = -1; + } + $issuer = $this->getAuthenticatedUser(); + + return [ + 'name' => $media->get_name(), + 'permalink' => $permalink, + 'height' => $media->get_height(), + 'width' => $media->get_width(), + 'filesize' => $media->get_size(), + 'devices' => $media->getDevices(), + 'player_type' => $media->get_type(), + 'mime_type' => $media->get_mime(), + 'substituted' => $media->is_substituted(), + 'created_on' => $media->get_creation_date()->format(DATE_ATOM), + 'updated_on' => $media->get_modification_date()->format(DATE_ATOM), + 'url' => $this->app['media_accessor.subdef_url_generator']->generate($issuer, $media, $urlTTL), + 'url_ttl' => $urlTTL, + ]; + } + + private function listPermalink(\media_Permalink_Adapter $permalink) + { + $downloadUrl = $permalink->get_url(); + $downloadUrl->getQuery()->set('download', '1'); + + return [ + 'created_on' => $permalink->get_created_on()->format(DATE_ATOM), + 'id' => $permalink->get_id(), + 'is_activated' => $permalink->get_is_activated(), + /** @Ignore */ + 'label' => $permalink->get_label(), + 'updated_on' => $permalink->get_last_modified()->format(DATE_ATOM), + 'page_url' => $permalink->get_page(), + 'download_url' => (string)$downloadUrl, + 'url' => (string)$permalink->get_url(), + ]; + } + + /** + * @param Request $request + * @param RecordReferenceInterface[]|RecordReferenceCollection $records + * @return array + */ + private function listRecords(Request $request, $records) + { + if (!$records instanceof RecordReferenceCollection) { + $records = new RecordReferenceCollection($records); + } + + $technicalData = $this->app['service.technical_data']->fetchRecordsTechnicalData($records); + + $data = []; + + foreach ($records->toRecords($this->getApplicationBox()) as $index => $record) { + $record->setTechnicalDataSet($technicalData[$index]); + + $data[$index] = $this->listRecord($request, $record); + } + + return $data; + } + + /** + * Retrieve detailed information about one record + * + * @param Request $request + * @param \record_adapter $record + * @return array + */ + private function listRecord(Request $request, \record_adapter $record) + { + $technicalInformation = []; + foreach ($record->get_technical_infos()->getValues() as $name => $value) { + $technicalInformation[] = ['name' => $name, 'value' => $value]; + } + + $data = [ + 'databox_id' => $record->getDataboxId(), + 'record_id' => $record->getRecordId(), + 'mime_type' => $record->getMimeType(), + 'title' => $record->get_title(), + 'original_name' => $record->get_original_name(), + 'updated_on' => $record->getUpdated()->format(DATE_ATOM), + 'created_on' => $record->getCreated()->format(DATE_ATOM), + 'collection_id' => $record->getCollectionId(), + 'base_id' => $record->getBaseId(), + 'sha256' => $record->getSha256(), + 'thumbnail' => $this->listEmbeddableMedia($request, $record, $record->get_thumbnail()), + 'technical_informations' => $technicalInformation, + 'phrasea_type' => $record->getType(), + 'uuid' => $record->getUuid(), + ]; + + if ($request->attributes->get('_extended', false)) { + $data = array_merge($data, [ + 'subdefs' => $this->listRecordEmbeddableMedias($request, $record), + 'metadata' => $this->listRecordMetadata($record), + 'status' => $this->listRecordStatus($record), + 'caption' => $this->listRecordCaption($record), + ]); + } + + return $data; + } + + /** + * @param Request $request + * @param \record_adapter $record + * @return array + */ + private function listRecordEmbeddableMedias(Request $request, \record_adapter $record) + { + $subdefs = []; + + foreach ($record->get_embedable_medias([], []) as $name => $media) { + if (null !== $subdef = $this->listEmbeddableMedia($request, $record, $media)) { + $subdefs[] = $subdef; + } + } + + return $subdefs; + } + + /** + * List all fields of given record + * + * @param \record_adapter $record + * @return array + */ + private function listRecordMetadata(\record_adapter $record) + { + $includeBusiness = $this->getAclForUser()->can_see_business_fields($record->getDatabox()); + + return $this->listRecordCaptionFields($record->get_caption()->get_fields(null, $includeBusiness)); + } + + /** + * @param \caption_field[] $fields + * @return array + */ + private function listRecordCaptionFields($fields) + { + $ret = []; + + foreach ($fields as $field) { + $databox_field = $field->get_databox_field(); + + $fieldData = [ + 'meta_structure_id' => $field->get_meta_struct_id(), + 'name' => $field->get_name(), + 'labels' => [ + 'fr' => $databox_field->get_label('fr'), + 'en' => $databox_field->get_label('en'), + 'de' => $databox_field->get_label('de'), + 'nl' => $databox_field->get_label('nl'), + ], + ]; + + foreach ($field->get_values() as $value) { + $data = [ + 'meta_id' => $value->getId(), + 'value' => $value->getValue(), + ]; + + $ret[] = $fieldData + $data; + } + } + + return $ret; + } + + /** + * Retrieve detailed information about one status + * + * @param \record_adapter $record + * @return array + */ + private function listRecordStatus(\record_adapter $record) + { + $ret = []; + foreach ($record->getStatusStructure() as $bit => $status) { + $ret[] = [ + 'bit' => $bit, + 'state' => \databox_status::bitIsSet($record->getStatusBitField(), $bit), + ]; + } + + return $ret; + } + + /** + * @param \record_adapter $record + * @return array + */ + private function listRecordCaption(\record_adapter $record) + { + $includeBusiness = $this->getAclForUser()->can_see_business_fields($record->getDatabox()); + + $caption = []; + + foreach ($record->get_caption()->get_fields(null, $includeBusiness) as $field) { + $caption[] = [ + 'meta_structure_id' => $field->get_meta_struct_id(), + 'name' => $field->get_name(), + 'value' => $field->get_serialized_values(';'), + ]; + } + + return $caption; + } + + /** + * Returns requested includes + * + * @param Request $request + * @return string[] + */ + private function resolveSearchIncludes(Request $request) + { + $includes = [ + 'results.stories.records' + ]; + + if ($request->attributes->get('_extended', false)) { + if ($request->get('search_type') != SearchEngineOptions::RECORD_STORY) { + $includes = array_merge($includes, [ + 'results.stories.records.subdefs', + 'results.stories.records.metadata', + 'results.stories.records.caption', + 'results.stories.records.status' + ]); + } + else { + $includes = [ 'results.stories.caption' ]; + } + + $includes = array_merge($includes, [ + 'results.records.subdefs', + 'results.records.metadata', + 'results.records.caption', + 'results.records.status' + ]); + } + + return $includes; + } + + /** + * @param SearchEngineResult $result + * @param string[] $includes + * @param int $urlTTL + * @param int|null $story_max_records + * @return SearchResultView + */ + private function buildSearchView(SearchEngineResult $result, array $includes, $urlTTL, $story_max_records = null) + { + $references = new RecordReferenceCollection($result->getResults()); + + $records = new RecordCollection(); + $stories = new RecordCollection(); + + foreach ($references->toRecords($this->getApplicationBox()) as $record) { + if ($record->isStory()) { + $stories[$record->getId()] = $record; + } else { + $records[$record->getId()] = $record; + } + } + + $resultView = new SearchResultView($result); + + if ($stories->count() > 0) { + $user = $this->getAuthenticatedUser(); + $children = []; + + foreach ($stories->getDataboxIds() as $databoxId) { + $storyIds = $stories->getDataboxRecordIds($databoxId); + + $selections = $this->findDataboxById($databoxId) + ->getRecordRepository() + ->findChildren($storyIds, $user,1, $story_max_records); + $children[$databoxId] = array_combine($storyIds, $selections); + } + + /** @var StoryView[] $storyViews */ + $storyViews = []; + /** @var RecordView[] $childrenViews */ + $childrenViews = []; + + foreach ($stories as $index => $story) { + $storyView = new StoryView($story); + + $selection = $children[$story->getDataboxId()][$story->getRecordId()]; + + $childrenView = $this->buildRecordViews($selection); + + foreach ($childrenView as $view) { + $childrenViews[spl_object_hash($view)] = $view; + } + + $storyView->setChildren($childrenView); + + $storyViews[$index] = $storyView; + } + + if (in_array('results.stories.thumbnail', $includes, true)) { + $subdefViews = $this->buildSubdefsViews($stories, ['thumbnail'], $urlTTL); + + foreach ($storyViews as $index => $storyView) { + $storyView->setSubdefs($subdefViews[$index]); + } + } + + if (in_array('results.stories.metadatas', $includes, true) || + in_array('results.stories.caption', $includes, true)) { + $captions = $this->app['service.caption']->findByReferenceCollection($stories); + $canSeeBusiness = $this->retrieveSeeBusinessPerDatabox($stories); + + $this->buildCaptionViews($storyViews, $captions, $canSeeBusiness); + } + + $allChildren = new RecordCollection(); + foreach ($childrenViews as $index => $childrenView) { + $allChildren[$index] = $childrenView->getRecord(); + } + + $names = in_array('results.stories.records.subdefs', $includes, true) ? null : ['thumbnail']; + $subdefViews = $this->buildSubdefsViews($allChildren, $names, $urlTTL); + $technicalDatasets = $this->app['service.technical_data']->fetchRecordsTechnicalData($allChildren); + + foreach ($childrenViews as $index => $recordView) { + $recordView->setSubdefs($subdefViews[$index]); + $recordView->setTechnicalDataView(new TechnicalDataView($technicalDatasets[$index])); + } + + if (array_intersect($includes, ['results.stories.records.metadata', 'results.stories.records.caption'])) { + $captions = $this->app['service.caption']->findByReferenceCollection($allChildren); + $canSeeBusiness = $this->retrieveSeeBusinessPerDatabox($allChildren); + + $this->buildCaptionViews($childrenViews, $captions, $canSeeBusiness); + } + + $resultView->setStories($storyViews); + } + + if ($records->count() > 0) { + $names = in_array('results.records.subdefs', $includes, true) ? null : ['thumbnail']; + $recordViews = $this->buildRecordViews($records); + $subdefViews = $this->buildSubdefsViews($records, $names, $urlTTL); + + $technicalDatasets = $this->app['service.technical_data']->fetchRecordsTechnicalData($records); + + foreach ($recordViews as $index => $recordView) { + $recordView->setSubdefs($subdefViews[$index]); + $recordView->setTechnicalDataView(new TechnicalDataView($technicalDatasets[$index])); + } + + if (array_intersect($includes, ['results.records.metadata', 'results.records.caption'])) { + $captions = $this->app['service.caption']->findByReferenceCollection($records); + $canSeeBusiness = $this->retrieveSeeBusinessPerDatabox($records); + + $this->buildCaptionViews($recordViews, $captions, $canSeeBusiness); + } + + $resultView->setRecords($recordViews); + } + + return $resultView; + } + + /** + * @param Request $request + * @return SearchEngineResult + */ + private function doSearch(Request $request) + { + $options = SearchEngineOptions::fromRequest($this->app, $request); + $options->setFirstResult((int)($request->get('offset_start') ?: 0)); + $options->setMaxResults((int)$request->get('per_page') ?: 10); + + $this->getSearchEngine()->resetCache(); + + $search_result = $this->getSearchEngine()->query((string)$request->get('query'), $options); + + $this->getUserManipulator()->logQuery($this->getAuthenticatedUser(), $search_result->getQueryText()); + + // log array of collectionIds (from $options) for each databox + $collectionsReferencesByDatabox = $options->getCollectionsReferencesByDatabox(); + foreach ($collectionsReferencesByDatabox as $sbid => $references) { + $databox = $this->findDataboxById($sbid); + $collectionsIds = array_map(function(CollectionReference $ref){return $ref->getCollectionId();}, $references); + $this->getSearchEngineLogger()->log($databox, $search_result->getQueryText(), $search_result->getTotal(), $collectionsIds); + } + + $this->getSearchEngine()->clearCache(); + + return $search_result; + } + + /** + * @return SearchEngineInterface + */ + private function getSearchEngine() + { + return $this->app['phraseanet.SE']; + } + + /** + * @return UserManipulator + */ + private function getUserManipulator() + { + return $this->app['manipulator.user']; + } + + /** + * @return SearchEngineLogger + */ + private function getSearchEngineLogger() + { + return $this->app['phraseanet.SE.logger']; + } + + /** + * @param Request $request + * @return int + */ + private function resolveSubdefUrlTTL(Request $request) + { + $urlTTL = $request->query->get('subdef_url_ttl'); + + if (null !== $urlTTL) { + return (int)$urlTTL; + } + + return $this->getConf()->get(['registry', 'general', 'default-subdef-url-ttl']); + } + + /** + * @param RecordCollection|\record_adapter[] $references + * @return RecordView[] + */ + private function buildRecordViews($references) + { + if (!$references instanceof RecordCollection) { + $references = new RecordCollection($references); + } + + $recordViews = []; + + foreach ($references as $index => $record) { + $recordViews[$index] = new RecordView($record); + } + + return $recordViews; + } + + /** + * @param RecordReferenceInterface[]|RecordReferenceCollection|DataboxGroupable $references + * @param array|null $names + * @param int $urlTTL + * @return SubdefView[][] + */ + private function buildSubdefsViews($references, array $names = null, $urlTTL) + { + $subdefGroups = $this->app['service.media_subdef'] + ->findSubdefsByRecordReferenceFromCollection($references, $names); + + $fakeSubdefs = []; + + foreach ($subdefGroups as $index => $subdefGroup) { + if (!isset($subdefGroup['thumbnail'])) { + $fakeSubdef = new \media_subdef($this->app, $references[$index], 'thumbnail', true, []); + $fakeSubdefs[spl_object_hash($fakeSubdef)] = $fakeSubdef; + + $subdefGroups[$index]['thumbnail'] = $fakeSubdef; + } + } + + $allSubdefs = $this->mergeGroupsIntoOneList($subdefGroups); + $allPermalinks = \media_Permalink_Adapter::getMany( + $this->app, + array_filter($allSubdefs, function (\media_subdef $subdef) use ($fakeSubdefs) { + return !isset($fakeSubdefs[spl_object_hash($subdef)]); + }) + ); + $urls = $this->app['media_accessor.subdef_url_generator'] + ->generateMany($this->getAuthenticatedUser(), $allSubdefs, $urlTTL); + + $subdefViews = []; + + /** @var \media_subdef $subdef */ + foreach ($allSubdefs as $index => $subdef) { + $subdefView = new SubdefView($subdef); + + if (isset($allPermalinks[$index])) { + $subdefView->setPermalinkView(new PermalinkView($allPermalinks[$index])); + } + + $subdefView->setUrl($urls[$index]); + $subdefView->setUrlTTL($urlTTL); + + $subdefViews[spl_object_hash($subdef)] = $subdefView; + } + + $reorderedGroups = []; + + /** @var \media_subdef[] $subdefGroup */ + foreach ($subdefGroups as $index => $subdefGroup) { + $reordered = []; + + foreach ($subdefGroup as $subdef) { + $reordered[] = $subdefViews[spl_object_hash($subdef)]; + } + + $reorderedGroups[$index] = $reordered; + } + + return $reorderedGroups; + } + + /** + * @param array $groups + * @return array|mixed + */ + private function mergeGroupsIntoOneList(array $groups) + { + // Strips keys from the internal array + array_walk($groups, function (array &$group) { + $group = array_values($group); + }); + + if ($groups) { + return call_user_func_array('array_merge', $groups); + } + + return []; + } + + /** + * @param RecordReferenceInterface[]|DataboxGroupable $references + * @return array + */ + private function retrieveSeeBusinessPerDatabox($references) + { + if (!$references instanceof DataboxGroupable) { + $references = new RecordReferenceCollection($references); + } + + $acl = $this->getAclForUser(); + + $canSeeBusiness = []; + + foreach ($references->getDataboxIds() as $databoxId) { + $canSeeBusiness[$databoxId] = $acl->can_see_business_fields($this->findDataboxById($databoxId)); + } + + $rights = []; + + foreach ($references as $index => $reference) { + $rights[$index] = $canSeeBusiness[$reference->getDataboxId()]; + } + + return $rights; + } + + /** + * @param RecordView[] $recordViews + * @param \caption_record[] $captions + * @param bool[] $canSeeBusiness + */ + private function buildCaptionViews($recordViews, $captions, $canSeeBusiness) + { + foreach ($recordViews as $index => $recordView) { + $caption = $captions[$index]; + + $captionView = new CaptionView($caption); + + $captionView->setFields($caption->get_fields(null, isset($canSeeBusiness[$index]) && (bool)$canSeeBusiness[$index])); + + $recordView->setCaption($captionView); + } + } +} diff --git a/lib/Alchemy/Phrasea/Controller/Prod/PushController.php b/lib/Alchemy/Phrasea/Controller/Prod/PushController.php index f9ce528e41..6e650aefaa 100644 --- a/lib/Alchemy/Phrasea/Controller/Prod/PushController.php +++ b/lib/Alchemy/Phrasea/Controller/Prod/PushController.php @@ -193,7 +193,7 @@ class PushController extends Controller 'Validation from %user%', [ '%user%' => $this->getAuthenticatedUser()->getDisplayName(), ])); - $validation_description = $request->request->get('validation_description'); + $validation_description = $request->request->get('message'); $participants = $request->request->get('participants'); diff --git a/lib/Alchemy/Phrasea/ControllerProvider/Api/V3.php b/lib/Alchemy/Phrasea/ControllerProvider/Api/V3.php new file mode 100644 index 0000000000..5925c74921 --- /dev/null +++ b/lib/Alchemy/Phrasea/ControllerProvider/Api/V3.php @@ -0,0 +1,48 @@ +share(function (PhraseaApplication $app) { + return (new V3Controller($app)); + }); + } + + public function boot(Application $app) + { + } + + public function connect(Application $app) + { + if (! $this->isApiEnabled($app)) { + return $app['controllers_factory']; + } + + /** @var ControllerCollection $controllers */ + $controllers = $app['controllers_factory']; + + $controllers->before(new OAuthListener()); + + $controllers->get('/stories/{databox_id}/{record_id}/', 'controller.api.v3:getStoryAction') + ->before('controller.api.v1:ensureCanAccessToRecord') + ->assert('databox_id', '\d+') + ->assert('record_id', '\d+'); + + $controllers->match('/search/', 'controller.api.v3:searchAction'); + + return $controllers; + } +} diff --git a/lib/Alchemy/Phrasea/Core/Event/Listener/OAuthListener.php b/lib/Alchemy/Phrasea/Core/Event/Listener/OAuthListener.php index 34c4685149..0dd4984306 100644 --- a/lib/Alchemy/Phrasea/Core/Event/Listener/OAuthListener.php +++ b/lib/Alchemy/Phrasea/Core/Event/Listener/OAuthListener.php @@ -15,6 +15,7 @@ use Alchemy\Phrasea\Authentication\Context; use Alchemy\Phrasea\Controller\Api\Result; use Alchemy\Phrasea\ControllerProvider\Api\V1; use Alchemy\Phrasea\ControllerProvider\Api\V2; +use Alchemy\Phrasea\ControllerProvider\Api\V3; use Alchemy\Phrasea\Core\Configuration\PropertyAccess; use Alchemy\Phrasea\Core\Event\ApiOAuth2EndEvent; use Alchemy\Phrasea\Core\Event\ApiOAuth2StartEvent; @@ -76,11 +77,13 @@ class OAuthListener // Sets the Api Version $CalledController = $request->attributes->get('_controller'); - if(mb_strpos($CalledController, 'controller.api.v1') !== FALSE){ + if (mb_strpos($CalledController, 'controller.api.v1') !== FALSE) { $request->attributes->set('api_version', V1::VERSION); - }elseif(mb_strpos($CalledController, 'controller.api.v2') !== FALSE){ + } elseif(mb_strpos($CalledController, 'controller.api.v2') !== FALSE) { $request->attributes->set('api_version', V2::VERSION); - }else{ + } elseif(mb_strpos($CalledController, 'controller.api.v3') !== FALSE) { + $request->attributes->set('api_version', V3::VERSION); + } else { $request->attributes->set('api_version', $oAuth2Account->getApiVersion()); } diff --git a/lib/Alchemy/Phrasea/Core/Provider/BorderManagerServiceProvider.php b/lib/Alchemy/Phrasea/Core/Provider/BorderManagerServiceProvider.php index 36f0ed0e7e..d7a0f636f9 100644 --- a/lib/Alchemy/Phrasea/Core/Provider/BorderManagerServiceProvider.php +++ b/lib/Alchemy/Phrasea/Core/Provider/BorderManagerServiceProvider.php @@ -78,6 +78,20 @@ class BorderManagerServiceProvider implements ServiceProviderInterface $checkerObj->restrictToCollections($collections); } + + if (isset($checker['compare-ignore-collections'])) { + $collections = []; + foreach ($checker['compare-ignore-collections'] as $base_id) { + try { + $collections[] = \collection::getByBaseId($app, $base_id); + } catch (\Exception $e) { + throw new \InvalidArgumentException('Invalid collection option'); + } + } + + $checkerObj->setCompareIgnoreCollections($collections); + } + $registeredCheckers[] = $checkerObj; } catch (\InvalidArgumentException $e) { $app['monolog']->error( diff --git a/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php b/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php index 522d49baae..30feada346 100644 --- a/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php +++ b/lib/Alchemy/Phrasea/Databox/Record/LegacyRecordRepository.php @@ -82,6 +82,34 @@ class LegacyRecordRepository implements RecordRepository return $this->mapRecordsFromResultSet($result); } + public function findBySha256WithExcludedCollIds($sha256, $excludedCollIds = []) + { + static $sql; + + if (!$sql) { + $qb = $this->createSelectBuilder() + ->where('sha256 = :sha256'); + + if (!empty($excludedCollIds)) { + $qb->andWhere($qb->expr()->notIn('coll_id', ':coll_id')); + } + + $sql = $qb->getSQL(); + } + + $result = $this->databox->get_connection()->fetchAll($sql, + [ + 'sha256' => $sha256, + 'coll_id' => $excludedCollIds + ], + [ + ':coll_id' => Connection::PARAM_INT_ARRAY + ] + ); + + return $this->mapRecordsFromResultSet($result); + } + /** * @param string $uuid * @return \record_adapter[] @@ -99,6 +127,40 @@ class LegacyRecordRepository implements RecordRepository return $this->mapRecordsFromResultSet($result); } + /** + * @param string $uuid + * @param array $excludedCollIds + * @return \record_adapter[] + */ + public function findByUuidWithExcludedCollIds($uuid, $excludedCollIds = []) + { + static $sql; + + if (!$sql) { + $qb = $this->createSelectBuilder() + ->where('uuid = :uuid') + ; + + if (!empty($excludedCollIds)) { + $qb->andWhere($qb->expr()->notIn('coll_id', ':coll_id')); + } + + $sql = $qb->getSQL(); + } + + $result = $this->databox->get_connection()->fetchAll($sql, + [ + 'uuid' => $uuid, + 'coll_id' => $excludedCollIds + ], + [ + ':coll_id' => Connection::PARAM_INT_ARRAY + ] + ); + + return $this->mapRecordsFromResultSet($result); + } + public function findByRecordIds(array $recordIds) { static $sql; @@ -120,7 +182,7 @@ class LegacyRecordRepository implements RecordRepository return $this->mapRecordsFromResultSet($result); } - public function findChildren(array $storyIds, $user = null) + public function findChildren(array $storyIds, $user = null, $offset = 1, $max_items = null) { if (!$storyIds) { return []; @@ -129,25 +191,73 @@ class LegacyRecordRepository implements RecordRepository $connection = $this->databox->get_connection(); $selects = $this->getRecordSelects(); - array_unshift($selects, 's.rid_parent as story_id'); - $builder = $connection->createQueryBuilder(); - $builder - ->select($selects) - ->from('regroup', 's') - ->innerJoin('s', 'record', 'r', 'r.record_id = s.rid_child') - ->where( - 's.rid_parent IN (:storyIds)', - 'r.parent_record_id = 0' - ) - ->setParameter('storyIds', $storyIds, Connection::PARAM_INT_ARRAY) - ; + if ($max_items) { + array_unshift($selects, 'sr.rid_parent as story_id'); - if (null !== $user) { - $this->addUserFilter($builder, $user); + $subBuilder = $connection->createQueryBuilder(); + + $subBuilder + ->select('s.*, + IF(@old_rid_parent != s.rid_parent, @cpt := 1, @cpt := @cpt+1) AS CPT') + ->addSelect("IF(@old_rid_parent != s.rid_parent, IF(@old_rid_parent:=s.rid_parent,'NEW PARENT',0), '----------') AS Y") + ->from('regroup', 's') + ->where('s.rid_parent IN (:storyIds)') + ->setParameter('storyIds', $storyIds, Connection::PARAM_INT_ARRAY) + ->orderBy('s.rid_parent, s.ord') + ; + + $builder = $subBuilder->getConnection()->createQueryBuilder(); + + $builder->select($selects) + ->from(sprintf('( %s )', $subBuilder->getSQL()), 'sr') + ->innerJoin('sr', 'record', 'r', 'r.record_id = sr.rid_child') + ->where('sr.CPT BETWEEN :offset AND :maxresult') + ->andWhere('r.parent_record_id = 0') + ->setParameter('offset', $offset) + ->setParameter('maxresult', ($offset + $max_items -1)) + ->orderBy('story_id, sr.CPT') + ; + + if (null !== $user) { + $this->addUserFilter($builder, $user); + } + + $connection->executeQuery('SET @cpt = 1'); + + $connection->executeQuery('SET @old_rid_parent = -1'); + + + $data = $connection->fetchAll( + $builder->getSQL(), + array_merge($subBuilder->getParameters(), $builder->getParameters()), + array_merge($subBuilder->getParameterTypes(), $builder->getParameterTypes()) + ); + + } else { + array_unshift($selects, 's.rid_parent as story_id'); + + $builder = $connection->createQueryBuilder(); + + $builder + ->select($selects) + ->from('regroup', 's') + ->innerJoin('s', 'record', 'r', 'r.record_id = s.rid_child') + ->where( + 's.rid_parent IN (:storyIds)', + 'r.parent_record_id = 0' + ) + ->orderBy('s.ord', 'ASC') + ->setParameter('storyIds', $storyIds, Connection::PARAM_INT_ARRAY) + ; + + if (null !== $user) { + $this->addUserFilter($builder, $user); + } + + $data = $connection->fetchAll($builder->getSQL(), $builder->getParameters(), $builder->getParameterTypes()); } - $data = $connection->fetchAll($builder->getSQL(), $builder->getParameters(), $builder->getParameterTypes()); $records = $this->mapRecordsFromResultSet($data); $selections = array_map( diff --git a/lib/Alchemy/Phrasea/Databox/Record/RecordRepository.php b/lib/Alchemy/Phrasea/Databox/Record/RecordRepository.php index 0da49bb00f..bab31055da 100644 --- a/lib/Alchemy/Phrasea/Databox/Record/RecordRepository.php +++ b/lib/Alchemy/Phrasea/Databox/Record/RecordRepository.php @@ -26,12 +26,26 @@ interface RecordRepository */ public function findBySha256($sha256); + /** + * @param string $sha256 + * @param array $excludedCollIds + * @return \record_adapter[] + */ + public function findBySha256WithExcludedCollIds($sha256, $excludedCollIds = []); + /** * @param string $uuid * @return \record_adapter[] */ public function findByUuid($uuid); + /** + * @param string $uuid + * @param array $excludedCollIds + * @return \record_adapter[] + */ + public function findByUuidWithExcludedCollIds($uuid, $excludedCollIds = []); + /** * @param array $recordIds * @return \record_adapter[] @@ -43,9 +57,11 @@ interface RecordRepository * * @param int[] $storyIds * @param null|int|User $user + * @param int $offset + * @param null|int $max_items * @return \set_selection[] */ - public function findChildren(array $storyIds, $user = null); + public function findChildren(array $storyIds, $user = null, $offset = 1, $max_items = null); /** diff --git a/lib/Alchemy/Phrasea/Media/Subdef/Video.php b/lib/Alchemy/Phrasea/Media/Subdef/Video.php index ef0a113564..be673b937a 100644 --- a/lib/Alchemy/Phrasea/Media/Subdef/Video.php +++ b/lib/Alchemy/Phrasea/Media/Subdef/Video.php @@ -33,7 +33,7 @@ class Video extends Audio $this->registerOption(new OptionType\Range($this->translator->trans('Frame Rate'), self::OPTION_FRAMERATE, 1, 200, 20)); $this->registerOption(new OptionType\Enum($this->translator->trans('Video Codec'), self::OPTION_VCODEC, ['libx264', 'libvpx', 'libtheora'], 'libx264')); $this->unregisterOption(self::OPTION_ACODEC); - $this->registerOption(new OptionType\Enum($this->translator->trans('Audio Codec'), self::OPTION_ACODEC, ['libfaac', 'libvo_aacenc', 'libmp3lame', 'libvorbis'], 'libfaac')); + $this->registerOption(new OptionType\Enum($this->translator->trans('Audio Codec'), self::OPTION_ACODEC, ['libfaac', 'libvo_aacenc', 'libmp3lame', 'libvorbis', 'libfdk_aac'], 'libmp3lame')); } public function getType() diff --git a/lib/classes/record/adapter.php b/lib/classes/record/adapter.php index c4045d9fc5..8e181c5d2e 100644 --- a/lib/classes/record/adapter.php +++ b/lib/classes/record/adapter.php @@ -1673,6 +1673,43 @@ class record_adapter implements RecordInterface, cache_cacheableInterface return $records; } + public static function getRecordsByOriginalnameWithExcludedCollIds(databox $databox, $original_name, $caseSensitive = false, $offset_start = 0, $how_many = 10, $excludedCollIds = []) + { + $offset_start = max(0, (int)$offset_start); + $how_many = max(1, (int)$how_many); + $collate = $caseSensitive ? 'utf8_bin' : 'utf8_unicode_ci'; + + $qb = $databox->get_connection()->createQueryBuilder() + ->select('record_id') + ->from('record') + ->where('originalname = :original_name COLLATE :collate') + ; + + $params = ['original_name' => $original_name, 'collate' => $collate]; + $types = []; + + if (!empty($excludedCollIds)) { + $qb->andWhere($qb->expr()->notIn('coll_id', ':coll_id')); + + $params['coll_id'] = $excludedCollIds; + $types[':coll_id'] = Connection::PARAM_INT_ARRAY; + } + + $sql = $qb->setFirstResult($offset_start) + ->setMaxResults($how_many) + ->getSQL() + ; + + $rs = $databox->get_connection()->fetchAll($sql, $params, $types); + + $records = []; + foreach ($rs as $row) { + $records[] = $databox->get_record($row['record_id']); + } + + return $records; + } + /** * @return set_selection|record_adapter[] * @throws Exception @@ -1685,17 +1722,20 @@ class record_adapter implements RecordInterface, cache_cacheableInterface } /** + * @param int $offset + * @param null|int $max_items + * * @return set_selection|record_adapter[] * @throws Exception * @throws \Doctrine\DBAL\DBALException */ - public function getChildren() + public function getChildren($offset = 1, $max_items = null) { if (!$this->isStory()) { throw new Exception('This record is not a grouping'); } - $selections = $this->getDatabox()->getRecordRepository()->findChildren([$this->getRecordId()]); + $selections = $this->getDatabox()->getRecordRepository()->findChildren([$this->getRecordId()], null, $offset, $max_items); return reset($selections); } diff --git a/package.json b/package.json index 31a385774f..7525421e67 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "normalize-css": "^2.1.0", "npm": "^6.0.0", "npm-modernizr": "^2.8.3", - "phraseanet-production-client": "0.34.82-d", + "phraseanet-production-client": "^0.34.86-d", "requirejs": "^2.3.5", "tinymce": "^4.0.28", "underscore": "^1.8.3", diff --git a/resources/www/common/images/icons/basket_feedback_read.png b/resources/www/common/images/icons/basket_feedback_read.png new file mode 100644 index 0000000000..129170a648 Binary files /dev/null and b/resources/www/common/images/icons/basket_feedback_read.png differ diff --git a/resources/www/common/images/icons/basket_feedback_unread.png b/resources/www/common/images/icons/basket_feedback_unread.png new file mode 100644 index 0000000000..31d91d31a4 Binary files /dev/null and b/resources/www/common/images/icons/basket_feedback_unread.png differ diff --git a/resources/www/common/styles/fonts/PhraseanetIcomoon/style.css b/resources/www/common/styles/fonts/PhraseanetIcomoon/style.css index 566f9d5786..bef5e9c08c 100644 --- a/resources/www/common/styles/fonts/PhraseanetIcomoon/style.css +++ b/resources/www/common/styles/fonts/PhraseanetIcomoon/style.css @@ -1,13 +1,3 @@ -@font-face { - font-family: 'icomoon'; - src: url('fonts/icomoon.eot?81kpnc'); - src: url('fonts/icomoon.eot?81kpnc#iefix') format('embedded-opentype'), - url('fonts/icomoon.ttf?81kpnc') format('truetype'), - url('fonts/icomoon.woff?81kpnc') format('woff'), - url('fonts/icomoon.svg?81kpnc#icomoon') format('svg'); - font-weight: normal; - font-style: normal; -} [class^="icon-"], [class*=" icon-"] { /* use !important to prevent issues with browser extensions that change fonts */ diff --git a/resources/www/lightbox/styles/jquery-mobile/_jquery-validator.scss b/resources/www/lightbox/styles/jquery-mobile/_jquery-validator.scss index 7f49c0af1c..013a7ae0a7 100644 --- a/resources/www/lightbox/styles/jquery-mobile/_jquery-validator.scss +++ b/resources/www/lightbox/styles/jquery-mobile/_jquery-validator.scss @@ -1,30 +1,34 @@ $iconsPath: '../../../assets/common/images/icons/'; - -ul.image_set{ - padding:0; - margin:0; - border:none; - width:100%; - border:none; +$feedbackColor : #8bc34a; +$basketColor : #2196f3 ; +ul.image_set { + padding: 0; + margin: 0; + border: none; + width: 100%; + border: none; list-style-type: none; display: flex; flex-wrap: wrap; } -li.image_box a img{ - position:relative; - border:none; - width: auto!important; - height: 100% !important; + +li.image_box a img { + position: relative; + border: none; + width: auto !important; + height: 100% !important; top: 0 !important; object-fit: contain; } -li.image_box a{ - padding:0; - text-shadow:0; - margin:0; + +li.image_box a { + padding: 0; + text-shadow: 0; + margin: 0; width: 100%; } -li.image_box{ + +li.image_box { width: 18%; position: relative; margin: 0 2.5% 15px 0; @@ -38,19 +42,20 @@ li.image_box{ } .thumb_wrapper { background: #ededed; - width: 100%!important; - height: 160px!important; + width: 100% !important; + height: 160px !important; @media screen and (max-width: 767px) { - height: 130px !important; + height: 130px !important; } } } + @media screen and (max-width: 767px) { - li.image_box{ + li.image_box { width: 32%; margin: 0 2% 15px 0; &:nth-child(5n) { - margin-right: 2% ; + margin-right: 2%; } &:nth-child(3n) { margin-right: 0; @@ -58,35 +63,37 @@ li.image_box{ } } -a.no.active_choice{ - background-color:red; +a.no.active_choice { + background-color: red; color: #fff; } -a.active_choice{ + +a.active_choice { background-color: #53b401; color: #fff; } -.valid_choice{ - position:absolute; - bottom:0; - right:0; - width:16px; - height:16px; - z-index:2; +.valid_choice { + position: absolute; + bottom: 0; + right: 0; + width: 16px; + height: 16px; + z-index: 2; } -.valid_choice.agree{ +.valid_choice.agree { background: #7ed321; border-top-left-radius: 100px; } -.valid_choice.disagree{ + +.valid_choice.disagree { background: #d0021b; border-top-left-radius: 100px; } .thumb_wrapper { - text-align:center; + text-align: center; } @media screen and (orientation: landscape) { @@ -109,21 +116,206 @@ a.active_choice{ font-size: 18px; } - -.ui-listview .ui-li-has-thumb .ui-li-thumb, .ui-listview .ui-li-has-thumb>.ui-btn>img:first-child, .ui-listview .ui-li-has-thumb>img:first-child { +.ui-listview .ui-li-has-thumb .ui-li-thumb, .ui-listview .ui-li-has-thumb > .ui-btn > img:first-child, .ui-listview .ui-li-has-thumb > img:first-child { top: 50%; transform: translateY(-50%); } /*user status*/ .menu-bar-item { - background: #000; - padding: 12px; - text-align: center; - a { - color: #fff!important; - text-decoration: none!important; - font-weight: normal; + background: #f0f0f0; + padding: 12px 15px; + text-align: left; + position: relative; + .icomoon { + font-size: 17px; + position: absolute; + left: 23px; + top: 50%; + transform: translateY(-50%); + } + .ui-link { + color: #4f4f4f !important; + text-decoration: none !important; + .text { + padding-left: 31px; + color: #4f4f4f !important; + text-decoration: none !important; + font-weight: 700; + font-size: 13px; + } } } +/*new design of lightbox*/ +/*main nav */ +#lightbox-menu { + li { + margin-bottom: 30px; + .ui-li-count { + border-radius: 3px !important; + border-top-left-radius: 0 !important; + border-bottom-left-radius: 0 !important; + border: 0; + color: #fff; + text-shadow: none; + padding: 18px 23px; + top: 0; + right: 0; + margin: 0; + font-size: 22px; + min-width: 25px; + background: $feedbackColor; + } + &.ui-first-child { + margin-top: 15px; + } + &.ui-last-child { + a { + &:before { + background: $basketColor; + } + &:hover, &:active, &:focus { + color: $basketColor; + } + } + .ui-li-count { + background: $basketColor; + } + } + + } + a { + padding: 22px 25px; + font-size: 20px; + border-radius: 3px !important; + box-shadow: 0 0 6px 0 rgba(0, 0, 0, 0.19); + background-color: #eeeeee; + &:hover, &:active, &:focus { + color: $feedbackColor; + } + &:after { + content: none !important; + } + &:before { + content: ""; + position: absolute; + display: block; + width: 100%; + height: 4px; + bottom: 0; + background: $feedbackColor; + left: 0; + border-radius: 3px; + } + } +} + +.lightbox-bottom-btn { + margin-top: 50px; + .ui-btn { + font-size: 15px; + } +} +#validation, #baskets { + .ui-content { + padding-left: 0; + padding-right: 0; + } +} +.basket-title { + background: $feedbackColor; + padding: 12px 30px; + font-size: 17px; + margin: 0; + text-shadow: none; + color: #fff; + font-weight: 700; + #baskets & { + background: $basketColor; + } + span { + float: right; + } +} + +.feed-list { + li { + height: 71px; + padding-left: 109px!important; + padding-right: 80px!important; + border-color: #d4d4d4!important; + text-overflow: inherit!important; + white-space: inherit!important; + } + .lightbox-img { + width: 90px; + height: 90px; + background-color: #ededed; + position: absolute; + left: 0; + top: 0; + display: flex; + flex-wrap: wrap; + img { + display: flex; + align-items: center; + width: 90px; + max-width: 100%; + max-height: 100%; + object-fit: contain; + } + } + h3 { + display: flex!important; + align-items: center; + height: 71px; + margin: 0!important; + font-size: 15px; + font-weight: bold!important; + text-overflow: inherit!important; + white-space: inherit!important; + a { + position: relative; + color: #313131!important; + width: 100%; + padding-right: 18px; + &:after { + content: "\e96c"; + font-family: icomoon; + position: absolute; + right: 0; + font-size: 20px; + line-height: 1; + top: 50%; + transform: translateY(-50%); + } + } + + } + span { + font-size: 17px; + color: #fff!important; + display: inline-block; + text-shadow: none!important; + top: 0; + width: 52px; + right: 0; + line-height: 25px; + padding: 31px 0px; + margin: 0; + border-radius: 0; + &.validation { + background: $feedbackColor!important; + } + &.baskets { + background: $basketColor!important; + } + } + +} +.lightbox-msg { + font-size: 14px; + color: #313131; + padding: 6px 0 6px 30px; +} diff --git a/resources/www/lightbox/styles/main-mobile.scss b/resources/www/lightbox/styles/main-mobile.scss index e5c9e1e93e..7f53448267 100644 --- a/resources/www/lightbox/styles/main-mobile.scss +++ b/resources/www/lightbox/styles/main-mobile.scss @@ -650,8 +650,12 @@ button.confirm_report { min-height: 26px; padding: 10px 0; } - +.ui-controlgroup, fieldset.ui-controlgroup { + margin: 10px 0!important; +} .ui-listview.lightbox-list-view { + margin-top: 0; + margin-bottom: 0; & > .ui-li-static { padding: .7em 1em; text-overflow: inherit; @@ -687,6 +691,10 @@ button.confirm_report { .center-image { text-align: center; + iframe { + min-height: 240px; + width: auto; + } } /*validate page*/ diff --git a/templates/mobile/common/menubar.html.twig b/templates/mobile/common/menubar.html.twig index 03a41053f7..d8190dd5fa 100644 --- a/templates/mobile/common/menubar.html.twig +++ b/templates/mobile/common/menubar.html.twig @@ -3,13 +3,13 @@ {% if app.getAuthenticator().isAuthenticated() %} diff --git a/templates/mobile/lightbox/basket_element.html.twig b/templates/mobile/lightbox/basket_element.html.twig index 06e6d590a1..54736a3fb2 100644 --- a/templates/mobile/lightbox/basket_element.html.twig +++ b/templates/mobile/lightbox/basket_element.html.twig @@ -69,16 +69,16 @@ {% if basket_element.getBasket().getValidation() %} {% if basket_element.getBasket().getValidation().getParticipant(app.getAuthenticatedUser()).getCanAgree() %}
- + - +
{% endif %} -
- +
+ {{ 'validation:: editer ma note' | trans }}
diff --git a/templates/mobile/lightbox/index.html.twig b/templates/mobile/lightbox/index.html.twig index a270116c9c..67f698664f 100644 --- a/templates/mobile/lightbox/index.html.twig +++ b/templates/mobile/lightbox/index.html.twig @@ -44,17 +44,17 @@ {% include 'common/menubar.html.twig' %}
-