@@ -5,7 +5,7 @@ Mapping tool for [*EVE ONLINE*](https://www.eveonline.com)
|
||||
- Official Forum post [https://forums.eveonline.com](https://forums.eveonline.com/default.aspx?g=posts&m=6021776#post6021776)
|
||||
- Screenshots [imgur.com](http://imgur.com/a/k2aVa)
|
||||
- Video [youtube.com](https://www.youtube.com/channel/UC7HU7XEoMbqRwqxDTbMjSPg)
|
||||
- Community [google +](https://plus.google.com/u/0/b/110257318165279088853/110257318165279088853)
|
||||
- Community [google +](https://plus.google.com/+Pathfinder-wSpace)
|
||||
- Licence [MIT](http://opensource.org/licenses/MIT)
|
||||
|
||||
##### IMPORTANT Information:
|
||||
|
||||
@@ -2,16 +2,16 @@
|
||||
|
||||
[ENVIRONMENT]
|
||||
; project environment (DEVELOP, PRODUCTION).
|
||||
; This effects: DB connection, Mail-Server connection
|
||||
; This effects: DB connection, Mail-Server, SSO, CREST configurations in this file
|
||||
; configuration below
|
||||
SERVER = DEVELOP
|
||||
|
||||
[ENVIRONMENT.DEVELOP]
|
||||
; base dir (Default: "auto-detect"
|
||||
; base dir (Default: "auto-detect")
|
||||
BASE =
|
||||
; deployment URL e.g. http://localhost
|
||||
; deployment URL (e.g. http://localhost)
|
||||
URL = http://pathfinder.local
|
||||
; Verbosity level of the stack trace
|
||||
; level of debug/error stack trace
|
||||
DEBUG = 3
|
||||
; main db
|
||||
DB_DNS = mysql:host=localhost;port=3306;dbname=
|
||||
@@ -25,11 +25,13 @@ DB_CCP_NAME = eve_parallax_min
|
||||
DB_CCP_USER = root
|
||||
DB_CCP_PASS =
|
||||
|
||||
; CCP SSO settings
|
||||
; CCP SSO settings (OAuth2) - visit: https://developers.eveonline.com/applications
|
||||
CCP_CREST_URL = https://api-sisi.testeveonline.com
|
||||
SSO_CCP_URL = https://sisilogin.testeveonline.com
|
||||
SSO_CCP_CLIENT_ID =
|
||||
SSO_CCP_SECRET_KEY =
|
||||
|
||||
; SMTP settings. see: https://developers.eveonline.com/applications
|
||||
; SMTP settings (optional)
|
||||
SMTP_HOST = localhost
|
||||
SMTP_PORT = 25
|
||||
SMTP_SCHEME = ""
|
||||
@@ -40,10 +42,11 @@ SMTP_FROM = pathfinder@localhost.com
|
||||
SMTP_ERROR = pathfinder@localhost.com
|
||||
|
||||
[ENVIRONMENT.PRODUCTION]
|
||||
; base dir (Default: "auto-detect"
|
||||
BASE = /www/htdocs/www.pathfinder-w.space
|
||||
; deployment URL
|
||||
; deployment URL (e.g. https://www.pathfinder-w.space)
|
||||
URL = https://www.pathfinder-w.space
|
||||
; Verbosity level of the stack trace
|
||||
; level of debug/error stack trace
|
||||
DEBUG = 0
|
||||
; main db
|
||||
DB_DNS = mysql:host=localhost;port=3306;dbname=
|
||||
@@ -58,10 +61,12 @@ DB_CCP_USER =
|
||||
DB_CCP_PASS =
|
||||
|
||||
; CCP SSO settings
|
||||
CCP_CREST_URL = https://crest-tq.eveonline.com
|
||||
SSO_CCP_URL = https://login.eveonline.com
|
||||
SSO_CCP_CLIENT_ID =
|
||||
SSO_CCP_SECRET_KEY =
|
||||
|
||||
; SMTP settings
|
||||
; SMTP settings (optional)
|
||||
SMTP_HOST = localhost
|
||||
SMTP_PORT = 25
|
||||
SMTP_SCHEME = TLS
|
||||
|
||||
@@ -13,14 +13,14 @@
|
||||
* | | < | <| -__|-- __|
|
||||
* |__|__|__||__|__|_____|_____|
|
||||
*
|
||||
* Copyright (c) 2014 by ikkez
|
||||
* Christian Knuth <ikkez0n3@gmail.com>
|
||||
* Copyright (c) 2016 by ikkez
|
||||
* Christian Knuth <mail@ikkez.de>
|
||||
* https://github.com/ikkez/F3-Sugar/
|
||||
*
|
||||
* @package DB
|
||||
* @version 1.4.1-dev
|
||||
* @version 1.4.1
|
||||
* @date 29.01.2016
|
||||
* @since 24.04.2012
|
||||
* @date 04.06.2015
|
||||
*/
|
||||
|
||||
namespace DB;
|
||||
@@ -173,7 +173,9 @@ class Cortex extends Cursor {
|
||||
list($key, $relField) = explode('.',$val,2);
|
||||
$this->relWhitelist[$key][(int)$exclude][] = $relField;
|
||||
unset($fields[$i]);
|
||||
$fields[] = $key;
|
||||
}
|
||||
$fields = array_unique($fields);
|
||||
$schema = $this->whitelist ?: $this->mapper->fields();
|
||||
if (!$schema && !$this->dbsType != 'sql' && $this->dry()) {
|
||||
$schema = $this->load()->mapper->fields();
|
||||
|
||||
@@ -7,20 +7,21 @@
|
||||
*/
|
||||
|
||||
namespace Controller;
|
||||
use Controller\Api as Api;
|
||||
use Model;
|
||||
|
||||
class AccessController extends Controller {
|
||||
|
||||
/**
|
||||
* event handler
|
||||
* @param $f3
|
||||
* @param \Base $f3
|
||||
*/
|
||||
function beforeroute($f3) {
|
||||
function beforeroute(\Base $f3) {
|
||||
parent::beforeroute($f3);
|
||||
|
||||
// Any CMS route of a child class of this one, requires a
|
||||
// valid logged in user!
|
||||
$loginCheck = $this->_checkLogIn();
|
||||
$loginCheck = $this->checkLogIn($f3);
|
||||
|
||||
if( !$loginCheck ){
|
||||
// no user found or LogIn timer expired
|
||||
@@ -30,16 +31,16 @@ class AccessController extends Controller {
|
||||
|
||||
/**
|
||||
* checks weather a user is currently logged in
|
||||
* @param \Base $f3
|
||||
* @return bool
|
||||
*/
|
||||
private function _checkLogIn(){
|
||||
|
||||
private function checkLogIn($f3){
|
||||
$loginCheck = false;
|
||||
|
||||
if($this->f3->get('SESSION.user.time') > 0){
|
||||
if($f3->get(Api\User::SESSION_KEY_CHARACTER_TIME) > 0){
|
||||
// check logIn time
|
||||
$logInTime = new \DateTime();
|
||||
$logInTime->setTimestamp($this->f3->get('SESSION.user.time'));
|
||||
$logInTime->setTimestamp( $f3->get(Api\User::SESSION_KEY_CHARACTER_TIME) );
|
||||
$now = new \DateTime();
|
||||
|
||||
$timeDiff = $now->diff($logInTime);
|
||||
@@ -48,7 +49,7 @@ class AccessController extends Controller {
|
||||
$minutes += $timeDiff->h * 60;
|
||||
$minutes += $timeDiff->i;
|
||||
|
||||
if($minutes <= $this->f3->get('PATHFINDER.TIMER.LOGGED')){
|
||||
if($minutes <= $f3->get('PATHFINDER.TIMER.LOGGED')){
|
||||
$loginCheck = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,25 +7,24 @@
|
||||
*/
|
||||
|
||||
namespace controller\api;
|
||||
use Controller;
|
||||
use Model;
|
||||
|
||||
class Access extends \Controller\AccessController {
|
||||
class Access extends Controller\AccessController {
|
||||
|
||||
/**
|
||||
* event handler
|
||||
* @param $f3
|
||||
* @param \Base $f3
|
||||
*/
|
||||
function beforeroute($f3) {
|
||||
|
||||
parent::beforeroute($f3);
|
||||
|
||||
function beforeroute(\Base $f3) {
|
||||
// set header for all routes
|
||||
header('Content-type: application/json');
|
||||
parent::beforeroute($f3);
|
||||
}
|
||||
|
||||
/**
|
||||
* search user/corporation or alliance by name
|
||||
* @param $f3
|
||||
* search character/corporation or alliance by name
|
||||
* @param \Base $f3
|
||||
* @param $params
|
||||
*/
|
||||
public function search($f3, $params){
|
||||
@@ -41,8 +40,8 @@ class Access extends \Controller\AccessController {
|
||||
|
||||
$accessModel = null;
|
||||
switch($searchType){
|
||||
case 'user':
|
||||
$accessModel = Model\BasicModel::getNew('UserModel');
|
||||
case 'character':
|
||||
$accessModel = Model\BasicModel::getNew('CharacterModel');
|
||||
break;
|
||||
case 'corporation':
|
||||
$accessModel = Model\BasicModel::getNew('CorporationModel');
|
||||
@@ -55,12 +54,12 @@ class Access extends \Controller\AccessController {
|
||||
if( is_object($accessModel) ){
|
||||
|
||||
// find "active" entries that have their "sharing" option activated
|
||||
$accessList = $accessModel->find( array(
|
||||
$accessList = $accessModel->find( [
|
||||
"LOWER(name) LIKE :token AND " .
|
||||
"active = 1 AND " .
|
||||
"shared = 1 ",
|
||||
':token' => '%' . $searchToken . '%'
|
||||
));
|
||||
]);
|
||||
|
||||
if($accessList){
|
||||
foreach($accessList as $accessObject){
|
||||
|
||||
@@ -7,27 +7,26 @@
|
||||
*/
|
||||
|
||||
namespace Controller\Api;
|
||||
use Controller;
|
||||
use Model;
|
||||
|
||||
class Connection extends \Controller\AccessController{
|
||||
class Connection extends Controller\AccessController{
|
||||
|
||||
/**
|
||||
* @param $f3
|
||||
* @param \Base $f3
|
||||
*/
|
||||
function beforeroute($f3) {
|
||||
|
||||
parent::beforeroute($f3);
|
||||
|
||||
function beforeroute(\Base $f3) {
|
||||
// set header for all routes
|
||||
header('Content-type: application/json');
|
||||
parent::beforeroute($f3);
|
||||
}
|
||||
|
||||
/**
|
||||
* save a new connection or updates an existing (drag/drop) between two systems
|
||||
* if a connection is changed (drag&drop) to another system. -> this function is called for update
|
||||
* @param $f3
|
||||
* @param \Base $f3
|
||||
*/
|
||||
public function save($f3){
|
||||
public function save(\Base $f3){
|
||||
$postData = (array)$f3->get('POST');
|
||||
$newConnectionData = [];
|
||||
|
||||
@@ -38,14 +37,18 @@ class Connection extends \Controller\AccessController{
|
||||
$mapData = (array)$postData['mapData'];
|
||||
$connectionData = (array)$postData['connectionData'];
|
||||
|
||||
$user = $this->_getUser();
|
||||
$activeCharacter = $this->getCharacter();
|
||||
|
||||
if($activeCharacter){
|
||||
|
||||
if($user){
|
||||
// get map model and check map access
|
||||
/**
|
||||
* @var Model\MapModel $map
|
||||
*/
|
||||
$map = Model\BasicModel::getNew('MapModel');
|
||||
$map->getById( (int)$mapData['id'] );
|
||||
|
||||
if( $map->hasAccess($user) ){
|
||||
if( $map->hasAccess($activeCharacter) ){
|
||||
$source = $map->getSystem( (int)$connectionData['source'] );
|
||||
$target = $map->getSystem( (int)$connectionData['target'] );
|
||||
|
||||
@@ -53,6 +56,9 @@ class Connection extends \Controller\AccessController{
|
||||
!is_null($source) &&
|
||||
!is_null($target)
|
||||
){
|
||||
/**
|
||||
* @var $connection Model\ConnectionModel
|
||||
*/
|
||||
$connection = Model\BasicModel::getNew('ConnectionModel');
|
||||
$connection->getById( (int)$connectionData['id'] );
|
||||
|
||||
@@ -90,20 +96,29 @@ class Connection extends \Controller\AccessController{
|
||||
echo json_encode($newConnectionData);
|
||||
}
|
||||
|
||||
public function delete($f3){
|
||||
/**
|
||||
* delete connection
|
||||
* @param \Base $f3
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function delete(\Base $f3){
|
||||
$connectionIds = $f3->get('POST.connectionIds');
|
||||
$activeCharacter = $this->getCharacter();
|
||||
|
||||
$user = $this->_getUser();
|
||||
$connection = Model\BasicModel::getNew('ConnectionModel');
|
||||
if($activeCharacter = $this->getCharacter()){
|
||||
/**
|
||||
* @var Model\ConnectionModel $connection
|
||||
*/
|
||||
$connection = Model\BasicModel::getNew('ConnectionModel');
|
||||
foreach($connectionIds as $connectionId){
|
||||
$connection->getById($connectionId);
|
||||
$connection->delete( $activeCharacter );
|
||||
|
||||
foreach($connectionIds as $connectionId){
|
||||
|
||||
$connection->getById($connectionId);
|
||||
$connection->delete($user);
|
||||
|
||||
$connection->reset();
|
||||
$connection->reset();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
echo json_encode([]);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
namespace Controller\Api;
|
||||
use Controller;
|
||||
use Model;
|
||||
|
||||
/**
|
||||
@@ -14,25 +15,23 @@ use Model;
|
||||
* Class Map
|
||||
* @package Controller\Api
|
||||
*/
|
||||
class Map extends \Controller\AccessController {
|
||||
class Map extends Controller\AccessController {
|
||||
|
||||
/**
|
||||
* event handler
|
||||
* @param $f3
|
||||
* @param \Base $f3
|
||||
*/
|
||||
function beforeroute($f3) {
|
||||
|
||||
function beforeroute(\Base $f3) {
|
||||
// set header for all routes
|
||||
header('Content-type: application/json');
|
||||
|
||||
parent::beforeroute($f3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all required static config data for program initialization
|
||||
* @param $f3
|
||||
* @param \Base $f3
|
||||
*/
|
||||
public function init($f3){
|
||||
public function init(\Base $f3){
|
||||
|
||||
// expire time in seconds
|
||||
$expireTimeHead = 60 * 60 * 12;
|
||||
@@ -40,10 +39,11 @@ class Map extends \Controller\AccessController {
|
||||
|
||||
$f3->expire($expireTimeHead);
|
||||
|
||||
$initData = [];
|
||||
$return = (object) [];
|
||||
$return->error = [];
|
||||
|
||||
// static program data ------------------------------------------------
|
||||
$initData['timer'] = $f3->get('PATHFINDER.TIMER');
|
||||
$return->timer = $f3->get('PATHFINDER.TIMER');
|
||||
|
||||
// get all available map types ----------------------------------------
|
||||
$mapType = Model\BasicModel::getNew('MapTypeModel');
|
||||
@@ -60,7 +60,7 @@ class Map extends \Controller\AccessController {
|
||||
$mapTypeData[$rowData->name] = $data;
|
||||
|
||||
}
|
||||
$initData['mapTypes'] = $mapTypeData;
|
||||
$return->mapTypes = $mapTypeData;
|
||||
|
||||
// get all available map scopes ---------------------------------------
|
||||
$mapScope = Model\BasicModel::getNew('MapScopeModel');
|
||||
@@ -73,7 +73,7 @@ class Map extends \Controller\AccessController {
|
||||
];
|
||||
$mapScopeData[$rowData->name] = $data;
|
||||
}
|
||||
$initData['mapScopes'] = $mapScopeData;
|
||||
$return->mapScopes = $mapScopeData;
|
||||
|
||||
// get all available system status ------------------------------------
|
||||
$systemStatus = Model\BasicModel::getNew('SystemStatusModel');
|
||||
@@ -87,7 +87,7 @@ class Map extends \Controller\AccessController {
|
||||
];
|
||||
$systemScopeData[$rowData->name] = $data;
|
||||
}
|
||||
$initData['systemStatus'] = $systemScopeData;
|
||||
$return->systemStatus = $systemScopeData;
|
||||
|
||||
// get all available system types -------------------------------------
|
||||
$systemType = Model\BasicModel::getNew('SystemTypeModel');
|
||||
@@ -100,7 +100,7 @@ class Map extends \Controller\AccessController {
|
||||
];
|
||||
$systemTypeData[$rowData->name] = $data;
|
||||
}
|
||||
$initData['systemType'] = $systemTypeData;
|
||||
$return->systemType = $systemTypeData;
|
||||
|
||||
// get available connection scopes ------------------------------------
|
||||
$connectionScope = Model\BasicModel::getNew('ConnectionScopeModel');
|
||||
@@ -114,7 +114,7 @@ class Map extends \Controller\AccessController {
|
||||
];
|
||||
$connectionScopeData[$rowData->name] = $data;
|
||||
}
|
||||
$initData['connectionScopes'] = $connectionScopeData;
|
||||
$return->connectionScopes = $connectionScopeData;
|
||||
|
||||
// get available character status -------------------------------------
|
||||
$characterStatus = Model\BasicModel::getNew('CharacterStatusModel');
|
||||
@@ -128,24 +128,40 @@ class Map extends \Controller\AccessController {
|
||||
];
|
||||
$characterStatusData[$rowData->name] = $data;
|
||||
}
|
||||
$initData['characterStatus'] = $characterStatusData;
|
||||
$return->characterStatus = $characterStatusData;
|
||||
|
||||
// get max number of shared entities per map --------------------------
|
||||
$maxSharedCount = [
|
||||
'user' => $f3->get('PATHFINDER.MAX_SHARED_USER'),
|
||||
'character' => $f3->get('PATHFINDER.MAX_SHARED_CHARACTER'),
|
||||
'corporation' => $f3->get('PATHFINDER.MAX_SHARED_CORPORATION'),
|
||||
'alliance' => $f3->get('PATHFINDER.MAX_SHARED_ALLIANCE'),
|
||||
];
|
||||
$initData['maxSharedCount'] = $maxSharedCount;
|
||||
$return->maxSharedCount = $maxSharedCount;
|
||||
|
||||
echo json_encode($initData);
|
||||
// get program routes -------------------------------------------------
|
||||
$return->routes = [
|
||||
'ssoLogin' => $this->getF3()->alias( 'sso', ['action' => 'requestAuthorization'] )
|
||||
];
|
||||
|
||||
// get SSO error messages that should be shown immediately ------------
|
||||
// -> e.g. errors while character switch from previous HTTP requests
|
||||
if( $f3->exists(Controller\Ccp\Sso::SESSION_KEY_SSO_ERROR) ){
|
||||
$ssoError = (object) [];
|
||||
$ssoError->type = 'error';
|
||||
$ssoError->title = 'Login failed';
|
||||
$ssoError->message = $f3->get(Controller\Ccp\Sso::SESSION_KEY_SSO_ERROR);
|
||||
$return->error[] = $ssoError;
|
||||
$f3->clear(Controller\Ccp\Sso::SESSION_KEY_SSO_ERROR);
|
||||
}
|
||||
|
||||
echo json_encode($return);
|
||||
}
|
||||
|
||||
/**
|
||||
* import new map data
|
||||
* @param $f3
|
||||
* @param \Base $f3
|
||||
*/
|
||||
public function import($f3){
|
||||
public function import(\Base $f3){
|
||||
$importData = (array)$f3->get('POST');
|
||||
|
||||
$return = (object) [];
|
||||
@@ -155,13 +171,24 @@ class Map extends \Controller\AccessController {
|
||||
isset($importData['typeId']) &&
|
||||
count($importData['mapData']) > 0
|
||||
){
|
||||
$user = $this->_getUser();
|
||||
$activeCharacter = $this->getCharacter();
|
||||
|
||||
if($user){
|
||||
$activeCharacter = $user->getActiveUserCharacter();
|
||||
if($activeCharacter){
|
||||
$user = $activeCharacter->getUser();
|
||||
|
||||
/**
|
||||
* @var $map Model\MapModel
|
||||
*/
|
||||
$map = Model\BasicModel::getNew('MapModel');
|
||||
|
||||
/**
|
||||
* @var $system Model\SystemModel
|
||||
*/
|
||||
$system = Model\BasicModel::getNew('SystemModel');
|
||||
|
||||
/**
|
||||
* @var $connection Model\ConnectionModel
|
||||
*/
|
||||
$connection = Model\BasicModel::getNew('ConnectionModel');
|
||||
|
||||
foreach($importData['mapData'] as $mapData){
|
||||
@@ -194,8 +221,8 @@ class Map extends \Controller\AccessController {
|
||||
|
||||
$system->setData($systemData);
|
||||
$system->mapId = $map;
|
||||
$system->createdCharacterId = $activeCharacter->characterId;
|
||||
$system->updatedCharacterId = $activeCharacter->characterId;
|
||||
$system->createdCharacterId = $activeCharacter;
|
||||
$system->updatedCharacterId = $activeCharacter;
|
||||
$system->save();
|
||||
|
||||
$tempSystemIdMapping[$oldId] = $system->id;
|
||||
@@ -203,7 +230,6 @@ class Map extends \Controller\AccessController {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
foreach($mapData['data']['connections'] as $connectionData){
|
||||
// check if source and target IDs match with new system ID
|
||||
if(
|
||||
@@ -228,13 +254,11 @@ class Map extends \Controller\AccessController {
|
||||
if($map->isPrivate()){
|
||||
$map->setAccess($user);
|
||||
}elseif($map->isCorporation()){
|
||||
$corporation = $activeCharacter->getCharacter()->getCorporation();
|
||||
if($corporation){
|
||||
if($corporation = $activeCharacter->getCorporation()){
|
||||
$map->setAccess($corporation);
|
||||
}
|
||||
}elseif($map->isAlliance()){
|
||||
$alliance = $activeCharacter->getCharacter()->getAlliance();
|
||||
if($alliance){
|
||||
if($alliance = $activeCharacter->getAlliance()){
|
||||
$map->setAccess($alliance);
|
||||
}
|
||||
}
|
||||
@@ -260,7 +284,7 @@ class Map extends \Controller\AccessController {
|
||||
}
|
||||
}else{
|
||||
// user not found
|
||||
$return->error[] = $this->getUserLoggedOffError();
|
||||
$return->error[] = $this->getLogoutError();
|
||||
}
|
||||
}else{
|
||||
// map data missing
|
||||
@@ -276,25 +300,28 @@ class Map extends \Controller\AccessController {
|
||||
|
||||
/**
|
||||
* save a new map or update an existing map
|
||||
* @param $f3
|
||||
* @param \Base $f3
|
||||
*/
|
||||
public function save($f3){
|
||||
public function save(\Base $f3){
|
||||
$formData = (array)$f3->get('POST.formData');
|
||||
|
||||
$return = (object) [];
|
||||
$return->error = [];
|
||||
|
||||
if( isset($formData['id']) ){
|
||||
$activeCharacter = $this->getCharacter(0);
|
||||
|
||||
$user = $this->_getUser(0);
|
||||
if($activeCharacter){
|
||||
|
||||
if($user){
|
||||
/**
|
||||
* @var $map Model\MapModel
|
||||
*/
|
||||
$map = Model\BasicModel::getNew('MapModel');
|
||||
$map->getById( (int)$formData['id'] );
|
||||
|
||||
if(
|
||||
$map->dry() ||
|
||||
$map->hasAccess($user)
|
||||
$map->hasAccess($activeCharacter)
|
||||
){
|
||||
// new map
|
||||
$map->setData($formData);
|
||||
@@ -303,118 +330,117 @@ class Map extends \Controller\AccessController {
|
||||
// save global map access. Depends on map "type"
|
||||
if($map->isPrivate()){
|
||||
|
||||
// share map between users -> set access
|
||||
if(isset($formData['mapUsers'])){
|
||||
// share map between characters -> set access
|
||||
if(isset($formData['mapCharacters'])){
|
||||
// avoid abuse -> respect share limits
|
||||
$accessUsers = array_slice( $formData['mapUsers'], 0, $f3->get('PATHFINDER.MAX_SHARED_USER') );
|
||||
$accessCharacters = array_slice( $formData['mapCharacters'], 0, $f3->get('PATHFINDER.MAX_SHARED_CHARACTER') );
|
||||
|
||||
// clear map access. In case something has removed from access list
|
||||
$map->clearAccess();
|
||||
|
||||
$tempUser = Model\BasicModel::getNew('UserModel');
|
||||
/**
|
||||
* @var $tempCharacter Model\CharacterModel
|
||||
*/
|
||||
$tempCharacter = Model\BasicModel::getNew('CharacterModel');
|
||||
|
||||
foreach($accessUsers as $userId){
|
||||
$tempUser->getById( (int)$userId );
|
||||
foreach($accessCharacters as $characterId){
|
||||
$tempCharacter->getById( (int)$characterId );
|
||||
|
||||
if(
|
||||
!$tempUser->dry() &&
|
||||
$tempUser->shared == 1 // check if map shared is enabled
|
||||
!$tempCharacter->dry() &&
|
||||
$tempCharacter->shared == 1 // check if map shared is enabled
|
||||
){
|
||||
$map->setAccess($tempUser);
|
||||
$map->setAccess($tempCharacter);
|
||||
}
|
||||
|
||||
$tempUser->reset();
|
||||
$tempCharacter->reset();
|
||||
}
|
||||
}
|
||||
|
||||
// the current user itself should always have access
|
||||
// the current character itself should always have access
|
||||
// just in case he removed himself :)
|
||||
$map->setAccess($user);
|
||||
$map->setAccess($activeCharacter);
|
||||
}elseif($map->isCorporation()){
|
||||
$activeCharacter = $user->getActiveUserCharacter();
|
||||
$corporation = $activeCharacter->getCorporation();
|
||||
|
||||
if($activeCharacter){
|
||||
$corporation = $activeCharacter->getCharacter()->getCorporation();
|
||||
if($corporation){
|
||||
// the current user has to have a corporation when
|
||||
// working on corporation maps!
|
||||
|
||||
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') );
|
||||
|
||||
// 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();
|
||||
|
||||
// clear map access. In case something has removed from access list
|
||||
$map->clearAccess();
|
||||
/**
|
||||
* @var $tempCorporation Model\CorporationModel
|
||||
*/
|
||||
$tempCorporation = Model\BasicModel::getNew('CorporationModel');
|
||||
|
||||
$tempCorporation = Model\BasicModel::getNew('CorporationModel');
|
||||
foreach($accessCorporations as $corporationId){
|
||||
$tempCorporation->getById( (int)$corporationId );
|
||||
|
||||
foreach($accessCorporations as $corporationId){
|
||||
$tempCorporation->getById( (int)$corporationId );
|
||||
|
||||
if(
|
||||
!$tempCorporation->dry() &&
|
||||
$tempCorporation->shared == 1 // check if map shared is enabled
|
||||
){
|
||||
$map->setAccess($tempCorporation);
|
||||
}
|
||||
|
||||
$tempCorporation->reset();
|
||||
if(
|
||||
!$tempCorporation->dry() &&
|
||||
$tempCorporation->shared == 1 // check if map shared is enabled
|
||||
){
|
||||
$map->setAccess($tempCorporation);
|
||||
}
|
||||
}
|
||||
|
||||
// the corporation of the current user should always have access
|
||||
$map->setAccess($corporation);
|
||||
$tempCorporation->reset();
|
||||
}
|
||||
}
|
||||
|
||||
// the corporation of the current user should always have access
|
||||
$map->setAccess($corporation);
|
||||
}
|
||||
}elseif($map->isAlliance()){
|
||||
$activeCharacter = $user->getActiveUserCharacter();
|
||||
$alliance = $activeCharacter->getAlliance();
|
||||
|
||||
if($activeCharacter){
|
||||
$alliance = $activeCharacter->getCharacter()->getAlliance();
|
||||
if($alliance){
|
||||
// the current user has to have a alliance when
|
||||
// working on alliance maps!
|
||||
|
||||
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') );
|
||||
|
||||
// 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();
|
||||
|
||||
// clear map access. In case something has removed from access list
|
||||
$map->clearAccess();
|
||||
/**
|
||||
* @var $tempAlliance Model\AllianceModel
|
||||
*/
|
||||
$tempAlliance = Model\BasicModel::getNew('AllianceModel');
|
||||
|
||||
$tempAlliance = Model\BasicModel::getNew('AllianceModel');
|
||||
foreach($accessAlliances as $allianceId){
|
||||
$tempAlliance->getById( (int)$allianceId );
|
||||
|
||||
foreach($accessAlliances as $allianceId){
|
||||
$tempAlliance->getById( (int)$allianceId );
|
||||
|
||||
if(
|
||||
!$tempAlliance->dry() &&
|
||||
$tempAlliance->shared == 1 // check if map shared is enabled
|
||||
){
|
||||
$map->setAccess($tempAlliance);
|
||||
}
|
||||
|
||||
$tempAlliance->reset();
|
||||
if(
|
||||
!$tempAlliance->dry() &&
|
||||
$tempAlliance->shared == 1 // check if map shared is enabled
|
||||
){
|
||||
$map->setAccess($tempAlliance);
|
||||
}
|
||||
|
||||
$tempAlliance->reset();
|
||||
}
|
||||
|
||||
// the alliance of the current user should always have access
|
||||
$map->setAccess($alliance);
|
||||
}
|
||||
|
||||
// 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) [];
|
||||
@@ -423,7 +449,6 @@ class Map extends \Controller\AccessController {
|
||||
$return->error[] = $captchaError;
|
||||
}
|
||||
}
|
||||
|
||||
}else{
|
||||
// map id field missing
|
||||
$idError = (object) [];
|
||||
@@ -437,17 +462,19 @@ class Map extends \Controller\AccessController {
|
||||
|
||||
/**
|
||||
* delete a map and all dependencies
|
||||
* @param $f3
|
||||
* @param \Base $f3
|
||||
*/
|
||||
public function delete($f3){
|
||||
public function delete(\Base $f3){
|
||||
$mapData = (array)$f3->get('POST.mapData');
|
||||
$activeCharacter = $this->getCharacter();
|
||||
|
||||
$user = $this->_getUser();
|
||||
|
||||
if($user){
|
||||
if($activeCharacter){
|
||||
/**
|
||||
* @var $map Model\MapModel
|
||||
*/
|
||||
$map = Model\BasicModel::getNew('MapModel');
|
||||
$map->getById($mapData['id']);
|
||||
$map->delete($user);
|
||||
$map->delete( $activeCharacter );
|
||||
}
|
||||
|
||||
echo json_encode([]);
|
||||
@@ -455,34 +482,28 @@ class Map extends \Controller\AccessController {
|
||||
|
||||
/**
|
||||
* update map data
|
||||
* function is called continuously
|
||||
* @param $f3
|
||||
* -> function is called continuously (trigger) by any active client
|
||||
* @param \Base $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;
|
||||
public function updateData(\Base $f3){
|
||||
$mapData = (array)$f3->get('POST.mapData');
|
||||
|
||||
$user = $this->_getUser();
|
||||
$activeCharacter = $this->getCharacter();
|
||||
|
||||
$return = (object) [];
|
||||
$return->error = [];
|
||||
|
||||
if($user){
|
||||
// -> get active character
|
||||
$activeCharacter = $user->getActiveUserCharacter();
|
||||
if($activeCharacter){
|
||||
|
||||
$cacheKey = 'user_map_data_' . $activeCharacter->id;
|
||||
$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)
|
||||
!empty($mapData) ||
|
||||
!$f3->exists($cacheKey)
|
||||
){
|
||||
|
||||
// get current map data ========================================================
|
||||
$maps = $user->getMaps();
|
||||
$maps = $activeCharacter->getMaps();
|
||||
|
||||
// loop all submitted map data that should be saved
|
||||
// -> currently there will only be ONE map data change submitted -> single loop
|
||||
@@ -532,7 +553,7 @@ class Map extends \Controller\AccessController {
|
||||
unset($systemData['updated']);
|
||||
$system = $filteredMap->systems->current();
|
||||
$system->setData($systemData);
|
||||
$system->updatedCharacterId = $activeCharacter->characterId;
|
||||
$system->updatedCharacterId = $activeCharacter;
|
||||
$system->save();
|
||||
|
||||
// a system belongs to ONE map -> speed up for multiple maps
|
||||
@@ -561,7 +582,7 @@ class Map extends \Controller\AccessController {
|
||||
unset($connectionData['updated']);
|
||||
$connection = $filteredMap->connections->current();
|
||||
$connection->setData($connectionData);
|
||||
$connection->save($user);
|
||||
$connection->save();
|
||||
|
||||
// a connection belongs to ONE map -> speed up for multiple maps
|
||||
unset($connectionData[$i]);
|
||||
@@ -574,6 +595,11 @@ class Map extends \Controller\AccessController {
|
||||
|
||||
// format map Data for return
|
||||
$return->mapData = self::getFormattedMapData($maps);
|
||||
|
||||
// cache time(s) per user should be equal or less than this function is called
|
||||
// prevent request flooding
|
||||
$responseTTL = (int)$f3->get('PATHFINDER.TIMER.UPDATE_SERVER_MAP.DELAY') / 1000;
|
||||
|
||||
$f3->set($cacheKey, $return, $responseTTL);
|
||||
}else{
|
||||
// get from cache
|
||||
@@ -582,23 +608,24 @@ class Map extends \Controller\AccessController {
|
||||
|
||||
}else{
|
||||
// user logged off
|
||||
$return->error[] = $this->getUserLoggedOffError();
|
||||
$return->error[] = $this->getLogoutError();
|
||||
}
|
||||
|
||||
echo json_encode( $return );
|
||||
}
|
||||
|
||||
/**
|
||||
* get formatted map data
|
||||
* @param $mapModels
|
||||
* @return Model\MapModel[]
|
||||
* @return array
|
||||
*/
|
||||
public static function getFormattedMapData($mapModels){
|
||||
|
||||
$mapData = [];
|
||||
foreach($mapModels as $mapModel){
|
||||
|
||||
foreach($mapModels as &$mapModel){
|
||||
/**
|
||||
* @var $mapModel Model\MapModel
|
||||
*/
|
||||
$allMapData = $mapModel->getData();
|
||||
|
||||
$mapData[] = [
|
||||
'config' => $allMapData->mapData,
|
||||
'data' => [
|
||||
@@ -613,33 +640,22 @@ class Map extends \Controller\AccessController {
|
||||
|
||||
/**
|
||||
* update map data api
|
||||
* function is called continuously
|
||||
* @param $f3
|
||||
* -> function is called continuously by any active client
|
||||
* @param \Base $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;
|
||||
|
||||
public function updateUserData(\Base $f3){
|
||||
$return = (object) [];
|
||||
$return->error = [];
|
||||
$activeCharacter = $this->getCharacter(0);
|
||||
|
||||
$user = $this->_getUser();
|
||||
|
||||
if($user){
|
||||
if($activeCharacter){
|
||||
|
||||
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);
|
||||
// update current location
|
||||
$activeCharacter = $activeCharacter->updateLog();
|
||||
|
||||
// if data is requested extend the cache key in order to get new data
|
||||
$requestSystemData = (object) [];
|
||||
@@ -649,14 +665,13 @@ class Map extends \Controller\AccessController {
|
||||
// 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
|
||||
// the userMapData 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 ){
|
||||
if( !$f3->exists($cacheKey) ){
|
||||
foreach($mapIds as $mapId){
|
||||
$map = $user->getMap($mapId);
|
||||
$map = $activeCharacter->getMap($mapId);
|
||||
|
||||
if( !is_null($map) ){
|
||||
$return->mapUserData[] = $map->getUserData();
|
||||
@@ -666,7 +681,7 @@ class Map extends \Controller\AccessController {
|
||||
$system = $map->getSystem( $requestSystemData->systemId );
|
||||
|
||||
if( !is_null($system) ){
|
||||
// data for the current selected system
|
||||
// data for currently selected system
|
||||
$return->system = $system->getData();
|
||||
$return->system->signatures = $system->getSignaturesData();
|
||||
}
|
||||
@@ -674,6 +689,10 @@ class Map extends \Controller\AccessController {
|
||||
}
|
||||
}
|
||||
|
||||
// cache time (seconds) should be equal or less than request trigger time
|
||||
// prevent request flooding
|
||||
$responseTTL = (int)$f3->get('PATHFINDER.TIMER.UPDATE_SERVER_USER_DATA.DELAY') / 1000;
|
||||
|
||||
// cache response
|
||||
$f3->set($cacheKey, $return, $responseTTL);
|
||||
}else{
|
||||
@@ -686,14 +705,12 @@ class Map extends \Controller\AccessController {
|
||||
|
||||
// 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();
|
||||
|
||||
$return->userData = $activeCharacter->getUser()->getData();
|
||||
}else{
|
||||
// user logged off
|
||||
$return->error[] = $this->getUserLoggedOffError();
|
||||
$return->error[] = $this->getLogoutError();
|
||||
}
|
||||
|
||||
|
||||
echo json_encode( $return );
|
||||
}
|
||||
|
||||
|
||||
@@ -14,14 +14,12 @@ class Signature extends \Controller\AccessController{
|
||||
|
||||
/**
|
||||
* event handler
|
||||
* @param $f3
|
||||
* @param \Base $f3
|
||||
*/
|
||||
function beforeroute($f3) {
|
||||
|
||||
parent::beforeroute($f3);
|
||||
|
||||
function beforeroute(\Base $f3) {
|
||||
// set header for all routes
|
||||
header('Content-type: application/json');
|
||||
parent::beforeroute($f3);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -31,18 +29,18 @@ class Signature extends \Controller\AccessController{
|
||||
public function getAll($f3){
|
||||
$signatureData = [];
|
||||
$systemIds = $f3->get('POST.systemIds');
|
||||
$activeCharacter = $this->getCharacter();
|
||||
|
||||
$user = $this->_getUser();
|
||||
|
||||
/**
|
||||
* @var Model\SystemModel $system
|
||||
*/
|
||||
$system = Model\BasicModel::getNew('SystemModel');
|
||||
|
||||
foreach($systemIds as $systemId){
|
||||
$system->getById($systemId);
|
||||
|
||||
if(!$system->dry()){
|
||||
|
||||
// check access
|
||||
if($system->hasAccess($user)){
|
||||
if( $system->hasAccess($activeCharacter) ){
|
||||
$signatureData = $system->getSignaturesData();
|
||||
}
|
||||
}
|
||||
@@ -74,11 +72,13 @@ class Signature extends \Controller\AccessController{
|
||||
}
|
||||
|
||||
if( !is_null($signatureData) ){
|
||||
$user = $this->_getUser();
|
||||
$activeCharacter = $this->getCharacter();
|
||||
|
||||
if($user){
|
||||
$activeUserCharacter = $user->getActiveUserCharacter();
|
||||
$activeCharacter = $activeUserCharacter->getCharacter();
|
||||
if($activeCharacter){
|
||||
|
||||
/**
|
||||
* @var Model\SystemModel $system
|
||||
*/
|
||||
$system = Model\BasicModel::getNew('SystemModel');
|
||||
|
||||
// update/add all submitted signatures
|
||||
@@ -94,9 +94,9 @@ class Signature extends \Controller\AccessController{
|
||||
$signature = null;
|
||||
if( isset($data['pk']) ){
|
||||
// try to get system by "primary key"
|
||||
$signature = $system->getSignatureById($user, (int)$data['pk']);
|
||||
$signature = $system->getSignatureById($activeCharacter, (int)$data['pk']);
|
||||
}elseif( isset($data['name']) ){
|
||||
$signature = $system->getSignatureByName($user, $data['name']);
|
||||
$signature = $system->getSignatureByName($activeCharacter, $data['name']);
|
||||
}
|
||||
|
||||
if( is_null($signature) ){
|
||||
@@ -173,23 +173,23 @@ class Signature extends \Controller\AccessController{
|
||||
|
||||
/**
|
||||
* delete signatures
|
||||
* @param $f3
|
||||
* @param \Base $f3
|
||||
*/
|
||||
public function delete($f3){
|
||||
$signatureIds = $f3->get('POST.signatureIds');
|
||||
$activeCharacter = $this->getCharacter();
|
||||
|
||||
$user = $this->_getUser();
|
||||
/**
|
||||
* @var Model\SystemSignatureModel $signature
|
||||
*/
|
||||
$signature = Model\BasicModel::getNew('SystemSignatureModel');
|
||||
|
||||
foreach($signatureIds as $signatureId){
|
||||
$signature->getById($signatureId);
|
||||
|
||||
$signature->delete($user);
|
||||
$signature->delete( $activeCharacter );
|
||||
$signature->reset();
|
||||
}
|
||||
|
||||
echo json_encode([]);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -63,9 +63,9 @@ class System extends \Controller\AccessController {
|
||||
private $limitQuery = "";
|
||||
|
||||
/**
|
||||
* @param $f3
|
||||
* @param \Base $f3
|
||||
*/
|
||||
function beforeroute($f3) {
|
||||
function beforeroute(\Base $f3) {
|
||||
|
||||
parent::beforeroute($f3);
|
||||
|
||||
@@ -92,7 +92,8 @@ class System extends \Controller\AccessController {
|
||||
* get static system Data from CCPs Static DB export
|
||||
* search column for IDs can be (solarSystemID, regionID, constellationID)
|
||||
* @param array $columnIDs
|
||||
* @return null
|
||||
* @param string $column
|
||||
* @return Model\SystemModel[]
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function _getSystemModelByIds($columnIDs = [], $column = 'solarSystemID'){
|
||||
@@ -110,10 +111,12 @@ class System extends \Controller\AccessController {
|
||||
|
||||
// format result
|
||||
$mapper = new Mapper\CcpSystemsMapper($rows);
|
||||
|
||||
$ccpSystemsData = $mapper->getData();
|
||||
|
||||
foreach($ccpSystemsData as $ccpSystemData){
|
||||
/**
|
||||
* @var Model\SystemModel $system
|
||||
*/
|
||||
$system = Model\BasicModel::getNew('SystemModel');
|
||||
$system->setData($ccpSystemData);
|
||||
$systemModels[] = $system;
|
||||
@@ -142,10 +145,10 @@ class System extends \Controller\AccessController {
|
||||
|
||||
/**
|
||||
* search systems by name
|
||||
* @param $f3
|
||||
* @param $params
|
||||
* @param \Base $f3
|
||||
* @param array $params
|
||||
*/
|
||||
public function search($f3, $params){
|
||||
public function search(\Base $f3, $params){
|
||||
|
||||
$ccpDB = $this->getDB('CCP');
|
||||
|
||||
@@ -172,10 +175,9 @@ class System extends \Controller\AccessController {
|
||||
|
||||
/**
|
||||
* save a new system to a a map
|
||||
* @param $f3
|
||||
* @param \Base $f3
|
||||
*/
|
||||
public function save($f3){
|
||||
|
||||
public function save(\Base $f3){
|
||||
$newSystemData = [];
|
||||
|
||||
$postData = (array)$f3->get('POST');
|
||||
@@ -187,22 +189,22 @@ class System extends \Controller\AccessController {
|
||||
isset($postData['systemData']) &&
|
||||
isset($postData['mapData'])
|
||||
){
|
||||
$user = $this->_getUser();
|
||||
$activeCharacter = $this->getCharacter();
|
||||
|
||||
if($user){
|
||||
if($activeCharacter){
|
||||
$systemData = (array)$postData['systemData'];
|
||||
$mapData = (array)$postData['mapData'];
|
||||
|
||||
$activeCharacter = $user->getActiveUserCharacter();
|
||||
|
||||
if( isset($systemData['id']) ){
|
||||
// update existing system
|
||||
|
||||
/**
|
||||
* @var $system Model\SystemModel
|
||||
*/
|
||||
$system = Model\BasicModel::getNew('SystemModel');
|
||||
$system->getById($systemData['id']);
|
||||
|
||||
if( !$system->dry() ){
|
||||
if( $system->hasAccess($user) ){
|
||||
if( $system->hasAccess($activeCharacter) ){
|
||||
// system model found
|
||||
$systemModel = $system;
|
||||
}
|
||||
@@ -210,18 +212,20 @@ class System extends \Controller\AccessController {
|
||||
}elseif( isset($mapData['id']) ){
|
||||
// save NEW system
|
||||
|
||||
/**
|
||||
* @var $map Model\MapModel
|
||||
*/
|
||||
$map = Model\BasicModel::getNew('MapModel');
|
||||
$map->getById($mapData['id']);
|
||||
|
||||
if( !$map->dry() ){
|
||||
if( $map->hasAccess($user) ){
|
||||
if( $map->hasAccess($activeCharacter) ){
|
||||
|
||||
$systemData['mapId'] = $map;
|
||||
|
||||
// get static system data (CCP DB)
|
||||
$systemModel = array_values( $this->_getSystemModelByIds([$systemData['systemId']]) )[0];
|
||||
|
||||
$systemModel->createdCharacterId = $activeCharacter->characterId;
|
||||
$systemModel->createdCharacterId = $activeCharacter;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -229,50 +233,23 @@ class System extends \Controller\AccessController {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if( !is_null($systemModel) ){
|
||||
// set/update system
|
||||
|
||||
$systemModel->setData($systemData);
|
||||
$systemModel->updatedCharacterId = $activeCharacter->characterId;
|
||||
$systemModel->updatedCharacterId = $activeCharacter;
|
||||
$systemModel->save();
|
||||
|
||||
$newSystemData = $systemModel->getData();
|
||||
}
|
||||
|
||||
echo json_encode($newSystemData);
|
||||
}
|
||||
|
||||
/**
|
||||
* delete systems and all its connections
|
||||
* @param $f3
|
||||
*/
|
||||
public function delete($f3){
|
||||
$systemIds = $f3->get('POST.systemIds');
|
||||
|
||||
$user = $this->_getUser();
|
||||
|
||||
if($user){
|
||||
$system = Model\BasicModel::getNew('SystemModel');
|
||||
|
||||
foreach((array)$systemIds as $systemId){
|
||||
|
||||
$system->getById($systemId);
|
||||
$system->delete($user);
|
||||
|
||||
$system->reset();
|
||||
}
|
||||
}
|
||||
|
||||
echo json_encode([]);
|
||||
}
|
||||
|
||||
/**
|
||||
* get system log data from CCP API import
|
||||
* system Kills, Jumps,....
|
||||
* @param $f3
|
||||
* @param \Base $f3
|
||||
*/
|
||||
public function graphData($f3){
|
||||
public function graphData(\Base $f3){
|
||||
$graphData = [];
|
||||
$systemIds = $f3->get('POST.systemIds');
|
||||
|
||||
@@ -288,14 +265,13 @@ class System extends \Controller\AccessController {
|
||||
];
|
||||
|
||||
foreach($systemIds as $systemId){
|
||||
|
||||
foreach($logTables as $label => $ModelClass){
|
||||
$systemLogModel = Model\BasicModel::getNew($ModelClass);
|
||||
|
||||
// 10min cache (could be up to 1h cache time)
|
||||
$systemLogModel->getByForeignKey('systemId', $systemId, array(), 60 * 10);
|
||||
$systemLogModel->getByForeignKey('systemId', $systemId, [], 60 * 10);
|
||||
|
||||
if(!$systemLogModel->dry()){
|
||||
if( !$systemLogModel->dry() ){
|
||||
$counter = 0;
|
||||
for( $i = $logEntryCount; $i >= 1; $i--){
|
||||
$column = 'value' . $i;
|
||||
@@ -313,7 +289,6 @@ class System extends \Controller\AccessController {
|
||||
$counter++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,25 +297,22 @@ class System extends \Controller\AccessController {
|
||||
|
||||
/**
|
||||
* get system data for all systems within a constellation
|
||||
* @param $f3
|
||||
* @param $params
|
||||
* @param \Base $f3
|
||||
* @param array $params
|
||||
*/
|
||||
public function constellationData($f3, $params){
|
||||
|
||||
public function constellationData(\Base $f3, $params){
|
||||
$return = (object) [];
|
||||
$return->error = [];
|
||||
$return->systemData = [];
|
||||
|
||||
$constellationId = 0;
|
||||
$activeCharacter = $this->getCharacter();
|
||||
|
||||
$user = $this->_getUser();
|
||||
|
||||
if($user){
|
||||
if($activeCharacter){
|
||||
// check for search parameter
|
||||
if( isset($params['arg1']) ){
|
||||
$constellationId = (int)$params['arg1'];
|
||||
}
|
||||
|
||||
$cacheKey = 'CACHE_CONSTELLATION_SYSTEMS_' . self::formatHiveKey($constellationId);
|
||||
|
||||
if($f3->exists($cacheKey)){
|
||||
@@ -361,7 +333,27 @@ class System extends \Controller\AccessController {
|
||||
echo json_encode($return);
|
||||
}
|
||||
|
||||
/**
|
||||
* delete systems and all its connections
|
||||
* @param \Base $f3
|
||||
*/
|
||||
public function delete(\Base $f3){
|
||||
$systemIds = $f3->get('POST.systemIds');
|
||||
|
||||
if($activeCharacter = $this->getCharacter()){
|
||||
/**
|
||||
* @var Model\SystemModel $system
|
||||
*/
|
||||
$system = Model\BasicModel::getNew('SystemModel');
|
||||
foreach((array)$systemIds as $systemId){
|
||||
$system->getById($systemId);
|
||||
$system->delete($activeCharacter);
|
||||
$system->reset();
|
||||
}
|
||||
}
|
||||
|
||||
echo json_encode([]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -15,87 +15,80 @@ use DB;
|
||||
|
||||
class User extends Controller\Controller{
|
||||
|
||||
// captcha specific session keys
|
||||
const SESSION_CAPTCHA_ACCOUNT_UPDATE = 'SESSION.CAPTCHA.ACCOUNT.UPDATE';
|
||||
const SESSION_CAPTCHA_ACCOUNT_DELETE = 'SESSION.CAPTCHA.ACCOUNT.DELETE';
|
||||
|
||||
// user specific session keys
|
||||
const SESSION_KEY_USER = 'SESSION.USER';
|
||||
const SESSION_KEY_USER_ID = 'SESSION.USER.ID';
|
||||
const SESSION_KEY_USER_NAME = 'SESSION.USER.NAME';
|
||||
|
||||
// character specific session keys
|
||||
const SESSION_KEY_CHARACTER = 'SESSION.CHARACTER';
|
||||
const SESSION_KEY_CHARACTER_ID = 'SESSION.CHARACTER.ID';
|
||||
const SESSION_KEY_CHARACTER_NAME = 'SESSION.CHARACTER.NAME';
|
||||
const SESSION_KEY_CHARACTER_TIME = 'SESSION.CHARACTER.TIME';
|
||||
|
||||
const SESSION_KEY_CHARACTER_ACCESS_TOKEN = 'SESSION.CHARACTER.ACCESS_TOKEN';
|
||||
const SESSION_KEY_CHARACTER_REFRESH_TOKEN = 'SESSION.CHARACTER.REFRESH_TOKEN';
|
||||
|
||||
// log text
|
||||
const LOG_LOGGED_IN = 'userId: %s, userName: %s, charId: %s, charName: %s';
|
||||
|
||||
/**
|
||||
* valid reasons for captcha images
|
||||
* @var array
|
||||
* @var string array
|
||||
*/
|
||||
private static $captchaReason = ['createAccount', 'deleteAccount'];
|
||||
private static $captchaReason = [self::SESSION_CAPTCHA_ACCOUNT_UPDATE, self::SESSION_CAPTCHA_ACCOUNT_DELETE];
|
||||
|
||||
/**
|
||||
* login function
|
||||
* @param $f3
|
||||
* login a valid character
|
||||
* @param Model\CharacterModel $characterModel
|
||||
* @return bool
|
||||
*/
|
||||
public function logIn($f3){
|
||||
$data = $data = $f3->get('POST');
|
||||
protected function loginByCharacter(Model\CharacterModel &$characterModel){
|
||||
$login = false;
|
||||
|
||||
$return = (object) [];
|
||||
|
||||
$user = null;
|
||||
|
||||
if($data['loginData']){
|
||||
$loginData = $data['loginData'];
|
||||
$user = $this->logUserIn( $loginData['userName'], $loginData['userPassword'] );
|
||||
}
|
||||
|
||||
// set "vague" error
|
||||
if(is_null($user)){
|
||||
$return->error = [];
|
||||
$loginError = (object) [];
|
||||
$loginError->type = 'login';
|
||||
$return->error[] = $loginError;
|
||||
}else{
|
||||
// update/check api data
|
||||
$user->updateApiData();
|
||||
|
||||
// route user to map app
|
||||
$return->reroute = rtrim(self::getEnvironmentData('URL'), '/') . $f3->alias('map');
|
||||
}
|
||||
|
||||
echo json_encode($return);
|
||||
}
|
||||
|
||||
/**
|
||||
* core function for user login
|
||||
* @param $userName
|
||||
* @param $password
|
||||
* @return Model\UserModel|null
|
||||
*/
|
||||
private function logUserIn($userName, $password){
|
||||
|
||||
// try to verify user
|
||||
$user = $this->_verifyUser($userName, $password);
|
||||
|
||||
if( !is_null($user)){
|
||||
// user is verified -> ready for login
|
||||
|
||||
// set Session login
|
||||
$dateTime = new \DateTime();
|
||||
|
||||
$this->f3->set('SESSION.user', [
|
||||
'time' => $dateTime->getTimestamp(),
|
||||
'name' => $user->name,
|
||||
'id' => $user->id
|
||||
if($user = $characterModel->getUser()){
|
||||
// set user/character data to session -------------------
|
||||
$this->f3->set(self::SESSION_KEY_USER, [
|
||||
'ID' => $user->_id,
|
||||
'NAME' => $user->name
|
||||
]);
|
||||
|
||||
// save user login information
|
||||
$user->touch('lastLogin');
|
||||
$user->save();
|
||||
$dateTime = new \DateTime();
|
||||
$this->f3->set(self::SESSION_KEY_CHARACTER, [
|
||||
'ID' => $characterModel->_id,
|
||||
'NAME' => $characterModel->name,
|
||||
'TIME' => $dateTime->getTimestamp()
|
||||
]);
|
||||
|
||||
// save log
|
||||
$logText = "id: %s, name: %s, ip: %s";
|
||||
// save user login information ---------------------------
|
||||
$characterModel->touch('lastLogin');
|
||||
$characterModel->save();
|
||||
|
||||
// write login log --------------------------------------
|
||||
self::getLogger( $this->f3->get('PATHFINDER.LOGFILES.LOGIN') )->write(
|
||||
sprintf($logText, $user->id, $user->name, $this->f3->get('IP'))
|
||||
sprintf(self::LOG_LOGGED_IN,
|
||||
$user->_id,
|
||||
$user->name,
|
||||
$characterModel->_id,
|
||||
$characterModel->name
|
||||
)
|
||||
);
|
||||
|
||||
$login = true;
|
||||
}
|
||||
|
||||
return $user;
|
||||
return $login;
|
||||
}
|
||||
|
||||
/**
|
||||
* get captcha image and store key to session
|
||||
* @param $f3
|
||||
* @param \Base $f3
|
||||
*/
|
||||
public function getCaptcha($f3){
|
||||
public function getCaptcha(\Base $f3){
|
||||
$data = $f3->get('POST');
|
||||
|
||||
$return = (object) [];
|
||||
@@ -117,7 +110,7 @@ class User extends Controller\Controller{
|
||||
'fonts/oxygen-bold-webfont.ttf',
|
||||
14,
|
||||
6,
|
||||
'SESSION.' . $reason,
|
||||
$reason,
|
||||
'',
|
||||
$colorText,
|
||||
$colorBG
|
||||
@@ -136,29 +129,22 @@ class User extends Controller\Controller{
|
||||
|
||||
/**
|
||||
* delete the character log entry for the current active (main) character
|
||||
* @param $f3
|
||||
* @param \Base $f3
|
||||
*/
|
||||
public function deleteLog($f3){
|
||||
|
||||
$user = $this->_getUser();
|
||||
if($user){
|
||||
$activeUserCharacter = $user->getActiveUserCharacter();
|
||||
|
||||
if($activeUserCharacter){
|
||||
$character = $activeUserCharacter->getCharacter();
|
||||
|
||||
if($characterLog = $character->getLog()){
|
||||
$characterLog->erase();
|
||||
}
|
||||
public function deleteLog(\Base $f3){
|
||||
$activeCharacter = $this->getCharacter();
|
||||
if($activeCharacter){
|
||||
if($characterLog = $activeCharacter->getLog()){
|
||||
$characterLog->erase();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* log the current user out + clear character system log data
|
||||
* @param $f3
|
||||
* @param \Base $f3
|
||||
*/
|
||||
public function logOut($f3){
|
||||
public function logOut(\Base $f3){
|
||||
$this->deleteLog($f3);
|
||||
parent::logOut($f3);
|
||||
}
|
||||
@@ -166,20 +152,19 @@ class User extends Controller\Controller{
|
||||
/**
|
||||
* save/update "map sharing" configurations for all map types
|
||||
* the user has access to
|
||||
* @param $f3
|
||||
* @param \Base $f3
|
||||
*/
|
||||
public function saveSharingConfig($f3){
|
||||
public function saveSharingConfig(\Base $f3){
|
||||
$data = $f3->get('POST');
|
||||
|
||||
$return = (object) [];
|
||||
|
||||
$privateSharing = 0;
|
||||
$corporationSharing = 0;
|
||||
$allianceSharing = 0;
|
||||
$activeCharacter = $this->getCharacter();
|
||||
|
||||
$user = $this->_getUser();
|
||||
|
||||
if($user){
|
||||
if($activeCharacter){
|
||||
$privateSharing = 0;
|
||||
$corporationSharing = 0;
|
||||
$allianceSharing = 0;
|
||||
|
||||
// form values
|
||||
if(isset($data['formData'])){
|
||||
@@ -198,28 +183,24 @@ class User extends Controller\Controller{
|
||||
}
|
||||
}
|
||||
|
||||
$user->shared = $privateSharing;
|
||||
$user->save();
|
||||
$activeCharacter->shared = $privateSharing;
|
||||
$activeCharacter = $activeCharacter->save();
|
||||
|
||||
// update corp/ally ---------------------------------------------------------------
|
||||
$corporation = $activeCharacter->getCorporation();
|
||||
$alliance = $activeCharacter->getAlliance();
|
||||
|
||||
$activeUserCharacter = $user->getActiveUserCharacter();
|
||||
|
||||
if(is_object($activeUserCharacter)){
|
||||
$corporation = $activeUserCharacter->getCharacter()->getCorporation();
|
||||
$alliance = $activeUserCharacter->getCharacter()->getAlliance();
|
||||
|
||||
if(is_object($corporation)){
|
||||
$corporation->shared = $corporationSharing;
|
||||
$corporation->save();
|
||||
}
|
||||
|
||||
if(is_object($alliance)){
|
||||
$alliance->shared = $allianceSharing;
|
||||
$alliance->save();
|
||||
}
|
||||
if(is_object($corporation)){
|
||||
$corporation->shared = $corporationSharing;
|
||||
$corporation->save();
|
||||
}
|
||||
|
||||
if(is_object($alliance)){
|
||||
$alliance->shared = $allianceSharing;
|
||||
$alliance->save();
|
||||
}
|
||||
|
||||
$user = $activeCharacter->getUser();
|
||||
$return->userData = $user->getData();
|
||||
}
|
||||
|
||||
@@ -227,246 +208,111 @@ class User extends Controller\Controller{
|
||||
}
|
||||
|
||||
/**
|
||||
* search for a registration key model
|
||||
* e.g. for new user registration with "invite" feature enabled
|
||||
* @param $email
|
||||
* @param $registrationKey
|
||||
* @return bool|Model\RegistrationKeyModel
|
||||
* @throws Exception
|
||||
* update user account data
|
||||
* -> a fresh user automatically generated on first login with a new character
|
||||
* -> see CREST SSO login
|
||||
* @param \Base $f3
|
||||
*/
|
||||
protected function getRegistrationKey($email, $registrationKey){
|
||||
$registrationKeyModel = Model\BasicModel::getNew('RegistrationKeyModel');
|
||||
$registrationKeyModel->load([
|
||||
'registrationKey = :registrationKey AND
|
||||
email = :email AND
|
||||
used = 0 AND
|
||||
active = 1',
|
||||
':registrationKey' => $registrationKey,
|
||||
':email' => $email
|
||||
]);
|
||||
|
||||
if( $registrationKeyModel->dry() ){
|
||||
return false;
|
||||
}else{
|
||||
return $registrationKeyModel;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* check if there is already an active Key for a mail
|
||||
* @param $email
|
||||
* @param bool|false $used
|
||||
* @return bool|null
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function findRegistrationKey($email, $used = false){
|
||||
|
||||
$queryPart = 'email = :email AND active = 1';
|
||||
|
||||
if(is_int($used)){
|
||||
$queryPart .= ' AND used = ' . $used;
|
||||
}
|
||||
|
||||
$registrationKeyModel = Model\BasicModel::getNew('RegistrationKeyModel');
|
||||
$registrationKeyModels = $registrationKeyModel->find([
|
||||
$queryPart,
|
||||
':email' => $email
|
||||
]);
|
||||
|
||||
if( is_object($registrationKeyModels) ){
|
||||
return $registrationKeyModels;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* save/update user account data
|
||||
* @param $f3
|
||||
*/
|
||||
public function saveAccount($f3){
|
||||
public function saveAccount(\Base $f3){
|
||||
$data = $f3->get('POST');
|
||||
|
||||
$return = (object) [];
|
||||
$return->error = [];
|
||||
|
||||
$captcha = $f3->get('SESSION.createAccount');
|
||||
$captcha = $f3->get(self::SESSION_CAPTCHA_ACCOUNT_UPDATE);
|
||||
|
||||
// reset captcha -> forces user to enter new one
|
||||
$f3->clear('SESSION.createAccount');
|
||||
$f3->clear(self::SESSION_CAPTCHA_ACCOUNT_UPDATE);
|
||||
|
||||
$newUserData = null;
|
||||
|
||||
// check for new user
|
||||
$loginAfterSave = false;
|
||||
|
||||
// valid registration key Model is required for new registration
|
||||
// if "invite" feature is enabled
|
||||
$registrationKeyModel = false;
|
||||
|
||||
if( isset($data['settingsData']) ){
|
||||
$settingsData = $data['settingsData'];
|
||||
if( isset($data['formData']) ){
|
||||
$formData = $data['formData'];
|
||||
|
||||
try{
|
||||
$user = $this->_getUser(0);
|
||||
if($activeCharacter = $this->getCharacter(0)){
|
||||
$user = $activeCharacter->getUser();
|
||||
|
||||
// captcha is send -> check captcha
|
||||
if(
|
||||
isset($settingsData['captcha']) &&
|
||||
!empty($settingsData['captcha'])
|
||||
){
|
||||
|
||||
|
||||
if($settingsData['captcha'] === $captcha){
|
||||
// change/set sensitive user data requires captcha!
|
||||
|
||||
if($user === false){
|
||||
|
||||
// check if registration key invite function is enabled
|
||||
if($f3->get('PATHFINDER.REGISTRATION.INVITE') === 1 ){
|
||||
$registrationKeyModel = $this->getRegistrationKey( $settingsData['email'], $settingsData['registrationKey'] );
|
||||
|
||||
if($registrationKeyModel === false){
|
||||
throw new Exception\RegistrationException('Registration key invalid', 'registrationKey');
|
||||
}
|
||||
}
|
||||
|
||||
// new user registration
|
||||
$user = $mapType = Model\BasicModel::getNew('UserModel');
|
||||
$loginAfterSave = true;
|
||||
// captcha is send -> check captcha ---------------------------------
|
||||
if(
|
||||
isset($formData['captcha']) &&
|
||||
!empty($formData['captcha'])
|
||||
){
|
||||
if($formData['captcha'] === $captcha){
|
||||
// change/set sensitive user data requires captcha!
|
||||
|
||||
// set username
|
||||
if(
|
||||
isset($settingsData['name']) &&
|
||||
!empty($settingsData['name'])
|
||||
isset($formData['name']) &&
|
||||
!empty($formData['name'])
|
||||
){
|
||||
$user->name = $settingsData['name'];
|
||||
}
|
||||
}
|
||||
|
||||
// change/set email
|
||||
if(
|
||||
isset($settingsData['email']) &&
|
||||
isset($settingsData['email_confirm']) &&
|
||||
!empty($settingsData['email']) &&
|
||||
!empty($settingsData['email_confirm']) &&
|
||||
$settingsData['email'] == $settingsData['email_confirm']
|
||||
){
|
||||
$user->email = $settingsData['email'];
|
||||
}
|
||||
|
||||
// change/set password
|
||||
if(
|
||||
isset($settingsData['password']) &&
|
||||
isset($settingsData['password_confirm']) &&
|
||||
!empty($settingsData['password']) &&
|
||||
!empty($settingsData['password_confirm']) &&
|
||||
$settingsData['password'] == $settingsData['password_confirm']
|
||||
){
|
||||
$user->password = $settingsData['password'];
|
||||
}
|
||||
}else{
|
||||
// captcha was send but not valid -> return error
|
||||
$captchaError = (object) [];
|
||||
$captchaError->type = 'error';
|
||||
$captchaError->message = 'Captcha does not match';
|
||||
$return->error[] = $captchaError;
|
||||
}
|
||||
}
|
||||
|
||||
// saving additional user info requires valid user object (no captcha required)
|
||||
if($user){
|
||||
|
||||
// save API data
|
||||
if(
|
||||
isset($settingsData['keyId']) &&
|
||||
isset($settingsData['vCode']) &&
|
||||
is_array($settingsData['keyId']) &&
|
||||
is_array($settingsData['vCode'])
|
||||
){
|
||||
|
||||
// get all existing API models for this user
|
||||
$apiModels = $user->getAPIs();
|
||||
|
||||
foreach($settingsData['keyId'] as $i => $keyId){
|
||||
$api = null;
|
||||
|
||||
// search for existing API model
|
||||
foreach($apiModels as $key => $apiModel){
|
||||
if($apiModel->keyId == $keyId){
|
||||
$api = $apiModel;
|
||||
// make sure model is up2data -> cast()
|
||||
$api->cast();
|
||||
unset($apiModels[$key]);
|
||||
break;
|
||||
}
|
||||
$user->name = $formData['name'];
|
||||
}
|
||||
|
||||
if(is_null($api)){
|
||||
// new API Key
|
||||
$api = Model\BasicModel::getNew('UserApiModel');
|
||||
$api->userId = $user;
|
||||
// set email
|
||||
if(
|
||||
isset($formData['email']) &&
|
||||
isset($formData['email_confirm']) &&
|
||||
!empty($formData['email']) &&
|
||||
!empty($formData['email_confirm']) &&
|
||||
$formData['email'] == $formData['email_confirm']
|
||||
){
|
||||
$user->email = $formData['email'];
|
||||
}
|
||||
|
||||
$api->keyId = $keyId;
|
||||
$api->vCode = $settingsData['vCode'][$i];
|
||||
$api->save();
|
||||
// save/update user model
|
||||
// this will fail if model validation fails!
|
||||
$user->save();
|
||||
|
||||
$characterCount = $api->updateCharacters();
|
||||
}else{
|
||||
// captcha was send but not valid -> return error
|
||||
$captchaError = (object) [];
|
||||
$captchaError->type = 'error';
|
||||
$captchaError->message = 'Captcha does not match';
|
||||
$return->error[] = $captchaError;
|
||||
}
|
||||
}
|
||||
|
||||
if($characterCount == 0){
|
||||
// no characters found -> return warning
|
||||
$characterError = (object) [];
|
||||
$characterError->type = 'warning';
|
||||
$characterError->message = 'API verification failed. No Characters found for KeyId ' . $api->keyId;
|
||||
$return->error[] = $characterError;
|
||||
}
|
||||
// sharing config ---------------------------------------------------
|
||||
if(isset($formData['share'])){
|
||||
$privateSharing = 0;
|
||||
$corporationSharing = 0;
|
||||
$allianceSharing = 0;
|
||||
|
||||
if(isset($formData['privateSharing'])){
|
||||
$privateSharing = 1;
|
||||
}
|
||||
|
||||
// delete API models that no longer exists
|
||||
foreach($apiModels as $apiModel){
|
||||
$apiModel->delete();
|
||||
if(isset($formData['corporationSharing'])){
|
||||
$corporationSharing = 1;
|
||||
}
|
||||
|
||||
// get fresh updated user object (API info may have has changed)
|
||||
$user = $this->_getUser(0);
|
||||
}
|
||||
if(isset($formData['allianceSharing'])){
|
||||
$allianceSharing = 1;
|
||||
}
|
||||
|
||||
// set main character
|
||||
if( isset($settingsData['mainCharacterId']) ){
|
||||
$user->setMainCharacterId((int)$settingsData['mainCharacterId']);
|
||||
}
|
||||
// update private/corp/ally
|
||||
$corporation = $activeCharacter->getCorporation();
|
||||
$alliance = $activeCharacter->getAlliance();
|
||||
|
||||
// check if the user already has a main character
|
||||
// if not -> save the next best character as main
|
||||
$mainUserCharacter = $user->getMainUserCharacter();
|
||||
if(is_object($corporation)){
|
||||
$corporation->shared = $corporationSharing;
|
||||
$corporation->save();
|
||||
}
|
||||
|
||||
// set main character if no main character exists
|
||||
if(is_null($mainUserCharacter)){
|
||||
$user->setMainCharacterId();
|
||||
}
|
||||
if(is_object($alliance)){
|
||||
$alliance->shared = $allianceSharing;
|
||||
$alliance->save();
|
||||
}
|
||||
|
||||
// save/update user model
|
||||
// this will fail if model validation fails!
|
||||
$user->save();
|
||||
|
||||
if(is_object($registrationKeyModel)){
|
||||
$registrationKeyModel->used = 1;
|
||||
$registrationKeyModel->save();
|
||||
}
|
||||
|
||||
// log user in (in case he is new
|
||||
if($loginAfterSave){
|
||||
$this->logUserIn( $user->name, $settingsData['password'] );
|
||||
|
||||
// return reroute path
|
||||
$return->reroute = rtrim(self::getEnvironmentData('URL'), '/') . $this->f3->alias('map');
|
||||
$activeCharacter->shared = $privateSharing;
|
||||
$activeCharacter->save();
|
||||
}
|
||||
|
||||
// get fresh updated user object
|
||||
$user = $this->_getUser(0);
|
||||
$newUserData = $user->getData();
|
||||
}
|
||||
|
||||
}catch(Exception\ValidationException $e){
|
||||
$validationError = (object) [];
|
||||
$validationError->type = 'error';
|
||||
@@ -483,109 +329,6 @@ class User extends Controller\Controller{
|
||||
|
||||
// return new/updated user data
|
||||
$return->userData = $newUserData;
|
||||
|
||||
}
|
||||
echo json_encode($return);
|
||||
}
|
||||
|
||||
/**
|
||||
* send mail with registration key
|
||||
* -> check INVITE in pathfinder.ini
|
||||
* @param $f3
|
||||
* @throws Exception
|
||||
*/
|
||||
public function sendInvite($f3){
|
||||
$data = $f3->get('POST.settingsData');
|
||||
$return = (object) [];
|
||||
|
||||
// check invite limit
|
||||
// get handed out key count
|
||||
$tempRegistrationKeyModel = Model\BasicModel::getNew('RegistrationKeyModel');
|
||||
$tempRegistrationKeyModels = $tempRegistrationKeyModel->find([ '
|
||||
email != "" AND
|
||||
active = 1'
|
||||
]);
|
||||
|
||||
$totalKeys = 0;
|
||||
if(is_object($tempRegistrationKeyModels)){
|
||||
$totalKeys = $tempRegistrationKeyModels->count();
|
||||
}
|
||||
|
||||
if(
|
||||
$f3->get('PATHFINDER.REGISTRATION.INVITE') == 1 &&
|
||||
$totalKeys < $f3->get('PATHFINDER.REGISTRATION.INVITE_LIMIT')
|
||||
){
|
||||
// key limit not reached
|
||||
|
||||
if(
|
||||
isset($data['email']) &&
|
||||
!empty($data['email'])
|
||||
){
|
||||
$email = trim($data['email']);
|
||||
|
||||
// check if mail is valid
|
||||
if( \Audit::instance()->email($email) ){
|
||||
|
||||
// new key for this mail is allowed
|
||||
$registrationKeyModel = $this->findRegistrationKey($email, 0);
|
||||
|
||||
if($registrationKeyModel === false){
|
||||
|
||||
// check for total number of invites (active and inactive) -> prevent spamming
|
||||
$allRegistrationKeysByMail = $this->findRegistrationKey($email);
|
||||
|
||||
if(
|
||||
$allRegistrationKeysByMail == false ||
|
||||
$allRegistrationKeysByMail->count() < 3
|
||||
){
|
||||
|
||||
// get a fresh key
|
||||
$registrationKeyModel = Model\BasicModel::getNew('RegistrationKeyModel');
|
||||
$registrationKeyModel->load(['
|
||||
used = 0 AND
|
||||
active = 1 AND
|
||||
email = "" ',
|
||||
':email' => $email
|
||||
], ['limit' => 1]);
|
||||
|
||||
}else{
|
||||
$validationError = (object) [];
|
||||
$validationError->type = 'warning';
|
||||
$validationError->message = 'The number of keys is limited by Email. You can not get more keys';
|
||||
$return->error[] = $validationError;
|
||||
}
|
||||
|
||||
}else{
|
||||
$registrationKeyModel = $registrationKeyModel[0];
|
||||
}
|
||||
|
||||
// send "old" key again or send a new key
|
||||
if( is_object($registrationKeyModel) ){
|
||||
$msg = 'Your personal Registration Key: ' . $registrationKeyModel->registrationKey;
|
||||
|
||||
$mailController = new MailController();
|
||||
$status = $mailController->sendInviteKey($email, $msg);
|
||||
|
||||
if( $status ){
|
||||
$registrationKeyModel->email = $email;
|
||||
$registrationKeyModel->ip = $this->f3->get('IP');
|
||||
$registrationKeyModel->save();
|
||||
}
|
||||
}
|
||||
|
||||
}else{
|
||||
$validationError = (object) [];
|
||||
$validationError->type = 'error';
|
||||
$validationError->field = 'email';
|
||||
$validationError->message = 'Email is not valid';
|
||||
$return->error[] = $validationError;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
$validationError = (object) [];
|
||||
$validationError->type = 'warning';
|
||||
$validationError->message = 'The pool of beta keys has been exhausted, please try again in a few days/weeks';
|
||||
$return->error[] = $validationError;
|
||||
}
|
||||
|
||||
echo json_encode($return);
|
||||
@@ -593,31 +336,26 @@ class User extends Controller\Controller{
|
||||
|
||||
/**
|
||||
* delete current user account from DB
|
||||
* @param $f3
|
||||
* @param \Base $f3
|
||||
*/
|
||||
public function deleteAccount($f3){
|
||||
public function deleteAccount(\Base $f3){
|
||||
$data = $f3->get('POST.formData');
|
||||
$return = (object) [];
|
||||
|
||||
$captcha = $f3->get('SESSION.deleteAccount');
|
||||
$captcha = $f3->get(self::SESSION_CAPTCHA_ACCOUNT_DELETE);
|
||||
|
||||
// reset captcha -> forces user to enter new one
|
||||
$f3->clear('SESSION.deleteAccount');
|
||||
$f3->clear(self::SESSION_CAPTCHA_ACCOUNT_DELETE);
|
||||
|
||||
if(
|
||||
isset($data['captcha']) &&
|
||||
!empty($data['captcha']) &&
|
||||
$data['captcha'] === $captcha
|
||||
){
|
||||
$user = $this->_getUser(0);
|
||||
$activeCharacter = $this->getCharacter(0);
|
||||
$user = $activeCharacter->getUser();
|
||||
|
||||
$validUser = $this->_verifyUser( $user->name, $data['password']);
|
||||
|
||||
if(
|
||||
is_object($validUser) &&
|
||||
is_object($user) &&
|
||||
$user->id === $validUser->id
|
||||
){
|
||||
if($user){
|
||||
// send delete account mail
|
||||
$msg = 'Hello ' . $user->name . ',<br><br>';
|
||||
$msg .= 'your account data has been successfully deleted.';
|
||||
@@ -638,12 +376,6 @@ class User extends Controller\Controller{
|
||||
$this->logOut($f3);
|
||||
die();
|
||||
}
|
||||
}else{
|
||||
// password does not match current user pw
|
||||
$passwordError = (object) [];
|
||||
$passwordError->type = 'error';
|
||||
$passwordError->message = 'Invalid password';
|
||||
$return->error[] = $passwordError;
|
||||
}
|
||||
}else{
|
||||
// captcha not valid -> return error
|
||||
|
||||
@@ -7,15 +7,28 @@
|
||||
*/
|
||||
|
||||
namespace Controller;
|
||||
|
||||
use Controller\Ccp as Ccp;
|
||||
|
||||
class AppController extends Controller {
|
||||
|
||||
/**
|
||||
* show main login (index) page
|
||||
* @param $f3
|
||||
* event handler after routing
|
||||
* @param \Base $f3
|
||||
*/
|
||||
public function init($f3) {
|
||||
public function afterroute(\Base $f3){
|
||||
parent::afterroute($f3);
|
||||
|
||||
// clear all SSO related temp data
|
||||
if( $f3->exists(Ccp\Sso::SESSION_KEY_SSO) ){
|
||||
$f3->clear(Ccp\Sso::SESSION_KEY_SSO);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* show main login (index) page
|
||||
* @param \Base $f3
|
||||
*/
|
||||
public function init(\Base $f3) {
|
||||
// page title
|
||||
$f3->set('pageTitle', 'Login');
|
||||
|
||||
|
||||
659
app/main/controller/ccp/sso.php
Normal file
659
app/main/controller/ccp/sso.php
Normal file
@@ -0,0 +1,659 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Exodus
|
||||
* Date: 23.01.2016
|
||||
* Time: 17:18
|
||||
*
|
||||
* Handles access to EVE-Online "CREST API" and "SSO" auth functions
|
||||
* - Add your API credentials in "environment.ini"
|
||||
* - Check "PATHFINDER.API" in "pathfinder.ini" for correct API URLs
|
||||
* Hint: \Web::instance()->request automatically caches responses by their response "Cache-Control" header!
|
||||
*/
|
||||
|
||||
namespace Controller\Ccp;
|
||||
use Controller;
|
||||
use Controller\Api as Api;
|
||||
use Data\Mapper as Mapper;
|
||||
use Model;
|
||||
use Lib;
|
||||
|
||||
class Sso extends Api\User{
|
||||
|
||||
/**
|
||||
* @var int timeout (seconds) for API calls
|
||||
*/
|
||||
const CREST_TIMEOUT = 3;
|
||||
|
||||
/**
|
||||
* @var int expire time (seconds) for an valid "accessToken"
|
||||
*/
|
||||
const ACCESS_KEY_EXPIRE_TIME = 20 * 60;
|
||||
|
||||
// SSO specific session keys
|
||||
const SESSION_KEY_SSO = 'SESSION.SSO';
|
||||
const SESSION_KEY_SSO_ERROR = 'SESSION.SSO.ERROR';
|
||||
const SESSION_KEY_SSO_STATE = 'SESSION.SSO.STATE';
|
||||
const SESSION_KEY_SSO_CHARACTER_ID = 'SESSION.SSO.CHARACTER.ID';
|
||||
|
||||
// cache keys
|
||||
const CACHE_KEY_LOCATION_DATA = 'CACHED.LOCATION.%s';
|
||||
|
||||
// error messages
|
||||
const ERROR_CCP_SSO_URL = 'Invalid "ENVIRONMENT.[ENVIRONMENT].SSO_CCP_URL" url. %s';
|
||||
const ERROR_CCP_CREST_URL = 'Invalid "ENVIRONMENT.[ENVIRONMENT].CCP_CREST_URL" url. %s';
|
||||
const ERROR_RESOURCE_DEPRECATED = 'Resource: %s has been marked as deprecated. %s';
|
||||
const ERROR_ACCESS_TOKEN = 'Unable to get a valid "access_token. %s';
|
||||
const ERROR_VERIFY_CHARACTER = 'Unable to verify character data. %s';
|
||||
const ERROR_GET_ENDPOINT = 'Unable to get endpoint data. $s';
|
||||
const ERROR_FIND_ENDPOINT = 'Unable to find endpoint: %s';
|
||||
const ERROR_LOGIN_FAILED = 'Failed authentication due to technical problems: %s';
|
||||
const ERROR_CHARACTER_FORBIDDEN = 'Character "%s" is not authorized to log in';
|
||||
const ERROR_CHARACTER_MISMATCH = 'The character "%s" you tried to log in, does not match';
|
||||
const ERROR_SERVICE_TIMEOUT = 'CCP SSO service timeout (%ss). Try again later';
|
||||
|
||||
/**
|
||||
* CREST "Scopes" are used by pathfinder
|
||||
* -> Enable scopes: https://developers.eveonline.com
|
||||
* @var array
|
||||
*/
|
||||
private $requestScopes = [
|
||||
// 'characterFittingsRead',
|
||||
// 'characterFittingsWrite',
|
||||
'characterLocationRead',
|
||||
'characterNavigationWrite'
|
||||
];
|
||||
|
||||
/**
|
||||
* redirect user to CCP SSO page and request authorization
|
||||
* @param \Base $f3
|
||||
*/
|
||||
public function requestAuthorization($f3){
|
||||
$params = $f3->get('GET');
|
||||
|
||||
if(isset($params['characterId'])){
|
||||
// restrict login to this characterId e.g. for character switch
|
||||
$f3->set(self::SESSION_KEY_SSO_CHARACTER_ID, (int)trim($params['characterId']) );
|
||||
}
|
||||
|
||||
// used for "state" check between request and callback
|
||||
$state = bin2hex(mcrypt_create_iv(12, MCRYPT_DEV_URANDOM));
|
||||
$f3->set(self::SESSION_KEY_SSO_STATE, $state);
|
||||
|
||||
$urlParams = [
|
||||
'response_type' => 'code',
|
||||
'redirect_uri' => Controller\Controller::getEnvironmentData('URL') . $f3->build('/sso/callbackAuthorization'),
|
||||
'client_id' => Controller\Controller::getEnvironmentData('SSO_CCP_CLIENT_ID'),
|
||||
'scope' => implode(' ', $this->requestScopes),
|
||||
'state' => $state
|
||||
];
|
||||
|
||||
$ssoAuthUrl = self::getAuthorizationEndpoint() . '?' . http_build_query($urlParams, '', '&', PHP_QUERY_RFC3986 );
|
||||
|
||||
$f3->status(302);
|
||||
$f3->reroute($ssoAuthUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* callback handler for CCP SSO user Auth
|
||||
* -> see requestAuthorization()
|
||||
* @param \Base $f3
|
||||
*/
|
||||
public function callbackAuthorization($f3){
|
||||
$getParams = (array)$f3->get('GET');
|
||||
|
||||
// users can log in either from @login (new user) or @map (existing user) root alias
|
||||
// -> in case login fails, users should be redirected differently
|
||||
$authFromMapAlias = false;
|
||||
|
||||
if($f3->exists(self::SESSION_KEY_SSO_STATE)){
|
||||
// check response and validate 'state'
|
||||
if(
|
||||
isset($getParams['code']) &&
|
||||
isset($getParams['state']) &&
|
||||
!empty($getParams['code']) &&
|
||||
!empty($getParams['state']) &&
|
||||
$f3->get(self::SESSION_KEY_SSO_STATE) === $getParams['state']
|
||||
){
|
||||
// $requestedCharacterId can be [-1 => add char, 0 => new user, >0 => specific user]
|
||||
$requiredCharacterId = (int)$f3->get(self::SESSION_KEY_SSO_CHARACTER_ID);
|
||||
if($requiredCharacterId !== 0){
|
||||
$authFromMapAlias = true;
|
||||
}
|
||||
|
||||
// clear 'state' for new next login request
|
||||
$f3->clear(self::SESSION_KEY_SSO_STATE);
|
||||
$f3->clear(self::SESSION_KEY_SSO_CHARACTER_ID);
|
||||
|
||||
$accessData = $this->getCrestAccessData($getParams['code']);
|
||||
|
||||
if(
|
||||
isset($accessData->accessToken) &&
|
||||
isset($accessData->refreshToken)
|
||||
){
|
||||
// login succeeded -> get basic character data for current login
|
||||
$verificationCharacterData = $this->verifyCharacterData($accessData->accessToken);
|
||||
|
||||
if( !is_null($verificationCharacterData)){
|
||||
|
||||
// check if login is restricted to a characterID
|
||||
if(
|
||||
$requiredCharacterId <= 0 ||
|
||||
$verificationCharacterData->CharacterID === $requiredCharacterId
|
||||
){
|
||||
// verification available data. Data is needed for "ownerHash" check
|
||||
|
||||
// get character data from CREST
|
||||
$characterData = $this->getCharacterData($accessData->accessToken);
|
||||
|
||||
if(isset($characterData->character)){
|
||||
// add "ownerHash" and CREST tokens
|
||||
$characterData->character['ownerHash'] = $verificationCharacterData->CharacterOwnerHash;
|
||||
$characterData->character['crestAccessToken'] = $accessData->accessToken;
|
||||
$characterData->character['crestRefreshToken'] = $accessData->refreshToken;
|
||||
|
||||
// add/update static character data
|
||||
$characterModel = $this->updateCharacter($characterData);
|
||||
|
||||
if( !is_null($characterModel) ){
|
||||
// check if character is authorized to log in
|
||||
if($characterModel->isAuthorized()){
|
||||
|
||||
// character is authorized to log in
|
||||
// -> update character log (current location,...)
|
||||
$characterModel = $characterModel->updateLog();
|
||||
|
||||
// check if there is already an active user logged in
|
||||
if($activeCharacter = $this->getCharacter()){
|
||||
// connect character with current user
|
||||
$user = $activeCharacter->getUser();
|
||||
}elseif( is_null( $user = $characterModel->getUser()) ){
|
||||
// no user found (new character) -> create new user and connect to character
|
||||
$user = Model\BasicModel::getNew('UserModel');
|
||||
$user->name = $characterModel->name;
|
||||
$user->save();
|
||||
}
|
||||
|
||||
if( is_null($userCharactersModel = $characterModel->userCharacter) ){
|
||||
$userCharactersModel = Model\BasicModel::getNew('UserCharacterModel');
|
||||
$userCharactersModel->characterId = $characterModel;
|
||||
}
|
||||
|
||||
// user might have changed
|
||||
$userCharactersModel->userId = $user;
|
||||
$userCharactersModel->save();
|
||||
|
||||
// get updated character model
|
||||
$characterModel = $userCharactersModel->getCharacter();
|
||||
|
||||
// login by character
|
||||
$loginCheck = $this->loginByCharacter($characterModel);
|
||||
|
||||
if($loginCheck){
|
||||
// route to "map"
|
||||
$f3->reroute('@map');
|
||||
}else{
|
||||
$f3->set(self::SESSION_KEY_SSO_ERROR, sprintf(self::ERROR_LOGIN_FAILED, $characterModel->name));
|
||||
}
|
||||
}else{
|
||||
// character is not authorized to log in
|
||||
$f3->set(self::SESSION_KEY_SSO_ERROR, sprintf(self::ERROR_CHARACTER_FORBIDDEN, $characterModel->name));
|
||||
}
|
||||
}
|
||||
}
|
||||
}else{
|
||||
// characterID is not allowed to login
|
||||
$f3->set(self::SESSION_KEY_SSO_ERROR, sprintf(self::ERROR_CHARACTER_MISMATCH, $verificationCharacterData->CharacterName));
|
||||
}
|
||||
}
|
||||
}else{
|
||||
// CREST "accessData" missing (e.g. timeout)
|
||||
$f3->set(self::SESSION_KEY_SSO_ERROR, sprintf(self::ERROR_SERVICE_TIMEOUT, self::CREST_TIMEOUT));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if($authFromMapAlias){
|
||||
// on error -> route back to map
|
||||
$f3->reroute('@map');
|
||||
}else{
|
||||
// on error -> route back to login form
|
||||
$f3->reroute('@login');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get a valid "access_token" for oAuth 2.0 verification
|
||||
* -> if $authCode is set -> request NEW "access_token"
|
||||
* -> else check for existing (not expired) "access_token"
|
||||
* -> else try to refresh auth and get fresh "access_token"
|
||||
* @param bool $authCode
|
||||
* @return null|\stdClass
|
||||
*/
|
||||
public function getCrestAccessData($authCode){
|
||||
$accessData = null;
|
||||
|
||||
if( !empty($authCode) ){
|
||||
// Authentication Code is set -> request new "accessToken"
|
||||
$accessData = $this->verifyAuthorizationCode($authCode);
|
||||
}else{
|
||||
// Unable to get Token -> trigger error
|
||||
self::getCrestLogger()->write(sprintf(self::ERROR_ACCESS_TOKEN, $authCode));
|
||||
}
|
||||
|
||||
return $accessData;
|
||||
}
|
||||
|
||||
/**
|
||||
* verify authorization code, and get an "access_token" data
|
||||
* @param $authCode
|
||||
* @return \stdClass
|
||||
*/
|
||||
protected function verifyAuthorizationCode($authCode){
|
||||
$requestParams = [
|
||||
'grant_type' => 'authorization_code',
|
||||
'code' => $authCode
|
||||
];
|
||||
|
||||
return $this->requestAccessData($requestParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* get new "access_token" by an existing "refresh_token"
|
||||
* -> if "access_token" is expired, this function gets a fresh one
|
||||
* @param $refreshToken
|
||||
* @return \stdClass
|
||||
*/
|
||||
public function refreshAccessToken($refreshToken){
|
||||
$requestParams = [
|
||||
'grant_type' => 'refresh_token',
|
||||
'refresh_token' => $refreshToken
|
||||
];
|
||||
|
||||
return $this->requestAccessData($requestParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* request an "access_token" AND "refresh_token" data
|
||||
* -> this can either be done by sending a valid "authorization code"
|
||||
* OR by providing a valid "refresh_token"
|
||||
* @param $requestParams
|
||||
* @return \stdClass
|
||||
*/
|
||||
protected function requestAccessData($requestParams){
|
||||
$verifyAuthCodeUrl = self::getVerifyAuthorizationCodeEndpoint();
|
||||
$verifyAuthCodeUrlParts = parse_url($verifyAuthCodeUrl);
|
||||
|
||||
$accessData = (object) [];
|
||||
$accessData->accessToken = null;
|
||||
$accessData->refreshToken = null;
|
||||
|
||||
if($verifyAuthCodeUrlParts){
|
||||
$contentType = 'application/x-www-form-urlencoded';
|
||||
$requestOptions = [
|
||||
'timeout' => self::CREST_TIMEOUT,
|
||||
'method' => 'POST',
|
||||
'user_agent' => $this->getUserAgent(),
|
||||
'header' => [
|
||||
'Authorization: Basic ' . $this->getAuthorizationHeader(),
|
||||
'Content-Type: ' . $contentType,
|
||||
'Host: ' . $verifyAuthCodeUrlParts['host']
|
||||
]
|
||||
];
|
||||
|
||||
// content (parameters to send with)
|
||||
$requestOptions['content'] = http_build_query($requestParams);
|
||||
|
||||
$apiResponse = Lib\Web::instance()->request($verifyAuthCodeUrl, $requestOptions);
|
||||
|
||||
if($apiResponse['body']){
|
||||
$authCodeRequestData = json_decode($apiResponse['body'], true);
|
||||
|
||||
if( !empty($authCodeRequestData) ){
|
||||
if( isset($authCodeRequestData['access_token']) ){
|
||||
// this token is required for endpoints that require Auth
|
||||
$accessData->accessToken = $authCodeRequestData['access_token'];
|
||||
}
|
||||
|
||||
if(isset($authCodeRequestData['refresh_token'])){
|
||||
// this token is used to refresh/get a new access_token when expires
|
||||
$accessData->refreshToken = $authCodeRequestData['refresh_token'];
|
||||
}
|
||||
}
|
||||
}else{
|
||||
self::getCrestLogger()->write(
|
||||
sprintf(
|
||||
self::ERROR_ACCESS_TOKEN,
|
||||
print_r($requestParams, true)
|
||||
)
|
||||
);
|
||||
}
|
||||
}else{
|
||||
self::getCrestLogger()->write(
|
||||
sprintf(self::ERROR_CCP_SSO_URL, __METHOD__)
|
||||
);
|
||||
}
|
||||
|
||||
return $accessData;
|
||||
}
|
||||
|
||||
/**
|
||||
* verify character data by "access_token"
|
||||
* -> get some basic information (like character id)
|
||||
* -> if more character information is required, use CREST endpoints request instead
|
||||
* @param $accessToken
|
||||
* @return mixed|null
|
||||
*/
|
||||
protected function verifyCharacterData($accessToken){
|
||||
$verifyUserUrl = self::getVerifyUserEndpoint();
|
||||
$verifyUrlParts = parse_url($verifyUserUrl);
|
||||
$characterData = null;
|
||||
|
||||
if($verifyUrlParts){
|
||||
$requestOptions = [
|
||||
'timeout' => self::CREST_TIMEOUT,
|
||||
'method' => 'GET',
|
||||
'user_agent' => $this->getUserAgent(),
|
||||
'header' => [
|
||||
'Authorization: Bearer ' . $accessToken,
|
||||
'Host: ' . $verifyUrlParts['host']
|
||||
]
|
||||
];
|
||||
|
||||
$apiResponse = Lib\Web::instance()->request($verifyUserUrl, $requestOptions);
|
||||
|
||||
if($apiResponse['body']){
|
||||
$characterData = json_decode($apiResponse['body']);
|
||||
}else{
|
||||
self::getCrestLogger()->write(sprintf(self::ERROR_VERIFY_CHARACTER, __METHOD__));
|
||||
}
|
||||
}else{
|
||||
self::getCrestLogger()->write(sprintf(self::ERROR_CCP_SSO_URL, __METHOD__));
|
||||
}
|
||||
|
||||
return $characterData;
|
||||
}
|
||||
|
||||
/**
|
||||
* get all available Endpoints
|
||||
* @param $accessToken
|
||||
* @return mixed|null
|
||||
*/
|
||||
protected function getEndpoints($accessToken){
|
||||
$crestUrl = self::getCrestEndpoint();
|
||||
$contentType = 'application/vnd.ccp.eve.Api-v3+json';
|
||||
$endpoint = $this->getEndpoint($accessToken, $crestUrl, $contentType);
|
||||
|
||||
return $endpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* get a specific endpoint by its $resourceUrl
|
||||
* @param $accessToken
|
||||
* @param $resourceUrl
|
||||
* @param string $contentType
|
||||
* @return mixed|null
|
||||
*/
|
||||
protected function getEndpoint($accessToken, $resourceUrl, $contentType = ''){
|
||||
$resourceUrlParts = parse_url($resourceUrl);
|
||||
$endpoint = null;
|
||||
|
||||
if($resourceUrlParts){
|
||||
$requestOptions = [
|
||||
'timeout' => self::CREST_TIMEOUT,
|
||||
'method' => 'GET',
|
||||
'user_agent' => $this->getUserAgent(),
|
||||
'header' => [
|
||||
'Authorization: Bearer ' . $accessToken,
|
||||
'Host: login.eveonline.com',
|
||||
'Host: ' . $resourceUrlParts['host']
|
||||
]
|
||||
];
|
||||
|
||||
// if specific contentType is required -> add it to request header
|
||||
// CREST versioning can be done by calling different "Accept:" Headers
|
||||
if( !empty($contentType) ){
|
||||
$requestOptions['header'][] = 'Accept: ' . $contentType;
|
||||
}
|
||||
|
||||
$apiResponse = Lib\Web::instance()->request($resourceUrl, $requestOptions);
|
||||
|
||||
if($apiResponse['headers']){
|
||||
// check headers for error
|
||||
$this->checkResponseHeaders($apiResponse['headers'], $requestOptions);
|
||||
|
||||
if($apiResponse['body']){
|
||||
$endpoint = json_decode($apiResponse['body'], true);
|
||||
}else{
|
||||
self::getCrestLogger()->write(sprintf(self::ERROR_GET_ENDPOINT, __METHOD__));
|
||||
}
|
||||
}
|
||||
}else{
|
||||
self::getCrestLogger()->write(sprintf(self::ERROR_CCP_CREST_URL, __METHOD__));
|
||||
}
|
||||
|
||||
return $endpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* recursively walk down the CREST API tree by a given $path array
|
||||
* -> return "leaf" endpoint
|
||||
* @param $accessToken
|
||||
* @param $endpoint
|
||||
* @param array $path
|
||||
* @return null|string
|
||||
*/
|
||||
protected function walkEndpoint($accessToken, $endpoint, $path = []){
|
||||
$targetEndpoint = null;
|
||||
|
||||
if( !empty($path) ){
|
||||
$newNode = array_shift($path);
|
||||
if(isset($endpoint[$newNode])){
|
||||
$currentEndpoint = $endpoint[$newNode];
|
||||
if(isset($currentEndpoint['href'])){
|
||||
$newEndpoint = $this->getEndpoint($accessToken, $currentEndpoint['href']);
|
||||
$targetEndpoint = $this->walkEndpoint($accessToken, $newEndpoint, $path);
|
||||
}else{
|
||||
// leaf found
|
||||
$targetEndpoint = $currentEndpoint;
|
||||
}
|
||||
}else{
|
||||
// endpoint not found
|
||||
self::getCrestLogger()->write(sprintf(self::ERROR_FIND_ENDPOINT, $newNode));
|
||||
}
|
||||
}else{
|
||||
$targetEndpoint = $endpoint;
|
||||
}
|
||||
|
||||
return $targetEndpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* get character data
|
||||
* @param $accessToken
|
||||
* @return array
|
||||
*/
|
||||
protected function getCharacterData($accessToken){
|
||||
$endpoints = $this->getEndpoints($accessToken);
|
||||
$characterData = (object) [];
|
||||
|
||||
$endpoint = $this->walkEndpoint($accessToken, $endpoints, [
|
||||
'decode',
|
||||
'character'
|
||||
]);
|
||||
|
||||
if( !empty($endpoint) ){
|
||||
$characterData->character = (new Mapper\CrestCharacter($endpoint))->getData();
|
||||
if(isset($endpoint['corporation'])){
|
||||
$characterData->corporation = (new Mapper\CrestCorporation($endpoint['corporation']))->getData();
|
||||
}
|
||||
}
|
||||
|
||||
return $characterData;
|
||||
}
|
||||
|
||||
/**
|
||||
* get current character location data (result is cached!)
|
||||
* -> solarSystem data where character is currently active
|
||||
* @param $accessToken
|
||||
* @param int $ttl
|
||||
* @return array
|
||||
*/
|
||||
public function getCharacterLocationData($accessToken, $ttl = 10){
|
||||
$locationData = [];
|
||||
|
||||
// in addition to the cURL caching (based on cache-control headers,
|
||||
// the final location data is cached additionally -> speed up
|
||||
$cacheKey = sprintf(self::CACHE_KEY_LOCATION_DATA, 'TOKEN_' . hash('md5', $accessToken));
|
||||
|
||||
if( !$this->getF3()->exists($cacheKey) ){
|
||||
$endpoints = $this->getEndpoints($accessToken);
|
||||
|
||||
$endpoint = $this->walkEndpoint($accessToken, $endpoints, [
|
||||
'decode',
|
||||
'character',
|
||||
'location'
|
||||
]);
|
||||
|
||||
if( !empty($endpoint) ){
|
||||
if(isset($endpoint['solarSystem'])){
|
||||
$locationData['system'] = (new Mapper\CrestSystem($endpoint['solarSystem']))->getData();
|
||||
}
|
||||
}
|
||||
|
||||
$this->getF3()->set($cacheKey, $locationData, $ttl);
|
||||
}else{
|
||||
$locationData = $this->getF3()->get($cacheKey);
|
||||
}
|
||||
|
||||
return $locationData;
|
||||
}
|
||||
|
||||
/**
|
||||
* update character
|
||||
* @param $characterData
|
||||
* @return \Model\CharacterModel
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function updateCharacter($characterData){
|
||||
|
||||
$characterModel = null;
|
||||
$corporationModel = null;
|
||||
$allianceModel = null;
|
||||
|
||||
if( isset($characterData->corporation) ){
|
||||
/**
|
||||
* @var Model\CorporationModel $corporationModel
|
||||
*/
|
||||
$corporationModel = Model\BasicModel::getNew('CorporationModel');
|
||||
$corporationModel->getById($characterData->corporation['id'], 0);
|
||||
$corporationModel->copyfrom($characterData->corporation);
|
||||
$corporationModel->save();
|
||||
}
|
||||
|
||||
if( isset($characterData->alliance) ){
|
||||
/**
|
||||
* @var Model\AllianceModel $allianceModel
|
||||
*/
|
||||
$allianceModel = Model\BasicModel::getNew('AllianceModel');
|
||||
$allianceModel->getById($characterData->alliance['id'], 0);
|
||||
$allianceModel->copyfrom($characterData->alliance);
|
||||
$allianceModel->save();
|
||||
}
|
||||
|
||||
if( isset($characterData->character) ){
|
||||
/**
|
||||
* @var Model\CharacterModel $characterModel
|
||||
*/
|
||||
$characterModel = Model\BasicModel::getNew('CharacterModel');
|
||||
$characterModel->getById($characterData->character['id'], 0);
|
||||
$characterModel->copyfrom($characterData->character);
|
||||
$characterModel->corporationId = $corporationModel;
|
||||
$characterModel->allianceId = $allianceModel;
|
||||
$characterModel = $characterModel->save();
|
||||
}
|
||||
|
||||
return $characterModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* check response "Header" data for errors
|
||||
* @param $headers
|
||||
* @param string $requestUrl
|
||||
* @param string $contentType
|
||||
*/
|
||||
protected function checkResponseHeaders($headers, $requestUrl = '', $contentType = ''){
|
||||
$headers = (array)$headers;
|
||||
if(preg_grep ('/^X-Deprecated/i', $headers)){
|
||||
self::getCrestLogger()->write(sprintf(self::ERROR_RESOURCE_DEPRECATED, $requestUrl, $contentType));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get "Authorization:" Header data
|
||||
* -> This header is required for any Auth-required endpoints!
|
||||
* @return string
|
||||
*/
|
||||
protected function getAuthorizationHeader(){
|
||||
return base64_encode(
|
||||
Controller\Controller::getEnvironmentData('SSO_CCP_CLIENT_ID') . ':'
|
||||
. Controller\Controller::getEnvironmentData('SSO_CCP_SECRET_KEY')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* get CCP CREST url from configuration file
|
||||
* -> throw error if url is broken/missing
|
||||
* @return string
|
||||
*/
|
||||
static function getCrestEndpoint(){
|
||||
$url = '';
|
||||
if( \Audit::instance()->url(self::getEnvironmentData('CCP_CREST_URL')) ){
|
||||
$url = self::getEnvironmentData('CCP_CREST_URL');
|
||||
}else{
|
||||
$error = sprintf(self::ERROR_CCP_CREST_URL, __METHOD__);
|
||||
self::getCrestLogger()->write($error);
|
||||
\Base::instance()->error(502, $error);
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* get CCP SSO url from configuration file
|
||||
* -> throw error if url is broken/missing
|
||||
* @return string
|
||||
*/
|
||||
static function getSsoUrlRoot(){
|
||||
$url = '';
|
||||
if( \Audit::instance()->url(self::getEnvironmentData('SSO_CCP_URL')) ){
|
||||
$url = self::getEnvironmentData('SSO_CCP_URL');
|
||||
}else{
|
||||
$error = sprintf(self::ERROR_CCP_SSO_URL, __METHOD__);
|
||||
self::getCrestLogger()->write($error);
|
||||
\Base::instance()->error(502, $error);
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
static function getAuthorizationEndpoint(){
|
||||
return self::getSsoUrlRoot() . '/oauth/authorize';
|
||||
}
|
||||
|
||||
static function getVerifyAuthorizationCodeEndpoint(){
|
||||
return self::getSsoUrlRoot() . '/oauth/token';
|
||||
}
|
||||
|
||||
static function getVerifyUserEndpoint(){
|
||||
return self::getSsoUrlRoot() . '/oauth/verify';
|
||||
}
|
||||
|
||||
/**
|
||||
* get logger for CREST logging
|
||||
* @return \Log
|
||||
*/
|
||||
static function getCrestLogger(){
|
||||
return parent::getLogger('crest');
|
||||
}
|
||||
}
|
||||
@@ -1,184 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: exodus4d
|
||||
* Date: 28.03.15
|
||||
* Time: 17:01
|
||||
*/
|
||||
|
||||
namespace Controller;
|
||||
use Model;
|
||||
|
||||
/**
|
||||
* CCP API controller
|
||||
* Class CcpApiController
|
||||
* @package Controller
|
||||
*/
|
||||
class CcpApiController extends Controller{
|
||||
|
||||
/**
|
||||
* get HTTP request options for API (curl) request
|
||||
* @return array
|
||||
*/
|
||||
protected function getRequestOptions(){
|
||||
$requestOptions = [
|
||||
'timeout' => 8,
|
||||
'method' => 'POST',
|
||||
'user_agent' => $this->getUserAgent(),
|
||||
'follow_location' => false // otherwise CURLOPT_FOLLOWLOCATION will fail
|
||||
];
|
||||
|
||||
return $requestOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* request character information from CCP API
|
||||
* @param $keyID
|
||||
* @param $vCode
|
||||
* @return bool|\SimpleXMLElement
|
||||
*/
|
||||
public function requestCharacters($keyID, $vCode){
|
||||
|
||||
$apiPath = $this->getF3()->get('PATHFINDER.API.CCP_XML') . '/account/APIKeyInfo.xml.aspx';
|
||||
|
||||
$xml = false;
|
||||
|
||||
// build request URL
|
||||
$options = $this->getRequestOptions();
|
||||
$options['content'] = http_build_query( [
|
||||
'keyID' => $keyID,
|
||||
'vCode' => $vCode
|
||||
]);
|
||||
|
||||
$apiResponse = \Web::instance()->request($apiPath, $options );
|
||||
|
||||
if($apiResponse['body']){
|
||||
$xml = simplexml_load_string($apiResponse['body']);
|
||||
}
|
||||
|
||||
return $xml;
|
||||
}
|
||||
|
||||
/**
|
||||
* update all character information for a given apiModel
|
||||
* @param $userApiModel
|
||||
* @return int
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function updateCharacters($userApiModel){
|
||||
|
||||
$xml = $this->requestCharacters($userApiModel->keyId, $userApiModel->vCode);
|
||||
|
||||
$characterCount = 0;
|
||||
|
||||
// important -> user API model must be up2date
|
||||
// if not -> matched userCharacter cant be found
|
||||
$userApiModel->getById($userApiModel->id, 0);
|
||||
|
||||
if($xml){
|
||||
// request successful
|
||||
$rowApiData = $xml->result->key->rowset;
|
||||
|
||||
if(
|
||||
is_object($rowApiData) &&
|
||||
$rowApiData->children()
|
||||
){
|
||||
$characterModel = Model\BasicModel::getNew('CharacterModel');
|
||||
$corporationModel = Model\BasicModel::getNew('CorporationModel');
|
||||
$allianceModel = Model\BasicModel::getNew('AllianceModel');
|
||||
|
||||
foreach($rowApiData->children() as $characterApiData){
|
||||
// map attributes to array
|
||||
$attributeData = current( $characterApiData->attributes() );
|
||||
|
||||
$newCharacter = true;
|
||||
|
||||
$characterId = (int)$attributeData['characterID'];
|
||||
$characterModel->getById($characterId, 0);
|
||||
|
||||
$corporationModelTemp = null;
|
||||
$allianceModelTemp = null;
|
||||
|
||||
// check if corporation already exists
|
||||
if($attributeData['corporationID'] > 0){
|
||||
$corporationModel->getById($attributeData['corporationID'], 0);
|
||||
if( $corporationModel->dry() ){
|
||||
$corporationModel->id = $attributeData['corporationID'];
|
||||
$corporationModel->name = $attributeData['corporationName'];
|
||||
$corporationModel->save();
|
||||
}
|
||||
$corporationModelTemp = $corporationModel;
|
||||
}
|
||||
|
||||
// check if alliance already exists
|
||||
if($attributeData['allianceID'] > 0){
|
||||
$allianceModel->getById($attributeData['allianceID'], 0);
|
||||
if( $allianceModel->dry() ){
|
||||
$allianceModel->id = $attributeData['allianceID'];
|
||||
$allianceModel->name = $attributeData['allianceName'];
|
||||
$allianceModel->save();
|
||||
}
|
||||
$allianceModelTemp = $allianceModel;
|
||||
}
|
||||
|
||||
if($userApiModel->userCharacters){
|
||||
$userApiModel->userCharacters->rewind();
|
||||
while($userApiModel->userCharacters->valid()){
|
||||
$tempCharacterModel = $userApiModel->userCharacters->current()->getCharacter();
|
||||
|
||||
// character already exists -> update
|
||||
if($tempCharacterModel->id == $characterId){
|
||||
$characterModel = $tempCharacterModel;
|
||||
|
||||
// unset userCharacter -> all leftover models are no longer part of this API
|
||||
// --> delete leftover models at the end
|
||||
$userApiModel->userCharacters->offsetUnset($userApiModel->userCharacters->key());
|
||||
|
||||
$newCharacter = false;
|
||||
break;
|
||||
}else{
|
||||
$userApiModel->userCharacters->next();
|
||||
}
|
||||
}
|
||||
$userApiModel->userCharacters->rewind();
|
||||
}
|
||||
|
||||
$characterModel->id = $characterId;
|
||||
$characterModel->name = $attributeData['characterName'];
|
||||
$characterModel->corporationId = $corporationModelTemp;
|
||||
$characterModel->allianceId = $allianceModelTemp;
|
||||
$characterModel->factionId = $attributeData['factionID'];
|
||||
$characterModel->factionName = $attributeData['factionName'];
|
||||
$characterModel->save();
|
||||
|
||||
if($newCharacter){
|
||||
// new character for this API
|
||||
$userCharactersModel = Model\BasicModel::getNew('UserCharacterModel', 0);
|
||||
$userCharactersModel->userId = $userApiModel->userId;
|
||||
$userCharactersModel->apiId = $userApiModel;
|
||||
$userCharactersModel->characterId = $characterModel;
|
||||
$userCharactersModel->save();
|
||||
}
|
||||
|
||||
$corporationModel->reset();
|
||||
$allianceModel->reset();
|
||||
$characterModel->reset();
|
||||
|
||||
$characterCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// delete leftover userCharacters from this API
|
||||
if(count($userApiModel->userCharacters) > 0){
|
||||
while($userApiModel->userCharacters->valid()){
|
||||
$userApiModel->userCharacters->current()->erase();
|
||||
$userApiModel->userCharacters->next();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $characterCount;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,500 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Exodus
|
||||
* Date: 23.01.2016
|
||||
* Time: 17:18
|
||||
*
|
||||
* Handles access to EVE-Online "CREST API" and "SSO" auth functions
|
||||
* - Add your API credentials in "environment.ini"
|
||||
* - Check "PATHFINDER.API" in "pathfinder.ini" for correct API URLs
|
||||
* Hint: \Web::instance()->request automatically caches responses by their response "Cache-Control" header!
|
||||
*/
|
||||
|
||||
namespace Controller;
|
||||
|
||||
use Data\Mapper as Mapper;
|
||||
use Model;
|
||||
|
||||
class CcpSsoController extends Controller {
|
||||
|
||||
const SESSION_KEY_ACCESS_TOKEN = 'SESSION.sso.access_token';
|
||||
const SESSION_KEY_REFRESH_TOKEN = 'SESSION.sso.refresh_token';
|
||||
|
||||
const ERROR_CCP_SSO_URL = 'Invalid "PATHFINDER.API.CCP_SSO" url. %s';
|
||||
const ERROR_CCP_CREST_URL = 'Invalid "PATHFINDER.API.CCP_CREST" url. %s';
|
||||
const ERROR_RESOURCE_DEPRECATED = 'Resource: %s has been marked deprecated. %s';
|
||||
const ERROR_ACCESS_TOKEN = 'Unable to get a valid "access_token. %s';
|
||||
const ERROR_VERIFY_CHARACTER = 'Unable to verify character data. %s';
|
||||
const ERROR_GET_ENDPOINTS = 'Unable to get endpoints data. $s';
|
||||
const ERROR_GET_ENDPOINT = 'Unable to get endpoint data. $s';
|
||||
const ERROR_FIND_ENDPOINT = 'Unable to find endpoint: %s';
|
||||
|
||||
/**
|
||||
* "Scopes" that are used by pathfinder
|
||||
* -> Enable scopes: https://developers.eveonline.com
|
||||
* @var array
|
||||
*/
|
||||
private $requestScopes = [
|
||||
'characterLocationRead',
|
||||
'characterNavigationWrite'
|
||||
];
|
||||
|
||||
/**
|
||||
* timeout for API calls
|
||||
* @var int
|
||||
*/
|
||||
private $apiTimeout = 3;
|
||||
|
||||
/**
|
||||
* redirect user to CCP SSO page and request authorization
|
||||
* @param $f3
|
||||
*/
|
||||
public function requestAuthorization($f3){
|
||||
// used for state check between request and callback
|
||||
$state = bin2hex(mcrypt_create_iv(12, MCRYPT_DEV_URANDOM));
|
||||
$f3->set('SESSION.sso.state', $state);
|
||||
|
||||
$urlParams = [
|
||||
'response_type' => 'code',
|
||||
'redirect_uri' => Controller::getEnvironmentData('URL') . $f3->build('/sso/callbackAuthorization'),
|
||||
'client_id' => Controller::getEnvironmentData('SSO_CCP_CLIENT_ID'),
|
||||
'scope' => implode(' ', $this->requestScopes),
|
||||
'state' => $state
|
||||
];
|
||||
|
||||
$ssoAuthUrl = self::getAuthorizationEndpoint() . '?' . http_build_query($urlParams, '', '&', PHP_QUERY_RFC3986 );
|
||||
|
||||
$f3->status(302);
|
||||
$f3->reroute($ssoAuthUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* callback handler for CCP SSO user Auth
|
||||
* -> see requestAuthorization()
|
||||
* @param $f3
|
||||
*/
|
||||
public function callbackAuthorization($f3){
|
||||
$getParams = (array)$f3->get('GET');
|
||||
|
||||
if($f3->exists('SESSION.sso.state')){
|
||||
// check response and validate 'state'
|
||||
if(
|
||||
isset($getParams['code']) &&
|
||||
isset($getParams['state']) &&
|
||||
!empty($getParams['code']) &&
|
||||
!empty($getParams['state']) &&
|
||||
$f3->get('SESSION.sso.state') === $getParams['state']
|
||||
){
|
||||
|
||||
// clear 'state' for new next request
|
||||
$f3->clear('SESSION.sso.state');
|
||||
|
||||
$accessToken = $this->getAccessToken($getParams['code']);
|
||||
if($accessToken){
|
||||
$data = $this->verifyCharacterData($accessToken);
|
||||
|
||||
$characterData = $this->getCharacterData($accessToken);
|
||||
$characterModel = $this->updateCharacter($characterData);
|
||||
|
||||
if( !is_null($characterModel) ){
|
||||
// everything OK -> login succeeded
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// on error -> route back to login form
|
||||
$this->getF3()->reroute('@login');
|
||||
}
|
||||
|
||||
/**
|
||||
* get a valid "access_token" for oAuth 2.0 verification
|
||||
* -> if $authCode is set -> request NEW "access_token"
|
||||
* -> else check for existing (not expired) "access_token"
|
||||
* -> else try to refresh auth and get fresh "access_token"
|
||||
* @param bool $authCode
|
||||
* @return bool|mixed
|
||||
*/
|
||||
private function getAccessToken($authCode = false){
|
||||
$accessToken = false;
|
||||
|
||||
if( !empty($authCode) ){
|
||||
// Authentication Code is set -> request new Access Token -------------------------------------------------
|
||||
|
||||
// clear "old" token (if exist and still valid)
|
||||
$this->getF3()->clear(self::SESSION_KEY_ACCESS_TOKEN);
|
||||
|
||||
$accessToken = $this->verifyAuthorizationCode($authCode);
|
||||
}elseif($this->getF3()->exists(self::SESSION_KEY_ACCESS_TOKEN)){
|
||||
// Access Token exists and not expired --------------------------------------------------------------------
|
||||
$accessToken = $this->getF3()->get(self::SESSION_KEY_ACCESS_TOKEN);
|
||||
}elseif($this->getF3()->exists(self::SESSION_KEY_REFRESH_TOKEN)){
|
||||
// Refresh Token exists -> refresh Access Token -----------------------------------------------------------
|
||||
$accessToken = $this->refreshAccessToken($this->getF3()->get(self::SESSION_KEY_REFRESH_TOKEN));
|
||||
}else{
|
||||
// Unable to get Token -> trigger error -------------------------------------------------------------------
|
||||
$this->getLogger('error')->write(sprintf(self::ERROR_ACCESS_TOKEN, $authCode));
|
||||
}
|
||||
|
||||
return $accessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* verify authorization code, and get an "access_token" data
|
||||
* @param $authCode
|
||||
* @return bool|mixed
|
||||
*/
|
||||
private function verifyAuthorizationCode($authCode){
|
||||
$requestParams = [
|
||||
'grant_type' => 'authorization_code',
|
||||
'code' => $authCode
|
||||
];
|
||||
|
||||
return $this->requestAccessToken($requestParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* get new "access_token" by an existing "refresh_token"
|
||||
* -> if "access_token" is expired, this function gets a fresh one
|
||||
* @param $refreshToken
|
||||
* @return bool|mixed
|
||||
*/
|
||||
private function refreshAccessToken($refreshToken){
|
||||
$requestParams = [
|
||||
'grant_type' => 'refresh_token',
|
||||
'refresh_token' => $refreshToken
|
||||
];
|
||||
|
||||
return $this->requestAccessToken($requestParams);
|
||||
}
|
||||
|
||||
/**
|
||||
* request an "access_token" AND "refresh_token" data
|
||||
* -> this can either be done by sending a valid "authorization code"
|
||||
* OR by providing a valid "refresh_token"
|
||||
* @param $requestParams
|
||||
* @return bool|mixed
|
||||
*/
|
||||
private function requestAccessToken($requestParams){
|
||||
$verifyAuthCodeUrl = self::getVerifyAuthorizationCodeEndpoint();
|
||||
$verifyAuthCodeUrlParts = parse_url($verifyAuthCodeUrl);
|
||||
$accessToken = false;
|
||||
|
||||
if($verifyAuthCodeUrlParts){
|
||||
$contentType = 'application/x-www-form-urlencoded';
|
||||
$requestOptions = [
|
||||
'timeout' => $this->apiTimeout,
|
||||
'method' => 'POST',
|
||||
'user_agent' => $this->getUserAgent(),
|
||||
'header' => [
|
||||
'Authorization: Basic ' . $this->getAuthorizationHeader(),
|
||||
'Content-Type: ' . $contentType,
|
||||
'Host: ' . $verifyAuthCodeUrlParts['host']
|
||||
]
|
||||
];
|
||||
|
||||
// content (parameters to send with)
|
||||
$requestOptions['content'] = http_build_query($requestParams);
|
||||
|
||||
$apiResponse = \Web::instance()->request($verifyAuthCodeUrl, $requestOptions);
|
||||
|
||||
if($apiResponse['body']){
|
||||
$authCodeRequestData = json_decode($apiResponse['body']);
|
||||
|
||||
if(property_exists($authCodeRequestData, 'refresh_token')){
|
||||
// this token is used to refresh/get a new access_token when expires
|
||||
$this->getF3()->set(self::SESSION_KEY_REFRESH_TOKEN, $authCodeRequestData->refresh_token);
|
||||
}
|
||||
|
||||
if(property_exists($authCodeRequestData, 'access_token')){
|
||||
// this token is required for endpoints that require Auth
|
||||
$accessToken = $this->getF3()->set(self::SESSION_KEY_ACCESS_TOKEN, $authCodeRequestData->access_token);
|
||||
}
|
||||
}else{
|
||||
$this->getLogger('error')->write(sprintf(self::ERROR_ACCESS_TOKEN, print_r($requestParams, true)));
|
||||
}
|
||||
}else{
|
||||
$this->getLogger('error')->write(sprintf(self::ERROR_CCP_SSO_URL, __METHOD__));
|
||||
}
|
||||
|
||||
return $accessToken;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* verify character data by "access_token"
|
||||
* -> get some basic information (like character id)
|
||||
* -> if more character information is required, use CREST endpoints request instead
|
||||
* @param $accessToken
|
||||
* @return bool|mixed
|
||||
*/
|
||||
private function verifyCharacterData($accessToken){
|
||||
$verifyUserUrl = self::getVerifyUserEndpoint();
|
||||
$verifyUrlParts = parse_url($verifyUserUrl);
|
||||
$characterData = false;
|
||||
|
||||
if($verifyUrlParts){
|
||||
$requestOptions = [
|
||||
'timeout' => $this->apiTimeout,
|
||||
'method' => 'GET',
|
||||
'user_agent' => $this->getUserAgent(),
|
||||
'header' => [
|
||||
'Authorization: Bearer ' . $accessToken,
|
||||
'Host: ' . $verifyUrlParts['host']
|
||||
]
|
||||
];
|
||||
|
||||
$apiResponse = \Web::instance()->request($verifyUserUrl, $requestOptions);
|
||||
|
||||
if($apiResponse['body']){
|
||||
$characterData = json_decode($apiResponse['body']);
|
||||
}else{
|
||||
$this->getLogger('error')->write(sprintf(self::ERROR_VERIFY_CHARACTER, __METHOD__));
|
||||
}
|
||||
}else{
|
||||
$this->getLogger('error')->write(sprintf(self::ERROR_CCP_SSO_URL, __METHOD__));
|
||||
}
|
||||
|
||||
return $characterData;
|
||||
}
|
||||
|
||||
/**
|
||||
* get all available Endpoints
|
||||
* @param $accessToken
|
||||
* @return bool|mixed
|
||||
*/
|
||||
private function getEndpoints($accessToken){
|
||||
$crestUrl = self::getCrestEndpoint();
|
||||
$endpointsData = false;
|
||||
$crestUrlParts = parse_url($crestUrl);
|
||||
|
||||
if($crestUrlParts){
|
||||
// represents API version
|
||||
$contentType = 'application/vnd.ccp.eve.Api-v3+json';
|
||||
$requestOptions = [
|
||||
'timeout' => $this->apiTimeout,
|
||||
'method' => 'GET',
|
||||
'user_agent' => $this->getUserAgent(),
|
||||
'header' => [
|
||||
'Authorization: Bearer ' . $accessToken,
|
||||
'Accept: ' . $contentType,
|
||||
'Host: ' . $crestUrlParts['host']
|
||||
]
|
||||
];
|
||||
|
||||
$apiResponse = \Web::instance()->request($crestUrl, $requestOptions);
|
||||
|
||||
if($apiResponse['headers']){
|
||||
// check headers for error
|
||||
$this->checkResponseHeaders($apiResponse['headers'], $crestUrl, $contentType);
|
||||
|
||||
if($apiResponse['body']){
|
||||
$endpointsData = json_decode($apiResponse['body'], true);
|
||||
}else{
|
||||
$this->getLogger('error')->write(sprintf(self::ERROR_GET_ENDPOINTS, __METHOD__));
|
||||
}
|
||||
}
|
||||
}else{
|
||||
$this->getLogger('error')->write(sprintf(self::ERROR_CCP_CREST_URL, __METHOD__));
|
||||
}
|
||||
|
||||
return $endpointsData;
|
||||
}
|
||||
|
||||
private function walkEndpoint($accessToken, $endpoint, $path = []){
|
||||
$targetEndpoint = null;
|
||||
|
||||
|
||||
if( !empty($path) ){
|
||||
$newNode = array_shift($path);
|
||||
|
||||
if(isset($endpoint[$newNode])){
|
||||
$currentEndpoint = $endpoint[$newNode];
|
||||
if(isset($currentEndpoint['href'])){
|
||||
$newEndpoint = $this->getEndpoint($accessToken, $currentEndpoint['href']);
|
||||
$targetEndpoint = $this->walkEndpoint($accessToken, $newEndpoint, $path);
|
||||
|
||||
}else{
|
||||
// TODO leaf
|
||||
$targetEndpoint = ' target:) ';
|
||||
}
|
||||
}else{
|
||||
// endpoint not found
|
||||
$this->getLogger('error')->write(sprintf(self::ERROR_FIND_ENDPOINT, $newNode));
|
||||
}
|
||||
}else{
|
||||
$targetEndpoint = $endpoint;
|
||||
}
|
||||
|
||||
|
||||
|
||||
return $targetEndpoint;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get a specific endpoint by its $resourceUrl
|
||||
* @param $accessToken
|
||||
* @param $resourceUrl
|
||||
* @return mixed|null
|
||||
*/
|
||||
private function getEndpoint($accessToken, $resourceUrl){
|
||||
$resourceUrlParts = parse_url($resourceUrl);
|
||||
$endpoint = null;
|
||||
|
||||
if($resourceUrlParts){
|
||||
$requestOptions = [
|
||||
'timeout' => $this->apiTimeout,
|
||||
'method' => 'GET',
|
||||
'user_agent' => $this->getUserAgent(),
|
||||
'header' => [
|
||||
'Authorization: Bearer ' . $accessToken,
|
||||
'Host: login.eveonline.com',
|
||||
'Host: ' . $resourceUrlParts['host']
|
||||
]
|
||||
];
|
||||
|
||||
$apiResponse = \Web::instance()->request($resourceUrl, $requestOptions);
|
||||
|
||||
if($apiResponse['headers']){
|
||||
// check headers for error
|
||||
$this->checkResponseHeaders($apiResponse['headers'], $requestOptions);
|
||||
|
||||
if($apiResponse['body']){
|
||||
$endpoint = json_decode($apiResponse['body'], true);
|
||||
}else{
|
||||
$this->getLogger('error')->write(sprintf(self::ERROR_GET_ENDPOINT, __METHOD__));
|
||||
}
|
||||
}
|
||||
}else{
|
||||
$this->getLogger('error')->write(sprintf(self::ERROR_CCP_CREST_URL, __METHOD__));
|
||||
}
|
||||
|
||||
return $endpoint;
|
||||
}
|
||||
|
||||
/**
|
||||
* get character data
|
||||
* @param $accessToken
|
||||
* @return array
|
||||
*/
|
||||
private function getCharacterData($accessToken){
|
||||
$endpoints = $this->getEndpoints($accessToken);
|
||||
$characterData = [];
|
||||
|
||||
$endpoint = $this->walkEndpoint($accessToken, $endpoints, [
|
||||
'decode',
|
||||
'character'
|
||||
]);
|
||||
|
||||
if( !empty($endpoint) ){
|
||||
$characterData['character'] = (new Mapper\CrestCharacter($endpoint))->getData();
|
||||
|
||||
if(isset($endpoint['corporation'])){
|
||||
$characterData['corporation'] = (new Mapper\CrestCorporation($endpoint['corporation']))->getData();
|
||||
}
|
||||
}
|
||||
|
||||
return $characterData;
|
||||
}
|
||||
|
||||
/*
|
||||
private function getCharacterLocation($accessToken){
|
||||
$endpoints = $this->getEndpoints($accessToken);
|
||||
$endpoint = $this->walkEndpoint($accessToken, $endpoints, [
|
||||
'decode',
|
||||
'character',
|
||||
'location'
|
||||
]);
|
||||
|
||||
var_dump($endpoint);
|
||||
|
||||
die(' END getCharacterLocation() ');
|
||||
|
||||
|
||||
$characterData = [];
|
||||
return $characterData;
|
||||
} */
|
||||
|
||||
/**
|
||||
* update character
|
||||
* @param $characterData
|
||||
* @return \Model\CharacterModel
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function updateCharacter($characterData){
|
||||
|
||||
$characterModel = null;
|
||||
$corporationModel = null;
|
||||
$allianceModel = null;
|
||||
|
||||
if( !empty($characterData['corporation']) ){
|
||||
$corporationModel = Model\BasicModel::getNew('CorporationModel');
|
||||
$corporationModel->getById($characterData['corporation']['id'], 0);
|
||||
$corporationModel->copyfrom($characterData['corporation']);
|
||||
$corporationModel->save();
|
||||
}
|
||||
|
||||
if( !empty($characterData['alliance']) ){
|
||||
$allianceModel = Model\BasicModel::getNew('AllianceModel');
|
||||
$allianceModel->getById($characterData['alliance']['id'], 0);
|
||||
$allianceModel->copyfrom($characterData['alliance']);
|
||||
$allianceModel->save();
|
||||
}
|
||||
|
||||
if( !empty($characterData['character']) ){
|
||||
$characterModel = Model\BasicModel::getNew('CharacterModel');
|
||||
$characterModel->getById($characterData['character']['id'], 0);
|
||||
$characterModel->copyfrom($characterData['character']);
|
||||
$characterModel->corporationId = $corporationModel;
|
||||
$characterModel->allianceId = $allianceModel;
|
||||
$characterModel->save();
|
||||
}
|
||||
|
||||
return $characterModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* check response "Header" data for errors
|
||||
* @param $headers
|
||||
* @param string $requestUrl
|
||||
* @param string $contentType
|
||||
*/
|
||||
private function checkResponseHeaders($headers, $requestUrl = '', $contentType = ''){
|
||||
$headers = (array)$headers;
|
||||
if(preg_grep ('/^X-Deprecated/i', $headers)){
|
||||
$this->getLogger('error')->write(sprintf(self::ERROR_RESOURCE_DEPRECATED, $requestUrl, $contentType));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get "Authorization:" Header data
|
||||
* -> This header is required for any Auth-required endpoints!
|
||||
* @return string
|
||||
*/
|
||||
private function getAuthorizationHeader(){
|
||||
return base64_encode(
|
||||
Controller::getEnvironmentData('SSO_CCP_CLIENT_ID') . ':'
|
||||
. Controller::getEnvironmentData('SSO_CCP_SECRET_KEY')
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
static function getAuthorizationEndpoint(){
|
||||
return \Base::instance()->get('PATHFINDER.API.CCP_SSO') . '/oauth/authorize';
|
||||
}
|
||||
|
||||
static function getVerifyAuthorizationCodeEndpoint(){
|
||||
return \Base::instance()->get('PATHFINDER.API.CCP_SSO') . '/oauth/token';
|
||||
}
|
||||
|
||||
static function getVerifyUserEndpoint(){
|
||||
return \Base::instance()->get('PATHFINDER.API.CCP_SSO') . '/oauth/verify';
|
||||
}
|
||||
|
||||
static function getCrestEndpoint(){
|
||||
return \Base::instance()->get('PATHFINDER.API.CCP_CREST');
|
||||
}
|
||||
}
|
||||
@@ -7,50 +7,62 @@
|
||||
*/
|
||||
|
||||
namespace Controller;
|
||||
use Controller\Api as Api;
|
||||
use Model;
|
||||
use DB;
|
||||
|
||||
class Controller {
|
||||
|
||||
/**
|
||||
* @var \Base
|
||||
*/
|
||||
protected $f3;
|
||||
private $template;
|
||||
|
||||
/**
|
||||
* @param mixed $template
|
||||
* @var string template for render
|
||||
*/
|
||||
public function setTemplate($template){
|
||||
protected $template;
|
||||
|
||||
/**
|
||||
* @param string $template
|
||||
*/
|
||||
protected function setTemplate($template){
|
||||
$this->template = $template;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* @return string
|
||||
*/
|
||||
public function getTemplate(){
|
||||
protected function getTemplate(){
|
||||
return $this->template;
|
||||
}
|
||||
|
||||
/**
|
||||
* set global f3 instance
|
||||
* @param null $f3
|
||||
* @return null|static
|
||||
* set $f3 base object
|
||||
* @param \Base $f3
|
||||
*/
|
||||
protected function getF3($f3 = null){
|
||||
if(is_object($f3)){
|
||||
$this->f3 = $f3;
|
||||
}else{
|
||||
$this->f3 = \Base::instance();
|
||||
}
|
||||
protected function setF3(\Base $f3){
|
||||
$this->f3 = $f3;
|
||||
}
|
||||
|
||||
/**
|
||||
* get $f3 base object
|
||||
* @return \Base
|
||||
*/
|
||||
protected function getF3(){
|
||||
if( !($this->f3 instanceof \Base) ){
|
||||
$this->setF3( \Base::instance() );
|
||||
}
|
||||
return $this->f3;
|
||||
}
|
||||
|
||||
/**
|
||||
* event handler for all "views"
|
||||
* some global template variables are set in here
|
||||
* @param $f3
|
||||
* @param \Base $f3
|
||||
*/
|
||||
function beforeroute($f3) {
|
||||
$this->getF3($f3);
|
||||
function beforeroute(\Base $f3) {
|
||||
$this->setF3($f3);
|
||||
|
||||
// initiate DB connection
|
||||
DB\Database::instance('PF');
|
||||
@@ -73,8 +85,9 @@ class Controller {
|
||||
/**
|
||||
* event handler after routing
|
||||
* -> render view
|
||||
* @param \Base $f3
|
||||
*/
|
||||
public function afterroute($f3){
|
||||
public function afterroute(\Base $f3){
|
||||
if($this->getTemplate()){
|
||||
// Ajax calls don´t need a page render..
|
||||
// this happens on client side
|
||||
@@ -85,7 +98,7 @@ class Controller {
|
||||
/**
|
||||
* set change the DB connection
|
||||
* @param string $database
|
||||
* @return mixed|void
|
||||
* @return DB\SQL
|
||||
*/
|
||||
protected function getDB($database = 'PF'){
|
||||
return DB\Database::instance()->getDB($database);
|
||||
@@ -96,49 +109,47 @@ class Controller {
|
||||
*/
|
||||
protected function initSession(){
|
||||
// init DB Session (not file based)
|
||||
if( $this->getDB('PF') instanceof \DB\SQL){
|
||||
new \DB\SQL\Session($this->getDB('PF'));
|
||||
if( $this->getDB('PF') instanceof DB\SQL){
|
||||
new DB\SQL\Session($this->getDB('PF'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get current user model
|
||||
* get current character model
|
||||
* @param int $ttl
|
||||
* @return bool|null
|
||||
* @return Model\CharacterModel|null
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function _getUser($ttl = 5){
|
||||
$user = false;
|
||||
public function getCharacter($ttl = 0){
|
||||
$character = null;
|
||||
|
||||
if( $this->f3->exists('SESSION.user.id') ){
|
||||
$userId = (int)$this->f3->get('SESSION.user.id');
|
||||
if( $this->getF3()->exists(Api\User::SESSION_KEY_CHARACTER_ID) ){
|
||||
$characterId = (int)$this->getF3()->get(Api\User::SESSION_KEY_CHARACTER_ID);
|
||||
if($characterId){
|
||||
/**
|
||||
* @var $characterModel \Model\CharacterModel
|
||||
*/
|
||||
$characterModel = Model\BasicModel::getNew('CharacterModel');
|
||||
$characterModel->getById($characterId, $ttl);
|
||||
|
||||
if($userId > 0){
|
||||
$userModel = Model\BasicModel::getNew('UserModel', $ttl);
|
||||
$userModel->getById($userId, $ttl);
|
||||
|
||||
if( !$userModel->dry() ){
|
||||
$user = $userModel;
|
||||
if( !$characterModel->dry() ){
|
||||
$character = &$characterModel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $user;
|
||||
return $character;
|
||||
}
|
||||
|
||||
/**
|
||||
* log the current user out
|
||||
* @param $f3
|
||||
* log out current user
|
||||
* @param \Base $f3
|
||||
*/
|
||||
public function logOut($f3){
|
||||
|
||||
public function logOut(\Base $f3){
|
||||
// destroy session
|
||||
$f3->clear('SESSION');
|
||||
|
||||
if( !$f3->get('AJAX') ){
|
||||
// redirect to landing page
|
||||
$f3->reroute('@login');
|
||||
}else{
|
||||
if( $f3->get('AJAX') ){
|
||||
$params = $f3->get('POST');
|
||||
$return = (object) [];
|
||||
if(
|
||||
@@ -148,55 +159,29 @@ class Controller {
|
||||
$return->reroute = rtrim(self::getEnvironmentData('URL'), '/') . $f3->alias('login');
|
||||
}else{
|
||||
// no reroute -> errors can be shown
|
||||
$return->error[] = $this->getUserLoggedOffError();
|
||||
$return->error[] = $this->getLogoutError();
|
||||
}
|
||||
|
||||
echo json_encode($return);
|
||||
die();
|
||||
}else{
|
||||
// redirect to landing page
|
||||
$f3->reroute('@login');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* verifies weather a given username and password is valid
|
||||
* @param $userName
|
||||
* @param $password
|
||||
* @return Model\UserModel|null
|
||||
*/
|
||||
protected function _verifyUser($userName, $password) {
|
||||
|
||||
$validUser = null;
|
||||
|
||||
$user = Model\BasicModel::getNew('UserModel', 0);
|
||||
|
||||
$user->getByName($userName);
|
||||
|
||||
// check userName is valid
|
||||
if( !$user->dry() ){
|
||||
// check if password is valid
|
||||
$isValid = $user->verify($password);
|
||||
|
||||
if($isValid === true){
|
||||
$validUser = $user;
|
||||
}
|
||||
}
|
||||
|
||||
return $validUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* check weather the page is IGB trusted or not
|
||||
* @return mixed
|
||||
* @return boolean
|
||||
*/
|
||||
static function isIGBTrusted(){
|
||||
|
||||
$igbHeaderData = self::getIGBHeaderData();
|
||||
|
||||
return $igbHeaderData->trusted;
|
||||
}
|
||||
|
||||
/**
|
||||
* get all eve IGB specific header data
|
||||
* @return object
|
||||
* @return \stdClass
|
||||
*/
|
||||
static function getIGBHeaderData(){
|
||||
$data = (object) [];
|
||||
@@ -229,7 +214,6 @@ class Controller {
|
||||
/**
|
||||
* Helper function to return all headers because
|
||||
* getallheaders() is not available under nginx
|
||||
*
|
||||
* @return array (string $key -> string $value)
|
||||
*/
|
||||
static function getRequestHeaders(){
|
||||
@@ -261,7 +245,7 @@ class Controller {
|
||||
/**
|
||||
* get some server information
|
||||
* @param int $ttl cache time (default: 1h)
|
||||
* @return object
|
||||
* @return \stdClass
|
||||
*/
|
||||
static function getServerData($ttl = 3600){
|
||||
$f3 = \Base::instance();
|
||||
@@ -308,25 +292,21 @@ class Controller {
|
||||
*/
|
||||
static function isIGB(){
|
||||
$isIGB = false;
|
||||
|
||||
$igbHeaderData = self::getIGBHeaderData();
|
||||
|
||||
if(count($igbHeaderData->values) > 0){
|
||||
$isIGB = true;
|
||||
}
|
||||
|
||||
return $isIGB;
|
||||
}
|
||||
|
||||
/**
|
||||
* get error object is a user is not found/logged of
|
||||
* @return object
|
||||
* @return \stdClass
|
||||
*/
|
||||
protected function getUserLoggedOffError(){
|
||||
protected function getLogoutError(){
|
||||
$userError = (object) [];
|
||||
$userError->type = 'error';
|
||||
$userError->message = 'User not found';
|
||||
|
||||
return $userError;
|
||||
}
|
||||
|
||||
@@ -341,8 +321,8 @@ class Controller {
|
||||
|
||||
/**
|
||||
* get a log controller e.g. "debug"
|
||||
* @param $loggerType
|
||||
* @return mixed
|
||||
* @param string $loggerType
|
||||
* @return \Log
|
||||
*/
|
||||
static function getLogger($loggerType){
|
||||
return LogController::getLogger($loggerType);
|
||||
@@ -351,7 +331,7 @@ class Controller {
|
||||
/**
|
||||
* removes illegal characters from a Hive-key that are not allowed
|
||||
* @param $key
|
||||
* @return mixed
|
||||
* @return string
|
||||
*/
|
||||
static function formatHiveKey($key){
|
||||
$illegalCharacters = ['-', ' '];
|
||||
@@ -360,8 +340,8 @@ class Controller {
|
||||
|
||||
/**
|
||||
* get environment specific configuration data
|
||||
* @param $key
|
||||
* @return mixed|null
|
||||
* @param string $key
|
||||
* @return string|null
|
||||
*/
|
||||
static function getEnvironmentData($key){
|
||||
$f3 = \Base::instance();
|
||||
@@ -378,7 +358,7 @@ class Controller {
|
||||
/**
|
||||
* get current server environment status
|
||||
* -> "DEVELOP" or "PRODUCTION"
|
||||
* @return mixed
|
||||
* @return string
|
||||
*/
|
||||
static function getEnvironment(){
|
||||
$f3 = \Base::instance();
|
||||
@@ -396,7 +376,7 @@ class Controller {
|
||||
/**
|
||||
* get required MySQL variable value
|
||||
* @param $key
|
||||
* @return mixed|null
|
||||
* @return string|null
|
||||
*/
|
||||
static function getRequiredMySqlVariables($key){
|
||||
$f3 = \Base::instance();
|
||||
@@ -413,7 +393,7 @@ class Controller {
|
||||
* get a program URL by alias
|
||||
* -> if no $alias given -> get "default" route (index.php)
|
||||
* @param null $alias
|
||||
* @return bool
|
||||
* @return bool|string
|
||||
*/
|
||||
protected function getRouteUrl($alias = null){
|
||||
$url = false;
|
||||
@@ -452,9 +432,9 @@ class Controller {
|
||||
* onError() callback function
|
||||
* -> on AJAX request -> return JSON with error information
|
||||
* -> on HTTP request -> render error page
|
||||
* @param $f3
|
||||
* @param \Base $f3
|
||||
*/
|
||||
public function showError($f3){
|
||||
public function showError(\Base $f3){
|
||||
// set HTTP status
|
||||
$errorCode = $f3->get('ERROR.code');
|
||||
if(!empty($errorCode)){
|
||||
@@ -510,8 +490,10 @@ class Controller {
|
||||
/**
|
||||
* Callback for framework "unload"
|
||||
* check -> config.ini
|
||||
* @param \Base $f3
|
||||
* @return bool
|
||||
*/
|
||||
public function unload($f3){
|
||||
public function unload(\Base $f3){
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,8 +8,11 @@
|
||||
|
||||
namespace Controller;
|
||||
|
||||
class MapController extends \Controller\AccessController {
|
||||
class MapController extends AccessController {
|
||||
|
||||
/**
|
||||
* @param \Base $f3
|
||||
*/
|
||||
public function init($f3) {
|
||||
|
||||
// page title
|
||||
|
||||
@@ -30,16 +30,14 @@ class Setup extends Controller {
|
||||
'Model\SystemStatusModel',
|
||||
'Model\SystemNeighbourModel',
|
||||
'Model\WormholeModel',
|
||||
'Model\RegistrationKeyModel',
|
||||
|
||||
'Model\CharacterStatusModel',
|
||||
'Model\ConnectionScopeModel',
|
||||
|
||||
'Model\UserMapModel',
|
||||
'Model\CharacterMapModel',
|
||||
'Model\AllianceMapModel',
|
||||
'Model\CorporationMapModel',
|
||||
|
||||
'Model\UserApiModel',
|
||||
'Model\UserCharacterModel',
|
||||
'Model\CharacterModel',
|
||||
'Model\CharacterLogModel',
|
||||
@@ -76,9 +74,9 @@ class Setup extends Controller {
|
||||
/**
|
||||
* event handler for all "views"
|
||||
* some global template variables are set in here
|
||||
* @param $f3
|
||||
* @param \Base $f3
|
||||
*/
|
||||
function beforeroute($f3) {
|
||||
function beforeroute(\Base $f3) {
|
||||
// page title
|
||||
$f3->set('pageTitle', 'Setup');
|
||||
|
||||
@@ -92,7 +90,7 @@ class Setup extends Controller {
|
||||
$f3->set('pathJs', 'public/js/' . $f3->get('PATHFINDER.VERSION') );
|
||||
}
|
||||
|
||||
public function afterroute($f3) {
|
||||
public function afterroute(\Base $f3) {
|
||||
// js view (file)
|
||||
$f3->set('jsView', 'setup');
|
||||
|
||||
@@ -103,7 +101,7 @@ class Setup extends Controller {
|
||||
/**
|
||||
* main setup route handler
|
||||
* works as dispatcher for setup functions
|
||||
* @param $f3
|
||||
* @param \Base $f3
|
||||
*/
|
||||
public function init($f3){
|
||||
$params = $f3->get('GET');
|
||||
@@ -141,7 +139,7 @@ class Setup extends Controller {
|
||||
|
||||
/**
|
||||
* get server information
|
||||
* @param $f3
|
||||
* @param \Base $f3
|
||||
* @return array
|
||||
*/
|
||||
protected function getServerInformation($f3){
|
||||
@@ -178,7 +176,7 @@ class Setup extends Controller {
|
||||
/**
|
||||
* check all required backend requirements
|
||||
* (Fat Free Framework)
|
||||
* @param $f3
|
||||
* @param \Base $f3
|
||||
* @return array
|
||||
*/
|
||||
protected function checkRequirements($f3){
|
||||
@@ -288,7 +286,7 @@ class Setup extends Controller {
|
||||
|
||||
/**
|
||||
* get database connection information
|
||||
* @param $f3
|
||||
* @param \Base $f3
|
||||
* @param bool|false $exec
|
||||
* @return array
|
||||
*/
|
||||
@@ -413,6 +411,7 @@ class Setup extends Controller {
|
||||
$changedType = false;
|
||||
$changedUnique = false;
|
||||
$changedIndex = false;
|
||||
$addConstraints = [];
|
||||
|
||||
// set (new) column information -------------------------------------------------------
|
||||
$requiredTables[$requiredTableName]['fieldConf'][$columnName]['exists'] = true;
|
||||
@@ -427,17 +426,22 @@ class Setup extends Controller {
|
||||
$constraint = $col->newConstraint($constraintData);
|
||||
|
||||
$foreignKeyExists = $col->constraintExists($constraint);
|
||||
|
||||
// constraint information -> show in template
|
||||
$requiredTables[$requiredTableName]['foreignKeys'][] = [
|
||||
'exists' => $foreignKeyExists,
|
||||
'keyName' => $constraint->getConstraintName()
|
||||
];
|
||||
|
||||
$col->addConstraint($constraint);
|
||||
|
||||
if(!$foreignKeyExists){
|
||||
if($foreignKeyExists){
|
||||
// drop constraint and re-add again at the and, in case something has changed
|
||||
$col->dropConstraint($constraint);
|
||||
}else{
|
||||
$tableStatusCheckCount++;
|
||||
$foreignKeyStatusCheck = false;
|
||||
}
|
||||
|
||||
$addConstraints[] = $constraint;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -452,11 +456,21 @@ class Setup extends Controller {
|
||||
$tableStatusCheckCount++;
|
||||
}
|
||||
|
||||
// check if column unique changed -----------------------------------------------------
|
||||
// check if column index changed ------------------------------------------------------
|
||||
$indexUpdate = false;
|
||||
$indexKey = (bool)$hasIndex;
|
||||
$indexUnique = (bool)$hasUnique;
|
||||
|
||||
if($currentColIndex != $fieldConf['index']){
|
||||
$changedIndex = true;
|
||||
$columnStatusCheck = false;
|
||||
$tableStatusCheckCount++;
|
||||
|
||||
$indexUpdate = true;
|
||||
$indexKey = (bool) $fieldConf['index'];
|
||||
}
|
||||
|
||||
// check if column unique changed -----------------------------------------------------
|
||||
if($currentColIndexData['unique'] != $fieldConf['unique']){
|
||||
$changedUnique = true;
|
||||
$columnStatusCheck = false;
|
||||
@@ -466,15 +480,6 @@ class Setup extends Controller {
|
||||
$indexUnique =(bool)$fieldConf['unique'];
|
||||
}
|
||||
|
||||
// check if column index changed ------------------------------------------------------
|
||||
if($currentColIndex != $fieldConf['index']){
|
||||
$changedIndex = true;
|
||||
$columnStatusCheck = false;
|
||||
$tableStatusCheckCount++;
|
||||
|
||||
$indexUpdate = true;
|
||||
$indexKey = (bool) $fieldConf['index'];
|
||||
}
|
||||
// build table with changed columns ---------------------------------------------------
|
||||
if(!$columnStatusCheck || !$foreignKeyStatusCheck){
|
||||
|
||||
@@ -495,6 +500,12 @@ class Setup extends Controller {
|
||||
$tableModifier->updateColumn($columnName, $col);
|
||||
}
|
||||
|
||||
// (re-)add constraints !after! index update is done
|
||||
// otherwise index update will fail if there are existing constraints
|
||||
foreach($addConstraints as $constraint){
|
||||
$col->addConstraint($constraint);
|
||||
}
|
||||
|
||||
$buildStatus = $tableModifier->build($exec);
|
||||
|
||||
if(
|
||||
@@ -559,7 +570,7 @@ class Setup extends Controller {
|
||||
}
|
||||
|
||||
/** check MySQL params
|
||||
* @param $f3
|
||||
* @param \Base $f3
|
||||
* @param $db
|
||||
* @return array
|
||||
*/
|
||||
|
||||
@@ -47,43 +47,48 @@ class AbstractIterator extends \RecursiveArrayIterator {
|
||||
*/
|
||||
static function recursiveIterator($iterator){
|
||||
|
||||
$keyWhitelist = array_keys(static::$map);
|
||||
|
||||
while($iterator->valid()){
|
||||
|
||||
if(array_key_exists($iterator->key(), static::$map)){
|
||||
if( isset(static::$map[$iterator->key()]) ){
|
||||
$mapValue = static::$map[$iterator->key()];
|
||||
|
||||
// check for mapping key
|
||||
if($iterator->hasChildren()){
|
||||
|
||||
// recursive call for child elements
|
||||
$iterator->offsetSet($iterator->key(), forward_static_call(array('self', __METHOD__), $iterator->getChildren())->getArrayCopy());
|
||||
$iterator->next();
|
||||
}elseif(is_array(static::$map[$iterator->key()])){
|
||||
}elseif(is_array($mapValue)){
|
||||
// a -> array mapping
|
||||
$parentKey = array_keys(static::$map[$iterator->key()])[0];
|
||||
$entryKey = array_values(static::$map[$iterator->key()])[0];
|
||||
$parentKey = array_keys($mapValue)[0];
|
||||
$entryKey = array_values($mapValue)[0];
|
||||
|
||||
// check if key already exists
|
||||
if($iterator->offsetExists($parentKey)){
|
||||
$currentValue = $iterator->offsetGet($parentKey);
|
||||
// add new array entry
|
||||
$currentValue[$entryKey] = $iterator->current();
|
||||
|
||||
$iterator->offsetSet($parentKey, $currentValue);
|
||||
}else{
|
||||
$iterator->offsetSet($parentKey, [$entryKey => $iterator->current()]);
|
||||
$keyWhitelist[] = $parentKey;
|
||||
}
|
||||
|
||||
|
||||
}elseif(is_object(static::$map[$iterator->key()])){
|
||||
$iterator->offsetUnset($iterator->key());
|
||||
}elseif(is_object($mapValue)){
|
||||
// a -> a (format by function)
|
||||
$formatFunction = static::$map[$iterator->key()];
|
||||
$formatFunction = $mapValue;
|
||||
$iterator->offsetSet($iterator->key(), call_user_func($formatFunction, $iterator));
|
||||
|
||||
// just value change no key change
|
||||
$iterator->next();
|
||||
}elseif(static::$map[$iterator->key()] !== $iterator->key()){
|
||||
}elseif($mapValue !== $iterator->key()){
|
||||
// a -> b mapping (key changed)
|
||||
$iterator->offsetSet(static::$map[$iterator->key()], $iterator->current());
|
||||
$iterator->offsetSet($mapValue, $iterator->current());
|
||||
$iterator->offsetUnset($iterator->key());
|
||||
$keyWhitelist[] = $mapValue;
|
||||
}else{
|
||||
// a -> a (no changes)
|
||||
$iterator->next();
|
||||
@@ -91,13 +96,13 @@ class AbstractIterator extends \RecursiveArrayIterator {
|
||||
|
||||
}elseif(
|
||||
static::$removeUnmapped &&
|
||||
!in_array($iterator->key(), static::$map)
|
||||
|
||||
!in_array($iterator->key(), $keyWhitelist)
|
||||
){
|
||||
$iterator->offsetUnset($iterator->key());
|
||||
}else{
|
||||
$iterator->next();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $iterator;
|
||||
|
||||
@@ -166,7 +166,7 @@ class CcpSystemsMapper extends AbstractIterator {
|
||||
|
||||
// just value change no key change
|
||||
$removeOldEntry = false;
|
||||
$iterator -> next();
|
||||
$iterator->next();
|
||||
}else{
|
||||
// a -> b mapping
|
||||
$iterator->offsetSet( self::$map[$iterator->key()], $iterator->current() );
|
||||
|
||||
18
app/main/data/mapper/crestsystem.php
Normal file
18
app/main/data/mapper/crestsystem.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Exodus
|
||||
* Date: 07.02.2016
|
||||
* Time: 14:34
|
||||
*/
|
||||
|
||||
namespace Data\Mapper;
|
||||
|
||||
|
||||
class CrestSystem extends AbstractIterator {
|
||||
|
||||
protected static $map = [
|
||||
'id' => 'id',
|
||||
'name' => 'name'
|
||||
];
|
||||
}
|
||||
47
app/main/data/mapper/igbheader.php
Normal file
47
app/main/data/mapper/igbheader.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Exodus
|
||||
* Date: 01.04.2016
|
||||
* Time: 19:48
|
||||
*/
|
||||
|
||||
namespace Data\Mapper;
|
||||
|
||||
|
||||
class IgbHeader extends AbstractIterator {
|
||||
|
||||
protected static $map = [
|
||||
'charid' => ['character' => 'id'],
|
||||
'charname' => ['character' => 'name'],
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
'solarsystemid' => ['system' => 'id'],
|
||||
'solarsystemname' => ['system' => 'name'],
|
||||
|
||||
'constellationid' => ['constellation' => 'id'],
|
||||
'constellationname' => ['constellation' => 'name'],
|
||||
|
||||
'regionid' => ['region' => 'id'],
|
||||
'regionname' => ['region' => 'name'],
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
'shiptypeid' => ['ship' => 'typeId'],
|
||||
'shiptypename' => ['ship' => 'typeName'],
|
||||
'shipid' => ['ship' => 'id'],
|
||||
'shipname' => ['ship' => 'name'],
|
||||
|
||||
'stationid' => ['station' => 'id'],
|
||||
'stationname' => ['station' => 'name'],
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
'corpid' => ['corporation' => 'id'],
|
||||
'corpname' => ['corporation' => 'name'],
|
||||
|
||||
'allianceid' => ['alliance' => 'id'],
|
||||
'alliancename' => ['alliance' => 'name']
|
||||
];
|
||||
}
|
||||
@@ -80,7 +80,7 @@ class TableModifier extends SQL\TableModifier {
|
||||
public function dropConstraint($constraint){
|
||||
if($constraint->isValid()){
|
||||
$this->queries[] = "ALTER TABLE " . $this->db->quotekey($this->name) . "
|
||||
DROP FOREIGN KEY " . $this->db->quotekey($constraint->getConstraintName());
|
||||
DROP FOREIGN KEY " . $this->db->quotekey($constraint->getConstraintName()) . ";";
|
||||
}else{
|
||||
trigger_error(sprintf(self::TEXT_ConstraintNotValid, 'table: ' . $this->name . ' constraintName: ' . $constraint->getConstraintName()));
|
||||
}
|
||||
@@ -93,18 +93,13 @@ class TableModifier extends SQL\TableModifier {
|
||||
public function addConstraint($constraint){
|
||||
|
||||
if($constraint->isValid()){
|
||||
if($this->constraintExists($constraint)){
|
||||
// drop constraint and re-add in case something has changed
|
||||
$this->dropConstraint($constraint);
|
||||
}
|
||||
|
||||
$this->queries[] = "
|
||||
ALTER TABLE " . $this->db->quotekey($this->name) . "
|
||||
ADD CONSTRAINT " . $this->db->quotekey($constraint->getConstraintName()) . "
|
||||
FOREIGN KEY (" . implode(', ', $constraint->getKeys()) . ")
|
||||
REFERENCES " . $this->db->quotekey($constraint->getReferencedTable()) . " (" . implode(', ', $constraint->getReferencedCols()) . ")
|
||||
ON DELETE " . $constraint->getOnDelete() . "
|
||||
ON UPDATE " . $constraint->getOnUpdate();
|
||||
ON UPDATE " . $constraint->getOnUpdate() . ";";
|
||||
}else{
|
||||
trigger_error(sprintf(self::TEXT_ConstraintNotValid, 'table: ' . $this->name . ' constraintName: ' . $constraint->getConstraintName()));
|
||||
}
|
||||
@@ -120,7 +115,15 @@ class Column extends SQL\Column {
|
||||
const TEXT_TableNameMissing = 'Table name missing for FOREIGN KEY in `%s`';
|
||||
|
||||
/**
|
||||
* ass constraint to this column
|
||||
* drop constraint from this column
|
||||
* @param Constraint $constraint
|
||||
*/
|
||||
public function dropConstraint(Constraint $constraint){
|
||||
$this->table->dropConstraint($constraint);
|
||||
}
|
||||
|
||||
/**
|
||||
* add constraint to this column
|
||||
* @param Constraint $constraint
|
||||
*/
|
||||
public function addConstraint(Constraint $constraint){
|
||||
|
||||
167
app/main/lib/web.php
Normal file
167
app/main/lib/web.php
Normal file
@@ -0,0 +1,167 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Exodus
|
||||
* Date: 12.03.2016
|
||||
* Time: 12:28
|
||||
*/
|
||||
|
||||
namespace Lib;
|
||||
|
||||
use controller\LogController;
|
||||
|
||||
class Web extends \Web {
|
||||
|
||||
const ERROR_DEFAULT_MSG = 'method: \'%s\', url: \'%s\'';
|
||||
const ERROR_STATUS_UNKNOWN = 'HTTP response - unknown HTTP status: \'%s\'. url: \'%s\'';
|
||||
const ERROR_TIMEOUT = 'Request timeout \'%ss\'. url: \'%s\'';
|
||||
|
||||
|
||||
/**
|
||||
* end of line
|
||||
* @var string
|
||||
*/
|
||||
private $eol = "\r\n";
|
||||
|
||||
/**
|
||||
* get status code from Header data array
|
||||
* @param array $headers
|
||||
* @return int
|
||||
*/
|
||||
protected function getStatuscodeFromHeaders($headers = []){
|
||||
$statusCode = 0;
|
||||
|
||||
if(
|
||||
preg_match(
|
||||
'/HTTP\/1\.\d (\d{3}?)/',
|
||||
implode($this->eol, $headers),
|
||||
$matches
|
||||
)
|
||||
){
|
||||
$statusCode = (int)$matches[1];
|
||||
}
|
||||
return $statusCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* get cache time in seconds from Header data array
|
||||
* @param array $headers
|
||||
* @return int
|
||||
*/
|
||||
protected function getCacheTimeFromHeaders($headers = []){
|
||||
$cacheTime = 0;
|
||||
|
||||
if(
|
||||
preg_match(
|
||||
'/Cache-Control:(.*?)max-age=([0-9]+)/',
|
||||
implode($this->eol, $headers),
|
||||
$matches
|
||||
)
|
||||
){
|
||||
$cacheTime = (int)$matches[2];
|
||||
}elseif(
|
||||
preg_match(
|
||||
'/Access-Control-Max-Age: ([0-9]+)/',
|
||||
implode($this->eol, $headers),
|
||||
$matches
|
||||
)
|
||||
){
|
||||
$cacheTime = (int)$matches[1];
|
||||
}
|
||||
return $cacheTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* get a unique cache kay for a request
|
||||
* @param $url
|
||||
* @param null $options
|
||||
* @return string
|
||||
*/
|
||||
protected function getCacheKey($url, $options = null){
|
||||
$f3 = \Base::instance();
|
||||
|
||||
$headers = isset($options['header']) ? implode($this->eol, (array) $options['header']) : '';
|
||||
|
||||
return $f3->hash(
|
||||
$options['method'] . ' '
|
||||
. $url . ' '
|
||||
. $headers
|
||||
) . 'url';
|
||||
}
|
||||
|
||||
/**
|
||||
* perform curl() request
|
||||
* -> caches response by returned HTTP Cache header data
|
||||
* @param string $url
|
||||
* @param array|null $options
|
||||
* @return array|FALSE|mixed
|
||||
*/
|
||||
public function request($url,array $options = null) {
|
||||
$f3 = \Base::instance();
|
||||
|
||||
if( !$f3->exists( $hash = $this->getCacheKey($url, $options) ) ){
|
||||
$result = parent::request($url, $options);
|
||||
$statusCode = $this->getStatuscodeFromHeaders( $result['headers'] );
|
||||
|
||||
switch($statusCode){
|
||||
case 200:
|
||||
// request succeeded -> check if response should be cached
|
||||
$ttl = $this->getCacheTimeFromHeaders( $result['headers'] );
|
||||
|
||||
if(
|
||||
$ttl > 0 &&
|
||||
!empty( json_decode( $result['body'], true ) )
|
||||
){
|
||||
$f3->set($hash, $result, $ttl);
|
||||
}
|
||||
break;
|
||||
case 500:
|
||||
case 501:
|
||||
case 502:
|
||||
case 503:
|
||||
case 504:
|
||||
case 505:
|
||||
$f3->error($statusCode, $this->getErrorMessageFromJsonResponse(
|
||||
$options['method'],
|
||||
$url,
|
||||
json_decode($result['body'])
|
||||
));
|
||||
break;
|
||||
case 0:
|
||||
// timeout
|
||||
LogController::getLogger('error')->write(
|
||||
sprintf(self::ERROR_TIMEOUT, $options['timeout'], $url)
|
||||
);
|
||||
break;
|
||||
default:
|
||||
// unknown status
|
||||
LogController::getLogger('error')->write(
|
||||
sprintf(self::ERROR_STATUS_UNKNOWN, $statusCode, $url)
|
||||
);
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
$result = $f3->get($hash);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* get error message from response object
|
||||
* @param string $method
|
||||
* @param string $url
|
||||
* @param \stdClass $responseBody
|
||||
* @return string
|
||||
*/
|
||||
protected function getErrorMessageFromJsonResponse($method, $url, $responseBody){
|
||||
if( empty($responseBody->message) ){
|
||||
$message = sprintf(self::ERROR_DEFAULT_MSG, $method, $url);
|
||||
}else{
|
||||
$message = $responseBody->message . ', url: \'' . $url . '\'';
|
||||
}
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,7 +13,7 @@ use Exception;
|
||||
use Controller;
|
||||
use DB;
|
||||
|
||||
class BasicModel extends \DB\Cortex {
|
||||
abstract class BasicModel extends \DB\Cortex {
|
||||
|
||||
/**
|
||||
* Hive key with DB object
|
||||
@@ -81,15 +81,17 @@ class BasicModel extends \DB\Cortex {
|
||||
$self->clearCacheData();
|
||||
});
|
||||
|
||||
// model updated
|
||||
$this->afterupdate( function($self){
|
||||
$self->clearCacheData();
|
||||
});
|
||||
|
||||
// model updated
|
||||
$this->beforeinsert( function($self){
|
||||
$self->beforeInsertEvent($self);
|
||||
});
|
||||
|
||||
$this->aftererase( function($self){
|
||||
$self->aftereraseEvent($self);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -106,18 +108,27 @@ class BasicModel extends \DB\Cortex {
|
||||
return;
|
||||
}
|
||||
|
||||
if($key != 'updated'){
|
||||
if(
|
||||
!$this->dry() &&
|
||||
$key != 'updated'
|
||||
){
|
||||
if( $this->exists($key) ){
|
||||
$currentVal = $this->get($key);
|
||||
|
||||
// if current value is not a relational object
|
||||
// and value has changed -> update table col
|
||||
if(
|
||||
!is_object($currentVal) &&
|
||||
$currentVal != $val
|
||||
){
|
||||
if(is_object($currentVal)){
|
||||
if(
|
||||
is_numeric($val) &&
|
||||
is_subclass_of($currentVal, 'Model\BasicModel') &&
|
||||
$currentVal->_id !== (int)$val
|
||||
){
|
||||
$this->touch('updated');
|
||||
}
|
||||
}elseif($currentVal != $val){
|
||||
$this->touch('updated');
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,7 +237,7 @@ class BasicModel extends \DB\Cortex {
|
||||
$cacheKey = null;
|
||||
|
||||
// set a model unique cache key if the model is saved
|
||||
if( $this->_id > 0){
|
||||
if( $this->id > 0){
|
||||
// check if there is a given key prefix
|
||||
// -> if not, use the standard key.
|
||||
// this is useful for caching multiple data sets according to one row entry
|
||||
@@ -245,6 +256,67 @@ class BasicModel extends \DB\Cortex {
|
||||
return $cacheKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* get cached data from this model
|
||||
* @param string $dataCacheKeyPrefix - optional key prefix
|
||||
* @return \stdClass|null
|
||||
*/
|
||||
protected function getCacheData($dataCacheKeyPrefix = ''){
|
||||
|
||||
$cacheKey = $this->getCacheKey($dataCacheKeyPrefix);
|
||||
$cacheData = null;
|
||||
|
||||
if( !is_null($cacheKey) ){
|
||||
$f3 = self::getF3();
|
||||
|
||||
if( $f3->exists($cacheKey) ){
|
||||
$cacheData = $f3->get( $cacheKey );
|
||||
}
|
||||
}
|
||||
|
||||
return $cacheData;
|
||||
}
|
||||
|
||||
/**
|
||||
* update/set the getData() cache for this object
|
||||
* @param $cacheData
|
||||
* @param string $dataCacheKeyPrefix
|
||||
* @param int $data_ttl
|
||||
*/
|
||||
public function updateCacheData($cacheData, $dataCacheKeyPrefix = '', $data_ttl = 300){
|
||||
|
||||
$cacheDataTmp = (array)$cacheData;
|
||||
|
||||
// check if data should be cached
|
||||
// and cacheData is not empty
|
||||
if(
|
||||
$data_ttl > 0 &&
|
||||
!empty( $cacheDataTmp )
|
||||
){
|
||||
$cacheKey = $this->getCacheKey($dataCacheKeyPrefix);
|
||||
|
||||
if( !is_null($cacheKey) ){
|
||||
self::getF3()->set($cacheKey, $cacheData, $data_ttl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* unset the getData() cache for this object
|
||||
*/
|
||||
public function clearCacheData(){
|
||||
$cacheKey = $this->getCacheKey();
|
||||
|
||||
if( !is_null($cacheKey) ){
|
||||
$f3 = self::getF3();
|
||||
|
||||
if( $f3->exists($cacheKey) ){
|
||||
$f3->clear($cacheKey);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws a validation error for a giben column
|
||||
* @param $col
|
||||
@@ -338,11 +410,20 @@ class BasicModel extends \DB\Cortex {
|
||||
}
|
||||
|
||||
/**
|
||||
* function should be overwritten in child classes with access restriction
|
||||
* @param $accessObject
|
||||
* Event "Hook" function
|
||||
* can be overwritten
|
||||
* @return bool
|
||||
*/
|
||||
public function hasAccess($accessObject){
|
||||
public function aftereraseEvent($self){
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* function should be overwritten in child classes with access restriction
|
||||
* @param CharacterModel $characterModel
|
||||
* @return bool
|
||||
*/
|
||||
public function hasAccess(CharacterModel $characterModel){
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -354,113 +435,6 @@ class BasicModel extends \DB\Cortex {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* get cached data from this model
|
||||
* @param string $dataCacheKeyPrefix - optional key prefix
|
||||
* @return mixed|null
|
||||
*/
|
||||
protected function getCacheData($dataCacheKeyPrefix = ''){
|
||||
|
||||
$cacheKey = $this->getCacheKey($dataCacheKeyPrefix);
|
||||
$cacheData = null;
|
||||
|
||||
if( !is_null($cacheKey) ){
|
||||
$f3 = self::getF3();
|
||||
|
||||
if( $f3->exists($cacheKey) ){
|
||||
$cacheData = $f3->get( $cacheKey );
|
||||
}
|
||||
}
|
||||
|
||||
return $cacheData;
|
||||
}
|
||||
|
||||
/**
|
||||
* update/set the getData() cache for this object
|
||||
* @param $cacheData
|
||||
* @param string $dataCacheKeyPrefix
|
||||
* @param int $data_ttl
|
||||
*/
|
||||
public function updateCacheData($cacheData, $dataCacheKeyPrefix = '', $data_ttl = 300){
|
||||
|
||||
$cacheDataTmp = (array)$cacheData;
|
||||
|
||||
// check if data should be cached
|
||||
// and cacheData is not empty
|
||||
if(
|
||||
$data_ttl > 0 &&
|
||||
!empty( $cacheDataTmp )
|
||||
){
|
||||
$cacheKey = $this->getCacheKey($dataCacheKeyPrefix);
|
||||
|
||||
if( !is_null($cacheKey) ){
|
||||
self::getF3()->set($cacheKey, $cacheData, $data_ttl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* unset the getData() cache for this object
|
||||
*/
|
||||
public function clearCacheData(){
|
||||
$cacheKey = $this->getCacheKey();
|
||||
|
||||
if( !is_null($cacheKey) ){
|
||||
$f3 = self::getF3();
|
||||
|
||||
if( $f3->exists($cacheKey) ){
|
||||
$f3->clear($cacheKey);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get the current class name
|
||||
* -> namespace not included
|
||||
* @return string
|
||||
*/
|
||||
public static function getClassName(){
|
||||
$parts = explode('\\', static::class);
|
||||
return end($parts);
|
||||
}
|
||||
|
||||
/**
|
||||
* factory for all Models
|
||||
* @param $model
|
||||
* @param int $ttl
|
||||
* @return null
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function getNew($model, $ttl = 86400){
|
||||
$class = null;
|
||||
|
||||
$model = '\\' . __NAMESPACE__ . '\\' . $model;
|
||||
if(class_exists($model)){
|
||||
$class = new $model( null, null, null, $ttl );
|
||||
}else{
|
||||
throw new \Exception('No model class found');
|
||||
}
|
||||
|
||||
return $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the framework instance (singleton)
|
||||
* @return static
|
||||
*/
|
||||
public static function getF3(){
|
||||
return \Base::instance();
|
||||
}
|
||||
|
||||
/**
|
||||
* debug log function
|
||||
* @param $text
|
||||
*/
|
||||
public static function log($text){
|
||||
Controller\LogController::getLogger('debug')->write($text);
|
||||
}
|
||||
|
||||
/**
|
||||
* export and download table data as *.csv
|
||||
* this is primarily used for static tables
|
||||
@@ -573,6 +547,52 @@ class BasicModel extends \DB\Cortex {
|
||||
return ['added' => $addedCount, 'updated' => $updatedCount, 'deleted' => $deletedCount];
|
||||
}
|
||||
|
||||
/**
|
||||
* get the current class name
|
||||
* -> namespace not included
|
||||
* @return string
|
||||
*/
|
||||
public static function getClassName(){
|
||||
$parts = explode('\\', static::class);
|
||||
return end($parts);
|
||||
}
|
||||
|
||||
/**
|
||||
* factory for all Models
|
||||
* @param string $model
|
||||
* @param int $ttl
|
||||
* @return BasicModel
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function getNew($model, $ttl = 86400){
|
||||
$class = null;
|
||||
|
||||
$model = '\\' . __NAMESPACE__ . '\\' . $model;
|
||||
if(class_exists($model)){
|
||||
$class = new $model( null, null, null, $ttl );
|
||||
}else{
|
||||
throw new \Exception('No model class found');
|
||||
}
|
||||
|
||||
return $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the framework instance (singleton)
|
||||
* @return \Base
|
||||
*/
|
||||
public static function getF3(){
|
||||
return \Base::instance();
|
||||
}
|
||||
|
||||
/**
|
||||
* debug log function
|
||||
* @param string $text
|
||||
*/
|
||||
public static function log($text){
|
||||
Controller\LogController::getLogger('debug')->write($text);
|
||||
}
|
||||
|
||||
/**
|
||||
* get tableModifier class for this table
|
||||
* @return bool|DB\SQL\TableModifier
|
||||
|
||||
@@ -14,6 +14,14 @@ class CharacterLogModel extends BasicModel {
|
||||
|
||||
protected $table = 'character_log';
|
||||
|
||||
/**
|
||||
* caching for relational data
|
||||
* -> 10s matches REST API - Expire: Header-Data
|
||||
* for "Location" calls
|
||||
* @var int
|
||||
*/
|
||||
protected $rel_ttl = 10;
|
||||
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
@@ -33,6 +41,9 @@ class CharacterLogModel extends BasicModel {
|
||||
]
|
||||
]
|
||||
],
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
'systemId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true
|
||||
@@ -42,6 +53,35 @@ class CharacterLogModel extends BasicModel {
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'constellationId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true
|
||||
],
|
||||
'constellationName' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'regionId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true
|
||||
],
|
||||
'regionName' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
'shipTypeId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true
|
||||
],
|
||||
'shipTypeName' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'shipId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true
|
||||
@@ -51,21 +91,69 @@ class CharacterLogModel extends BasicModel {
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'shipTypeName' => [
|
||||
'stationId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true
|
||||
],
|
||||
'stationName' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
]
|
||||
];
|
||||
|
||||
public function __construct($db = NULL, $table = NULL, $fluid = NULL, $ttl = 0){
|
||||
/**
|
||||
* set log data from array
|
||||
* @param array $logData
|
||||
*/
|
||||
public function setData($logData){
|
||||
|
||||
parent::__construct($db, $table, $fluid, $ttl);
|
||||
if( isset($logData['system']) ){
|
||||
$this->systemId = (int)$logData['system']['id'];
|
||||
$this->systemName = $logData['system']['name'];
|
||||
}else{
|
||||
$this->systemId = null;
|
||||
$this->systemName = '';
|
||||
}
|
||||
|
||||
if( isset($logData['constellation']) ){
|
||||
$this->constellationId = (int)$logData['constellation']['id'];
|
||||
$this->constellationName = $logData['constellation']['name'];
|
||||
}else{
|
||||
$this->constellationId = null;
|
||||
$this->constellationName = '';
|
||||
}
|
||||
|
||||
if( isset($logData['region']) ){
|
||||
$this->regionId = (int)$logData['region']['id'];
|
||||
$this->regionName = $logData['region']['name'];
|
||||
}else{
|
||||
$this->regionId = null;
|
||||
$this->regionName = '';
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
if( isset($logData['ship']) ){
|
||||
$this->shipTypeId = (int)$logData['ship']['typeId'];
|
||||
$this->shipTypeName = $logData['ship']['typeName'];
|
||||
$this->shipId = (int)$logData['ship']['id'];
|
||||
$this->shipName = $logData['ship']['name'];
|
||||
}else{
|
||||
$this->shipTypeId = null;
|
||||
$this->shipTypeName = '';
|
||||
$this->shipId = null;
|
||||
$this->shipName = '';
|
||||
}
|
||||
|
||||
if( isset($logData['station']) ){
|
||||
$this->stationId = (int)$logData['station']['id'];
|
||||
$this->stationName = $logData['station']['name'];
|
||||
}else{
|
||||
$this->stationId = null;
|
||||
$this->stationName = '';
|
||||
}
|
||||
|
||||
// events -----------------------------------------
|
||||
$this->beforeerase(function($self){
|
||||
$self->clearCacheData();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,30 +164,30 @@ class CharacterLogModel extends BasicModel {
|
||||
|
||||
$logData = (object) [];
|
||||
$logData->system = (object) [];
|
||||
$logData->system->id = $this->systemId;
|
||||
$logData->system->id = (int)$this->systemId;
|
||||
$logData->system->name = $this->systemName;
|
||||
|
||||
$logData->constellation = (object) [];
|
||||
$logData->constellation->id = (int)$this->constellationId;
|
||||
$logData->constellation->name = $this->constellationName;
|
||||
|
||||
$logData->region = (object) [];
|
||||
$logData->region->id = (int)$this->regionId;
|
||||
$logData->region->name = $this->regionName;
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
|
||||
$logData->ship = (object) [];
|
||||
$logData->ship->typeId = (int)$this->shipTypeId;
|
||||
$logData->ship->typeName = $this->shipTypeName;
|
||||
$logData->ship->id = $this->shipId;
|
||||
$logData->ship->name = $this->shipName;
|
||||
$logData->ship->typeName = $this->shipTypeName;
|
||||
|
||||
$logData->station = (object) [];
|
||||
$logData->station->id = (int)$this->stationId;
|
||||
$logData->station->name = $this->stationName;
|
||||
|
||||
return $logData;
|
||||
}
|
||||
|
||||
/**
|
||||
* see parent
|
||||
*/
|
||||
public function clearCacheData(){
|
||||
parent::clearCacheData();
|
||||
|
||||
// delete log cache key as well
|
||||
$f3 = self::getF3();
|
||||
$character = $this->characterId;
|
||||
|
||||
$character->clearCacheData();
|
||||
$f3->clear('LOGGED.user.character.id_' . $character->id);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,18 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: exodus4d
|
||||
* Date: 28.02.15
|
||||
* Time: 11:57
|
||||
* User: Exodus
|
||||
* Date: 07.02.2016
|
||||
* Time: 12:31
|
||||
*/
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class UserMapModel extends BasicModel {
|
||||
class CharacterMapModel extends BasicModel {
|
||||
|
||||
protected $table = 'user_map';
|
||||
protected $table = 'character_map';
|
||||
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
@@ -21,13 +21,13 @@ class UserMapModel extends BasicModel {
|
||||
'default' => 1,
|
||||
'index' => true
|
||||
],
|
||||
'userId' => [
|
||||
'characterId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\UserModel',
|
||||
'belongs-to-one' => 'Model\CharacterModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'user',
|
||||
'table' => 'character',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
@@ -66,10 +66,10 @@ class UserMapModel extends BasicModel {
|
||||
$status = parent::setup($db,$table,$fields);
|
||||
|
||||
if($status === true){
|
||||
$status = parent::setMultiColumnIndex(['userId', 'mapId'], true);
|
||||
$status = parent::setMultiColumnIndex(['characterId', 'mapId'], true);
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -8,13 +8,20 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use Controller;
|
||||
use Controller\Ccp;
|
||||
use DB\SQL\Schema;
|
||||
use Data\Mapper as Mapper;
|
||||
|
||||
class CharacterModel extends BasicModel {
|
||||
|
||||
protected $table = 'character';
|
||||
|
||||
protected $fieldConf = [
|
||||
'lastLogin' => [
|
||||
'type' => Schema::DT_TIMESTAMP,
|
||||
'index' => true
|
||||
],
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
@@ -26,6 +33,22 @@ class CharacterModel extends BasicModel {
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'ownerHash' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'crestAccessToken' => [
|
||||
'type' => Schema::DT_VARCHAR256
|
||||
],
|
||||
'crestAccessTokenUpdated' => [
|
||||
'type' => Schema::DT_TIMESTAMP,
|
||||
'default' => Schema::DF_CURRENT_TIMESTAMP,
|
||||
'index' => true
|
||||
],
|
||||
'crestRefreshToken' => [
|
||||
'type' => Schema::DT_VARCHAR256
|
||||
],
|
||||
'corporationId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
@@ -57,29 +80,46 @@ class CharacterModel extends BasicModel {
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'shared' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => 0
|
||||
],
|
||||
'userCharacter' => [
|
||||
'has-one' => ['Model\UserCharacterModel', 'characterId']
|
||||
],
|
||||
'characterLog' => [
|
||||
'has-one' => ['Model\CharacterLogModel', 'characterId']
|
||||
],
|
||||
'characterMaps' => [
|
||||
'has-many' => ['Model\CharacterMapModel', 'characterId']
|
||||
]
|
||||
];
|
||||
|
||||
/**
|
||||
* get character data
|
||||
* @param bool|false $addCharacterLogData
|
||||
* @return object
|
||||
* @return \stdClass
|
||||
*/
|
||||
public function getData($addCharacterLogData = false){
|
||||
$characterData = null;
|
||||
|
||||
$cacheKeyModifier = '';
|
||||
|
||||
// check if there is cached data
|
||||
// temporary disabled (performance test)
|
||||
$characterData = null; //$this->getCacheData();
|
||||
if($addCharacterLogData){
|
||||
$cacheKeyModifier = strtoupper($this->table) . '_LOG';
|
||||
}
|
||||
|
||||
$characterData = $this->getCacheData($cacheKeyModifier);
|
||||
|
||||
if(is_null($characterData)){
|
||||
|
||||
// no cached character data found
|
||||
|
||||
$characterData = (object) [];
|
||||
|
||||
$characterData->id = $this->id;
|
||||
$characterData->name = $this->name;
|
||||
$characterData->shared = $this->shared;
|
||||
|
||||
if($addCharacterLogData){
|
||||
if($logModel = $this->getLog()){
|
||||
@@ -100,24 +140,56 @@ class CharacterModel extends BasicModel {
|
||||
// max caching time for a system
|
||||
// the cached date has to be cleared manually on any change
|
||||
// this includes system, connection,... changes (all dependencies)
|
||||
$this->updateCacheData($characterData, '', 300);
|
||||
$this->updateCacheData($characterData, $cacheKeyModifier, 10);
|
||||
}
|
||||
|
||||
return $characterData;
|
||||
}
|
||||
|
||||
/**
|
||||
* set unique "ownerHash" for this character
|
||||
* -> Hash will change when character is transferred (sold)
|
||||
* @param string $ownerHash
|
||||
* @return string
|
||||
*/
|
||||
public function set_ownerHash($ownerHash){
|
||||
if (
|
||||
$this->hasUserCharacter() &&
|
||||
$this->ownerHash !== $ownerHash
|
||||
){
|
||||
$this->userCharacter->erase();
|
||||
}
|
||||
return $ownerHash;
|
||||
}
|
||||
|
||||
/**
|
||||
* set CREST accessToken for current session
|
||||
* -> update "tokenUpdated" column on change
|
||||
* -> this is required for expire checking!
|
||||
* @param string $accessToken
|
||||
* @return string
|
||||
*/
|
||||
public function set_crestAccessToken($accessToken){
|
||||
if($this->crestAccessToken !== $accessToken){
|
||||
$this->touch('crestAccessTokenUpdated');
|
||||
}
|
||||
return $accessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* check whether this character has already a user assigned to it
|
||||
* @return bool
|
||||
*/
|
||||
public function hasUserCharacter(){
|
||||
return is_object($this->userCharacter);
|
||||
}
|
||||
|
||||
/**
|
||||
* check whether this character has a corporation
|
||||
* @return bool
|
||||
*/
|
||||
public function hasCorporation(){
|
||||
$hasCorporation = false;
|
||||
|
||||
if($this->corporationId){
|
||||
$hasCorporation = true;
|
||||
}
|
||||
|
||||
return $hasCorporation;
|
||||
return is_object($this->corporationId);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -125,46 +197,198 @@ class CharacterModel extends BasicModel {
|
||||
* @return bool
|
||||
*/
|
||||
public function hasAlliance(){
|
||||
$hasAlliance = false;
|
||||
return is_object($this->allianceId);
|
||||
}
|
||||
|
||||
if($this->allianceId){
|
||||
$hasAlliance = true;
|
||||
/**
|
||||
* @return UserModel|null
|
||||
*/
|
||||
public function getUser(){
|
||||
$user = null;
|
||||
if($this->hasUserCharacter()){
|
||||
/**
|
||||
* @var $user UserModel
|
||||
*/
|
||||
$user = $this->userCharacter->userId;
|
||||
}
|
||||
|
||||
return $hasAlliance;
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the corporation for this user
|
||||
* @return mixed|null
|
||||
* @return \Model\CorporationModel|null
|
||||
*/
|
||||
public function getCorporation(){
|
||||
$corporation = null;
|
||||
|
||||
if($this->hasCorporation()){
|
||||
$corporation = $this->corporationId;
|
||||
}
|
||||
|
||||
return $corporation;
|
||||
return $this->corporationId;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the alliance of this user
|
||||
* @return mixed|null
|
||||
* @return \Model\AllianceModel|null
|
||||
*/
|
||||
public function getAlliance(){
|
||||
$alliance = null;
|
||||
return $this->allianceId;
|
||||
}
|
||||
|
||||
if($this->hasAlliance()){
|
||||
$alliance = $this->allianceId;
|
||||
/**
|
||||
* get CREST API "access_token" from OAuth
|
||||
* @return bool|string
|
||||
*/
|
||||
private function getAccessToken(){
|
||||
$accessToken = false;
|
||||
|
||||
// check if there is already an "accessToken" for this user
|
||||
// check expire timer for stored "accessToken"
|
||||
if(
|
||||
!empty($this->crestAccessToken) &&
|
||||
!empty($this->crestAccessTokenUpdated)
|
||||
){
|
||||
$timezone = new \DateTimeZone( $this->getF3()->get('TZ') );
|
||||
$tokenTime = \DateTime::createFromFormat(
|
||||
'Y-m-d H:i:s',
|
||||
$this->crestAccessTokenUpdated,
|
||||
$timezone
|
||||
);
|
||||
// add expire time buffer for this "accessToken"
|
||||
// token should be marked as "deprecated" BEFORE it actually expires.
|
||||
$timeBuffer = 2 * 60;
|
||||
$tokenTime->add(new \DateInterval('PT' . (Ccp\Sso::ACCESS_KEY_EXPIRE_TIME - $timeBuffer) . 'S'));
|
||||
|
||||
$now = new \DateTime('now', $timezone);
|
||||
if($tokenTime->getTimestamp() > $now->getTimestamp()){
|
||||
$accessToken = $this->crestAccessToken;
|
||||
}
|
||||
}
|
||||
|
||||
return $alliance;
|
||||
// if no "accessToken" was found -> get a fresh one by an existing "refreshToken"
|
||||
if(
|
||||
!$accessToken &&
|
||||
!empty($this->crestRefreshToken)
|
||||
){
|
||||
// no accessToken found OR token is deprecated
|
||||
$ssoController = new Ccp\Sso();
|
||||
$accessData = $ssoController->refreshAccessToken($this->crestRefreshToken);
|
||||
|
||||
if(
|
||||
isset($accessData->accessToken) &&
|
||||
isset($accessData->refreshToken)
|
||||
){
|
||||
$this->crestAccessToken = $accessData->accessToken;
|
||||
$this->save();
|
||||
|
||||
$accessToken = $this->crestAccessToken;
|
||||
}
|
||||
}
|
||||
|
||||
return $accessToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* checks whether this character is authorized to log in
|
||||
* -> check corp/ally whitelist config (pathfinder.ini)
|
||||
* @return bool
|
||||
*/
|
||||
public function isAuthorized(){
|
||||
$isAuthorized = false;
|
||||
$f3 = self::getF3();
|
||||
|
||||
$whitelistCorporations = $whitelistAlliance = [];
|
||||
if( !empty($f3->get('PATHFINDER.LOGIN.CORPORATION')) ){
|
||||
$whitelistCorporations = array_map('trim',(array) $f3->get('PATHFINDER.LOGIN.CORPORATION') );
|
||||
}
|
||||
if( !empty($f3->get('PATHFINDER.LOGIN.ALLIANCE')) ){
|
||||
$whitelistAlliance = array_map('trim',(array) $f3->get('PATHFINDER.LOGIN.ALLIANCE') );
|
||||
}
|
||||
|
||||
if(
|
||||
empty($whitelistCorporations) &&
|
||||
empty($whitelistAlliance)
|
||||
){
|
||||
// no corp/ally restrictions set -> any character is allowed to login
|
||||
$isAuthorized = true;
|
||||
}else{
|
||||
// check if character corporation is set in whitelist
|
||||
if(
|
||||
!empty($whitelistCorporations) &&
|
||||
$this->hasCorporation() &&
|
||||
in_array($this->getCorporation()->_id, $whitelistCorporations)
|
||||
){
|
||||
$isAuthorized = true;
|
||||
}
|
||||
|
||||
// check if character alliance is set in whitelist
|
||||
if(
|
||||
!$isAuthorized &&
|
||||
!empty($whitelistAlliance) &&
|
||||
$this->hasAlliance() &&
|
||||
in_array($this->getAlliance()->_id, $whitelistAlliance)
|
||||
){
|
||||
$isAuthorized = true;
|
||||
}
|
||||
}
|
||||
|
||||
return $isAuthorized;
|
||||
}
|
||||
|
||||
/**
|
||||
* update character log (active system, ...)
|
||||
* -> HTTP Header Data (if IGB)
|
||||
* -> CREST API request for character log data (if not IGB)
|
||||
* @return CharacterModel
|
||||
*/
|
||||
public function updateLog(){
|
||||
|
||||
$logData = [];
|
||||
$headerData = Controller\Controller::getIGBHeaderData();
|
||||
|
||||
// check if IGB Data is available
|
||||
if(
|
||||
$headerData->trusted === true &&
|
||||
!empty($headerData->values)
|
||||
){
|
||||
// format header data
|
||||
$formattedHeaderData = (new Mapper\IgbHeader($headerData->values))->getData();
|
||||
|
||||
// just for security -> check if Header Data matches THIS character
|
||||
if(
|
||||
isset($formattedHeaderData['character']) &&
|
||||
$formattedHeaderData['character']['id'] == $this->_id
|
||||
){
|
||||
$logData = $formattedHeaderData;
|
||||
}
|
||||
}else{
|
||||
// get Location Data from CREST endpoint
|
||||
// user is NOT with IGB online OR has not jet set "trusted" page
|
||||
$ssoController = new Ccp\Sso();
|
||||
$logData = $ssoController->getCharacterLocationData($this->getAccessToken());
|
||||
}
|
||||
|
||||
if( empty($logData) ){
|
||||
// character is not in-game
|
||||
if(is_object($this->characterLog)){
|
||||
// delete existing log
|
||||
$this->characterLog->erase();
|
||||
$this->save();
|
||||
}
|
||||
}else{
|
||||
// character is currently in-game
|
||||
if( !$characterLog = $this->getLog() ){
|
||||
// create new log
|
||||
$characterLog = $this->rel('characterLog');
|
||||
$characterLog->characterId = $this->_id;
|
||||
}
|
||||
$characterLog->setData($logData);
|
||||
$characterLog->save();
|
||||
|
||||
$this->characterLog = $characterLog;
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the character log entry for this character
|
||||
* @return bool|null
|
||||
* @return bool|CharacterLogModel
|
||||
*/
|
||||
public function getLog(){
|
||||
|
||||
@@ -173,10 +397,65 @@ class CharacterModel extends BasicModel {
|
||||
is_object($this->characterLog) &&
|
||||
!$this->characterLog->dry()
|
||||
){
|
||||
$characterLog = $this->characterLog;
|
||||
$characterLog = &$this->characterLog;
|
||||
}
|
||||
|
||||
return $characterLog;
|
||||
}
|
||||
|
||||
/**
|
||||
* get mapModel by id and check if user has access
|
||||
* @param int $mapId
|
||||
* @return MapModel|null
|
||||
*/
|
||||
public function getMap(int $mapId){
|
||||
/**
|
||||
* @var $map MapModel
|
||||
*/
|
||||
$map = self::getNew('MapModel');
|
||||
$map->getById( $mapId );
|
||||
|
||||
$returnMap = null;
|
||||
if($map->hasAccess($this)){
|
||||
$returnMap = $map;
|
||||
}
|
||||
|
||||
return $returnMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* get all accessible map models for this character
|
||||
* @return MapModel[]
|
||||
*/
|
||||
public function getMaps(){
|
||||
|
||||
$this->filter(
|
||||
'characterMaps',
|
||||
['active = ?', 1],
|
||||
['order' => 'created']
|
||||
);
|
||||
|
||||
$maps = [];
|
||||
if($this->characterMaps){
|
||||
$mapCountPrivate = 0;
|
||||
foreach($this->characterMaps as &$characterMap){
|
||||
if($mapCountPrivate < self::getF3()->get('PATHFINDER.MAX_MAPS_PRIVATE')){
|
||||
$maps[] = &$characterMap->mapId;
|
||||
$mapCountPrivate++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get
|
||||
if($alliance = $this->getAlliance()){
|
||||
$maps = array_merge($maps, $alliance->getMaps());
|
||||
}
|
||||
|
||||
if($corporation = $this->getCorporation()){
|
||||
$maps = array_merge($maps, $corporation->getMaps());
|
||||
}
|
||||
|
||||
return $maps;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -103,11 +103,11 @@ class ConnectionModel extends BasicModel{
|
||||
|
||||
/**
|
||||
* check object for model access
|
||||
* @param $accessObject
|
||||
* @return bool
|
||||
* @param CharacterModel $characterModel
|
||||
* @return mixed
|
||||
*/
|
||||
public function hasAccess($accessObject){
|
||||
return $this->mapId->hasAccess($accessObject);
|
||||
public function hasAccess(CharacterModel $characterModel){
|
||||
return $this->mapId->hasAccess($characterModel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,13 +127,12 @@ class ConnectionModel extends BasicModel{
|
||||
|
||||
/**
|
||||
* delete a connection
|
||||
* @param $accessObject
|
||||
* @param CharacterModel $characterModel
|
||||
*/
|
||||
public function delete($accessObject){
|
||||
|
||||
if(!$this->dry()){
|
||||
// check if editor has access
|
||||
if($this->hasAccess($accessObject)){
|
||||
public function delete(CharacterModel $characterModel){
|
||||
if( !$this->dry() ){
|
||||
// check if character has access
|
||||
if($this->hasAccess($characterModel)){
|
||||
$this->erase();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use Controller\Api\User;
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class MapModel extends BasicModel {
|
||||
@@ -60,8 +61,8 @@ class MapModel extends BasicModel {
|
||||
'connections' => [
|
||||
'has-many' => ['Model\ConnectionModel', 'mapId']
|
||||
],
|
||||
'mapUsers' => [
|
||||
'has-many' => ['Model\UserMapModel', 'mapId']
|
||||
'mapCharacters' => [
|
||||
'has-many' => ['Model\CharacterMapModel', 'mapId']
|
||||
],
|
||||
'mapCorporations' => [
|
||||
'has-many' => ['Model\CorporationMapModel', 'mapId']
|
||||
@@ -117,16 +118,14 @@ class MapModel extends BasicModel {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get map data
|
||||
* -> this includes system and connection data as well!
|
||||
* @return array
|
||||
* @return \stdClass
|
||||
*/
|
||||
public function getData(){
|
||||
|
||||
// check if there is cached data
|
||||
$mapDataAll = $this->getCacheData();
|
||||
// check if there is cached data
|
||||
$mapDataAll = $this->getCacheData();
|
||||
|
||||
if(is_null($mapDataAll)){
|
||||
// no cached map data found
|
||||
@@ -158,17 +157,23 @@ class MapModel extends BasicModel {
|
||||
|
||||
// get access object data -------------------------------------
|
||||
if($this->isPrivate()){
|
||||
$users = $this->getUsers();
|
||||
$userData = [];
|
||||
foreach($users as $user){
|
||||
$userData[] = $user->getSimpleData();
|
||||
$characters = $this->getCharacters();
|
||||
$characterData = [];
|
||||
foreach($characters as $character){
|
||||
/**
|
||||
* @var $character CharacterModel
|
||||
*/
|
||||
$characterData[] = $character->getData();
|
||||
}
|
||||
$mapData->access->user = $userData;
|
||||
$mapData->access->character = $characterData;
|
||||
} elseif($this->isCorporation()){
|
||||
$corporations = $this->getCorporations();
|
||||
$corporationData = [];
|
||||
|
||||
foreach($corporations as $corporation){
|
||||
/**
|
||||
* @var $corporation CorporationModel
|
||||
*/
|
||||
$corporationData[] = $corporation->getData();
|
||||
}
|
||||
$mapData->access->corporation = $corporationData;
|
||||
@@ -177,6 +182,9 @@ class MapModel extends BasicModel {
|
||||
$allianceData = [];
|
||||
|
||||
foreach($alliances as $alliance){
|
||||
/**
|
||||
* @var $alliance AllianceModel
|
||||
*/
|
||||
$allianceData[] = $alliance->getData();
|
||||
}
|
||||
$mapData->access->alliance = $allianceData;
|
||||
@@ -231,8 +239,9 @@ class MapModel extends BasicModel {
|
||||
$this->filter('systems',
|
||||
['active = :active AND id > 0',
|
||||
':active' => 1
|
||||
],
|
||||
['order' => 'posX']);
|
||||
],
|
||||
['order' => 'posX']
|
||||
);
|
||||
|
||||
$systems = [];
|
||||
if($this->systems){
|
||||
@@ -252,6 +261,9 @@ class MapModel extends BasicModel {
|
||||
|
||||
$systemData = [];
|
||||
foreach($systems as $system){
|
||||
/**
|
||||
* @var $system SystemModel
|
||||
*/
|
||||
$systemData[] = $system->getData();
|
||||
}
|
||||
|
||||
@@ -285,6 +297,9 @@ class MapModel extends BasicModel {
|
||||
|
||||
$connectionData = [];
|
||||
foreach($connections as $connection){
|
||||
/**
|
||||
* @var $connection ConnectionModel
|
||||
*/
|
||||
$connectionData[] = $connection->getData();
|
||||
}
|
||||
|
||||
@@ -292,26 +307,26 @@ class MapModel extends BasicModel {
|
||||
}
|
||||
|
||||
/**
|
||||
* set map access for an object (user, corporation or alliance)
|
||||
* set map access for an object (character, corporation or alliance)
|
||||
* @param $obj
|
||||
*/
|
||||
public function setAccess($obj){
|
||||
|
||||
$newAccessGranted = false;
|
||||
|
||||
if($obj instanceof UserModel){
|
||||
if($obj instanceof CharacterModel){
|
||||
// private map
|
||||
|
||||
// check whether the user has already map access
|
||||
$this->has('mapUsers', ['active = 1 AND userId = :userId', ':userId' => $obj->id]);
|
||||
$this->has('mapCharacters', ['active = 1 AND characterId = :characterId', ':characterId' => $obj->id]);
|
||||
$result = $this->findone(['id = :id', ':id' => $this->id]);
|
||||
|
||||
if($result === false){
|
||||
// grant access for the user
|
||||
$userMap = self::getNew('UserMapModel');
|
||||
$userMap->userId = $obj;
|
||||
$userMap->mapId = $this;
|
||||
$userMap->save();
|
||||
// grant access for the character
|
||||
$characterMap = self::getNew('CharacterMapModel');
|
||||
$characterMap-> characterId = $obj;
|
||||
$characterMap->mapId = $this;
|
||||
$characterMap->save();
|
||||
|
||||
$newAccessGranted = true;
|
||||
}
|
||||
@@ -355,25 +370,34 @@ class MapModel extends BasicModel {
|
||||
|
||||
/**
|
||||
* clear access for a given type of objects
|
||||
* @param $clearKeys
|
||||
* @param array $clearKeys
|
||||
*/
|
||||
public function clearAccess($clearKeys = ['user', 'corporation', 'alliance']){
|
||||
public function clearAccess($clearKeys = ['character', 'corporation', 'alliance']){
|
||||
|
||||
foreach($clearKeys as $key){
|
||||
switch($key){
|
||||
case 'user':
|
||||
foreach((array)$this->mapUsers as $obj){
|
||||
$obj->erase();
|
||||
case 'character':
|
||||
foreach((array)$this->mapCharacters as $characterMapModel){
|
||||
/**
|
||||
* @var CharacterMapModel $characterMapModel
|
||||
*/
|
||||
$characterMapModel->erase();
|
||||
};
|
||||
break;
|
||||
case 'corporation':
|
||||
foreach((array)$this->mapCorporations as $obj){
|
||||
$obj->erase();
|
||||
foreach((array)$this->mapCorporations as $corporationMapModel){
|
||||
/**
|
||||
* @var CorporationMapModel $corporationMapModel
|
||||
*/
|
||||
$corporationMapModel->erase();
|
||||
};
|
||||
break;
|
||||
case 'alliance':
|
||||
foreach((array)$this->mapAlliances as $obj){
|
||||
$obj->erase();
|
||||
foreach((array)$this->mapAlliances as $allianceMapModel){
|
||||
/**
|
||||
* @var AllianceMapModel $allianceMapModel
|
||||
*/
|
||||
$allianceMapModel->erase();
|
||||
};
|
||||
break;
|
||||
}
|
||||
@@ -381,22 +405,17 @@ class MapModel extends BasicModel {
|
||||
}
|
||||
|
||||
/**
|
||||
* checks weather a user has access to this map or not
|
||||
* @param $user
|
||||
* checks weather a character has access to this map or not
|
||||
* @param CharacterModel $characterModel
|
||||
* @return bool
|
||||
*/
|
||||
public function hasAccess($user){
|
||||
public function hasAccess(CharacterModel $characterModel){
|
||||
$hasAccess = false;
|
||||
|
||||
if(
|
||||
!$this->dry() &&
|
||||
$user instanceof UserModel
|
||||
){
|
||||
|
||||
if( !$this->dry() ){
|
||||
// get all maps the user has access to
|
||||
// this includes corporation and alliance maps
|
||||
$maps = $user->getMaps();
|
||||
|
||||
$maps = $characterModel->getMaps();
|
||||
foreach($maps as $map){
|
||||
if($map->id === $this->id){
|
||||
$hasAccess = true;
|
||||
@@ -409,54 +428,56 @@ class MapModel extends BasicModel {
|
||||
}
|
||||
|
||||
/**
|
||||
* get all user models that have access to this map
|
||||
* note: This function is just for "private" maps
|
||||
* @return array
|
||||
*/
|
||||
public function getUsers(){
|
||||
$users = [];
|
||||
|
||||
if($this->isPrivate()){
|
||||
$this->filter('mapUsers', ['active = ?', 1]);
|
||||
|
||||
if($this->mapUsers){
|
||||
foreach($this->mapUsers as $mapUser){
|
||||
$users[] = $mapUser->userId;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $users;
|
||||
}
|
||||
|
||||
/**
|
||||
* get all character models that are currently online "viewing" this map
|
||||
* @return array
|
||||
* get all (private) characters for this map
|
||||
* @return CharacterModel array
|
||||
*/
|
||||
private function getCharacters(){
|
||||
$characters = [];
|
||||
|
||||
$this->filter('mapCharacters', ['active = ?', 1]);
|
||||
|
||||
if($this->mapCharacters){
|
||||
foreach($this->mapCharacters as $characterMapModel){
|
||||
$characters[] = $characterMapModel->characterId;
|
||||
}
|
||||
}
|
||||
|
||||
return $characters;
|
||||
}
|
||||
|
||||
/**
|
||||
* get all character models that are currently online "viewing" this map
|
||||
* @return CharacterModel[]
|
||||
*/
|
||||
private function getActiveCharacters(){
|
||||
$characters = [];
|
||||
|
||||
if($this->isPrivate()){
|
||||
$users = $this->getUsers();
|
||||
$activeCharacters = $this->getCharacters();
|
||||
|
||||
foreach($users as $user){
|
||||
// get all active character logs for a user
|
||||
$tempActiveUserCharacters = $user->getActiveUserCharacters();
|
||||
|
||||
foreach($tempActiveUserCharacters as $tempActiveUserCharacter){
|
||||
$characters[] = $tempActiveUserCharacter;
|
||||
}
|
||||
// add active character for each user
|
||||
foreach($activeCharacters as $activeCharacter){
|
||||
/**
|
||||
* @var UserModel $user
|
||||
*/
|
||||
$characters[] = $activeCharacter;
|
||||
}
|
||||
}elseif($this->isCorporation()){
|
||||
$corporations = $this->getCorporations();
|
||||
|
||||
foreach($corporations as $corporation){
|
||||
/**
|
||||
* @var CorporationModel $corporation
|
||||
*/
|
||||
$characters = array_merge($characters, $corporation->getCharacters());
|
||||
}
|
||||
}elseif($this->isAlliance()){
|
||||
$alliances = $this->getAlliances();
|
||||
|
||||
foreach($alliances as $alliance){
|
||||
/**
|
||||
* @var AllianceModel $alliance
|
||||
*/
|
||||
$characters = array_merge($characters, $alliance->getCharacters());
|
||||
}
|
||||
}
|
||||
@@ -476,7 +497,7 @@ class MapModel extends BasicModel {
|
||||
|
||||
if(is_null($charactersData)){
|
||||
$charactersData = [];
|
||||
$characters = $this->getCharacters();
|
||||
$characters = $this->getActiveCharacters();
|
||||
|
||||
foreach($characters as $character){
|
||||
$charactersData[] = $character->getData(true);
|
||||
@@ -484,7 +505,7 @@ class MapModel extends BasicModel {
|
||||
|
||||
// cache active characters (if found)
|
||||
if(!empty($charactersData)){
|
||||
$this->updateCacheData($charactersData, 'CHARACTERS', 10);
|
||||
$this->updateCacheData($charactersData, 'CHARACTERS', 5);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -531,19 +552,15 @@ class MapModel extends BasicModel {
|
||||
return $alliances;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* delete this map and all dependencies
|
||||
* @param $accessObject
|
||||
* @param CharacterModel $characterModel
|
||||
*/
|
||||
public function delete($accessObject){
|
||||
|
||||
if(!$this->dry()){
|
||||
// check if editor has access
|
||||
if($this->hasAccess($accessObject)){
|
||||
public function delete(CharacterModel $characterModel){
|
||||
if( !$this->dry() ){
|
||||
// check if character has access
|
||||
if($this->hasAccess($characterModel)){
|
||||
// all map related tables will be deleted on cascade
|
||||
|
||||
// delete map
|
||||
$this->erase();
|
||||
}
|
||||
}
|
||||
@@ -656,9 +673,9 @@ class MapModel extends BasicModel {
|
||||
if( $mapModel->isPrivate() ){
|
||||
$mapModel->clearAccess(['corporation', 'alliance']);
|
||||
}elseif( $mapModel->isCorporation() ){
|
||||
$mapModel->clearAccess(['user', 'alliance']);
|
||||
$mapModel->clearAccess(['character', 'alliance']);
|
||||
}elseif( $mapModel->isAlliance() ){
|
||||
$mapModel->clearAccess(['user', 'corporation']);
|
||||
$mapModel->clearAccess(['character', 'corporation']);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: exodus4d
|
||||
* Date: 29.08.15
|
||||
* Time: 11:57
|
||||
*/
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class RegistrationKeyModel extends BasicModel {
|
||||
|
||||
protected $table = 'registration_key';
|
||||
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => 1,
|
||||
'index' => true
|
||||
],
|
||||
'ip' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'used' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => 0
|
||||
],
|
||||
'email' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => '',
|
||||
'index' => true
|
||||
],
|
||||
'registrationKey' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => '',
|
||||
'index' => true,
|
||||
'unique' => true
|
||||
]
|
||||
];
|
||||
|
||||
}
|
||||
@@ -177,18 +177,18 @@ class SystemModel extends BasicModel {
|
||||
}else{
|
||||
// special array data
|
||||
if($key == 'constellation'){
|
||||
$this->constellationId = $value['id'];
|
||||
$this->constellationId = (int)$value['id'];
|
||||
$this->constellation = $value['name'];
|
||||
}elseif($key == 'region'){
|
||||
$this->regionId = $value['id'];
|
||||
$this->regionId = (int)$value['id'];
|
||||
$this->region = $value['name'];
|
||||
}elseif($key == 'type'){
|
||||
$this->typeId = $value['id'];
|
||||
$this->typeId = (int)$value['id'];
|
||||
}elseif($key == 'status'){
|
||||
$this->statusId = $value['id'];
|
||||
$this->statusId = (int)$value['id'];
|
||||
}elseif($key == 'position'){
|
||||
$this->posX = $value['x'];
|
||||
$this->posY = $value['y'];
|
||||
$this->posX = (int)$value['x'];
|
||||
$this->posY = (int)$value['y'];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -313,23 +313,22 @@ class SystemModel extends BasicModel {
|
||||
|
||||
/**
|
||||
* check object for model access
|
||||
* @param $accessObject
|
||||
* @return bool
|
||||
* @param CharacterModel $characterModel
|
||||
* @return mixed
|
||||
*/
|
||||
public function hasAccess($accessObject){
|
||||
return $this->mapId->hasAccess($accessObject);
|
||||
public function hasAccess(CharacterModel $characterModel){
|
||||
return $this->mapId->hasAccess($characterModel);
|
||||
}
|
||||
|
||||
/**
|
||||
* delete a system from a map
|
||||
* hint: signatures and connections will be deleted on cascade
|
||||
* @param $accessObject
|
||||
* @param CharacterModel $characterModel
|
||||
*/
|
||||
public function delete($accessObject){
|
||||
|
||||
if(! $this->dry()){
|
||||
// check if user has access
|
||||
if($this->hasAccess($accessObject)){
|
||||
public function delete(CharacterModel $characterModel){
|
||||
if( !$this->dry() ){
|
||||
// check if character has access
|
||||
if($this->hasAccess($characterModel)){
|
||||
$this->erase();
|
||||
}
|
||||
}
|
||||
@@ -367,14 +366,14 @@ class SystemModel extends BasicModel {
|
||||
|
||||
/**
|
||||
* get Signature by id and check for access
|
||||
* @param $accessObject
|
||||
* @param CharacterModel $characterModel
|
||||
* @param $id
|
||||
* @return bool|null
|
||||
*/
|
||||
public function getSignatureById($accessObject, $id){
|
||||
public function getSignatureById(CharacterModel $characterModel, $id){
|
||||
$signature = null;
|
||||
|
||||
if($this->hasAccess($accessObject)){
|
||||
if($this->hasAccess($characterModel)){
|
||||
$this->filter('signatures', ['active = ? AND id = ?', 1, $id]);
|
||||
if($this->signatures){
|
||||
$signature = reset( $this->signatures );
|
||||
@@ -386,14 +385,14 @@ class SystemModel extends BasicModel {
|
||||
|
||||
/**
|
||||
* get a signature by its "unique" 3-digit name
|
||||
* @param $accessObject
|
||||
* @param CharacterModel $characterModel
|
||||
* @param $name
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function getSignatureByName($accessObject, $name){
|
||||
public function getSignatureByName(CharacterModel $characterModel, $name){
|
||||
$signature = null;
|
||||
|
||||
if($this->hasAccess($accessObject)){
|
||||
if($this->hasAccess($characterModel)){
|
||||
$this->filter('signatures', ['active = ? AND name = ?', 1, $name]);
|
||||
if($this->signatures){
|
||||
$signature = reset( $this->signatures );
|
||||
|
||||
@@ -151,18 +151,21 @@ class SystemSignatureModel extends BasicModel {
|
||||
|
||||
/**
|
||||
* check object for model access
|
||||
* @param $accessObject
|
||||
* @param CharacterModel $characterModel
|
||||
* @return bool
|
||||
*/
|
||||
public function hasAccess($accessObject){
|
||||
return $this->systemId->hasAccess($accessObject);
|
||||
public function hasAccess(CharacterModel $characterModel){
|
||||
return $this->systemId->hasAccess($characterModel);
|
||||
}
|
||||
|
||||
public function delete($accessObject){
|
||||
|
||||
if(!$this->dry()){
|
||||
// check if editor has access
|
||||
if($this->hasAccess($accessObject)){
|
||||
/**
|
||||
* delete signature
|
||||
* @param CharacterModel $characterModel
|
||||
*/
|
||||
public function delete(CharacterModel $characterModel){
|
||||
if( !$this->dry() ){
|
||||
// check if character has access
|
||||
if($this->hasAccess($characterModel)){
|
||||
$this->erase();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,152 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: exodus4d
|
||||
* Date: 28.03.15
|
||||
* Time: 16:41
|
||||
*/
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
use Controller;
|
||||
|
||||
class UserApiModel extends BasicModel {
|
||||
|
||||
protected $table = 'user_api';
|
||||
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => 1,
|
||||
'index' => true
|
||||
],
|
||||
'userId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\UserModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'user',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
],
|
||||
'keyId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'unique' => true
|
||||
],
|
||||
'vCode' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => '',
|
||||
],
|
||||
'userCharacters' => [
|
||||
'has-many' => ['Model\UserCharacterModel', 'apiId']
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
* get all data for this api
|
||||
* @return object
|
||||
*/
|
||||
public function getData(){
|
||||
$apiData = (object) [];
|
||||
$apiData->keyId = $this->keyId;
|
||||
$apiData->vCode = $this->vCode;
|
||||
|
||||
return $apiData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function updateCharacters(){
|
||||
$apiController = new Controller\CcpApiController();
|
||||
|
||||
return $apiController->updateCharacters($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* get all characters for this API
|
||||
* @return array|mixed
|
||||
*/
|
||||
public function getUserCharacters(){
|
||||
$this->filter('userCharacters', ['active = ?', 1]);
|
||||
|
||||
$userCharacters = [];
|
||||
if($this->userCharacters){
|
||||
$userCharacters = $this->userCharacters;
|
||||
}
|
||||
|
||||
return $userCharacters;
|
||||
}
|
||||
|
||||
/**
|
||||
* search for a user character model by a characterId
|
||||
* @param $characterId
|
||||
* @return null
|
||||
*/
|
||||
public function getUserCharacterById($characterId){
|
||||
$userCharacters = $this->getUserCharacters();
|
||||
$returnUserCharacter = null;
|
||||
|
||||
foreach($userCharacters as $userCharacter){
|
||||
if($userCharacter->characterId->id == $characterId){
|
||||
$returnUserCharacter = $userCharacter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $returnUserCharacter;
|
||||
}
|
||||
|
||||
/**
|
||||
* check if this api model has a main character
|
||||
* @return bool
|
||||
*/
|
||||
public function hasMainCharacter(){
|
||||
$hasMain = false;
|
||||
|
||||
$characters = $this->getUserCharacters();
|
||||
foreach($characters as $character){
|
||||
if($character->isMain()){
|
||||
$hasMain = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $hasMain;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the user object for this model
|
||||
* @return mixed
|
||||
*/
|
||||
public function getUser(){
|
||||
return $this->userId;
|
||||
}
|
||||
|
||||
/**
|
||||
* delete this api model
|
||||
*/
|
||||
public function delete(){
|
||||
|
||||
// check if this api model had a main character
|
||||
$user = $this->userId;
|
||||
$setNewMain = false;
|
||||
|
||||
if($this->hasMainCharacter()){
|
||||
$setNewMain = true;
|
||||
}
|
||||
$this->erase();
|
||||
|
||||
if($setNewMain){
|
||||
$user->setMainCharacterId();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -32,20 +32,10 @@ class UserCharacterModel extends BasicModel {
|
||||
]
|
||||
]
|
||||
],
|
||||
'apiId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\UserApiModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'user_api',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
],
|
||||
'characterId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'unique' => true,
|
||||
'belongs-to-one' => 'Model\CharacterModel',
|
||||
'constraint' => [
|
||||
[
|
||||
@@ -53,12 +43,6 @@ class UserCharacterModel extends BasicModel {
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
],
|
||||
'isMain' => [
|
||||
'type' => Schema::DT_BOOLEAN,
|
||||
'nullable' => false,
|
||||
'default' => 0,
|
||||
'index' => true
|
||||
]
|
||||
];
|
||||
|
||||
@@ -67,9 +51,7 @@ class UserCharacterModel extends BasicModel {
|
||||
* @param $characterData
|
||||
*/
|
||||
public function setData($characterData){
|
||||
|
||||
foreach((array)$characterData as $key => $value){
|
||||
|
||||
if(!is_array($value)){
|
||||
if($this->exists($key)){
|
||||
$this->$key = $value;
|
||||
@@ -79,52 +61,19 @@ class UserCharacterModel extends BasicModel {
|
||||
}
|
||||
|
||||
/**
|
||||
* get all character data
|
||||
* @param $addCharacterLogData
|
||||
* @return array
|
||||
*/
|
||||
public function getData($addCharacterLogData = false){
|
||||
|
||||
// get characterModel
|
||||
$characterModel = $this->getCharacter();
|
||||
|
||||
// get static character data
|
||||
$characterData = $characterModel->getData($addCharacterLogData);
|
||||
|
||||
// add user specific character data
|
||||
$characterData->isMain = $this->isMain;
|
||||
|
||||
// check for corporation
|
||||
if( is_object( $characterModel->corporationId ) ){
|
||||
$characterData->corporation = $characterModel->corporationId->getData();
|
||||
}
|
||||
|
||||
// check for alliance
|
||||
if( is_object( $characterModel->allianceId ) ){
|
||||
$characterData->alliance = $characterModel->allianceId->getData();
|
||||
}
|
||||
|
||||
return $characterData;
|
||||
}
|
||||
|
||||
/**
|
||||
* check if this character is Main character or not
|
||||
* event "Hook"
|
||||
* -> remove user if there are no other characters bound to this user
|
||||
* @param $self
|
||||
* @return bool
|
||||
*/
|
||||
public function isMain(){
|
||||
$isMain = false;
|
||||
if($this->isMain == 1){
|
||||
$isMain = true;
|
||||
public function aftereraseEvent($self){
|
||||
if(
|
||||
is_object($self->userId) &&
|
||||
is_null($self->userId->userCharacters)
|
||||
){
|
||||
$self->userId->erase();
|
||||
}
|
||||
|
||||
return $isMain;
|
||||
}
|
||||
|
||||
/**
|
||||
* set this character as main character
|
||||
*/
|
||||
public function setMain($value = 0){
|
||||
$this->isMain = $value;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,10 +95,7 @@ class UserCharacterModel extends BasicModel {
|
||||
$status = parent::setup($db,$table,$fields);
|
||||
|
||||
if($status === true){
|
||||
$status = parent::setMultiColumnIndex(['userId', 'apiId', 'characterId'], true);
|
||||
if($status === true){
|
||||
$status = parent::setMultiColumnIndex(['userId', 'apiId']);
|
||||
}
|
||||
$status = parent::setMultiColumnIndex(['userId', 'characterId'], true);
|
||||
}
|
||||
|
||||
return $status;
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
use Controller;
|
||||
use Controller\Api;
|
||||
use Exception;
|
||||
|
||||
class UserModel extends BasicModel {
|
||||
@@ -17,10 +18,6 @@ class UserModel extends BasicModel {
|
||||
protected $table = 'user';
|
||||
|
||||
protected $fieldConf = [
|
||||
'lastLogin' => [
|
||||
'type' => Schema::DT_TIMESTAMP,
|
||||
'index' => true
|
||||
],
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
@@ -31,34 +28,15 @@ class UserModel extends BasicModel {
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => '',
|
||||
'index' => true,
|
||||
'unique' => true
|
||||
'index' => true
|
||||
],
|
||||
'email' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => '',
|
||||
'index' => true,
|
||||
'unique' => true
|
||||
],
|
||||
'password' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'shared' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => 0
|
||||
],
|
||||
'apis' => [
|
||||
'has-many' => ['Model\UserApiModel', 'userId']
|
||||
],
|
||||
'userCharacters' => [
|
||||
'has-many' => ['Model\UserCharacterModel', 'userId']
|
||||
],
|
||||
'userMaps' => [
|
||||
'has-many' => ['Model\UserMapModel', 'userId']
|
||||
]
|
||||
];
|
||||
|
||||
@@ -68,24 +46,14 @@ class UserModel extends BasicModel {
|
||||
'min' => 5,
|
||||
'max' => 25
|
||||
]
|
||||
],
|
||||
'email' => [
|
||||
'length' => [
|
||||
'min' => 5
|
||||
]
|
||||
],
|
||||
'password' => [
|
||||
'length' => [
|
||||
'min' => 6
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
/**
|
||||
* get all data for this user
|
||||
* ! caution ! this function returns sensitive data!
|
||||
* -> ! caution ! this function returns sensitive data! (e.g. email,..)
|
||||
* -> user getSimpleData() for faster performance and public user data
|
||||
* @return object
|
||||
* @return \stdClass
|
||||
*/
|
||||
public function getData(){
|
||||
|
||||
@@ -95,27 +63,19 @@ class UserModel extends BasicModel {
|
||||
// add sensitive user data
|
||||
$userData->email = $this->email;
|
||||
|
||||
// user shared info
|
||||
$userData->shared = $this->shared;
|
||||
|
||||
// api data
|
||||
$APIs = $this->getAPIs();
|
||||
foreach($APIs as $api){
|
||||
$userData->api[] = $api->getData();
|
||||
}
|
||||
|
||||
// all chars
|
||||
$userData->characters = [];
|
||||
$userCharacters = $this->getUserCharacters();
|
||||
foreach($userCharacters as $userCharacter){
|
||||
$userData->characters[] = $userCharacter->getData();
|
||||
$characters = $this->getCharacters();
|
||||
foreach($characters as $character){
|
||||
/**
|
||||
* @var $character CharacterModel
|
||||
*/
|
||||
$userData->characters[] = $character->getData();
|
||||
}
|
||||
|
||||
// set active character with log data
|
||||
$activeUserCharacter = $this->getActiveUserCharacter();
|
||||
if($activeUserCharacter){
|
||||
$userData->character = $activeUserCharacter->getData(true);
|
||||
}
|
||||
// get active character with log data
|
||||
$activeCharacter = $this->getActiveCharacter();
|
||||
$userData->character = $activeCharacter->getData(true);
|
||||
|
||||
return $userData;
|
||||
}
|
||||
@@ -123,7 +83,7 @@ class UserModel extends BasicModel {
|
||||
/**
|
||||
* get public user data
|
||||
* - check out getData() for all user data
|
||||
* @return object
|
||||
* @return \stdClass
|
||||
*/
|
||||
public function getSimpleData(){
|
||||
$userData = (object) [];
|
||||
@@ -135,31 +95,21 @@ class UserModel extends BasicModel {
|
||||
|
||||
/**
|
||||
* validate and set a email address for this user
|
||||
* @param $email
|
||||
* @return mixed
|
||||
* -> empty email is allowed!
|
||||
* @param string $email
|
||||
* @return string
|
||||
*/
|
||||
public function set_email($email){
|
||||
if (\Audit::instance()->email($email) == false) {
|
||||
if (
|
||||
!empty($email) &&
|
||||
\Audit::instance()->email($email) == false
|
||||
) {
|
||||
// no valid email address
|
||||
$this->throwValidationError('email');
|
||||
}
|
||||
return $email;
|
||||
}
|
||||
|
||||
/**
|
||||
* set a password hash for this user
|
||||
* @param $password
|
||||
* @return FALSE|string
|
||||
*/
|
||||
public function set_password($password){
|
||||
if(strlen($password) < 6){
|
||||
$this->throwValidationError('password');
|
||||
}
|
||||
|
||||
$salt = uniqid('', true);
|
||||
return \Bcrypt::instance()->hash($password, $salt);
|
||||
}
|
||||
|
||||
/**
|
||||
* check if new user registration is allowed
|
||||
* @return bool
|
||||
@@ -191,366 +141,89 @@ class UserModel extends BasicModel {
|
||||
return $this->getByForeignKey('name', $name, [], 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* verify a user by his password
|
||||
* @param $password
|
||||
* @return bool
|
||||
*/
|
||||
public function verify($password){
|
||||
$valid = false;
|
||||
|
||||
if(! $this->dry()){
|
||||
$valid = (bool) \Bcrypt::instance()->verify($password, $this->password);
|
||||
}
|
||||
|
||||
return $valid;
|
||||
}
|
||||
|
||||
/**
|
||||
* get all accessible map models for this user
|
||||
* @return array
|
||||
*/
|
||||
public function getMaps(){
|
||||
$f3 = self::getF3();
|
||||
|
||||
$this->filter(
|
||||
'userMaps',
|
||||
['active = ?', 1],
|
||||
['order' => 'created']
|
||||
);
|
||||
|
||||
$maps = [];
|
||||
if($this->userMaps){
|
||||
$mapCountPrivate = 0;
|
||||
foreach($this->userMaps as $userMap){
|
||||
if(
|
||||
$userMap->mapId->isActive() &&
|
||||
$mapCountPrivate < $f3->get('PATHFINDER.MAX_MAPS_PRIVATE')
|
||||
){
|
||||
$maps[] = $userMap->mapId;
|
||||
$mapCountPrivate++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$activeUserCharacter = $this->getActiveUserCharacter();
|
||||
|
||||
if($activeUserCharacter){
|
||||
$character = $activeUserCharacter->getCharacter();
|
||||
$corporation = $character->getCorporation();
|
||||
$alliance = $character->getAlliance();
|
||||
|
||||
if($alliance){
|
||||
$allianceMaps = $alliance->getMaps();
|
||||
$maps = array_merge($maps, $allianceMaps);
|
||||
}
|
||||
|
||||
if($corporation){
|
||||
$corporationMaps = $corporation->getMaps();
|
||||
$maps = array_merge($maps, $corporationMaps);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return $maps;
|
||||
}
|
||||
|
||||
/**
|
||||
* get mapModel by id and check if user has access
|
||||
* @param $mapId
|
||||
* @return null
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function getMap($mapId){
|
||||
$map = self::getNew('MapModel');
|
||||
$map->getById( (int)$mapId );
|
||||
|
||||
$returnMap = null;
|
||||
if($map->hasAccess($this)){
|
||||
$returnMap = $map;
|
||||
}
|
||||
|
||||
return $returnMap;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get all API models for this user
|
||||
* @return array|mixed
|
||||
*/
|
||||
public function getAPIs(){
|
||||
$this->filter('apis', ['active = ?', 1]);
|
||||
|
||||
$apis = [];
|
||||
if($this->apis){
|
||||
$apis = $this->apis;
|
||||
}
|
||||
|
||||
return $apis;
|
||||
}
|
||||
|
||||
/**
|
||||
* set main character ID for this user.
|
||||
* If id does not match with his API chars -> select "random" main character
|
||||
* @param int $characterId
|
||||
*/
|
||||
public function setMainCharacterId($characterId = 0){
|
||||
|
||||
if(is_int($characterId)){
|
||||
$userCharacters = $this->getUserCharacters();
|
||||
|
||||
if(count($userCharacters) > 0){
|
||||
$mainSet = false;
|
||||
foreach($userCharacters as $userCharacter){
|
||||
if($characterId == $userCharacter->getCharacter()->id){
|
||||
$mainSet = true;
|
||||
$userCharacter->setMain(1);
|
||||
}else{
|
||||
$userCharacter->setMain(0);
|
||||
}
|
||||
$userCharacter->save();
|
||||
}
|
||||
|
||||
// set first character as "main"
|
||||
if( !$mainSet ){
|
||||
$userCharacter = reset($userCharacters);
|
||||
$userCharacter->setMain(1);
|
||||
$userCharacter->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get all userCharacters models for a user
|
||||
* characters will be checked/updated on login by CCP API call
|
||||
* @return array|mixed
|
||||
* @return UserCharacterModel[]
|
||||
*/
|
||||
public function getUserCharacters(){
|
||||
$this->filter('userCharacters', ['active = ?', 1]);
|
||||
|
||||
$this->filter('apis', ['active = ?', 1]);
|
||||
|
||||
// if a user has multiple API keys saved for ONE character,
|
||||
// skip double characters!
|
||||
$userCharacters = [];
|
||||
|
||||
if($this->apis){
|
||||
$this->apis->rewind();
|
||||
while($this->apis->valid()){
|
||||
|
||||
$this->apis->current()->filter('userCharacters', ['active = ?', 1]);
|
||||
|
||||
if($this->apis->current()->userCharacters){
|
||||
$this->apis->current()->userCharacters->rewind();
|
||||
while($this->apis->current()->userCharacters->valid()){
|
||||
|
||||
$tempCharacterId = $this->apis->current()->userCharacters->current()->characterId->get('id');
|
||||
if( !isset($userCharacters[ $tempCharacterId ]) ){
|
||||
$userCharacters[ $tempCharacterId ] = $this->apis->current()->userCharacters->current();
|
||||
}
|
||||
$this->apis->current()->userCharacters->next();
|
||||
}
|
||||
}
|
||||
$this->apis->next();
|
||||
}
|
||||
if($this->userCharacters){
|
||||
$userCharacters = $this->userCharacters;
|
||||
}
|
||||
|
||||
return $userCharacters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the main user character for this user
|
||||
* @return null
|
||||
* get the current active character for this user
|
||||
* -> EITHER - the current active one for the current user
|
||||
* -> OR - get the first active one
|
||||
* @return null|CharacterModel
|
||||
*/
|
||||
public function getMainUserCharacter(){
|
||||
$mainUserCharacter = null;
|
||||
public function getActiveCharacter(){
|
||||
$activeCharacter = null;
|
||||
$controller = new Controller\Controller();
|
||||
$currentActiveCharacter = $controller->getCharacter();
|
||||
|
||||
if(
|
||||
!is_null($currentActiveCharacter) &&
|
||||
$currentActiveCharacter->getUser()->_id === $this->id
|
||||
){
|
||||
$activeCharacter = &$currentActiveCharacter;
|
||||
}else{
|
||||
// set "first" found as active for this user
|
||||
if($activeCharacters = $this->getActiveCharacters()){
|
||||
$activeCharacter = $activeCharacters[0];
|
||||
}
|
||||
}
|
||||
|
||||
return $activeCharacter;
|
||||
}
|
||||
|
||||
/**
|
||||
* get all characters for this user
|
||||
* @return CharacterModel[]
|
||||
*/
|
||||
public function getCharacters(){
|
||||
$userCharacters = $this->getUserCharacters();
|
||||
|
||||
$characters = [];
|
||||
foreach($userCharacters as $userCharacter){
|
||||
if($userCharacter->isMain()){
|
||||
$mainUserCharacter = $userCharacter;
|
||||
break;
|
||||
/**
|
||||
* @var $userCharacter UserCharacterModel
|
||||
*/
|
||||
if( $currentCharacter = $userCharacter->getCharacter() ){
|
||||
// check if userCharacter has a valid character
|
||||
// -> this should never fail!
|
||||
$characters[] = $currentCharacter;
|
||||
}
|
||||
}
|
||||
|
||||
return $mainUserCharacter;
|
||||
return $characters;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the active user character for this user
|
||||
* either there is an active Character (IGB) or the character labeled as "main"
|
||||
* @return null
|
||||
*/
|
||||
public function getActiveUserCharacter(){
|
||||
$activeUserCharacter = null;
|
||||
|
||||
$headerData = Controller\CcpApiController::getIGBHeaderData();
|
||||
|
||||
// check if IGB Data is available
|
||||
if( !empty($headerData->values) ){
|
||||
// search for the active character by IGB Header Data
|
||||
|
||||
$this->filter('userCharacters',
|
||||
[
|
||||
'active = :active AND characterId = :characterId',
|
||||
':active' => 1,
|
||||
':characterId' => intval($headerData->values['charid'])
|
||||
],
|
||||
['limit' => 1]
|
||||
);
|
||||
|
||||
if($this->userCharacters){
|
||||
// check if userCharacter has active log
|
||||
$userCharacter = current($this->userCharacters);
|
||||
|
||||
if( $userCharacter->getCharacter()->getLog() ){
|
||||
$activeUserCharacter = $userCharacter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if no active character is found
|
||||
// e.g. not online in IGB
|
||||
// -> get main Character
|
||||
if(is_null($activeUserCharacter)){
|
||||
$activeUserCharacter = $this->getMainUserCharacter();
|
||||
}
|
||||
|
||||
return $activeUserCharacter;
|
||||
}
|
||||
|
||||
/**
|
||||
* get all active user characters (with log entry)
|
||||
* get all active characters (with log entry)
|
||||
* hint: a user can have multiple active characters
|
||||
* @return array
|
||||
* @return CharacterModel[]
|
||||
*/
|
||||
public function getActiveUserCharacters(){
|
||||
public function getActiveCharacters(){
|
||||
$userCharacters = $this->getUserCharacters();
|
||||
|
||||
$activeUserCharacters = [];
|
||||
$activeCharacters = [];
|
||||
foreach($userCharacters as $userCharacter){
|
||||
$characterLog = $userCharacter->getCharacter()->getLog();
|
||||
|
||||
if($characterLog){
|
||||
$activeUserCharacters[] = $userCharacter;
|
||||
/**
|
||||
* @var $userCharacter UserCharacterModel
|
||||
*/
|
||||
$characterModel = $userCharacter->getCharacter();
|
||||
if($characterLog = $characterModel->getLog()){
|
||||
$activeCharacters[] = $characterModel;
|
||||
}
|
||||
}
|
||||
|
||||
return $activeUserCharacters;
|
||||
return $activeCharacters;
|
||||
}
|
||||
|
||||
/**
|
||||
* update/check API information.
|
||||
* request API information from CCP
|
||||
*/
|
||||
public function updateApiData(){
|
||||
$this->filter('apis', ['active = ?', 1]);
|
||||
|
||||
if($this->apis){
|
||||
$this->apis->rewind();
|
||||
while($this->apis->valid()){
|
||||
$this->apis->current()->updateCharacters();
|
||||
$this->apis->next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* updated the character log entry for a user character by IGB Header data
|
||||
* @param int $ttl cache time in seconds
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function updateCharacterLog($ttl = 0){
|
||||
$headerData = Controller\CcpApiController::getIGBHeaderData();
|
||||
|
||||
// check if IGB Data is available
|
||||
if( !empty($headerData->values) ){
|
||||
$f3 = self::getF3();
|
||||
|
||||
// check if system has changed since the last call
|
||||
// current location is stored (global) to avoid unnecessary DB calls
|
||||
$sessionCharacterKey = 'LOGGED.user.character.id_' . $headerData->values['charid'];
|
||||
|
||||
if($f3->exists($sessionCharacterKey)){
|
||||
// cache data exists
|
||||
$cacheData = $f3->get($sessionCharacterKey);
|
||||
}else{
|
||||
// new cache data
|
||||
$cacheData = [
|
||||
'systemId' => 0,
|
||||
'shipId' => 0
|
||||
];
|
||||
}
|
||||
|
||||
if(
|
||||
$cacheData['systemId'] != $headerData->values['solarsystemid'] ||
|
||||
$cacheData['shipId'] != $headerData->values['shiptypeid']
|
||||
){
|
||||
$cacheData['systemId'] = (int)$headerData->values['solarsystemid'];
|
||||
$cacheData['shipId'] = (int)$headerData->values['shiptypeid'];
|
||||
|
||||
// character has changed system, or character just logged on
|
||||
$character = self::getNew('CharacterModel');
|
||||
$character->getById( (int)$headerData->values['charid'] );
|
||||
|
||||
if( $character->dry() ){
|
||||
// this can happen if a valid user plays the game with a not registered character
|
||||
// whose API is not registered -> save new character or update character data
|
||||
$corporationId = array_key_exists('corpid', $headerData->values) ? $headerData->values['corpid'] : null;
|
||||
$allianceId = array_key_exists('allianceid', $headerData->values) ? $headerData->values['allianceid'] : null;
|
||||
|
||||
// check if corp exists
|
||||
if( !is_null($corporationId) ){
|
||||
$corporation = self::getNew('CorporationModel');
|
||||
$corporation->getById( (int)$corporationId );
|
||||
if( $corporation->dry() ){
|
||||
$corporation->id = $corporationId;
|
||||
$corporation->name = $headerData->values['corpname'];
|
||||
$corporation->save();
|
||||
}
|
||||
}
|
||||
|
||||
// check if ally exists
|
||||
if( !is_null($allianceId) ){
|
||||
$alliance = self::getNew('AllianceModel');
|
||||
$alliance->getById( (int)$allianceId );
|
||||
if( $alliance->dry() ){
|
||||
$alliance->id = $allianceId;
|
||||
$alliance->name = $headerData->values['alliancename'];
|
||||
$alliance->save();
|
||||
}
|
||||
}
|
||||
|
||||
$character->id = (int) $headerData->values['charid'];
|
||||
$character->name = $headerData->values['charname'];
|
||||
$character->corporationId = $corporationId;
|
||||
$character->allianceId = $allianceId;
|
||||
$character->save();
|
||||
}
|
||||
|
||||
// check if this character has an active log
|
||||
if( !$characterLog = $character->getLog() ){
|
||||
$characterLog = self::getNew('CharacterLogModel');
|
||||
}
|
||||
|
||||
// set character log values
|
||||
$characterLog->characterId = $character;
|
||||
$characterLog->systemId = (int)$headerData->values['solarsystemid'];
|
||||
$characterLog->systemName = $headerData->values['solarsystemname'];
|
||||
$characterLog->shipId = (int)$headerData->values['shiptypeid'];
|
||||
$characterLog->shipName = $headerData->values['shipname'];
|
||||
$characterLog->shipTypeName = $headerData->values['shiptypename'];
|
||||
|
||||
$characterLog->save();
|
||||
|
||||
// clear cache for the characterModel as well
|
||||
$character->clearCacheData();
|
||||
|
||||
// cache character log information
|
||||
$f3->set($sessionCharacterKey, $cacheData, $ttl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
[PATHFINDER]
|
||||
NAME = PATHFINDER
|
||||
; installed version (used for CSS/JS cache busting)
|
||||
VERSION = v1.0.0RC2
|
||||
VERSION = v1.0.0RC3
|
||||
; contact information (DO NOT CHANGE)
|
||||
CONTACT = https://github.com/exodus4d
|
||||
; source code (DO NOT CHANGE)
|
||||
@@ -15,7 +15,7 @@ MAX_MAPS_CORPORATION = 3
|
||||
MAX_MAPS_ALLIANCE = 3
|
||||
|
||||
; Max number of shared entities per map
|
||||
MAX_SHARED_USER = 10
|
||||
MAX_SHARED_CHARACTER = 10
|
||||
MAX_SHARED_CORPORATION = 3
|
||||
MAX_SHARED_ALLIANCE = 2
|
||||
|
||||
@@ -34,6 +34,11 @@ INVITE = 0
|
||||
; the limit of registration keys. Increase it to hand out more keys
|
||||
INVITE_LIMIT = 50
|
||||
|
||||
[PATHFINDER.LOGIN]
|
||||
; restrict login to specific corporations/alliances by id (e.g. 1000166,1000080)
|
||||
CORPORATION =
|
||||
ALLIANCE =
|
||||
|
||||
; View ============================================================================================
|
||||
[PATHFINDER.VIEW]
|
||||
; static page templates
|
||||
@@ -78,7 +83,7 @@ EXECUTION_LIMIT = 50
|
||||
; map user update ping (ajax) (ms)
|
||||
[PATHFINDER.TIMER.UPDATE_SERVER_USER_DATA]
|
||||
DELAY = 5000
|
||||
EXECUTION_LIMIT = 200
|
||||
EXECUTION_LIMIT = 300
|
||||
|
||||
; update client user data (ms)
|
||||
[PATHFINDER.TIMER.UPDATE_CLIENT_USER_DATA]
|
||||
@@ -102,11 +107,6 @@ DELETE_ACCOUNT = delete_account
|
||||
|
||||
; API =============================================================================================
|
||||
[PATHFINDER.API]
|
||||
; CCP SSO OAuth 2.0
|
||||
CCP_SSO = https://login.eveonline.com
|
||||
; CCP CREST API
|
||||
CCP_CREST = https://crest-tq.eveonline.com
|
||||
; CCP_CREST = https://api-sisi.testeveonline.com
|
||||
; CCP XML APIv2
|
||||
CCP_XML = https://api.eveonline.com
|
||||
; GitHub Developer API
|
||||
|
||||
@@ -3,16 +3,15 @@
|
||||
[routes]
|
||||
; DB setup setup
|
||||
; IMPORTANT: remove/comment this line after setup/update is finished!
|
||||
GET @setup: /setup = Controller\Setup->init, 0
|
||||
GET @setup: /setup [sync] = Controller\Setup->init, 0
|
||||
; login (index) page
|
||||
GET @login: / = Controller\AppController->init, 0
|
||||
GET @login: / [sync] = Controller\AppController->init, 0
|
||||
; CCP SSO redirect
|
||||
GET @sso: /sso/@action = Controller\CcpSsoController->@action, 0
|
||||
|
||||
GET @sso: /sso/@action [sync] = Controller\Ccp\Sso->@action, 0
|
||||
; map page
|
||||
GET @map: /map = Controller\MapController->init, 0
|
||||
GET @map: /map [sync] = Controller\MapController->init, 0
|
||||
|
||||
; ajax wildcard APIs (throttled)
|
||||
GET|POST /api/@controller/@action [ajax] = Controller\Api\@controller->@action, 0, 512
|
||||
GET|POST /api/@controller/@action/@arg1 [ajax] = Controller\Api\@controller->@action, 0, 512
|
||||
GET|POST /api/@controller/@action/@arg1/@arg2 [ajax] = Controller\Api\@controller->@action, 0, 512
|
||||
GET|POST /api/@controller/@action [ajax] = Controller\Api\@controller->@action, 0, 512
|
||||
GET|POST /api/@controller/@action/@arg1 [ajax] = Controller\Api\@controller->@action, 0, 512
|
||||
GET|POST /api/@controller/@action/@arg1/@arg2 [ajax] = Controller\Api\@controller->@action, 0, 512
|
||||
|
||||
28
gulpfile.js
28
gulpfile.js
@@ -6,7 +6,6 @@ var plumber = require('gulp-plumber');
|
||||
var gzip = require('gulp-gzip');
|
||||
var gulpif = require('gulp-if');
|
||||
var clean = require('gulp-clean');
|
||||
var critical = require('critical');
|
||||
|
||||
var runSequence = require('run-sequence');
|
||||
var exec = require('child_process').exec;
|
||||
@@ -91,13 +90,7 @@ gulp.task('jshint', function(){
|
||||
errorHandler: onError
|
||||
}))
|
||||
.pipe(jshint())
|
||||
.pipe(jshint.reporter(stylish))
|
||||
.pipe(notify({
|
||||
icon: path.resolve(__dirname, _src.ICON),
|
||||
title: 'JSHint',
|
||||
message: 'Task complete',
|
||||
onLast: true
|
||||
}));
|
||||
.pipe(jshint.reporter(stylish));
|
||||
// .pipe(jshint.reporter('fail')); // uncomment this line to stop build on error
|
||||
});
|
||||
|
||||
@@ -247,25 +240,6 @@ gulp.task('default', function(tag) {
|
||||
);
|
||||
});
|
||||
|
||||
/*
|
||||
// This removes all CSS styles "above the fold" from *.css and inlines them
|
||||
// -> to improve pagespeed. The remaining (main) css file will be lazy loaded afterwards...
|
||||
// https://github.com/addyosmani/critical
|
||||
gulp.task('critical', function (cb) {
|
||||
critical.generate({
|
||||
inline: true,
|
||||
base: './',
|
||||
src: './public/templates/view/index.html',
|
||||
dest: './public/templates/view/index-critical.html',
|
||||
extract: true,
|
||||
minify: true,
|
||||
width: 2560,
|
||||
height: 1440
|
||||
});
|
||||
});
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* clear all backend (fat free framework) cache files
|
||||
*/
|
||||
|
||||
@@ -45,7 +45,7 @@ requirejs.config({
|
||||
hoverIntent: 'lib/jquery.hoverIntent.minified', // v1.8.0 Hover intention - http://cherne.net/brian/resources/jquery.hoverIntent.html
|
||||
fullScreen: 'lib/jquery.fullscreen.min', // v0.5.0 Full screen mode - https://github.com/private-face/jquery.fullscreen
|
||||
select2: 'lib/select2.min', // v4.0.0 Drop Down customization - https://select2.github.io/
|
||||
validator: 'lib/validator.min', // v0.7.2 Validator for Bootstrap 3 - https://github.com/1000hz/bootstrap-validator
|
||||
validator: 'lib/validator.min', // v0.10.1 Validator for Bootstrap 3 - https://github.com/1000hz/bootstrap-validator
|
||||
lazylinepainter: 'lib/jquery.lazylinepainter-1.5.1.min', // v1.5.1 SVG line animation plugin - http://lazylinepainter.info/
|
||||
blueImpGallery: 'lib/blueimp-gallery', // v2.15.2 Image Gallery - https://github.com/blueimp/Gallery/
|
||||
blueImpGalleryHelper: 'lib/blueimp-helper', // helper function for Blue Imp Gallery
|
||||
|
||||
@@ -16,6 +16,7 @@ define(['jquery'], function($) {
|
||||
logOut: 'api/user/logOut', // ajax URL - logout
|
||||
deleteLog: 'api/user/deleteLog', // ajax URL - delete character log
|
||||
saveUserConfig: 'api/user/saveAccount', // ajax URL - saves/update user account
|
||||
getUserData: 'api/user/getData', // ajax URL - get user data
|
||||
saveSharingConfig: 'api/user/saveSharingConfig', // ajax URL - save "sharing settings" dialog
|
||||
deleteAccount: 'api/user/deleteAccount', // ajax URL - delete Account data
|
||||
// access API
|
||||
|
||||
@@ -83,6 +83,7 @@ define([
|
||||
autoWidth: false,
|
||||
hover: false,
|
||||
pageLength: 15,
|
||||
lengthMenu: [[10, 15, 25, 50, 50], [10, 15, 25, 50, 50]],
|
||||
data: logData, // load cached logs (if available)
|
||||
language: {
|
||||
emptyTable: 'No entries',
|
||||
|
||||
@@ -84,54 +84,6 @@ define([
|
||||
});
|
||||
});
|
||||
|
||||
// login buttons ------------------------------------------------
|
||||
var loginForm = $('#' + config.loginFormId);
|
||||
|
||||
loginForm.on('submit', function(e){
|
||||
e.preventDefault();
|
||||
|
||||
var loginFormMessageContainer = $('#' + config.loginMessageContainerId);
|
||||
|
||||
// validate form
|
||||
loginForm.validator('validate');
|
||||
|
||||
// check weather the form is valid
|
||||
var formValid = loginForm.isValidForm();
|
||||
|
||||
if(formValid === true){
|
||||
|
||||
// show splash overlay
|
||||
$('.' + config.splashOverlayClass).showSplashOverlay(function(){
|
||||
|
||||
var loginData = {loginData: loginForm.getFormValues()};
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: Init.path.logIn,
|
||||
data: loginData,
|
||||
dataType: 'json'
|
||||
}).done(function(data){
|
||||
// login error
|
||||
if(data.error !== undefined){
|
||||
$('.' + config.splashOverlayClass).hideSplashOverlay();
|
||||
loginFormMessageContainer.showMessage({title: 'Login failed', text: ' Invalid username or password', type: 'error'});
|
||||
|
||||
}else if(data.reroute !== undefined){
|
||||
window.location = data.reroute;
|
||||
}
|
||||
}).fail(function( jqXHR, status, error) {
|
||||
$('.' + config.splashOverlayClass).hideSplashOverlay();
|
||||
|
||||
var reason = status + ' ' + error;
|
||||
Util.showNotify({title: jqXHR.status + ': login', text: reason, type: 'error'});
|
||||
|
||||
// show Form message
|
||||
loginFormMessageContainer.showMessage({title: 'Login failed', text: ' internal server error', type: 'error'});
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// releases -----------------------------------------------------
|
||||
$('.' + config.navigationVersionLinkClass).on('click', function(e){
|
||||
$.fn.releasesDialog();
|
||||
|
||||
@@ -602,12 +602,12 @@ define([
|
||||
system.attr('data-mapid', parseInt(mapContainer.data('id')));
|
||||
|
||||
// locked system
|
||||
if( Boolean( system.data( 'locked') ) !== Boolean( parseInt( data.locked ) )){
|
||||
if( Boolean( system.data( 'locked') ) !== data.locked ){
|
||||
system.toggleLockSystem(false, {hideNotification: true, hideCounter: true, map: map});
|
||||
}
|
||||
|
||||
// rally system
|
||||
if( Boolean( system.data( 'rally') ) !== Boolean( parseInt( data.rally ) )){
|
||||
if( Boolean( system.data( 'rally') ) !== data.rally ){
|
||||
system.toggleRallyPoint(false, {hideNotification: true, hideCounter: true});
|
||||
}
|
||||
|
||||
@@ -3099,12 +3099,10 @@ define([
|
||||
// this is restricted to IGB-usage! CharacterLog data is always set through the IGB
|
||||
// ->this prevent adding the same system multiple times, if a user is online with IGB AND OOG
|
||||
if(
|
||||
CCP.isInGameBrowser() === true &&
|
||||
currentUserOnMap === false &&
|
||||
currentCharacterLog &&
|
||||
mapTracking
|
||||
){
|
||||
|
||||
// add new system to the map
|
||||
var requestData = {
|
||||
systemData: {
|
||||
@@ -3344,6 +3342,15 @@ define([
|
||||
return data;
|
||||
};
|
||||
|
||||
/**
|
||||
* removes a map instance from local cache
|
||||
* @param mapId
|
||||
*/
|
||||
var clearMapInstance = function(mapId){
|
||||
if(typeof activeInstances[mapId] === 'object'){
|
||||
delete activeInstances[mapId];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* get a new jsPlumb map instance or or get a cached one for update
|
||||
@@ -3583,4 +3590,8 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
clearMapInstance: clearMapInstance
|
||||
};
|
||||
|
||||
});
|
||||
@@ -39,14 +39,26 @@ define([
|
||||
// map init load static data =======================================================
|
||||
$.getJSON( Init.path.initMap, function( initData ) {
|
||||
|
||||
Init.timer = initData.timer;
|
||||
Init.mapTypes = initData.mapTypes;
|
||||
Init.mapScopes = initData.mapScopes;
|
||||
Init.connectionScopes = initData.connectionScopes;
|
||||
Init.systemStatus = initData.systemStatus;
|
||||
Init.systemType = initData.systemType;
|
||||
Init.characterStatus = initData.characterStatus;
|
||||
Init.maxSharedCount = initData.maxSharedCount;
|
||||
|
||||
if( initData.error.length > 0 ){
|
||||
for(var i = 0; i < initData.error.length; i++){
|
||||
Util.showNotify({
|
||||
title: initData.error[i].title,
|
||||
text: initData.error[i].message,
|
||||
type: initData.error[i].type
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Init.timer = initData.timer;
|
||||
Init.mapTypes = initData.mapTypes;
|
||||
Init.mapScopes = initData.mapScopes;
|
||||
Init.connectionScopes = initData.connectionScopes;
|
||||
Init.systemStatus = initData.systemStatus;
|
||||
Init.systemType = initData.systemType;
|
||||
Init.characterStatus = initData.characterStatus;
|
||||
Init.maxSharedCount = initData.maxSharedCount;
|
||||
Init.routes = initData.routes;
|
||||
|
||||
// init tab change observer, Once the timers are available
|
||||
Page.initTabChangeObserver();
|
||||
@@ -168,14 +180,7 @@ define([
|
||||
}
|
||||
}
|
||||
|
||||
}).fail(function( jqXHR, status, error) {
|
||||
|
||||
// clear both main update request trigger timer
|
||||
clearUpdateTimeouts();
|
||||
|
||||
var reason = status + ' ' + jqXHR.status + ': ' + error;
|
||||
$(document).trigger('pf:shutdown', {reason: reason});
|
||||
});
|
||||
}).fail(handleAjaxErrorResponse);
|
||||
};
|
||||
|
||||
// ping for user data update =======================================================
|
||||
@@ -258,14 +263,35 @@ define([
|
||||
}
|
||||
}
|
||||
|
||||
}).fail(function( jqXHR, status, error) {
|
||||
}).fail(handleAjaxErrorResponse);
|
||||
|
||||
// clear both main update request trigger timer
|
||||
clearUpdateTimeouts();
|
||||
};
|
||||
|
||||
var reason = status + ' ' + jqXHR.status + ': ' + error;
|
||||
$(document).trigger('pf:shutdown', {reason: reason});
|
||||
});
|
||||
/**
|
||||
* Ajax error response handler function for main-ping functions
|
||||
* @param jqXHR
|
||||
* @param status
|
||||
* @param error
|
||||
*/
|
||||
var handleAjaxErrorResponse = function(jqXHR, status, error){
|
||||
// clear both main update request trigger timer
|
||||
clearUpdateTimeouts();
|
||||
|
||||
var reason = status + ' ' + jqXHR.status + ': ' + error;
|
||||
var errorData = [];
|
||||
|
||||
if(jqXHR.responseText){
|
||||
var errorObj = $.parseJSON(jqXHR.responseText);
|
||||
|
||||
if(
|
||||
errorObj.error &&
|
||||
errorObj.error.length > 0
|
||||
){
|
||||
errorData = errorObj.error;
|
||||
}
|
||||
}
|
||||
|
||||
$(document).trigger('pf:shutdown', {reason: reason, error: errorData});
|
||||
|
||||
};
|
||||
|
||||
@@ -287,7 +313,6 @@ define([
|
||||
|
||||
};
|
||||
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
@@ -2,6 +2,7 @@ define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util',
|
||||
'app/map/map',
|
||||
'app/counter',
|
||||
'app/ui/system_info',
|
||||
'app/ui/system_graph',
|
||||
@@ -9,9 +10,8 @@ define([
|
||||
'app/ui/system_route',
|
||||
'app/ui/system_killboard',
|
||||
'datatablesTableTools',
|
||||
'datatablesResponsive',
|
||||
'app/map/map'
|
||||
], function($, Init, Util) {
|
||||
'datatablesResponsive'
|
||||
], function($, Init, Util, Map) {
|
||||
|
||||
'use strict';
|
||||
|
||||
@@ -259,6 +259,11 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* get a fresh tab element
|
||||
* @param options
|
||||
* @returns {*|jQuery|HTMLElement}
|
||||
*/
|
||||
var getTabElement = function(options){
|
||||
|
||||
var tabElement = $('<div>', {
|
||||
@@ -395,7 +400,7 @@ define([
|
||||
// update Tab element -> set data
|
||||
linkElement.updateTabData(options);
|
||||
|
||||
// tabs content ====================================
|
||||
// tabs content =======================================================
|
||||
var contentElement = $('<div>', {
|
||||
id: config.mapTabIdPrefix + parseInt( options.id ),
|
||||
class: [config.mapTabContentClass].join(' ')
|
||||
@@ -405,8 +410,7 @@ define([
|
||||
|
||||
tabContent.append(contentElement);
|
||||
|
||||
|
||||
// init tab =========================================================
|
||||
// init tab ===========================================================
|
||||
linkElement.on('click', function(e){
|
||||
e.preventDefault();
|
||||
|
||||
@@ -482,8 +486,11 @@ define([
|
||||
liElement.remove();
|
||||
contentElement.remove();
|
||||
|
||||
// remove map instance from local cache
|
||||
Map.clearMapInstance(mapId);
|
||||
|
||||
if(findNewActiveTab === true){
|
||||
tabElement.find('a:first').tab('show');
|
||||
tabElement.find('.' + config.mapTabClass + ':not(.pull-right):first a').tab('show');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -540,6 +547,9 @@ define([
|
||||
// tab element already exists
|
||||
var tabElements = mapModuleElement.getMapTabElements();
|
||||
|
||||
// map ID that is currently active
|
||||
var activeMapId = 0;
|
||||
|
||||
// mapIds that are currently active
|
||||
var activeMapIds = [];
|
||||
|
||||
@@ -582,6 +592,15 @@ define([
|
||||
|
||||
var newTabElements = tabMapElement.addTab(data.config);
|
||||
|
||||
// check if there is any active map yet (this is not the case
|
||||
// when ALL maps are removed AND new maps are added in one call
|
||||
// e.g. character switch)
|
||||
if(tabMapElement.find('.' + config.mapTabClass + '.active:not(.pull-right)').length === 0){
|
||||
tabMapElement.find('.' + config.mapTabClass + ':not(.pull-right):first a').tab('show');
|
||||
|
||||
activeMapId = data.config.id;
|
||||
}
|
||||
|
||||
// set observer for manually triggered map events
|
||||
newTabElements.contentElement.setTabContentObserver();
|
||||
|
||||
@@ -596,7 +615,9 @@ define([
|
||||
});
|
||||
|
||||
// get current active map
|
||||
var activeMapId = Util.getMapModule().getActiveMap().data('id');
|
||||
if(activeMapId === 0){
|
||||
activeMapId = Util.getMapModule().getActiveMap().data('id');
|
||||
}
|
||||
var activeMapData = Util.getCurrentMapData(activeMapId);
|
||||
|
||||
if(activeMapData !== false){
|
||||
|
||||
@@ -14,7 +14,6 @@ define([
|
||||
'text!templates/modules/footer.html',
|
||||
'dialog/notification',
|
||||
'dialog/trust',
|
||||
'dialog/sharing_settings',
|
||||
'dialog/map_info',
|
||||
'dialog/account_settings',
|
||||
'dialog/manual',
|
||||
@@ -143,13 +142,13 @@ define([
|
||||
$('<a>', {
|
||||
class: 'list-group-item',
|
||||
href: '#'
|
||||
}).html(' Sharing settings').prepend(
|
||||
}).html(' Settings').prepend(
|
||||
$('<i>',{
|
||||
class: 'fa fa-share-alt fa-fw'
|
||||
class: 'fa fa-gears fa-fw'
|
||||
})
|
||||
).on('click', function(){
|
||||
$(document).triggerMenuEvent('ShowSharingSettings');
|
||||
})
|
||||
$(document).triggerMenuEvent('ShowSettingsDialog');
|
||||
})
|
||||
).append(
|
||||
$('<a>', {
|
||||
class: 'list-group-item',
|
||||
@@ -400,11 +399,6 @@ define([
|
||||
slideMenu.slidebars.toggle('right');
|
||||
});
|
||||
|
||||
// settings
|
||||
$('.' + config.headUserCharacterClass).find('a').on('click', function(){
|
||||
$(document).triggerMenuEvent('ShowSettingsDialog');
|
||||
});
|
||||
|
||||
// active pilots
|
||||
$('.' + config.headActiveUserClass).find('a').on('click', function(){
|
||||
$(document).triggerMenuEvent('ShowMapInfo');
|
||||
@@ -439,11 +433,8 @@ define([
|
||||
});
|
||||
|
||||
// set default values for map tracking checkbox
|
||||
if(CCP.isInGameBrowser() === false){
|
||||
mapTrackingCheckbox.bootstrapToggle('disable');
|
||||
}else{
|
||||
mapTrackingCheckbox.bootstrapToggle('on');
|
||||
}
|
||||
// -> always "enable"
|
||||
mapTrackingCheckbox.bootstrapToggle('on');
|
||||
|
||||
mapTrackingCheckbox.on('change', function(e) {
|
||||
var value = $(this).is(':checked');
|
||||
@@ -502,13 +493,6 @@ define([
|
||||
*/
|
||||
var setDocumentObserver = function(){
|
||||
|
||||
// tab close/reload detected
|
||||
window.addEventListener('beforeunload', function (e) {
|
||||
|
||||
// logout
|
||||
deleteLog();
|
||||
});
|
||||
|
||||
// on "full-screen" change event
|
||||
$(document).on('fscreenchange', function(e, state, elem){
|
||||
|
||||
@@ -526,12 +510,6 @@ define([
|
||||
}
|
||||
});
|
||||
|
||||
$(document).on('pf:menuShowSharingSettings', function(e){
|
||||
// show sharing settings dialog
|
||||
$.fn.showSharingSettingsDialog();
|
||||
return false;
|
||||
});
|
||||
|
||||
$(document).on('pf:menuShowSystemEffectInfo', function(e){
|
||||
// show system effects info box
|
||||
$.fn.showSystemEffectInfoDialog();
|
||||
@@ -670,12 +648,22 @@ define([
|
||||
title: 'Shutdown',
|
||||
headline: 'Emergency shutdown',
|
||||
text: [
|
||||
'Sorry! Under normal circumstances that should not happen',
|
||||
data.reason
|
||||
]
|
||||
],
|
||||
textSmaller: []
|
||||
}
|
||||
};
|
||||
|
||||
// add error information (if available)
|
||||
if(
|
||||
data.error &&
|
||||
data.error.length
|
||||
){
|
||||
for(var i = 0; i < data.error.length; i++){
|
||||
options.content.textSmaller.push(data.error[i].message);
|
||||
}
|
||||
}
|
||||
|
||||
$.fn.showNotificationDialog(options);
|
||||
|
||||
$(document).setProgramStatus('offline');
|
||||
@@ -752,7 +740,7 @@ define([
|
||||
newCharacterName = userData.character.name;
|
||||
|
||||
if(userData.character.log){
|
||||
newShipId = userData.character.log.ship.id;
|
||||
newShipId = userData.character.log.ship.typeId;
|
||||
newShipName = userData.character.log.ship.typeName;
|
||||
}
|
||||
}
|
||||
@@ -769,6 +757,9 @@ define([
|
||||
animateHeaderElement(userInfoElement, function(){
|
||||
userInfoElement.find('span').text( newCharacterName );
|
||||
userInfoElement.find('img').attr('src', Init.url.ccpImageServer + 'Character/' + newCharacterId + '_32.jpg' );
|
||||
|
||||
// init "character switch" popover
|
||||
userInfoElement.initCharacterSwitchPopover(userData);
|
||||
}, showCharacterElement);
|
||||
|
||||
// set new id for next check
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* user register/settings dialog
|
||||
* user settings/share dialog
|
||||
*/
|
||||
|
||||
define([
|
||||
@@ -12,22 +12,13 @@ define([
|
||||
'use strict';
|
||||
|
||||
var config = {
|
||||
dialogWizardNavigationClass: 'pf-wizard-navigation', // class for wizard navigation bar
|
||||
|
||||
// select character dialog
|
||||
settingsDialogId: 'pf-settings-dialog', // id for "settings" dialog
|
||||
settingsImageWrapperClass: 'pf-dialog-image-wrapper', // class for image wrapper (animated)
|
||||
settingsImageInfoClass: 'pf-dialog-character-info', // class for character info layer (visible on hover)
|
||||
settingsMainClass: 'pf-dialog-character-main', // class for main character highlighting
|
||||
settingsNavigationButtonClass: 'pf-dialog-navigation-button', // class for all navigation buttons
|
||||
settingsFinishButtonClass: 'pf-dialog-finish-button', // class for "finish" button
|
||||
settingsPrevButtonClass: 'pf-dialog-prev-button', // class for "prev" button
|
||||
settingsNextButtonClass: 'pf-dialog-next-button', // class for "next" button
|
||||
settingsCloneApiRowClass: 'pf-dialog-api-row', // class for form row with API data (will be cloned)
|
||||
settingsCloneRowButtonClass: 'pf-dialog-clone-button', // class for clone button (api row)
|
||||
settingsDeleteRowButtonClass: 'pf-dialog-delete-button', // class for delete button (api row)
|
||||
settingsAccountContainerId: 'pf-settings-dialog-account', // id for the "account" container
|
||||
settingsShareContainerId: 'pf-settings-dialog-share', // id for the "share" container
|
||||
|
||||
// captcha
|
||||
captchaKeyUpdateAccount: 'SESSION.CAPTCHA.ACCOUNT.UPDATE', // key for captcha reason
|
||||
captchaImageWrapperId: 'pf-dialog-captcha-wrapper', // id for "captcha image" wrapper
|
||||
captchaImageId: 'pf-dialog-captcha-image', // id for "captcha image"
|
||||
|
||||
@@ -35,80 +26,9 @@ define([
|
||||
icon: {
|
||||
size: 'fa-2x'
|
||||
}
|
||||
},
|
||||
|
||||
// character status
|
||||
settingsCharacterStatusOwn : { // "own" -> my characters
|
||||
name: 'own',
|
||||
class: 'pf-user-status-own'
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* get active Tab link element for a dialog
|
||||
* @param dialog
|
||||
* @returns {JQuery|*}
|
||||
*/
|
||||
var getActiveTabElement = function(dialog){
|
||||
var navigationBarElement = $(dialog).find('.' + config.dialogWizardNavigationClass);
|
||||
var currentActiveTab = navigationBarElement.find('li.active');
|
||||
|
||||
return currentActiveTab;
|
||||
};
|
||||
|
||||
/**
|
||||
* init popovers in dialog
|
||||
* @param dialogElement
|
||||
*/
|
||||
var initPopover = function(dialogElement){
|
||||
|
||||
var apiCloneButtons = dialogElement.find('.' + config.settingsCloneRowButtonClass);
|
||||
var apiDeleteButtons = dialogElement.find('.' + config.settingsDeleteRowButtonClass);
|
||||
|
||||
var confirmationSettings = {
|
||||
container: 'body',
|
||||
placement: 'left',
|
||||
btnCancelClass: 'btn btn-sm btn-default',
|
||||
btnCancelLabel: 'cancel',
|
||||
btnCancelIcon: 'fa fa-fw fa-ban'
|
||||
};
|
||||
|
||||
// add API key row
|
||||
var cloneConfirmationSettings = $.extend({
|
||||
title: 'Add additional key',
|
||||
btnOkClass: 'btn btn-sm btn-success',
|
||||
btnOkLabel: 'confirm',
|
||||
btnOkIcon: 'fa fa-fw fa-check',
|
||||
onConfirm: function(e) {
|
||||
var cloneRow = dialogElement.find('.' + config.settingsCloneApiRowClass).last();
|
||||
var newApiRow = cloneRow.clone();
|
||||
|
||||
newApiRow.find('.form-group').removeClass('has-success has-error');
|
||||
newApiRow.find('input').val('');
|
||||
cloneRow.after(newApiRow);
|
||||
|
||||
// init new row with popups
|
||||
initPopover(dialogElement);
|
||||
}
|
||||
}, confirmationSettings);
|
||||
|
||||
// delete API key row
|
||||
var deleteConfirmationSettings = $.extend({
|
||||
title: 'Delete key',
|
||||
btnOkClass: 'btn btn-sm btn-danger',
|
||||
btnOkLabel: 'delete',
|
||||
btnOkIcon: 'fa fa-fw fa-close',
|
||||
onConfirm: function(e, target) {
|
||||
$(target).parents('.row').remove();
|
||||
}
|
||||
}, confirmationSettings);
|
||||
|
||||
$(apiCloneButtons).confirmation(cloneConfirmationSettings);
|
||||
$(apiDeleteButtons).confirmation(deleteConfirmationSettings);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* show "register/settings" dialog
|
||||
* @param options
|
||||
@@ -122,213 +42,124 @@ define([
|
||||
return false;
|
||||
}
|
||||
|
||||
var reroutePath = '';
|
||||
|
||||
// check navigation buttons and show/hide them
|
||||
var checkNavigationButton = function(dialog){
|
||||
var navigationBarElement = $(dialog).find('.' + config.dialogWizardNavigationClass);
|
||||
var currentActiveTab = navigationBarElement.find('li.active');
|
||||
|
||||
var hidePrevButton = currentActiveTab.prevAll().length > 0 ? false : true;
|
||||
var hideNextButton = currentActiveTab.nextAll().length > 0 ? false : true;
|
||||
|
||||
if(hidePrevButton){
|
||||
$('.' + config.settingsPrevButtonClass).hide();
|
||||
}else{
|
||||
$('.' + config.settingsPrevButtonClass).show();
|
||||
}
|
||||
|
||||
if(hideNextButton){
|
||||
$('.' + config.settingsNextButtonClass).hide();
|
||||
}else{
|
||||
$('.' + config.settingsNextButtonClass).show();
|
||||
}
|
||||
};
|
||||
|
||||
requirejs(['text!templates/dialog/settings.html', 'mustache'], function(template, Mustache) {
|
||||
|
||||
// if this is a new registration there is no API key -> fake an empty API to make fields visible
|
||||
if(options.register === 1){
|
||||
Init.currentUserData = {};
|
||||
Init.currentUserData.api = [{
|
||||
keyId: '',
|
||||
vCode: ''
|
||||
}];
|
||||
}else if(Init.currentUserData.api === undefined){
|
||||
Init.currentUserData.api = [{
|
||||
keyId: '',
|
||||
vCode: ''
|
||||
}];
|
||||
}
|
||||
|
||||
var data = {
|
||||
id: config.settingsDialogId,
|
||||
register: options.register === 1 ? 1 : 0,
|
||||
invite : options.invite === 1 ? 1 : 0,
|
||||
navigationClass: config.dialogWizardNavigationClass,
|
||||
settingsAccountContainerId: config.settingsAccountContainerId,
|
||||
settingsShareContainerId: config.settingsShareContainerId,
|
||||
userData: Init.currentUserData,
|
||||
cloneApiRowClass: config.settingsCloneApiRowClass,
|
||||
cloneRowButtonClass: config.settingsCloneRowButtonClass,
|
||||
deleteRowButtonClass: config.settingsDeleteRowButtonClass,
|
||||
captchaImageWrapperId: config.captchaImageWrapperId,
|
||||
captchaImageId: config.captchaImageId,
|
||||
formErrorContainerClass: Util.config.formErrorContainerClass,
|
||||
formWarningContainerClass: Util.config.formWarningContainerClass
|
||||
ccpImageServer: Init.url.ccpImageServer
|
||||
};
|
||||
|
||||
var content = Mustache.render(template, data);
|
||||
|
||||
var selectCharacterDialog = bootbox.dialog({
|
||||
title: options.register === 1 ? 'Registration' : 'Account settings',
|
||||
var accountSettingsDialog = bootbox.dialog({
|
||||
title: 'Account settings',
|
||||
message: content,
|
||||
buttons: {
|
||||
close: {
|
||||
label: 'finish',
|
||||
className: ['btn-success', 'pull-right', config.settingsFinishButtonClass].join(' '),
|
||||
callback: function(e){
|
||||
|
||||
if(options.register === 1){
|
||||
if(reroutePath !== undefined){
|
||||
// root user to main app
|
||||
window.location = reroutePath;
|
||||
}
|
||||
}else{
|
||||
// close dialog
|
||||
return true;
|
||||
}
|
||||
}
|
||||
label: 'cancel',
|
||||
className: 'btn-default'
|
||||
},
|
||||
prev: {
|
||||
label: '<i class="fa fa-fw fa-angle-left"></i>back',
|
||||
className: ['btn-default', 'pull-left', config.settingsNavigationButtonClass, config.settingsPrevButtonClass].join(' '),
|
||||
callback: function (e) {
|
||||
var currentActiveTab = getActiveTabElement(this);
|
||||
currentActiveTab.removeClass('finished');
|
||||
currentActiveTab.prev('li').find('a').tab('show');
|
||||
success: {
|
||||
label: '<i class="fa fa-check fa-fw"></i> save',
|
||||
className: 'btn-success',
|
||||
callback: function() {
|
||||
|
||||
return false;
|
||||
}
|
||||
},
|
||||
next: {
|
||||
label: 'next<i class="fa fa-fw fa-angle-right"></i>',
|
||||
className: ['btn-primary', 'pull-right', config.settingsNavigationButtonClass, config.settingsNextButtonClass].join(' '),
|
||||
callback: function (e) {
|
||||
var dialogElement = $(this);
|
||||
var currentActiveTab = getActiveTabElement(dialogElement);
|
||||
var currentActiveLink = currentActiveTab.find('a');
|
||||
var tabContentElement = $(currentActiveLink.attr('href'));
|
||||
var form = tabContentElement.find('form');
|
||||
|
||||
var changeTab = function(){
|
||||
currentActiveTab.addClass('finished');
|
||||
currentActiveLink.removeClass('btn-danger btn-default');
|
||||
currentActiveLink.addClass('btn-primary');
|
||||
|
||||
currentActiveTab.next('li').find('a').tab('show');
|
||||
};
|
||||
// get the current active form
|
||||
var form = $('#' + config.settingsDialogId).find('form').filter(':visible');
|
||||
|
||||
// validate form
|
||||
form.validator('validate');
|
||||
|
||||
// check weather the form is valid
|
||||
var formValid = form.isValidForm();
|
||||
|
||||
if(!formValid){
|
||||
currentActiveTab.removeClass('disabled');
|
||||
currentActiveLink.removeClass('btn-default btn-primary');
|
||||
currentActiveLink.addClass('btn-danger');
|
||||
}else{
|
||||
if(formValid === true){
|
||||
var tabFormValues = form.getFormValues();
|
||||
|
||||
if(! $.isEmptyObject(tabFormValues) ){
|
||||
// send Tab data and store values
|
||||
var requestData = {
|
||||
formData: tabFormValues
|
||||
};
|
||||
|
||||
// send Tab data and store values
|
||||
var requestData = {
|
||||
settingsData: tabFormValues
|
||||
};
|
||||
accountSettingsDialog.find('.modal-content').showLoadingAnimation();
|
||||
|
||||
selectCharacterDialog.find('.modal-content').showLoadingAnimation();
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: Init.path.saveUserConfig,
|
||||
data: requestData,
|
||||
dataType: 'json'
|
||||
}).done(function(responseData){
|
||||
accountSettingsDialog.find('.modal-content').hideLoadingAnimation();
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: Init.path.saveUserConfig,
|
||||
data: requestData,
|
||||
dataType: 'json'
|
||||
}).done(function(responseData){
|
||||
selectCharacterDialog.find('.modal-content').hideLoadingAnimation();
|
||||
// set new captcha for any request
|
||||
// captcha is required for sensitive data (not for all data)
|
||||
if(
|
||||
responseData.error &&
|
||||
responseData.error.length > 0
|
||||
){
|
||||
form.showFormMessage(responseData.error);
|
||||
|
||||
// set new captcha for any request
|
||||
// captcha is required for sensitive data (not for all data)
|
||||
if(
|
||||
responseData.error &&
|
||||
responseData.error.length > 0
|
||||
){
|
||||
form.showFormMessage(responseData.error);
|
||||
|
||||
$('#' + config.captchaImageWrapperId).showCaptchaImage('createAccount', function(){
|
||||
$('#captcha').resetFormFields();
|
||||
});
|
||||
}else{
|
||||
// store new/updated user data -> update head
|
||||
if(responseData.userData){
|
||||
Util.setCurrentUserData(responseData.userData);
|
||||
}
|
||||
|
||||
// store reroute path after registration finished
|
||||
if(responseData.reroute){
|
||||
reroutePath = responseData.reroute;
|
||||
}
|
||||
|
||||
dialogElement.find('.alert').velocity('transition.slideDownOut',{
|
||||
duration: 500,
|
||||
complete: function(){
|
||||
// switch tab
|
||||
changeTab();
|
||||
|
||||
$('#' + config.captchaImageWrapperId).showCaptchaImage('createAccount', function(){
|
||||
$('#captcha').resetFormFields();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Util.showNotify({title: 'Account saved', type: 'success'});
|
||||
}
|
||||
|
||||
}).fail(function( jqXHR, status, error) {
|
||||
selectCharacterDialog.find('.modal-content').hideLoadingAnimation();
|
||||
|
||||
var reason = status + ' ' + error;
|
||||
Util.showNotify({title: jqXHR.status + ': saveAccount', text: reason, type: 'error'});
|
||||
|
||||
// set new captcha for any request
|
||||
// captcha is required for sensitive data (not for all)
|
||||
$('#' + config.captchaImageWrapperId).showCaptchaImage('createAccount', function(){
|
||||
$('#' + config.captchaImageWrapperId).showCaptchaImage(config.captchaKeyUpdateAccount, function(){
|
||||
$('#captcha').resetFormFields();
|
||||
});
|
||||
}else{
|
||||
// store new/updated user data -> update head
|
||||
if(responseData.userData){
|
||||
Util.setCurrentUserData(responseData.userData);
|
||||
}
|
||||
|
||||
// check for DB errors
|
||||
if(jqXHR.status === 500){
|
||||
|
||||
if(jqXHR.responseText){
|
||||
var errorObj = $.parseJSON(jqXHR.responseText);
|
||||
|
||||
if(
|
||||
errorObj.error &&
|
||||
errorObj.error.length > 0
|
||||
){
|
||||
form.showFormMessage(errorObj.error);
|
||||
}
|
||||
form.find('.alert').velocity('transition.slideDownOut',{
|
||||
duration: 500,
|
||||
complete: function(){
|
||||
$('#' + config.captchaImageWrapperId).showCaptchaImage(config.captchaKeyUpdateAccount, function(){
|
||||
$('#captcha').resetFormFields();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if( options.register !== 1 ){
|
||||
$(document).setProgramStatus('problem');
|
||||
}
|
||||
Util.showNotify({title: 'Account saved', type: 'success'});
|
||||
|
||||
// close dialog/menu
|
||||
$(document).trigger('pf:closeMenu', [{}]);
|
||||
accountSettingsDialog.modal('hide');
|
||||
}
|
||||
|
||||
}).fail(function( jqXHR, status, error) {
|
||||
accountSettingsDialog.find('.modal-content').hideLoadingAnimation();
|
||||
|
||||
var reason = status + ' ' + error;
|
||||
Util.showNotify({title: jqXHR.status + ': saveAccountSettings', text: reason, type: 'error'});
|
||||
|
||||
// set new captcha for any request
|
||||
// captcha is required for sensitive data (not for all)
|
||||
$('#' + config.captchaImageWrapperId).showCaptchaImage(config.captchaKeyUpdateAccount, function(){
|
||||
$('#captcha').resetFormFields();
|
||||
});
|
||||
|
||||
}else{
|
||||
// no request required -> change tab
|
||||
changeTab();
|
||||
}
|
||||
// check for DB errors
|
||||
if(jqXHR.status === 500){
|
||||
|
||||
if(jqXHR.responseText){
|
||||
var errorObj = $.parseJSON(jqXHR.responseText);
|
||||
|
||||
if(
|
||||
errorObj.error &&
|
||||
errorObj.error.length > 0
|
||||
){
|
||||
form.showFormMessage(errorObj.error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$(document).setProgramStatus('problem');
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -338,163 +169,42 @@ define([
|
||||
});
|
||||
|
||||
// after modal is shown =======================================================================
|
||||
selectCharacterDialog.on('shown.bs.modal', function(e) {
|
||||
accountSettingsDialog.on('shown.bs.modal', function(e) {
|
||||
|
||||
var dialogElement = $(this);
|
||||
var tabLinkElements = dialogElement.find('a[data-toggle="tab"]');
|
||||
var form = dialogElement.find('form');
|
||||
|
||||
// request captcha image and show
|
||||
$('#' + config.captchaImageWrapperId).showCaptchaImage('createAccount');
|
||||
var captchaImageWrapperContainer = $('#' + config.captchaImageWrapperId);
|
||||
captchaImageWrapperContainer.showCaptchaImage(config.captchaKeyUpdateAccount);
|
||||
|
||||
// init captcha refresh button
|
||||
captchaImageWrapperContainer.find('i').on('click', function(){
|
||||
captchaImageWrapperContainer.showCaptchaImage(config.captchaKeyUpdateAccount);
|
||||
});
|
||||
|
||||
|
||||
// init dialog tooltips
|
||||
dialogElement.initTooltips();
|
||||
|
||||
// init popups
|
||||
initPopover( dialogElement );
|
||||
|
||||
// init form validation
|
||||
form.initFormValidation();
|
||||
});
|
||||
|
||||
// on Tab switch ======================================================================
|
||||
tabLinkElements.on('shown.bs.tab', function (e) {
|
||||
|
||||
// check navigation buttons (hide/show)
|
||||
checkNavigationButton(dialogElement);
|
||||
|
||||
$(e.target).removeClass('disabled');
|
||||
|
||||
// hide finish button
|
||||
dialogElement.find('.' + config.settingsFinishButtonClass).hide();
|
||||
|
||||
|
||||
if($(e.target).text() < $(e.relatedTarget).text()){
|
||||
var currentActiveTab = getActiveTabElement(dialogElement);
|
||||
var nextTabElements = currentActiveTab.nextAll();
|
||||
|
||||
// disable all next tabs
|
||||
currentActiveTab.removeClass('finished');
|
||||
nextTabElements.removeClass('finished');
|
||||
nextTabElements.find('a').removeClass('btn-primary btn-danger').addClass('btn-default disabled');
|
||||
}
|
||||
|
||||
if($(e.target).text() === '3'){
|
||||
|
||||
// load character tab -----------------------------------------------
|
||||
|
||||
requirejs(['text!templates/form/character_panel.html', 'mustache'], function(template, Mustache) {
|
||||
|
||||
// all characters for the current user
|
||||
var characters = Init.currentUserData.characters;
|
||||
// calculate grid class
|
||||
var characterCount = characters.length;
|
||||
var gridClass = ((12 / characterCount) < 4)? 4 : 12 / characterCount ;
|
||||
|
||||
// add character status information for each character
|
||||
var statusInfo = {};
|
||||
statusInfo.class = config.settingsCharacterStatusOwn.class;
|
||||
statusInfo.label = config.settingsCharacterStatusOwn.name;
|
||||
|
||||
var mainCharacter = 0;
|
||||
for(var i = 0; i < characters.length; i++){
|
||||
characters[i].status = statusInfo;
|
||||
|
||||
if(characters[i].isMain === 1){
|
||||
mainCharacter = characters[i].id;
|
||||
}else if(mainCharacter === 0){
|
||||
// mark at least one character as "main" if no main char was found
|
||||
// e.g. first account setup
|
||||
mainCharacter = characters[i].id;
|
||||
}
|
||||
}
|
||||
|
||||
var characterTemplateData = {
|
||||
imageWrapperClass: config.settingsImageWrapperClass,
|
||||
imageInfoClass: config.settingsImageInfoClass,
|
||||
imageWrapperMainClass: config.settingsMainClass,
|
||||
charactersData: characters,
|
||||
gridClass: 'col-sm-' + gridClass,
|
||||
mainCharacter: mainCharacter
|
||||
};
|
||||
|
||||
var content = Mustache.render(template, characterTemplateData);
|
||||
|
||||
var characterForm = dialogElement.find('#pf-dialog-settings-character form');
|
||||
|
||||
// add form HTML
|
||||
characterForm.html(content);
|
||||
|
||||
var imageWrapperElements = dialogElement.find('.' + config.settingsImageWrapperClass);
|
||||
|
||||
// special effects :)
|
||||
imageWrapperElements.velocity('stop').delay(100).velocity('transition.flipBounceXIn', {
|
||||
display: 'inline-block',
|
||||
stagger: 60,
|
||||
drag: true,
|
||||
duration: 400,
|
||||
complete: function(){
|
||||
// init new character tooltips
|
||||
dialogElement.initTooltips();
|
||||
}
|
||||
});
|
||||
|
||||
// Hover effect for character info layer
|
||||
imageWrapperElements.hoverIntent(function(e){
|
||||
var characterInfoElement = $(this).find('.' + config.settingsImageInfoClass);
|
||||
|
||||
characterInfoElement.velocity('finish').velocity({
|
||||
width: ['100%', [ 400, 15 ] ]
|
||||
},{
|
||||
easing: 'easeInSine'
|
||||
});
|
||||
}, function(e){
|
||||
var characterInfoElement = $(this).find('.' + config.settingsImageInfoClass);
|
||||
|
||||
characterInfoElement.velocity('finish').velocity({
|
||||
width: 0
|
||||
},{
|
||||
duration: 150,
|
||||
easing: 'easeInOutSine'
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// click event on character image
|
||||
imageWrapperElements.on('click', function(e){
|
||||
var wrapperElement = $(this);
|
||||
var characterId = wrapperElement.data('id');
|
||||
|
||||
// update layout if character is selected
|
||||
if(characterId > 0){
|
||||
// update hidden field with new mainCharacterId
|
||||
dialogElement.find('input[name="mainCharacterId"]').val(characterId);
|
||||
|
||||
imageWrapperElements.removeClass( config.settingsMainClass );
|
||||
wrapperElement.addClass( config.settingsMainClass );
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}else if($(e.target).text() === '4'){
|
||||
// show finish button
|
||||
dialogElement.find('.' + config.settingsFinishButtonClass).show();
|
||||
|
||||
// show success message
|
||||
dialogElement.find('h1').velocity('stop').delay(200).velocity('transition.flipBounceXIn', {
|
||||
duration: 500
|
||||
}).delay(100).velocity('callout.pulse');
|
||||
}
|
||||
// events for tab change
|
||||
accountSettingsDialog.find('.navbar a').on('shown.bs.tab', function(e){
|
||||
|
||||
// init "toggle" switches on current active tab
|
||||
accountSettingsDialog.find( $(this).attr('href') ).find('input[type="checkbox"]').bootstrapToggle({
|
||||
on: '<i class="fa fa-fw fa-check"></i> Enable',
|
||||
off: 'Disable <i class="fa fa-fw fa-ban"></i>',
|
||||
onstyle: 'success',
|
||||
offstyle: 'warning',
|
||||
width: 90,
|
||||
height: 30
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
});
|
||||
@@ -15,6 +15,7 @@ define([
|
||||
deleteAccountId: 'pf-dialog-delete-account', // dialog id
|
||||
|
||||
// captcha
|
||||
captchaKeyDeleteAccount: 'SESSION.CAPTCHA.ACCOUNT.DELETE', // key for captcha reason
|
||||
captchaImageWrapperId: 'pf-dialog-captcha-wrapper' // id for "captcha image" wrapper
|
||||
};
|
||||
|
||||
@@ -82,8 +83,8 @@ define([
|
||||
){
|
||||
form.showFormMessage(responseData.error);
|
||||
|
||||
$('#' + config.captchaImageWrapperId).showCaptchaImage('deleteAccount', function(){
|
||||
form.find('[name="captcha"], [name="password"]').resetFormFields();
|
||||
$('#' + config.captchaImageWrapperId).showCaptchaImage(config.captchaKeyDeleteAccount, function(){
|
||||
form.find('[name="captcha"]').resetFormFields();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -106,7 +107,7 @@ define([
|
||||
// after modal is shown =======================================================================
|
||||
deleteAccountDialog.on('shown.bs.modal', function(e) {
|
||||
// request captcha image and show
|
||||
$('#' + config.captchaImageWrapperId).showCaptchaImage('deleteAccount');
|
||||
$('#' + config.captchaImageWrapperId).showCaptchaImage(config.captchaKeyDeleteAccount);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -643,7 +643,6 @@ define([
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var userDataTable = userTable.dataTable( {
|
||||
pageLength: 20,
|
||||
paging: true,
|
||||
@@ -670,7 +669,7 @@ define([
|
||||
data: 'log.ship',
|
||||
render: {
|
||||
_: function(data, type, row, meta){
|
||||
return '<img src="' + Init.url.ccpImageServer + 'Render/' + data.id + '_32.png" />';
|
||||
return '<img src="' + Init.url.ccpImageServer + 'Render/' + data.typeId + '_32.png" />';
|
||||
}
|
||||
}
|
||||
},{
|
||||
@@ -736,6 +735,16 @@ define([
|
||||
}
|
||||
},{
|
||||
targets: 7,
|
||||
title: 'station',
|
||||
orderable: true,
|
||||
searchable: true,
|
||||
data: 'log.station',
|
||||
render: {
|
||||
_: 'name',
|
||||
sort: 'name'
|
||||
}
|
||||
},{
|
||||
targets: 8,
|
||||
title: '',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
@@ -754,7 +763,7 @@ define([
|
||||
});
|
||||
}
|
||||
},{
|
||||
targets: 8,
|
||||
targets: 9,
|
||||
title: '',
|
||||
orderable: false,
|
||||
searchable: false,
|
||||
|
||||
@@ -20,7 +20,7 @@ define([
|
||||
dialogMapSettingsContainerId: 'pf-map-dialog-settings', // id for the "settings" container
|
||||
dialogMapDownloadContainerId: 'pf-map-dialog-download', // id for the "download" container
|
||||
|
||||
userSelectId: 'pf-map-dialog-user-select', // id for "user" select
|
||||
characterSelectId: 'pf-map-dialog-character-select', // id for "character" select
|
||||
corporationSelectId: 'pf-map-dialog-corporation-select', // id for "corporation" select
|
||||
allianceSelectId: 'pf-map-dialog-alliance-select', // id for "alliance" select
|
||||
|
||||
@@ -100,7 +100,7 @@ define([
|
||||
contentEditMap = $(contentEditMap);
|
||||
|
||||
// current map access info
|
||||
var accessUser = [];
|
||||
var accessCharacter = [];
|
||||
var accessCorporation = [];
|
||||
var accessAlliance = [];
|
||||
|
||||
@@ -112,7 +112,7 @@ define([
|
||||
contentEditMap.find('select[name="scopeId"]').val( mapData.config.scope.id );
|
||||
contentEditMap.find('select[name="typeId"]').val( mapData.config.type.id );
|
||||
|
||||
accessUser = mapData.config.access.user;
|
||||
accessCharacter = mapData.config.access.character;
|
||||
accessCorporation = mapData.config.access.corporation;
|
||||
accessAlliance = mapData.config.access.alliance;
|
||||
}
|
||||
@@ -145,17 +145,17 @@ define([
|
||||
hideDownloadTab: hideDownloadTab,
|
||||
|
||||
// settings tab --------------
|
||||
userSelectId: config.userSelectId,
|
||||
characterSelectId: config.characterSelectId,
|
||||
corporationSelectId: config.corporationSelectId,
|
||||
allianceSelectId: config.allianceSelectId,
|
||||
|
||||
// map access objects --------
|
||||
accessUser: accessUser,
|
||||
accessCharacter: accessCharacter,
|
||||
accessCorporation: accessCorporation,
|
||||
accessAlliance: accessAlliance,
|
||||
|
||||
// access limitations --------
|
||||
maxUser: Init.maxSharedCount.user,
|
||||
maxCharacter: Init.maxSharedCount.character,
|
||||
maxCorporation: Init.maxSharedCount.corporation,
|
||||
maxAlliance: Init.maxSharedCount.alliance,
|
||||
|
||||
@@ -287,7 +287,7 @@ define([
|
||||
// events for tab change
|
||||
mapInfoDialog.find('.navbar a').on('shown.bs.tab', function(e){
|
||||
|
||||
var selectElementUser = mapInfoDialog.find('#' + config.userSelectId);
|
||||
var selectElementCharacter = mapInfoDialog.find('#' + config.characterSelectId);
|
||||
var selectElementCorporation = mapInfoDialog.find('#' + config.corporationSelectId);
|
||||
var selectElementAlliance = mapInfoDialog.find('#' + config.allianceSelectId);
|
||||
|
||||
@@ -295,8 +295,8 @@ define([
|
||||
// "settings" tab
|
||||
initSettingsSelectFields(mapInfoDialog);
|
||||
}else{
|
||||
if( $(selectElementUser).data('select2') !== undefined ){
|
||||
$(selectElementUser).select2('destroy');
|
||||
if( $(selectElementCharacter).data('select2') !== undefined ){
|
||||
$(selectElementCharacter).select2('destroy');
|
||||
}
|
||||
|
||||
if( $(selectElementCorporation).data('select2') !== undefined ){
|
||||
@@ -550,14 +550,14 @@ define([
|
||||
*/
|
||||
var initSettingsSelectFields = function(mapInfoDialog){
|
||||
|
||||
var selectElementUser = mapInfoDialog.find('#' + config.userSelectId);
|
||||
var selectElementCharacter = mapInfoDialog.find('#' + config.characterSelectId);
|
||||
var selectElementCorporation = mapInfoDialog.find('#' + config.corporationSelectId);
|
||||
var selectElementAlliance = mapInfoDialog.find('#' + config.allianceSelectId);
|
||||
|
||||
// init corporation select live search
|
||||
selectElementUser.initAccessSelect({
|
||||
type: 'user',
|
||||
maxSelectionLength: Init.maxSharedCount.user
|
||||
// init character select live search
|
||||
selectElementCharacter.initAccessSelect({
|
||||
type: 'character',
|
||||
maxSelectionLength: Init.maxSharedCount.character
|
||||
});
|
||||
|
||||
// init corporation select live search
|
||||
@@ -575,7 +575,7 @@ define([
|
||||
|
||||
/**
|
||||
* shows the delete map Dialog
|
||||
* @param mapElement
|
||||
* @param mapData
|
||||
*/
|
||||
$.fn.showDeleteMapDialog = function(mapData){
|
||||
|
||||
|
||||
@@ -47,8 +47,6 @@ define([
|
||||
releasesDialog.find('ul.timeline').append(content);
|
||||
}
|
||||
|
||||
// console.log()
|
||||
|
||||
$('.timeline > li').velocity('transition.expandIn', {
|
||||
stagger: 300,
|
||||
duration: 240,
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
/**
|
||||
* sharing settings dialog
|
||||
*/
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util',
|
||||
'app/render',
|
||||
'bootbox'
|
||||
], function($, Init, Util, Render, bootbox) {
|
||||
'use strict';
|
||||
|
||||
var config = {
|
||||
// select character dialog
|
||||
sharingDialogId: 'pf-sharing-dialog', // id for "sharing settings" dialog
|
||||
};
|
||||
|
||||
$.fn.showSharingSettingsDialog = function(){
|
||||
|
||||
var sharingDialogElement = $('#' + config.sharingDialogId);
|
||||
if(!sharingDialogElement.is(':visible')){
|
||||
|
||||
var userData = Util.getCurrentUserData();
|
||||
|
||||
if(userData){
|
||||
|
||||
requirejs([
|
||||
'text!templates/dialog/sharing_settings.html',
|
||||
'mustache'
|
||||
], function(templatSharingDialog, Mustache) {
|
||||
|
||||
var data = {
|
||||
id: config.sharingDialogId,
|
||||
ccpImageServer: Init.url.ccpImageServer,
|
||||
userData: userData
|
||||
};
|
||||
|
||||
// render "new map" tab content -------------------------------------------
|
||||
var contentSharingDialog = Mustache.render(templatSharingDialog, data);
|
||||
|
||||
var sharingSettingsDialog = bootbox.dialog({
|
||||
title: 'Sharing settings',
|
||||
message: $(contentSharingDialog),
|
||||
buttons: {
|
||||
close: {
|
||||
label: 'cancel',
|
||||
className: 'btn-default'
|
||||
},
|
||||
success: {
|
||||
label: '<i class="fa fa-check fa-fw"></i> save',
|
||||
className: 'btn-success',
|
||||
callback: function() {
|
||||
|
||||
var form = $('#' + config.sharingDialogId).find('form');
|
||||
|
||||
var sharingSettingsData = {formData: form.getFormValues()};
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: Init.path.saveSharingConfig,
|
||||
data: sharingSettingsData,
|
||||
dataType: 'json'
|
||||
}).done(function(data){
|
||||
|
||||
if(data.userData !== undefined){
|
||||
// store current user data global (cache)
|
||||
Util.setCurrentUserData(data.userData);
|
||||
|
||||
$(document).trigger('pf:closeMenu', [{}]);
|
||||
$(sharingSettingsDialog).modal('hide');
|
||||
|
||||
// success
|
||||
Util.showNotify({title: 'Sharing settings saved', type: 'success'});
|
||||
}
|
||||
|
||||
}).fail(function( jqXHR, status, error) {
|
||||
var reason = status + ' ' + error;
|
||||
Util.showNotify({title: jqXHR.status + ': shareSettings', text: reason, type: 'warning'});
|
||||
$(document).setProgramStatus('problem');
|
||||
});
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// after modal is shown ---------------------------------------------------
|
||||
sharingSettingsDialog.on('shown.bs.modal', function(e) {
|
||||
|
||||
$(this).find('input[type="checkbox"]').bootstrapToggle({
|
||||
on: '<i class="fa fa-fw fa-check"></i> Enable',
|
||||
off: 'Disable <i class="fa fa-fw fa-ban"></i>',
|
||||
onstyle: 'success',
|
||||
offstyle: 'warning',
|
||||
width: 90,
|
||||
height: 30
|
||||
});
|
||||
});
|
||||
});
|
||||
}else{
|
||||
Util.showNotify({title: 'No userData found', type: 'warning'});
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
});
|
||||
@@ -131,7 +131,7 @@ define([
|
||||
|
||||
/**
|
||||
* init a select element as an ajax based "select2" object for Access resources
|
||||
* user (private map), corporation (corp map), alliance (ally map)
|
||||
* character (private map), corporation (corp map), alliance (ally map)
|
||||
* @param options
|
||||
*/
|
||||
$.fn.initAccessSelect = function(options){
|
||||
@@ -162,8 +162,9 @@ define([
|
||||
var previewContent = '';
|
||||
|
||||
switch(options.type){
|
||||
case 'user':
|
||||
previewContent = '<i class="fa fa-lg fa-user"></i>';
|
||||
case 'character':
|
||||
imagePath = Init.url.ccpImageServer + 'Character/' + data.id + '_32.jpg';
|
||||
previewContent = '<img src="' + imagePath + '" style="max-width: 100%" />';
|
||||
break;
|
||||
case 'corporation':
|
||||
imagePath = Init.url.ccpImageServer + 'Corporation/' + data.id + '_32.png';
|
||||
|
||||
@@ -150,57 +150,58 @@ define([
|
||||
dataType: 'json'
|
||||
}).done(function(systemGraphsData){
|
||||
|
||||
// create new (hidden) module container
|
||||
var moduleElement = $('<div>', {
|
||||
class: [config.moduleClass, config.systemGraphModuleClass].join(' '),
|
||||
css: {opacity: 0}
|
||||
});
|
||||
|
||||
// insert at the correct position
|
||||
if($(parentElement).children().length === 1){
|
||||
$(parentElement).append(moduleElement);
|
||||
}else{
|
||||
$(parentElement).find('>:first-child').after(moduleElement);
|
||||
}
|
||||
|
||||
// row element
|
||||
var rowElement = $('<div>', {
|
||||
class: 'row'
|
||||
});
|
||||
moduleElement.append(rowElement);
|
||||
|
||||
$.each(systemGraphsData, function(systemId, graphsData){
|
||||
$.each(graphsData, function(graphKey, graphData){
|
||||
|
||||
var colElement = $('<div>', {
|
||||
class: ['col-xs-12', 'col-sm-6', 'col-md-4'].join(' ')
|
||||
});
|
||||
|
||||
var headlineElement = $('<h5>').text( getInfoForGraph(graphKey, 'headline') );
|
||||
|
||||
colElement.append(headlineElement);
|
||||
|
||||
var graphElement = $('<div>', {
|
||||
class: config.systemGraphClass
|
||||
});
|
||||
|
||||
colElement.append(graphElement);
|
||||
|
||||
rowElement.append(colElement);
|
||||
initGraph(graphElement, graphKey, graphData, eventLine);
|
||||
if(systemGraphsData.length > 0){
|
||||
// create new (hidden) module container
|
||||
var moduleElement = $('<div>', {
|
||||
class: [config.moduleClass, config.systemGraphModuleClass].join(' '),
|
||||
css: {opacity: 0}
|
||||
});
|
||||
});
|
||||
|
||||
moduleElement.append($('<div>', {
|
||||
css: {'clear': 'both'}
|
||||
}));
|
||||
// insert at the correct position
|
||||
if($(parentElement).children().length === 1){
|
||||
$(parentElement).append(moduleElement);
|
||||
}else{
|
||||
$(parentElement).find('>:first-child').after(moduleElement);
|
||||
}
|
||||
|
||||
// show module
|
||||
moduleElement.velocity('transition.slideDownIn', {
|
||||
duration: Init.animationSpeed.mapModule,
|
||||
delay: Init.animationSpeed.mapModule
|
||||
});
|
||||
// row element
|
||||
var rowElement = $('<div>', {
|
||||
class: 'row'
|
||||
});
|
||||
moduleElement.append(rowElement);
|
||||
|
||||
$.each(systemGraphsData, function(systemId, graphsData){
|
||||
$.each(graphsData, function(graphKey, graphData){
|
||||
|
||||
var colElement = $('<div>', {
|
||||
class: ['col-xs-12', 'col-sm-6', 'col-md-4'].join(' ')
|
||||
});
|
||||
|
||||
var headlineElement = $('<h5>').text( getInfoForGraph(graphKey, 'headline') );
|
||||
|
||||
colElement.append(headlineElement);
|
||||
|
||||
var graphElement = $('<div>', {
|
||||
class: config.systemGraphClass
|
||||
});
|
||||
|
||||
colElement.append(graphElement);
|
||||
|
||||
rowElement.append(colElement);
|
||||
initGraph(graphElement, graphKey, graphData, eventLine);
|
||||
});
|
||||
});
|
||||
|
||||
moduleElement.append($('<div>', {
|
||||
css: {'clear': 'both'}
|
||||
}));
|
||||
|
||||
// show module
|
||||
moduleElement.velocity('transition.slideDownIn', {
|
||||
duration: Init.animationSpeed.mapModule,
|
||||
delay: Init.animationSpeed.mapModule
|
||||
});
|
||||
}
|
||||
}).fail(function( jqXHR, status, error) {
|
||||
var reason = status + ' ' + error;
|
||||
Util.showNotify({title: jqXHR.status + ': System graph data', text: reason, type: 'warning'});
|
||||
|
||||
@@ -333,34 +333,34 @@ define([
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: 'GET',
|
||||
dataType: 'jsonp'
|
||||
}).done(function(kbData){
|
||||
dataType: 'json'
|
||||
}).done(function(kbData) {
|
||||
|
||||
// the API wont return more than 200KMs ! - remember last bar block with complete KM information
|
||||
var lastCompleteDiffHourData = 0;
|
||||
|
||||
|
||||
// loop kills and count kills by hour
|
||||
for(var i = 0; i < kbData.length; i++){
|
||||
for (var i = 0; i < kbData.length; i++) {
|
||||
var killmailData = kbData[i];
|
||||
|
||||
var killDate = getDateObjectByTimeString(killmailData.killTime);
|
||||
|
||||
// get time diff
|
||||
var timeDiffMin = Math.round( ( serverDate - killDate ) / 1000 / 60 );
|
||||
var timeDiffHour = Math.round( timeDiffMin / 60 );
|
||||
var timeDiffMin = Math.round(( serverDate - killDate ) / 1000 / 60);
|
||||
var timeDiffHour = Math.round(timeDiffMin / 60);
|
||||
|
||||
// update chart data
|
||||
if(chartData[timeDiffHour]){
|
||||
if (chartData[timeDiffHour]) {
|
||||
chartData[timeDiffHour].kills++;
|
||||
|
||||
// add kill mail data
|
||||
if(chartData[timeDiffHour].killmails === undefined){
|
||||
if (chartData[timeDiffHour].killmails === undefined) {
|
||||
chartData[timeDiffHour].killmails = [];
|
||||
}
|
||||
chartData[timeDiffHour].killmails.push(killmailData);
|
||||
|
||||
if(timeDiffHour > lastCompleteDiffHourData){
|
||||
if (timeDiffHour > lastCompleteDiffHourData) {
|
||||
lastCompleteDiffHourData = timeDiffHour;
|
||||
}
|
||||
}
|
||||
@@ -368,7 +368,7 @@ define([
|
||||
}
|
||||
|
||||
// remove empty chart Data
|
||||
if(kbData.length >= maxKillmailCount){
|
||||
if (kbData.length >= maxKillmailCount) {
|
||||
chartData = chartData.splice(0, lastCompleteDiffHourData + 1);
|
||||
}
|
||||
|
||||
@@ -378,7 +378,7 @@ define([
|
||||
cache.systemKillsGraphData[cacheKey].count = kbData.length;
|
||||
|
||||
// draw table
|
||||
drawGraph( cache.systemKillsGraphData[cacheKey] );
|
||||
drawGraph(cache.systemKillsGraphData[cacheKey]);
|
||||
|
||||
// show killmail information
|
||||
showKillmails(moduleElement, cache.systemKillsGraphData[cacheKey]);
|
||||
|
||||
@@ -1634,6 +1634,10 @@ define([
|
||||
// submit all fields within a table row
|
||||
var formFields = rowElement.find('.editable');
|
||||
|
||||
// the "toggle" makes sure to take care about open editable fields (e.g. description)
|
||||
// otherwise, changes would not be submitted in this field (not necessary)
|
||||
formFields.editable('toggle');
|
||||
|
||||
// submit all xEditable fields
|
||||
formFields.editable('submit', {
|
||||
url: Init.path.saveSignatureData,
|
||||
|
||||
@@ -317,15 +317,17 @@ define([
|
||||
|
||||
/**
|
||||
* init form elements for validation (bootstrap3 validation)
|
||||
* @returns {any|JQuery|*}
|
||||
* @param options
|
||||
* @returns {*}
|
||||
*/
|
||||
$.fn.initFormValidation = function(){
|
||||
$.fn.initFormValidation = function(options){
|
||||
options = (typeof options === 'undefined')? {} : options;
|
||||
|
||||
return this.each(function(){
|
||||
var form = $(this);
|
||||
|
||||
// init form validation
|
||||
form.validator();
|
||||
form.validator(options);
|
||||
|
||||
// validation event listener
|
||||
form.on('valid.bs.validator', function(validatorObj){
|
||||
@@ -342,7 +344,6 @@ define([
|
||||
inputGroup.removeClass('has-success').addClass('has-error');
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
@@ -545,6 +546,84 @@ define([
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* add character switch popover
|
||||
* @param userData
|
||||
*/
|
||||
$.fn.initCharacterSwitchPopover = function(userData){
|
||||
var elements = $(this);
|
||||
var eventNamespace = 'hideCharacterPopup';
|
||||
|
||||
requirejs(['text!templates/tooltip/character_switch.html', 'mustache'], function (template, Mustache) {
|
||||
|
||||
var data = {
|
||||
routes: Init.routes,
|
||||
userData: userData,
|
||||
otherCharacters: $.grep( userData.characters, function( character ) {
|
||||
// exclude current active character
|
||||
return character.id !== userData.character.id;
|
||||
})
|
||||
};
|
||||
|
||||
var content = Mustache.render(template, data);
|
||||
|
||||
return elements.each(function() {
|
||||
var element = $(this);
|
||||
|
||||
// destroy "popover" and remove "click" event for animation
|
||||
element.popover('destroy').off();
|
||||
|
||||
// init popover and add specific class to it (for styling)
|
||||
element.popover({
|
||||
html: true,
|
||||
title: 'select character',
|
||||
trigger: 'click',
|
||||
placement: 'bottom',
|
||||
content: content,
|
||||
animation: false
|
||||
}).data('bs.popover').tip().addClass('pf-character-info-popover');
|
||||
|
||||
element.on('click', function(e) {
|
||||
e.preventDefault();
|
||||
var easeEffect = $(this).attr('data-easein');
|
||||
var popover = $(this).data('bs.popover').tip();
|
||||
var velocityOptions = {
|
||||
duration: CCP.isInGameBrowser() ? 0 : Init.animationSpeed.dialogEvents
|
||||
};
|
||||
|
||||
switch(easeEffect){
|
||||
case 'shake':
|
||||
case 'pulse':
|
||||
case 'tada':
|
||||
case 'flash':
|
||||
case 'bounce':
|
||||
case 'swing':
|
||||
popover.velocity('callout.' + easeEffect, velocityOptions);
|
||||
break;
|
||||
default:
|
||||
popover.velocity('transition.' + easeEffect, velocityOptions);
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
// hide popup on clicking "somewhere" outside
|
||||
$('body').off('click.' + eventNamespace).on('click.' + eventNamespace, function (e) {
|
||||
|
||||
//the 'is' for buttons that trigger popups
|
||||
//the 'has' for icons within a button that triggers a popup
|
||||
if (
|
||||
!$(element).is(e.target) &&
|
||||
$(element).has(e.target).length === 0 &&
|
||||
$('.popover').has(e.target).length === 0
|
||||
){
|
||||
$(element).popover('hide');
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* add a wormhole tooltip with wh specific data to elements
|
||||
* @param tooltipData
|
||||
@@ -575,7 +654,6 @@ define([
|
||||
var popover = element.data('bs.popover');
|
||||
popover.options.content = content;
|
||||
});
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1129,7 +1207,6 @@ define([
|
||||
* @returns {string}
|
||||
*/
|
||||
var getSystemEffectTable = function(data){
|
||||
|
||||
var table = '';
|
||||
|
||||
if(data.length > 0){
|
||||
|
||||
128
js/lib/validator.min.js
vendored
128
js/lib/validator.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
BIN
public/img/landing/eve_sso_login_buttons_large_black.png
Normal file
BIN
public/img/landing/eve_sso_login_buttons_large_black.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.1 KiB |
BIN
public/img/landing/eve_sso_login_buttons_large_black_hover.png
Normal file
BIN
public/img/landing/eve_sso_login_buttons_large_black_hover.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.8 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 199 KiB After Width: | Height: | Size: 144 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 224 KiB After Width: | Height: | Size: 174 KiB |
@@ -1,2 +0,0 @@
|
||||
var mainScriptPath=document.body.getAttribute("data-script"),jsBaseUrl=document.body.getAttribute("data-js-path");requirejs.config({baseUrl:"js",paths:{layout:"layout",config:"app/config",dialog:"app/ui/dialog",templates:"../../templates",img:"../../img",login:"./app/login",mappage:"./app/mappage",setup:"./app/setup",jquery:"lib/jquery-1.11.3.min",bootstrap:"lib/bootstrap.min",text:"lib/requirejs/text",mustache:"lib/mustache.min",velocity:"lib/velocity.min",velocityUI:"lib/velocity.ui.min",slidebars:"lib/slidebars",jsPlumb:"lib/dom.jsPlumb-1.7.6",farahey:"lib/farahey-0.5",customScrollbar:"lib/jquery.mCustomScrollbar.concat.min",datatables:"lib/datatables/jquery.dataTables.min",datatablesResponsive:"lib/datatables/extensions/responsive/dataTables.responsive",datatablesTableTools:"lib/datatables/extensions/tabletools/js/dataTables.tableTools",xEditable:"lib/bootstrap-editable.min",morris:"lib/morris.min",raphael:"lib/raphael-min",bootbox:"lib/bootbox.min",easyPieChart:"lib/jquery.easypiechart.min",dragToSelect:"lib/jquery.dragToSelect",hoverIntent:"lib/jquery.hoverIntent.minified",fullScreen:"lib/jquery.fullscreen.min",select2:"lib/select2.min",validator:"lib/validator.min",lazylinepainter:"lib/jquery.lazylinepainter-1.5.1.min",blueImpGallery:"lib/blueimp-gallery",blueImpGalleryHelper:"lib/blueimp-helper",blueImpGalleryBootstrap:"lib/bootstrap-image-gallery",bootstrapConfirmation:"lib/bootstrap-confirmation",bootstrapToggle:"lib/bootstrap2-toggle.min",lazyload:"lib/jquery.lazyload.min",easePack:"lib/EasePack.min",tweenLite:"lib/TweenLite.min",pnotify:"lib/pnotify/pnotify.core","pnotify.buttons":"lib/pnotify/pnotify.buttons","pnotify.confirm":"lib/pnotify/pnotify.confirm","pnotify.nonblock":"lib/pnotify/pnotify.nonblock","pnotify.desktop":"lib/pnotify/pnotify.desktop","pnotify.history":"lib/pnotify/pnotify.history","pnotify.callbacks":"lib/pnotify/pnotify.callbacks","pnotify.reference":"lib/pnotify/pnotify.reference"},shim:{bootstrap:{deps:["jquery"]},farahey:{deps:["jsPlumb"]},velocity:{deps:["jquery"]},velocityUI:{deps:["velocity"]},slidebars:{deps:["jquery"]},customScrollbar:{deps:["jquery"]},datatables:{deps:["jquery"]},datatablesBootstrap:{deps:["datatables"]},datatablesResponsive:{deps:["datatables"]},datatablesTableTools:{deps:["datatables"]},xEditable:{deps:["bootstrap"]},bootbox:{deps:["jquery","bootstrap"],exports:"bootbox"},morris:{deps:["jquery","raphael"],exports:"Morris"},pnotify:{deps:["jquery"]},easyPieChart:{deps:["jquery"]},dragToSelect:{deps:["jquery"]},hoverIntent:{deps:["jquery"]},fullScreen:{deps:["jquery"]},select2:{deps:["jquery"],exports:"Select2"},validator:{deps:["jquery","bootstrap"]},lazylinepainter:{deps:["jquery","bootstrap"]},blueImpGallery:{deps:["jquery"]},bootstrapConfirmation:{deps:["bootstrap"]},bootstrapToggle:{deps:["jquery"]},lazyload:{deps:["jquery"]}}});require.config({baseUrl:jsBaseUrl});requirejs([mainScriptPath]);
|
||||
//# sourceMappingURL=app.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"sources":["app.js.src.js"],"names":["mainScriptPath","document","body","getAttribute","jsBaseUrl","requirejs","config","baseUrl","paths","layout","dialog","templates","img","login","mappage","setup","jquery","bootstrap","text","mustache","velocity","velocityUI","slidebars","jsPlumb","farahey","customScrollbar","datatables","datatablesResponsive","datatablesTableTools","xEditable","morris","raphael","bootbox","easyPieChart","dragToSelect","hoverIntent","fullScreen","select2","validator","lazylinepainter","blueImpGallery","blueImpGalleryHelper","blueImpGalleryBootstrap","bootstrapConfirmation","bootstrapToggle","lazyload","easePack","tweenLite","pnotify","pnotify.buttons","pnotify.confirm","pnotify.nonblock","pnotify.desktop","pnotify.history","pnotify.callbacks","pnotify.reference","shim","deps","datatablesBootstrap","exports","require"],"mappings":"AACA,GAAIA,gBAAiBC,SAASC,KAAKC,aAAa,eAI5CC,UAAYH,SAASC,KAAKC,aAAa,eAG3CE,WAAUC,QACNC,QAAS,KAETC,OACIC,OAAQ,SACRH,OAAQ,aACRI,OAAQ,gBACRC,UAAW,kBACXC,IAAK,YAGLC,MAAO,cACPC,QAAS,gBACTC,MAAO,cAEPC,OAAQ,wBACRC,UAAW,oBACXC,KAAM,qBACNC,SAAU,mBACVC,SAAU,mBACVC,WAAY,sBACZC,UAAW,gBACXC,QAAS,wBACTC,QAAS,kBACTC,gBAAiB,yCACjBC,WAAY,uCAEZC,qBAAsB,6DAEtBC,qBAAsB,gEACtBC,UAAW,6BACXC,OAAQ,iBACRC,QAAS,kBACTC,QAAS,kBACTC,aAAc,8BACdC,aAAc,0BACdC,YAAa,kCACbC,WAAY,4BACZC,QAAS,kBACTC,UAAW,oBACXC,gBAAiB,uCACjBC,eAAgB,sBAChBC,qBAAsB,qBACtBC,wBAAyB,8BACzBC,sBAAuB,6BACvBC,gBAAiB,4BACjBC,SAAU,0BAGVC,SAAU,mBACVC,UAAW,oBAGXC,QAAS,2BACTC,kBAAmB,8BACnBC,kBAAmB,8BACnBC,mBAAoB,+BACpBC,kBAAmB,8BACnBC,kBAAmB,8BACnBC,oBAAqB,gCACrBC,oBAAqB,iCAGzBC,MACIvC,WACIwC,MAAO,WAEXjC,SACIiC,MAAO,YAEXrC,UACIqC,MAAO,WAEXpC,YACIoC,MAAO,aAEXnC,WACImC,MAAO,WAEXhC,iBACIgC,MAAO,WAEX/B,YACI+B,MAAO,WAEXC,qBACID,MAAO,eAEX9B,sBACI8B,MAAO,eAEX7B,sBACI6B,MAAO,eAEX5B,WACI4B,MAAO,cAEXzB,SACIyB,MAAO,SAAU,aACjBE,QAAS,WAEb7B,QACI2B,MAAO,SAAU,WACjBE,QAAS,UAEbX,SACIS,MAAQ,WAEZxB,cACIwB,MAAQ,WAEZvB,cACIuB,MAAQ,WAEZtB,aACIsB,MAAQ,WAEZrB,YACIqB,MAAQ,WAEZpB,SACIoB,MAAQ,UACRE,QAAS,WAEbrB,WACImB,MAAQ,SAAU,cAEtBlB,iBACIkB,MAAQ,SAAU,cAEtBjB,gBACIiB,MAAQ,WAEZd,uBACIc,MAAQ,cAEZb,iBACIa,MAAQ,WAEZZ,UACIY,MAAQ,aAQpBG,SAAQtD,QACJC,QAASH,WAIbC,YAAYL","file":"app.js.map"}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,132 +0,0 @@
|
||||
|
||||
app/login.js
|
||||
----------------
|
||||
lib/jquery-1.11.3.min.js
|
||||
app/init.js
|
||||
app/config/system_effect.js
|
||||
app/config/signature_type.js
|
||||
lib/bootstrap.min.js
|
||||
lib/bootbox.min.js
|
||||
app/ccp.js
|
||||
lib/velocity.min.js
|
||||
lib/velocity.ui.min.js
|
||||
lib/jquery.mCustomScrollbar.concat.min.js
|
||||
lib/validator.min.js
|
||||
lib/bootstrap-editable.min.js
|
||||
lib/jquery.easypiechart.min.js
|
||||
lib/jquery.hoverIntent.minified.js
|
||||
lib/bootstrap-confirmation.js
|
||||
lib/bootstrap2-toggle.min.js
|
||||
app/util.js
|
||||
lib/mustache.min.js
|
||||
app/render.js
|
||||
lib/blueimp-helper.js
|
||||
lib/blueimp-gallery.js
|
||||
lib/jquery.lazyload.min.js
|
||||
lib/EasePack.min.js
|
||||
lib/TweenLite.min.js
|
||||
app/ui/header.js
|
||||
lib/jquery.lazylinepainter-1.5.1.min.js
|
||||
app/ui/logo.js
|
||||
app/ui/demo_map.js
|
||||
app/ui/dialog/account_settings.js
|
||||
app/ui/dialog/notification.js
|
||||
app/ui/dialog/manual.js
|
||||
app/ui/dialog/releases.js
|
||||
app/ui/dialog/credit.js
|
||||
app/login.js
|
||||
lib/requirejs/text.js
|
||||
|
||||
app/mappage.js
|
||||
----------------
|
||||
lib/jquery-1.11.3.min.js
|
||||
app/init.js
|
||||
app/config/system_effect.js
|
||||
app/config/signature_type.js
|
||||
lib/bootstrap.min.js
|
||||
lib/bootbox.min.js
|
||||
app/ccp.js
|
||||
lib/velocity.min.js
|
||||
lib/velocity.ui.min.js
|
||||
lib/jquery.mCustomScrollbar.concat.min.js
|
||||
lib/validator.min.js
|
||||
lib/bootstrap-editable.min.js
|
||||
lib/jquery.easypiechart.min.js
|
||||
lib/jquery.hoverIntent.minified.js
|
||||
lib/bootstrap-confirmation.js
|
||||
lib/bootstrap2-toggle.min.js
|
||||
app/util.js
|
||||
lib/mustache.min.js
|
||||
app/render.js
|
||||
app/logging.js
|
||||
lib/requirejs/text.js
|
||||
text!img/logo.svg!strip
|
||||
text!templates/modules/header.html
|
||||
text!templates/modules/footer.html
|
||||
app/ui/dialog/notification.js
|
||||
app/ui/dialog/trust.js
|
||||
app/ui/dialog/sharing_settings.js
|
||||
app/ui/dialog/map_info.js
|
||||
app/ui/dialog/account_settings.js
|
||||
app/ui/dialog/manual.js
|
||||
app/ui/dialog/map_settings.js
|
||||
app/ui/dialog/system_effects.js
|
||||
app/ui/dialog/jump_info.js
|
||||
app/ui/dialog/delete_account.js
|
||||
lib/jquery.lazylinepainter-1.5.1.min.js
|
||||
app/ui/logo.js
|
||||
app/ui/dialog/credit.js
|
||||
lib/slidebars.js
|
||||
app/counter.js
|
||||
app/ui/system_info.js
|
||||
lib/raphael-min.js
|
||||
lib/morris.min.js
|
||||
app/ui/system_graph.js
|
||||
app/ui/system_signature.js
|
||||
app/ui/system_route.js
|
||||
app/ui/system_killboard.js
|
||||
lib/datatables/jquery.dataTables.min.js
|
||||
lib/datatables/extensions/tabletools/js/dataTables.tableTools.js
|
||||
lib/datatables/extensions/responsive/dataTables.responsive.js
|
||||
lib/dom.jsPlumb-1.7.6.js
|
||||
lib/farahey-0.5.js
|
||||
app/map/magnetizing.js
|
||||
lib/jquery.dragToSelect.js
|
||||
lib/select2.min.js
|
||||
app/map/contextmenu.js
|
||||
app/map/overlay.js
|
||||
app/map/map.js
|
||||
app/module_map.js
|
||||
app/page.js
|
||||
app/ui/form_element.js
|
||||
app/mappage.js
|
||||
|
||||
app/setup.js
|
||||
----------------
|
||||
lib/jquery-1.11.3.min.js
|
||||
app/init.js
|
||||
app/config/system_effect.js
|
||||
app/config/signature_type.js
|
||||
lib/bootstrap.min.js
|
||||
lib/bootbox.min.js
|
||||
app/ccp.js
|
||||
lib/velocity.min.js
|
||||
lib/velocity.ui.min.js
|
||||
lib/jquery.mCustomScrollbar.concat.min.js
|
||||
lib/validator.min.js
|
||||
lib/bootstrap-editable.min.js
|
||||
lib/jquery.easypiechart.min.js
|
||||
lib/jquery.hoverIntent.minified.js
|
||||
lib/bootstrap-confirmation.js
|
||||
lib/bootstrap2-toggle.min.js
|
||||
app/util.js
|
||||
app/setup.js
|
||||
|
||||
app/notification.js
|
||||
----------------
|
||||
app/init.js
|
||||
lib/pnotify/pnotify.core.js
|
||||
lib/pnotify/pnotify.nonblock.js
|
||||
lib/pnotify/pnotify.desktop.js
|
||||
lib/pnotify/pnotify.callbacks.js
|
||||
app/notification.js
|
||||
@@ -1,2 +0,0 @@
|
||||
!function(t){"use strict";"function"==typeof define&&define.amd?define(["jquery","blueImpGallery"],t):t(window.jQuery,window.blueimp.Gallery)}(function(t,o){"use strict";t.extend(o.prototype.options,{useBootstrapModal:!0});var e=o.prototype.close,n=o.prototype.imageFactory,i=o.prototype.videoFactory,r=o.prototype.textFactory;t.extend(o.prototype,{modalFactory:function(o,e,n,i){if(!this.options.useBootstrapModal||n)return i.call(this,o,e,n);var r=this,a=t(this.container).children(".modal"),c=a.clone().show().on("click",function(t){if(t.target===c[0]||t.target===c.children()[0]){t.preventDefault();t.stopPropagation();r.close()}}),l=i.call(this,o,function(t){e({type:t.type,target:c[0]});c.addClass("in")},n);c.find(".modal-title").text(l.title||String.fromCharCode(160));c.find(".modal-body").append(l);return c[0]},imageFactory:function(t,o,e){return this.modalFactory(t,o,e,n)},videoFactory:function(t,o,e){return this.modalFactory(t,o,e,i)},textFactory:function(t,o,e){return this.modalFactory(t,o,e,r)},close:function(){this.container.find(".modal").removeClass("in");e.call(this)}})});
|
||||
//# sourceMappingURL=bootstrap-image-gallery.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"sources":["bootstrap-image-gallery.js.src.js"],"names":["factory","define","amd","window","jQuery","blueimp","Gallery","$","extend","prototype","options","useBootstrapModal","close","imageFactory","videoFactory","textFactory","modalFactory","obj","callback","factoryInterface","this","call","that","modalTemplate","container","children","modal","clone","show","on","event","target","preventDefault","stopPropagation","element","type","addClass","find","text","title","String","fromCharCode","append","removeClass"],"mappings":"CAaC,SAAUA,GACP,YACsB,mBAAXC,SAAyBA,OAAOC,IAEvCD,QACI,SACA,kBACDD,GAEHA,EACIG,OAAOC,OACPD,OAAOE,QAAQC,UAGzB,SAAUC,EAAGD,GACX,YAEAC,GAAEC,OAAOF,EAAQG,UAAUC,SACvBC,mBAAmB,GAGvB,IAAIC,GAAQN,EAAQG,UAAUG,MAC1BC,EAAeP,EAAQG,UAAUI,aACjCC,EAAeR,EAAQG,UAAUK,aACjCC,EAAcT,EAAQG,UAAUM,WAEpCR,GAAEC,OAAOF,EAAQG,WAEbO,aAAc,SAAUC,EAAKC,EAAUC,EAAkBnB,GACrD,IAAKoB,KAAKV,QAAQC,mBAAqBQ,EACnC,MAAOnB,GAAQqB,KAAKD,KAAMH,EAAKC,EAAUC,EAE7C,IAAIG,GAAOF,KACPG,EAAgBhB,EAAEa,KAAKI,WAAWC,SAAS,UAC3CC,EAAQH,EAAcI,QAAQC,OACzBC,GAAG,QAAS,SAAUC,GAEnB,GAAIA,EAAMC,SAAWL,EAAM,IACnBI,EAAMC,SAAWL,EAAMD,WAAW,GAAI,CAC1CK,EAAME,gBACNF,GAAMG,iBACNX,GAAKV,WAGjBsB,EAAUlC,EAAQqB,KAAKD,KAAMH,EAAK,SAAUa,GACxCZ,GACIiB,KAAML,EAAMK,KACZJ,OAAQL,EAAM,IAElBA,GAAMU,SAAS,OAChBjB,EACPO,GAAMW,KAAK,gBAAgBC,KAAKJ,EAAQK,OAASC,OAAOC,aAAa,KACrEf,GAAMW,KAAK,eAAeK,OAAOR,EACjC,OAAOR,GAAM,IAGjBb,aAAc,SAAUI,EAAKC,EAAUC,GACnC,MAAOC,MAAKJ,aAAaC,EAAKC,EAAUC,EAAkBN,IAG9DC,aAAc,SAAUG,EAAKC,EAAUC,GACnC,MAAOC,MAAKJ,aAAaC,EAAKC,EAAUC,EAAkBL,IAG9DC,YAAa,SAAUE,EAAKC,EAAUC,GAClC,MAAOC,MAAKJ,aAAaC,EAAKC,EAAUC,EAAkBJ,IAG9DH,MAAO,WACHQ,KAAKI,UAAUa,KAAK,UAAUM,YAAY,KAC1C/B,GAAMS,KAAKD","file":"bootstrap-image-gallery.js.map"}
|
||||
@@ -1,2 +0,0 @@
|
||||
!function(e,t,a){var n=function(e,t){"use strict";e.extend(!0,t.defaults,{dom:"<'row'<'col-xs-6'l><'col-xs-6'f>r><'row'<'col-xs-12't>><'row'<'col-xs-6'i><'col-xs-6'p>>",renderer:"bootstrap"});e.extend(t.ext.classes,{sWrapper:"dataTables_wrapper form-inline dt-bootstrap",sFilterInput:"form-control input-sm",sLengthSelect:"form-control input-sm"});t.ext.renderer.pageButton.bootstrap=function(a,n,o,s,r,i){var l,d,c=new t.Api(a),u=a.oClasses,b=a.oLanguage.oPaginate,p=function(t,n){var s,f,T,x,m=function(t){t.preventDefault();e(t.currentTarget).hasClass("disabled")||c.page(t.data.action).draw(!1)};for(s=0,f=n.length;f>s;s++){x=n[s];if(e.isArray(x))p(t,x);else{l="";d="";switch(x){case"ellipsis":l="…";d="disabled";break;case"first":l=b.sFirst;d=x+(r>0?"":" disabled");break;case"previous":l=b.sPrevious;d=x+(r>0?"":" disabled");break;case"next":l=b.sNext;d=x+(i-1>r?"":" disabled");break;case"last":l=b.sLast;d=x+(i-1>r?"":" disabled");break;default:l=x+1;d=r===x?"active":""}if(l){T=e("<li>",{"class":u.sPageButton+" "+d,"aria-controls":a.sTableId,tabindex:a.iTabIndex,id:0===o&&"string"==typeof x?a.sTableId+"_"+x:null}).append(e("<a>",{href:"#"}).html(l)).appendTo(t);a.oApi._fnBindAction(T,{action:x},m)}}}};p(e(n).empty().html('<ul class="pagination"/>').children("ul"),s)};if(t.TableTools){e.extend(!0,t.TableTools.classes,{container:"DTTT btn-group",buttons:{normal:"btn btn-default",disabled:"disabled"},collection:{container:"DTTT_dropdown dropdown-menu",buttons:{normal:"",disabled:"disabled"}},print:{info:"DTTT_print_info"},select:{row:"active"}});e.extend(!0,t.TableTools.DEFAULTS.oTags,{collection:{container:"ul",button:"li",liner:"a"}})}};"function"==typeof define&&define.amd?define(["jquery",""],n):"object"==typeof exports?n(require("jquery"),require("datatables")):jQuery&&n(jQuery,jQuery.fn.dataTable)}(window,document);
|
||||
//# sourceMappingURL=dataTables.bootstrap.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"sources":["dataTables.bootstrap.js.src.js"],"names":["window","document","undefined","factory","$","DataTable","extend","defaults","dom","renderer","ext","classes","sWrapper","sFilterInput","sLengthSelect","pageButton","bootstrap","settings","host","idx","buttons","page","pages","btnDisplay","btnClass","api","Api","oClasses","lang","oLanguage","oPaginate","attach","container","i","ien","node","button","clickHandler","e","preventDefault","currentTarget","hasClass","data","action","draw","length","isArray","sFirst","sPrevious","sNext","sLast","class","sPageButton","aria-controls","sTableId","tabindex","iTabIndex","id","append","href","html","appendTo","oApi","_fnBindAction","empty","children","TableTools","normal","disabled","collection","print","info","select","row","DEFAULTS","oTags","liner","define","amd","exports","require","jQuery","fn","dataTable"],"mappings":"CAUA,SAAUA,EAAQC,EAAUC,GAE5B,GAAIC,GAAU,SAAUC,EAAGC,GAC3B,YAIAD,GAAEE,QAAQ,EAAMD,EAAUE,UACzBC,IACC,2FAGDC,SAAU,aAKXL,GAAEE,OAAQD,EAAUK,IAAIC,SACvBC,SAAe,8CACfC,aAAe,wBACfC,cAAe,yBAKhBT,GAAUK,IAAID,SAASM,WAAWC,UAAY,SAAWC,EAAUC,EAAMC,EAAKC,EAASC,EAAMC,GAC5F,GAGIC,GAAYC,EAHZC,EAAU,GAAIpB,GAAUqB,IAAKT,GAC7BN,EAAUM,EAASU,SACnBC,EAAUX,EAASY,UAAUC,UAG7BC,EAAS,SAAUC,EAAWZ,GACjC,GAAIa,GAAGC,EAAKC,EAAMC,EACdC,EAAe,SAAWC,GAC7BA,EAAEC,gBACInC,GAAEkC,EAAEE,eAAeC,SAAS,aACjChB,EAAIJ,KAAMiB,EAAEI,KAAKC,QAASC,MAAM,GAIlC,KAAMX,EAAE,EAAGC,EAAId,EAAQyB,OAAWX,EAAFD,EAAQA,IAAM,CAC7CG,EAAShB,EAAQa,EAEjB,IAAK7B,EAAE0C,QAASV,GACfL,EAAQC,EAAWI,OAEf,CACJb,EAAa,EACbC,GAAW,EAEX,QAASY,GACR,IAAK,WACJb,EAAa,UACbC,GAAW,UACX,MAED,KAAK,QACJD,EAAaK,EAAKmB,MAClBvB,GAAWY,GAAUf,EAAO,EAC3B,GAAK,YACN,MAED,KAAK,WACJE,EAAaK,EAAKoB,SAClBxB,GAAWY,GAAUf,EAAO,EAC3B,GAAK,YACN,MAED,KAAK,OACJE,EAAaK,EAAKqB,KAClBzB,GAAWY,GAAiBd,EAAM,EAAbD,EACpB,GAAK,YACN,MAED,KAAK,OACJE,EAAaK,EAAKsB,KAClB1B,GAAWY,GAAiBd,EAAM,EAAbD,EACpB,GAAK,YACN,MAED,SACCE,EAAaa,EAAS,CACtBZ,GAAWH,IAASe,EACnB,SAAW,GAId,GAAKb,EAAa,CACjBY,EAAO/B,EAAE,QACP+C,QAASxC,EAAQyC,YAAY,IAAI5B,EACjC6B,gBAAiBpC,EAASqC,SAC1BC,SAAYtC,EAASuC,UACrBC,GAAc,IAARtC,GAA+B,gBAAXiB,GACzBnB,EAASqC,SAAU,IAAKlB,EACxB,OAEDsB,OAAQtD,EAAE,OACTuD,KAAQ,MAERC,KAAMrC,IAEPsC,SAAU7B,EAEZf,GAAS6C,KAAKC,cACb5B,GAAOQ,OAAQP,GAASC,MAO7BN,GACC3B,EAAEc,GAAM8C,QAAQJ,KAAK,4BAA4BK,SAAS,MAC1D7C,GASF,IAAKf,EAAU6D,WAAa,CAE3B9D,EAAEE,QAAQ,EAAMD,EAAU6D,WAAWvD,SACpCqB,UAAa,iBACbZ,SACC+C,OAAU,kBACVC,SAAY,YAEbC,YACCrC,UAAa,8BACbZ,SACC+C,OAAU,GACVC,SAAY,aAGdE,OACCC,KAAQ,mBAETC,QACCC,IAAO,WAKTrE,GAAEE,QAAQ,EAAMD,EAAU6D,WAAWQ,SAASC,OAC7CN,YACCrC,UAAa,KACbI,OAAU,KACVwC,MAAS,QASW,mBAAXC,SAAyBA,OAAOC,IAC3CD,QAAS,SAAU,IAAK1E,GAEI,gBAAZ4E,SAEb5E,EAAS6E,QAAQ,UAAWA,QAAQ,eAE9BC,QAET9E,EAAS8E,OAAQA,OAAOC,GAAGC,YAIzBnF,OAAQC","file":"dataTables.bootstrap.js.map"}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -45,7 +45,7 @@ requirejs.config({
|
||||
hoverIntent: 'lib/jquery.hoverIntent.minified', // v1.8.0 Hover intention - http://cherne.net/brian/resources/jquery.hoverIntent.html
|
||||
fullScreen: 'lib/jquery.fullscreen.min', // v0.5.0 Full screen mode - https://github.com/private-face/jquery.fullscreen
|
||||
select2: 'lib/select2.min', // v4.0.0 Drop Down customization - https://select2.github.io/
|
||||
validator: 'lib/validator.min', // v0.7.2 Validator for Bootstrap 3 - https://github.com/1000hz/bootstrap-validator
|
||||
validator: 'lib/validator.min', // v0.10.1 Validator for Bootstrap 3 - https://github.com/1000hz/bootstrap-validator
|
||||
lazylinepainter: 'lib/jquery.lazylinepainter-1.5.1.min', // v1.5.1 SVG line animation plugin - http://lazylinepainter.info/
|
||||
blueImpGallery: 'lib/blueimp-gallery', // v2.15.2 Image Gallery - https://github.com/blueimp/Gallery/
|
||||
blueImpGalleryHelper: 'lib/blueimp-helper', // helper function for Blue Imp Gallery
|
||||
60
public/js/v1.0.0RC3/app/ccp.js
Normal file
60
public/js/v1.0.0RC3/app/ccp.js
Normal file
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Global CCPEvE function wrapper
|
||||
*/
|
||||
|
||||
define(['jquery'], function($) {
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* checks weather the program URL is IGB trusted or not
|
||||
* @returns {boolean}
|
||||
*/
|
||||
var isTrusted = function(){
|
||||
var isPageTrusted = false;
|
||||
|
||||
if(isInGameBrowser()){
|
||||
var trustedAttribute = $('body').attr('data-trusted');
|
||||
if(trustedAttribute === '1'){
|
||||
isPageTrusted = true;
|
||||
}
|
||||
}else{
|
||||
// out of game browser is always trusted
|
||||
isPageTrusted = true;
|
||||
}
|
||||
|
||||
return isPageTrusted;
|
||||
};
|
||||
|
||||
/**
|
||||
* show IGB trust message
|
||||
*/
|
||||
var requestTrust = function(){
|
||||
|
||||
if(
|
||||
isInGameBrowser() &&
|
||||
!isTrusted()
|
||||
){
|
||||
CCPEVE.requestTrust( location.protocol + '//' + location.host );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* in-game or out-of-game browser
|
||||
* @returns {boolean}
|
||||
*/
|
||||
var isInGameBrowser = function(){
|
||||
var inGame = false;
|
||||
if(typeof CCPEVE === 'object'){
|
||||
inGame = true;
|
||||
}
|
||||
|
||||
return inGame;
|
||||
};
|
||||
|
||||
return {
|
||||
isInGameBrowser: isInGameBrowser,
|
||||
isTrusted: isTrusted,
|
||||
requestTrust: requestTrust
|
||||
};
|
||||
});
|
||||
340
public/js/v1.0.0RC3/app/config/signature_type.js
Normal file
340
public/js/v1.0.0RC3/app/config/signature_type.js
Normal file
@@ -0,0 +1,340 @@
|
||||
/**
|
||||
* Created by exodus4d on 06.07.2015.
|
||||
* static signature types
|
||||
*
|
||||
* (*) marked fields are in-game verified and
|
||||
* proofed, signature names (copy & paste from scanning window)
|
||||
*/
|
||||
|
||||
define([], function() {
|
||||
|
||||
'use strict';
|
||||
|
||||
// system effects
|
||||
var signatureTypes = {
|
||||
1: { // system type (wh)
|
||||
1: { // C1 (area id)
|
||||
1: { // Combat
|
||||
1: 'Perimeter Ambush Point',
|
||||
2: 'Perimeter Camp',
|
||||
3: 'Phase Catalyst Node',
|
||||
4: 'The Line'
|
||||
},
|
||||
2: { // Relic
|
||||
1: 'Forgotten Perimeter Coronation Platform',
|
||||
2: 'Forgotten Perimeter Power Array'
|
||||
},
|
||||
3: { // Data
|
||||
1: 'Unsecured Perimeter Amplifier',
|
||||
2: 'Unsecured Perimeter Information Center '
|
||||
},
|
||||
4: { // Gas
|
||||
1: 'Barren Perimeter Reservoir', //*
|
||||
2: 'Token Perimeter Reservoir', //*
|
||||
3: 'Minor Perimeter Reservoir', //*
|
||||
4: 'Sizeable Perimeter Reservoir', //*
|
||||
5: 'Ordinary Perimeter Reservoir' //*
|
||||
},
|
||||
5: { // Wormhole
|
||||
1: 'H121 - C1',
|
||||
2: 'C125 - C2',
|
||||
3: 'O883 - C3',
|
||||
4: 'M609 - C4',
|
||||
5: 'L614 - C5',
|
||||
6: 'S804 - C6'
|
||||
},
|
||||
6: { // ORE
|
||||
1: 'Ordinary Perimeter Deposit', //*
|
||||
2: 'Common Perimeter Deposit', //*
|
||||
3: 'Unexceptional Frontier Deposit', //*
|
||||
4: 'Average Frontier Deposit', //*
|
||||
5: 'Isolated Core Deposit', //*
|
||||
6: 'Uncommon Core Deposit' //*
|
||||
},
|
||||
7: { // Ghost
|
||||
|
||||
}
|
||||
},
|
||||
2: { // C2
|
||||
1: { // Combat
|
||||
1: 'Perimeter Checkpoint',
|
||||
2: 'Perimeter Hangar',
|
||||
3: 'The Ruins of Enclave Cohort 27',
|
||||
4: 'Sleeper Data Sanctuary'
|
||||
},
|
||||
2: { // Relic
|
||||
1: 'Forgotten Perimeter Gateway',
|
||||
2: 'Forgotten Perimeter Habitation Coils'
|
||||
},
|
||||
3: { // Data
|
||||
1: 'Unsecured Perimeter Comms Relay',
|
||||
2: 'Unsecured Perimeter Transponder Farm '
|
||||
},
|
||||
4: { // Gas
|
||||
1: 'Barren Perimeter Reservoir', //*
|
||||
2: 'Token Perimeter Reservoir', //*
|
||||
3: 'Minor Perimeter Reservoir', //*
|
||||
4: 'Sizeable Perimeter Reservoir', //*
|
||||
5: 'Ordinary Perimeter Reservoir' //*
|
||||
},
|
||||
5: { // Wormhole
|
||||
// no *wandering* w-space -> k-space wormholes
|
||||
// all holes are statics or K162
|
||||
},
|
||||
6: { // ORE
|
||||
1: 'Ordinary Perimeter Deposit', //*
|
||||
2: 'Common Perimeter Deposit', //*
|
||||
3: 'Unexceptional Frontier Deposit', //*
|
||||
4: 'Average Frontier Deposit', //*
|
||||
5: 'Isolated Core Deposit', //*
|
||||
6: 'Uncommon Core Deposit' //*
|
||||
},
|
||||
7: { // Ghost
|
||||
|
||||
}
|
||||
},
|
||||
3: { // C3
|
||||
1: { // Combat
|
||||
1: 'Fortification Frontier Stronghold',
|
||||
2: 'Outpost Frontier Stronghold',
|
||||
3: 'Solar Cell',
|
||||
4: 'The Oruze Construct'
|
||||
},
|
||||
2: { // Relic
|
||||
1: 'Forgotten Frontier Quarantine Outpost',
|
||||
2: 'Forgotten Frontier Recursive Depot'
|
||||
},
|
||||
3: { // Data
|
||||
1: 'Unsecured Frontier Database',
|
||||
2: 'Unsecured Frontier Receiver'
|
||||
},
|
||||
4: { // Gas
|
||||
1: 'Barren Perimeter Reservoir', //*
|
||||
2: 'Token Perimeter Reservoir', //*
|
||||
3: 'Minor Perimeter Reservoir', //*
|
||||
4: 'Sizeable Perimeter Reservoir', //*
|
||||
5: 'Ordinary Perimeter Reservoir', //*
|
||||
6: 'Bountiful Frontier Reservoir', //*
|
||||
7: 'Vast Frontier Reservoir' //*
|
||||
},
|
||||
5: { // Wormhole
|
||||
1: 'V301 - C1',
|
||||
2: 'I182 - C2',
|
||||
3: 'N968 - C3',
|
||||
4: 'T405 - C4',
|
||||
5: 'N770 - C5',
|
||||
6: 'A982 - C6'
|
||||
},
|
||||
6: { // ORE
|
||||
1: 'Ordinary Perimeter Deposit', //*
|
||||
2: 'Common Perimeter Deposit', //*
|
||||
3: 'Unexceptional Frontier Deposit', //*
|
||||
4: 'Average Frontier Deposit', //*
|
||||
5: 'Infrequent Core Deposit', //*
|
||||
6: 'Unusual Core Deposit' //*
|
||||
},
|
||||
7: { // Ghost
|
||||
|
||||
}
|
||||
},
|
||||
4: { // C4
|
||||
1: { // Combat
|
||||
1: 'Frontier Barracks',
|
||||
2: 'Frontier Command Post',
|
||||
3: 'Integrated Terminus',
|
||||
4: 'Sleeper Information Sanctum'
|
||||
},
|
||||
2: { // Relic
|
||||
1: 'Forgotten Frontier Conversion Module',
|
||||
2: 'Forgotten Frontier Evacuation Center'
|
||||
},
|
||||
3: { // Data
|
||||
1: 'Unsecured Frontier Digital Nexus',
|
||||
2: 'Unsecured Frontier Trinary Hub'
|
||||
},
|
||||
4: { // Gas
|
||||
1: 'Barren Perimeter Reservoir', //*
|
||||
2: 'Token Perimeter Reservoir', //*
|
||||
3: 'Minor Perimeter Reservoir', //*
|
||||
4: 'Sizeable Perimeter Reservoir', //*
|
||||
5: 'Ordinary Perimeter Reservoir', //*
|
||||
6: 'Vast Frontier Reservoir' //*
|
||||
},
|
||||
5: { // Wormhole
|
||||
// no *wandering* w-space -> k-space wormholes
|
||||
// all holes are statics or K162
|
||||
},
|
||||
6: { // ORE
|
||||
1: 'Ordinary Perimeter Deposit', //*
|
||||
2: 'Common Perimeter Deposit', //*
|
||||
3: 'Unexceptional Frontier Deposit', //*
|
||||
4: 'Average Frontier Deposit', //*
|
||||
5: 'Unusual Core Deposit' //*
|
||||
},
|
||||
7: { // Ghost
|
||||
|
||||
}
|
||||
},
|
||||
5: { // C5
|
||||
1: { // Combat
|
||||
1: 'Core Garrison', //*
|
||||
2: 'Core Stronghold', //*
|
||||
3: 'Oruze Osobnyk', //*
|
||||
4: 'Quarantine Area'
|
||||
},
|
||||
2: { // Relic
|
||||
1: 'Forgotten Core Data Field',
|
||||
2: 'Forgotten Core Information Pen'
|
||||
},
|
||||
3: { // Data
|
||||
1: 'Unsecured Frontier Enclave Relay',
|
||||
2: 'Unsecured Frontier Server Bank'
|
||||
},
|
||||
4: { // Gas
|
||||
1: 'Barren Perimeter Reservoir', //*
|
||||
2: 'Token Perimeter Reservoir', //*
|
||||
3: 'Sizeable Perimeter Reservoir', //*
|
||||
4: 'Ordinary Perimeter Reservoir', //*
|
||||
5: 'Bountiful Frontier Reservoir', //*
|
||||
6: 'Instrumental Core Reservoir', //*
|
||||
7: 'Vital Core Reservoir', //*
|
||||
8: 'Minor Perimeter Reservoir' //*
|
||||
},
|
||||
5: { // Wormhole
|
||||
1: 'D792 - HS',
|
||||
2: 'C140 - LS',
|
||||
3: 'Z142 - 0.0'
|
||||
},
|
||||
6: { // ORE
|
||||
1: 'Ordinary Perimeter Deposit', //*
|
||||
2: 'Common Perimeter Deposit', //*
|
||||
3: 'Rarified Core Deposit' //*
|
||||
},
|
||||
7: { // Ghost
|
||||
|
||||
}
|
||||
},
|
||||
6: { // C6
|
||||
1: { // Combat
|
||||
1: 'Core Citadel', //*
|
||||
2: 'Core Bastion', //*
|
||||
3: 'Strange Energy Readings', //*
|
||||
4: 'The Mirror' //*
|
||||
},
|
||||
2: { // Relic
|
||||
1: 'Forgotten Core Assembly Hall', //*
|
||||
2: 'Forgotten Core Circuitry Disassembler' //*
|
||||
},
|
||||
3: { // Data
|
||||
1: 'Unsecured Core Backup Array', //*
|
||||
2: 'Unsecured Core Emergence' //*
|
||||
},
|
||||
4: { // Gas
|
||||
1: 'Token Perimeter Reservoir', //*
|
||||
2: 'Minor Perimeter Reservoir', //*
|
||||
3: 'Sizeable Perimeter Reservoir', //*
|
||||
4: 'Ordinary Perimeter Reservoir', //*
|
||||
5: 'Bountiful Frontier Reservoir', //*
|
||||
6: 'Vast Frontier Reservoir', //*
|
||||
7: 'Instrumental Core Reservoir', //*
|
||||
8: 'Vital Core Reservoir' //*
|
||||
},
|
||||
5: { // Wormhole
|
||||
1: 'D792 - HS',
|
||||
2: 'C391 - LS',
|
||||
3: 'Z142 - 0.0'
|
||||
},
|
||||
6: { // ORE
|
||||
1: 'Ordinary Perimeter Deposit', //*
|
||||
2: 'Common Perimeter Deposit', //*
|
||||
3: 'Unexceptional Frontier Deposit', //*
|
||||
4: 'Average Frontier Deposit', //*
|
||||
5: 'Rarified Core Deposit' //*
|
||||
},
|
||||
7: { // Ghost
|
||||
1: 'Superior Blood Raider Covert Research Facility' //*
|
||||
}
|
||||
},
|
||||
13: { // Shattered Wormholes
|
||||
5: { // Wormhole (some of them are static)
|
||||
1: 'P060 - C1',
|
||||
2: 'Z647 - C1',
|
||||
3: 'D382 - C2',
|
||||
4: 'L005 - C2',
|
||||
5: 'N766 - C2',
|
||||
6: 'C247 - C3',
|
||||
7: 'K346 - C3',
|
||||
8: 'M267 - C3',
|
||||
9: 'O477 - C3',
|
||||
10: 'X877 - C4',
|
||||
11: 'Y683 - C4',
|
||||
12: 'H296 - C5',
|
||||
13: 'H900 - C5',
|
||||
14: 'H296 - C5',
|
||||
15: 'N062 - C5',
|
||||
16: 'V911 - C5',
|
||||
17: 'U574 - C6',
|
||||
18: 'V753 - C6',
|
||||
19: 'W237 - C6',
|
||||
20: 'B274 - HS',
|
||||
21: 'D792 - HS',
|
||||
22: 'D845 - HS',
|
||||
23: 'N110 - HS',
|
||||
24: 'A239 - LS',
|
||||
25: 'C391 - LS',
|
||||
26: 'J244 - LS',
|
||||
27: 'U201 - LS',
|
||||
28: 'U210 - LS',
|
||||
29: 'C248 - NS',
|
||||
30: 'E545 - NS',
|
||||
31: 'K346 - NS',
|
||||
32: 'Z060 - NS'
|
||||
}
|
||||
}
|
||||
}, // system type (k-space)
|
||||
2: {
|
||||
10: { // High Sec
|
||||
5: { // Wormhole
|
||||
1: 'Z971 - C1',
|
||||
2: 'R943 - C2',
|
||||
3: 'X702 - C3',
|
||||
// no C4
|
||||
4: 'M555 - C5',
|
||||
5: 'B041 - C6',
|
||||
6: 'A641 - HS',
|
||||
7: 'R051 - LS',
|
||||
8: 'V283 - NS'
|
||||
}
|
||||
},
|
||||
11: { // Low Sec
|
||||
5: { // Wormhole
|
||||
1: 'Z971 - C1',
|
||||
2: 'R943 - C2',
|
||||
3: 'X702 - C3',
|
||||
// no C4
|
||||
4: 'N432 - C5',
|
||||
5: 'U319 - C6',
|
||||
6: 'B449 - HS',
|
||||
7: 'N944 - LS',
|
||||
8: 'S199 - NS'
|
||||
}
|
||||
},
|
||||
12: { // 0.0
|
||||
5: { // Wormhole
|
||||
1: 'Z971 - C1',
|
||||
2: 'R943 - C2',
|
||||
3: 'X702 - C3',
|
||||
// no C4
|
||||
4: 'N432 - C5',
|
||||
5: 'U319 - C6',
|
||||
6: 'B449 - HS',
|
||||
7: 'N944 - LS',
|
||||
8: 'S199 - NS'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return signatureTypes;
|
||||
});
|
||||
733
public/js/v1.0.0RC3/app/config/system_effect.js
Normal file
733
public/js/v1.0.0RC3/app/config/system_effect.js
Normal file
@@ -0,0 +1,733 @@
|
||||
/**
|
||||
* Created by exodus4d on 06.07.2015.
|
||||
* static system effects
|
||||
*/
|
||||
|
||||
|
||||
define([], function() {
|
||||
|
||||
'use strict';
|
||||
|
||||
// system effects
|
||||
var systemEffects = {
|
||||
wh: {
|
||||
magnetar: {
|
||||
1: [
|
||||
{
|
||||
effect: 'Damage',
|
||||
value: '+30%'
|
||||
},{
|
||||
effect: 'Missile explosion radius',
|
||||
value: '+15%'
|
||||
},{
|
||||
effect: 'Drone Tracking',
|
||||
value: '-15%'
|
||||
},{
|
||||
effect: 'Targeting Range',
|
||||
value: '-15%'
|
||||
},{
|
||||
effect: 'Tracking Speed',
|
||||
value: '-15%'
|
||||
},{
|
||||
effect: 'Target Painter Strength',
|
||||
value: '-15%'
|
||||
}
|
||||
],
|
||||
2: [
|
||||
{
|
||||
effect: 'Damage',
|
||||
value: '+44%'
|
||||
},{
|
||||
effect: 'Missile explosion radius',
|
||||
value: '+22%'
|
||||
},{
|
||||
effect: 'Drone Tracking',
|
||||
value: '-22%'
|
||||
},{
|
||||
effect: 'Targeting Range',
|
||||
value: '-22%'
|
||||
},{
|
||||
effect: 'Tracking Speed',
|
||||
value: '-22%'
|
||||
},{
|
||||
effect: 'Target Painter Strength',
|
||||
value: '-22%'
|
||||
}
|
||||
],
|
||||
3: [
|
||||
{
|
||||
effect: 'Damage',
|
||||
value: '+58%'
|
||||
},{
|
||||
effect: 'Missile explosion radius',
|
||||
value: '+29%'
|
||||
},{
|
||||
effect: 'Drone Tracking',
|
||||
value: '-29%'
|
||||
},{
|
||||
effect: 'Targeting Range',
|
||||
value: '-29%'
|
||||
},{
|
||||
effect: 'Tracking Speed',
|
||||
value: '-29%'
|
||||
},{
|
||||
effect: 'Target Painter Strength',
|
||||
value: '-29%'
|
||||
}
|
||||
],
|
||||
4: [
|
||||
{
|
||||
effect: 'Damage',
|
||||
value: '+72%'
|
||||
},{
|
||||
effect: 'Missile explosion radius',
|
||||
value: '+36%'
|
||||
},{
|
||||
effect: 'Drone Tracking',
|
||||
value: '-36%'
|
||||
},{
|
||||
effect: 'Targeting Range',
|
||||
value: '-36%'
|
||||
},{
|
||||
effect: 'Tracking Speed',
|
||||
value: '-36%'
|
||||
},{
|
||||
effect: 'Target Painter Strength',
|
||||
value: '-36%'
|
||||
}
|
||||
],
|
||||
5: [
|
||||
{
|
||||
effect: 'Damage',
|
||||
value: '+86%'
|
||||
},{
|
||||
effect: 'Missile explosion radius',
|
||||
value: '+43%'
|
||||
},{
|
||||
effect: 'Drone Tracking',
|
||||
value: '-43%'
|
||||
},{
|
||||
effect: 'Targeting Range',
|
||||
value: '-43%'
|
||||
},{
|
||||
effect: 'Tracking Speed',
|
||||
value: '-43%'
|
||||
},{
|
||||
effect: 'Target Painter Strength',
|
||||
value: '-43%'
|
||||
}
|
||||
],
|
||||
6: [
|
||||
{
|
||||
effect: 'Damage',
|
||||
value: '+100%'
|
||||
},{
|
||||
effect: 'Missile explosion radius',
|
||||
value: '+50%'
|
||||
},{
|
||||
effect: 'Drone Tracking',
|
||||
value: '-50%'
|
||||
},{
|
||||
effect: 'Targeting Range',
|
||||
value: '-50%'
|
||||
},{
|
||||
effect: 'Tracking Speed',
|
||||
value: '-50%'
|
||||
},{
|
||||
effect: 'Target Painter Strength',
|
||||
value: '-50%'
|
||||
}
|
||||
]
|
||||
},
|
||||
redGiant: {
|
||||
1: [
|
||||
{
|
||||
effect: 'Heat Damage',
|
||||
value: '+15%'
|
||||
},{
|
||||
effect: 'Overload Bonus',
|
||||
value: '+30%'
|
||||
},{
|
||||
effect: 'Smart Bomb Range',
|
||||
value: '+30%'
|
||||
},{
|
||||
effect: 'Smart Bomb Damage',
|
||||
value: '+30%'
|
||||
},{
|
||||
effect: 'Bomb Damage',
|
||||
value: '+30%'
|
||||
}
|
||||
],
|
||||
2: [
|
||||
{
|
||||
effect: 'Heat Damage',
|
||||
value: '+22%'
|
||||
},{
|
||||
effect: 'Overload Bonus',
|
||||
value: '+44%'
|
||||
},{
|
||||
effect: 'Smart Bomb Range',
|
||||
value: '+44%'
|
||||
},{
|
||||
effect: 'Smart Bomb Damage',
|
||||
value: '+44%'
|
||||
},{
|
||||
effect: 'Bomb Damage',
|
||||
value: '+44%'
|
||||
}
|
||||
],
|
||||
3: [
|
||||
{
|
||||
effect: 'Heat Damage',
|
||||
value: '+29%'
|
||||
},{
|
||||
effect: 'Overload Bonus',
|
||||
value: '+58%'
|
||||
},{
|
||||
effect: 'Smart Bomb Range',
|
||||
value: '+58%'
|
||||
},{
|
||||
effect: 'Smart Bomb Damage',
|
||||
value: '+58%'
|
||||
},{
|
||||
effect: 'Bomb Damage',
|
||||
value: '+58%'
|
||||
}
|
||||
],
|
||||
4: [
|
||||
{
|
||||
effect: 'Heat Damage',
|
||||
value: '+36%'
|
||||
},{
|
||||
effect: 'Overload Bonus',
|
||||
value: '+72%'
|
||||
},{
|
||||
effect: 'Smart Bomb Range',
|
||||
value: '+72%'
|
||||
},{
|
||||
effect: 'Smart Bomb Damage',
|
||||
value: '+72%'
|
||||
},{
|
||||
effect: 'Bomb Damage',
|
||||
value: '+72%'
|
||||
}
|
||||
],
|
||||
5: [
|
||||
{
|
||||
effect: 'Heat Damage',
|
||||
value: '+43%'
|
||||
},{
|
||||
effect: 'Overload Bonus',
|
||||
value: '+86%'
|
||||
},{
|
||||
effect: 'Smart Bomb Range',
|
||||
value: '+86%'
|
||||
},{
|
||||
effect: 'Smart Bomb Damage',
|
||||
value: '+86%'
|
||||
},{
|
||||
effect: 'Bomb Damage',
|
||||
value: '+86%'
|
||||
}
|
||||
],
|
||||
6: [
|
||||
{
|
||||
effect: 'Heat Damage',
|
||||
value: '+50%'
|
||||
},{
|
||||
effect: 'Overload Bonus',
|
||||
value: '+100%'
|
||||
},{
|
||||
effect: 'Smart Bomb Range',
|
||||
value: '+100%'
|
||||
},{
|
||||
effect: 'Smart Bomb Damage',
|
||||
value: '+100%'
|
||||
},{
|
||||
effect: 'Bomb Damage',
|
||||
value: '+100%'
|
||||
}
|
||||
]
|
||||
},
|
||||
pulsar: {
|
||||
1: [
|
||||
{
|
||||
effect: 'Shield HP',
|
||||
value: '+30%'
|
||||
},{
|
||||
effect: 'Armor Resists',
|
||||
value: '-15%'
|
||||
},{
|
||||
effect: 'Capacitor recharge',
|
||||
value: '-15%'
|
||||
},{
|
||||
effect: 'Signature',
|
||||
value: '+30%'
|
||||
},{
|
||||
effect: 'NOS / Neut Drain Amount',
|
||||
value: '+30%'
|
||||
}
|
||||
],
|
||||
2: [
|
||||
{
|
||||
effect: 'Shield HP',
|
||||
value: '+44%'
|
||||
},{
|
||||
effect: 'Armor Resists',
|
||||
value: '-22%'
|
||||
},{
|
||||
effect: 'Capacitor recharge',
|
||||
value: '-22%'
|
||||
},{
|
||||
effect: 'Signature',
|
||||
value: '+44%'
|
||||
},{
|
||||
effect: 'NOS / Neut Drain Amount',
|
||||
value: '+44%'
|
||||
}
|
||||
],
|
||||
3: [
|
||||
{
|
||||
effect: 'Shield HP',
|
||||
value: '+58%'
|
||||
},{
|
||||
effect: 'Armor Resists',
|
||||
value: '-29%'
|
||||
},{
|
||||
effect: 'Capacitor recharge',
|
||||
value: '-29%'
|
||||
},{
|
||||
effect: 'Signature',
|
||||
value: '+58%'
|
||||
},{
|
||||
effect: 'NOS / Neut Drain Amount',
|
||||
value: '+58%'
|
||||
}
|
||||
],
|
||||
4: [
|
||||
{
|
||||
effect: 'Shield HP',
|
||||
value: '+72%'
|
||||
},{
|
||||
effect: 'Armor Resists',
|
||||
value: '-36%'
|
||||
},{
|
||||
effect: 'Capacitor recharge',
|
||||
value: '-36%'
|
||||
},{
|
||||
effect: 'Signature',
|
||||
value: '+72%'
|
||||
},{
|
||||
effect: 'NOS / Neut Drain Amount',
|
||||
value: '+72%'
|
||||
}
|
||||
],
|
||||
5: [
|
||||
{
|
||||
effect: 'Shield HP',
|
||||
value: '+86%'
|
||||
},{
|
||||
effect: 'Armor Resists',
|
||||
value: '-43%'
|
||||
},{
|
||||
effect: 'Capacitor recharge',
|
||||
value: '-43%'
|
||||
},{
|
||||
effect: 'Signature',
|
||||
value: '+86%'
|
||||
},{
|
||||
effect: 'NOS / Neut Drain Amount',
|
||||
value: '+86%'
|
||||
}
|
||||
],
|
||||
6: [
|
||||
{
|
||||
effect: 'Shield HP',
|
||||
value: '+100%'
|
||||
},{
|
||||
effect: 'Armor Resists',
|
||||
value: '-50%'
|
||||
},{
|
||||
effect: 'Capacitor recharge',
|
||||
value: '-50%'
|
||||
},{
|
||||
effect: 'Signature',
|
||||
value: '+100%'
|
||||
},{
|
||||
effect: 'NOS / Neut Drain Amount',
|
||||
value: '+100%'
|
||||
}
|
||||
]
|
||||
},
|
||||
wolfRayet: {
|
||||
1: [
|
||||
{
|
||||
effect: 'Armor HP',
|
||||
value: '+30%'
|
||||
},{
|
||||
effect: 'Shield Resist',
|
||||
value: '-15%'
|
||||
},{
|
||||
effect: 'Small Weapon Damage',
|
||||
value: '+60%'
|
||||
},{
|
||||
effect: 'Signature Size',
|
||||
value: '-15%'
|
||||
}
|
||||
],
|
||||
2: [
|
||||
{
|
||||
effect: 'Armor HP',
|
||||
value: '+44%'
|
||||
},{
|
||||
effect: 'Shield Resist',
|
||||
value: '-22%'
|
||||
},{
|
||||
effect: 'Small Weapon Damage',
|
||||
value: '+88%'
|
||||
},{
|
||||
effect: 'Signature Size',
|
||||
value: '-22%'
|
||||
}
|
||||
],
|
||||
3: [
|
||||
{
|
||||
effect: 'Armor HP',
|
||||
value: '+58%'
|
||||
},{
|
||||
effect: 'Shield Resist',
|
||||
value: '-29%'
|
||||
},{
|
||||
effect: 'Small Weapon Damage',
|
||||
value: '+116%'
|
||||
},{
|
||||
effect: 'Signature Size',
|
||||
value: '-29%'
|
||||
}
|
||||
],
|
||||
4: [
|
||||
{
|
||||
effect: 'Armor HP',
|
||||
value: '+72%'
|
||||
},{
|
||||
effect: 'Shield Resist',
|
||||
value: '-36%'
|
||||
},{
|
||||
effect: 'Small Weapon Damage',
|
||||
value: '+144%'
|
||||
},{
|
||||
effect: 'Signature Size',
|
||||
value: '-36%'
|
||||
}
|
||||
],
|
||||
5: [
|
||||
{
|
||||
effect: 'Armor HP',
|
||||
value: '+86%'
|
||||
},{
|
||||
effect: 'Shield Resist',
|
||||
value: '-43%'
|
||||
},{
|
||||
effect: 'Small Weapon Damage',
|
||||
value: '+172%'
|
||||
},{
|
||||
effect: 'Signature Size',
|
||||
value: '-43%'
|
||||
}
|
||||
],
|
||||
6: [
|
||||
{
|
||||
effect: 'Armor HP',
|
||||
value: '+100%'
|
||||
},{
|
||||
effect: 'Shield Resist',
|
||||
value: '-50%'
|
||||
},{
|
||||
effect: 'Small Weapon Damage',
|
||||
value: '+200%'
|
||||
},{
|
||||
effect: 'Signature Size',
|
||||
value: '-50%'
|
||||
}
|
||||
]
|
||||
},
|
||||
cataclysmic: {
|
||||
1: [
|
||||
{
|
||||
effect: 'Local armor repair amount',
|
||||
value: '-15%'
|
||||
},{
|
||||
effect: 'Local shield boost amount',
|
||||
value: '-15%'
|
||||
},{
|
||||
effect: 'Shield transfer amount',
|
||||
value: '+30%'
|
||||
},{
|
||||
effect: 'Remote repair amount',
|
||||
value: '+30%'
|
||||
},{
|
||||
effect: 'Capacitor capacity',
|
||||
value: '+30%'
|
||||
},{
|
||||
effect: 'Capacitor recharge time',
|
||||
value: '+15%'
|
||||
},{
|
||||
effect: 'Remote Capacitor Transmitter amount',
|
||||
value: '-15%'
|
||||
}
|
||||
],
|
||||
2: [
|
||||
{
|
||||
effect: 'Local armor repair amount',
|
||||
value: '-22%'
|
||||
},{
|
||||
effect: 'Local shield boost amount',
|
||||
value: '-22%'
|
||||
},{
|
||||
effect: 'Shield transfer amount',
|
||||
value: '+44%'
|
||||
},{
|
||||
effect: 'Remote repair amount',
|
||||
value: '+44%'
|
||||
},{
|
||||
effect: 'Capacitor capacity',
|
||||
value: '+44%'
|
||||
},{
|
||||
effect: 'Capacitor recharge time',
|
||||
value: '+22%'
|
||||
},{
|
||||
effect: 'Remote Capacitor Transmitter amount',
|
||||
value: '-22%'
|
||||
}
|
||||
],
|
||||
3: [
|
||||
{
|
||||
effect: 'Local armor repair amount',
|
||||
value: '-29%'
|
||||
},{
|
||||
effect: 'Local shield boost amount',
|
||||
value: '-29%'
|
||||
},{
|
||||
effect: 'Shield transfer amount',
|
||||
value: '+58%'
|
||||
},{
|
||||
effect: 'Remote repair amount',
|
||||
value: '+58%'
|
||||
},{
|
||||
effect: 'Capacitor capacity',
|
||||
value: '+58%'
|
||||
},{
|
||||
effect: 'Capacitor recharge time',
|
||||
value: '+29%'
|
||||
},{
|
||||
effect: 'Remote Capacitor Transmitter amount',
|
||||
value: '-29%'
|
||||
}
|
||||
],
|
||||
4: [
|
||||
{
|
||||
effect: 'Local armor repair amount',
|
||||
value: '-36%'
|
||||
},{
|
||||
effect: 'Local shield boost amount',
|
||||
value: '-36%'
|
||||
},{
|
||||
effect: 'Shield transfer amount',
|
||||
value: '+72%'
|
||||
},{
|
||||
effect: 'Remote repair amount',
|
||||
value: '+72%'
|
||||
},{
|
||||
effect: 'Capacitor capacity',
|
||||
value: '+72%'
|
||||
},{
|
||||
effect: 'Capacitor recharge time',
|
||||
value: '+36%'
|
||||
},{
|
||||
effect: 'Remote Capacitor Transmitter amount',
|
||||
value: '-36%'
|
||||
}
|
||||
],
|
||||
5: [
|
||||
{
|
||||
effect: 'Local armor repair amount',
|
||||
value: '-43%'
|
||||
},{
|
||||
effect: 'Local shield boost amount',
|
||||
value: '-43%'
|
||||
},{
|
||||
effect: 'Shield transfer amount',
|
||||
value: '+86%'
|
||||
},{
|
||||
effect: 'Remote repair amount',
|
||||
value: '+86%'
|
||||
},{
|
||||
effect: 'Capacitor capacity',
|
||||
value: '+86%'
|
||||
},{
|
||||
effect: 'Capacitor recharge time',
|
||||
value: '+43%'
|
||||
},{
|
||||
effect: 'Remote Capacitor Transmitter amount',
|
||||
value: '-43%'
|
||||
}
|
||||
],
|
||||
6: [
|
||||
{
|
||||
effect: 'Local armor repair amount',
|
||||
value: '-50%'
|
||||
},{
|
||||
effect: 'Local shield boost amount',
|
||||
value: '-50%'
|
||||
},{
|
||||
effect: 'Shield transfer amount',
|
||||
value: '+100%'
|
||||
},{
|
||||
effect: 'Remote repair amount',
|
||||
value: '+100%'
|
||||
},{
|
||||
effect: 'Capacitor capacity',
|
||||
value: '+100%'
|
||||
},{
|
||||
effect: 'Capacitor recharge time',
|
||||
value: '+50%'
|
||||
},{
|
||||
effect: 'Remote Capacitor Transmitter amount',
|
||||
value: '-50%'
|
||||
}
|
||||
]
|
||||
},
|
||||
blackHole: {
|
||||
1: [
|
||||
{
|
||||
effect: 'Missile velocity',
|
||||
value: '+15%'
|
||||
},{
|
||||
effect: 'Missile Explosion Velocity',
|
||||
value: '+30%'
|
||||
},{
|
||||
effect: 'Ship velocity',
|
||||
value: '+30%'
|
||||
},{
|
||||
effect: 'Stasis Webifier Strength',
|
||||
value: '-15%'
|
||||
},{
|
||||
effect: 'Inertia',
|
||||
value: '+15%'
|
||||
},{
|
||||
effect: 'Targeting range',
|
||||
value: '+30%'
|
||||
}
|
||||
],
|
||||
2: [
|
||||
{
|
||||
effect: 'Missile velocity',
|
||||
value: '+22%'
|
||||
},{
|
||||
effect: 'Missile Explosion Velocity',
|
||||
value: '+44%'
|
||||
},{
|
||||
effect: 'Ship velocity',
|
||||
value: '+44%'
|
||||
},{
|
||||
effect: 'Stasis Webifier Strength',
|
||||
value: '-22%'
|
||||
},{
|
||||
effect: 'Inertia',
|
||||
value: '+22%'
|
||||
},{
|
||||
effect: 'Targeting range',
|
||||
value: '+44%'
|
||||
}
|
||||
],
|
||||
3: [
|
||||
{
|
||||
effect: 'Missile velocity',
|
||||
value: '+29%'
|
||||
},{
|
||||
effect: 'Missile Explosion Velocity',
|
||||
value: '+58%'
|
||||
},{
|
||||
effect: 'Ship velocity',
|
||||
value: '+58%'
|
||||
},{
|
||||
effect: 'Stasis Webifier Strength',
|
||||
value: '-29%'
|
||||
},{
|
||||
effect: 'Inertia',
|
||||
value: '+29%'
|
||||
},{
|
||||
effect: 'Targeting range',
|
||||
value: '+58%'
|
||||
}
|
||||
],
|
||||
4: [
|
||||
{
|
||||
effect: 'Missile velocity',
|
||||
value: '+36%'
|
||||
},{
|
||||
effect: 'Missile Explosion Velocity',
|
||||
value: '+72%'
|
||||
},{
|
||||
effect: 'Ship velocity',
|
||||
value: '+72%'
|
||||
},{
|
||||
effect: 'Stasis Webifier Strength',
|
||||
value: '-36%'
|
||||
},{
|
||||
effect: 'Inertia',
|
||||
value: '+36%'
|
||||
},{
|
||||
effect: 'Targeting range',
|
||||
value: '+72%'
|
||||
}
|
||||
],
|
||||
5: [
|
||||
{
|
||||
effect: 'Missile velocity',
|
||||
value: '+43%'
|
||||
},{
|
||||
effect: 'Missile Explosion Velocity',
|
||||
value: '+86%'
|
||||
},{
|
||||
effect: 'Ship velocity',
|
||||
value: '+86%'
|
||||
},{
|
||||
effect: 'Stasis Webifier Strength',
|
||||
value: '-43%'
|
||||
},{
|
||||
effect: 'Inertia',
|
||||
value: '+43%'
|
||||
},{
|
||||
effect: 'Targeting range',
|
||||
value: '+86%'
|
||||
}
|
||||
],
|
||||
6: [
|
||||
{
|
||||
effect: 'Missile velocity',
|
||||
value: '+50%'
|
||||
},{
|
||||
effect: 'Missile Explosion Velocity',
|
||||
value: '+100%'
|
||||
},{
|
||||
effect: 'Ship velocity',
|
||||
value: '+100%'
|
||||
},{
|
||||
effect: 'Stasis Webifier Strength',
|
||||
value: '-50%'
|
||||
},{
|
||||
effect: 'Inertia',
|
||||
value: '+50%'
|
||||
},{
|
||||
effect: 'Targeting range',
|
||||
value: '+100%'
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return systemEffects;
|
||||
});
|
||||
101
public/js/v1.0.0RC3/app/counter.js
Normal file
101
public/js/v1.0.0RC3/app/counter.js
Normal file
@@ -0,0 +1,101 @@
|
||||
define(["jquery"], function($) {
|
||||
|
||||
"use strict";
|
||||
|
||||
var config = {
|
||||
counterDigitSmallClass: 'pf-digit-counter-small',
|
||||
counterDigitLargeClass: 'pf-digit-counter-large'
|
||||
};
|
||||
|
||||
var updateDateDiff = function(element, tempDate){
|
||||
|
||||
var date1 = new Date();
|
||||
var date2 = tempDate;
|
||||
//Customise date2 for your required future time
|
||||
|
||||
var diff = (date1 - date2)/1000;
|
||||
diff = Math.abs(Math.floor(diff));
|
||||
|
||||
var days = Math.floor(diff/(24*60*60));
|
||||
var leftSec = diff - days * 24*60*60;
|
||||
|
||||
var hrs = Math.floor(leftSec/(60*60));
|
||||
leftSec = leftSec - hrs * 60*60;
|
||||
|
||||
var min = Math.floor(leftSec/(60));
|
||||
leftSec = leftSec - min * 60;
|
||||
|
||||
|
||||
var value = [];
|
||||
|
||||
if(
|
||||
days > 0 ||
|
||||
value.length > 0
|
||||
){
|
||||
value.push('<span class="' + config.counterDigitLargeClass + '">' + days + 'd' + '</span>');
|
||||
}
|
||||
if(
|
||||
hrs > 0 ||
|
||||
value.length > 0
|
||||
){
|
||||
value.push('<span class="' + config.counterDigitSmallClass + '">' + hrs + 'h' + '</span>');
|
||||
}
|
||||
if(
|
||||
min > 0 ||
|
||||
value.length > 0
|
||||
){
|
||||
value.push('<span class="' + config.counterDigitSmallClass + '">' + min + 'm' + '</span>');
|
||||
}
|
||||
|
||||
if(
|
||||
leftSec >= 0 ||
|
||||
value.length > 0
|
||||
){
|
||||
value.push('<span class="' + config.counterDigitSmallClass + '">' + leftSec + 's' + '</span>');
|
||||
}
|
||||
|
||||
|
||||
element.html(value.join(' '));
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* init a live counter based on a unix timestamp
|
||||
* @returns {*}
|
||||
*/
|
||||
$.fn.initTimestampCounter = function(){
|
||||
return this.each(function(){
|
||||
|
||||
var element = $(this);
|
||||
|
||||
var timestamp = parseInt( element.text() );
|
||||
|
||||
// do not init twice
|
||||
if(timestamp > 0){
|
||||
// mark as init
|
||||
element.attr('data-counter', 'init');
|
||||
|
||||
var date = new Date( timestamp * 1000);
|
||||
|
||||
updateDateDiff(element, date);
|
||||
|
||||
var refreshIntervalId = window.setInterval(function(){
|
||||
|
||||
// update element with current time
|
||||
if( !element.hasClass('stopCounter')){
|
||||
updateDateDiff(element, date);
|
||||
}else{
|
||||
clearInterval( element.data('interval') );
|
||||
}
|
||||
}, 100);
|
||||
|
||||
element.data('interval', refreshIntervalId);
|
||||
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
|
||||
|
||||
};
|
||||
});
|
||||
386
public/js/v1.0.0RC3/app/init.js
Normal file
386
public/js/v1.0.0RC3/app/init.js
Normal file
@@ -0,0 +1,386 @@
|
||||
/**
|
||||
* Init
|
||||
*/
|
||||
|
||||
define(['jquery'], function($) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var Config = {
|
||||
path: {
|
||||
img: 'public/img/', // path for images
|
||||
// user API
|
||||
getCaptcha: 'api/user/getCaptcha', // ajax URL - get captcha image
|
||||
sendInviteKey: 'api/user/sendInvite', // ajax URL - send registration key
|
||||
logIn: 'api/user/logIn', // ajax URL - login
|
||||
logOut: 'api/user/logOut', // ajax URL - logout
|
||||
deleteLog: 'api/user/deleteLog', // ajax URL - delete character log
|
||||
saveUserConfig: 'api/user/saveAccount', // ajax URL - saves/update user account
|
||||
getUserData: 'api/user/getData', // ajax URL - get user data
|
||||
saveSharingConfig: 'api/user/saveSharingConfig', // ajax URL - save "sharing settings" dialog
|
||||
deleteAccount: 'api/user/deleteAccount', // ajax URL - delete Account data
|
||||
// access API
|
||||
searchAccess: 'api/access/search', // ajax URL - search user/corporation/ally by name
|
||||
// main config/map ping API
|
||||
initMap: 'api/map/init', // ajax URL - get static data
|
||||
updateMapData: 'api/map/updateData', // ajax URL - main map update trigger
|
||||
updateUserData: 'api/map/updateUserData', // ajax URL - main map user data trigger
|
||||
// map API
|
||||
saveMap: 'api/map/save', // ajax URL - save/update map
|
||||
deleteMap: 'api/map/delete', // ajax URL - delete map
|
||||
importMap: 'api/map/import', // ajax URL - import map
|
||||
// system API
|
||||
searchSystem: 'api/system/search', // ajax URL - search system by name
|
||||
saveSystem: 'api/system/save', // ajax URL - saves system to map
|
||||
deleteSystem: 'api/system/delete', // ajax URL - delete system from map
|
||||
getSystemGraphData: 'api/system/graphData', // ajax URL - get all system graph data
|
||||
getConstellationData: 'api/system/constellationData', // ajax URL - get system constellation data
|
||||
|
||||
// connection API
|
||||
saveConnection: 'api/connection/save', // ajax URL - save new connection to map
|
||||
deleteConnection: 'api/connection/delete', // ajax URL - delete connection from map
|
||||
// signature API
|
||||
getSignatures: 'api/signature/getAll', // ajax URL - get all signature data for system
|
||||
saveSignatureData: 'api/signature/save', // ajax URL - save signature data for system
|
||||
deleteSignatureData: 'api/signature/delete', // ajax URL - delete signature data for system
|
||||
// route API
|
||||
searchRoute: 'api/route/search', // ajax URL - search system routes
|
||||
// GitHub API
|
||||
gitHubReleases: 'api/github/releases' // ajax URL - get release info from GitHub
|
||||
},
|
||||
url: {
|
||||
ccpImageServer: 'https://image.eveonline.com/', // CCP image Server
|
||||
zKillboard: 'https://zkillboard.com/api/' // killboard api
|
||||
},
|
||||
animationSpeed: {
|
||||
splashOverlay: 300, // "splash" loading overlay
|
||||
headerLink: 100, // links in head bar
|
||||
mapOverlay: 200, // show/hide duration for map overlays
|
||||
mapMoveSystem: 300, // system position has changed animation
|
||||
mapDeleteSystem: 200, // remove system from map
|
||||
mapModule: 200, // show/hide of an map module
|
||||
dialogEvents: 180 // dialog events /slide/show/...
|
||||
},
|
||||
mapIcons: [ // map tab-icons
|
||||
{
|
||||
class: 'fa-desktop',
|
||||
label: 'desktop',
|
||||
unicode: ''
|
||||
},{
|
||||
class: 'fa-bookmark',
|
||||
label: 'bookmark',
|
||||
unicode: ''
|
||||
},{
|
||||
class: 'fa-cube',
|
||||
label: 'cube',
|
||||
unicode: ''
|
||||
},{
|
||||
class: 'fa-plane',
|
||||
label: 'plane',
|
||||
unicode: ''
|
||||
},{
|
||||
class: 'fa-globe',
|
||||
label: 'globe',
|
||||
unicode: ''
|
||||
},{
|
||||
class: 'fa-rocket',
|
||||
label: 'rocket',
|
||||
unicode: ''
|
||||
},{
|
||||
class: 'fa-life-ring',
|
||||
label: 'life ring',
|
||||
unicode: ''
|
||||
},{
|
||||
class: 'fa-heart',
|
||||
label: 'heart',
|
||||
unicode: ''
|
||||
}
|
||||
],
|
||||
|
||||
classes: {
|
||||
// log types
|
||||
logTypes: {
|
||||
info: {
|
||||
class: 'pf-log-info',
|
||||
label: 'info'
|
||||
},
|
||||
warning: {
|
||||
class: 'pf-log-warning',
|
||||
label: 'warning'
|
||||
},
|
||||
error: {
|
||||
class: 'pf-log-error',
|
||||
label: 'error'
|
||||
}
|
||||
},
|
||||
// system effects
|
||||
systemEffects: {
|
||||
|
||||
effect: {
|
||||
class: 'pf-system-effect',
|
||||
name: 'no effect'
|
||||
},
|
||||
magnetar: {
|
||||
class: 'pf-system-effect-magnetar',
|
||||
name: 'magnetar'
|
||||
},
|
||||
redGiant: {
|
||||
class: 'pf-system-effect-redgiant',
|
||||
name: 'red gaint'
|
||||
},
|
||||
pulsar: {
|
||||
class: 'pf-system-effect-pulsar',
|
||||
name: 'pulsar'
|
||||
},
|
||||
wolfRayet: {
|
||||
class: 'pf-system-effect-wolfrayet',
|
||||
name: 'wolf rayet'
|
||||
},
|
||||
cataclysmic: {
|
||||
class: 'pf-system-effect-cataclysmic',
|
||||
name: 'cytaclysmic'
|
||||
},
|
||||
blackHole: {
|
||||
class: 'pf-system-effect-blackhole',
|
||||
name: 'black hole'
|
||||
}
|
||||
},
|
||||
// system security
|
||||
systemSecurity: {
|
||||
security: {
|
||||
class: 'pf-system-sec'
|
||||
},
|
||||
'SH': {
|
||||
class: 'pf-system-sec-unknown'
|
||||
},
|
||||
'H': {
|
||||
class: 'pf-system-sec-highSec'
|
||||
},
|
||||
'L': {
|
||||
class: 'pf-system-sec-lowSec'
|
||||
},
|
||||
'0.0': {
|
||||
class: 'pf-system-sec-nullSec'
|
||||
},
|
||||
'C6': {
|
||||
class: 'pf-system-sec-high'
|
||||
},
|
||||
'C5': {
|
||||
class: 'pf-system-sec-high'
|
||||
},
|
||||
'C4': {
|
||||
class: 'pf-system-sec-mid'
|
||||
},
|
||||
'C3': {
|
||||
class: 'pf-system-sec-mid'
|
||||
},
|
||||
'C2': {
|
||||
class: 'pf-system-sec-low'
|
||||
},
|
||||
'C1': {
|
||||
class: 'pf-system-sec-low'
|
||||
}
|
||||
},
|
||||
// true sec
|
||||
trueSec: {
|
||||
'0.0': {
|
||||
class: 'pf-system-security-0-0'
|
||||
},
|
||||
'0.1': {
|
||||
class: 'pf-system-security-0-1'
|
||||
},
|
||||
'0.2': {
|
||||
class: 'pf-system-security-0-2'
|
||||
},
|
||||
'0.3': {
|
||||
class: 'pf-system-security-0-3'
|
||||
},
|
||||
'0.4': {
|
||||
class: 'pf-system-security-0-4'
|
||||
},
|
||||
'0.5': {
|
||||
class: 'pf-system-security-0-5'
|
||||
},
|
||||
'0.6': {
|
||||
class: 'pf-system-security-0-6'
|
||||
},
|
||||
'0.7': {
|
||||
class: 'pf-system-security-0-7'
|
||||
},
|
||||
'0.8': {
|
||||
class: 'pf-system-security-0-8'
|
||||
},
|
||||
'0.9': {
|
||||
class: 'pf-system-security-0-9'
|
||||
},
|
||||
'1.0': {
|
||||
class: 'pf-system-security-1-0'
|
||||
}
|
||||
},
|
||||
// system info
|
||||
systemInfo: {
|
||||
rally: {
|
||||
class: 'pf-system-info-rally',
|
||||
label: 'rally point'
|
||||
}
|
||||
},
|
||||
// easy-pie-charts
|
||||
pieChart: {
|
||||
class: 'pf-pie-chart', // class for all pie charts
|
||||
pieChartMapCounterClass: 'pf-pie-chart-map-timer' // class for timer chart
|
||||
}
|
||||
},
|
||||
// map scopes
|
||||
defaultMapScope: 'wh', // default scope for connection
|
||||
// map connection types
|
||||
connectionTypes: {
|
||||
jumpbridge: {
|
||||
cssClass: 'pf-map-connection-jumpbridge',
|
||||
paintStyle: {
|
||||
dashstyle: '4 2 1 2'
|
||||
}
|
||||
},
|
||||
stargate: {
|
||||
cssClass: 'pf-map-connection-stargate',
|
||||
paintStyle: {
|
||||
dashstyle: '0' // solid line
|
||||
}
|
||||
},
|
||||
wh_eol: {
|
||||
cssClass: 'pf-map-connection-wh-eol',
|
||||
paintStyle: {
|
||||
dashstyle: '0' // solid line
|
||||
}
|
||||
},
|
||||
wh_fresh: {
|
||||
cssClass: 'pf-map-connection-wh-fresh',
|
||||
paintStyle: {
|
||||
dashstyle: '0' // solid line
|
||||
}
|
||||
},
|
||||
wh_reduced: {
|
||||
cssClass: 'pf-map-connection-wh-reduced',
|
||||
paintStyle: {
|
||||
dashstyle: '0' // solid line
|
||||
}
|
||||
},
|
||||
wh_critical: {
|
||||
cssClass: 'pf-map-connection-wh-critical',
|
||||
paintStyle: {
|
||||
dashstyle: '0' // solid line
|
||||
}
|
||||
},
|
||||
frigate: {
|
||||
cssClass: 'pf-map-connection-frig',
|
||||
paintStyle: {
|
||||
dashstyle: '0.99'
|
||||
},
|
||||
overlays:[
|
||||
[ 'Label',
|
||||
{
|
||||
label: 'frig',
|
||||
cssClass: ['pf-map-connection-overlay', 'frig'].join(' ')
|
||||
} ]
|
||||
]
|
||||
},
|
||||
preserve_mass: {
|
||||
cssClass: 'pf-map-connection-preserve-mass',
|
||||
overlays:[
|
||||
[ 'Label',
|
||||
{
|
||||
label: '<i class="fa fa-warning"></i> save mass',
|
||||
cssClass: ['pf-map-connection-overlay', 'mass'].join(' '),
|
||||
width:50, length:30,
|
||||
location: 0.5
|
||||
} ]
|
||||
]
|
||||
}
|
||||
},
|
||||
// signature groups
|
||||
signatureGroups: {
|
||||
1: {
|
||||
name: 'combat site', //*
|
||||
label: 'Combat'
|
||||
},
|
||||
2: {
|
||||
name: 'relic site', //*
|
||||
label: 'Relic'
|
||||
},
|
||||
3: {
|
||||
name: 'data site',
|
||||
label: 'Data'
|
||||
},
|
||||
4: {
|
||||
name: 'gas site',
|
||||
label: 'Gas'
|
||||
},
|
||||
5: {
|
||||
name: 'wormhole',
|
||||
label: 'Wormhole'
|
||||
},
|
||||
6: {
|
||||
name: 'ore site',
|
||||
label: 'Ore'
|
||||
},
|
||||
7: {
|
||||
name: 'ghost',
|
||||
label: 'Ghost'
|
||||
}
|
||||
},
|
||||
// frigate wormholes
|
||||
frigateWormholes: {
|
||||
1: { // C1
|
||||
|
||||
},
|
||||
2: { // C2
|
||||
1: 'L005 - C2',
|
||||
2: 'C008 - C5',
|
||||
3: 'Q003 - 0.0'
|
||||
},
|
||||
3: { // C3
|
||||
1: 'E004 - C1',
|
||||
2: 'L005 - C2',
|
||||
3: 'M001 - C4'
|
||||
},
|
||||
4: { // C4
|
||||
1: 'L005 - C2',
|
||||
2: 'G008 - C6',
|
||||
3: 'Q003 - 0.0'
|
||||
},
|
||||
5: { // C5
|
||||
1: 'E004 - C1',
|
||||
2: 'L005 - C2',
|
||||
3: 'Z006 - C3',
|
||||
4: 'C008 - C5',
|
||||
5: 'Q003 - 0.0'
|
||||
},
|
||||
6: { // C6
|
||||
1: 'E004 - C1',
|
||||
2: 'Z006 - C3',
|
||||
5: 'Q003 - 0.0'
|
||||
},
|
||||
13: { // Shattered Wormholes (some of them are static)
|
||||
1: 'E004 - C1',
|
||||
2: 'L005 - C2',
|
||||
3: 'Z006 - C3',
|
||||
4: 'M001 - C4',
|
||||
5: 'C008 - C5',
|
||||
6: 'G008 - C6',
|
||||
7: 'Q003 - C7'
|
||||
|
||||
}
|
||||
},
|
||||
// incoming wormholes
|
||||
incomingWormholes: {
|
||||
1: 'K162 - C1/2/3 (unknown)',
|
||||
2: 'K162 - C4/5 (dangerous)',
|
||||
3: 'K162 - C6 (deadly)',
|
||||
4: 'K162 - HS',
|
||||
5: 'K162 - LS',
|
||||
6: 'K162 - 0.0'
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
return Config;
|
||||
});
|
||||
499
public/js/v1.0.0RC3/app/logging.js
Normal file
499
public/js/v1.0.0RC3/app/logging.js
Normal file
@@ -0,0 +1,499 @@
|
||||
/**
|
||||
* logging
|
||||
*/
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util',
|
||||
'bootbox'
|
||||
], function($, Init, Util, bootbox) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var logData = []; // cache object for all log entries
|
||||
var logDataTable = null; // "Datatables" Object
|
||||
|
||||
// Morris charts data
|
||||
var maxGraphDataCount = 30; // max date entries for a graph
|
||||
var chartData = {}; // chart Data object for all Morris Log graphs
|
||||
|
||||
var config = {
|
||||
dialogDynamicAreaClass: 'pf-dynamic-area', // class for dynamic areas
|
||||
logGraphClass: 'pf-log-graph' // class for all log Morris graphs
|
||||
};
|
||||
|
||||
/**
|
||||
* get log time string
|
||||
* @returns {string}
|
||||
*/
|
||||
var getLogTime = function(){
|
||||
|
||||
var serverTime = Util.getServerTime();
|
||||
|
||||
var logTime = serverTime.toLocaleTimeString('en-US', { hour12: false });
|
||||
|
||||
return logTime;
|
||||
};
|
||||
|
||||
/**
|
||||
* shows the logging dialog
|
||||
*/
|
||||
var showDialog = function(){
|
||||
|
||||
// dialog content
|
||||
|
||||
var content = $('<div>');
|
||||
|
||||
// content row for log graphs
|
||||
var rowElementGraphs = $('<div>', {
|
||||
class: 'row'
|
||||
});
|
||||
|
||||
content.append(rowElementGraphs);
|
||||
|
||||
|
||||
|
||||
var tableHeadline = $('<h4>', {
|
||||
text: ' Processes'
|
||||
}).prepend( $('<i>', {
|
||||
class: ['fa', 'fa-fw', 'fa-lg', 'fa-list-alt'].join(' ')
|
||||
}));
|
||||
|
||||
// add content Structure to dome before table initialization
|
||||
content.append(tableHeadline);
|
||||
|
||||
// log table area --------------------------------------------------
|
||||
var logTableArea = $('<div>', {
|
||||
class: config.dialogDynamicAreaClass
|
||||
});
|
||||
|
||||
var logTable = $('<table>', {
|
||||
class: ['compact', 'stripe', 'order-column', 'row-border'].join(' ')
|
||||
});
|
||||
|
||||
logTableArea.append(logTable);
|
||||
content.append(logTableArea);
|
||||
|
||||
// init log table
|
||||
logDataTable = logTable.DataTable( {
|
||||
paging: true,
|
||||
ordering: true,
|
||||
order: [ 1, 'desc' ],
|
||||
autoWidth: false,
|
||||
hover: false,
|
||||
pageLength: 15,
|
||||
lengthMenu: [[10, 15, 25, 50, 50], [10, 15, 25, 50, 50]],
|
||||
data: logData, // load cached logs (if available)
|
||||
language: {
|
||||
emptyTable: 'No entries',
|
||||
zeroRecords: 'No entries found',
|
||||
lengthMenu: 'Show _MENU_ entries',
|
||||
info: 'Showing _START_ to _END_ of _TOTAL_ entries'
|
||||
},
|
||||
columnDefs: [
|
||||
{
|
||||
targets: 0,
|
||||
title: '<i class="fa fa-lg fa-tag"></i>',
|
||||
width: '18px',
|
||||
searchable: false,
|
||||
class: ['text-center'].join(' '),
|
||||
data: 'status'
|
||||
},{
|
||||
targets: 1,
|
||||
title: '<i class="fa fa-lg fa-fw fa-clock-o"></i> ',
|
||||
width: '50px',
|
||||
searchable: true,
|
||||
class: 'text-right',
|
||||
data: 'time'
|
||||
},{
|
||||
targets: 2,
|
||||
title: '<i class="fa fa-lg fa-fw fa-history"></i> ',
|
||||
width: '35px',
|
||||
searchable: false,
|
||||
class: 'text-right',
|
||||
sType: 'html',
|
||||
data: 'duration'
|
||||
},{
|
||||
targets: 3,
|
||||
title: 'description',
|
||||
searchable: true,
|
||||
data: 'description'
|
||||
},{
|
||||
targets: 4,
|
||||
title: 'type',
|
||||
width: '40px',
|
||||
searchable: true,
|
||||
class: ['text-center'].join(' '),
|
||||
data: 'type'
|
||||
},{
|
||||
targets: 5,
|
||||
title: 'Prozess-ID ',
|
||||
width: '80px',
|
||||
searchable: false,
|
||||
class: 'text-right',
|
||||
data: 'key'
|
||||
}
|
||||
]
|
||||
|
||||
});
|
||||
|
||||
// open dialog
|
||||
var logDialog = bootbox.dialog({
|
||||
title: 'Task-Manager',
|
||||
message: content,
|
||||
size: 'large',
|
||||
buttons: {
|
||||
close: {
|
||||
label: 'close',
|
||||
className: 'btn-default'
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// modal dialog is shown
|
||||
logDialog.on('shown.bs.modal', function(e) {
|
||||
|
||||
// show Morris graphs ----------------------------------------------------------
|
||||
|
||||
// function for chart label formation
|
||||
var labelYFormat = function(y){
|
||||
return Math.round(y) + 'ms';
|
||||
};
|
||||
|
||||
for(var key in chartData) {
|
||||
if(chartData.hasOwnProperty(key)) {
|
||||
// create a chart for each key
|
||||
|
||||
var colElementGraph = $('<div>', {
|
||||
class: ['col-md-6'].join(' ')
|
||||
});
|
||||
|
||||
|
||||
// graph element
|
||||
var graphElement = $('<div>', {
|
||||
class: config.logGraphClass
|
||||
});
|
||||
|
||||
var graphArea = $('<div>', {
|
||||
class: config.dialogDynamicAreaClass
|
||||
}).append( graphElement );
|
||||
|
||||
// headline
|
||||
var headline = $('<h4>', {
|
||||
text: key
|
||||
}).prepend(
|
||||
$('<span>', {
|
||||
class: ['txt-color', 'txt-color-grayLight'].join(' '),
|
||||
text: 'Prozess-ID: '
|
||||
})
|
||||
);
|
||||
|
||||
// show update ping between function calls
|
||||
var updateElement = $('<small>', {
|
||||
class: ['txt-color', 'txt-color-blue', 'pull-right'].join(' ')
|
||||
});
|
||||
headline.append(updateElement).append('<br>');
|
||||
|
||||
// show average execution time
|
||||
var averageElement = $('<small>', {
|
||||
class: 'pull-right'
|
||||
});
|
||||
headline.append(averageElement);
|
||||
|
||||
colElementGraph.append( headline );
|
||||
colElementGraph.append( graphArea );
|
||||
|
||||
graphArea.showLoadingAnimation();
|
||||
|
||||
rowElementGraphs.append( colElementGraph );
|
||||
|
||||
// cache DOM Elements that will be updated frequently
|
||||
chartData[key].averageElement = averageElement;
|
||||
chartData[key].updateElement = updateElement;
|
||||
|
||||
chartData[key].graph = Morris.Area({
|
||||
element: graphElement,
|
||||
data: [],
|
||||
xkey: 'x',
|
||||
ykeys: ['y'],
|
||||
labels: [key],
|
||||
units: 'ms',
|
||||
parseTime: false,
|
||||
ymin: 0,
|
||||
yLabelFormat: labelYFormat,
|
||||
padding: 10,
|
||||
hideHover: true,
|
||||
pointSize: 3,
|
||||
lineColors: ['#375959'],
|
||||
pointFillColors: ['#477372'],
|
||||
pointStrokeColors: ['#313335'],
|
||||
lineWidth: 2,
|
||||
grid: false,
|
||||
gridStrokeWidth: 0.3,
|
||||
gridTextSize: 9,
|
||||
gridTextFamily: 'Oxygen Bold',
|
||||
gridTextColor: '#63676a',
|
||||
behaveLikeLine: true,
|
||||
goals: [],
|
||||
goalLineColors: ['#66c84f'],
|
||||
smooth: false,
|
||||
fillOpacity: 0.3,
|
||||
resize: true
|
||||
});
|
||||
|
||||
graphArea.hideLoadingAnimation();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// add TableTool Buttons
|
||||
var tt = new $.fn.DataTable.TableTools( logDataTable, {
|
||||
sSwfPath: require.toUrl('') + 'lib/datatables/extensions/tabletools/swf/copy_csv_xls.swf',
|
||||
aButtons: [ 'copy', 'csv', 'print' ]
|
||||
});
|
||||
|
||||
$(tt.fnContainer()).insertBefore('.bootbox-body div.dataTables_wrapper');
|
||||
|
||||
// add button icons
|
||||
$('.DTTT_button_csv').prepend( $('<i>', {
|
||||
class: ['fa', 'fa-fw', 'fa-download'].join(' ')
|
||||
}));
|
||||
$('.DTTT_button_copy').prepend( $('<i>', {
|
||||
class: ['fa', 'fa-fw', 'fa-clipboard'].join(' ')
|
||||
}));
|
||||
$('.DTTT_button_print').prepend( $('<i>', {
|
||||
class: ['fa', 'fa-fw', 'fa-print'].join(' ')
|
||||
}));
|
||||
});
|
||||
|
||||
|
||||
// modal dialog is closed
|
||||
logDialog.on('hidden.bs.modal', function(e) {
|
||||
// clear memory -> destroy all charts
|
||||
for (var key in chartData) {
|
||||
if (chartData.hasOwnProperty(key)) {
|
||||
chartData[key].graph = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// modal dialog before hide
|
||||
logDialog.on('hide.bs.modal', function(e) {
|
||||
|
||||
// destroy logTable
|
||||
logDataTable.destroy(true);
|
||||
logDataTable= null;
|
||||
|
||||
// remove event -> prevent calling this multiple times
|
||||
$(this).off('hide.bs.modal');
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* updates the log graph for a log key
|
||||
* @param key
|
||||
* @param duration
|
||||
*/
|
||||
var updateLogGraph = function(key, duration){
|
||||
|
||||
// check if graph data already exist
|
||||
if( !(chartData.hasOwnProperty(key))){
|
||||
chartData[key] = {};
|
||||
chartData[key].data = [];
|
||||
chartData[key].graph = null;
|
||||
chartData[key].averageElement = null;
|
||||
chartData[key].updateElement = null;
|
||||
}
|
||||
|
||||
// add new value
|
||||
chartData[key].data.unshift(duration);
|
||||
|
||||
if(chartData[key].data.length > maxGraphDataCount){
|
||||
chartData[key].data = chartData[key].data.slice(0, maxGraphDataCount);
|
||||
}
|
||||
|
||||
function getGraphData(data) {
|
||||
var tempChartData = {
|
||||
data: [],
|
||||
dataSum: 0,
|
||||
average: 0
|
||||
};
|
||||
|
||||
for(var x = 0; x < maxGraphDataCount; x++){
|
||||
var value = 0;
|
||||
if(data[x]){
|
||||
value = data[x];
|
||||
tempChartData.dataSum = Number( (tempChartData.dataSum + value).toFixed(2) );
|
||||
}
|
||||
|
||||
tempChartData.data.push({
|
||||
x: x,
|
||||
y: value
|
||||
});
|
||||
}
|
||||
|
||||
// calculate average
|
||||
tempChartData.average = Number( ( tempChartData.dataSum / data.length ).toFixed(2) );
|
||||
|
||||
return tempChartData;
|
||||
}
|
||||
|
||||
var tempChartData = getGraphData(chartData[key].data);
|
||||
|
||||
// add new data to graph (Morris chart) - if is already initialized
|
||||
if(chartData[key].graph !== null){
|
||||
var avgElement = chartData[key].averageElement;
|
||||
var updateElement = chartData[key].updateElement;
|
||||
|
||||
var delay = Util.getCurrentTriggerDelay( key, 0 );
|
||||
|
||||
if(delay){
|
||||
updateElement[0].textContent = ' delay: ' + delay + 'ms ';
|
||||
}
|
||||
|
||||
// set/change average line
|
||||
chartData[key].graph.options.goals = [tempChartData.average];
|
||||
|
||||
// change avg. display
|
||||
avgElement[0].textContent = 'Avg. ' + tempChartData.average + 'ms';
|
||||
|
||||
var avgStatus = getLogStatusByDuration(key, tempChartData.average);
|
||||
var avgStatusClass = Util.getLogInfo( avgStatus, 'class' );
|
||||
|
||||
//change avg. display class
|
||||
if( !avgElement.hasClass(avgStatusClass) ){
|
||||
// avg status changed!
|
||||
avgElement.removeClass().addClass('pull-right txt-color ' + avgStatusClass);
|
||||
|
||||
// change goals line color
|
||||
if(avgStatus === 'warning'){
|
||||
chartData[key].graph.options.goalLineColors = ['#e28a0d'];
|
||||
$(document).setProgramStatus('problem');
|
||||
}else{
|
||||
chartData[key].graph.options.goalLineColors = ['#5cb85c'];
|
||||
}
|
||||
}
|
||||
|
||||
// set new data and redraw
|
||||
chartData[key].graph.setData( tempChartData.data );
|
||||
}
|
||||
|
||||
return tempChartData.data;
|
||||
};
|
||||
|
||||
/**
|
||||
* get the log "status" by log duration (ms).
|
||||
* If duration > warning limit -> show as warning
|
||||
* @param logKey
|
||||
* @param logDuration
|
||||
* @returns {string}
|
||||
*/
|
||||
var getLogStatusByDuration = function(logKey, logDuration){
|
||||
|
||||
var logStatus = 'info';
|
||||
if( logDuration > Init.timer[logKey].EXECUTION_LIMIT ){
|
||||
logStatus = 'warning';
|
||||
}
|
||||
return logStatus;
|
||||
};
|
||||
|
||||
/**
|
||||
* get the css class for a specific log type
|
||||
* @param logType
|
||||
* @returns {string}
|
||||
*/
|
||||
var getLogTypeIconClass = function(logType){
|
||||
|
||||
var logIconClass = '';
|
||||
|
||||
switch(logType){
|
||||
case 'client':
|
||||
logIconClass = 'fa-user';
|
||||
break;
|
||||
case 'server':
|
||||
logIconClass = 'fa-download';
|
||||
break;
|
||||
}
|
||||
|
||||
return logIconClass;
|
||||
};
|
||||
|
||||
/**
|
||||
* init logging -> set global log event
|
||||
*/
|
||||
var init = function(){
|
||||
|
||||
var maxEntries = 150;
|
||||
|
||||
// set global logging listener
|
||||
$(window).on('pf:log', function(e, logKey, options){
|
||||
|
||||
// check required logging information
|
||||
if(
|
||||
options &&
|
||||
options.duration &&
|
||||
options.description
|
||||
){
|
||||
var logDescription = options.description;
|
||||
var logDuration = options.duration;
|
||||
var logType = options.type;
|
||||
|
||||
// check log status by duration
|
||||
var logStatus = getLogStatusByDuration(logKey, logDuration);
|
||||
|
||||
var statusClass = Util.getLogInfo( logStatus, 'class' );
|
||||
|
||||
var typeIconClass = getLogTypeIconClass(logType);
|
||||
|
||||
// update graph data
|
||||
updateLogGraph(logKey, logDuration);
|
||||
|
||||
var logRowData = {
|
||||
status: '<i class="fa fa-fw fa-circle txt-color ' + statusClass + '"></i>',
|
||||
time: getLogTime(),
|
||||
duration: '<span class="txt-color ' + statusClass + '">' + logDuration + '<small>ms</small></span>',
|
||||
description: logDescription,
|
||||
type: '<i class="fa ' + typeIconClass + '"></i>',
|
||||
key: logKey
|
||||
};
|
||||
|
||||
|
||||
if(logDataTable){
|
||||
// add row if dataTable is initialized before new log
|
||||
logDataTable.row.add( logRowData ).draw(false);
|
||||
}else{
|
||||
// add row data to cache
|
||||
logData.push(logRowData);
|
||||
}
|
||||
}
|
||||
|
||||
// delete old log entries from table ---------------------------------
|
||||
var rowCount = logData.length;
|
||||
|
||||
if( rowCount >= maxEntries ){
|
||||
|
||||
if(logDataTable){
|
||||
logDataTable.rows(0, {order:'index'}).remove().draw(false);
|
||||
}else{
|
||||
logData.shift();
|
||||
}
|
||||
}
|
||||
|
||||
// cache logs in order to keep previous logs in table after reopening the dialog
|
||||
if(logDataTable){
|
||||
logData = logDataTable.rows({order:'index'}).data();
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
return {
|
||||
init: init,
|
||||
getLogTime: getLogTime,
|
||||
showDialog: showDialog
|
||||
};
|
||||
});
|
||||
521
public/js/v1.0.0RC3/app/login.js
Normal file
521
public/js/v1.0.0RC3/app/login.js
Normal file
@@ -0,0 +1,521 @@
|
||||
/**
|
||||
* Main loginPage application
|
||||
*/
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util',
|
||||
'app/render',
|
||||
'app/ccp',
|
||||
'blueImpGallery',
|
||||
'bootbox',
|
||||
'lazyload',
|
||||
'app/ui/header',
|
||||
'app/ui/logo',
|
||||
'app/ui/demo_map',
|
||||
'dialog/account_settings',
|
||||
'dialog/notification',
|
||||
'dialog/manual',
|
||||
'dialog/releases',
|
||||
'dialog/credit'
|
||||
], function($, Init, Util, Render, CCP, Gallery, bootbox) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var config = {
|
||||
splashOverlayClass: 'pf-splash', // class for "splash" overlay
|
||||
|
||||
// header
|
||||
headerContainerId: 'pf-header-container', // id for header container
|
||||
logoContainerId: 'pf-logo-container', // id for main header logo container
|
||||
headHeaderMapId: 'pf-header-map', // id for header image (svg animation)
|
||||
|
||||
// map bg
|
||||
headMapBgId: 'pf-header-map-bg', // id for header background container
|
||||
mapNeocomId: 'pf-map-neocom', // id for map "neocom" image
|
||||
mapBrowserId: 'pf-map-browser', // id for "browser" image
|
||||
mapBgImageId: 'pf-map-bg-image', // id for "background" map image
|
||||
|
||||
// navigation
|
||||
navigationElementId: 'pf-navbar', // id for navbar element
|
||||
navigationLinkManualClass: 'pf-navbar-manual', // class for "manual" trigger link
|
||||
navigationLinkLicenseClass: 'pf-navbar-license', // class for "license" trigger link
|
||||
navigationVersionLinkClass: 'pf-navbar-version-info', // class for "version information"
|
||||
|
||||
// login form
|
||||
loginFormId: 'pf-login-form', // id for login form
|
||||
loginButtonClass: 'pf-login-button', // class for "login" button(s)
|
||||
registerButtonClass: 'pf-register-button', // class for "register" button(s)
|
||||
loginMessageContainerId: 'pf-login-message-container', // id for login form message container
|
||||
|
||||
// gallery
|
||||
galleryId: 'pf-gallery', // id for gallery container
|
||||
galleryThumbImageClass: 'pf-landing-image-preview', // class for gallery thumb images
|
||||
galleryThumbContainerId: 'pf-landing-gallery-thumb-container', // id for gallery thumb images
|
||||
galleryCarouselId: 'pf-landing-gallery-carousel', // id for "carousel" element
|
||||
|
||||
// animation
|
||||
animateElementClass: 'pf-animate-on-visible' // class for elements that will be animated to show
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* set page observer
|
||||
*/
|
||||
var setPageObserver = function(){
|
||||
|
||||
// login form =====================================================================================
|
||||
// register buttons ---------------------------------------------
|
||||
$('.' + config.registerButtonClass).on('click', function(e){
|
||||
e.preventDefault();
|
||||
|
||||
// logout current user (if there e.g. to register a second account)
|
||||
Util.logout({
|
||||
ajaxData: {
|
||||
reroute: 0
|
||||
}
|
||||
});
|
||||
|
||||
// show register/settings dialog
|
||||
$.fn.showSettingsDialog({
|
||||
register: 1,
|
||||
invite : parseInt( $('body').data('invite') )
|
||||
});
|
||||
});
|
||||
|
||||
// releases -----------------------------------------------------
|
||||
$('.' + config.navigationVersionLinkClass).on('click', function(e){
|
||||
$.fn.releasesDialog();
|
||||
});
|
||||
|
||||
// manual -------------------------------------------------------
|
||||
$('.' + config.navigationLinkManualClass).on('click', function(e){
|
||||
e.preventDefault();
|
||||
$.fn.showMapManual();
|
||||
});
|
||||
|
||||
// license ------------------------------------------------------
|
||||
$('.' + config.navigationLinkLicenseClass).on('click', function(e){
|
||||
e.preventDefault();
|
||||
$.fn.showCreditsDialog(false, true);
|
||||
});
|
||||
|
||||
// tooltips -----------------------------------------------------
|
||||
var mapTooltipOptions = {
|
||||
toggle: 'tooltip',
|
||||
container: 'body',
|
||||
delay: 150
|
||||
};
|
||||
|
||||
$('[title]').not('.slide img').tooltip(mapTooltipOptions);
|
||||
};
|
||||
|
||||
/**
|
||||
* show "registration key" dialog (see "Invite" feature)
|
||||
*/
|
||||
var showRequestRegistrationKeyDialog = function(){
|
||||
var data = {
|
||||
id: config.signatureReaderDialogId,
|
||||
formErrorContainerClass: Util.config.formErrorContainerClass,
|
||||
formWarningContainerClass: Util.config.formWarningContainerClass
|
||||
};
|
||||
|
||||
requirejs(['text!templates/dialog/registration.html', 'mustache'], function(template, Mustache) {
|
||||
|
||||
var content = Mustache.render(template, data);
|
||||
|
||||
var registrationKeyDialog = bootbox.dialog({
|
||||
title: 'Registration Key',
|
||||
message: content,
|
||||
buttons: {
|
||||
close: {
|
||||
label: 'cancel',
|
||||
className: 'btn-default'
|
||||
},
|
||||
success: {
|
||||
label: '<i class="fa fa-envelope fa-fw"></i> send',
|
||||
className: 'btn-success',
|
||||
callback: function () {
|
||||
var dialogElement = $(this);
|
||||
var form = dialogElement.find('form');
|
||||
|
||||
// validate form
|
||||
form.validator('validate');
|
||||
var formValid = form.isValidForm();
|
||||
|
||||
if(formValid){
|
||||
var formValues = form.getFormValues();
|
||||
|
||||
if( !$.isEmptyObject(formValues) ){
|
||||
|
||||
// send Tab data and store values
|
||||
var requestData = {
|
||||
settingsData: formValues
|
||||
};
|
||||
|
||||
var modalContent = registrationKeyDialog.find('.modal-content');
|
||||
modalContent.showLoadingAnimation();
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: Init.path.sendInviteKey,
|
||||
data: requestData,
|
||||
dataType: 'json'
|
||||
}).done(function(responseData){
|
||||
|
||||
if(
|
||||
responseData.error &&
|
||||
responseData.error.length > 0
|
||||
){
|
||||
form.showFormMessage(responseData.error);
|
||||
|
||||
|
||||
}else{
|
||||
$('.modal').modal('hide');
|
||||
Util.showNotify({title: 'Registration Key send', text: 'Check your Mails', type: 'success'});
|
||||
}
|
||||
|
||||
modalContent.hideLoadingAnimation();
|
||||
}).fail(function( jqXHR, status, error) {
|
||||
modalContent.hideLoadingAnimation();
|
||||
|
||||
var reason = status + ' ' + error;
|
||||
Util.showNotify({title: jqXHR.status + ': send Registration Key', text: reason, type: 'error'});
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* init image carousel
|
||||
*/
|
||||
var initCarousel = function(){
|
||||
|
||||
// check if carousel exists (e.g. not in IGB browser
|
||||
if($('#' + config.galleryCarouselId).length === 0){
|
||||
return;
|
||||
}
|
||||
|
||||
// extent "blueimp" gallery for a textFactory method to show HTML templates
|
||||
Gallery.prototype.textFactory = function (obj, callback) {
|
||||
var newSlideContent = $('<div>')
|
||||
.addClass('text-content')
|
||||
.attr('title', obj.title);
|
||||
|
||||
var moduleConfig = {
|
||||
name: obj.href, // template name
|
||||
position: newSlideContent,
|
||||
functions: {
|
||||
after: function(){
|
||||
// element inserted -> load complete
|
||||
callback({
|
||||
type: 'complete',
|
||||
target: newSlideContent[0]
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// render HTML file (template)
|
||||
var moduleData = {
|
||||
id: config.headHeaderMapId,
|
||||
bgId: config.headMapBgId,
|
||||
neocomId: config.mapNeocomId,
|
||||
browserId: config.mapBrowserId,
|
||||
mapBgImageId: config.mapBgImageId
|
||||
};
|
||||
|
||||
Render.showModule(moduleConfig, moduleData);
|
||||
|
||||
return newSlideContent[0];
|
||||
};
|
||||
|
||||
// initialize carousel ------------------------------------------
|
||||
var carousel = new Gallery([
|
||||
{
|
||||
title: 'IGB',
|
||||
href: 'ui/map',
|
||||
type: 'text/html'
|
||||
},
|
||||
{
|
||||
href: 'public/img/landing/responsive.jpg',
|
||||
title: 'Responsive layout',
|
||||
type: 'image/jpg',
|
||||
thumbnail: ''
|
||||
},
|
||||
{
|
||||
href: 'public/img/landing/pathfinder_1.jpg',
|
||||
title: 'Map view',
|
||||
type: 'image/jpg',
|
||||
thumbnail: ''
|
||||
},
|
||||
{
|
||||
href: 'public/img/landing/pathfinder_3.jpg',
|
||||
title: 'Map information',
|
||||
type: 'image/jpg',
|
||||
thumbnail: ''
|
||||
},
|
||||
{
|
||||
href: 'public/img/landing/pathfinder_2.jpg',
|
||||
title: 'System information',
|
||||
type: 'image/jpg',
|
||||
thumbnail: ''
|
||||
}
|
||||
], {
|
||||
container: '#' + config.galleryCarouselId,
|
||||
carousel: true,
|
||||
startSlideshow: false,
|
||||
titleProperty: 'title',
|
||||
transitionSpeed: 600,
|
||||
slideshowInterval: 5000,
|
||||
onopened: function () {
|
||||
// Callback function executed when the Gallery has been initialized
|
||||
// and the initialization transition has been completed.
|
||||
// -> show "demo" map
|
||||
|
||||
$('#' + config.headHeaderMapId).drawDemoMap(function(){
|
||||
|
||||
// zoom map SVGs
|
||||
$('#' + config.headHeaderMapId + ' svg').velocity({
|
||||
scaleX: 0.66,
|
||||
scaleY: 0.66
|
||||
}, {
|
||||
duration: 360
|
||||
});
|
||||
|
||||
// position map container
|
||||
$('#' + config.headHeaderMapId).velocity({
|
||||
marginTop: '130px',
|
||||
marginLeft: '-50px'
|
||||
}, {
|
||||
duration: 360,
|
||||
complete: function(){
|
||||
// show browser
|
||||
$('#' + config.mapBrowserId).velocity('transition.slideUpBigIn', {
|
||||
duration: 360,
|
||||
complete: function(){
|
||||
// show neocom
|
||||
$('#' + config.mapNeocomId).velocity('transition.slideLeftIn', {
|
||||
duration: 180
|
||||
});
|
||||
|
||||
// show background
|
||||
$('#' + config.mapBgImageId).velocity('transition.shrinkIn', {
|
||||
duration: 360
|
||||
});
|
||||
|
||||
// when map is shown -> start carousel looping
|
||||
carousel.play();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* init image gallery
|
||||
*/
|
||||
var initGallery = function(){
|
||||
|
||||
requirejs(['blueImpGalleryBootstrap'], function() {
|
||||
// thumb links
|
||||
var thumbLinks = $('a[data-gallery="#pf-gallery"]');
|
||||
|
||||
var borderless = false;
|
||||
|
||||
var galleryElement = $('#' + config.galleryId);
|
||||
galleryElement.data('useBootstrapModal', !borderless);
|
||||
galleryElement.toggleClass('blueimp-gallery-controls', borderless);
|
||||
|
||||
// init gallery on click
|
||||
thumbLinks.on('click', function(e){
|
||||
e.preventDefault();
|
||||
|
||||
e = e || window.event;
|
||||
var target = e.target || e.srcElement;
|
||||
var link = target.src ? target.parentNode : target;
|
||||
|
||||
var options = {
|
||||
index: link,
|
||||
event: e,
|
||||
container: '#' + config.galleryId,
|
||||
titleProperty: 'description'
|
||||
};
|
||||
|
||||
new Gallery(thumbLinks, options);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var initYoutube = function(){
|
||||
|
||||
$(".youtube").each(function() {
|
||||
// Based on the YouTube ID, we can easily find the thumbnail image
|
||||
$(this).css('background-image', 'url(https://i.ytimg.com/vi/' + this.id + '/sddefault.jpg)');
|
||||
|
||||
// Overlay the Play icon to make it look like a video player
|
||||
$(this).append($('<div/>', {'class': 'play'}));
|
||||
|
||||
$(document).delegate('#'+this.id, 'click', function() {
|
||||
// Create an iFrame with autoplay set to true
|
||||
var iframe_url = "https://www.youtube.com/embed/" + this.id + "?autoplay=1&autohide=1";
|
||||
if ($(this).data('params')) iframe_url+='&'+$(this).data('params');
|
||||
|
||||
// The height and width of the iFrame should be the same as parent
|
||||
var iframe = $('<iframe/>', {
|
||||
frameborder: '0',
|
||||
src: iframe_url,
|
||||
width: $(this).width(),
|
||||
height: $(this).height(),
|
||||
class: 'pricing-big'
|
||||
});
|
||||
|
||||
// Replace the YouTube thumbnail with YouTube HTML5 Player
|
||||
$(this).replaceWith(iframe);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* init scrollspy for navigation bar
|
||||
*/
|
||||
var initScrollspy = function(){
|
||||
// init scrollspy
|
||||
|
||||
// show elements that are currently in the viewport
|
||||
var showVisibleElements = function(){
|
||||
// find all elements that should be animated
|
||||
var visibleElements = $('.' + config.animateElementClass).isInViewport();
|
||||
|
||||
$(visibleElements).removeClass( config.animateElementClass );
|
||||
|
||||
$(visibleElements).velocity('transition.flipXIn', {
|
||||
duration: 600,
|
||||
stagger: 60,
|
||||
delay: 500,
|
||||
complete: function(element){
|
||||
$(element).find('.fade').addClass('in');
|
||||
},
|
||||
visibility: 'visible'
|
||||
});
|
||||
};
|
||||
|
||||
$( window ).scroll(function() {
|
||||
// check for new visible elements
|
||||
showVisibleElements();
|
||||
});
|
||||
|
||||
// initial check for visible elements
|
||||
showVisibleElements();
|
||||
|
||||
// event listener for navigation links
|
||||
$('.page-scroll').on('click', function(){
|
||||
// get element to scroll
|
||||
var anchorTag = $(this).attr('data-anchor');
|
||||
|
||||
// scroll to container
|
||||
$(anchorTag).velocity('scroll', {
|
||||
duration: 300,
|
||||
easing: 'swing'
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* main init "landing" page
|
||||
*/
|
||||
$(function(){
|
||||
|
||||
// show app information in browser console
|
||||
Util.showVersionInfo();
|
||||
|
||||
// show log off message
|
||||
var isLogOut = location.search.split('logout')[1];
|
||||
if(isLogOut !== undefined){
|
||||
|
||||
// show logout dialog
|
||||
var options = {
|
||||
buttons: {
|
||||
close: {
|
||||
label: 'close',
|
||||
className: ['btn-default'].join(' ')
|
||||
}
|
||||
},
|
||||
content: {
|
||||
icon: 'fa-sign-out',
|
||||
class: 'txt-color-warning',
|
||||
title: 'Logout',
|
||||
headline: 'Logout',
|
||||
text: [
|
||||
'For security reasons, you were logged out automatically',
|
||||
'Please log in again'
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
$.fn.showNotificationDialog(options);
|
||||
|
||||
// change url (remove logout parameter)
|
||||
if (history.pushState) {
|
||||
history.pushState({}, '', location.protocol + '//' + location.host + location.pathname);
|
||||
}
|
||||
}
|
||||
|
||||
// show get registration key dialog
|
||||
var showRegistrationDialog = location.search.split('register')[1];
|
||||
if(showRegistrationDialog !== undefined){
|
||||
showRequestRegistrationKeyDialog();
|
||||
}
|
||||
|
||||
// init "lazy loading" for images
|
||||
$('.' + config.galleryThumbImageClass).lazyload({
|
||||
threshold : 300
|
||||
});
|
||||
|
||||
// hide splash loading animation
|
||||
$('.' + config.splashOverlayClass).hideSplashOverlay();
|
||||
|
||||
// init carousel
|
||||
initCarousel();
|
||||
|
||||
// init scrollspy
|
||||
initScrollspy();
|
||||
|
||||
// init gallery
|
||||
initGallery();
|
||||
|
||||
// init youtube videos
|
||||
initYoutube();
|
||||
|
||||
// show logo -> hide animation in IGB
|
||||
if( !CCP.isInGameBrowser() ){
|
||||
$('#' + config.logoContainerId).drawLogo(function(){
|
||||
|
||||
// init header animation
|
||||
$('#' + config.headerContainerId).initHeader(function(){
|
||||
|
||||
});
|
||||
}, false);
|
||||
}
|
||||
|
||||
setPageObserver();
|
||||
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
111
public/js/v1.0.0RC3/app/map/contextmenu.js
Normal file
111
public/js/v1.0.0RC3/app/map/contextmenu.js
Normal file
@@ -0,0 +1,111 @@
|
||||
/**
|
||||
* context menu
|
||||
*/
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'app/ccp'
|
||||
], function($, CCP) {
|
||||
|
||||
'use strict';
|
||||
|
||||
$.fn.contextMenu = function (settings) {
|
||||
|
||||
// animation
|
||||
var animationInType = CCP.isInGameBrowser() ? 'fadeIn' : 'transition.flipXIn';
|
||||
var animationInDuration = CCP.isInGameBrowser() ? 0 : 150;
|
||||
var animationOutType = CCP.isInGameBrowser() ? 'fadeOut' : 'transition.flipXOut';
|
||||
var animationOutDuration = CCP.isInGameBrowser() ? 0 : 150;
|
||||
|
||||
return this.each(function () {
|
||||
|
||||
// Open context menu
|
||||
$(this).off('pf:openContextMenu').on('pf:openContextMenu', function (e, originalEvent, component, hiddenOptions, activeOptions) {
|
||||
|
||||
// hide all other open context menus
|
||||
$('#pf-dialog-wrapper > .dropdown-menu').hide();
|
||||
|
||||
var contextMenu = $(settings.menuSelector);
|
||||
|
||||
var menuLiElements = contextMenu.find('li');
|
||||
|
||||
// show all menu entries
|
||||
menuLiElements.show();
|
||||
|
||||
// disable specific menu entries
|
||||
for(var i = 0; i < hiddenOptions.length; i++){
|
||||
contextMenu.find('li[data-action="' + hiddenOptions[i] + '"]').hide();
|
||||
}
|
||||
|
||||
// deactivate all menu entries
|
||||
menuLiElements.removeClass('active');
|
||||
|
||||
//set active specific menu entries
|
||||
for(var j = 0; j < activeOptions.length; j++){
|
||||
contextMenu.find('li[data-action="' + activeOptions[j] + '"]').addClass('active');
|
||||
}
|
||||
|
||||
//open menu
|
||||
contextMenu.css({
|
||||
position: 'absolute',
|
||||
left: getLeftLocation(originalEvent),
|
||||
top: getTopLocation(originalEvent)
|
||||
}).velocity(animationInType, {
|
||||
duration: animationInDuration,
|
||||
complete: function(){
|
||||
// set context menu "click" observer
|
||||
$(this).off('click').one('click', {component: component, position:{x: originalEvent.offsetX, y: originalEvent.offsetY}}, function (e) {
|
||||
// hide contextmenu
|
||||
$(this).hide();
|
||||
|
||||
var params = {
|
||||
selectedMenu: $(e.target),
|
||||
component: e.data.component,
|
||||
position: e.data.position
|
||||
};
|
||||
|
||||
settings.menuSelected.call(this, params);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
//make sure menu closes on any click
|
||||
$(document).one('click.closeContextmenu', function () {
|
||||
$('.dropdown-menu[role="menu"]').velocity(animationOutType, {
|
||||
duration: animationOutDuration
|
||||
});
|
||||
});
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function getLeftLocation(e) {
|
||||
var mouseWidth = e.pageX;
|
||||
var pageWidth = $(window).width();
|
||||
var menuWidth = $(settings.menuSelector).width();
|
||||
|
||||
// opening menu would pass the side of the page
|
||||
if (mouseWidth + menuWidth > pageWidth &&
|
||||
menuWidth < mouseWidth) {
|
||||
return mouseWidth - menuWidth;
|
||||
}
|
||||
return mouseWidth;
|
||||
}
|
||||
|
||||
function getTopLocation(e) {
|
||||
var mouseHeight = e.pageY;
|
||||
var pageHeight = $(window).height();
|
||||
var menuHeight = $(settings.menuSelector).height();
|
||||
|
||||
// opening menu would pass the bottom of the page
|
||||
if (mouseHeight + menuHeight > pageHeight &&
|
||||
menuHeight < mouseHeight) {
|
||||
return mouseHeight - menuHeight;
|
||||
}
|
||||
return mouseHeight;
|
||||
}
|
||||
|
||||
};
|
||||
});
|
||||
156
public/js/v1.0.0RC3/app/map/magnetizing.js
Normal file
156
public/js/v1.0.0RC3/app/map/magnetizing.js
Normal file
@@ -0,0 +1,156 @@
|
||||
/**
|
||||
* Map "magnetizing" feature
|
||||
* jsPlumb extension used: http://morrisonpitt.com/farahey/
|
||||
*/
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'farahey'
|
||||
], function($) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var config = {
|
||||
systemClass: 'pf-system' // class for all systems
|
||||
};
|
||||
|
||||
/**
|
||||
* Cached current "Magnetizer" object
|
||||
* @type {Magnetizer}
|
||||
*/
|
||||
var m8 = null;
|
||||
|
||||
/**
|
||||
* init a jsPlumb (map) Element for "magnetised" function.
|
||||
* this is optional and prevents systems from being overlapped
|
||||
*/
|
||||
$.fn.initMagnetizer = function(){
|
||||
var mapContainer = this;
|
||||
|
||||
var systemsOnMap = mapContainer.find('.' + config.systemClass);
|
||||
|
||||
/**
|
||||
* helper function
|
||||
* get current system offset
|
||||
* @param system
|
||||
* @returns {{left, top}}
|
||||
* @private
|
||||
*/
|
||||
var _offset = function(system) {
|
||||
|
||||
var _ = function(p) {
|
||||
var v = system.style[p];
|
||||
return parseInt(v.substring(0, v.length - 2));
|
||||
};
|
||||
|
||||
return {
|
||||
left:_('left'),
|
||||
top:_('top')
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* helper function
|
||||
* set new syste offset
|
||||
* @param system
|
||||
* @param o
|
||||
* @private
|
||||
*/
|
||||
var _setOffset = function(system, o) {
|
||||
|
||||
var markAsUpdated = false;
|
||||
|
||||
// new position must be within parent container
|
||||
// no negative offset!
|
||||
if(
|
||||
o.left >= 0 &&
|
||||
o.left <= 2300
|
||||
){
|
||||
markAsUpdated = true;
|
||||
system.style.left = o.left + 'px';
|
||||
}
|
||||
|
||||
if(
|
||||
o.top >= 0 &&
|
||||
o.top <= 498
|
||||
){
|
||||
markAsUpdated = true;
|
||||
system.style.top = o.top + 'px';
|
||||
}
|
||||
|
||||
if(markAsUpdated === true){
|
||||
$(system).markAsChanged();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* helper function
|
||||
* exclude current dragged element(s) from position update
|
||||
* @param id
|
||||
* @returns {boolean}
|
||||
* @private
|
||||
*/
|
||||
var _dragFilter = function(id) {
|
||||
|
||||
return !$('#' + id).hasClass('jsPlumb_dragged');
|
||||
};
|
||||
|
||||
// main init for "magnetize" feature ------------------------------------------------------
|
||||
m8 = new Magnetizer({
|
||||
container: mapContainer,
|
||||
getContainerPosition:function(c) {
|
||||
return c.offset();
|
||||
},
|
||||
getPosition:_offset,
|
||||
getSize: function(system) {
|
||||
return [ $(system).outerWidth(), $(system).outerHeight() ];
|
||||
},
|
||||
getId : function(system) {
|
||||
return $(system).attr('id');
|
||||
},
|
||||
setPosition:_setOffset,
|
||||
elements: systemsOnMap,
|
||||
filter:_dragFilter,
|
||||
padding:[8, 8]
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
$.fn.destroyMagnetizer = function(){
|
||||
var mapContainer = this;
|
||||
|
||||
// remove cached "magnetizer" instance
|
||||
m8 = null;
|
||||
};
|
||||
|
||||
/**
|
||||
* update system positions for "all" systems that are effected by drag&drop
|
||||
* @param map
|
||||
* @param e
|
||||
*/
|
||||
var executeAtEvent = function(map, e){
|
||||
|
||||
// check if magnetizer is active
|
||||
if(m8 !== null && e ){
|
||||
m8.executeAtEvent(e);
|
||||
map.repaintEverything();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* rearrange all systems of a map
|
||||
* needs "magnetization" to be active
|
||||
* @param map
|
||||
*/
|
||||
var executeAtCenter = function(map){
|
||||
if(m8 !== null){
|
||||
m8.executeAtCenter();
|
||||
map.repaintEverything();
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
executeAtCenter: executeAtCenter,
|
||||
executeAtEvent: executeAtEvent
|
||||
};
|
||||
});
|
||||
3597
public/js/v1.0.0RC3/app/map/map.js
Normal file
3597
public/js/v1.0.0RC3/app/map/map.js
Normal file
File diff suppressed because it is too large
Load Diff
273
public/js/v1.0.0RC3/app/map/overlay.js
Normal file
273
public/js/v1.0.0RC3/app/map/overlay.js
Normal file
@@ -0,0 +1,273 @@
|
||||
/**
|
||||
* map overlay functions
|
||||
*/
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util'
|
||||
], function($, Init, Util) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var config = {
|
||||
logTimerCount: 3, // map log timer in seconds
|
||||
|
||||
// map
|
||||
mapWrapperClass: 'pf-map-wrapper', // wrapper div (scrollable)
|
||||
|
||||
// map overlays
|
||||
mapOverlayClass: 'pf-map-overlay', // class for all map overlays
|
||||
mapOverlayTimerClass: 'pf-map-overlay-timer', // class for map overlay timer e.g. map timer
|
||||
mapOverlayInfoClass: 'pf-map-overlay-info' // class for map overlay info e.g. map info
|
||||
|
||||
};
|
||||
|
||||
// overlay options (all available map options shown in overlay)
|
||||
var options = {
|
||||
filter: {
|
||||
title: 'active filter',
|
||||
class: 'pf-map-overlay-filter',
|
||||
iconClass: ['fa', 'fa-fw', 'fa-filter']
|
||||
},
|
||||
mapSnapToGrid: {
|
||||
title: 'active grid',
|
||||
class: 'pf-map-overlay-grid',
|
||||
iconClass: ['glyphicon', 'glyphicon-th']
|
||||
},
|
||||
mapMagnetizer: {
|
||||
title: 'active magnetizer',
|
||||
class: 'pf-map-overlay-magnetizer',
|
||||
iconClass: ['fa', 'fa-fw', 'fa-magnet']
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* get map overlay element by type e.g. timer/counter, info - overlay
|
||||
* @param overlayType
|
||||
* @returns {*}
|
||||
*/
|
||||
$.fn.getMapOverlay = function(overlayType){
|
||||
|
||||
var mapWrapperElement = $(this).parents('.' + config.mapWrapperClass);
|
||||
|
||||
var mapOverlay = null;
|
||||
switch(overlayType){
|
||||
case 'timer':
|
||||
mapOverlay = mapWrapperElement.find('.' + config.mapOverlayTimerClass);
|
||||
break;
|
||||
case 'info':
|
||||
mapOverlay = mapWrapperElement.find('.' + config.mapOverlayInfoClass);
|
||||
break;
|
||||
}
|
||||
|
||||
return mapOverlay;
|
||||
};
|
||||
|
||||
/**
|
||||
* draws the map update counter to the map overlay timer
|
||||
* @param percent
|
||||
* @returns {*}
|
||||
*/
|
||||
$.fn.setMapUpdateCounter = function(percent, value){
|
||||
|
||||
var mapOverlayTimer = $(this);
|
||||
|
||||
// check if counter already exists
|
||||
var counterChart = mapOverlayTimer.getMapCounter();
|
||||
|
||||
if(counterChart.length === 0){
|
||||
// create new counter
|
||||
|
||||
counterChart = $('<div>', {
|
||||
class: [Init.classes.pieChart.class, Init.classes.pieChart.pieChartMapCounterClass].join(' ')
|
||||
}).attr('data-percent', percent).append(
|
||||
$('<span>', {
|
||||
text: value
|
||||
})
|
||||
);
|
||||
|
||||
mapOverlayTimer.append(counterChart);
|
||||
|
||||
// init counter
|
||||
counterChart.initMapUpdateCounter();
|
||||
|
||||
// set tooltip
|
||||
mapOverlayTimer.attr('data-placement', 'left');
|
||||
mapOverlayTimer.attr('title', 'update counter');
|
||||
mapOverlayTimer.tooltip();
|
||||
}
|
||||
|
||||
return counterChart;
|
||||
};
|
||||
|
||||
/**
|
||||
* get the map counter chart by an overlay
|
||||
* @returns {*}
|
||||
*/
|
||||
$.fn.getMapCounter = function(){
|
||||
|
||||
var mapOverlayTimer = $(this);
|
||||
|
||||
return mapOverlayTimer.find('.' + Init.classes.pieChart.pieChartMapCounterClass);
|
||||
};
|
||||
|
||||
/**
|
||||
* start the map update counter or reset
|
||||
*/
|
||||
$.fn.startMapUpdateCounter = function(){
|
||||
|
||||
var mapOverlayTimer = $(this);
|
||||
var counterChart = mapOverlayTimer.getMapCounter();
|
||||
|
||||
var maxSeconds = config.logTimerCount;
|
||||
|
||||
var counterChartLabel = counterChart.find('span');
|
||||
|
||||
var percentPerCount = 100 / maxSeconds;
|
||||
|
||||
// update counter
|
||||
var updateChart = function(tempSeconds){
|
||||
var pieChart = counterChart.data('easyPieChart');
|
||||
|
||||
if(pieChart !== undefined){
|
||||
counterChart.data('easyPieChart').update( percentPerCount * tempSeconds);
|
||||
}
|
||||
counterChartLabel.text(tempSeconds);
|
||||
};
|
||||
|
||||
// main timer function is called on any counter update
|
||||
var timer = function(){
|
||||
// decrease timer
|
||||
var currentSeconds = counterChart.data('currentSeconds');
|
||||
currentSeconds--;
|
||||
counterChart.data('currentSeconds', currentSeconds);
|
||||
|
||||
|
||||
if(currentSeconds >= 0){
|
||||
// update counter
|
||||
updateChart(currentSeconds);
|
||||
}else{
|
||||
// hide counter and reset
|
||||
clearInterval(mapUpdateCounter);
|
||||
|
||||
mapOverlayTimer.velocity('transition.whirlOut', {
|
||||
duration: Init.animationSpeed.mapOverlay,
|
||||
complete: function(){
|
||||
counterChart.data('interval', false);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// get current seconds (in case the timer is already running)
|
||||
var currentSeconds = counterChart.data('currentSeconds');
|
||||
|
||||
// start values for timer and chart
|
||||
counterChart.data('currentSeconds', maxSeconds);
|
||||
updateChart(maxSeconds);
|
||||
|
||||
if(
|
||||
currentSeconds === undefined ||
|
||||
currentSeconds < 0
|
||||
){
|
||||
// start timer
|
||||
var mapUpdateCounter = setInterval(timer, 1000);
|
||||
|
||||
// store counter interval
|
||||
counterChart.data('interval', mapUpdateCounter);
|
||||
|
||||
// show overlay
|
||||
if(mapOverlayTimer.is(':hidden')){
|
||||
mapOverlayTimer.velocity('stop').velocity('transition.whirlIn', { duration: Init.animationSpeed.mapOverlay });
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* update (show/hide) a overlay icon in the "info"-overlay
|
||||
* show/hide the overlay itself is no icons are visible
|
||||
* @param option
|
||||
* @param viewType
|
||||
*/
|
||||
$.fn.updateOverlayIcon = function(option, viewType){
|
||||
var mapOverlayInfo = $(this);
|
||||
|
||||
var showOverlay = false;
|
||||
|
||||
var mapOverlayIconClass = options[option].class;
|
||||
|
||||
// look for the overlay icon that should be updated
|
||||
var iconElement = mapOverlayInfo.find('.' + mapOverlayIconClass);
|
||||
|
||||
if(iconElement){
|
||||
if(viewType === 'show'){
|
||||
showOverlay = true;
|
||||
iconElement.velocity('fadeIn');
|
||||
}else if(viewType === 'hide'){
|
||||
iconElement.hide();
|
||||
|
||||
// check if there is any visible icon remaining
|
||||
var visibleIcons = mapOverlayInfo.find('i:visible');
|
||||
if(visibleIcons.length > 0){
|
||||
showOverlay = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// show the entire overlay if there is at least one active icon
|
||||
if(
|
||||
showOverlay === true &&
|
||||
mapOverlayInfo.is(':hidden')
|
||||
){
|
||||
// show overlay
|
||||
mapOverlayInfo.velocity('stop').velocity('transition.whirlIn', { duration: Init.animationSpeed.mapOverlay });
|
||||
}else if(
|
||||
showOverlay === false &&
|
||||
mapOverlayInfo.is(':visible')
|
||||
){
|
||||
// hide overlay
|
||||
mapOverlayInfo.velocity('stop').velocity('transition.whirlOut', { duration: Init.animationSpeed.mapOverlay });
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* init all map overlays on a "parent" element
|
||||
* @returns {any|JQuery|*}
|
||||
*/
|
||||
$.fn.initMapOverlays = function(){
|
||||
return this.each(function(){
|
||||
var parentElement = $(this);
|
||||
|
||||
var mapOverlayTimer = $('<div>', {
|
||||
class: [config.mapOverlayClass, config.mapOverlayTimerClass].join(' ')
|
||||
});
|
||||
parentElement.append(mapOverlayTimer);
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// add map overlay info. after scrollbar is initialized
|
||||
var mapOverlayInfo = $('<div>', {
|
||||
class: [config.mapOverlayClass, config.mapOverlayInfoClass].join(' ')
|
||||
});
|
||||
|
||||
// add all overlay elements
|
||||
for (var prop in options) {
|
||||
if(options.hasOwnProperty(prop)){
|
||||
mapOverlayInfo.append(
|
||||
$('<i>', {
|
||||
class: options[prop].iconClass.concat( ['pull-right', options[prop].class] ).join(' ')
|
||||
}).attr('title', options[prop].title).tooltip({
|
||||
placement: 'left',
|
||||
container: 'body'
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
parentElement.append(mapOverlayInfo);
|
||||
|
||||
// reset map update timer
|
||||
mapOverlayTimer.setMapUpdateCounter(100, config.logTimerCount);
|
||||
});
|
||||
};
|
||||
|
||||
});
|
||||
318
public/js/v1.0.0RC3/app/mappage.js
Normal file
318
public/js/v1.0.0RC3/app/mappage.js
Normal file
@@ -0,0 +1,318 @@
|
||||
/**
|
||||
* Main map application
|
||||
*/
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util',
|
||||
'app/render',
|
||||
'app/logging',
|
||||
'app/ccp',
|
||||
'app/page',
|
||||
'app/ui/form_element',
|
||||
'app/module_map'
|
||||
], function($, Init, Util, Render, Logging, CCP, Page) {
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* main init "map" page
|
||||
*/
|
||||
$(function(){
|
||||
// load page
|
||||
$('body').loadPageStructure();
|
||||
|
||||
// show app information in browser console
|
||||
Util.showVersionInfo();
|
||||
|
||||
// init logging
|
||||
Logging.init();
|
||||
|
||||
if( !CCP.isTrusted() ){
|
||||
// show trust message
|
||||
$(document).trigger('pf:showTrustDialog');
|
||||
return;
|
||||
}
|
||||
var mapModule = $('#' + Util.config.mapModuleId);
|
||||
|
||||
// map init load static data =======================================================
|
||||
$.getJSON( Init.path.initMap, function( initData ) {
|
||||
|
||||
|
||||
if( initData.error.length > 0 ){
|
||||
for(var i = 0; i < initData.error.length; i++){
|
||||
Util.showNotify({
|
||||
title: initData.error[i].title,
|
||||
text: initData.error[i].message,
|
||||
type: initData.error[i].type
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Init.timer = initData.timer;
|
||||
Init.mapTypes = initData.mapTypes;
|
||||
Init.mapScopes = initData.mapScopes;
|
||||
Init.connectionScopes = initData.connectionScopes;
|
||||
Init.systemStatus = initData.systemStatus;
|
||||
Init.systemType = initData.systemType;
|
||||
Init.characterStatus = initData.characterStatus;
|
||||
Init.maxSharedCount = initData.maxSharedCount;
|
||||
Init.routes = initData.routes;
|
||||
|
||||
// init tab change observer, Once the timers are available
|
||||
Page.initTabChangeObserver();
|
||||
|
||||
// init map module
|
||||
mapModule.initMapModule();
|
||||
|
||||
}).fail(function( jqXHR, status, error) {
|
||||
var reason = status + ' ' + jqXHR.status + ': ' + error;
|
||||
|
||||
$(document).trigger('pf:shutdown', {reason: reason});
|
||||
});
|
||||
|
||||
/**
|
||||
* main function for init all map relevant trigger calls
|
||||
*/
|
||||
$.fn.initMapModule = function(){
|
||||
|
||||
var mapModule = $(this);
|
||||
|
||||
// log keys ------------------------------------------------------------------------
|
||||
|
||||
// ajax request update map data
|
||||
var logKeyServerMapData = 'UPDATE_SERVER_MAP';
|
||||
|
||||
// update client map data
|
||||
var logKeyClientMapData = 'UPDATE_CLIENT_MAP';
|
||||
|
||||
// ajax request update map user data
|
||||
var logKeyServerUserData = 'UPDATE_SERVER_USER_DATA';
|
||||
|
||||
// update client map user data
|
||||
var logKeyClientUserData = 'UPDATE_CLIENT_USER_DATA';
|
||||
|
||||
// main update intervals/trigger (heartbeat)
|
||||
var updateTimeouts = {
|
||||
mapUpdate: 0,
|
||||
userUpdate: 0
|
||||
};
|
||||
|
||||
// ping for main map update ========================================================
|
||||
var triggerMapUpdatePing = function(){
|
||||
|
||||
// check each execution time if map module is still available
|
||||
var check = $('#' + mapModule.attr('id')).length;
|
||||
|
||||
if(check === 0){
|
||||
// program crash stop any update
|
||||
return;
|
||||
}
|
||||
|
||||
// get updated map data
|
||||
var updatedMapData = mapModule.getMapModuleDataForUpdate();
|
||||
|
||||
// wrap array to object
|
||||
updatedMapData = {mapData: updatedMapData};
|
||||
|
||||
// start log
|
||||
Util.timeStart(logKeyServerMapData);
|
||||
|
||||
// store updatedMapData
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: Init.path.updateMapData,
|
||||
data: updatedMapData,
|
||||
dataType: 'json'
|
||||
}).done(function(data){
|
||||
|
||||
// log request time
|
||||
var duration = Util.timeStop(logKeyServerMapData);
|
||||
Util.log(logKeyServerMapData, {duration: duration, type: 'server', description: 'request map data'});
|
||||
|
||||
if(
|
||||
data.error &&
|
||||
data.error.length > 0
|
||||
){
|
||||
// any error in the main trigger functions result in a user log-off
|
||||
$(document).trigger('pf:menuLogout');
|
||||
}else{
|
||||
|
||||
$(document).setProgramStatus('online');
|
||||
|
||||
if(data.mapData.length === 0){
|
||||
// clear all existing maps
|
||||
mapModule.clearMapModule();
|
||||
|
||||
// no map data available -> show "new map" dialog
|
||||
$(document).trigger('pf:menuShowMapSettings', {tab: 'new'});
|
||||
}else{
|
||||
// map data found
|
||||
|
||||
// start log
|
||||
Util.timeStart(logKeyClientMapData);
|
||||
|
||||
// load/update main map module
|
||||
mapModule.updateMapModule(data.mapData);
|
||||
|
||||
// log client map update time
|
||||
duration = Util.timeStop(logKeyClientMapData);
|
||||
Util.log(logKeyClientMapData, {duration: duration, type: 'client', description: 'update map'});
|
||||
}
|
||||
|
||||
// get the current update delay (this can change if a user is inactive)
|
||||
var mapUpdateDelay = Util.getCurrentTriggerDelay( logKeyServerMapData, 0 );
|
||||
|
||||
// init new trigger
|
||||
updateTimeouts.mapUpdate = setTimeout(function(){
|
||||
triggerMapUpdatePing();
|
||||
}, mapUpdateDelay);
|
||||
|
||||
// initial start for the userUpdate trigger
|
||||
// this should only be called at the first time!
|
||||
if(updateTimeouts.userUpdate === 0){
|
||||
|
||||
// start user update trigger after map loaded
|
||||
updateTimeouts.userUpdate = setTimeout(function(){
|
||||
triggerUserUpdatePing();
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
|
||||
}).fail(handleAjaxErrorResponse);
|
||||
};
|
||||
|
||||
// ping for user data update =======================================================
|
||||
var triggerUserUpdatePing = function(){
|
||||
|
||||
// IMPORTANT: Get user data for ONE map that is currently visible
|
||||
// On later releases this can be easy changed to "full update" all maps for a user
|
||||
//
|
||||
var mapIds = [];
|
||||
var activeMap = Util.getMapModule().getActiveMap();
|
||||
if(activeMap){
|
||||
mapIds = [ activeMap.data('id') ];
|
||||
}
|
||||
|
||||
var updatedUserData = {
|
||||
mapIds: mapIds,
|
||||
systemData: Util.getCurrentSystemData()
|
||||
};
|
||||
|
||||
Util.timeStart(logKeyServerUserData);
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: Init.path.updateUserData,
|
||||
data: updatedUserData,
|
||||
dataType: 'json'
|
||||
}).done(function(data){
|
||||
|
||||
// log request time
|
||||
var duration = Util.timeStop(logKeyServerUserData);
|
||||
Util.log(logKeyServerUserData, {duration: duration, type: 'server', description:'request user data'});
|
||||
|
||||
if(data.error.length > 0){
|
||||
// any error in the main trigger functions result in a user log-off
|
||||
$(document).trigger('pf:menuLogout');
|
||||
}else{
|
||||
|
||||
$(document).setProgramStatus('online');
|
||||
|
||||
if(data.userData !== undefined){
|
||||
// store current user data global (cache)
|
||||
var userData = Util.setCurrentUserData(data.userData);
|
||||
|
||||
if(userData.character === undefined){
|
||||
// no active character found -> show settings dialog
|
||||
|
||||
Util.showNotify({title: 'Main character not set', text: 'Check your API data and set a main character', type: 'error'});
|
||||
|
||||
$(document).triggerMenuEvent('ShowSettingsDialog');
|
||||
}
|
||||
|
||||
// store current map user data (cache)
|
||||
if(data.mapUserData !== undefined){
|
||||
Util.setCurrentMapUserData(data.mapUserData);
|
||||
}
|
||||
|
||||
// start log
|
||||
Util.timeStart(logKeyClientUserData);
|
||||
|
||||
// active character data found
|
||||
mapModule.updateMapModuleData();
|
||||
|
||||
// log client user data update time
|
||||
duration = Util.timeStop(logKeyClientUserData);
|
||||
Util.log(logKeyClientUserData, {duration: duration, type: 'client', description:'update users'});
|
||||
|
||||
// update system info panels
|
||||
if(data.system){
|
||||
mapModule.updateSystemModuleData(data.system);
|
||||
}
|
||||
|
||||
// get the current update delay (this can change if a user is inactive)
|
||||
var mapUserUpdateDelay = Util.getCurrentTriggerDelay( logKeyServerUserData, 0 );
|
||||
|
||||
// init new trigger
|
||||
updateTimeouts.userUpdate = setTimeout(function(){
|
||||
triggerUserUpdatePing();
|
||||
}, mapUserUpdateDelay);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}).fail(handleAjaxErrorResponse);
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Ajax error response handler function for main-ping functions
|
||||
* @param jqXHR
|
||||
* @param status
|
||||
* @param error
|
||||
*/
|
||||
var handleAjaxErrorResponse = function(jqXHR, status, error){
|
||||
// clear both main update request trigger timer
|
||||
clearUpdateTimeouts();
|
||||
|
||||
var reason = status + ' ' + jqXHR.status + ': ' + error;
|
||||
var errorData = [];
|
||||
|
||||
if(jqXHR.responseText){
|
||||
var errorObj = $.parseJSON(jqXHR.responseText);
|
||||
|
||||
if(
|
||||
errorObj.error &&
|
||||
errorObj.error.length > 0
|
||||
){
|
||||
errorData = errorObj.error;
|
||||
}
|
||||
}
|
||||
|
||||
$(document).trigger('pf:shutdown', {reason: reason, error: errorData});
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* clear both main update timeouts
|
||||
* -> stop program from working -> shutdown
|
||||
*/
|
||||
var clearUpdateTimeouts = function(){
|
||||
for(var intervalKey in updateTimeouts) {
|
||||
|
||||
if(updateTimeouts.hasOwnProperty(intervalKey)){
|
||||
clearTimeout( updateTimeouts[intervalKey] );
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// initial start of the map update function
|
||||
triggerMapUpdatePing();
|
||||
|
||||
};
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
769
public/js/v1.0.0RC3/app/module_map.js
Normal file
769
public/js/v1.0.0RC3/app/module_map.js
Normal file
@@ -0,0 +1,769 @@
|
||||
define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util',
|
||||
'app/map/map',
|
||||
'app/counter',
|
||||
'app/ui/system_info',
|
||||
'app/ui/system_graph',
|
||||
'app/ui/system_signature',
|
||||
'app/ui/system_route',
|
||||
'app/ui/system_killboard',
|
||||
'datatablesTableTools',
|
||||
'datatablesResponsive'
|
||||
], function($, Init, Util, Map) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var config = {
|
||||
dynamicElementWrapperId: 'pf-dialog-wrapper', // parent Element for dynamic content (dialogs,..)
|
||||
mapTabElementId: 'pf-map-tab-element', // id for map tab element (tabs + content)
|
||||
mapTabBarId: 'pf-map-tabs', // id for map tab bar
|
||||
mapTabIdPrefix: 'pf-map-tab-', // id prefix for a map tab
|
||||
mapTabClass: 'pf-map-tab', // class for a map tab
|
||||
mapTabLinkTextClass: 'nav-tabs-link', // class for span elements in a tab
|
||||
mapTabIconClass: 'pf-map-tab-icon', // class for map icon
|
||||
mapTabSharedIconClass: 'pf-map-tab-shared-icon', // class for map shared icon
|
||||
mapTabContentClass: 'pf-map-tab-content', // class for tab content container
|
||||
mapTabContentSystemInfoClass: 'pf-map-tab-content-system',
|
||||
mapWrapperClass: 'pf-map-wrapper', // scrollable
|
||||
mapClass: 'pf-map', // class for each map
|
||||
|
||||
// TabContentStructure
|
||||
mapTabContentRow: 'pf-map-content-row', // main row for Tab content (grid)
|
||||
mapTabContentCell: 'pf-map-content-col', // column
|
||||
mapTabContentCellFirst: 'pf-map-content-col-first', // first column
|
||||
mapTabContentCellSecond: 'pf-map-content-col-second', // second column
|
||||
|
||||
// module
|
||||
moduleClass: 'pf-module', // class for a module
|
||||
moduleClosedClass: 'pf-module-closed' // class for a closed module
|
||||
|
||||
};
|
||||
|
||||
var mapTabChangeBlocked = false; // flag for preventing map tab switch
|
||||
|
||||
/**
|
||||
* get all maps for a maps module
|
||||
* @param mapModule
|
||||
* @returns {*}
|
||||
*/
|
||||
$.fn.getMaps = function(){
|
||||
|
||||
var maps = $(this).find('.' + config.mapClass);
|
||||
|
||||
return maps;
|
||||
};
|
||||
|
||||
/**
|
||||
* get the current active map for
|
||||
* @returns {*}
|
||||
*/
|
||||
$.fn.getActiveMap = function(){
|
||||
|
||||
var map = $(this).find('.active.' + config.mapTabContentClass + ' .' + config.mapClass);
|
||||
|
||||
if(map.length === 0){
|
||||
map = false;
|
||||
}
|
||||
|
||||
return map;
|
||||
};
|
||||
|
||||
/**
|
||||
* set Tab Observer, events are triggered within map.js
|
||||
* @param mapContentModule
|
||||
*/
|
||||
$.fn.setTabContentObserver = function(){
|
||||
|
||||
return this.each(function(){
|
||||
// update Tab Content with system data information
|
||||
$(this).on('pf:drawSystemModules', function(e){
|
||||
|
||||
drawSystemModules($( e.target ));
|
||||
});
|
||||
|
||||
$(this).on('pf:removeSystemModules', function(e){
|
||||
|
||||
removeSystemModules($( e.target ));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* clear all system info modules and remove them
|
||||
* @param tabContentElement
|
||||
*/
|
||||
var removeSystemModules = function(tabContentElement, callback){
|
||||
tabContentElement.find('.' + config.moduleClass).velocity('transition.slideDownOut', {
|
||||
duration: Init.animationSpeed.mapModule,
|
||||
complete: function(tempElement){
|
||||
$(tempElement).remove();
|
||||
|
||||
if(callback){
|
||||
callback();
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* clears and updates the system info element (signature table, system info,...)
|
||||
* @param tabContentElement
|
||||
*/
|
||||
var drawSystemModules = function(tabContentElement){
|
||||
|
||||
var currentSystemData = Util.getCurrentSystemData();
|
||||
|
||||
// get Table cell for system Info
|
||||
var firstCell = $(tabContentElement).find('.' + config.mapTabContentCellFirst);
|
||||
var secondCell = $(tabContentElement).find('.' + config.mapTabContentCellSecond);
|
||||
|
||||
// draw system info module
|
||||
firstCell.drawSystemInfoModule(currentSystemData.mapId, currentSystemData.systemData);
|
||||
|
||||
// draw system graph module
|
||||
firstCell.drawSystemGraphModule(currentSystemData.systemData);
|
||||
|
||||
// draw signature table module
|
||||
firstCell.drawSignatureTableModule(currentSystemData.systemData);
|
||||
|
||||
// draw system routes module
|
||||
secondCell.drawSystemRouteModule(currentSystemData.systemData);
|
||||
|
||||
// draw system killboard module
|
||||
secondCell.drawSystemKillboardModule(currentSystemData.systemData);
|
||||
|
||||
// set Module Observer
|
||||
setModuleObserver();
|
||||
};
|
||||
|
||||
/**
|
||||
* set observer for each module
|
||||
*/
|
||||
var setModuleObserver = function(){
|
||||
|
||||
// toggle height for a module
|
||||
$(document).off('click.toggleModuleHeight').on('click.toggleModuleHeight', '.' + config.moduleClass, function(e){
|
||||
var moduleElement = $(this);
|
||||
// get click position
|
||||
var posX = moduleElement.offset().left;
|
||||
var posY = moduleElement.offset().top;
|
||||
var clickX = e.pageX - posX;
|
||||
var clickY = e.pageY - posY;
|
||||
|
||||
// check for top-left click
|
||||
if(clickX <= 6 && clickY <= 6){
|
||||
|
||||
// remember height
|
||||
if(! moduleElement.data('origHeight')){
|
||||
|
||||
moduleElement.data('origHeight', moduleElement.outerHeight());
|
||||
}
|
||||
|
||||
if(moduleElement.hasClass( config.moduleClosedClass )){
|
||||
var moduleHeight = moduleElement.data('origHeight');
|
||||
moduleElement.velocity('finish').velocity({
|
||||
height: [ moduleHeight + 'px', [ 400, 15 ] ]
|
||||
},{
|
||||
duration: 400,
|
||||
easing: 'easeInSine',
|
||||
complete: function(){
|
||||
moduleElement.removeClass( config.moduleClosedClass );
|
||||
moduleElement.removeData();
|
||||
}
|
||||
});
|
||||
}else{
|
||||
moduleElement.velocity('finish').velocity({
|
||||
height: [ '40px', [ 400, 15 ] ]
|
||||
},{
|
||||
duration: 400,
|
||||
easing: 'easeInSine',
|
||||
complete: function(){
|
||||
moduleElement.addClass( config.moduleClosedClass );
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* updates only visible/active map module
|
||||
* @returns {boolean}
|
||||
*/
|
||||
$.fn.updateMapModuleData = function(){
|
||||
var mapModule = $(this);
|
||||
|
||||
// get all active map elements for module
|
||||
var mapElement = mapModule.getActiveMap();
|
||||
|
||||
if(mapElement !== false){
|
||||
var mapId = mapElement.data('id');
|
||||
|
||||
var currentMapUserData = Util.getCurrentMapUserData(mapId);
|
||||
|
||||
// update map with current user data
|
||||
if(currentMapUserData){
|
||||
mapElement.updateUserData(currentMapUserData);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* update system info panels (below map)
|
||||
* @param systemData
|
||||
*/
|
||||
$.fn.updateSystemModuleData = function(systemData){
|
||||
var mapModule = $(this);
|
||||
|
||||
if(systemData){
|
||||
// check if current open system is still the requested info system
|
||||
var currentSystemData = Util.getCurrentSystemData();
|
||||
|
||||
if(currentSystemData){
|
||||
if(systemData.id === currentSystemData.systemData.id){
|
||||
// trigger system update event
|
||||
$(document).trigger('pf:updateSystemModules', [systemData]);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* load all structure elements into a TabsContent div (tab body)
|
||||
*/
|
||||
$.fn.initContentStructure = function(){
|
||||
|
||||
return this.each(function(){
|
||||
// init bootstrap Grid
|
||||
var contentStructure = $('<div>', {
|
||||
class: ['row', config.mapTabContentRow].join(' ')
|
||||
}).append(
|
||||
$('<div>', {
|
||||
class: ['col-xs-12', 'col-md-8', config.mapTabContentCellFirst, config.mapTabContentCell].join(' ')
|
||||
})
|
||||
).append(
|
||||
$('<div>', {
|
||||
class: ['col-xs-12', 'col-md-4', config.mapTabContentCellSecond, config.mapTabContentCell].join(' ')
|
||||
})
|
||||
);
|
||||
|
||||
|
||||
// append grid structure
|
||||
$(this).append(contentStructure);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* get a fresh tab element
|
||||
* @param options
|
||||
* @returns {*|jQuery|HTMLElement}
|
||||
*/
|
||||
var getTabElement = function(options){
|
||||
|
||||
var tabElement = $('<div>', {
|
||||
id: config.mapTabElementId
|
||||
});
|
||||
|
||||
var tabBar = $('<ul>', {
|
||||
class: ['nav', 'nav-tabs'].join(' '),
|
||||
id: options.barId
|
||||
}).attr('role', 'tablist');
|
||||
|
||||
var tabContent = $('<div>', {
|
||||
class: 'tab-content'
|
||||
}).attr('data-map-tabs', options.barId);
|
||||
|
||||
tabElement.append(tabBar);
|
||||
tabElement.append(tabContent);
|
||||
|
||||
return tabElement;
|
||||
};
|
||||
|
||||
/**
|
||||
* set data for a map tab, or update an existing map tab with new data
|
||||
* @param options
|
||||
*/
|
||||
$.fn.updateTabData = function(options){
|
||||
var tabElement = $(this);
|
||||
|
||||
// set "main" data
|
||||
tabElement.data('map-id', options.id).data('updated', options.updated);
|
||||
|
||||
// change "tab" link
|
||||
tabElement.attr('href', '#' + config.mapTabIdPrefix + options.id);
|
||||
|
||||
// change "map" icon
|
||||
var mapIconElement = tabElement.find('.' + config.mapTabIconClass);
|
||||
mapIconElement.removeClass().addClass([config.mapTabIconClass, 'fa', 'fa-fw', options.icon].join(' '));
|
||||
|
||||
// change "shared" icon
|
||||
var mapSharedIconElement = tabElement.find('.' + config.mapTabSharedIconClass);
|
||||
mapSharedIconElement.hide();
|
||||
|
||||
// check if the map is a "shared" map
|
||||
if(options.access){
|
||||
if(
|
||||
options.access.user.length > 1 ||
|
||||
options.access.corporation.length > 1 ||
|
||||
options.access.alliance.length > 1
|
||||
){
|
||||
mapSharedIconElement.show();
|
||||
}
|
||||
}
|
||||
|
||||
// change map name label
|
||||
var tabLinkTextElement = tabElement.find('.' + config.mapTabLinkTextClass);
|
||||
tabLinkTextElement.text(options.name);
|
||||
|
||||
// change tabClass
|
||||
var listElement = tabElement.parent();
|
||||
|
||||
// new tab classes
|
||||
var tabClasses = [config.mapTabClass, options.type.classTab ];
|
||||
|
||||
// check if tab was "active" before
|
||||
if( listElement.hasClass('active') ){
|
||||
tabClasses.push('active');
|
||||
}
|
||||
|
||||
listElement.removeClass().addClass( tabClasses.join(' ') );
|
||||
|
||||
// set title for tooltip
|
||||
if(options.type.name !== undefined){
|
||||
|
||||
tabLinkTextElement.attr('title', options.type.name + ' map');
|
||||
}
|
||||
|
||||
var mapTooltipOptions = {
|
||||
placement: 'bottom',
|
||||
container: 'body',
|
||||
trigger: 'hover',
|
||||
delay: 150
|
||||
};
|
||||
|
||||
listElement.find('[title]').tooltip(mapTooltipOptions).tooltip('fixTitle');
|
||||
|
||||
if(options.right === true){
|
||||
listElement.addClass('pull-right');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* add a new tab to tab-map-module end returns the new objects
|
||||
* @param options
|
||||
* @returns {{listElement: (*|void), contentElement: (*|HTMLElement)}}
|
||||
*/
|
||||
$.fn.addTab = function(options){
|
||||
|
||||
var tabElement = $(this);
|
||||
var tabBar = tabElement.find('ul.nav-tabs');
|
||||
var tabContent = tabElement.find('div.tab-content');
|
||||
|
||||
var listElement = $('<li>').attr('role', 'presentation');
|
||||
|
||||
if(options.right === true){
|
||||
listElement.addClass('pull-right');
|
||||
}
|
||||
|
||||
// link element
|
||||
var linkElement = $('<a>').attr('role', 'tab');
|
||||
|
||||
// map icon element
|
||||
var mapIconElement = $('<i>', {
|
||||
class: config.mapTabIconClass
|
||||
});
|
||||
|
||||
// map shared icon element
|
||||
var mapSharedIconElement = $('<i>', {
|
||||
class: [config.mapTabSharedIconClass, 'fa', 'fa-fw', 'fa-share-alt'].join(' '),
|
||||
title: 'shared map'
|
||||
});
|
||||
|
||||
// text element
|
||||
var textElement = $('<span>', {
|
||||
class: config.mapTabLinkTextClass
|
||||
});
|
||||
|
||||
var newListElement = listElement.append(
|
||||
linkElement.append(mapIconElement).append(textElement).append(mapSharedIconElement)
|
||||
);
|
||||
|
||||
tabBar.append( newListElement );
|
||||
|
||||
// update Tab element -> set data
|
||||
linkElement.updateTabData(options);
|
||||
|
||||
// tabs content =======================================================
|
||||
var contentElement = $('<div>', {
|
||||
id: config.mapTabIdPrefix + parseInt( options.id ),
|
||||
class: [config.mapTabContentClass].join(' ')
|
||||
});
|
||||
|
||||
contentElement.addClass('tab-pane');
|
||||
|
||||
tabContent.append(contentElement);
|
||||
|
||||
// init tab ===========================================================
|
||||
linkElement.on('click', function(e){
|
||||
e.preventDefault();
|
||||
|
||||
// callback function after tab switch
|
||||
function switchTabCallback(mapElement, tabLinkElement){
|
||||
tabLinkElement.tab('show');
|
||||
// unfreeze map
|
||||
mapElement.data('frozen', false);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(mapTabChangeBlocked === false){
|
||||
|
||||
var tabLinkElement = $(this);
|
||||
var mapId = tabLinkElement.data('map-id');
|
||||
|
||||
// ignore "add" tab. no need for map change
|
||||
if(mapId > 0){
|
||||
var mapElement = $('#' + config.mapTabElementId).getActiveMap();
|
||||
|
||||
if(mapId !== mapElement.data('id')){
|
||||
// block tabs until switch is done
|
||||
mapTabChangeBlocked = true;
|
||||
|
||||
// freeze active map -> no user data update while map switch
|
||||
mapElement.data('frozen', true);
|
||||
|
||||
// hide current map with animation
|
||||
mapElement.visualizeMap('hide', function(){
|
||||
// un-block map tabs
|
||||
mapTabChangeBlocked = switchTabCallback(mapElement, tabLinkElement);
|
||||
});
|
||||
}
|
||||
}else{
|
||||
tabLinkElement.tab('show');
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return {
|
||||
listElement: newListElement,
|
||||
contentElement: contentElement
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* deletes a map tab for a given map id
|
||||
* @param mapId
|
||||
*/
|
||||
$.fn.deleteTab = function(mapId){
|
||||
|
||||
var tabElement = $(this);
|
||||
|
||||
var linkElement = tabElement.find('a[href="#' + config.mapTabIdPrefix + mapId + '"]');
|
||||
|
||||
var deletedTabName = '';
|
||||
|
||||
if(linkElement.length > 0){
|
||||
deletedTabName = linkElement.find('.' + config.mapTabLinkTextClass).text();
|
||||
|
||||
var liElement = linkElement.parent();
|
||||
var contentElement = tabElement.find('div[id="' + config.mapTabIdPrefix + mapId + '"]');
|
||||
|
||||
var findNewActiveTab = false;
|
||||
// check if liElement was active
|
||||
if(liElement.hasClass('active')){
|
||||
// search any remaining li element and set active
|
||||
findNewActiveTab = true;
|
||||
}
|
||||
|
||||
liElement.remove();
|
||||
contentElement.remove();
|
||||
|
||||
// remove map instance from local cache
|
||||
Map.clearMapInstance(mapId);
|
||||
|
||||
if(findNewActiveTab === true){
|
||||
tabElement.find('.' + config.mapTabClass + ':not(.pull-right):first a').tab('show');
|
||||
}
|
||||
}
|
||||
|
||||
return deletedTabName;
|
||||
};
|
||||
|
||||
/**
|
||||
* clear all active maps
|
||||
*/
|
||||
$.fn.clearMapModule = function(){
|
||||
|
||||
var mapModuleElement = $(this);
|
||||
|
||||
var tabMapElement = $('#' + config.mapTabElementId);
|
||||
|
||||
if(tabMapElement.length > 0){
|
||||
var tabElements = mapModuleElement.getMapTabElements();
|
||||
|
||||
for(var i = 0; i < tabElements.length; i++){
|
||||
var tabElement = $(tabElements[i]);
|
||||
var mapId = tabElement.data('map-id');
|
||||
|
||||
if(mapId > 0){
|
||||
tabMapElement.deleteTab(mapId);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* load/update map module into element (all maps)
|
||||
* @param mapData
|
||||
* @returns {boolean}
|
||||
*/
|
||||
$.fn.updateMapModule = function(mapData){
|
||||
|
||||
if(mapData.length === 0){
|
||||
return true;
|
||||
}
|
||||
|
||||
// store current map data global (cache)
|
||||
// temp store current map data to prevent data-change while function execution!
|
||||
var tempMapData = Util.setCurrentMapData(mapData);
|
||||
|
||||
var mapModuleElement = $(this);
|
||||
|
||||
// check if tabs module is already loaded
|
||||
var tabMapElement = $('#' + config.mapTabElementId);
|
||||
|
||||
// check if tabs have changed
|
||||
var tabsChanged = false;
|
||||
|
||||
if(tabMapElement.length > 0){
|
||||
// tab element already exists
|
||||
var tabElements = mapModuleElement.getMapTabElements();
|
||||
|
||||
// map ID that is currently active
|
||||
var activeMapId = 0;
|
||||
|
||||
// mapIds that are currently active
|
||||
var activeMapIds = [];
|
||||
|
||||
// check whether a tab/map is still active
|
||||
for(var i = 0; i < tabElements.length; i++){
|
||||
var tabElement = $(tabElements[i]);
|
||||
var mapId = tabElement.data('map-id');
|
||||
|
||||
if(mapId > 0){
|
||||
|
||||
var tabMapData = Util.getCurrentMapData(mapId);
|
||||
|
||||
if(tabMapData !== false){
|
||||
// map data available ->
|
||||
activeMapIds.push(mapId);
|
||||
|
||||
// check for map data change and update tab
|
||||
if(tabMapData.config.updated !== tabElement.data('updated')){
|
||||
tabElement.updateTabData(tabMapData.config);
|
||||
}
|
||||
|
||||
}else{
|
||||
// map data not available -> remove tab
|
||||
var deletedTabName = tabMapElement.deleteTab(mapId);
|
||||
|
||||
tabsChanged = true;
|
||||
|
||||
if(deletedTabName.length > 0){
|
||||
Util.showNotify({title: 'Map removed', text: deletedTabName + ' deleted', type: 'warning'});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add new tabs for new maps
|
||||
$.each(tempMapData, function(i, data){
|
||||
|
||||
if( activeMapIds.indexOf( data.config.id ) === -1 ){
|
||||
// add new map tab
|
||||
|
||||
var newTabElements = tabMapElement.addTab(data.config);
|
||||
|
||||
// check if there is any active map yet (this is not the case
|
||||
// when ALL maps are removed AND new maps are added in one call
|
||||
// e.g. character switch)
|
||||
if(tabMapElement.find('.' + config.mapTabClass + '.active:not(.pull-right)').length === 0){
|
||||
tabMapElement.find('.' + config.mapTabClass + ':not(.pull-right):first a').tab('show');
|
||||
|
||||
activeMapId = data.config.id;
|
||||
}
|
||||
|
||||
// set observer for manually triggered map events
|
||||
newTabElements.contentElement.setTabContentObserver();
|
||||
|
||||
// load all the structure elements for the new tab
|
||||
newTabElements.contentElement.initContentStructure();
|
||||
|
||||
tabsChanged = true;
|
||||
|
||||
Util.showNotify({title: 'Map added', text: data.config.name + ' added', type: 'success'});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// get current active map
|
||||
if(activeMapId === 0){
|
||||
activeMapId = Util.getMapModule().getActiveMap().data('id');
|
||||
}
|
||||
var activeMapData = Util.getCurrentMapData(activeMapId);
|
||||
|
||||
if(activeMapData !== false){
|
||||
// update active map with new mapData
|
||||
var currentTabContentElement = $('#' + config.mapTabIdPrefix + activeMapId);
|
||||
$( currentTabContentElement).loadMap( activeMapData, {} );
|
||||
}
|
||||
}else{
|
||||
// create Tab Element
|
||||
|
||||
tabsChanged = true;
|
||||
|
||||
var options = {
|
||||
barId: config.mapTabBarId
|
||||
};
|
||||
|
||||
tabMapElement = getTabElement(options);
|
||||
|
||||
// add new tab for each map
|
||||
for(var j = 0; j < tempMapData.length; j++){
|
||||
|
||||
var data = tempMapData[j];
|
||||
tabMapElement.addTab(data.config);
|
||||
}
|
||||
|
||||
// add "add" button
|
||||
var tabAddOptions = {
|
||||
id: 0,
|
||||
type: {
|
||||
classTab: Util.getInfoForMap( 'standard', 'classTab')
|
||||
},
|
||||
icon: 'fa-plus',
|
||||
name: 'add',
|
||||
right: true
|
||||
};
|
||||
|
||||
tabMapElement.addTab(tabAddOptions);
|
||||
|
||||
|
||||
mapModuleElement.prepend(tabMapElement);
|
||||
|
||||
// set first Tab active
|
||||
tabMapElement.find('.' + config.mapTabClass + ':first a').tab('show');
|
||||
|
||||
// ==============================================================
|
||||
|
||||
// this new created module
|
||||
var tabContentElements = tabMapElement.find('.' + config.mapTabContentClass);
|
||||
|
||||
// set observer for manually triggered map events
|
||||
tabContentElements.setTabContentObserver();
|
||||
|
||||
// load all the structure elements for ALL Tab Content Body
|
||||
tabContentElements.initContentStructure();
|
||||
|
||||
// load first map i in first tab content container
|
||||
$( tabContentElements[0] ).loadMap( tempMapData[0], {showAnimation: true} );
|
||||
}
|
||||
|
||||
if(tabsChanged === true){
|
||||
|
||||
// remove previous event handlers
|
||||
var allTabElements = mapModuleElement.getMapTabElements();
|
||||
allTabElements.off('show.bs.tab');
|
||||
allTabElements.off('shown.bs.tab');
|
||||
allTabElements.off('hide.bs.tab');
|
||||
|
||||
|
||||
// check for "new map" action before tap-change
|
||||
allTabElements.on('show.bs.tab', function (e) {
|
||||
var mapId = $(e.target).data('map-id');
|
||||
|
||||
if(mapId === 0){
|
||||
// add new Tab selected
|
||||
$(document).trigger('pf:menuShowMapSettings', {tab: 'new'});
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
// load new map right after tab-change
|
||||
allTabElements.on('shown.bs.tab', function (e) {
|
||||
var mapId = $(e.target).data('map-id');
|
||||
var tabMapData = Util.getCurrentMapData(mapId);
|
||||
|
||||
if(tabMapData !== false){
|
||||
// load map
|
||||
var currentTabContentElement = $('#' + config.mapTabIdPrefix + mapId);
|
||||
|
||||
$( currentTabContentElement).loadMap( tabMapData, {showAnimation: true} );
|
||||
|
||||
// "wake up" scrollbar for map and get previous state back
|
||||
var scrollableElement = currentTabContentElement.find('.' + config.mapWrapperClass);
|
||||
$(scrollableElement).mCustomScrollbar( 'update');
|
||||
}else{
|
||||
// no map data found -> remove tab
|
||||
tabMapElement.deleteTab(mapId);
|
||||
}
|
||||
});
|
||||
|
||||
allTabElements.on('hide.bs.tab', function (e) {
|
||||
|
||||
var newMapId = $(e.relatedTarget).data('map-id');
|
||||
var oldMapId = $(e.target).data('map-id');
|
||||
|
||||
// disable map if new map is selected -> not "add button"
|
||||
if(newMapId > 0){
|
||||
|
||||
var currentTabContentElement = $('#' + config.mapTabIdPrefix + oldMapId);
|
||||
|
||||
// disable scrollbar for map that will be hidden. "freeze" current state
|
||||
var scrollableElement = currentTabContentElement.find('.' + config.mapWrapperClass);
|
||||
$(scrollableElement).mCustomScrollbar( 'disable' );
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
/**
|
||||
* collect all data (systems/connections) for export/save from each active map in the map module
|
||||
* if no change detected -> do not attach map data to return array
|
||||
* @returns {Array}
|
||||
*/
|
||||
$.fn.getMapModuleDataForUpdate = function(){
|
||||
|
||||
// get all active map elements for module
|
||||
var mapElements = $(this).getMaps();
|
||||
|
||||
var data = [];
|
||||
for(var i = 0; i < mapElements.length; i++){
|
||||
// get all changed (system / connection) data from this map
|
||||
var mapData = $(mapElements[i]).getMapDataFromClient({forceData: false, checkForChange: true});
|
||||
|
||||
if(mapData !== false){
|
||||
|
||||
if(
|
||||
mapData.data.systems.length > 0 ||
|
||||
mapData.data.connections.length > 0
|
||||
){
|
||||
data.push(mapData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
};
|
||||
|
||||
});
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user