mirror of
https://github.com/alchemy-fr/Phraseanet.git
synced 2025-10-18 07:23:13 +00:00
Merge branch 'master' into PHRAS-3006_Port41_Front_delete_3_by_3
This commit is contained in:
39
README.md
39
README.md
@@ -18,6 +18,8 @@ Phraseanet is licensed under GPL-v3 license.
|
||||
|
||||
https://docs.phraseanet.com/
|
||||
|
||||
For development with Phraseanet API see https://docs.phraseanet.com/4.0/en/Devel/index.html
|
||||
|
||||
# Installation :
|
||||
|
||||
You **must** not download the source from GitHub, but download a packaged version here :
|
||||
@@ -26,13 +28,7 @@ https://www.phraseanet.com/download/
|
||||
|
||||
And follow the install steps described at https://docs.phraseanet.com/4.0/en/Admin/Install.html
|
||||
|
||||
# Try Phraseanet :
|
||||
|
||||
You can also download a testing pre installed Virtual Machine in OVA format here :
|
||||
|
||||
https://www.phraseanet.com/download/
|
||||
|
||||
# With Docker
|
||||
# Phraseanet with Docker:
|
||||
|
||||
## Prerequisites
|
||||
|
||||
@@ -92,9 +88,27 @@ Where `<command>` can be:
|
||||
- `bin/console worker:execute -m 2`
|
||||
- ...
|
||||
|
||||
|
||||
The default parameters allow you to reach the app with : `http://localhost:8082`
|
||||
|
||||
### Use Phraseanet images from docker hub
|
||||
|
||||
Retrieve on Docker hub prebuilt images for Phraseanet.
|
||||
|
||||
https://hub.docker.com/r/alchemyfr/phraseanet-fpm
|
||||
|
||||
https://hub.docker.com/r/alchemyfr/phraseanet-worker
|
||||
|
||||
https://hub.docker.com/r/alchemyfr/phraseanet-nginx
|
||||
|
||||
To use them and not build the images locally, we advise to override the properties in file: env.local
|
||||
|
||||
```bash
|
||||
# Registry from where you pull Docker images
|
||||
PHRASEANET_DOCKER_REGISTRY=alchemyfr
|
||||
# Tag of the Docker images
|
||||
PHRASEANET_DOCKER_TAG=
|
||||
```
|
||||
|
||||
## Development mode
|
||||
|
||||
The development mode uses the `docker-compose-override.yml` file.
|
||||
@@ -175,6 +189,12 @@ export PHRASEANET_SSH_PRIVATE_KEY=$(cat ~/.ssh/id_rsa)
|
||||
export PHRASEANET_SSH_PRIVATE_KEY=$(openssl rsa -in ~/.ssh/id_rsa -out /tmp/id_rsa_raw && cat /tmp/id_rsa_raw && rm /tmp/id_rsa_raw)
|
||||
```
|
||||
|
||||
# Try Phraseanet with Pre installed VM (deprecated)
|
||||
|
||||
You can also download a testing pre installed Virtual Machine in OVA format here :
|
||||
|
||||
https://www.phraseanet.com/download/
|
||||
|
||||
# With Vagrant (deprecated)
|
||||
|
||||
## Development :
|
||||
@@ -194,4 +214,5 @@ Ex:
|
||||
- vagrant up --provision //// 5.6 ///// 1 >> Build the alchemy/phraseanet-php-5.6 box
|
||||
|
||||
|
||||
For development with Phraseanet API see https://docs.phraseanet.com/4.0/en/Devel/index.html
|
||||
|
||||
|
||||
|
@@ -96,7 +96,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.5",
|
||||
"media-alchemyst/media-alchemyst": "^0.5.6",
|
||||
"monolog/monolog": "~1.3",
|
||||
"mrclay/minify": "~2.1.6",
|
||||
"neutron/process-manager": "2.0.x-dev@dev",
|
||||
@@ -105,7 +105,7 @@
|
||||
"neutron/silex-imagine-provider": "~0.1.0",
|
||||
"neutron/temporary-filesystem": "~2.1",
|
||||
"pagerfanta/pagerfanta": "^1.0",
|
||||
"php-ffmpeg/php-ffmpeg": "~0.5.0",
|
||||
"php-ffmpeg/php-ffmpeg": "^v0.15",
|
||||
"php-xpdf/php-xpdf": "~0.2.1",
|
||||
"exiftool/exiftool": "^11",
|
||||
"ramsey/uuid": "^3.0",
|
||||
|
57
composer.lock
generated
57
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "5a4a0be62b13071a6b06893b7ce08372",
|
||||
"content-hash": "008ff0b5d3d13b4f0ce5d34348ded83a",
|
||||
"packages": [
|
||||
{
|
||||
"name": "alchemy-fr/tcpdf-clone",
|
||||
@@ -4331,16 +4331,16 @@
|
||||
},
|
||||
{
|
||||
"name": "media-alchemyst/media-alchemyst",
|
||||
"version": "0.5.5",
|
||||
"version": "0.5.6",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/alchemy-fr/Media-Alchemyst.git",
|
||||
"reference": "3bd3204b69882f495adfb617383a077face92ed0"
|
||||
"reference": "2b9f7697997f7863bbc3d08344c559a1cba519c2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/alchemy-fr/Media-Alchemyst/zipball/3bd3204b69882f495adfb617383a077face92ed0",
|
||||
"reference": "3bd3204b69882f495adfb617383a077face92ed0",
|
||||
"url": "https://api.github.com/repos/alchemy-fr/Media-Alchemyst/zipball/2b9f7697997f7863bbc3d08344c559a1cba519c2",
|
||||
"reference": "2b9f7697997f7863bbc3d08344c559a1cba519c2",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -4350,7 +4350,7 @@
|
||||
"monolog/monolog": "~1.0",
|
||||
"neutron/temporary-filesystem": "^2.1.1",
|
||||
"php": ">=5.3.3",
|
||||
"php-ffmpeg/php-ffmpeg": ">=0.4.2,<0.6",
|
||||
"php-ffmpeg/php-ffmpeg": "^v0.15",
|
||||
"php-mp4box/php-mp4box": "~0.3.0",
|
||||
"php-unoconv/php-unoconv": "~0.3.1",
|
||||
"pimple/pimple": "~1.0",
|
||||
@@ -4401,7 +4401,7 @@
|
||||
"video",
|
||||
"video processing"
|
||||
],
|
||||
"time": "2019-12-11T07:20:45+00:00"
|
||||
"time": "2020-04-01T08:51:55+00:00"
|
||||
},
|
||||
{
|
||||
"name": "monolog/monolog",
|
||||
@@ -5147,29 +5147,29 @@
|
||||
},
|
||||
{
|
||||
"name": "php-ffmpeg/php-ffmpeg",
|
||||
"version": "0.5.1",
|
||||
"version": "v0.15",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHP-FFMpeg/PHP-FFMpeg.git",
|
||||
"reference": "c8949fe3df89edd7692368cc110a51a27971f28a"
|
||||
"reference": "984dbd046b6d8c285f9e7419fc7645f197513bfa"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHP-FFMpeg/PHP-FFMpeg/zipball/c8949fe3df89edd7692368cc110a51a27971f28a",
|
||||
"reference": "c8949fe3df89edd7692368cc110a51a27971f28a",
|
||||
"url": "https://api.github.com/repos/PHP-FFMpeg/PHP-FFMpeg/zipball/984dbd046b6d8c285f9e7419fc7645f197513bfa",
|
||||
"reference": "984dbd046b6d8c285f9e7419fc7645f197513bfa",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"alchemy/binary-driver": "~1.5",
|
||||
"doctrine/cache": "~1.0",
|
||||
"evenement/evenement": "~1.0",
|
||||
"neutron/temporary-filesystem": "~2.1, >=2.1.1",
|
||||
"php": ">=5.3.3"
|
||||
"alchemy/binary-driver": "^1.5 || ~2.0.0 || ^5.0",
|
||||
"doctrine/cache": "^1.0",
|
||||
"evenement/evenement": "^3.0 || ^2.0 || ^1.0",
|
||||
"neutron/temporary-filesystem": "^2.1.1",
|
||||
"php": "^5.3.9 || ^7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~3.7",
|
||||
"sami/sami": "~1.0",
|
||||
"silex/silex": "~1.0"
|
||||
"silex/silex": "~1.0",
|
||||
"symfony/phpunit-bridge": "^5.0.4"
|
||||
},
|
||||
"suggest": {
|
||||
"php-ffmpeg/extras": "A compilation of common audio & video drivers for PHP-FFMpeg"
|
||||
@@ -5177,7 +5177,7 @@
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "0.5-dev"
|
||||
"dev-master": "0.7-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
@@ -5199,6 +5199,21 @@
|
||||
"name": "Phraseanet Team",
|
||||
"email": "info@alchemy.fr",
|
||||
"homepage": "http://www.phraseanet.com/"
|
||||
},
|
||||
{
|
||||
"name": "Patrik Karisch",
|
||||
"email": "patrik@karisch.guru",
|
||||
"homepage": "http://www.karisch.guru"
|
||||
},
|
||||
{
|
||||
"name": "Romain Biard",
|
||||
"email": "romain.biard@gmail.com",
|
||||
"homepage": "https://www.strime.io/"
|
||||
},
|
||||
{
|
||||
"name": "Jens Hausdorf",
|
||||
"email": "hello@jens-hausdorf.de",
|
||||
"homepage": "https://jens-hausdorf.de"
|
||||
}
|
||||
],
|
||||
"description": "FFMpeg PHP, an Object Oriented library to communicate with AVconv / ffmpeg",
|
||||
@@ -5212,7 +5227,7 @@
|
||||
"video",
|
||||
"video processing"
|
||||
],
|
||||
"time": "2014-08-26T08:46:56+00:00"
|
||||
"time": "2020-03-23T09:32:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "php-mp4box/php-mp4box",
|
||||
@@ -7772,7 +7787,7 @@
|
||||
],
|
||||
"packages-dev": [
|
||||
{
|
||||
"name": "mikey179/vfsStream",
|
||||
"name": "mikey179/vfsstream",
|
||||
"version": "v1.6.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
|
@@ -15,6 +15,7 @@ chown -R app:app \
|
||||
FILE=config/configuration.yml
|
||||
|
||||
if [ -f "$FILE" ]; then
|
||||
bin/setup system:config set registry.general.title $PHRASEANET_PROJECT_NAME
|
||||
echo "$FILE exists, skip setup."
|
||||
else
|
||||
echo "$FILE doesn't exist, entering setup..."
|
||||
|
@@ -43,6 +43,7 @@ use Silex\ServiceProviderInterface;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\HttpKernel\KernelEvents;
|
||||
|
||||
|
||||
class SearchEngineServiceProvider implements ServiceProviderInterface
|
||||
{
|
||||
public function register(Application $app)
|
||||
@@ -145,6 +146,7 @@ class SearchEngineServiceProvider implements ServiceProviderInterface
|
||||
|
||||
$app['elasticsearch.indexer.databox_fetcher_factory'] = $app->share(function ($app) {
|
||||
return new DataboxFetcherFactory(
|
||||
$app['conf'],
|
||||
$app['elasticsearch.record_helper'],
|
||||
$app['elasticsearch.options'],
|
||||
$app,
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Alchemy\Phrasea\SearchEngine\Elastic;
|
||||
|
||||
use Alchemy\Phrasea\Core\Configuration\PropertyAccess;
|
||||
use Alchemy\Phrasea\SearchEngine\Elastic\Indexer\Record\Delegate\FetcherDelegateInterface;
|
||||
use Alchemy\Phrasea\SearchEngine\Elastic\Indexer\Record\Fetcher;
|
||||
use Alchemy\Phrasea\SearchEngine\Elastic\Indexer\Record\Hydrator\CoreHydrator;
|
||||
@@ -13,8 +14,14 @@ use Alchemy\Phrasea\SearchEngine\Elastic\Indexer\Record\Hydrator\TitleHydrator;
|
||||
use Alchemy\Phrasea\SearchEngine\Elastic\Structure\Structure;
|
||||
use Alchemy\Phrasea\SearchEngine\Elastic\Thesaurus\CandidateTerms;
|
||||
|
||||
|
||||
class DataboxFetcherFactory
|
||||
{
|
||||
/**
|
||||
* @var PropertyAccess phraseanet configuration
|
||||
*/
|
||||
private $conf;
|
||||
|
||||
/**
|
||||
* @var \ArrayAccess
|
||||
*/
|
||||
@@ -39,14 +46,16 @@ class DataboxFetcherFactory
|
||||
private $options;
|
||||
|
||||
/**
|
||||
* @param PropertyAccess $conf
|
||||
* @param RecordHelper $recordHelper
|
||||
* @param ElasticsearchOptions $options
|
||||
* @param \ArrayAccess $container
|
||||
* @param string $structureKey
|
||||
* @param string $thesaurusKey
|
||||
*/
|
||||
public function __construct(RecordHelper $recordHelper, ElasticsearchOptions $options, \ArrayAccess $container, $structureKey, $thesaurusKey)
|
||||
public function __construct(PropertyAccess $conf, RecordHelper $recordHelper, ElasticsearchOptions $options, \ArrayAccess $container, $structureKey, $thesaurusKey)
|
||||
{
|
||||
$this->conf = $conf;
|
||||
$this->recordHelper = $recordHelper;
|
||||
$this->options = $options;
|
||||
$this->container = $container;
|
||||
@@ -70,7 +79,7 @@ class DataboxFetcherFactory
|
||||
[
|
||||
new CoreHydrator($databox->get_sbas_id(), $databox->get_viewname(), $this->recordHelper),
|
||||
new TitleHydrator($connection, $this->recordHelper),
|
||||
new MetadataHydrator($connection, $this->getStructure(), $this->recordHelper),
|
||||
new MetadataHydrator($this->conf, $connection, $this->getStructure(), $this->recordHelper),
|
||||
new FlagHydrator($this->getStructure(), $databox),
|
||||
new ThesaurusHydrator($this->getStructure(), $this->getThesaurus(), $candidateTerms),
|
||||
new SubDefinitionHydrator($connection)
|
||||
|
@@ -15,6 +15,7 @@ use Assert\Assertion;
|
||||
|
||||
class GpsPosition
|
||||
{
|
||||
const FULL_GEO_NOTATION = 'FullNotation';
|
||||
const LONGITUDE_TAG_NAME = 'Longitude';
|
||||
const LONGITUDE_REF_TAG_NAME = 'LongitudeRef';
|
||||
const LONGITUDE_REF_WEST = 'W';
|
||||
@@ -29,6 +30,16 @@ class GpsPosition
|
||||
private $latitude;
|
||||
private $latitude_ref;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->clear();
|
||||
}
|
||||
|
||||
public function clear()
|
||||
{
|
||||
$this->longitude = $this->longitude_ref = $this->latitude = $this->latitude_ref = null;
|
||||
}
|
||||
|
||||
public function set($tag_name, $value)
|
||||
{
|
||||
switch ($tag_name) {
|
||||
@@ -64,6 +75,53 @@ class GpsPosition
|
||||
$this->latitude_ref = $normalized;
|
||||
break;
|
||||
|
||||
case self::FULL_GEO_NOTATION:
|
||||
$re = '/(-?\d+(?:\.\d+)?°?)\s*(\d+(?:\.\d+)?\')?\s*(\d+(?:\.\d+)?")?\s*(N|S|E|W)?/um';
|
||||
$normalized = trim(strtoupper($value));
|
||||
$matches = null;
|
||||
preg_match_all($re, $normalized, $matches, PREG_SET_ORDER, 0);
|
||||
if(count($matches) === 2) { // we need lat and lon
|
||||
$lat = $lon = null;
|
||||
foreach ($matches as $imatch => $match) {
|
||||
if(count($match) != 5) {
|
||||
continue;
|
||||
}
|
||||
$v = 0.0;
|
||||
for($part=1, $div=1.0; $part<=3; $part++, $div*=60.0) {
|
||||
$v += floatval($match[$part]) / $div;
|
||||
}
|
||||
switch($match[4]) { // N S E W
|
||||
case 'N':
|
||||
$lat = $v;
|
||||
break;
|
||||
case 'S':
|
||||
$lat = -$v;
|
||||
break;
|
||||
case 'E':
|
||||
$lon = $v;
|
||||
break;
|
||||
case 'W':
|
||||
$lon = -$v;
|
||||
break;
|
||||
case '': // no ref -> lat lon (first=lat, second=lon)
|
||||
if($imatch === 0) {
|
||||
$lat = $v;
|
||||
}
|
||||
else {
|
||||
$lon = $v;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new \InvalidArgumentException(sprintf('Unsupported reference "%s", should be N|S|E|W.', $match[4]));
|
||||
}
|
||||
}
|
||||
if($lat !== null && $lon != null) {
|
||||
$this->set(self::LATITUDE_TAG_NAME, $lat);
|
||||
$this->set(self::LONGITUDE_TAG_NAME, $lon);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \InvalidArgumentException(sprintf('Unsupported tag name "%s".', $tag_name));
|
||||
}
|
||||
@@ -95,19 +153,11 @@ class GpsPosition
|
||||
|
||||
public function getCompositeLongitude()
|
||||
{
|
||||
if ($this->longitude === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->longitude ;
|
||||
}
|
||||
|
||||
public function getCompositeLatitude()
|
||||
{
|
||||
if ($this->latitude === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->latitude;
|
||||
}
|
||||
|
||||
|
@@ -11,6 +11,7 @@
|
||||
|
||||
namespace Alchemy\Phrasea\SearchEngine\Elastic\Indexer\Record\Hydrator;
|
||||
|
||||
use Alchemy\Phrasea\Core\Configuration\PropertyAccess;
|
||||
use Alchemy\Phrasea\SearchEngine\Elastic\Exception\Exception;
|
||||
use Alchemy\Phrasea\SearchEngine\Elastic\FieldMapping;
|
||||
use Alchemy\Phrasea\SearchEngine\Elastic\Mapping;
|
||||
@@ -24,28 +25,48 @@ use InvalidArgumentException;
|
||||
|
||||
class MetadataHydrator implements HydratorInterface
|
||||
{
|
||||
private $conf;
|
||||
private $connection;
|
||||
private $structure;
|
||||
private $helper;
|
||||
|
||||
private $gps_position_buffer = [];
|
||||
private $position_fields_mapping; // get from conf
|
||||
|
||||
public function __construct(DriverConnection $connection, Structure $structure, RecordHelper $helper)
|
||||
private $caption_gps_position;
|
||||
private $exif_gps_position;
|
||||
|
||||
public function __construct(PropertyAccess $conf, DriverConnection $connection, Structure $structure, RecordHelper $helper)
|
||||
{
|
||||
$this->conf = $conf;
|
||||
$this->connection = $connection;
|
||||
$this->structure = $structure;
|
||||
$this->helper = $helper;
|
||||
|
||||
// get the fieldnames of source of lat / lon geo fields (defined in instance conf)
|
||||
$this->position_fields_mapping = [];
|
||||
foreach($conf->get(['geocoding-providers'], []) as $provider) {
|
||||
if($provider['enabled'] && array_key_exists('position-fields', $provider)) {
|
||||
foreach ($provider['position-fields'] as $position_field) {
|
||||
$this->position_fields_mapping[$position_field['name']] = $position_field['type'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->caption_gps_position = new GpsPosition();
|
||||
$this->exif_gps_position = new GpsPosition();
|
||||
}
|
||||
|
||||
public function hydrateRecords(array &$records)
|
||||
{
|
||||
$sql = "(SELECT record_id, ms.name AS `key`, m.value AS value, 'caption' AS type, ms.business AS private\n"
|
||||
$sql = "SELECT * FROM ("
|
||||
. "(SELECT record_id, ms.name AS `key`, m.value AS value, 'caption' AS type, ms.business AS private\n"
|
||||
. " FROM metadatas AS m INNER JOIN metadatas_structure AS ms ON (ms.id = m.meta_struct_id)\n"
|
||||
. " WHERE record_id IN (?))\n"
|
||||
. "UNION\n"
|
||||
. "(SELECT record_id, t.name AS `key`, t.value AS value, 'exif' AS type, 0 AS private\n"
|
||||
. " FROM technical_datas AS t\n"
|
||||
. " WHERE record_id IN (?))\n";
|
||||
. " WHERE record_id IN (?))\n"
|
||||
. ") AS t ORDER BY record_id";
|
||||
|
||||
$ids = array_keys($records);
|
||||
$statement = $this->connection->executeQuery(
|
||||
@@ -54,7 +75,17 @@ class MetadataHydrator implements HydratorInterface
|
||||
array(Connection::PARAM_INT_ARRAY, Connection::PARAM_INT_ARRAY)
|
||||
);
|
||||
|
||||
$record_id = -1;
|
||||
while ($metadata = $statement->fetch()) {
|
||||
|
||||
if($metadata['record_id'] !== $record_id) {
|
||||
// record has changed, don't mix with previous one
|
||||
$this->caption_gps_position->clear();
|
||||
$this->exif_gps_position->clear();
|
||||
|
||||
$record_id = $metadata['record_id'];
|
||||
}
|
||||
|
||||
// Store metadata value
|
||||
$key = $metadata['key'];
|
||||
$value = trim($metadata['value']);
|
||||
@@ -64,10 +95,10 @@ class MetadataHydrator implements HydratorInterface
|
||||
continue;
|
||||
}
|
||||
|
||||
$id = $metadata['record_id'];
|
||||
if (isset($records[$id])) {
|
||||
$record =& $records[$id];
|
||||
} else {
|
||||
if (isset($records[$record_id])) {
|
||||
$record =& $records[$record_id];
|
||||
}
|
||||
else {
|
||||
throw new Exception('Received metadata from unexpected record');
|
||||
}
|
||||
|
||||
@@ -89,11 +120,31 @@ class MetadataHydrator implements HydratorInterface
|
||||
$record[$field] = array();
|
||||
}
|
||||
$record[$field][] = $value;
|
||||
|
||||
if(array_key_exists($key, $this->position_fields_mapping)) {
|
||||
// this field is mapped as a position part (lat, lon, latlon), push it
|
||||
switch($this->position_fields_mapping[$key]) {
|
||||
case 'lat':
|
||||
$this->handleGpsPosition($this->caption_gps_position, $record, GpsPosition::LATITUDE_TAG_NAME, $value);
|
||||
break;
|
||||
case 'lng':
|
||||
case 'lon':
|
||||
$this->handleGpsPosition($this->caption_gps_position, $record, GpsPosition::LONGITUDE_TAG_NAME, $value);
|
||||
break;
|
||||
case 'latlng':
|
||||
case 'latlon':
|
||||
$this->handleGpsPosition($this->caption_gps_position, $record, GpsPosition::FULL_GEO_NOTATION, $value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'exif':
|
||||
if (GpsPosition::isSupportedTagName($key)) {
|
||||
$this->handleGpsPosition($records, $id, $key, $value);
|
||||
// exif gps is a first-chance if caption is not yet set
|
||||
// anyway if caption is set later, it will override the exif values
|
||||
if (GpsPosition::isSupportedTagName($key) && !$this->caption_gps_position->isCompleteComposite()) {
|
||||
$this->handleGpsPosition($this->exif_gps_position, $record, $key, $value);
|
||||
break;
|
||||
}
|
||||
$tag = $this->structure->getMetadataTagByName($key);
|
||||
@@ -109,38 +160,25 @@ class MetadataHydrator implements HydratorInterface
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->clearGpsPositionBuffer();
|
||||
}
|
||||
|
||||
private function handleGpsPosition(&$records, $id, $tag_name, $value)
|
||||
private function handleGpsPosition(GpsPosition &$position, &$record, $tag_name, $value)
|
||||
{
|
||||
// Get position object
|
||||
if (!isset($this->gps_position_buffer[$id])) {
|
||||
$this->gps_position_buffer[$id] = new GpsPosition();
|
||||
}
|
||||
$position = $this->gps_position_buffer[$id];
|
||||
// Push this tag into object
|
||||
$position->set($tag_name, $value);
|
||||
|
||||
// Try to output complete position
|
||||
if ($position->isCompleteComposite()) {
|
||||
$lon = $position->getCompositeLongitude();
|
||||
$lat = $position->getCompositeLatitude();
|
||||
|
||||
$records[$id]['metadata_tags']['Longitude'] = $lon;
|
||||
$records[$id]['metadata_tags']['Latitude'] = $lat;
|
||||
$record['metadata_tags']['Longitude'] = $lon;
|
||||
$record['metadata_tags']['Latitude'] = $lat;
|
||||
|
||||
$records[$id]["location"] = [
|
||||
$record["location"] = [
|
||||
"lat" => $lat,
|
||||
"lon" => $lon
|
||||
];
|
||||
|
||||
unset($this->gps_position_buffer[$id]);
|
||||
}
|
||||
}
|
||||
|
||||
private function clearGpsPositionBuffer()
|
||||
{
|
||||
$this->gps_position_buffer = [];
|
||||
}
|
||||
}
|
||||
|
@@ -79,7 +79,7 @@
|
||||
<size>748</size>
|
||||
<mediatype>video</mediatype>
|
||||
<writeDatas>yes</writeDatas>
|
||||
<acodec>libmp3lame</acodec>
|
||||
<acodec>libfdk_aac</acodec>
|
||||
<vcodec>libx264</vcodec>
|
||||
<devices>screen</devices>
|
||||
<bitrate>1000</bitrate>
|
||||
|
@@ -79,7 +79,7 @@
|
||||
<size>748</size>
|
||||
<mediatype>video</mediatype>
|
||||
<writeDatas>yes</writeDatas>
|
||||
<acodec>libmp3lame</acodec>
|
||||
<acodec>libfdk_aac</acodec>
|
||||
<vcodec>libx264</vcodec>
|
||||
<devices>screen</devices>
|
||||
<bitrate>1000</bitrate>
|
||||
|
@@ -79,7 +79,7 @@
|
||||
<size>748</size>
|
||||
<mediatype>video</mediatype>
|
||||
<writeDatas>yes</writeDatas>
|
||||
<acodec>libmp3lame</acodec>
|
||||
<acodec>libfdk_aac</acodec>
|
||||
<vcodec>libx264</vcodec>
|
||||
<devices>screen</devices>
|
||||
<bitrate>1000</bitrate>
|
||||
|
Reference in New Issue
Block a user