vendor/elements/alpstein-bundle/src/Command/ImportCommand.php line 452

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace Elements\Bundle\AlpsteinBundle\Command;
  4. use Carbon\Carbon;
  5. use Elements\Bundle\AlpsteinBundle\Services\AlpsteinConfig;
  6. use Elements\Bundle\RecurringDatesTypeBundle\Model\RecurringDateDefinition;
  7. use GuzzleHttp\Client;
  8. use Pimcore\Console\AbstractCommand;
  9. use Pimcore\Console\Traits\DryRun;
  10. use Pimcore\Db;
  11. use Pimcore\Log\ApplicationLogger;
  12. use Pimcore\Model\Asset\Image;
  13. use Pimcore\Model\DataObject;
  14. use Pimcore\Model\DataObject\AlpsteinPoi;
  15. use Pimcore\Model\DataObject\AlpsteinProperty;
  16. use Pimcore\Model\DataObject\AlpsteinRegion;
  17. use Pimcore\Model\DataObject\AlpsteinRegionCategory;
  18. use Pimcore\Model\DataObject\AlpsteinTour;
  19. use Pimcore\Model\DataObject\AlpsteinKey;
  20. use Pimcore\Model\DataObject\AlpsteinVideo;
  21. use Pimcore\Model\DataObject\Data\Geobounds;
  22. use Pimcore\Model\DataObject\Data\GeoCoordinates;
  23. use Pimcore\Model\DataObject\Data\ObjectMetadata;
  24. use Pimcore\Model\DataObject\Data\Video;
  25. use Pimcore\Model\DataObject\AlpsteinCategory;
  26. use Pimcore\Model\DataObject\AlpsteinSource;
  27. use Pimcore\Model\DataObject\AlpsteinAuthor;
  28. use Pimcore\Model\DataObject\Service;
  29. use Pimcore\Model\DataObject\ULicense;
  30. use Symfony\Component\Console\Input\InputInterface;
  31. use Symfony\Component\Console\Input\InputOption;
  32. use Symfony\Component\Console\Output\OutputInterface;
  33. class ImportCommand extends AbstractCommand
  34. {
  35.     use DryRun;
  36.     const TIMESTAMPFILE '/alpstein_import_timestamp.tmp';
  37.     const IGNORE_FALLBACK 'ignore-fallback';
  38.     protected $alpsteinConfig;
  39.     protected $defaultLicense;
  40.     protected $doRemoveICCProfile;
  41.     protected $minimumRanking;
  42.     protected $importOnlyCCCompliant;
  43.     protected $validLanguage = [];
  44.     protected $categoryFolder;
  45.     protected $regionCache;
  46.     protected $regionFolder;
  47.     protected $regionCategoryFolder;
  48.     protected $tourFolder;
  49.     protected $poiFolder;
  50.     protected $videosFolder;
  51.     protected $assetIconFolder;
  52.     protected $assetImageFolder '/Alpstein/Images/';
  53.     protected $assetImageFolderObject;
  54.     protected $assetPropertiesFolder;
  55.     protected $objectPropertiesFolder;
  56.     protected $objectSourceFolder;
  57.     protected $assetSourceFolder;
  58.     protected $objectAuthorFolder;
  59.     protected $assetAuthorFolder;
  60.     protected $objectKeyFolder;
  61.     protected $importedTourIds = [];
  62.     protected $importedPoiIds = [];
  63.     protected $importedRegions = [];
  64.     protected $options = [];
  65.     protected $numToursPerImportIteration 0;
  66.     protected $importTime 0;
  67.     /**
  68.      * @var Client
  69.      */
  70.     private $client;
  71.     private ApplicationLogger $applicationLogger;
  72.     protected function configure()
  73.     {
  74.         $this
  75.             ->setName('alpstein:import')
  76.             ->setDescription('Migrate existing structure to new file extensions')
  77.             ->addOption('full''f'null'start Full Import')
  78.             ->addOption('regions''r'null'also includes regions in Import')
  79.             ->addOption('pois''p'null'also includes pois in Import')
  80.             ->addOption('override''o'null'Override Images')
  81.             ->addOption('delta''d'null'Only Import changed Tours & Pois')
  82.             ->addOption('skip-images'nullnull'Ignore Images')
  83.             ->addOption('tourId'nullInputOption::VALUE_OPTIONAL'Import selected Tour only')
  84.             ->addOption('tours-per-iterations'nullInputOption::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)
  85.             ->addOption(self::IGNORE_FALLBACK'if'InputOption::VALUE_OPTIONAL'Adds the parameter fallback=false to the tour import, so that language fallbacks are not added.')
  86.         ;
  87.         $this->configureDryRunOption();
  88.     }
  89.     /**
  90.      * ImportCommand constructor.
  91.      * @param AlpsteinConfig $alpsteinConfig
  92.      * @param Client $client
  93.      */
  94.     public function __construct(AlpsteinConfig $alpsteinConfigClient $clientApplicationLogger $applicationLogger)
  95.     {
  96.         parent::__construct();
  97.         $this->alpsteinConfig $alpsteinConfig->getConfig();
  98.         $this->doRemoveICCProfile $alpsteinConfig->doRemoveICCProfile();
  99.         $this->minimumRanking $alpsteinConfig->getMinimumRanking();
  100.         $this->importOnlyCCCompliant $alpsteinConfig->getImportOnlyCCCompliant();
  101.         $this->client $client;
  102.         $this->applicationLogger $applicationLogger;
  103.     }
  104.     /**
  105.      * @param InputInterface $input
  106.      * @param OutputInterface $output
  107.      * @return int|null|void
  108.      * @throws \GuzzleHttp\Exception\GuzzleException
  109.      */
  110.     protected function execute(InputInterface $inputOutputInterface $output)
  111.     {
  112.         if( $input->getOption('full') ){
  113.             $this->options[] = 'full';
  114.         }
  115.         if( $input->getOption('regions') ){
  116.             $this->options[] = 'regions';
  117.         }
  118.         if( $input->getOption('pois') ){
  119.             $this->options[] = 'pois';
  120.         }
  121.         if( $input->getOption('override') ){
  122.             $this->options[] = 'override';
  123.         }
  124.         if( $input->getOption('delta') ){
  125.             $this->options[] = 'delta';
  126.         }
  127.         if( $input->getOption('skip-images') ){
  128.             $this->options[] = 'skip-images';
  129.         }
  130.         if($input->getOption('tours-per-iterations')) {
  131.             $this->numToursPerImportIteration = (int)$input->getOption('tours-per-iterations');
  132.         }
  133.         if($input->getOption(self::IGNORE_FALLBACK)) {
  134.             $this->options[] = self::IGNORE_FALLBACK;
  135.         }
  136.         $tourId $input->getOption('tourId');
  137.         $this->validLanguage = ['de'];
  138.         foreach( \Pimcore\Tool::getValidLanguages() as $lang ){
  139.             if( $lang != 'de' ){
  140.                 $this->validLanguage[] = $lang;
  141.             }
  142.         }
  143.         $defaultLicense ULicense::getByCode('AlpsteinDefault'1);
  144.         if (!$defaultLicense instanceof ULicense) {
  145.             $defaultLicense = new ULicense();
  146.             $defaultLicense->setKey('AlpsteinDefaultLicense');
  147.             $defaultLicense->setParent(Service::createFolderByPath('Alpstein/License'));
  148.             $defaultLicense->setPublished(true);
  149.             $defaultLicense->setCode('AlpsteinDefault');
  150.             $defaultLicense->setName('Outdooractive AGB''de');
  151.             $defaultLicense->setName('Outdooractive Terms of Service''en');
  152.             $defaultLicense->save();
  153.         }
  154.         $this->defaultLicense $defaultLicense;
  155.         $this->categoryFolder Service::createFolderByPath('/Alpstein/Categories');
  156.         $this->regionFolder Service::createFolderByPath('/Alpstein/Regions');
  157.         $this->regionCategoryFolder Service::createFolderByPath('/Alpstein/RegionCategories');
  158.         $this->assetIconFolder \Pimcore\Model\Asset\Service::createFolderByPath('/Alpstein/Icons');
  159.         $this->tourFolder Service::createFolderByPath('/Alpstein/Tour');
  160.         $this->poiFolder Service::createFolderByPath('/Alpstein/Poi');
  161.         $this->assetImageFolderObject \Pimcore\Model\Asset\Service::createFolderByPath$this->assetImageFolder );
  162.         $this->assetPropertiesFolder \Pimcore\Model\Asset\Service::createFolderByPath'/Alpstein/Properties');
  163.         $this->objectPropertiesFolder Service::createFolderByPath'/Alpstein/Properties');
  164.         $this->objectSourceFolder Service::createFolderByPath'/Alpstein/Sources');
  165.         $this->objectAuthorFolder Service::createFolderByPath'/Alpstein/Authors');
  166.         $this->assetSourceFolder \Pimcore\Model\Asset\Service::createFolderByPath'/Alpstein/Sources');
  167.         $this->assetAuthorFolder \Pimcore\Model\Asset\Service::createFolderByPath'/Alpstein/Authors');
  168.         $this->videosFolder Service::createFolderByPath'/Alpstein/Videos');
  169.         $this->objectKeyFolder Service::createFolderByPath'/Alpstein/Key');
  170.         $this->importTime time();
  171.         try {
  172.             if( is_array($this->alpsteinConfig['project']) ){
  173.                 foreach( $this->alpsteinConfig['project'] as $key => $project ){
  174.                     $alpsteinConfig = [
  175.                         'project' => $project,
  176.                         'apiKey' => $this->alpsteinConfig['apiKey'][$key]
  177.                     ];
  178.                     $alpsteinConfig['keyObject'] = $this->createAndGetKey$alpsteinConfig['project'], $alpsteinConfig['apiKey'] );
  179.                     $this->importCategories$alpsteinConfig );
  180.                     if ($tourId != '') {
  181.                         $this->importSingleTour($tourId$alpsteinConfig);
  182.                     } else {
  183.                         if (in_array('regions'$this->options)) {
  184.                             $this->importRegions$alpsteinConfig );
  185.                         }
  186.                         if (in_array('pois'$this->options)) {
  187.                             $this->importPois$alpsteinConfig );
  188.                         }
  189.                         $this->importTours$alpsteinConfig );
  190.                     }
  191.                 }
  192.             } else {
  193.                 $this->alpsteinConfig['keyObject'] = $this->createAndGetKey$this->alpsteinConfig['project'], $this->alpsteinConfig['apiKey'] );
  194.                 if ($tourId != '') {
  195.                     $this->importSingleTour($tourId$this->alpsteinConfig);
  196.                 } else {
  197.                     $this->importCategories$this->alpsteinConfig );
  198.                     if (in_array('regions'$this->options)) {
  199.                         $this->importRegions$this->alpsteinConfig );
  200.                     }
  201.                     if (in_array('pois'$this->options)) {
  202.                         $this->importPois$this->alpsteinConfig );
  203.                     }
  204.                     $this->importTours$this->alpsteinConfig );
  205.                 }
  206.             }
  207.             if (!empty($this->importedTourIds) && !in_array('delta'$this->options) && $tourId == '') {
  208.                 $tours = new AlpsteinTour\Listing();
  209.                 $tours->addConditionParam('alpsteinId IS NOT NULL AND alpsteinId != "" AND alpsteinId NOT IN (' implode(','$this->importedTourIds) . ')');
  210.                 foreach ($tours as $tour) {
  211.                     $tour->setPublished(false);
  212.                     $tour->save();
  213.                 }
  214.             }
  215.             if (!empty($this->importedPoiIds) && !in_array('delta'$this->options)) {
  216.                 $pois = new AlpsteinPoi\Listing();
  217.                 $pois->addConditionParam('alpsteinId IS NOT NULL AND alpsteinId != "" AND alpsteinId NOT IN (' implode(','$this->importedPoiIds) . ')');
  218.                 foreach ($pois as $poi) {
  219.                     $poi->setPublished(false);
  220.                     $poi->save();
  221.                 }
  222.             }
  223.         } catch (\Exception $exception) {
  224.             $this->applicationLogger->info("Error:\n{$exception->getMessage()}\n\n{$exception->getTraceAsString()}", ['component' => 'AlpsteinImportCommand']);
  225.         }
  226.         if ($tourId == '') {
  227.             file_put_contents(PIMCORE_PRIVATE_VAR self::TIMESTAMPFILE$this->importTime);
  228.         }
  229.         return 0;
  230.     }
  231.     /**
  232.      * @param $project
  233.      * @param $apiKey
  234.      * @return AlpsteinKey|AlpsteinKey\Listing
  235.      * @throws \Exception
  236.      */
  237.     private function createAndGetKey$project$apiKey ){
  238.         $keyObject AlpsteinKey::getByApiKey$apiKey, ['limit' => 1] );
  239.         if( !$keyObject instanceof AlpsteinKey ){
  240.             $keyObject = new AlpsteinKey();
  241.             $keyObject->setName($project);
  242.             $keyObject->setApiKey($apiKey);
  243.             $keyObject->setKey\Pimcore\File::getValidFilename($project '-' $apiKey) );
  244.             $keyObject->setParent$this->objectKeyFolder );
  245.             $keyObject->setPublishedtrue );
  246.             $keyObject->save();
  247.         }
  248.         return $keyObject;
  249.     }
  250.     /**
  251.      * Import Categories
  252.      * @param $alpsteinConfig
  253.      * @throws \GuzzleHttp\Exception\GuzzleException
  254.      */
  255.     private function importCategories$alpsteinConfig )
  256.     {
  257.         foreach( $this->validLanguage as $language ){
  258.             $url 'https://www.outdooractive.com/api/project/' $alpsteinConfig['project'] . '/category/tree?lang=' $language '&key=' $alpsteinConfig['apiKey'];
  259.             $client $this->client;
  260.             $requestType 'GET';
  261.             $config = [
  262.                 \GuzzleHttp\RequestOptions::ALLOW_REDIRECTS => [
  263.                     'max' => 2
  264.                 ],
  265.                 \GuzzleHttp\RequestOptions::TIMEOUT => 60
  266.             ];
  267.             $config[\GuzzleHttp\RequestOptions::HEADERS] = [
  268.                 'Accept' => 'application/json'
  269.             ];
  270.             /**
  271.              * @var $response \GuzzleHttp\Psr7\Response
  272.              */
  273.             try {
  274.                 $response $client->request($requestType$url$config);
  275.             } catch (\Throwable $exception) {
  276.                 $this->dump('################### ERROR ###################');
  277.                 $this->dump($exception->getMessage());
  278.                 $this->dump($exception->getTraceAsString());
  279.                 $this->dump('################### ERROR ###################');
  280.             }
  281.             if ($response && $response->getStatusCode() == 200) {
  282.                 $data $response->getBody();
  283.                 $categoryArray json_decode$data->getContents() );
  284.                 foreach( $categoryArray as $itemArray ){
  285.                     // Top Category
  286.                     foreach( $itemArray as $item ){
  287.                         $parentId $this->createCategory$item$alpsteinConfig['keyObject'], $this->categoryFolder->getId(), $language );
  288.                         // Sub Category
  289.                         foreach( $item->category ?? [] as $subCategory ){
  290.                             $this->createCategory$subCategory$alpsteinConfig['keyObject'], $parentId$language );
  291.                         }
  292.                     }
  293.                 }
  294.             }
  295.         }
  296.     }
  297.     /**
  298.      * Import Categories
  299.      * @param $alpsteinConfig
  300.      * @throws \GuzzleHttp\Exception\GuzzleException
  301.      */
  302.     private function importRegions$alpsteinConfig )
  303.     {
  304.         foreach( $this->validLanguage as $language ){
  305.             $url 'https://www.outdooractive.com/api/project/' $alpsteinConfig['project'] . '/region/tree?lang=' $language '&key=' $alpsteinConfig['apiKey'];
  306.             $client $this->client;
  307.             $requestType 'GET';
  308.             $config = [
  309.                 \GuzzleHttp\RequestOptions::ALLOW_REDIRECTS => [
  310.                     'max' => 2
  311.                 ],
  312.                 \GuzzleHttp\RequestOptions::TIMEOUT => 60
  313.             ];
  314.             $config[\GuzzleHttp\RequestOptions::HEADERS] = [
  315.                 'Accept' => 'application/json'
  316.             ];
  317.             /**
  318.              * @var $response \GuzzleHttp\Psr7\Response
  319.              */
  320.             try {
  321.                 $response $client->request($requestType$url$config);
  322.             } catch (\Throwable $exception) {
  323.                 $this->dump('################### ERROR ###################');
  324.                 $this->dump($exception->getMessage());
  325.                 $this->dump($exception->getTraceAsString());
  326.                 $this->dump('################### ERROR ###################');
  327.             }
  328.             if ($response && $response->getStatusCode() == 200) {
  329.                 $data $response->getBody();
  330.                 $regionArray json_decode$data->getContents() );
  331.                 foreach( $regionArray->region as $regionData ){
  332.                     $this->createRegion($regionData$this->regionFolder->getId(), $alpsteinConfig['keyObject'], $language);
  333.                 }
  334.             }
  335.         }
  336.     }
  337.     /**
  338.      * @param $item
  339.      * @param null $parentId
  340.      * @param string $language
  341.      * @param $keyObject AlpsteinKey
  342.      * @return int
  343.      * @throws \Exception
  344.      */
  345.     private function createCategory$item$keyObject$parentId null$language 'de' ){
  346.         $category AlpsteinCategory::getByCategoryId( (int)$item->id);
  347.         if( !$category instanceof AlpsteinCategory ){
  348.             $category = new AlpsteinCategory();
  349.             $category->setParentId$parentId );
  350.             $category->setPublishedtrue );
  351.             $category->setKey\Pimcore\File::getValidFilename$item->name '-' $item->id ) );
  352.             $category->setCategoryId((int)$item->id);
  353.             if( $language == 'de' && !$category->getIcon() instanceof Image ){
  354.                 if( isset($item->iconUrl) ){
  355.                     preg_match('/^.*\.(jpg|jpeg|png|gif|svg)$/i'$item->iconUrl$reg);
  356.                     $imageName \Pimcore\File::getValidFilename$item->name '-' $item->id ) . '.' $reg[1];
  357.                     $image Image::getByPath$this->assetIconFolder->getFullPath() . '/' $imageName );
  358.                     if( !$image instanceof Image ){
  359.                         try {
  360.                             $iconUrl \Pimcore\Tool::getHttpData($item->iconUrl, [], [], ['timeout' => 60]);
  361.                         } catch (\Throwable $exception) {
  362.                             $this->dump('################### ERROR ###################');
  363.                             $this->dump($exception->getMessage());
  364.                             $this->dump($exception->getTraceAsString());
  365.                             $this->dump('################### ERROR ###################');
  366.                         }
  367.                         if( $iconUrl ){
  368.                             $image = new Image();
  369.                             $image->setData$iconUrl );
  370.                             $image->setFilename$imageName \Pimcore\File::getValidFilename$item->name '-' $item->id ) . '.' $reg[1] );
  371.                             $image->setParent$this->assetIconFolder );
  372.                             $image->save();
  373.                             $category->setIcon($image);
  374.                         }
  375.                     }else{
  376.                         $category->setIcon($image);
  377.                     }
  378.                 }
  379.             }
  380.         }
  381.         $catAlpsteinKeys $category->getAlpsteinKey();
  382.         $hasKey false;
  383.         foreach( $catAlpsteinKeys as $keyObj ){
  384.             if( $keyObj->getApiKey() == $keyObject->getApiKey() ){
  385.                 $hasKey true;
  386.                 break;
  387.             }
  388.         }
  389.         if( !$hasKey ){
  390.             $catAlpsteinKeys[] = $keyObject;
  391.         }
  392.         $category->setAlpsteinKey$catAlpsteinKeys );
  393.         $category->setModificationDatetime() );
  394.         $category->setName$item->name$language );
  395.         $category->save();
  396.         return $category->getId();
  397.     }
  398.     /**
  399.      * @param $regionData
  400.      * @param $parentId
  401.      * @param string $language
  402.      * @param AlpsteinKey $keyObject
  403.      * @throws \Exception
  404.      */
  405.     private function createRegion$regionData$parentId$keyObject$language 'de' ){
  406.         if (array_key_exists($language$this->importedRegions) && array_key_exists($regionData->id$this->importedRegions[$language]) && ($region $this->importedRegions[$language][$regionData->id])) {
  407.             return $region;
  408.         }
  409.         $region AlpsteinRegion::getByAlpsteinId( (int)$regionData->id);
  410.         if( !$region instanceof AlpsteinRegion ){
  411.             $region = new AlpsteinRegion();
  412.             $region->setParentId$parentId );
  413.             $region->setPublishedtrue );
  414.             $region->setKey\Pimcore\File::getValidFilename$regionData->name '-' $regionData->id ) );
  415.             $region->setAlpsteinId((int)$regionData->id);
  416.         }
  417.         $alpsteinKeys $region->getAlpsteinKey();
  418.         $hasKey false;
  419.         foreach( $alpsteinKeys as $keyObj ){
  420.             if( $keyObj->getApiKey() == $keyObject->getApiKey() ){
  421.                 $hasKey true;
  422.                 break;
  423.             }
  424.         }
  425.         if( !$hasKey ){
  426.             $alpsteinKeys[] = $keyObject;
  427.         }
  428.         $region->setAlpsteinKey$alpsteinKeys );
  429.         $region->setModificationDatetime() );
  430.         $region->setName$regionData->name$language );
  431.         $region->setRegionType$regionData->type );
  432.         $region->setLevel$regionData->level );
  433.         $region->setHasTour($regionData->hasTour);
  434.         if ($regionData->bbox) {
  435.             $geodata explode(','$regionData->bbox);
  436.             $southWest = new GeoCoordinates($geodata[1], $geodata[0]);
  437.             $northEast = new GeoCoordinates($geodata[3], $geodata[2]);
  438.             $bbox = new Geobounds($northEast$southWest);
  439.             $region->setBbox($bbox);
  440.         }
  441.         $region->setCategory($this->createRegionCategory($regionData->categoryId$regionData->categoryTitle$keyObject$language));
  442.         $region->save();
  443.         $subregions $region->getSubRegions();
  444.         $containingRegions = [];
  445.         foreach ($subregions ?: [] as $subRegionObj) {
  446.             $containingRegions[] = $subRegionObj->getAlpsteinId();
  447.         }
  448.         if (!empty($regionData->region)) {
  449.             foreach ($regionData->region as $subRegionData) {
  450.                 $subRegion $this->createRegion($subRegionData$region->getId(), $keyObject$language);
  451.                 if (!in_array($subRegion->getAlpsteinId(), $containingRegions)) {
  452.                     $subregions[] = $subRegion;
  453.                     $containingRegions[] = $subRegion->getAlpsteinId();
  454.                 }
  455.             }
  456.         }
  457.         $region->setSubRegions($subregions);
  458.         $region->save();
  459.         $this->importedRegions[$language][$regionData->id] = $region;
  460.         return $region;
  461.     }
  462.     /**
  463.      * @param $regionCategoryId
  464.      * @param $regionCategoryName
  465.      * @param string $language
  466.      * @param AlpsteinKey $keyObject
  467.      * @return AlpsteinRegionCategory
  468.      * @throws \Exception
  469.      */
  470.     private function createRegionCategory$regionCategoryId$regionCategoryName$keyObject$language 'de' ){
  471.         $regionCategory AlpsteinRegionCategory::getByAlpsteinId( (int)$regionCategoryId);
  472.         if( !$regionCategory instanceof AlpsteinRegionCategory ){
  473.             $regionCategory = new AlpsteinRegionCategory();
  474.             $regionCategory->setParentId$this->regionCategoryFolder->getId() );
  475.             $regionCategory->setPublishedtrue );
  476.             $regionCategory->setKey\Pimcore\File::getValidFilename$regionCategoryName '-' $regionCategoryId ) );
  477.             $regionCategory->setAlpsteinId((int)$regionCategoryId);
  478.         }
  479.         $alpsteinKeys $regionCategory->getAlpsteinKey();
  480.         $hasKey false;
  481.         foreach( $alpsteinKeys as $keyObj ){
  482.             if( $keyObj->getApiKey() == $keyObject->getApiKey() ){
  483.                 $hasKey true;
  484.                 break;
  485.             }
  486.         }
  487.         if( !$hasKey ){
  488.             $alpsteinKeys[] = $keyObject;
  489.         }
  490.         $regionCategory->setAlpsteinKey$alpsteinKeys );
  491.         $regionCategory->setName$regionCategoryName$language );
  492.         $regionCategory->setModificationDatetime() );
  493.         $regionCategory->save();
  494.         return $regionCategory;
  495.     }
  496.     private function importSingleTour ($tourObjectId$alpsteinConfig) {
  497.         $tour AlpsteinTour::getById($tourObjectId);
  498.         if ($tour instanceof AlpsteinTour) {
  499.             $lastImport 0;
  500.             $importTimeStampFile PIMCORE_PRIVATE_VAR '/alpstein-single-import-' $tourObjectId '.txt';
  501.             if (file_exists($importTimeStampFile)) {
  502.                 $lastImport file_get_contents($importTimeStampFile);
  503.             }
  504.             if ($lastImport strtotime('-2 hours')) {
  505.                 file_put_contents((string)time(), $importTimeStampFile);
  506.                 $tourId $tour->getAlpsteinId();
  507.                 foreach ($this->validLanguage as $language) {
  508.                     $url 'https://www.outdooractive.com/api/project/' $alpsteinConfig['project'] . '/oois/' $tourId '?lang=' $language '&key=' $alpsteinConfig['apiKey'];
  509.                     if(in_array(self::IGNORE_FALLBACK$this->options)) {
  510.                         $url .= '&fallback=false';
  511.                     }
  512.                     $client $this->client;
  513.                     $requestType 'GET';
  514.                     $config = [
  515.                         \GuzzleHttp\RequestOptions::ALLOW_REDIRECTS => [
  516.                             'max' => 2
  517.                         ],
  518.                         \GuzzleHttp\RequestOptions::TIMEOUT => 60
  519.                     ];
  520.                     $config[\GuzzleHttp\RequestOptions::HEADERS] = [
  521.                         'Accept' => 'application/json'
  522.                     ];
  523.                     /**
  524.                      * @var $response \GuzzleHttp\Psr7\Response
  525.                      */
  526.                     try {
  527.                         $response $client->request($requestType$url$config);
  528.                     } catch (\Throwable $exception) {
  529.                         $this->dump('################### ERROR ###################');
  530.                         $this->dump($exception->getMessage());
  531.                         $this->dump($exception->getTraceAsString());
  532.                         $this->dump('################### ERROR ###################');
  533.                     }
  534.                     if ($response && $response->getStatusCode() == 200) {
  535.                         $data $response->getBody();
  536.                         $tourArray json_decode($data->getContents());
  537.                         if( $tourArray->tour[0] && in_array($language$tourArray->tour[0]->meta->translation ) ){
  538.                             $this->createTour$tourArray->tour[0], $alpsteinConfig['keyObject'], $language );
  539.                         }
  540.                     }
  541.                 }
  542.                 unlink($importTimeStampFile);
  543.             }
  544.         }
  545.     }
  546.     private function importTours$alpsteinConfig ){
  547.         $tourIds $this->importTourIdList($alpsteinConfig);
  548.         $tourIdPackages $this->createTourIdPackages($tourIds);
  549.         $numPackages count($tourIdPackages);
  550.         try {
  551.             foreach ($tourIdPackages as $key => $tourIds) {
  552.                 $this->applicationLogger->info('Tour Import Package #' $key+"/{$numPackages}", ['component' => 'AlpsteinImportCommand']);
  553.                 $this->dump("Importing package #" . ($key 1) . "/{$numPackages}; package size: " count($tourIds));
  554.                 foreach ($this->validLanguage as $language) {
  555.                     foreach ($tourIds as $tourId) {
  556.                         $url 'https://www.outdooractive.com/api/project/' $alpsteinConfig['project'] . '/oois/' $tourId '?lang=' $language '&key=' $alpsteinConfig['apiKey'];
  557.                         if(in_array(self::IGNORE_FALLBACK$this->options)) {
  558.                             $url .= '&fallback=false';
  559.                         }
  560.                         $client $this->client;
  561.                         $requestType 'GET';
  562.                         $config = [
  563.                             \GuzzleHttp\RequestOptions::ALLOW_REDIRECTS => [
  564.                                 'max' => 2
  565.                             ],
  566.                             \GuzzleHttp\RequestOptions::TIMEOUT => 60
  567.                         ];
  568.                         $config[\GuzzleHttp\RequestOptions::HEADERS] = [
  569.                             'Accept' => 'application/json'
  570.                         ];
  571.                         /**
  572.                          * @var $response \GuzzleHttp\Psr7\Response
  573.                          */
  574.                         try {
  575.                             $response $client->request($requestType$url$config);
  576.                         } catch (\Throwable $exception) {
  577.                             $this->dump('################### ERROR ###################');
  578.                             $this->dump($exception->getMessage());
  579.                             $this->dump($exception->getTraceAsString());
  580.                             $this->dump('################### ERROR ###################');
  581.                         }
  582.                         if ($response && $response->getStatusCode() == 200) {
  583.                             $data $response->getBody();
  584.                             $tourArray json_decode($data->getContents());
  585.                             if ($tourArray->tour[0] && in_array($language$tourArray->tour[0]->meta->translation)) {
  586.                                 $this->createTour($tourArray->tour[0], $alpsteinConfig['keyObject'], $language);
  587.                             }
  588.                         }
  589.                         $this->dump(" ");
  590.                     }
  591.                 }
  592.                 \Pimcore::collectGarbage();
  593.             }
  594.         } catch (\Throwable $e) {
  595.             $this->applicationLogger->info("Error while importing tour\n{$e->getMessage()}\n\n{$e->getTraceAsString()}", ['component' => 'AlpsteinImportCommand']);
  596.         }
  597.         $this->dump('----> Done');
  598.     }
  599.     private function importPois$alpsteinConfig ){
  600.         $poiIds $this->importPoiIdList($alpsteinConfig);
  601.         foreach ($this->validLanguage as $language) {
  602.             foreach( $poiIds as $poiId ){
  603.                 $url 'https://www.outdooractive.com/api/project/' $alpsteinConfig['project'] . '/oois/' $poiId '?lang=' $language '&key=' $alpsteinConfig['apiKey'];
  604.                 if(in_array(self::IGNORE_FALLBACK$this->options)) {
  605.                     $url .= '&fallback=false';
  606.                 }
  607.                 $client $this->client;
  608.                 $requestType 'GET';
  609.                 $config = [
  610.                     \GuzzleHttp\RequestOptions::ALLOW_REDIRECTS => [
  611.                         'max' => 2
  612.                     ],
  613.                     \GuzzleHttp\RequestOptions::TIMEOUT => 60
  614.                 ];
  615.                 $config[\GuzzleHttp\RequestOptions::HEADERS] = [
  616.                     'Accept' => 'application/json'
  617.                 ];
  618.                 /**
  619.                  * @var $response \GuzzleHttp\Psr7\Response
  620.                  */
  621.                 try {
  622.                     $response $client->request($requestType$url$config);
  623.                 } catch (\Throwable $exception) {
  624.                     $this->dump('################### ERROR ###################');
  625.                     $this->dump($exception->getMessage());
  626.                     $this->dump($exception->getTraceAsString());
  627.                     $this->dump('################### ERROR ###################');
  628.                 }
  629.                 if ($response && $response->getStatusCode() == 200) {
  630.                     $data $response->getBody();
  631.                     $poiArray json_decode($data->getContents());
  632.                     if( $poiArray->poi[0] && in_array($language$poiArray->poi[0]->meta->translation ) ){
  633.                         $this->createPoi$poiArray->poi[0], $alpsteinConfig['keyObject'], $language );
  634.                     }
  635.                 }
  636.                 $this->dump(" ");
  637.             }
  638.         }
  639.         $this->dump('----> Done');
  640.     }
  641.     /**
  642.      * Import List of Id's
  643.      * @param string $language
  644.      * @return array
  645.      * @throws \GuzzleHttp\Exception\GuzzleException
  646.      */
  647.     private function importTourIdList$alpsteinConfig$language 'de' ) : array {
  648.         $tourIds = [];
  649.         $url 'https://www.outdooractive.com/api/project/' $alpsteinConfig['project'] . '/tours?key=' $alpsteinConfig['apiKey'];
  650.         if (in_array('delta'$this->options) && file_exists(PIMCORE_PRIVATE_VAR self::TIMESTAMPFILE)) {
  651.             $timestamp Carbon::createFromTimestamp((int)file_get_contents(PIMCORE_PRIVATE_VAR self::TIMESTAMPFILE));
  652.             $url .= '&lastModifiedAfter=' $timestamp->format('d.m.Y');
  653.         }
  654.         $client $this->client;
  655.         $requestType 'GET';
  656.         $config = [
  657.             \GuzzleHttp\RequestOptions::ALLOW_REDIRECTS => [
  658.                 'max' => 2
  659.             ],
  660.             \GuzzleHttp\RequestOptions::TIMEOUT => 60
  661.         ];
  662.         $config[\GuzzleHttp\RequestOptions::HEADERS] = [
  663.             'Accept' => 'application/json'
  664.         ];
  665.         /**
  666.          * @var $response \GuzzleHttp\Psr7\Response
  667.          */
  668.         try {
  669.             $response $client->request($requestType$url$config);
  670.         } catch (\Throwable $exception) {
  671.             $this->dump('################### ERROR ###################');
  672.             $this->dump($exception->getMessage());
  673.             $this->dump($exception->getTraceAsString());
  674.             $this->dump('################### ERROR ###################');
  675.             $this->applicationLogger->info("error importing tour: \n{$exception->getMessage()}", ['component' => 'AlpsteinImportCommand']);
  676.         }
  677.         if ($response && $response->getStatusCode() == 200) {
  678.             $data $response->getBody();
  679.             $tourArray json_decode($data->getContents());
  680.             foreach ($tourArray->data ?? [] as $itemArray) {
  681.                 $tourIds[] = $itemArray->id;
  682.             }
  683.         }
  684.         return $tourIds;
  685.     }
  686.     /**
  687.      * Import List of Id's
  688.      * @param string $language
  689.      * @return array
  690.      * @throws \GuzzleHttp\Exception\GuzzleException
  691.      */
  692.     private function importPoiIdList$alpsteinConfig$language 'de' ) : array {
  693.         $poiIds = [];
  694.         $url 'https://www.outdooractive.com/api/project/' $alpsteinConfig['project'] . '/pois?key=' $alpsteinConfig['apiKey'];
  695.         if (in_array('delta'$this->options) && file_exists(PIMCORE_PRIVATE_VAR self::TIMESTAMPFILE)) {
  696.             $timestamp Carbon::createFromTimestamp((int)file_get_contents(PIMCORE_PRIVATE_VAR self::TIMESTAMPFILE));
  697.             $url .= '&lastModifiedAfter=' $timestamp->format('d.m.Y');
  698.         }
  699.         $client $this->client;
  700.         $requestType 'GET';
  701.         $config = [
  702.             \GuzzleHttp\RequestOptions::ALLOW_REDIRECTS => [
  703.                 'max' => 2
  704.             ],
  705.             \GuzzleHttp\RequestOptions::TIMEOUT => 60
  706.         ];
  707.         $config[\GuzzleHttp\RequestOptions::HEADERS] = [
  708.             'Accept' => 'application/json'
  709.         ];
  710.         /**
  711.          * @var $response \GuzzleHttp\Psr7\Response
  712.          */
  713.         try {
  714.             $response $client->request($requestType$url$config);
  715.         } catch (\Throwable $exception) {
  716.             $this->dump('################### ERROR ###################');
  717.             $this->dump($exception->getMessage());
  718.             $this->dump($exception->getTraceAsString());
  719.             $this->dump('################### ERROR ###################');
  720.         }
  721.         if ($response && $response->getStatusCode() == 200) {
  722.             $data $response->getBody();
  723.             $poiArray json_decode($data->getContents());
  724.             foreach ($poiArray->data as $itemArray) {
  725.                 $poiIds[] = $itemArray->id;
  726.             }
  727.         }
  728.         return $poiIds;
  729.     }
  730.     // Create or Update Tour
  731.     private function createTour$tour$keyObject$language 'de' ){
  732.         /** not yet considered Fields:
  733.          * - lineOptions
  734.          * - riskPotential
  735.          * - exposition
  736.          * - wayType
  737.          * - elements
  738.          * - difficulties
  739.          * - literature
  740.          * - maps
  741.          * - bookWorks
  742.          * - mapWorks
  743.          * - localizedTitle
  744.          * - type
  745.          * - frontendtype
  746.          * - license
  747.          */
  748.         $tourObject AlpsteinTour::getByAlpsteinId( (int)$tour->id, [ 'limit' => 1'unpublished' => true ] );
  749.         // ignore tours not meeting minimumRanking condition and unpublish if already exists
  750.         if ($this->minimumRanking && $tour->ranking $this->minimumRanking) {
  751.             if ($tourObject instanceof AlpsteinTour) {
  752.                 $tourObject->setPublished(false);
  753.                 $tourObject->save();
  754.             }
  755.             return;
  756.         }
  757.         if( !$tourObject instanceof AlpsteinTour ){
  758.             $tourObject = new AlpsteinTour();
  759.             $tourObject->setKey\Pimcore\File::getValidFilename( ($tour->title ?? 'no-title') . '-' $tour->id ) );
  760.             $tourObject->setAlpsteinId( (int)$tour->id );
  761.             $tourObject->setParent$this->tourFolder );
  762.             $tourObject->save();
  763.         }
  764.         $catAlpsteinKeys $tourObject->getAlpsteinKey();
  765.         $hasKey false;
  766.         foreach( $catAlpsteinKeys as $keyObj ){
  767.             if( $keyObj->getApiKey() == $keyObject->getApiKey() ){
  768.                 $hasKey true;
  769.                 break;
  770.             }
  771.         }
  772.         if( !$hasKey ){
  773.             $catAlpsteinKeys[] = $keyObject;
  774.         }
  775.         $tourObject->setAlpsteinKey$catAlpsteinKeys );
  776.         $this->dump('-> Tour: ' $tourObject->getName('de') . '(' $tourObject->getId() . ')');
  777.         $published false;
  778.         if( $tour->meta->workflow->state == 'published' ){
  779.             $published true;
  780.         }
  781.         if(isset($tour->meta->source) && $tour->meta->source != ''){
  782.             $this->dump('-> Tour Source: ' $tourObject->getName('de') . '(' $tour->meta->source->id ')');
  783.             $source $tour->meta->source;
  784.             $sourceObject $this->createSource($source$language);
  785.             $tourObject->setSource($sourceObject);
  786.         }
  787.         if(isset($tour->meta->authorFull)  && $tour->meta->authorFull != ''){
  788.             $this->dump('-> Tour Author: ' $tourObject->getName('de') . '(' $tour->meta->authorFull->id ')');
  789.             $author $tour->meta->authorFull;
  790.             $authorObject $this->createAuthor($author);
  791.             $tourObject->setAuthorFull($authorObject);
  792.         }
  793.         $tourObject->setAuthor($tour->meta->author ?? '');
  794.         if ($tourObject->getId() == '' ) {
  795.             p_r($tour->meta->workflow); die();
  796.         }
  797.         $tourObject->setPublished$published );
  798.         $tourObject->setName$tour->title ?? ''$language );
  799.         $tourObject->setRanking($tour->ranking ?? '');
  800.         // Destination
  801.         $tourObject->setDestination$tour->destination ?? ''$language );
  802.         //ShortText
  803.         $tourObject->setShortText$tour->shortText ?? ''$language );
  804.         // Longtext
  805.         $tourObject->setLongText$tour->longText ?? ''$language );
  806.         // Import all Images and return an array [ primaryImage, allImages ]
  807.         $primaryId null;
  808.         $primaryTitle 'primaryImage';
  809.         if( isset($tour->primaryImage) && isset($tour->primaryImage->id) ){
  810.             $primaryId $tour->primaryImage->id;
  811.             if(isset($tour->primaryImage->title)) {
  812.                 $primaryTitle $tour->primaryImage->title;
  813.             }
  814.         }
  815.         if (!in_array('skip-images'$this->options)) {
  816.             if( isset( $tour->images ) ){
  817.                 $images $this->loadAllImages$tourObject$tour->id$tour->images->image$primaryId$language$primaryTitle );
  818.                 if( !is_null$images'primaryImage' ] ) ){
  819.                     $tourObject->setPrimaryImage$images'primaryImage' ] );
  820.                 }
  821.                 if( !is_null$images'videos' ] ) ){
  822.                     $tourObject->setVideos$images'videos' ] );
  823.                 }
  824.                 if( in_array'full'$this->options ) ){
  825.                     if( !is_null$images'allImages' ] ) ){
  826.                         $tourObject->setImages$images'allImages' ] );
  827.                     }
  828.                 }
  829.             }
  830.         }
  831.         // set Category
  832.         $category AlpsteinCategory::getByCategoryId$tour->category->id, [ 'limit' => 1'unpublished' => true ] );
  833.         if( $category ){
  834.             $tourObject->setCategory([ $category ]);
  835.         }
  836.         // Opened
  837.         if (isset( $tour->opened ) && $tour->opened !== null){
  838.             $tourObject->setOpened($tour->opened);
  839.         } else {
  840.             $tourObject->setOpened(true);
  841.         }
  842.         // -- Regions
  843.         $oldRegions $tourObject->getRegions();
  844.         if( isset($tour->regions) && isset($tour->regions->region) ) {
  845.             $regions = [];
  846.             foreach ($tour->regions->region as $regionData) {
  847.                 if (!isset($this->regionCache[$regionData->id]) instanceof AlpsteinRegion) {
  848.                     $this->regionCache[$regionData->id] = AlpsteinRegion::getByAlpsteinId((string) $regionData->id1);
  849.                 }
  850.                 $region $this->regionCache[$regionData->id];
  851.                 if ($region instanceof AlpsteinRegion) {
  852.                     $objectMetadata = new ObjectMetadata('regions', ['isStartingRegion'], $region);
  853.                     $oldIsStartingRegion null;
  854.                     if($tourObject->getDoNotUpdateStartingRegion()) { //if not set, always update starting region
  855.                         $oldIsStartingRegion $this->getStartingRegionFromOldRegionsArray($region$oldRegions);
  856.                     }
  857.                     if($oldIsStartingRegion === null) {
  858.                         if (isset($regionData->isStartRegion)) {
  859.                             $objectMetadata->setIsStartingRegion(true);
  860.                         } else {
  861.                             $objectMetadata->setIsStartingRegion(false);
  862.                         }
  863.                     } else { //old region did exist + getDoNotUpdateStartingRegion === true
  864.                         $objectMetadata->setIsStartingRegion($oldIsStartingRegion);
  865.                     }
  866.                     $regions[] = $objectMetadata;
  867.                 }
  868.             }
  869.             $tourObject->setRegions($regions);
  870.         }
  871.         // -- Texte
  872.         if( in_array'full'$this->options ) ){
  873.             // global
  874.             $tourObject->setStartingPointDesc$tour->startingPointDescr ?? ''$language );
  875.             // transit
  876.             $tourObject->setPublicTransit$tour->publicTransit ?? ''$language );
  877.             // getting There
  878.             $tourObject->setGettingThere$tour->gettingThere ?? ''$language );
  879.             // parking
  880.             $tourObject->setParking$tour->parking ?? ''$language );
  881.             // Safety Guide
  882.             $tourObject->setSafetyGuidlines$tour->safetyGuidlines ?? ''$language );
  883.             // Tip
  884.             $tourObject->setTip$tour->tip ?? ''$language );
  885.             // Additional Information
  886.             $tourObject->setEquipment$tour->equipment ?? ''$language );
  887.             // Additional Information
  888.             $tourObject->setAdditionalInformation$tour->additionalInformation ?? ''$language );
  889.             // Direction
  890.             $tourObject->setDirections$tour->directions ?? ''$language);
  891.             // -- Labels
  892.             // top
  893.             $tourObject->setTop$tour->labels->top ?? '' );
  894.             //publicTransportFriendly
  895.             if( isset( $tour->labels) ){
  896.                 $tourObject->setPublicTransportFriendly$tour->labels->publicTransportFriendly ?? '' );
  897.             }
  898.             // winter activity
  899.             $tourObject->setWinterActivity$tour->winterActivity ?? '' );
  900.             // -- Data
  901.             // Publisher ID
  902.             $tourObject->setPublisherID$tour->meta->source->id ?? '' );
  903.             // Time Min
  904.             $tourObject->setTimeMin$tour->time->min ?? '' );
  905.             // Length
  906.             $tourObject->setLength$tour->length ?? '' );
  907.             // Elevation
  908.             $tourObject->setElevationAscent$tour->elevation->ascent ?? '' );
  909.             $tourObject->setElevationDescent$tour->elevation->descent ?? '' );
  910.             $tourObject->setElevationMinAltitude$tour->elevation->minAltitude ?? '' );
  911.             $tourObject->setElevationMaxAltitude$tour->elevation->maxAltitude ?? '' );
  912.             $tourObject->setElevationProfileId$tour->elevationProfile->id ?? '');
  913.             // Rating
  914.             $tourObject->setRatingCondition$tour->rating->condition ?? '' );
  915.             $tourObject->setRatingDifficulty$tour->rating->difficulty ?? '' );
  916.             $tourObject->setRatingTechnique$tour->rating->technique ?? '' );
  917.             $tourObject->setRatingQualityExp$tour->rating->qualityOfExperience ?? '' );
  918.             $tourObject->setRatingLandscape$tour->rating->landscape ?? '' );
  919.             // -- Season
  920.             foreach( [ 'jan''feb''mar''apr''may''jun''jul''aug''sep''oct''nov''dec' ] as $season ){
  921.                 $setter 'set' ucfirst($season);
  922.                 $tourObject->$setter$tour->season->{$season} );
  923.             }
  924.             // -- License
  925.             $license false;
  926.             if (isset($tour->meta) && isset($tour->meta->license)) {
  927.                 $license $this->getLicenseByFid($tour->meta->license->short);
  928.             }
  929.             if ($license) {
  930.                 $tourObject->setProperty('ulicense_object''object'$license);
  931.             } else {
  932.                 $tourObject->setProperty('ulicense_object''object'$this->defaultLicense);
  933.             }
  934.             $pois = [];
  935.             if( isset( $tour->pois ) ){
  936.                 foreach ($tour->pois->poi ?? [] as $poi) {
  937.                     $poiObject AlpsteinPoi::getByAlpsteinId($poi->id1);
  938.                     if ($poiObject instanceof AlpsteinPoi) {
  939.                         $objectMetadata = new ObjectMetadata('pois', ['isElevationProfilePoi''isReststopPoi''isRecommendationPoi'], $poiObject);
  940.                         if ($poi->isElevationProfilePoi ?? false) {
  941.                             $objectMetadata->setIsElevationProfilePoi(true);
  942.                         }
  943.                         if ($poi->isReststopPoi ?? false) {
  944.                             $objectMetadata->setIsReststopPoi(true);
  945.                         }
  946.                         if ($poi->isRecommendationPoi ?? false) {
  947.                             $objectMetadata->setIsRecommendationPoi(true);
  948.                         }
  949.                         $pois[] = $objectMetadata;
  950.                     }
  951.                 }
  952.             }
  953.             $tourObject->setPois($pois);
  954.             // -- GEO
  955.             // Destination
  956.             $tourObject->setDestination$tour->destination ?? ''$language );
  957.             // startingPoint
  958.             $startingGeo = new GeoCoordinates();
  959.             $startingGeo->setLatitude$tour->startingPoint->lat );
  960.             $startingGeo->setLongitude$tour->startingPoint->lon );
  961.             $tourObject->setStartingPoint$startingGeo );
  962.             // geoPositions (tour)
  963.             $tourObject->setGeometry$tour->geometry );
  964.             // -- Properties
  965.             if( isset( $tour->properties)){
  966.                 $tourProperties $this->tourProperties$tour->properties->property ?? ''$language );
  967.                 $tourObject->setTourProperties$tourProperties );
  968.             }
  969.         } // end only full import
  970.         $tourObject->save();
  971.         $this->importedTourIds[] = $tourObject->getAlpsteinId();
  972.     }
  973.     // Create or Update Poi
  974.     private function createPoi$poi$keyObject$language 'de' ){
  975.         /** not yet considered Fields:
  976.          * - frontendtype
  977.          * - license
  978.          */
  979.         $poiObject AlpsteinPoi::getByAlpsteinId( (int)$poi->id, [ 'limit' => 1'unpublished' => true ] );
  980.         // ignore tours not meeting minimumRanking condition and unpublish if already exists
  981.         if ($this->minimumRanking && $poi->ranking $this->minimumRanking) {
  982.             if ($poiObject instanceof AlpsteinPoi) {
  983.                 $poiObject->setPublished(false);
  984.                 $poiObject->save();
  985.             }
  986.             return;
  987.         }
  988.         if( !$poiObject instanceof AlpsteinPoi ){
  989.             $poiObject = new AlpsteinPoi();
  990.             $poiObject->setKey\Pimcore\File::getValidFilename$poi->title '-' $poi->id ) );
  991.             $poiObject->setAlpsteinId( (int)$poi->id );
  992.             $poiObject->setParent$this->poiFolder );
  993.             $poiObject->save();
  994.         }
  995.         $catAlpsteinKeys $poiObject->getAlpsteinKey();
  996.         $hasKey false;
  997.         foreach( $catAlpsteinKeys as $keyObj ){
  998.             if( $keyObj->getApiKey() == $keyObject->getApiKey() ){
  999.                 $hasKey true;
  1000.                 break;
  1001.             }
  1002.         }
  1003.         if( !$hasKey ){
  1004.             $catAlpsteinKeys[] = $keyObject;
  1005.         }
  1006.         $poiObject->setAlpsteinKey$catAlpsteinKeys );
  1007.         $this->dump('-> POI: ' $poiObject->getName('de') . '(' $poiObject->getId() . ')');
  1008.         $published false;
  1009.         if( $poi->meta->workflow->state == 'published' ){
  1010.             $published true;
  1011.         }
  1012.         if ($poiObject->getId() == '' ) {
  1013.             p_r($poi->meta->workflow); die();
  1014.         }
  1015.         $poiObject->setPublished$published );
  1016.         $poiObject->setName$poi->title ?? ''$language );
  1017.         $poiObject->setRanking($poi->ranking ?? '');
  1018.         $poiObject->setFrontendType($poi->frontendtype ?? '');
  1019.         //ShortText
  1020.         $poiObject->setShortText$poi->shortText ?? ''$language );
  1021.         // Longtext
  1022.         $poiObject->setLongText$poi->longText ?? ''$language );
  1023.         // Import all Images and return an array [ primaryImage, allImages ]
  1024.         $primaryId null;
  1025.         $primaryTitle 'primaryImage';
  1026.         if( isset($poi->primaryImage) && isset($poi->primaryImage->id) ){
  1027.             $primaryId $poi->primaryImage->id;
  1028.             if(isset($poi->primaryImage->title)) {
  1029.                 $primaryTitle $poi->primaryImage->title;
  1030.             }
  1031.         }
  1032.         if (!in_array('skip-images'$this->options)) {
  1033.             if (isset($poi->images)) {
  1034.                 $images $this->loadAllImages($poiObject$poi->id$poi->images->image$primaryId$language,
  1035.                     $primaryTitle);
  1036.                 if (!is_null($images['primaryImage'])) {
  1037.                     $poiObject->setPrimaryImage($images['primaryImage']);
  1038.                 }
  1039.                 if (!is_null($images['videos'])) {
  1040.                     $poiObject->setVideos($images['videos']);
  1041.                 }
  1042.                 if (in_array('full'$this->options)) {
  1043.                     if (!is_null($images['allImages'])) {
  1044.                         $poiObject->setImages($images['allImages']);
  1045.                     }
  1046.                 }
  1047.             }
  1048.         }
  1049.         // set Category
  1050.         $category AlpsteinCategory::getByCategoryId$poi->category->id, [ 'limit' => 1'unpublished' => true ] );
  1051.         if( $category ){
  1052.             $poiObject->setCategory([ $category ]);
  1053.         }
  1054.         // -- Labels
  1055.         // top
  1056.         $poiObject->setTop$poi->labels->top ?? '' );
  1057.         // winter activity
  1058.         $poiObject->setWinterActivity$poi->winterActivity ?? '' );
  1059.         $poiObject->setAltitude$poi->altitude ?? '' );
  1060.         // contact data
  1061.         $poiObject->setStreet($poi->address->street ?? '');
  1062.         $poiObject->setZipcode($poi->address->zipcode ?? '');
  1063.         $poiObject->setTown($poi->address->town ?? '');
  1064.         $poiObject->setHomepage($poi->homepage ?? '');
  1065.         $poiObject->setEmail($poi->email ?? '');
  1066.         $poiObject->setPhone($poi->phone ?? '');
  1067.         // Texte
  1068.         $poiObject->setPublicTransit($poi->publicTransit ?? ''$language);
  1069.         $poiObject->setGettingThere($poi->gettingThere ?? ''$language);
  1070.         $poiObject->setParking($poi->parking ?? ''$language);
  1071.         // Publisher ID
  1072.         $poiObject->setPublisherID$poi->meta->source->id ?? '');
  1073.         if(isset($poi->meta->source) && $poi->meta->source != ''){
  1074.             $this->dump('-> Poi Source: ' $poiObject->getName('de') . '(' $poi->meta->source->id ')');
  1075.             $source $poi->meta->source;
  1076.             $sourceObject $this->createSource($source$language);
  1077.             $poiObject->setSource($sourceObject);
  1078.         }
  1079.         if(isset($poi->meta->authorFull)  && $poi->meta->authorFull != ''){
  1080.             $this->dump('-> Poi Author: ' $poiObject->getName('de') . '(' $poi->meta->authorFull->id ')');
  1081.             $author $poi->meta->authorFull;
  1082.             $authorObject $this->createAuthor($author);
  1083.             $poiObject->setAuthorFull($authorObject);
  1084.         }
  1085.         $poiObject->setAuthor($poi->meta->author ?? '');
  1086.         // -- Regions
  1087.         if( isset($poi->regions) && isset($poi->regions->region) ) {
  1088.             $regions = [];
  1089.             foreach ($poi->regions->region as $regionData) {
  1090.                 if (!isset($this->regionCache[$regionData->id]) || !$this->regionCache[$regionData->id] instanceof AlpsteinRegion) {
  1091.                     $this->regionCache[$regionData->id] = AlpsteinRegion::getByAlpsteinId((string) $regionData->id1);
  1092.                 }
  1093.                 $region $this->regionCache[$regionData->id];
  1094.                 if ($region instanceof AlpsteinRegion) {
  1095.                     $objectMetadata = new ObjectMetadata('regions', ['isStartingRegion'], $region);
  1096.                     if ($regionData->isStartRegion) {
  1097.                         $objectMetadata->setIsStartingRegion(true);
  1098.                     }
  1099.                     $regions[] = $objectMetadata;
  1100.                 }
  1101.             }
  1102.             $poiObject->setRegions($regions);
  1103.         }
  1104.         // -- GEO
  1105.         // positions
  1106.         if (isset($poi->geometry)) {
  1107.             $posData explode(','$poi->geometry);
  1108.             $poiObject->setPosition( new GeoCoordinates($posData[0], $posData[1]) );
  1109.         }
  1110.         // -- Properties
  1111.         $poiProperties $this->tourProperties$poi->properties->property ?? [], $language );
  1112.         $poiObject->setPoiProperties$poiProperties );
  1113.         $poiObject->setBusinessHours($poi->businessHours ?? ''$language);
  1114.         $this->poiSetOpeningTimes($poiObject$poi->openingHours ?? []);
  1115.         $poiObject->save();
  1116.         $this->importedPoiIds[] = $poiObject->getAlpsteinId();
  1117.     }
  1118.     private function poiSetOpeningTimes($object$openingHours = []) {
  1119.         $dates $object->getOpeningTimes();
  1120.         if (!$dates) {
  1121.             $dates = new RecurringDateDefinition();
  1122.         }
  1123.         $definitionArray = [];
  1124.         if (!empty($openingHours->weekday->openTime)) {
  1125.             // as no daterange is given for the general openingtimes, but recurring dates needs a
  1126.             // daterange (otherwise for fromDate and toDate the current date from the import will be used),
  1127.             // the first day of the year is used for fromDate and the last day of the next year is for toDate
  1128.             $times = [];
  1129.             $dayMapping = [
  1130.                 'Monday' => 'mo',
  1131.                 'Tuesday' => 'tu',
  1132.                 'Wednesday' => 'we',
  1133.                 'Thursday' => 'th',
  1134.                 'Friday' => 'fr',
  1135.                 'Saturday' => 'sa',
  1136.                 'Sunday' => 'su',
  1137.             ];
  1138.             // start to get the times for every weekday
  1139.             foreach ($openingHours->weekday->openTime ?? [] as $date) {
  1140.                 foreach ($date->openHours ?? [] as $openHour) {
  1141.                     $timeFrom $openHour->from ?? null;
  1142.                     $timeTo $openHour->to ?? null;
  1143.                     $weekday $dayMapping[$date->weekday];
  1144.                     $times[$weekday]['times'][] = [
  1145.                         'start' => $timeFrom == '24:00' '23:59' $timeFrom,
  1146.                         'end' => $timeTo == '24:00' '23:59' $timeTo
  1147.                     ];
  1148.                 }
  1149.             }
  1150.             // combine all identical time entries to only get one entry for the same time on different weekdays
  1151.             $identicalTimes = [];
  1152.             $hashes = [];
  1153.             foreach ($times as $weekday => $time) {
  1154.                 $hash hash('sha256'serialize($time));
  1155.                 if (isset($hashes[$hash])) {
  1156.                     $identicalTimes[$hash] = array_merge($identicalTimes[$hash], [
  1157.                         $weekday => true
  1158.                     ]);
  1159.                 } else {
  1160.                     $hashes[$hash] = $weekday;
  1161.                     $identicalTimes[$hash] = array_merge($time, [
  1162.                         $weekday => true,
  1163.                         'fromDate' => Carbon::today()->setMonth(1)->setDay(1)->format('Y-m-d'),
  1164.                         'toDate' => Carbon::today()->setMonth(12)->setDay(31)->addYear()->format('Y-m-d'),
  1165.                     ]);
  1166.                 }
  1167.             }
  1168.             foreach ($identicalTimes as $entries) {
  1169.                 $definitionArray[] = [
  1170.                     'type' => RecurringDateDefinition::DEFINITION_TYPE_RECURRING_DATE_TIME,
  1171.                     'values' => $entries,
  1172.                 ];
  1173.             }
  1174.         }
  1175.         if (!empty($openingHours->special->openTime)) {
  1176.             $times = ['times' => []];
  1177.             foreach ($openingHours->special->openTime as $openTime) {
  1178.                 foreach ($openTime->openHours ?? [] as $openHour) {
  1179.                     $timeFrom $openHour->from ?? null;
  1180.                     $timeTo $openHour->to ?? null;
  1181.                     $times = [
  1182.                         'times' => [
  1183.                             [
  1184.                                 'start' => $timeFrom == '24:00' '23:59' $timeFrom,
  1185.                                 'end' => $timeTo == '24:00' '23:59' $timeTo
  1186.                             ]
  1187.                         ],
  1188.                         'mo' => in_array('MON'$openHour->days ?? []),
  1189.                         'tu' => in_array('TUE'$openHour->days ?? []),
  1190.                         'we' => in_array('WED'$openHour->days ?? []),
  1191.                         'th' => in_array('THU'$openHour->days ?? []),
  1192.                         'fr' => in_array('FRI'$openHour->days ?? []),
  1193.                         'sa' => in_array('SAT'$openHour->days ?? []),
  1194.                         'su' => in_array('SUN'$openHour->days ?? []),
  1195.                     ];
  1196.                 }
  1197.                 // special opening times depend on a time range, and can also be excluded
  1198.                 $definitionArray[] = [
  1199.                     'type' => RecurringDateDefinition::DEFINITION_TYPE_RECURRING_DATE_TIME,
  1200.                     'values' =>  array_merge([
  1201.                         'fromDate' => (string)$openTime->dateFrom,
  1202.                         'toDate' => (string)$openTime->dateTo,
  1203.                         'excluded' => $openTime->isOpen != 'true',
  1204.                     ], $times)
  1205.                 ];
  1206.             }
  1207.         }
  1208.         $dates->setDefinitionArray($definitionArray);
  1209.         $object->setOpeningTimes($dates);
  1210.     }
  1211.     /**
  1212.      * @param DataObject $relatedObject
  1213.      * @param $folderName
  1214.      * @param $imagesArray
  1215.      * @param string $language
  1216.      * @return array
  1217.      * @throws \Exception
  1218.      */
  1219.     private function loadAllImagesDataObject $relatedObject$folderName$imagesArray$primaryId null$language 'de'$primaryTitle 'primaryImage' ) : array{
  1220.         $this->dump('-> LoadImages');
  1221.         $imagesArray $imagesArray ?? [];
  1222.         $assetImage = [
  1223.             'primaryImage' => null,
  1224.             'allImages' => null,
  1225.             'videos' => null
  1226.         ];
  1227.         // Get Image Folder for Tour
  1228.         $folder \Pimcore\Model\Asset\Service::createFolderByPath$this->assetImageFolder $folderName );
  1229.         // Load Available Images
  1230.         $availableImages = [];
  1231.         foreach( $folder->getChildren() as $avImg ){
  1232.             try {
  1233.                 $availableImages$avImg->getMetadata('alpstein-img-id') ] = $avImg;
  1234.             } catch(\Exception $e) {
  1235.                 $this->applicationLogger->info("error accessing metadata (Folder: {$folder->getId()}, Image: {$avImg->getId()}): \n{$e->getMessage()}\n\n{$e->getTraceAsString()}", ['component' => 'AlpsteinImportCommand']);
  1236.             }
  1237.         }
  1238.         $this->dump('---> Images Available: ' . (bool)!empty($availableImages));
  1239.         // get all new Images
  1240.         foreach( $imagesArray as $image ){
  1241.             try {
  1242.                 $inGallery $image->gallery ?? '';
  1243.                 $isVideo $image->isVideo ?? '';
  1244.                 $isPrimary $image->primary ?? '';
  1245.                 if( !$isPrimary && !is_null($primaryId) ){
  1246.                     $isPrimary $primaryId == $image->id true false;
  1247.                 }
  1248.                 $date = new Carbon($image->meta->date->lastModified);
  1249.                 // -- License
  1250.                 $license false;
  1251.                 if (isset($image->meta) && isset($image->meta->license)) {
  1252.                     $license $this->getLicenseByFid($image->meta->license->short);
  1253.                 }
  1254.                 $this->dump('-------> Image: ' . ($image->title ?? ' no - title') . ' Primary: ' . (bool)$isPrimary );
  1255.                 if ($isVideo) {
  1256.                     if ($image->video && $image->video->youtubeId) { // only youtube supported for now
  1257.                         $videoObject AlpsteinVideo::getByAlpsteinId(trim($image->id), 1);
  1258.                         if (!$videoObject instanceof AlpsteinVideo) {
  1259.                             $videoObject = new AlpsteinVideo();
  1260.                             $videoObject->setPublished(true);
  1261.                             $videoObject->setKey(Service::getValidKey(trim($image->id), 'object'));
  1262.                             $videoObject->setParent($this->videosFolder);
  1263.                             $videoObject->setAlpsteinId(trim($image->id));
  1264.                         }
  1265.                         $videoData = new Video();
  1266.                         $videoData->setType('youtube');
  1267.                         $videoData->setData((string)$image->video->youtubeId);
  1268.                         $videoData->setTitle((string)$image->title ?? '');
  1269.                         $videoData->setDescription((string)$image->description);
  1270.                         $videoObject->setVideo($videoData$language);
  1271.                         $videoObject->setSource$image->source ?? '' );
  1272.                         if ($license) {
  1273.                             $videoObject->setProperty('ulicense_object''object'$license);
  1274.                         } else {
  1275.                             $videoObject->setProperty('ulicense_object''object'$this->defaultLicense);
  1276.                         }
  1277.                         $videoObject->save();
  1278.                         $assetImage['videos'][] = $videoObject;
  1279.                     }
  1280.                 } 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
  1281.                     $imageUrl 'http://img.oastatic.com/img/2048/2048/' $image->id '/.jpg';
  1282.                     try {
  1283.                         $loadedImage \Pimcore\Tool::getHttpData$imageUrl, [], [], ['timeout' => 60] );
  1284.                     } catch (\Throwable $exception) {
  1285.                         $this->dump('################### ERROR ###################');
  1286.                         $this->dump($exception->getMessage());
  1287.                         $this->dump($exception->getTraceAsString());
  1288.                         $this->dump('################### ERROR ###################');
  1289.                     }
  1290.                     if( $loadedImage ){
  1291.                         $name \Pimcore\Tool\Transliteration::toASCII($image->title ?? '');
  1292.                         if (strlen($name ?: '') > 50) {
  1293.                             $name substr($name050);
  1294.                         }
  1295.                         $filename \Pimcore\File::getValidFilename$name '-' $image->id ) . '.jpg';
  1296.                         if ($this->doRemoveICCProfile) {
  1297.                             $loadedImage \Elements\Bundle\AlpsteinBundle\Tools\Image::removeICCProfile($loadedImage$filename);
  1298.                         }
  1299.                         if( array_key_exists(trim($image->id), $availableImages) ){
  1300.                             $this->dump('------------> Override Image' );
  1301.                             /**
  1302.                              * @var $editImage Image
  1303.                              */
  1304.                             $newImage $availableImages[$image->id];
  1305.                             $newImage->setData$loadedImage );
  1306.                         }else{
  1307.                             $this->dump('------------> new Image' );
  1308.                             $newImage Image::getByPath$folder->getFullPath() . '/' $filename );
  1309.                             if( !$newImage instanceof Image ) {
  1310.                                 $newImage = new Image();
  1311.                             }
  1312.                             $newImage->addMetadata'alpstein-img-id''input'trim($image->id) );
  1313.                             $newImage->setData($loadedImage);
  1314.                             $newImage->setFilename$filename );
  1315.                             $newImage->setParent$folder );
  1316.                             $availableImages[trim($image->id)] = $newImage;
  1317.                         }
  1318.                         $newImage $this->addImageMetadata($newImage$image$language$date$inGallery$isPrimary$license);
  1319.                         $saveImageSuccess false;
  1320.                         try {
  1321.                             $newImage->save();
  1322.                             $saveImageSuccess true;
  1323.                             $this->dump('Image ID:' $image->id ' Image: ' . ($image->title ?? 'no-title' ));
  1324.                         } catch (\Throwable $exception) {
  1325.                             if (strpos($exception->getMessage(), 'Duplicate full path') === false) {
  1326.                                 $this->dump('Delete and retry Image ID:' $image->id ' Image: ' . ($image->title ?? 'no-title' ) . PHP_EOL $exception->getMessage());
  1327.                                 try {
  1328.                                     $newImage->delete();
  1329.                                 } catch (\Throwable $e) {
  1330.                                     $this->applicationLogger->info("Could not delete image after error occured\nrecreating image...:\n\n{$exception->getMessage()}\n{$exception->getTraceAsString()}", ['component' => 'AlpsteinImportCommand''relatedObject' => $relatedObject]);
  1331.                                 }
  1332.                                 $newImage = new Image();
  1333.                                 $newImage->addMetadata'alpstein-img-id''input'trim($image->id) );
  1334.                                 $newImage->setData($loadedImage);
  1335.                                 $newImage->setFilename$filename );
  1336.                                 $newImage->setParent$folder );
  1337.                                 $availableImages[trim($image->id)] = $newImage;
  1338.                                 $newImage $this->addImageMetadata($newImage$image$language$date$inGallery$isPrimary$license);
  1339.                                 $newImage->save();
  1340.                                 $saveImageSuccess true;
  1341.                                 $this->dump('Image ID:' $image->id ' Image: ' . ($image->title ?? 'no-title'));
  1342.                             } else {
  1343.                                 $saveImageSuccess false;
  1344.                                 $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]);
  1345.                             }
  1346.                         }
  1347.                         if( $saveImageSuccess && $isPrimary ){
  1348.                             $assetImage['primaryImage'] = $newImage;
  1349.                         }
  1350.                         if( $saveImageSuccess && $inGallery ){
  1351.                             $assetImage['allImages'][] = $newImage;
  1352.                         }
  1353.                     }
  1354.                 }
  1355.             } catch (\Exception $e) {
  1356.                 $this->applicationLogger->info("Could not import image " .
  1357.                     ($image && $image->id $image->id null) .
  1358.                     "\n{$e->getMessage()}\n\n{$e->getTraceAsString()}",
  1359.                     ['component' => 'AlpsteinImportCommand''relatedObject' => $relatedObject]);
  1360.             }
  1361.         }
  1362.         if(empty($assetImage['primaryImage']) && $primaryId) {
  1363.             $newPrimaryImage =  $this->createNewPrimaryImage($primaryId$folder$primaryTitle);
  1364.             $assetImage['primaryImage'] = $newPrimaryImage;
  1365.         }
  1366.         foreach( $imagesArray as $img ){
  1367.             if( array_key_exists($img->id$availableImages) ){
  1368.                 unset($availableImages[$img->id]);
  1369.             }
  1370.         }
  1371.         foreach( $availableImages as $deleteImage ){
  1372.             $deleteImage->delete();
  1373.         }
  1374.         return $assetImage;
  1375.     }
  1376.     private function addImageMetadata($newImage$image$language$date$inGallery$isPrimary$license ) {
  1377.         $imageAuthorName '';
  1378.         if (isset($image->author)) {
  1379.             $imageAuthorName $image->author;
  1380.         } else if (isset($image->meta->authorFull)) {
  1381.             $imageAuthorName $image->meta->authorfull->name;
  1382.         } else if (isset($image->meta->author)) {
  1383.             $imageAuthorName $image->meta->author;
  1384.         }
  1385.         $imageSourceName '';
  1386.         $imageSourceUrl '';
  1387.         if (isset($image->source)) {
  1388.             $imageSourceName = (string)$image->source ?? '';
  1389.         }
  1390.         if ($image->meta->source) {
  1391.             $imageSourceName = (string)$image->meta->source->name ?? '';
  1392.             $imageSourceUrl =  isset($image->meta->source->url) ? (string)$image->meta->source->url '';
  1393.         }
  1394.         if ($imageAuthorName) {
  1395.             $newImage->addMetadata'author''input'$imageAuthorName);
  1396.         }
  1397.         if ($imageSourceName) {
  1398.             $newImage->addMetadata('source''input'$imageSourceName);
  1399.         }
  1400.         if ($imageSourceUrl) {
  1401.             $newImage->addMetadata('sourceUrl''input'$imageSourceUrl);
  1402.         }
  1403.         $newImage->addMetadata'copyright''input'$image->meta->source->name);
  1404.         $newImage->addMetadata'title''input'$image->title ?? ''$language );
  1405.         $newImage->addMetadata'last-modified''input'$date->timestamp );
  1406.         $newImage->addMetadata'gallery''checkbox'$inGallery );
  1407.         $newImage->addMetadata'primary''checkbox'$isPrimary );
  1408.         if ($license) {
  1409.             $newImage->setProperty('ulicense_object''object'$license);
  1410.         } else {
  1411.             $newImage->setProperty('ulicense_object''object'$this->defaultLicense);
  1412.         }
  1413.         return $newImage;
  1414.     }
  1415.     /**
  1416.      * @param $properties
  1417.      * @param string $language
  1418.      * @return array
  1419.      * @throws \Exception
  1420.      */
  1421.     private function tourProperties$properties$language 'de' ){
  1422.         $tourPropertiesArray = [];
  1423.         $properties $properties ?? [];
  1424.         foreach( $properties as $prop ){
  1425.             $propObj AlpsteinProperty::getByTag$prop->tag, [ 'limit' => 1'unpublished' => true ] );
  1426.             if( !$propObj instanceof AlpsteinProperty ){
  1427.                 $propObj = new AlpsteinProperty();
  1428.                 $propObj->setKey\Pimcore\File::getValidFilename($prop->tag '-' time() ) );
  1429.                 $propObj->setParent$this->objectPropertiesFolder );
  1430.                 $propObj->setPublishedtrue );
  1431.                 $propObj->setTag$prop->tag );
  1432.             }
  1433.             if (isset($prop->text) && $prop->text != '') {
  1434.                 $propObj->setName$prop->text$language );
  1435.             }
  1436.             if(isset($prop->hasIcon)){
  1437.                 $filename \Pimcore\File::getValidFilename$prop->text );
  1438.                 $icon Image::getByPath$this->assetPropertiesFolder->getFullPath() . '/' $filename '.svg' );
  1439.                 //$this->assetPropertiesFolder;
  1440.                 if( !$icon instanceof Image && isset($prop->iconURL) ){
  1441.                     try {
  1442.                         $imageUrl \Pimcore\Tool::getHttpData($prop->iconURL, [], [], ['timeout' => 60]);
  1443.                     } catch (\Throwable $exception) {
  1444.                         $this->dump('################### ERROR ###################');
  1445.                         $this->dump($exception->getMessage());
  1446.                         $this->dump($exception->getTraceAsString());
  1447.                         $this->dump('################### ERROR ###################');
  1448.                     }
  1449.                     if( $imageUrl ){
  1450.                         $icon = new Image();
  1451.                         $icon->setFilename$filename '.svg' );
  1452.                         $icon->setParent$this->assetPropertiesFolder );
  1453.                         $icon->setData($imageUrl);
  1454.                         $icon->save();
  1455.                         $propObj->setIcon$icon );
  1456.                     }
  1457.                 }
  1458.             }
  1459.             $propObj->save();
  1460.             $tourPropertiesArray[] = $propObj;
  1461.         }
  1462.         return $tourPropertiesArray;
  1463.     }
  1464.     /**
  1465.      * @param $source
  1466.      * @param string $language
  1467.      */
  1468.     private function createSource($source$language 'de' ){
  1469.         if($source && isset($source->id)) {
  1470.             $sourceObj AlpsteinSource::getBySourceId($source->id, ['limit' => 1'unpublished' => true]);
  1471.             if (!$sourceObj instanceof AlpsteinSource) {
  1472.                 $this->dump('------------> new source ' $source->id);
  1473.                 $sourceObj = new AlpsteinSource();
  1474.                 $sourceObj->setKey(\Pimcore\File::getValidFilename($source->id '-' $source->name));
  1475.                 $sourceObj->setParent($this->objectSourceFolder);
  1476.                 $sourceObj->setPublished(true);
  1477.                 $sourceObj->setSourceId($source->id);
  1478.             }
  1479.             if (isset($source->name) && $source->name != '') {
  1480.                 $sourceObj->setName($source->name$language);
  1481.             }
  1482.             if (isset($source->url) && $source->url != '') {
  1483.                 $sourceObj->setUrl($source->url);
  1484.             }
  1485.             if (!in_array('skip-images'$this->options)) {
  1486.                 if (isset($source->logo)) {
  1487.                     $logo $source->logo;
  1488.                     $folder \Pimcore\Model\Asset\Service::createFolderByPath($this->assetSourceFolder '/' $source->id);
  1489.                     $sourceLogoAsset $this->createNewPrimaryImage($logo->id$folder'');
  1490.                     if ($sourceLogoAsset instanceof Image) {
  1491.                         $sourceLogoAsset->addMetadata('title''input'$logo->title ?? ''$language);
  1492.                         if ($source->name) {
  1493.                             $sourceLogoAsset->addMetadata('source''input'$source->name$language);
  1494.                         }
  1495.                         if ($source->url) {
  1496.                             $sourceLogoAsset->addMetadata('sourceUrl''input'$source->url);
  1497.                         }
  1498.                         try {
  1499.                             $sourceLogoAsset->save();
  1500.                         } catch (\Throwable $exception) {
  1501.                             $this->applicationLogger->info("Could not set metadata to source logo asset \n\n{$exception->getMessage()}\n{$exception->getTraceAsString()}",
  1502.                                 ['component' => 'AlpsteinImportCommand''relatedObject' => $sourceObj]);
  1503.                         }
  1504.                         $sourceObj->setLogo($sourceLogoAsset);
  1505.                     }
  1506.                 }
  1507.                 if (isset($source->favicon)) {
  1508.                     $favicon $source->favicon;
  1509.                     $folder \Pimcore\Model\Asset\Service::createFolderByPath($this->assetSourceFolder '/' $source->id);
  1510.                     $sourceFaviconAsset $this->createNewPrimaryImage($favicon->id$folder'');
  1511.                     if ($sourceFaviconAsset instanceof Image) {
  1512.                         $sourceFaviconAsset->addMetadata('title''input'$favicon->title ?? ''$language);
  1513.                         if ($source->name) {
  1514.                             $sourceFaviconAsset->addMetadata('source''input'$source->name$language);
  1515.                         }
  1516.                         if ($source->url) {
  1517.                             $sourceFaviconAsset->addMetadata('sourceUrl''input'$source->url);
  1518.                         }
  1519.                         try {
  1520.                             $sourceFaviconAsset->save();
  1521.                         } catch (\Throwable $exception) {
  1522.                             $this->applicationLogger->info("Could not set metadata to source favicon asset \n\n{$exception->getMessage()}\n{$exception->getTraceAsString()}",
  1523.                                 ['component' => 'AlpsteinImportCommand''relatedObject' => $sourceObj]);
  1524.                         }
  1525.                         $sourceObj->setFavicon($sourceFaviconAsset);
  1526.                     }
  1527.                 }
  1528.             }
  1529.             try {
  1530.                 $sourceObj->save();
  1531.                 return $sourceObj;
  1532.             } catch (\Throwable $exception) {
  1533.                 $this->applicationLogger->info("Could not save source object \n\n{$exception->getMessage()}\n{$exception->getTraceAsString()}",
  1534.                     ['component' => 'AlpsteinImportCommand''relatedObject' => $sourceObj]);
  1535.             }
  1536.         }
  1537.         return null;
  1538.     }
  1539.     /**
  1540.      * @param $authorFull
  1541.      */
  1542.     private function createAuthor($authorFull ){
  1543.         if($authorFull && isset($authorFull->id)) {
  1544.             $authorObj AlpsteinAuthor::getByAuthorId($authorFull->id, ['limit' => 1'unpublished' => true]);
  1545.             if (!$authorObj instanceof AlpsteinAuthor) {
  1546.                 $this->dump('------------> new author ' $authorFull->id);
  1547.                 $authorObj = new AlpsteinAuthor();
  1548.                 $authorObj->setKey(\Pimcore\File::getValidFilename($authorFull->id '-' $authorFull->name));
  1549.                 $authorObj->setParent($this->objectAuthorFolder);
  1550.                 $authorObj->setPublished(true);
  1551.                 $authorObj->setAuthorId($authorFull->id);
  1552.             }
  1553.             if (isset($authorFull->name) && $authorFull->name != '') {
  1554.                 $authorObj->setName($authorFull->name);
  1555.             }
  1556.             if (!in_array('skip-images'$this->options)) {
  1557.                 if (isset($authorFull->profileImageId)) {
  1558.                     $folder \Pimcore\Model\Asset\Service::createFolderByPath($this->assetAuthorFolder '/' $authorFull->id);
  1559.                     $authorProfileAsset $this->createNewPrimaryImage($authorFull->profileImageId$folder,
  1560.                         $authorFull->name ?? '');
  1561.                     if ($authorProfileAsset instanceof Image) {
  1562.                         $authorProfileAsset->addMetadata('title''input'$authorFull->name ?? '');
  1563.                         try {
  1564.                             $authorProfileAsset->save();
  1565.                         } catch (\Throwable $exception) {
  1566.                             $this->applicationLogger->info("Could not set metadata to author profile image asset \n\n{$exception->getMessage()}\n{$exception->getTraceAsString()}",
  1567.                                 ['component' => 'AlpsteinImportCommand''relatedObject' => $authorObj]);
  1568.                         }
  1569.                         $authorObj->setProfileImage($authorProfileAsset);
  1570.                     }
  1571.                 }
  1572.             }
  1573.             try {
  1574.                 $authorObj->save();
  1575.                 return $authorObj;
  1576.             } catch (\Throwable $exception) {
  1577.                 $this->applicationLogger->info("Could not save author object \n\n{$exception->getMessage()}\n{$exception->getTraceAsString()}",
  1578.                     ['component' => 'AlpsteinImportCommand''relatedObject' => $authorObj]);
  1579.             }
  1580.         }
  1581.         return null;
  1582.     }
  1583.     protected $licenses = [];
  1584.     protected function getLicenseByFid($fid) {
  1585.         if (!array_key_exists($fid$this->licenses) || !$this->licenses[$fid]) {
  1586.             $db Db::get();
  1587.             $id $db->fetchOne('SELECT o_id FROM object_collection_ULicenseFid_ULicense WHERE systemIdentifier = "Alpstein" AND fid = ' $db->quote($fid));
  1588.             if ($id) {
  1589.                 $this->licenses[$fid] = ULicense::getById($id);
  1590.             }
  1591.         }
  1592.         if (!array_key_exists($fid$this->licenses) || !$this->licenses[$fid]) {
  1593.             ApplicationLogger::getInstance()->warning('Could not find License for FID ' $fid, ['component' => 'Alpstein Importer']);
  1594.         }
  1595.         return $this->licenses[$fid];
  1596.     }
  1597.     private function createNewPrimaryImage($primaryId$folder$primaryTitle)
  1598.     {
  1599.         $this->dump('------------> new Primary Image' );
  1600.         $imageUrl 'http://img.oastatic.com/img/2048/2048/' $primaryId '/.jpg';
  1601.         try {
  1602.             $loadedImage \Pimcore\Tool::getHttpData$imageUrl, [], [], ['timeout' => 60] );
  1603.         } catch (\Throwable $exception) {
  1604.             $this->dump('################### ERROR ###################');
  1605.             $this->dump($exception->getMessage());
  1606.             $this->dump($exception->getTraceAsString());
  1607.             $this->dump('################### ERROR ###################');
  1608.             return null;
  1609.         }
  1610.         if ($loadedImage) {
  1611.             if (strlen($primaryTitle ?: '') > 50) {
  1612.                 $primaryTitle substr($primaryTitle050);
  1613.             }
  1614.             $filename \Pimcore\File::getValidFilename$primaryTitle '-' $primaryId ) . '.jpg';
  1615.             if ($this->doRemoveICCProfile) {
  1616.                 $loadedImage \Elements\Bundle\AlpsteinBundle\Tools\Image::removeICCProfile($loadedImage$filename);
  1617.             }
  1618.             $newImage Image::getByPath$folder->getFullPath() . '/' $filename );
  1619.             if( !$newImage instanceof Image ) {
  1620.                 $newImage = new Image();
  1621.             }
  1622.             $newImage->addMetadata'alpstein-img-id''input'trim($primaryId) );
  1623.             $newImage->setData($loadedImage);
  1624.             $newImage->setFilename$filename );
  1625.             $newImage->setParent$folder );
  1626.             //no metadata in primary Image
  1627. //        $newImage = $this->addImageMetadata($newImage, $image);
  1628.             $newImage->save();
  1629.             return $newImage;
  1630.         }
  1631.         return null;
  1632.     }
  1633.     protected function createTourIdPackages(array $tourIds) {
  1634.         if($this->numToursPerImportIteration) {
  1635.             return array_chunk($tourIds$this->numToursPerImportIteration);
  1636.         }
  1637.         return [$tourIds]; //single package
  1638.     }
  1639.     /**
  1640.      * @param AlpsteinRegion $region
  1641.      * @param ObjectMetadata[] $objectMetadata
  1642.      */
  1643.     private function getStartingRegionFromOldRegionsArray(AlpsteinRegion $region, array $objectMetadata) {
  1644.         foreach ($objectMetadata as $metadata) {
  1645.             $metadataElement $metadata->getElement();
  1646.             if($metadataElement instanceof AlpsteinRegion && $metadataElement->getId() === $region->getId()){
  1647.                 return $metadata->getData()['isStartingRegion'];
  1648.             }
  1649.         }
  1650.         return null//region does not exists => new region
  1651.     }
  1652. }