<?php
declare(strict_types=1);
namespace Elements\Bundle\AlpsteinBundle\Command;
use Carbon\Carbon;
use Elements\Bundle\AlpsteinBundle\Services\AlpsteinConfig;
use Elements\Bundle\RecurringDatesTypeBundle\Model\RecurringDateDefinition;
use GuzzleHttp\Client;
use Pimcore\Console\AbstractCommand;
use Pimcore\Console\Traits\DryRun;
use Pimcore\Db;
use Pimcore\Log\ApplicationLogger;
use Pimcore\Model\Asset\Image;
use Pimcore\Model\DataObject;
use Pimcore\Model\DataObject\AlpsteinPoi;
use Pimcore\Model\DataObject\AlpsteinProperty;
use Pimcore\Model\DataObject\AlpsteinRegion;
use Pimcore\Model\DataObject\AlpsteinRegionCategory;
use Pimcore\Model\DataObject\AlpsteinTour;
use Pimcore\Model\DataObject\AlpsteinKey;
use Pimcore\Model\DataObject\AlpsteinVideo;
use Pimcore\Model\DataObject\Data\Geobounds;
use Pimcore\Model\DataObject\Data\GeoCoordinates;
use Pimcore\Model\DataObject\Data\ObjectMetadata;
use Pimcore\Model\DataObject\Data\Video;
use Pimcore\Model\DataObject\AlpsteinCategory;
use Pimcore\Model\DataObject\Service;
use Pimcore\Model\DataObject\ULicense;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class ImportCommand extends AbstractCommand
{
use DryRun;
const TIMESTAMPFILE = '/alpstein_import_timestamp.tmp';
protected $alpsteinConfig;
protected $defaultLicense;
protected $doRemoveICCProfile;
protected $minimumRanking;
protected $importOnlyCCCompliant;
protected $validLanguage = [];
protected $categoryFolder;
protected $regionCache;
protected $regionFolder;
protected $regionCategoryFolder;
protected $tourFolder;
protected $poiFolder;
protected $videosFolder;
protected $assetIconFolder;
protected $assetImageFolder = '/Alpstein/Images/';
protected $assetImageFolderObject;
protected $assetPropertiesFolder;
protected $objectPropertiesFolder;
protected $objectKeyFolder;
protected $importedTourIds = [];
protected $importedPoiIds = [];
protected $importedRegions = [];
protected $options = [];
protected $numToursPerImportIteration = 0;
protected $importTime = 0;
/**
* @var Client
*/
private $client;
private ApplicationLogger $applicationLogger;
protected function configure()
{
$this
->setName('alpstein:import')
->setDescription('Migrate existing structure to new file extensions')
->addOption('full', 'f', null, 'start Full Import')
->addOption('regions', 'r', null, 'also includes regions in Import')
->addOption('pois', 'p', null, 'also includes pois in Import')
->addOption('override', 'o', null, 'Override Images')
->addOption('delta', 'd', null, 'Only Import changed Tours')
->addOption('skip-images', null, null, 'Ignore Images')
->addOption('tourId', null, InputOption::VALUE_OPTIONAL, 'Import selected Tour only')
->addOption('tours-per-iterations', null, InputOption::VALUE_OPTIONAL, 'Import the tours in smaller packages, the value is the number of tours per package. Use 0 for not splitting tours into packages', 0)
;
$this->configureDryRunOption();
}
/**
* ImportCommand constructor.
* @param AlpsteinConfig $alpsteinConfig
* @param Client $client
*/
public function __construct(AlpsteinConfig $alpsteinConfig, Client $client, ApplicationLogger $applicationLogger)
{
parent::__construct();
$this->alpsteinConfig = $alpsteinConfig->getConfig();
$this->doRemoveICCProfile = $alpsteinConfig->doRemoveICCProfile();
$this->minimumRanking = $alpsteinConfig->getMinimumRanking();
$this->importOnlyCCCompliant = $alpsteinConfig->getImportOnlyCCCompliant();
$this->client = $client;
$this->applicationLogger = $applicationLogger;
}
/**
* @param InputInterface $input
* @param OutputInterface $output
* @return int|null|void
* @throws \GuzzleHttp\Exception\GuzzleException
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
if( $input->getOption('full') ){
$this->options[] = 'full';
}
if( $input->getOption('regions') ){
$this->options[] = 'regions';
}
if( $input->getOption('pois') ){
$this->options[] = 'pois';
}
if( $input->getOption('override') ){
$this->options[] = 'override';
}
if( $input->getOption('delta') ){
$this->options[] = 'delta';
}
if( $input->getOption('skip-images') ){
$this->options[] = 'skip-images';
}
if($input->getOption('tours-per-iterations')) {
$this->numToursPerImportIteration = (int)$input->getOption('tours-per-iterations');
}
$tourId = $input->getOption('tourId');
$this->validLanguage = ['de'];
foreach( \Pimcore\Tool::getValidLanguages() as $lang ){
if( $lang != 'de' ){
$this->validLanguage[] = $lang;
}
}
$defaultLicense = ULicense::getByCode('AlpsteinDefault', 1);
if (!$defaultLicense instanceof ULicense) {
$defaultLicense = new ULicense();
$defaultLicense->setKey('AlpsteinDefaultLicense');
$defaultLicense->setParent(Service::createFolderByPath('Alpstein/License'));
$defaultLicense->setPublished(true);
$defaultLicense->setCode('AlpsteinDefault');
$defaultLicense->setName('Outdooractive AGB', 'de');
$defaultLicense->setName('Outdooractive Terms of Service', 'en');
$defaultLicense->save();
}
$this->defaultLicense = $defaultLicense;
$this->categoryFolder = Service::createFolderByPath('/Alpstein/Categories');
$this->regionFolder = Service::createFolderByPath('/Alpstein/Regions');
$this->regionCategoryFolder = Service::createFolderByPath('/Alpstein/RegionCategories');
$this->assetIconFolder = \Pimcore\Model\Asset\Service::createFolderByPath('/Alpstein/Icons');
$this->tourFolder = Service::createFolderByPath('/Alpstein/Tour');
$this->poiFolder = Service::createFolderByPath('/Alpstein/Poi');
$this->assetImageFolderObject = \Pimcore\Model\Asset\Service::createFolderByPath( $this->assetImageFolder );
$this->assetPropertiesFolder = \Pimcore\Model\Asset\Service::createFolderByPath( '/Alpstein/Properties');
$this->objectPropertiesFolder = Service::createFolderByPath( '/Alpstein/Properties');
$this->videosFolder = Service::createFolderByPath( '/Alpstein/Videos');
$this->objectKeyFolder = Service::createFolderByPath( '/Alpstein/Key');
$this->importTime = time();
try {
if( is_array($this->alpsteinConfig['project']) ){
foreach( $this->alpsteinConfig['project'] as $key => $project ){
$alpsteinConfig = [
'project' => $project,
'apiKey' => $this->alpsteinConfig['apiKey'][$key]
];
$alpsteinConfig['keyObject'] = $this->createAndGetKey( $alpsteinConfig['project'], $alpsteinConfig['apiKey'] );
$this->importCategories( $alpsteinConfig );
if ($tourId != '') {
$this->importSingleTour($tourId, $alpsteinConfig);
} else {
if (in_array('regions', $this->options)) {
$this->importRegions( $alpsteinConfig );
}
if (in_array('pois', $this->options)) {
$this->importPois( $alpsteinConfig );
}
$this->importTours( $alpsteinConfig );
}
}
} else {
$this->alpsteinConfig['keyObject'] = $this->createAndGetKey( $this->alpsteinConfig['project'], $this->alpsteinConfig['apiKey'] );
if ($tourId != '') {
$this->importSingleTour($tourId, $this->alpsteinConfig);
} else {
$this->importCategories( $this->alpsteinConfig );
if (in_array('regions', $this->options)) {
$this->importRegions( $this->alpsteinConfig );
}
if (in_array('pois', $this->options)) {
$this->importPois( $this->alpsteinConfig );
}
$this->importTours( $this->alpsteinConfig );
}
}
if (!empty($this->importedTourIds) && !in_array('delta', $this->options) && $tourId == '') {
$tours = new AlpsteinTour\Listing();
$tours->addConditionParam('alpsteinId IS NOT NULL AND alpsteinId != "" AND alpsteinId NOT IN (' . implode(',', $this->importedTourIds) . ')');
foreach ($tours as $tour) {
$tour->setPublished(false);
$tour->save();
}
}
} catch (\Exception $exception) {
$this->applicationLogger->info("Error:\n{$exception->getMessage()}\n\n{$exception->getTraceAsString()}", ['component' => 'AlpsteinImportCommand']);
}
if ($tourId == '') {
file_put_contents(PIMCORE_PRIVATE_VAR . self::TIMESTAMPFILE, $this->importTime);
}
return 0;
}
/**
* @param $project
* @param $apiKey
* @return AlpsteinKey|AlpsteinKey\Listing
* @throws \Exception
*/
private function createAndGetKey( $project, $apiKey ){
$keyObject = AlpsteinKey::getByApiKey( $apiKey, ['limit' => 1] );
if( !$keyObject instanceof AlpsteinKey ){
$keyObject = new AlpsteinKey();
$keyObject->setName($project);
$keyObject->setApiKey($apiKey);
$keyObject->setKey( \Pimcore\File::getValidFilename($project . '-' . $apiKey) );
$keyObject->setParent( $this->objectKeyFolder );
$keyObject->setPublished( true );
$keyObject->save();
}
return $keyObject;
}
/**
* Import Categories
* @param $alpsteinConfig
* @throws \GuzzleHttp\Exception\GuzzleException
*/
private function importCategories( $alpsteinConfig )
{
foreach( $this->validLanguage as $language ){
$url = 'https://www.outdooractive.com/api/project/' . $alpsteinConfig['project'] . '/category/tree?lang=' . $language . '&key=' . $alpsteinConfig['apiKey'];
$client = $this->client;
$requestType = 'GET';
$config = [
\GuzzleHttp\RequestOptions::ALLOW_REDIRECTS => [
'max' => 2
],
\GuzzleHttp\RequestOptions::TIMEOUT => 60
];
$config[\GuzzleHttp\RequestOptions::HEADERS] = [
'Accept' => 'application/json'
];
/**
* @var $response \GuzzleHttp\Psr7\Response
*/
try {
$response = $client->request($requestType, $url, $config);
} catch (\Throwable $exception) {
$this->dump('################### ERROR ###################');
$this->dump($exception->getMessage());
$this->dump($exception->getTraceAsString());
$this->dump('################### ERROR ###################');
}
if ($response && $response->getStatusCode() == 200) {
$data = $response->getBody();
$categoryArray = json_decode( $data->getContents() );
foreach( $categoryArray as $itemArray ){
// Top Category
foreach( $itemArray as $item ){
$parentId = $this->createCategory( $item, $alpsteinConfig['keyObject'], $this->categoryFolder->getId(), $language );
// Sub Category
foreach( $item->category ?? [] as $subCategory ){
$this->createCategory( $subCategory, $alpsteinConfig['keyObject'], $parentId, $language );
}
}
}
}
}
}
/**
* Import Categories
* @param $alpsteinConfig
* @throws \GuzzleHttp\Exception\GuzzleException
*/
private function importRegions( $alpsteinConfig )
{
foreach( $this->validLanguage as $language ){
$url = 'https://www.outdooractive.com/api/project/' . $alpsteinConfig['project'] . '/region/tree?lang=' . $language . '&key=' . $alpsteinConfig['apiKey'];
$client = $this->client;
$requestType = 'GET';
$config = [
\GuzzleHttp\RequestOptions::ALLOW_REDIRECTS => [
'max' => 2
],
\GuzzleHttp\RequestOptions::TIMEOUT => 60
];
$config[\GuzzleHttp\RequestOptions::HEADERS] = [
'Accept' => 'application/json'
];
/**
* @var $response \GuzzleHttp\Psr7\Response
*/
try {
$response = $client->request($requestType, $url, $config);
} catch (\Throwable $exception) {
$this->dump('################### ERROR ###################');
$this->dump($exception->getMessage());
$this->dump($exception->getTraceAsString());
$this->dump('################### ERROR ###################');
}
if ($response && $response->getStatusCode() == 200) {
$data = $response->getBody();
$regionArray = json_decode( $data->getContents() );
foreach( $regionArray->region as $regionData ){
$this->createRegion($regionData, $this->regionFolder->getId(), $language, $alpsteinConfig['keyObject']);
}
}
}
}
/**
* @param $item
* @param null $parentId
* @param string $language
* @param $keyObject AlpsteinKey
* @return int
* @throws \Exception
*/
private function createCategory( $item, $keyObject, $parentId = null, $language = 'de' ){
$category = AlpsteinCategory::getByCategoryId( (int)$item->id, 1 );
if( !$category instanceof AlpsteinCategory ){
$category = new AlpsteinCategory();
$category->setParentId( $parentId );
$category->setPublished( true );
$category->setKey( \Pimcore\File::getValidFilename( $item->name . '-' . $item->id ) );
$category->setCategoryId((int)$item->id);
if( $language == 'de' && !$category->getIcon() instanceof Image ){
if( isset($item->iconUrl) ){
preg_match('/^.*\.(jpg|jpeg|png|gif|svg)$/i', $item->iconUrl, $reg);
$imageName = \Pimcore\File::getValidFilename( $item->name . '-' . $item->id ) . '.' . $reg[1];
$image = Image::getByPath( $this->assetIconFolder->getFullPath() . '/' . $imageName );
if( !$image instanceof Image ){
try {
$iconUrl = \Pimcore\Tool::getHttpData($item->iconUrl, [], [], ['timeout' => 60]);
} catch (\Throwable $exception) {
$this->dump('################### ERROR ###################');
$this->dump($exception->getMessage());
$this->dump($exception->getTraceAsString());
$this->dump('################### ERROR ###################');
}
if( $iconUrl ){
$image = new Image();
$image->setData( $iconUrl );
$image->setFilename( $imageName = \Pimcore\File::getValidFilename( $item->name . '-' . $item->id ) . '.' . $reg[1] );
$image->setParent( $this->assetIconFolder );
$image->save();
$category->setIcon($image);
}
}else{
$category->setIcon($image);
}
}
}
}
$catAlpsteinKeys = $category->getAlpsteinKey();
$hasKey = false;
foreach( $catAlpsteinKeys as $keyObj ){
if( $keyObj->getApiKey() == $keyObject->getApiKey() ){
$hasKey = true;
break;
}
}
if( !$hasKey ){
$catAlpsteinKeys[] = $keyObject;
}
$category->setAlpsteinKey( $catAlpsteinKeys );
$category->setModificationDate( time() );
$category->setName( $item->name, $language );
$category->save();
return $category->getId();
}
/**
* @param $regionData
* @param $parentId
* @param string $language
* @param $keyObject AlpsteinKey
* @throws \Exception
*/
private function createRegion( $regionData, $parentId, $language = 'de', $keyObject ){
if (array_key_exists($language, $this->importedRegions) && array_key_exists($regionData->id, $this->importedRegions[$language]) && ($region = $this->importedRegions[$language][$regionData->id])) {
return $region;
}
$region = AlpsteinRegion::getByAlpsteinId( (int)$regionData->id, 1 );
if( !$region instanceof AlpsteinRegion ){
$region = new AlpsteinRegion();
$region->setParentId( $parentId );
$region->setPublished( true );
$region->setKey( \Pimcore\File::getValidFilename( $regionData->name . '-' . $regionData->id ) );
$region->setAlpsteinId((int)$regionData->id);
}
$alpsteinKeys = $region->getAlpsteinKey();
$hasKey = false;
foreach( $alpsteinKeys as $keyObj ){
if( $keyObj->getApiKey() == $keyObject->getApiKey() ){
$hasKey = true;
break;
}
}
if( !$hasKey ){
$alpsteinKeys[] = $keyObject;
}
$region->setAlpsteinKey( $alpsteinKeys );
$region->setModificationDate( time() );
$region->setName( $regionData->name, $language );
$region->setRegionType( $regionData->type );
$region->setLevel( $regionData->level );
$region->setHasTour($regionData->hasTour);
if ($regionData->bbox) {
$geodata = explode(',', $regionData->bbox);
$southWest = new GeoCoordinates($geodata[1], $geodata[0]);
$northEast = new GeoCoordinates($geodata[3], $geodata[2]);
$bbox = new Geobounds($northEast, $southWest);
$region->setBbox($bbox);
}
$region->setCategory($this->createRegionCategory($regionData->categoryId, $regionData->categoryTitle, $language, $keyObject));
$region->save();
$subregions = $region->getSubRegions();
$containingRegions = [];
foreach ($subregions ?: [] as $subRegionObj) {
$containingRegions[] = $subRegionObj->getAlpsteinId();
}
if (!empty($regionData->region)) {
foreach ($regionData->region as $subRegionData) {
$subRegion = $this->createRegion($subRegionData, $region->getId(), $language, $keyObject);
if (!in_array($subRegion->getAlpsteinId(), $containingRegions)) {
$subregions[] = $subRegion;
$containingRegions[] = $subRegion->getAlpsteinId();
}
}
}
$region->setSubRegions($subregions);
$region->save();
$this->importedRegions[$language][$regionData->id] = $region;
return $region;
}
/**
* @param $regionCategoryId
* @param $regionCategoryName
* @param string $language
* @param $keyObject AlpsteinKey
* @return AlpsteinRegionCategory
* @throws \Exception
*/
private function createRegionCategory( $regionCategoryId, $regionCategoryName, $language = 'de', $keyObject ){
$regionCategory = AlpsteinRegionCategory::getByAlpsteinId( (int)$regionCategoryId, 1 );
if( !$regionCategory instanceof AlpsteinRegionCategory ){
$regionCategory = new AlpsteinRegionCategory();
$regionCategory->setParentId( $this->regionCategoryFolder->getId() );
$regionCategory->setPublished( true );
$regionCategory->setKey( \Pimcore\File::getValidFilename( $regionCategoryName . '-' . $regionCategoryId ) );
$regionCategory->setAlpsteinId((int)$regionCategoryId);
}
$alpsteinKeys = $regionCategory->getAlpsteinKey();
$hasKey = false;
foreach( $alpsteinKeys as $keyObj ){
if( $keyObj->getApiKey() == $keyObject->getApiKey() ){
$hasKey = true;
break;
}
}
if( !$hasKey ){
$alpsteinKeys[] = $keyObject;
}
$regionCategory->setAlpsteinKey( $alpsteinKeys );
$regionCategory->setName( $regionCategoryName, $language );
$regionCategory->setModificationDate( time() );
$regionCategory->save();
return $regionCategory;
}
private function importSingleTour ($tourObjectId, $alpsteinConfig) {
$tour = AlpsteinTour::getById($tourObjectId);
if ($tour instanceof AlpsteinTour) {
$lastImport = 0;
$importTimeStampFile = PIMCORE_PRIVATE_VAR . '/alpstein-single-import-' . $tourObjectId . '.txt';
if (file_exists($importTimeStampFile)) {
$lastImport = file_get_contents($importTimeStampFile);
}
if ($lastImport < strtotime('-2 hours')) {
file_put_contents((string)time(), $importTimeStampFile);
$tourId = $tour->getAlpsteinId();
foreach ($this->validLanguage as $language) {
$url = 'https://www.outdooractive.com/api/project/' . $alpsteinConfig['project'] . '/oois/' . $tourId . '?lang=' . $language . '&key=' . $alpsteinConfig['apiKey'];
$client = $this->client;
$requestType = 'GET';
$config = [
\GuzzleHttp\RequestOptions::ALLOW_REDIRECTS => [
'max' => 2
],
\GuzzleHttp\RequestOptions::TIMEOUT => 60
];
$config[\GuzzleHttp\RequestOptions::HEADERS] = [
'Accept' => 'application/json'
];
/**
* @var $response \GuzzleHttp\Psr7\Response
*/
try {
$response = $client->request($requestType, $url, $config);
} catch (\Throwable $exception) {
$this->dump('################### ERROR ###################');
$this->dump($exception->getMessage());
$this->dump($exception->getTraceAsString());
$this->dump('################### ERROR ###################');
}
if ($response && $response->getStatusCode() == 200) {
$data = $response->getBody();
$tourArray = json_decode($data->getContents());
if( $tourArray->tour[0] && in_array($language, $tourArray->tour[0]->meta->translation ) ){
$this->createTour( $tourArray->tour[0], $language, $alpsteinConfig['keyObject'] );
}
}
}
unlink($importTimeStampFile);
}
}
}
private function importTours( $alpsteinConfig ){
$tourIds = $this->importTourIdList($alpsteinConfig);
$tourIdPackages = $this->createTourIdPackages($tourIds);
$numPackages = count($tourIdPackages);
try {
foreach ($tourIdPackages as $key => $tourIds) {
$this->applicationLogger->info('Tour Import Package #' . $key+1 . "/{$numPackages}", ['component' => 'AlpsteinImportCommand']);
$this->dump("Importing package #" . ($key + 1) . "/{$numPackages}; package size: " . count($tourIds));
foreach ($this->validLanguage as $language) {
foreach ($tourIds as $tourId) {
$url = 'https://www.outdooractive.com/api/project/' . $alpsteinConfig['project'] . '/oois/' . $tourId . '?lang=' . $language . '&key=' . $alpsteinConfig['apiKey'];
$client = $this->client;
$requestType = 'GET';
$config = [
\GuzzleHttp\RequestOptions::ALLOW_REDIRECTS => [
'max' => 2
],
\GuzzleHttp\RequestOptions::TIMEOUT => 60
];
$config[\GuzzleHttp\RequestOptions::HEADERS] = [
'Accept' => 'application/json'
];
/**
* @var $response \GuzzleHttp\Psr7\Response
*/
try {
$response = $client->request($requestType, $url, $config);
} catch (\Throwable $exception) {
$this->dump('################### ERROR ###################');
$this->dump($exception->getMessage());
$this->dump($exception->getTraceAsString());
$this->dump('################### ERROR ###################');
}
if ($response && $response->getStatusCode() == 200) {
$data = $response->getBody();
$tourArray = json_decode($data->getContents());
if ($tourArray->tour[0] && in_array($language, $tourArray->tour[0]->meta->translation)) {
$this->createTour($tourArray->tour[0], $language, $alpsteinConfig['keyObject']);
}
}
$this->dump(" ");
}
}
\Pimcore::collectGarbage();
}
} catch (\Throwable $e) {
$this->applicationLogger->info("Error while importing tour\n{$e->getMessage()}\n\n{$e->getTraceAsString()}", ['component' => 'AlpsteinImportCommand']);
}
$this->dump('----> Done');
}
private function importPois( $alpsteinConfig ){
$poiIds = $this->importPoiIdList($alpsteinConfig);
foreach ($this->validLanguage as $language) {
foreach( $poiIds as $poiId ){
$url = 'https://www.outdooractive.com/api/project/' . $alpsteinConfig['project'] . '/oois/' . $poiId . '?lang=' . $language . '&key=' . $alpsteinConfig['apiKey'];
$client = $this->client;
$requestType = 'GET';
$config = [
\GuzzleHttp\RequestOptions::ALLOW_REDIRECTS => [
'max' => 2
],
\GuzzleHttp\RequestOptions::TIMEOUT => 60
];
$config[\GuzzleHttp\RequestOptions::HEADERS] = [
'Accept' => 'application/json'
];
/**
* @var $response \GuzzleHttp\Psr7\Response
*/
try {
$response = $client->request($requestType, $url, $config);
} catch (\Throwable $exception) {
$this->dump('################### ERROR ###################');
$this->dump($exception->getMessage());
$this->dump($exception->getTraceAsString());
$this->dump('################### ERROR ###################');
}
if ($response && $response->getStatusCode() == 200) {
$data = $response->getBody();
$poiArray = json_decode($data->getContents());
if( $poiArray->poi[0] && in_array($language, $poiArray->poi[0]->meta->translation ) ){
$this->createPoi( $poiArray->poi[0], $language, $alpsteinConfig['keyObject'] );
}
}
$this->dump(" ");
}
}
$this->dump('----> Done');
}
/**
* Import List of Id's
* @param string $language
* @return array
* @throws \GuzzleHttp\Exception\GuzzleException
*/
private function importTourIdList( $alpsteinConfig, $language = 'de' ) : array {
$tourIds = [];
$url = 'https://www.outdooractive.com/api/project/' . $alpsteinConfig['project'] . '/tours?key=' . $alpsteinConfig['apiKey'];
if (in_array('delta', $this->options) && file_exists(PIMCORE_PRIVATE_VAR . self::TIMESTAMPFILE)) {
$timestamp = Carbon::createFromTimestamp((int)file_get_contents(PIMCORE_PRIVATE_VAR . self::TIMESTAMPFILE));
$url .= '&lastModifiedAfter=' . $timestamp->format('d.m.Y');
}
$client = $this->client;
$requestType = 'GET';
$config = [
\GuzzleHttp\RequestOptions::ALLOW_REDIRECTS => [
'max' => 2
],
\GuzzleHttp\RequestOptions::TIMEOUT => 60
];
$config[\GuzzleHttp\RequestOptions::HEADERS] = [
'Accept' => 'application/json'
];
/**
* @var $response \GuzzleHttp\Psr7\Response
*/
try {
$response = $client->request($requestType, $url, $config);
} catch (\Throwable $exception) {
$this->dump('################### ERROR ###################');
$this->dump($exception->getMessage());
$this->dump($exception->getTraceAsString());
$this->dump('################### ERROR ###################');
$this->applicationLogger->info("error importing tour: \n{$exception->getMessage()}", ['component' => 'AlpsteinImportCommand']);
}
if ($response && $response->getStatusCode() == 200) {
$data = $response->getBody();
$tourArray = json_decode($data->getContents());
foreach ($tourArray->data ?? [] as $itemArray) {
$tourIds[] = $itemArray->id;
}
}
return $tourIds;
}
/**
* Import List of Id's
* @param string $language
* @return array
* @throws \GuzzleHttp\Exception\GuzzleException
*/
private function importPoiIdList( $alpsteinConfig, $language = 'de' ) : array {
$poiIds = [];
$url = 'https://www.outdooractive.com/api/project/' . $alpsteinConfig['project'] . '/pois?key=' . $alpsteinConfig['apiKey'];
if (in_array('delta', $this->options) && file_exists(PIMCORE_PRIVATE_VAR . self::TIMESTAMPFILE)) {
$timestamp = Carbon::createFromTimestamp((int)file_get_contents(PIMCORE_PRIVATE_VAR . self::TIMESTAMPFILE));
$url .= '&lastModifiedAfter=' . $timestamp->format('d.m.Y');
}
$client = $this->client;
$requestType = 'GET';
$config = [
\GuzzleHttp\RequestOptions::ALLOW_REDIRECTS => [
'max' => 2
],
\GuzzleHttp\RequestOptions::TIMEOUT => 60
];
$config[\GuzzleHttp\RequestOptions::HEADERS] = [
'Accept' => 'application/json'
];
/**
* @var $response \GuzzleHttp\Psr7\Response
*/
try {
$response = $client->request($requestType, $url, $config);
} catch (\Throwable $exception) {
$this->dump('################### ERROR ###################');
$this->dump($exception->getMessage());
$this->dump($exception->getTraceAsString());
$this->dump('################### ERROR ###################');
}
if ($response && $response->getStatusCode() == 200) {
$data = $response->getBody();
$poiArray = json_decode($data->getContents());
foreach ($poiArray->data as $itemArray) {
$poiIds[] = $itemArray->id;
}
}
return $poiIds;
}
// Create or Update Tour
private function createTour( $tour, $language = 'de', $keyObject ){
/** not yet considered Fields:
* - lineOptions
* - riskPotential
* - exposition
* - wayType
* - elements
* - difficulties
* - literature
* - maps
* - bookWorks
* - mapWorks
* - localizedTitle
* - type
* - frontendtype
* - license
*/
$tourObject = AlpsteinTour::getByAlpsteinId( (int)$tour->id, [ 'limit' => 1, 'unpublished' => true ] );
// ignore tours not meeting minimumRanking condition and unpublish if already exists
if ($this->minimumRanking && $tour->ranking < $this->minimumRanking) {
if ($tourObject instanceof AlpsteinTour) {
$tourObject->setPublished(false);
$tourObject->save();
}
return;
}
if( !$tourObject instanceof AlpsteinTour ){
$tourObject = new AlpsteinTour();
$tourObject->setKey( \Pimcore\File::getValidFilename( ($tour->title ?? 'no-title') . '-' . $tour->id ) );
$tourObject->setAlpsteinId( (int)$tour->id );
$tourObject->setParent( $this->tourFolder );
$tourObject->save();
}
$catAlpsteinKeys = $tourObject->getAlpsteinKey();
$hasKey = false;
foreach( $catAlpsteinKeys as $keyObj ){
if( $keyObj->getApiKey() == $keyObject->getApiKey() ){
$hasKey = true;
break;
}
}
if( !$hasKey ){
$catAlpsteinKeys[] = $keyObject;
}
$tourObject->setAlpsteinKey( $catAlpsteinKeys );
$this->dump('-> Tour: ' . $tourObject->getName('de') . '(' . $tourObject->getId() . ')');
$published = false;
if( $tour->meta->workflow->state == 'published' ){
$published = true;
}
if ($tourObject->getId() == '' ) {
p_r($tour->meta->workflow); die();
}
$tourObject->setPublished( $published );
$tourObject->setName( $tour->title ?? '', $language );
$tourObject->setRanking($tour->ranking ?? '');
// Destination
$tourObject->setDestination( $tour->destination ?? '', $language );
//ShortText
$tourObject->setShortText( $tour->shortText ?? '', $language );
// Longtext
$tourObject->setLongText( $tour->longText ?? '', $language );
// Import all Images and return an array [ primaryImage, allImages ]
$primaryId = null;
$primaryTitle = 'primaryImage';
if( isset($tour->primaryImage) && isset($tour->primaryImage->id) ){
$primaryId = $tour->primaryImage->id;
if(isset($tour->primaryImage->title)) {
$primaryTitle = $tour->primaryImage->title;
}
}
if (!in_array('skip-images', $this->options)) {
if( isset( $tour->images ) ){
$images = $this->loadAllImages( $tourObject, $tour->id, $tour->images->image, $primaryId, $language, $primaryTitle );
if( !is_null( $images[ 'primaryImage' ] ) ){
$tourObject->setPrimaryImage( $images[ 'primaryImage' ] );
}
if( !is_null( $images[ 'videos' ] ) ){
$tourObject->setVideos( $images[ 'videos' ] );
}
if( in_array( 'full', $this->options ) ){
if( !is_null( $images[ 'allImages' ] ) ){
$tourObject->setImages( $images[ 'allImages' ] );
}
}
}
}
// set Category
$category = AlpsteinCategory::getByCategoryId( $tour->category->id, [ 'limit' => 1, 'unpublished' => true ] );
if( $category ){
$tourObject->setCategory([ $category ]);
}
// Opened
if (isset( $tour->opened ) && $tour->opened !== null){
$tourObject->setOpened($tour->opened);
} else {
$tourObject->setOpened(true);
}
// -- Regions
$oldRegions = $tourObject->getRegions();
if( isset($tour->regions) && isset($tour->regions->region) ) {
$regions = [];
foreach ($tour->regions->region as $regionData) {
if (!isset($this->regionCache[$regionData->id]) instanceof AlpsteinRegion) {
$this->regionCache[$regionData->id] = AlpsteinRegion::getByAlpsteinId((string) $regionData->id, 1);
}
$region = $this->regionCache[$regionData->id];
if ($region instanceof AlpsteinRegion) {
$objectMetadata = new ObjectMetadata('regions', ['isStartingRegion'], $region);
$oldIsStartingRegion = null;
if($tourObject->getDoNotUpdateStartingRegion()) { //if not set, always update starting region
$oldIsStartingRegion = $this->getStartingRegionFromOldRegionsArray($region, $oldRegions);
}
if($oldIsStartingRegion === null) {
if (isset($regionData->isStartRegion)) {
$objectMetadata->setIsStartingRegion(true);
} else {
$objectMetadata->setIsStartingRegion(false);
}
} else { //old region did exist + getDoNotUpdateStartingRegion === true
$objectMetadata->setIsStartingRegion($oldIsStartingRegion);
}
$regions[] = $objectMetadata;
}
}
$tourObject->setRegions($regions);
}
// -- Texte
if( in_array( 'full', $this->options ) ){
// global
$tourObject->setStartingPointDesc( $tour->startingPointDescr ?? '', $language );
// transit
$tourObject->setPublicTransit( $tour->publicTransit ?? '', $language );
// getting There
$tourObject->setGettingThere( $tour->gettingThere ?? '', $language );
// parking
$tourObject->setParking( $tour->parking ?? '', $language );
// Safety Guide
$tourObject->setSafetyGuidlines( $tour->safetyGuidlines ?? '', $language );
// Tip
$tourObject->setTip( $tour->tip ?? '', $language );
// Additional Information
$tourObject->setEquipment( $tour->equipment ?? '', $language );
// Additional Information
$tourObject->setAdditionalInformation( $tour->additionalInformation ?? '', $language );
// Direction
$tourObject->setDirections( $tour->directions ?? '', $language);
// -- Labels
// top
$tourObject->setTop( $tour->labels->top ?? '' );
//publicTransportFriendly
if( isset( $tour->labels) ){
$tourObject->setPublicTransportFriendly( $tour->labels->publicTransportFriendly ?? '' );
}
// winter activity
$tourObject->setWinterActivity( $tour->winterActivity ?? '' );
// -- Data
// Publisher ID
$tourObject->setPublisherID( $tour->meta->source->id ?? '' );
// Time Min
$tourObject->setTimeMin( $tour->time->min ?? '' );
// Length
$tourObject->setLength( $tour->length ?? '' );
// Elevation
$tourObject->setElevationAscent( $tour->elevation->ascent ?? '' );
$tourObject->setElevationDescent( $tour->elevation->descent ?? '' );
$tourObject->setElevationMinAltitude( $tour->elevation->minAltitude ?? '' );
$tourObject->setElevationMaxAltitude( $tour->elevation->maxAltitude ?? '' );
$tourObject->setElevationProfileId( $tour->elevationProfile->id ?? '');
// Rating
$tourObject->setRatingCondition( $tour->rating->condition ?? '' );
$tourObject->setRatingDifficulty( $tour->rating->difficulty ?? '' );
$tourObject->setRatingTechnique( $tour->rating->technique ?? '' );
$tourObject->setRatingQualityExp( $tour->rating->qualityOfExperience ?? '' );
$tourObject->setRatingLandscape( $tour->rating->landscape ?? '' );
// -- Season
foreach( [ 'jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec' ] as $season ){
$setter = 'set' . ucfirst($season);
$tourObject->$setter( $tour->season->{$season} );
}
// -- License
$license = false;
if (isset($tour->meta) && isset($tour->meta->license)) {
$license = $this->getLicenseByFid($tour->meta->license->short);
}
if ($license) {
$tourObject->setProperty('ulicense_object', 'object', $license);
} else {
$tourObject->setProperty('ulicense_object', 'object', $this->defaultLicense);
}
$pois = [];
if( isset( $tour->pois ) ){
foreach ($tour->pois->poi ?? [] as $poi) {
$poiObject = AlpsteinPoi::getByAlpsteinId($poi->id, 1);
if ($poiObject instanceof AlpsteinPoi) {
$objectMetadata = new ObjectMetadata('pois', ['isElevationProfilePoi', 'isReststopPoi', 'isRecommendationPoi'], $poiObject);
if ($poi->isElevationProfilePoi ?? false) {
$objectMetadata->setIsElevationProfilePoi(true);
}
if ($poi->isReststopPoi ?? false) {
$objectMetadata->setIsReststopPoi(true);
}
if ($poi->isRecommendationPoi ?? false) {
$objectMetadata->setIsRecommendationPoi(true);
}
$pois[] = $objectMetadata;
}
}
}
$tourObject->setPois($pois);
// -- GEO
// Destination
$tourObject->setDestination( $tour->destination ?? '', $language );
// startingPoint
$startingGeo = new GeoCoordinates();
$startingGeo->setLatitude( $tour->startingPoint->lat );
$startingGeo->setLongitude( $tour->startingPoint->lon );
$tourObject->setStartingPoint( $startingGeo );
// geoPositions (tour)
$tourObject->setGeometry( $tour->geometry );
// -- Properties
if( isset( $tour->properties)){
$tourProperties = $this->tourProperties( $tour->properties->property ?? '', $language );
$tourObject->setTourProperties( $tourProperties );
}
} // end only full import
$tourObject->save();
$this->importedTourIds[] = $tourObject->getAlpsteinId();
}
// Create or Update Poi
private function createPoi( $poi, $language = 'de', $keyObject ){
/** not yet considered Fields:
* - frontendtype
* - license
*/
$poiObject = AlpsteinPoi::getByAlpsteinId( (int)$poi->id, [ 'limit' => 1, 'unpublished' => true ] );
// ignore tours not meeting minimumRanking condition and unpublish if already exists
if ($this->minimumRanking && $poi->ranking < $this->minimumRanking) {
if ($poiObject instanceof AlpsteinPoi) {
$poiObject->setPublished(false);
$poiObject->save();
}
return;
}
if( !$poiObject instanceof AlpsteinPoi ){
$poiObject = new AlpsteinPoi();
$poiObject->setKey( \Pimcore\File::getValidFilename( $poi->title . '-' . $poi->id ) );
$poiObject->setAlpsteinId( (int)$poi->id );
$poiObject->setParent( $this->poiFolder );
$poiObject->save();
}
$catAlpsteinKeys = $poiObject->getAlpsteinKey();
$hasKey = false;
foreach( $catAlpsteinKeys as $keyObj ){
if( $keyObj->getApiKey() == $keyObject->getApiKey() ){
$hasKey = true;
break;
}
}
if( !$hasKey ){
$catAlpsteinKeys[] = $keyObject;
}
$poiObject->setAlpsteinKey( $catAlpsteinKeys );
$this->dump('-> POI: ' . $poiObject->getName('de') . '(' . $poiObject->getId() . ')');
$published = false;
if( $poi->meta->workflow->state == 'published' ){
$published = true;
}
if ($poiObject->getId() == '' ) {
p_r($poi->meta->workflow); die();
}
$poiObject->setPublished( $published );
$poiObject->setName( $poi->title ?? '', $language );
$poiObject->setRanking($poi->ranking ?? '');
$poiObject->setFrontendType($poi->frontendtype ?? '');
//ShortText
$poiObject->setShortText( $poi->shortText ?? '', $language );
// Longtext
$poiObject->setLongText( $poi->longText ?? '', $language );
// Import all Images and return an array [ primaryImage, allImages ]
$primaryId = null;
$primaryTitle = 'primaryImage';
if( isset($poi->primaryImage) && isset($poi->primaryImage->id) ){
$primaryId = $poi->primaryImage->id;
if(isset($poi->primaryImage->title)) {
$primaryTitle = $poi->primaryImage->title;
}
}
if (!in_array('skip-images', $this->options)) {
if (isset($poi->images)) {
$images = $this->loadAllImages($poiObject, $poi->id, $poi->images->image, $primaryId, $language,
$primaryTitle);
if (!is_null($images['primaryImage'])) {
$poiObject->setPrimaryImage($images['primaryImage']);
}
if (!is_null($images['videos'])) {
$poiObject->setVideos($images['videos']);
}
if (in_array('full', $this->options)) {
if (!is_null($images['allImages'])) {
$poiObject->setImages($images['allImages']);
}
}
}
}
// set Category
$category = AlpsteinCategory::getByCategoryId( $poi->category->id, [ 'limit' => 1, 'unpublished' => true ] );
if( $category ){
$poiObject->setCategory([ $category ]);
}
// -- Labels
// top
$poiObject->setTop( $poi->labels->top ?? '' );
// winter activity
$poiObject->setWinterActivity( $poi->winterActivity ?? '' );
$poiObject->setAltitude( $poi->altitude ?? '' );
// contact data
$poiObject->setStreet($poi->address->street ?? '');
$poiObject->setZipcode($poi->address->zipcode ?? '');
$poiObject->setTown($poi->address->town ?? '');
$poiObject->setHomepage($poi->homepage ?? '');
$poiObject->setEmail($poi->email ?? '');
$poiObject->setPhone($poi->phone ?? '');
// Texte
$poiObject->setPublicTransit($poi->publicTransit ?? '', $language);
$poiObject->setGettingThere($poi->gettingThere ?? '', $language);
$poiObject->setParking($poi->parking ?? '', $language);
// Publisher ID
$poiObject->setPublisherID( $poi->meta->source->id ?? '');
// -- Regions
if( isset($poi->regions) && isset($poi->regions->region) ) {
$regions = [];
foreach ($poi->regions->region as $regionData) {
if (!isset($this->regionCache[$regionData->id]) || !$this->regionCache[$regionData->id] instanceof AlpsteinRegion) {
$this->regionCache[$regionData->id] = AlpsteinRegion::getByAlpsteinId((string) $regionData->id, 1);
}
$region = $this->regionCache[$regionData->id];
if ($region instanceof AlpsteinRegion) {
$objectMetadata = new ObjectMetadata('regions', ['isStartingRegion'], $region);
if ($regionData->isStartRegion) {
$objectMetadata->setIsStartingRegion(true);
}
$regions[] = $objectMetadata;
}
}
$poiObject->setRegions($regions);
}
// -- GEO
// positions
if (isset($poi->geometry)) {
$posData = explode(',', $poi->geometry);
$poiObject->setPosition( new GeoCoordinates($posData[0], $posData[1]) );
}
// -- Properties
$poiProperties = $this->tourProperties( $poi->properties->property ?? [], $language );
$poiObject->setPoiProperties( $poiProperties );
$poiObject->setBusinessHours($poi->businessHours ?? '', $language);
$this->poiSetOpeningTimes($poiObject, $poi->openingHours ?? []);
$poiObject->save();
$this->importedTourIds[] = $poiObject->getAlpsteinId();
}
private function poiSetOpeningTimes($object, $openingHours = []) {
$dates = $object->getOpeningTimes();
if (!$dates) {
$dates = new RecurringDateDefinition();
}
$definitionArray = [];
if (!empty($openingHours->weekday->openTime)) {
// as no daterange is given for the general openingtimes, but recurring dates needs a
// daterange (otherwise for fromDate and toDate the current date from the import will be used),
// the first day of the year is used for fromDate and the last day of the next year is for toDate
$times = [];
$dayMapping = [
'Monday' => 'mo',
'Tuesday' => 'tu',
'Wednesday' => 'we',
'Thursday' => 'th',
'Friday' => 'fr',
'Saturday' => 'sa',
'Sunday' => 'su',
];
// start to get the times for every weekday
foreach ($openingHours->weekday->openTime ?? [] as $date) {
foreach ($date->openHours ?? [] as $openHour) {
$timeFrom = $openHour->from ?? null;
$timeTo = $openHour->to ?? null;
$weekday = $dayMapping[$date->weekday];
$times[$weekday]['times'][] = [
'start' => $timeFrom == '24:00' ? '23:59' : $timeFrom,
'end' => $timeTo == '24:00' ? '23:59' : $timeTo
];
}
}
// combine all identical time entries to only get one entry for the same time on different weekdays
$identicalTimes = [];
$hashes = [];
foreach ($times as $weekday => $time) {
$hash = hash('sha256', serialize($time));
if (isset($hashes[$hash])) {
$identicalTimes[$hash] = array_merge($identicalTimes[$hash], [
$weekday => true
]);
} else {
$hashes[$hash] = $weekday;
$identicalTimes[$hash] = array_merge($time, [
$weekday => true,
'fromDate' => Carbon::today()->setMonth(1)->setDay(1)->format('Y-m-d'),
'toDate' => Carbon::today()->setMonth(12)->setDay(31)->addYear()->format('Y-m-d'),
]);
}
}
foreach ($identicalTimes as $entries) {
$definitionArray[] = [
'type' => RecurringDateDefinition::DEFINITION_TYPE_RECURRING_DATE_TIME,
'values' => $entries,
];
}
}
if (!empty($openingHours->special->openTime)) {
$times = ['times' => []];
foreach ($openingHours->special->openTime as $openTime) {
foreach ($openTime->openHours ?? [] as $openHour) {
$timeFrom = $openHour->from ?? null;
$timeTo = $openHour->to ?? null;
$times = [
'times' => [
[
'start' => $timeFrom == '24:00' ? '23:59' : $timeFrom,
'end' => $timeTo == '24:00' ? '23:59' : $timeTo
]
],
'mo' => in_array('MON', $openHour->days ?? []),
'tu' => in_array('TUE', $openHour->days ?? []),
'we' => in_array('WED', $openHour->days ?? []),
'th' => in_array('THU', $openHour->days ?? []),
'fr' => in_array('FRI', $openHour->days ?? []),
'sa' => in_array('SAT', $openHour->days ?? []),
'su' => in_array('SUN', $openHour->days ?? []),
];
}
// special opening times depend on a time range, and can also be excluded
$definitionArray[] = [
'type' => RecurringDateDefinition::DEFINITION_TYPE_RECURRING_DATE_TIME,
'values' => array_merge([
'fromDate' => (string)$openTime->dateFrom,
'toDate' => (string)$openTime->dateTo,
'excluded' => $openTime->isOpen != 'true',
], $times)
];
}
}
$dates->setDefinitionArray($definitionArray);
$object->setOpeningTimes($dates);
}
/**
* @param DataObject $relatedObject
* @param $folderName
* @param $imagesArray
* @param string $language
* @return array
* @throws \Exception
*/
private function loadAllImages( DataObject $relatedObject, $folderName, $imagesArray, $primaryId = null, $language = 'de', $primaryTitle = 'primaryImage' ) : array{
$this->dump('-> LoadImages');
$imagesArray = $imagesArray ?? [];
$assetImage = [
'primaryImage' => null,
'allImages' => null,
'videos' => null
];
// Get Image Folder for Tour
$folder = \Pimcore\Model\Asset\Service::createFolderByPath( $this->assetImageFolder . $folderName );
// Load Available Images
$availableImages = [];
foreach( $folder->getChildren() as $avImg ){
try {
$availableImages[ $avImg->getMetadata('alpstein-img-id') ] = $avImg;
} catch(\Exception $e) {
$this->applicationLogger->info("error accessing metadata (Folder: {$folder->getId()}, Image: {$avImg->getId()}): \n{$e->getMessage()}\n\n{$e->getTraceAsString()}", ['component' => 'AlpsteinImportCommand']);
}
}
$this->dump('---> Images Available: ' . (bool)!empty($availableImages));
// get all new Images
foreach( $imagesArray as $image ){
try {
$inGallery = $image->gallery ?? '';
$isVideo = $image->isVideo ?? '';
$isPrimary = $image->primary ?? '';
if( !$isPrimary && !is_null($primaryId) ){
$isPrimary = $primaryId == $image->id ? true : false;
}
$date = new Carbon($image->meta->date->lastModified);
// -- License
$license = false;
if (isset($image->meta) && isset($image->meta->license)) {
$license = $this->getLicenseByFid($image->meta->license->short);
}
$this->dump('-------> Image: ' . ($image->title ?? ' no - title') . ' Primary: ' . (bool)$isPrimary );
if ($isVideo) {
if ($image->video && $image->video->youtubeId) { // only youtube supported for now
$videoObject = AlpsteinVideo::getByAlpsteinId(trim($image->id), 1);
if (!$videoObject instanceof AlpsteinVideo) {
$videoObject = new AlpsteinVideo();
$videoObject->setPublished(true);
$videoObject->setKey(Service::getValidKey(trim($image->id), 'object'));
$videoObject->setParent($this->videosFolder);
$videoObject->setAlpsteinId(trim($image->id));
}
$videoData = new Video();
$videoData->setType('youtube');
$videoData->setData((string)$image->video->youtubeId);
$videoData->setTitle((string)$image->title ?? '');
$videoData->setDescription((string)$image->description);
$videoObject->setVideo($videoData, $language);
$videoObject->setSource( $image->source ?? '' );
if ($license) {
$videoObject->setProperty('ulicense_object', 'object', $license);
} else {
$videoObject->setProperty('ulicense_object', 'object', $this->defaultLicense);
}
$videoObject->save();
$assetImage['videos'][] = $videoObject;
}
} else if( in_array('full', $this->options) || $isPrimary || (isset($availableImages[$image->id]) && (int)$availableImages[$image->id]->getMetadata('last-modified') < $date->timestamp) ){ // wenn voll import oder Primary image
$imageUrl = 'http://img.oastatic.com/img/2048/2048/' . $image->id . '/.jpg';
try {
$loadedImage = \Pimcore\Tool::getHttpData( $imageUrl, [], [], ['timeout' => 60] );
} catch (\Throwable $exception) {
$this->dump('################### ERROR ###################');
$this->dump($exception->getMessage());
$this->dump($exception->getTraceAsString());
$this->dump('################### ERROR ###################');
}
if( $loadedImage ){
$name = \Pimcore\Tool\Transliteration::toASCII($image->title ?? '');
if (strlen($name ?: '') > 50) {
$name = substr($name, 0, 50);
}
$filename = \Pimcore\File::getValidFilename( $name . '-' . $image->id ) . '.jpg';
if ($this->doRemoveICCProfile) {
$loadedImage = \Elements\Bundle\AlpsteinBundle\Tools\Image::removeICCProfile($loadedImage, $filename);
}
if( array_key_exists(trim($image->id), $availableImages) ){
$this->dump('------------> Override Image' );
/**
* @var $editImage Image
*/
$newImage = $availableImages[$image->id];
$newImage->setData( $loadedImage );
}else{
$this->dump('------------> new Image' );
$newImage = Image::getByPath( $folder->getFullPath() . '/' . $filename );
if( !$newImage instanceof Image ) {
$newImage = new Image();
}
$newImage->addMetadata( 'alpstein-img-id', 'input', trim($image->id) );
$newImage->setData($loadedImage);
$newImage->setFilename( $filename );
$newImage->setParent( $folder );
$availableImages[trim($image->id)] = $newImage;
}
$newImage = $this->addImageMetadata($newImage, $image, $language, $date, $inGallery, $isPrimary, $license);
$saveImageSuccess = false;
try {
$newImage->save();
$saveImageSuccess = true;
$this->dump('Image ID:' . $image->id . ' Image: ' . ($image->title ?? 'no-title' ));
} catch (\Throwable $exception) {
if (strpos($exception->getMessage(), 'Duplicate full path') === false) {
$this->dump('Delete and retry Image ID:' . $image->id . ' Image: ' . ($image->title ?? 'no-title' ) . PHP_EOL . $exception->getMessage());
try {
$newImage->delete();
} catch (\Throwable $e) {
$this->applicationLogger->info("Could not delete image after error occured\nrecreating image...:\n\n{$exception->getMessage()}\n{$exception->getTraceAsString()}", ['component' => 'AlpsteinImportCommand', 'relatedObject' => $relatedObject]);
}
$newImage = new Image();
$newImage->addMetadata( 'alpstein-img-id', 'input', trim($image->id) );
$newImage->setData($loadedImage);
$newImage->setFilename( $filename );
$newImage->setParent( $folder );
$availableImages[trim($image->id)] = $newImage;
$newImage = $this->addImageMetadata($newImage, $image, $language, $date, $inGallery, $isPrimary, $license);
$newImage->save();
$saveImageSuccess = true;
$this->dump('Image ID:' . $image->id . ' Image: ' . ($image->title ?? 'no-title'));
} else {
$saveImageSuccess = false;
$this->applicationLogger->error('Could not save Image: ' . PHP_EOL . 'Foldername: ' . $folderName . PHP_EOL . 'Image URL: ' . $imageUrl . PHP_EOL . $exception->getMessage() . PHP_EOL . $exception->getTraceAsString(), ['component' => 'AlpsteinImportCommand', 'relatedObject' => $relatedObject]);
}
}
if( $saveImageSuccess && $isPrimary ){
$assetImage['primaryImage'] = $newImage;
}
if( $saveImageSuccess && $inGallery ){
$assetImage['allImages'][] = $newImage;
}
}
}
} catch (\Exception $e) {
$this->applicationLogger->info("Could not import image " .
($image && $image->id ? $image->id : null) .
"\n{$e->getMessage()}\n\n{$e->getTraceAsString()}",
['component' => 'AlpsteinImportCommand', 'relatedObject' => $relatedObject]);
}
}
if(empty($assetImage['primaryImage']) && $primaryId) {
$newPrimaryImage = $this->createNewPrimaryImage($primaryId, $folder, $primaryTitle);
$assetImage['primaryImage'] = $newPrimaryImage;
}
foreach( $imagesArray as $img ){
if( array_key_exists($img->id, $availableImages) ){
unset($availableImages[$img->id]);
}
}
foreach( $availableImages as $deleteImage ){
$deleteImage->delete();
}
return $assetImage;
}
private function addImageMetadata($newImage, $image, $language, $date, $inGallery, $isPrimary, $license ) {
$imageAuthorName = '';
if (isset($image->author)) {
$imageAuthorName = $image->author;
} else if (isset($image->meta->authorFull)) {
$imageAuthorName = $image->meta->authorfull->name;
} else if (isset($image->meta->author)) {
$imageAuthorName = $image->meta->author;
}
$imageSourceName = '';
$imageSourceUrl = '';
if (isset($image->source)) {
$imageSourceName = (string)$image->source ?? '';
}
if ($image->meta->source) {
$imageSourceName = (string)$image->meta->source->name ?? '';
$imageSourceUrl = isset($image->meta->source->url) ? (string)$image->meta->source->url : '';
}
if ($imageAuthorName) {
$newImage->addMetadata( 'author', 'input', $imageAuthorName);
}
if ($imageSourceName) {
$newImage->addMetadata('source', 'input', $imageSourceName);
}
if ($imageSourceUrl) {
$newImage->addMetadata('sourceUrl', 'input', $imageSourceUrl);
}
$newImage->addMetadata( 'copyright', 'input', $image->meta->source->name);
$newImage->addMetadata( 'title', 'input', $image->title ?? '', $language );
$newImage->addMetadata( 'last-modified', 'input', $date->timestamp );
$newImage->addMetadata( 'gallery', 'checkbox', $inGallery );
$newImage->addMetadata( 'primary', 'checkbox', $isPrimary );
if ($license) {
$newImage->setProperty('ulicense_object', 'object', $license);
} else {
$newImage->setProperty('ulicense_object', 'object', $this->defaultLicense);
}
return $newImage;
}
/**
* @param $properties
* @param string $language
* @return array
* @throws \Exception
*/
private function tourProperties( $properties, $language = 'de' ){
$tourPropertiesArray = [];
$properties = $properties ?? [];
foreach( $properties as $prop ){
$propObj = AlpsteinProperty::getByTag( $prop->tag, [ 'limit' => 1, 'unpublished' => true ] );
if( !$propObj instanceof AlpsteinProperty ){
$propObj = new AlpsteinProperty();
$propObj->setKey( \Pimcore\File::getValidFilename($prop->tag . '-' . time() ) );
$propObj->setParent( $this->objectPropertiesFolder );
$propObj->setPublished( true );
$propObj->setTag( $prop->tag );
}
if (isset($prop->text) && $prop->text != '') {
$propObj->setName( $prop->text, $language );
}
if(isset($prop->hasIcon)){
$filename = \Pimcore\File::getValidFilename( $prop->text );
$icon = Image::getByPath( $this->assetPropertiesFolder->getFullPath() . '/' . $filename . '.svg' );
//$this->assetPropertiesFolder;
if( !$icon instanceof Image && isset($prop->iconURL) ){
try {
$imageUrl = \Pimcore\Tool::getHttpData($prop->iconURL, [], [], ['timeout' => 60]);
} catch (\Throwable $exception) {
$this->dump('################### ERROR ###################');
$this->dump($exception->getMessage());
$this->dump($exception->getTraceAsString());
$this->dump('################### ERROR ###################');
}
if( $imageUrl ){
$icon = new Image();
$icon->setFilename( $filename . '.svg' );
$icon->setParent( $this->assetPropertiesFolder );
$icon->setData($imageUrl);
$icon->save();
$propObj->setIcon( $icon );
}
}
}
$propObj->save();
$tourPropertiesArray[] = $propObj;
}
return $tourPropertiesArray;
}
protected $licenses = [];
protected function getLicenseByFid($fid) {
if (!array_key_exists($fid, $this->licenses) || !$this->licenses[$fid]) {
$db = Db::get();
$id = $db->fetchOne('SELECT o_id FROM object_collection_ULicenseFid_ULicense WHERE systemIdentifier = "Alpstein" AND fid = ' . $db->quote($fid));
if ($id) {
$this->licenses[$fid] = ULicense::getById($id);
}
}
if (!array_key_exists($fid, $this->licenses) || !$this->licenses[$fid]) {
ApplicationLogger::getInstance()->warning('Could not find License for FID ' . $fid, ['component' => 'Alpstein Importer']);
}
return $this->licenses[$fid];
}
private function createNewPrimaryImage($primaryId, $folder, $primaryTitle)
{
$this->dump('------------> new Primary Image' );
$imageUrl = 'http://img.oastatic.com/img/2048/2048/' . $primaryId . '/.jpg';
try {
$loadedImage = \Pimcore\Tool::getHttpData( $imageUrl, [], [], ['timeout' => 60] );
} catch (\Throwable $exception) {
$this->dump('################### ERROR ###################');
$this->dump($exception->getMessage());
$this->dump($exception->getTraceAsString());
$this->dump('################### ERROR ###################');
return null;
}
if ($loadedImage) {
if (strlen($primaryTitle ?: '') > 50) {
$primaryTitle = substr($primaryTitle, 0, 50);
}
$filename = \Pimcore\File::getValidFilename( $primaryTitle . '-' . $primaryId ) . '.jpg';
if ($this->doRemoveICCProfile) {
$loadedImage = \Elements\Bundle\AlpsteinBundle\Tools\Image::removeICCProfile($loadedImage, $filename);
}
$newImage = Image::getByPath( $folder->getFullPath() . '/' . $filename );
if( !$newImage instanceof Image ) {
$newImage = new Image();
}
$newImage->addMetadata( 'alpstein-img-id', 'input', trim($primaryId) );
$newImage->setData($loadedImage);
$newImage->setFilename( $filename );
$newImage->setParent( $folder );
//no metadata in primary Image
// $newImage = $this->addImageMetadata($newImage, $image);
$newImage->save();
return $newImage;
}
return null;
}
protected function createTourIdPackages(array $tourIds) {
if($this->numToursPerImportIteration) {
return array_chunk($tourIds, $this->numToursPerImportIteration);
}
return [$tourIds]; //single package
}
/**
* @param AlpsteinRegion $region
* @param ObjectMetadata[] $objectMetadata
*/
private function getStartingRegionFromOldRegionsArray(AlpsteinRegion $region, array $objectMetadata) {
foreach ($objectMetadata as $metadata) {
$metadataElement = $metadata->getElement();
if($metadataElement instanceof AlpsteinRegion && $metadataElement->getId() === $region->getId()){
return $metadata->getData()['isStartingRegion'];
}
}
return null; //region does not exists => new region
}
}