expire($expireTimeHead); $initData = []; // static program data ------------------------------------------------ $initData['timer'] = $f3->get('PATHFINDER.TIMER'); // get all available map types ---------------------------------------- $mapType = Model\BasicModel::getNew('MapTypeModel'); $rows = $mapType->find('active = 1', null, $expireTimeSQL); $mapTypeData = []; foreach((array)$rows as $rowData){ $data = [ 'id' => $rowData->id, 'label' => $rowData->label, 'class' => $rowData->class, 'classTab' => $rowData->classTab ]; $mapTypeData[$rowData->name] = $data; } $initData['mapTypes'] = $mapTypeData; // get all available map scopes --------------------------------------- $mapScope = Model\BasicModel::getNew('MapScopeModel'); $rows = $mapScope->find('active = 1', null, $expireTimeSQL); $mapScopeData = []; foreach((array)$rows as $rowData){ $data = [ 'id' => $rowData->id, 'label' => $rowData->label ]; $mapScopeData[$rowData->name] = $data; } $initData['mapScopes'] = $mapScopeData; // get all available system status ------------------------------------ $systemStatus = Model\BasicModel::getNew('SystemStatusModel'); $rows = $systemStatus->find('active = 1', null, $expireTimeSQL); $systemScopeData = []; foreach((array)$rows as $rowData){ $data = [ 'id' => $rowData->id, 'label' => $rowData->label, 'class' => $rowData->class ]; $systemScopeData[$rowData->name] = $data; } $initData['systemStatus'] = $systemScopeData; // get all available system types ------------------------------------- $systemType = Model\BasicModel::getNew('SystemTypeModel'); $rows = $systemType->find('active = 1', null, $expireTimeSQL); $systemTypeData = []; foreach((array)$rows as $rowData){ $data = [ 'id' => $rowData->id, 'name' => $rowData->name ]; $systemTypeData[$rowData->name] = $data; } $initData['systemType'] = $systemTypeData; // get available connection scopes ------------------------------------ $connectionScope = Model\BasicModel::getNew('ConnectionScopeModel'); $rows = $connectionScope->find('active = 1', null, $expireTimeSQL); $connectionScopeData = []; foreach((array)$rows as $rowData){ $data = [ 'id' => $rowData->id, 'label' => $rowData->label, 'connectorDefinition' => $rowData->connectorDefinition ]; $connectionScopeData[$rowData->name] = $data; } $initData['connectionScopes'] = $connectionScopeData; // get available character status ------------------------------------- $characterStatus = Model\BasicModel::getNew('CharacterStatusModel'); $rows = $characterStatus->find('active = 1', null, $expireTimeSQL); $characterStatusData = []; foreach((array)$rows as $rowData){ $data = [ 'id' => $rowData->id, 'name' => $rowData->name, 'class' => $rowData->class ]; $characterStatusData[$rowData->name] = $data; } $initData['characterStatus'] = $characterStatusData; // get max number of shared entities per map -------------------------- $maxSharedCount = [ 'user' => $f3->get('PATHFINDER.MAX_SHARED_USER'), 'corporation' => $f3->get('PATHFINDER.MAX_SHARED_CORPORATION'), 'alliance' => $f3->get('PATHFINDER.MAX_SHARED_ALLIANCE'), ]; $initData['maxSharedCount'] = $maxSharedCount; echo json_encode($initData); } /** * import new map data * @param $f3 */ public function import($f3){ $importData = (array)$f3->get('POST'); $return = (object) []; $return->error = []; if( isset($importData['typeId']) && count($importData['mapData']) > 0 ){ $user = $this->_getUser(); if($user){ $activeCharacter = $user->getActiveUserCharacter(); $map = Model\BasicModel::getNew('MapModel'); $system = Model\BasicModel::getNew('SystemModel'); $connection = Model\BasicModel::getNew('ConnectionModel'); foreach($importData['mapData'] as $mapData){ if( isset($mapData['config']) && isset($mapData['data']) ){ if( isset($mapData['data']['systems']) && isset($mapData['data']['connections']) ){ if(isset($mapData['config']['id'])){ unset($mapData['config']['id']); } $map->setData($mapData['config']); $map->typeId = (int)$importData['typeId']; $map->save(); // new system IDs will be generated // therefore we need to temp store a mapping between IDs $tempSystemIdMapping = []; foreach($mapData['data']['systems'] as $systemData){ if(isset($systemData['id'])){ $oldId = (int)$systemData['id']; unset($systemData['id']); $system->setData($systemData); $system->mapId = $map; $system->createdCharacterId = $activeCharacter->characterId; $system->updatedCharacterId = $activeCharacter->characterId; $system->save(); $tempSystemIdMapping[$oldId] = $system->id; $system->reset(); } } foreach($mapData['data']['connections'] as $connectionData){ // check if source and target IDs match with new system ID if( isset( $tempSystemIdMapping[$connectionData['source']] ) && isset( $tempSystemIdMapping[$connectionData['target']] ) ){ if(isset($connectionData['id'])){ unset($connectionData['id']); } $connection->setData($connectionData); $connection->mapId = $map; $connection->source = $tempSystemIdMapping[$connectionData['source']]; $connection->target = $tempSystemIdMapping[$connectionData['target']]; $connection->save(); $connection->reset(); } } // map access info should not automatically imported if($map->isPrivate()){ $map->setAccess($user); }elseif($map->isCorporation()){ $corporation = $activeCharacter->getCharacter()->getCorporation(); if($corporation){ $map->setAccess($corporation); } }elseif($map->isAlliance()){ $alliance = $activeCharacter->getCharacter()->getAlliance(); if($alliance){ $map->setAccess($alliance); } } }else{ // systems || connections missing $missingConfigError = (object) []; $missingConfigError->type = 'error'; $missingConfigError->message = 'Map data not valid (systems || connections) missing'; $return->error[] = $missingConfigError; } }else{ // map config || systems/connections missing $missingConfigError = (object) []; $missingConfigError->type = 'error'; $missingConfigError->message = 'Map data not valid (config || data) missing'; $return->error[] = $missingConfigError; } $map->reset(); } }else{ // user not found $return->error[] = $this->getUserLoggedOffError(); } }else{ // map data missing $missingDataError = (object) []; $missingDataError->type = 'error'; $missingDataError->message = 'Map data missing'; $return->error[] = $missingDataError; } echo json_encode($return); } /** * save a new map or update an existing map * @param $f3 */ public function save($f3){ $formData = (array)$f3->get('POST.formData'); $return = (object) []; $return->error = []; if( isset($formData['id']) ){ $user = $this->_getUser(0); if($user){ $map = Model\BasicModel::getNew('MapModel'); $map->getById( (int)$formData['id'] ); if( $map->dry() || $map->hasAccess($user) ){ // new map $map->setData($formData); $map = $map->save(); // save global map access. Depends on map "type" if($map->isPrivate()){ // share map between users -> set access if(isset($formData['mapUsers'])){ // avoid abuse -> respect share limits $accessUsers = array_slice( $formData['mapUsers'], 0, $f3->get('PATHFINDER.MAX_SHARED_USER') ); // clear map access. In case something has removed from access list $map->clearAccess(); $tempUser = Model\BasicModel::getNew('UserModel'); foreach($accessUsers as $userId){ $tempUser->getById( (int)$userId ); if( !$tempUser->dry() && $tempUser->sharing == 1 // check if map sharing is enabled ){ $map->setAccess($tempUser); } $tempUser->reset(); } } // the current user itself should always have access // just in case he removed himself :) $map->setAccess($user); }elseif($map->isCorporation()){ $activeCharacter = $user->getActiveUserCharacter(); if($activeCharacter){ $corporation = $activeCharacter->getCharacter()->getCorporation(); if($corporation){ // the current user has to have a corporation when // working on corporation maps! // share map between corporations -> set access if(isset($formData['mapCorporations'])){ // avoid abuse -> respect share limits $accessCorporations = array_slice( $formData['mapCorporations'], 0, $f3->get('PATHFINDER.MAX_SHARED_CORPORATION') ); // clear map access. In case something has removed from access list $map->clearAccess(); $tempCorporation = Model\BasicModel::getNew('CorporationModel'); foreach($accessCorporations as $corporationId){ $tempCorporation->getById( (int)$corporationId ); if( !$tempCorporation->dry() && $tempCorporation->sharing == 1 // check if map sharing is enabled ){ $map->setAccess($tempCorporation); } $tempCorporation->reset(); } } // the corporation of the current user should always have access $map->setAccess($corporation); } } }elseif($map->isAlliance()){ $activeCharacter = $user->getActiveUserCharacter(); if($activeCharacter){ $alliance = $activeCharacter->getCharacter()->getAlliance(); if($alliance){ // the current user has to have a alliance when // working on alliance maps! // share map between alliances -> set access if(isset($formData['mapAlliances'])){ // avoid abuse -> respect share limits $accessAlliances = array_slice( $formData['mapAlliances'], 0, $f3->get('PATHFINDER.MAX_SHARED_ALLIANCE') ); // clear map access. In case something has removed from access list $map->clearAccess(); $tempAlliance = Model\BasicModel::getNew('AllianceModel'); foreach($accessAlliances as $allianceId){ $tempAlliance->getById( (int)$allianceId ); if( !$tempAlliance->dry() && $tempAlliance->sharing == 1 // check if map sharing is enabled ){ $map->setAccess($tempAlliance); } $tempAlliance->reset(); } } // the alliance of the current user should always have access $map->setAccess($alliance); } } } // reload the same map model (refresh) // this makes sure all data is up2date $map->getById( $map->id, 0 ); $return->mapData = $map->getData(); }else{ // map access denied $captchaError = (object) []; $captchaError->type = 'error'; $captchaError->message = 'Access denied'; $return->error[] = $captchaError; } } }else{ // map id field missing $idError = (object) []; $idError->type = 'error'; $idError->message = 'Map id missing'; $return->error[] = $idError; } echo json_encode($return); } /** * delete a map and all dependencies * @param $f3 */ public function delete($f3){ $mapData = (array)$f3->get('POST.mapData'); $user = $this->_getUser(); if($user){ $map = Model\BasicModel::getNew('MapModel'); $map->getById($mapData['id']); $map->delete($user); } echo json_encode([]); } /** * update map data * function is called continuously * @param $f3 */ public function updateData($f3){ // cache time(s) per user should be equal or less than this function is called // prevent request flooding $responseTTL = $f3->get('PATHFINDER.TIMER.UPDATE_SERVER_MAP.DELAY') / 1000; $mapData = (array)$f3->get('POST.mapData'); $user = $this->_getUser(); $return = (object) []; $return->error = []; if($user){ // -> get active character $activeCharacter = $user->getActiveUserCharacter(); $cacheKey = 'user_map_data_' . $activeCharacter->id; // if there is any system/connection change data submitted -> save new data if( $f3->exists($cacheKey) === false || !empty($mapData) ){ // get current map data ======================================================== $maps = $user->getMaps(); // loop all submitted map data that should be saved // -> currently there will only be ONE map data change submitted -> single loop foreach($mapData as $data){ $systems = []; $connections = []; // check whether system data and/or connection data is send // empty arrays are not included in ajax requests if( isset($data['data']['systems']) ){ $systems = (array)$data['data']['systems']; } if( isset($data['data']['connections']) ){ $connections = (array)$data['data']['connections']; } // check if system data or connection data is send if( count($systems) > 0 || count($connections) > 0 ){ // map changes expected ============================================= // loop current user maps and check for changes foreach($maps as $map){ // update system data ----------------------------------------------- foreach($systems as $i => $systemData){ // check if current system belongs to the current map $map->filter('systems', ['id = ?', $systemData['id'] ]); $filteredMap = $map->find( ['id = ?', $map->id ], ['limit' => 1] ); // this should never fail if(is_object($filteredMap)){ $filteredMap = $filteredMap->current(); // system belongs to the current map if(is_object($filteredMap->systems)){ // update unset($systemData['updated']); $system = $filteredMap->systems->current(); $system->setData($systemData); $system->updatedCharacterId = $activeCharacter->characterId; $system->save(); // a system belongs to ONE map -> speed up for multiple maps unset($systemData[$i]); } } } // update connection data ------------------------------------------- foreach($connections as $i => $connectionData){ // check if the current connection belongs to the current map $map->filter('connections', ['id = ?', $connectionData['id'] ]); $filteredMap = $map->find( ['id = ?', $map->id ], ['limit' => 1] ); // this should never fail if(is_object($filteredMap)){ $filteredMap = $filteredMap->current(); // connection belongs to the current map if(is_object($filteredMap->connections)){ // update unset($connectionData['updated']); $connection = $filteredMap->connections->current(); $connection->setData($connectionData); $connection->save($user); // a connection belongs to ONE map -> speed up for multiple maps unset($connectionData[$i]); } } } } } } // format map Data for return $return->mapData = self::getFormattedMapData($maps); $f3->set($cacheKey, $return, $responseTTL); }else{ // get from cache $return = $f3->get($cacheKey); } }else{ // user logged off $return->error[] = $this->getUserLoggedOffError(); } echo json_encode( $return ); } /** * @param $mapModels * @return Model\MapModel[] */ public static function getFormattedMapData($mapModels){ $mapData = []; foreach($mapModels as $mapModel){ $allMapData = $mapModel->getData(); $mapData[] = [ 'config' => $allMapData->mapData, 'data' => [ 'systems' => $allMapData->systems, 'connections' => $allMapData->connections, ] ]; } return $mapData; } /** * update map data api * function is called continuously * @param $f3 */ public function updateUserData($f3){ // cache time(s) should be equal or less than request trigger time // prevent request flooding $responseTTL = $f3->get('PATHFINDER.TIMER.UPDATE_SERVER_USER_DATA.DELAY') / 1000; // if the cache key will be set -> cache request $cacheKey = null; $return = (object) []; $return->error = []; $user = $this->_getUser(); if($user){ if( !empty($f3->get('POST.mapIds')) ){ $mapIds = (array)$f3->get('POST.mapIds'); // check if data for specific system is requested $systemData = (array)$f3->get('POST.systemData'); // update current location (IGB data) $user->updateCharacterLog(60 * 5); // if data is requested extend the cache key in order to get new data $requestSystemData = (object) []; $requestSystemData->mapId = isset($systemData['mapId']) ? (int) $systemData['mapId'] : 0; $requestSystemData->systemId = isset($systemData['systemData']['id']) ? (int) $systemData['systemData']['id'] : 0; // IMPORTANT for now -> just update a single map (save performance) $mapIds = array_slice($mapIds, 0, 1); // the userMasData is cached per map (this must be changed if multiple maps // will be allowed in future... $tempId = (int)$mapIds[0]; $cacheKey = 'user_data_' . $tempId . '_' . $requestSystemData->systemId; if( $f3->exists($cacheKey) === false ){ foreach($mapIds as $mapId){ $map = $user->getMap($mapId); if( !is_null($map) ){ $return->mapUserData[] = $map->getUserData(); // request signature data for a system if user has map access! if( $map->id === $requestSystemData->mapId ){ $system = $map->getSystem( $requestSystemData->systemId ); if( !is_null($system) ){ // data for the current selected system $return->system = $system->getData(); $return->system->signatures = $system->getSignaturesData(); } } } } // cache response $f3->set($cacheKey, $return, $responseTTL); }else{ // get from cache // this should happen if a user has multiple program instances running // with the same main char $return = $f3->get($cacheKey); } } // get current user data -> this should not be cached because each user has different personal data // even if they have multiple characters using the same map! $return->userData = $user->getData(); }else{ // user logged off $return->error[] = $this->getUserLoggedOffError(); } echo json_encode( $return ); } }