Merge pull request #929 from exodus4d/develop

v2.0.0
This commit is contained in:
Mark Friedrich
2020-04-06 22:52:56 +02:00
committed by GitHub
738 changed files with 27353 additions and 39260 deletions

1
.gitignore vendored
View File

@@ -47,7 +47,6 @@ Temporary Items
# project files
# ========================
.idea
.sass-cache
.usage
*.gz
composer-dev.lock

View File

@@ -35,7 +35,7 @@
"latedef": false,
// Enforce line length to 100 characters
"maxlen": 200,
"maxlen": 220,
// Require capitalized names for constructor functions.
"newcap": true,

View File

@@ -1,18 +1,16 @@
# ![Pathfinder logo](favicon/favicon-32x32.png "Logo") *PATHFINDER*
Mapping tool for [*EVE ONLINE*](https://www.eveonline.com)
#### Mapping tool for [*EVE ONLINE*](https://www.eveonline.com)
- Project URL [https://www.pathfinder-w.space](https://www.pathfinder-w.space)
- 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)
- Videos [youtube.com](https://www.youtube.com/channel/UC7HU7XEoMbqRwqxDTbMjSPg)
- Licence [MIT](http://opensource.org/licenses/MIT)
#### Development
- Test server
- URL: http://www.dev.pathfinder-w.space
- Test server: [https://www.dev.pathfinder-w.space](https://www.dev.pathfinder-w.space)
- Running current `develop` branch
- _SISI_ _ESI_ (make sure to use your test-server client)
- Available for public testing (e.g. new feature,.. )
- Available for public testing (e.g. new feature, )
- Database will be cleared from time to time
- Installation guide:
- [wiki](https://github.com/exodus4d/pathfinder/wiki)
@@ -27,52 +25,55 @@ Issues should be reported in the [Issue](https://github.com/exodus4d/pathfinder/
***
### Project structure
<pre>
─╮
├─ app/ [0755] → PHP root
│ ├─ Controller/ → controller classes for app/ajax endpoints (see routes.ini)
│ ├─ Cron/ → controller classes cronjob endpoints (see cron.ini)
│ ├─ Data/ → classes for data handling
│ ├─ Db/ → classes for DB handling
│ ├─ Exception/ → custom exceptions
│ ├─ Lib/ → libs
│ ├─ Model/ → ORM
│ ├─ config.ini → config - F3 core config: <a href="//fatfreeframework.com/3.7/quick-reference#SystemVariables" title="Fat-Free Framework - SystemVariables">SystemVariables</a>
│ ├─ cron.ini → config - cronjobs
│ ├─ environment.ini → config - system environment
│ ├─ pathfinder.ini → config - pathfinder
│ ├─ plugin.ini → config - custom plugins
│ ├─ requirements.ini → config - system requirements
│ └─ routes.ini → config - routes
├─ export/ [0755] → static data
│ ├─ csv/ → *.csv used by /setup page
│ └─ sql/ → DB dump for import (eve_universe.sql.zip)
├─ favicon/ [0755] → favicons
├─ history/ [0777] → log files (map history logs) [optional]
├─ js/ [0755] → JS source files (not used for production)
│ ├─ app/ → "PATHFINDER" core files
│ ├─ lib/ → 3rd party libs
│ └─ app.js → require.js config
├─ logs/ [0777] → log files
│ └─ …
├─ public/ [0755] → static resources
│ ├─ css/ → CSS dist/build folder (minified)
│ ├─ fonts/ → icon-/fonts
│ ├─ img/ → images
│ ├─ js/ → JS dist/build folder and source maps (minified, uglified)
│ └─ templates/ → templates
├─ sass/ → SCSS sources (not used for production)
├─ tmp/ [0777] → cache folder (PHP templates)
│ └─ cache/ [0777] → cache folder (PHP cache)
├─ .htaccess [0755] → reroute/caching rules ("Apache" only!)
└─ index.php [0755]
```
|-- [0755] app/ --> backend [*.php]
|-- app/ --> "Fat Free Framework" extensions
|-- lib/ --> "Fat Free Framework"
|-- main/ --> "PATHFINDER" root
|-- config.ini --> config "f3" framework
|-- cron.ini --> config - cronjobs
|-- environment.ini --> config - system environment
|-- pathfinder.ini --> config - pathfinder
|-- requirements.ini --> config - system requirements
|-- routes.ini --> config - routes
|-- [0755] export/ --> static data
|-- csv/ --> *.csv used by /setup page
|-- sql/ --> DB dump for import (eve_universe.sql.zip)
|-- [0755] favicon/ --> Favicons
|-- [0777] history/ --> log files (map history logs) [optional]
|-- [0755] js/ --> JS source files
|-- app/ --> "PASTHFINDER" core files (not used for production)
|-- lib/ --> 3rd partie extension/library (not used for production)
|-- app.js --> require.js config (!required for production!)
|-- [0777] logs/ --> log files
|-- ...
|-- node_modules/ --> node.js modules (not used for production)
|-- ...
|-- [0755] public/ --> frontend source
|-- css/ --> CSS dist/build folder (minified)
|-- fonts/ --> (icon)-Fonts
|-- img/ --> images
|-- js/ --> JS dist/build folder and source maps (minified, uglified)
|-- templates/ --> templates
|-- sass/ --> SCSS source (not used for production)
|-- [0777] tmp/ --> cache folder
|-- [0755] .htaccess --> reroute/caching rules ("Apache" only!)
|-- [0755] index.php
--------------------------
━━━━━━━━━━━━━━━━━━━━━━━━━━
CI/CD config files:
--------------------------
|-- .jshintrc --> "JSHint" config (not used for production)
|-- composer.json --> Composer package definition
|-- config.rb --> "Compass" config (not used for production)
|-- gulpfile.js --> "Gulp" task config (not used for production )
|-- package.json --> "Node.js" dependency config (not used for production)
|-- README.md --> This file :) (not used for production)
```
├─ .jshintrc "JSHint" config (not used for production)
├─ composer.json → "Composer" package definition
├─ gulpfile.js → "Gulp" task config (not used for production)
├─ package.json → "Node.js" dependency config (not used for production)
└─ README.md → This file :) (not used for production)
</pre>
***

View File

@@ -6,10 +6,10 @@
* Time: 23:30
*/
namespace Controller;
namespace Exodus4D\Pathfinder\Controller;
use Model\Pathfinder;
use Exodus4D\Pathfinder\Model\Pathfinder;
class AccessController extends Controller {
@@ -77,11 +77,11 @@ class AccessController extends Controller {
/**
* broadcast MapModel to clients
* @see broadcastMapData()
* @param Pathfinder\MapModel $map
* @param bool $noCache
*/
protected function broadcastMap(Pathfinder\MapModel $map) : void {
$this->broadcastMapData($this->getFormattedMapData($map));
protected function broadcastMap(Pathfinder\MapModel $map, bool $noCache = false) : void {
$this->broadcastMapData($this->getFormattedMapData($map, $noCache));
}
@@ -99,18 +99,13 @@ class AccessController extends Controller {
/**
* get formatted Map Data
* @param Pathfinder\MapModel $map
* @return array
* @throws \Exception
*/
/**
* @param Pathfinder\MapModel $map
* @param bool $noCache
* @return array|null
*/
protected function getFormattedMapData(Pathfinder\MapModel $map) : ?array {
protected function getFormattedMapData(Pathfinder\MapModel $map, bool $noCache = false) : ?array {
$data = null;
try{
$mapData = $map->getData();
$mapData = $map->getData($noCache);
$data = [
'config' => $mapData->mapData,
'data' => [

View File

@@ -6,15 +6,15 @@
* Time: 20:30
*/
namespace Controller;
namespace Exodus4D\Pathfinder\Controller;
use Controller\Ccp\Sso;
use lib\Config;
use Model\Pathfinder\CharacterModel;
use Model\Pathfinder\CorporationModel;
use Model\Pathfinder\MapModel;
use Model\Pathfinder\RoleModel;
use Exodus4D\Pathfinder\Controller\Ccp\Sso;
use Exodus4D\Pathfinder\Lib\Config;
use Exodus4D\Pathfinder\Model\Pathfinder\CharacterModel;
use Exodus4D\Pathfinder\Model\Pathfinder\CorporationModel;
use Exodus4D\Pathfinder\Model\Pathfinder\MapModel;
use Exodus4D\Pathfinder\Model\Pathfinder\RoleModel;
class Admin extends Controller{
@@ -203,7 +203,7 @@ class Admin extends Controller{
// character has access to that corporation -> create/update/delete rights...
if($corporationRightsData = (array)$settings['rights']){
// get existing corp rights
foreach($corporation->getRights(['addInactive' => true]) as $corporationRight){
foreach($corporation->getRights($corporation::RIGHTS, ['addInactive' => true]) as $corporationRight){
$corporationRightData = $corporationRightsData[$corporationRight->rightId->_id];
if(
$corporationRightData &&

View File

@@ -6,10 +6,10 @@
* Time: 17:42
*/
namespace Controller\Api;
namespace Exodus4D\Pathfinder\Controller\Api;
use Controller;
use Model\Pathfinder;
use Exodus4D\Pathfinder\Controller;
use Exodus4D\Pathfinder\Model\Pathfinder;
class Access extends Controller\AccessController {

View File

@@ -7,12 +7,11 @@
* Time: 03:34
*/
namespace Controller\Api;
namespace Exodus4D\Pathfinder\Controller\Api;
use lib\Config;
use Controller;
use Exodus4D\Pathfinder\Lib\Config;
use Exodus4D\Pathfinder\Controller;
/**
* Github controller
@@ -36,9 +35,7 @@ class GitHub extends Controller\Controller {
$return->version->delta = null;
$return->version->dev = false;
$md = \Markdown::instance();
$releases = $f3->gitHubClient()->getProjectReleases('exodus4d/pathfinder', $releaseCount);
$releases = $f3->gitHubClient()->send('getProjectReleases', 'exodus4d/pathfinder', $releaseCount);
foreach($releases as $key => &$release){
// check version ------------------------------------------------------------------------------------------
@@ -70,12 +67,12 @@ class GitHub extends Controller\Controller {
// convert Markdown to HTML -> use either gitHub API (in oder to create abs, issue links)
// -> or F3´s markdown as fallback
$html = $f3->gitHubClient()->markdownToHtml('exodus4d/pathfinder', $body);
$html = $f3->gitHubClient()->send('markdownToHtml', 'exodus4d/pathfinder', $body);
if(!empty($html)){
$body = $html;
}else{
$body = $md->convert(trim($body));
$body = \Markdown::instance()->convert(trim($body));
}
$release['body'] = $body;

View File

@@ -6,15 +6,15 @@
* Time: 20:23
*/
namespace Controller\Api;
namespace Exodus4D\Pathfinder\Controller\Api;
use Controller;
use data\file\FileHandler;
use lib\Config;
use Model\AbstractModel;
use Model\Pathfinder;
use Model\Universe;
use Exception;
use Exodus4D\Pathfinder\Lib\Config;
use Exodus4D\Pathfinder\Controller;
use Exodus4D\Pathfinder\Data\File\FileHandler;
use Exodus4D\Pathfinder\Model\AbstractModel;
use Exodus4D\Pathfinder\Model\Pathfinder;
use Exodus4D\Pathfinder\Model\Universe;
use Exodus4D\Pathfinder\Exception;
/**
* Map controller
@@ -49,7 +49,7 @@ class Map extends Controller\AccessController {
/**
* Get all required static config data for program initialization
* @param \Base $f3
* @throws Exception
* @throws \Exception
*/
public function initData(\Base $f3){
$validInitData = true;
@@ -170,7 +170,7 @@ class Map extends Controller\AccessController {
// get program routes -------------------------------------------------------------------------------------
$return->routes = [
'ssoLogin' => $this->getF3()->alias( 'sso', ['action' => 'requestAuthorization'] )
'ssoLogin' => $this->getF3()->alias('sso', ['action' => 'requestAuthorization'])
];
// get third party APIs -----------------------------------------------------------------------------------
@@ -179,7 +179,13 @@ class Map extends Controller\AccessController {
'zKillboard' => Config::getPathfinderData('api.z_killboard'),
'eveeye' => Config::getPathfinderData('api.eveeye'),
'dotlan' => Config::getPathfinderData('api.dotlan'),
'anoik' => Config::getPathfinderData('api.anoik')
'anoik' => Config::getPathfinderData('api.anoik'),
'eveScout' => Config::getPathfinderData('api.eve_scout')
];
// get Plugin config --------------------------------------------------------------------------------------
$return->plugin = [
'modules' => Config::getPluginConfig('modules')
];
// Character default config -------------------------------------------------------------------------------
@@ -254,11 +260,11 @@ class Map extends Controller\AccessController {
// 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, $message)){
if($f3->exists(Controller\Ccp\Sso::SESSION_KEY_SSO_ERROR, $text)){
$ssoError = (object) [];
$ssoError->type = 'error';
$ssoError->title = 'Login failed';
$ssoError->message = $message;
$ssoError->text = $text;
$return->error[] = $ssoError;
$f3->clear(Controller\Ccp\Sso::SESSION_KEY_SSO_ERROR);
}elseif($validInitData){
@@ -272,7 +278,7 @@ class Map extends Controller\AccessController {
/**
* import new map data
* @param \Base $f3
* @throws Exception
* @throws \Exception
*/
public function import(\Base $f3){
$importData = (array)$f3->get('POST');
@@ -386,7 +392,7 @@ class Map extends Controller\AccessController {
}else{
$maxSystemsError = (object) [];
$maxSystemsError->type = 'error';
$maxSystemsError->message = 'Map has to many systems (' . $systemCount . ').'
$maxSystemsError->text = 'Map has to many systems (' . $systemCount . ').'
.' Max system count is ' . $defaultConfig['max_systems'] . ' for ' . $mapType->name . ' maps.';
$return->error[] = $maxSystemsError;
}
@@ -394,20 +400,20 @@ class Map extends Controller\AccessController {
// systems || connections missing
$missingConfigError = (object) [];
$missingConfigError->type = 'error';
$missingConfigError->message = 'Map data not valid (systems || connections) missing';
$missingConfigError->text = 'Map data not valid (systems || connections) missing';
$return->error[] = $missingConfigError;
}
}else{
$unknownMapScope= (object) [];
$unknownMapScope->type = 'error';
$unknownMapScope->message = 'Map scope unknown!';
$unknownMapScope->text = 'Map scope unknown!';
$return->error[] = $unknownMapScope;
}
}else{
// map config || systems/connections missing
$missingConfigError = (object) [];
$missingConfigError->type = 'error';
$missingConfigError->message = 'Map data not valid (config || data) missing';
$missingConfigError->text = 'Map data not valid (config || data) missing';
$return->error[] = $missingConfigError;
}
@@ -416,250 +422,31 @@ class Map extends Controller\AccessController {
}else{
$unknownMapType = (object) [];
$unknownMapType->type = 'error';
$unknownMapType->message = 'Map type unknown!';
$unknownMapType->text = 'Map type unknown!';
$return->error[] = $unknownMapType;
}
}else{
// map data missing
$missingDataError = (object) [];
$missingDataError->type = 'error';
$missingDataError->message = 'Map data missing';
$missingDataError->text = 'Map data missing';
$return->error[] = $missingDataError;
}
echo json_encode($return);
}
/**
* save a new map or update an existing map
* @param \Base $f3
* @throws Exception
*/
public function save(\Base $f3){
$formData = (array)$f3->get('POST.formData');
$return = (object) [];
$return->error = [];
if( isset($formData['id']) ){
$activeCharacter = $this->getCharacter();
/**
* @var $map Pathfinder\MapModel
*/
$map = Pathfinder\AbstractPathfinderModel::getNew('MapModel');
$map->getById( (int)$formData['id'] );
if(
$map->dry() ||
$map->hasAccess($activeCharacter)
){
try{
// new map
$map->setData($formData);
$map = $map->save($activeCharacter);
$mapDefaultConf = Config::getMapsDefaultConfig();
// save global map access. Depends on map "type"
if($map->isPrivate()){
// share map between characters -> set access
if(isset($formData['mapCharacters'])){
// remove character (re-add later)
$accessCharacters = array_diff($formData['mapCharacters'], [$activeCharacter->_id]);
// avoid abuse -> respect share limits
$maxShared = max($mapDefaultConf['private']['max_shared'] - 1, 0);
$accessCharacters = array_slice($accessCharacters, 0, $maxShared);
// clear map access. In case something has removed from access list
$map->clearAccess();
if($accessCharacters){
/**
* @var $tempCharacter Pathfinder\CharacterModel
*/
$tempCharacter = Pathfinder\AbstractPathfinderModel::getNew('CharacterModel');
foreach($accessCharacters as $characterId){
$tempCharacter->getById( (int)$characterId );
if(
!$tempCharacter->dry() &&
$tempCharacter->shared == 1 // check if map shared is enabled
){
$map->setAccess($tempCharacter);
}
$tempCharacter->reset();
}
}
}
// the current character itself should always have access
// just in case he removed himself :)
$map->setAccess($activeCharacter);
}elseif($map->isCorporation()){
$corporation = $activeCharacter->getCorporation();
if($corporation){
// the current user has to have a corporation when
// working on corporation maps!
// share map between corporations -> set access
if(isset($formData['mapCorporations'])){
// remove character corporation (re-add later)
$accessCorporations = array_diff($formData['mapCorporations'], [$corporation->_id]);
// avoid abuse -> respect share limits
$maxShared = max($mapDefaultConf['corporation']['max_shared'] - 1, 0);
$accessCorporations = array_slice($accessCorporations, 0, $maxShared);
// clear map access. In case something has removed from access list
$map->clearAccess();
if($accessCorporations){
/**
* @var $tempCorporation Pathfinder\CorporationModel
*/
$tempCorporation = Pathfinder\AbstractPathfinderModel::getNew('CorporationModel');
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();
}
}
}
// the corporation of the current user should always have access
$map->setAccess($corporation);
}
}elseif($map->isAlliance()){
$alliance = $activeCharacter->getAlliance();
if($alliance){
// the current user has to have a alliance when
// working on alliance maps!
// share map between alliances -> set access
if(isset($formData['mapAlliances'])){
// remove character alliance (re-add later)
$accessAlliances = array_diff($formData['mapAlliances'], [$alliance->_id]);
// avoid abuse -> respect share limits
$maxShared = max($mapDefaultConf['alliance']['max_shared'] - 1, 0);
$accessAlliances = array_slice($accessAlliances, 0, $maxShared);
// clear map access. In case something has removed from access list
$map->clearAccess();
if($accessAlliances){
/**
* @var $tempAlliance Pathfinder\AllianceModel
*/
$tempAlliance = Pathfinder\AbstractPathfinderModel::getNew('AllianceModel');
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();
}
}
}
// 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);
// broadcast map Access -> and send map Data
$this->broadcastMapAccess($map);
$return->mapData = $map->getData();
}catch(Exception\ValidationException $e){
$return->error[] = $e->getError();
}
}else{
// map access denied
$captchaError = (object) [];
$captchaError->type = 'error';
$captchaError->message = 'Access denied';
$return->error[] = $captchaError;
}
}else{
// map id field missing
$idError = (object) [];
$idError->type = 'error';
$idError->message = 'Map id missing';
$return->error[] = $idError;
}
echo json_encode($return);
}
/**
* delete a map and all dependencies
* @param \Base $f3
* @throws Exception
*/
public function delete(\Base $f3){
$mapData = (array)$f3->get('POST.mapData');
$mapId = (int)$mapData['id'];
$return = (object) [];
$return->deletedMapIds = [];
if($mapId){
$activeCharacter = $this->getCharacter();
/**
* @var $map Pathfinder\MapModel
*/
$map = Pathfinder\AbstractPathfinderModel::getNew('MapModel');
$map->getById($mapId);
if($map->hasAccess($activeCharacter)){
$map->setActive(false);
$map->save($activeCharacter);
$return->deletedMapIds[] = $mapId;
// broadcast map delete
$this->broadcastMapDeleted($mapId);
}
}
echo json_encode($return);
}
/**
* broadcast characters with map access rights to WebSocket server
* -> if characters with map access found -> broadcast mapData to them
* @param Pathfinder\MapModel $map
* @throws Exception
* @throws \Exception
*/
protected function broadcastMapAccess(Pathfinder\MapModel $map){
$mapAccess = [
'id' => $map->_id,
'name' => $map->name,
'characterIds' => array_map(function ($data){
'characterIds' => array_map(function($data){
return $data->id;
}, $map->getCharactersData())
];
@@ -667,22 +454,14 @@ class Map extends Controller\AccessController {
$this->getF3()->webSocket()->write('mapAccess', $mapAccess);
// map has (probably) active connections that should receive map Data
$this->broadcastMap($map);
}
/**
* broadcast map delete information to clients
* @param int $mapId
*/
protected function broadcastMapDeleted(int $mapId){
$this->getF3()->webSocket()->write('mapDeleted', $mapId);
$this->broadcastMap($map, true);
}
/**
* get map access tokens for current character
* -> send access tokens via TCP Socket for WebSocket auth
* @param \Base $f3
* @throws Exception
* @throws \Exception
*/
public function getAccessData(\Base $f3){
$return = (object) [];
@@ -827,7 +606,7 @@ class Map extends Controller\AccessController {
* update map data
* -> function is called continuously (trigger) by any active client
* @param \Base $f3
* @throws Exception
* @throws \Exception
*/
public function updateData(\Base $f3){
$postData = (array)$f3->get('POST');
@@ -851,7 +630,7 @@ class Map extends Controller\AccessController {
* onUnload map sync
* @see https://developer.mozilla.org/docs/Web/API/Navigator/sendBeacon
* @param \Base $f3
* @throws Exception
* @throws \Exception
*/
public function updateUnloadData(\Base $f3){
$postData = (array)$f3->get('POST');
@@ -870,7 +649,7 @@ class Map extends Controller\AccessController {
* update map data api
* -> function is called continuously by any active client
* @param \Base $f3
* @throws Exception
* @throws \Exception
*/
public function updateUserData(\Base $f3){
$postData = (array)$f3->get('POST');
@@ -941,7 +720,7 @@ class Map extends Controller\AccessController {
* @param Pathfinder\CharacterModel $character
* @param array $newSystemPositions
* @return Pathfinder\MapModel
* @throws Exception
* @throws \Exception
*/
protected function updateMapByCharacter(Pathfinder\MapModel $map, Pathfinder\CharacterModel $character, array $newSystemPositions = []) : Pathfinder\MapModel {
// map changed. update cache (system/connection) changed
@@ -1065,7 +844,7 @@ class Map extends Controller\AccessController {
){
// check distance between systems (in jumps)
// -> if > 1 it is !very likely! a wormhole
$route = (new Route())->searchRoute($sourceSystem->systemId, $targetSystem->systemId, 1);
$route = (new Controller\Api\Rest\Route())->searchRoute($sourceSystem->systemId, $targetSystem->systemId, 1);
if(!$route['routePossible']){
$addSourceSystem = true;
@@ -1165,7 +944,7 @@ class Map extends Controller\AccessController {
// .. now we need to check jump distance between systems
// -> if > 1 it is !very likely! podded jump
if(empty($route)){
$route = (new Route())->searchRoute($sourceSystem->systemId, $targetSystem->systemId, 1);
$route = (new Controller\Api\Rest\Route())->searchRoute($sourceSystem->systemId, $targetSystem->systemId, 1);
}
if(!$route['routePossible']){
@@ -1207,7 +986,7 @@ class Map extends Controller\AccessController {
/**
* get connectionData
* @param \Base $f3
* @throws Exception
* @throws \Exception
*/
public function getConnectionData(\Base $f3){
$postData = (array)$f3->get('POST');
@@ -1258,7 +1037,7 @@ class Map extends Controller\AccessController {
/**
* get map log data
* @param \Base $f3
* @throws Exception
* @throws \Exception
*/
public function getLogData(\Base $f3){
$postData = (array)$f3->get('POST');

View File

@@ -6,9 +6,9 @@
* Time: 16:14
*/
namespace Controller\Api\Rest;
namespace Exodus4D\Pathfinder\Controller\Api\Rest;
use Controller;
use Exodus4D\Pathfinder\Controller;
abstract class AbstractRestController extends Controller\AccessController {

View File

@@ -6,12 +6,58 @@
* Time: 12:10
*/
namespace Controller\Api\Rest;
namespace Exodus4D\Pathfinder\Controller\Api\Rest;
use Model\Pathfinder;
use Exodus4D\Pathfinder\Model\Pathfinder;
class Connection extends AbstractRestController {
/**
* @param \Base $f3
* @param $params
* @throws \Exception
*/
public function get(\Base $f3, $params){
$requestData = $this->getRequestData($f3);
$connectionIds = array_map('intval', explode(',', (string)$params['id']));
$addData = (array)$requestData['addData'];
$filterData = (array)$requestData['filterData'];
$connectionData = [];
if($mapId = (int)$requestData['mapId']){
$activeCharacter = $this->getCharacter();
/**
* @var $map Pathfinder\MapModel
*/
$map = Pathfinder\AbstractPathfinderModel::getNew('MapModel');
$map->getById($mapId);
if($map->hasAccess($activeCharacter)){
$connections = $map->getConnections($connectionIds, 'wh');
foreach($connections as $connection){
$check = true;
$data = $connection->getData(in_array('signatures', $addData), in_array('logs', $addData));
// filter result
if(in_array('signatures', $filterData) && !$data->signatures){
$check = false;
}
if(in_array('logs', $filterData) && !$data->logs){
$check = false;
}
if($check){
$connectionData[] = $data;
}
}
}
}
$this->out($connectionData);
}
/**
* 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
@@ -47,10 +93,16 @@ class Connection extends AbstractRestController {
$connection->mapId = $map;
$connection->source = $source;
$connection->target = $target;
$connection->copyfrom($connectionData, ['scope', 'type']);
// change the default type for the new connection
$connection->setDefaultTypeData();
// if scope + type data send -> use them ...
if($requestData['scope'] && !empty($requestData['type'])){
$connection->copyfrom($requestData, ['scope', 'type']);
}
// ... set/change default scope + type
if(!$requestData['disableAutoScope']){
$connection->setAutoScopeAndType();
}
if($connection->save($activeCharacter)){
$connectionData = $connection->getData();

View File

@@ -6,9 +6,10 @@
* Time: 15:28
*/
namespace Controller\Api\Rest;
namespace Exodus4D\Pathfinder\Controller\Api\Rest;
use Model\Pathfinder;
use Exodus4D\Pathfinder\Model\Pathfinder;
class Log extends AbstractRestController {

View File

@@ -0,0 +1,239 @@
<?php
/**
* Created by PhpStorm.
* User: Exodus 4D
* Date: 12.03.2020
* Time: 19:30
*/
namespace Exodus4D\Pathfinder\Controller\Api\Rest;
use Exodus4D\Pathfinder\Lib\Config;
use Exodus4D\Pathfinder\Model\Pathfinder;
class Map extends AbstractRestController {
/**
* error message missing character right for map delete
*/
const ERROR_MAP_DELETE = 'Character %s does not have sufficient rights for map delete';
/**
* @param \Base $f3
* @param $test
* @throws \Exception
*/
public function put(\Base $f3, $test){
$requestData = $this->getRequestData($f3);
/**
* @var $map Pathfinder\MapModel
*/
$map = Pathfinder\AbstractPathfinderModel::getNew('MapModel');
$mapData = $this->update($map, $requestData)->getData();
$this->out($mapData);
}
/**
* @param \Base $f3
* @param $params
* @throws \Exception
*/
public function patch(\Base $f3, $params){
$requestData = $this->getRequestData($f3);
$mapData = [];
if($mapId = (int)$params['id']){
$activeCharacter = $this->getCharacter();
/**
* @var $map Pathfinder\MapModel
*/
$map = Pathfinder\AbstractPathfinderModel::getNew('MapModel');
$map->getById($mapId);
if($map->hasAccess($activeCharacter)){
$mapData = $this->update($map, $requestData)->getData(true);
}
}
$this->out($mapData);
}
/**
* @param \Base $f3
* @param $params
* @throws \Exception
*/
public function delete(\Base $f3, $params){
$deletedMapIds = [];
if($mapId = (int)$params['id']){
$activeCharacter = $this->getCharacter();
/**
* @var $map Pathfinder\MapModel
*/
$map = Pathfinder\AbstractPathfinderModel::getNew('MapModel');
$map->getById($mapId);
if($map->hasAccess($activeCharacter)){
// check if character has delete right for map type
$hasRight = true;
if($map->isCorporation()){
if($corpRight = $activeCharacter->getCorporation()->getRights(['map_delete'])){
if($corpRight[0]->get('roleId', true) !== $activeCharacter->get('roleId', true)){
$hasRight = false;
}
}
}
if($hasRight){
$map->setActive(false);
$map->save($activeCharacter);
$deletedMapIds[] = $mapId;
// broadcast map delete
$this->broadcastMapDeleted($mapId);
}else{
$f3->set('HALT', true);
$f3->error(401, sprintf(self::ERROR_MAP_DELETE, $activeCharacter->name));
}
}
}
$this->out($deletedMapIds);
}
/**
* @param Pathfinder\MapModel $map
* @param array $mapData
* @return Pathfinder\MapModel
* @throws \Exception
*/
private function update(Pathfinder\MapModel $map, array $mapData) : Pathfinder\MapModel {
$activeCharacter = $this->getCharacter();
$map->setData($mapData);
$typeChange = $map->changed('typeId');
$map->save($activeCharacter);
// save global map access. Depends on map "type" --------------------------------------------------------------
/**
* @param Pathfinder\AbstractPathfinderModel $primaryModel
* @param array|null $modelIds
* @param int $maxShared
* @return int
*/
$setMapAccess = function(Pathfinder\AbstractPathfinderModel &$primaryModel, ?array $modelIds = [], int $maxShared = 3) use (&$map) : int {
$added = 0;
$deleted = 0;
if(is_array($modelIds)){
// remove primaryModel id (-> re-add later)
$modelIds = array_diff(array_map('intval', $modelIds), [$primaryModel->_id]);
// avoid abuse -> respect share limits (-1 is because the primaryModel has also access)
$modelIds = array_slice($modelIds, 0, max($maxShared - 1, 0));
// add the primaryModel id back (again)
$modelIds[] = $primaryModel->_id;
// clear map access for entities that do not match the map "mapType"
$deleted += $map->clearAccessByType();
$compare = $map->compareAccess($modelIds);
foreach((array)$compare['old'] as $modelId) {
$deleted += $map->removeFromAccess($modelId);
}
$modelClass = (new \ReflectionClass($primaryModel))->getShortName();
$tempModel = Pathfinder\AbstractPathfinderModel::getNew($modelClass);
foreach((array)$compare['new'] as $modelId) {
$tempModel->getById($modelId);
if(
$tempModel->valid() &&
(
$modelId == $primaryModel->_id || // primary model has always access (regardless of "shared" value)
$tempModel->shared == 1 // check if map shared is enabled
)
){
$added += (int)$map->setAccess($tempModel);
}
$tempModel->reset();
}
}
return $added + $deleted;
};
$accessChangeCount = 0;
$mapDefaultConf = Config::getMapsDefaultConfig();
if($map->isPrivate()){
$accessChangeCount = $setMapAccess(
$activeCharacter,
$typeChange ? [$activeCharacter->_id] : $mapData['mapCharacters'],
(int)$mapDefaultConf['private']['max_shared']
);
}elseif($map->isCorporation()){
if($corporation = $activeCharacter->getCorporation()){
$accessChangeCount = $setMapAccess(
$corporation,
$typeChange ? [$corporation->_id] : $mapData['mapCorporations'],
(int)$mapDefaultConf['corporation']['max_shared']
);
}
}elseif($map->isAlliance()){
if($alliance = $activeCharacter->getAlliance()){
$accessChangeCount = $setMapAccess(
$alliance,
$typeChange ? [$alliance->_id] : $mapData['mapAlliances'],
(int)$mapDefaultConf['alliance']['max_shared']
);
}
}
if($accessChangeCount){
$map->touch('updated');
$map->save($activeCharacter);
}
// reload the same map model (refresh)
// this makes sure all data is up2date
$map->getById($map->_id, 0);
// broadcast map Access -> and send map Data
$this->broadcastMapAccess($map);
return $map;
}
/**
* broadcast characters with map access rights to WebSocket server
* -> if characters with map access found -> broadcast mapData to them
* @param Pathfinder\MapModel $map
* @throws \Exception
*/
protected function broadcastMapAccess(Pathfinder\MapModel $map){
$mapAccess = [
'id' => $map->_id,
'name' => $map->name,
'characterIds' => array_map(function($data){
return $data->id;
}, $map->getCharactersData())
];
$this->getF3()->webSocket()->write('mapAccess', $mapAccess);
// map has (probably) active connections that should receive map Data
$this->broadcastMap($map, true);
}
/**
* broadcast map delete information to clients
* @param int $mapId
*/
private function broadcastMapDeleted(int $mapId){
$this->getF3()->webSocket()->write('mapDeleted', $mapId);
}
}

View File

@@ -1,24 +1,20 @@
<?php
/**
* Created by PhpStorm.
* User: exodus4d
* Date: 06.06.15
* Time: 03:34
*/
namespace Controller\Api;
use Controller;
use Controller\Ccp\Universe;
use lib\Config;
use Model\Pathfinder;
namespace Exodus4D\Pathfinder\Controller\Api\Rest;
/**
* Routes controller
* Class Route
* @package Controller\Api
*/
class Route extends Controller\AccessController {
use Exodus4D\Pathfinder\Lib\Config;
use Exodus4D\Pathfinder\Controller\Ccp\Universe;
use Exodus4D\Pathfinder\Model\Pathfinder;
class Route extends AbstractRestController {
/**
* cache key for current Thera connections from eve-scout.com
*/
const CACHE_KEY_THERA_JUMP_DATA = 'CACHED_THERA_JUMP_DATA';
/**
* route search depth
@@ -43,6 +39,12 @@ class Route extends Controller\AccessController {
*/
private $dynamicJumpDataCacheTime = 10;
/**
* cache time for Thera connections from eve-scout.com
* @var int
*/
private $theraJumpDataCacheTime = 60;
/**
* array system information grouped by systemId
* @var array
@@ -229,11 +231,11 @@ class Route extends Controller\AccessController {
!is_null($staticData = $universe->getSystemData($row[$systemSourceKey]))
){
$jumpData[$row[$systemSourceKey]] = [
'systemId' => (int)$row[$systemSourceKey],
'systemName' => $staticData->name,
'constellationId' => $staticData->constellation->id,
'regionId' => $staticData->constellation->region->id,
'trueSec' => $staticData->trueSec,
'systemId' => (int)$row[$systemSourceKey],
'systemName' => $staticData->name,
'constellationId' => $staticData->constellation->id,
'regionId' => $staticData->constellation->region->id,
'trueSec' => $staticData->trueSec,
];
}
@@ -247,20 +249,70 @@ class Route extends Controller\AccessController {
$enrichJumpData($rows[$i], 'systemTargetId', 'systemSourceId');
}
// update jump data for this instance
$this->updateJumpData($jumpData);
}
}
}
}
/**
* set current Thera connections jump data for this instance
* -> Connected wormholes pulled from eve-scout.com
*/
private function setTheraJumpData(){
if(!$this->getF3()->exists(self::CACHE_KEY_THERA_JUMP_DATA, $jumpData)){
$jumpData = [];
$connectionsData = $this->getF3()->eveScoutClient()->send('getTheraConnections');
if(!empty($connectionsData) && !isset($connectionsData['error'])){
/**
* map Thera jump data to Pathfinder format
* @param array $row
* @param string $systemSourceKey
* @param string $systemTargetKey
*/
$enrichJumpData = function(array &$row, string $systemSourceKey, string $systemTargetKey) use (&$jumpData) {
// check if response data is valid
if(
is_object($systemSource = $row[$systemSourceKey]) && !empty((array)$systemSource) &&
is_object($systemTarget = $row[$systemTargetKey]) && !empty((array)$systemTarget)
){
if(!array_key_exists($systemSource->id, $jumpData)){
$jumpData[$systemSource->id] = [
'systemId' => (int)$systemSource->id,
'systemName' => $systemSource->name,
'constellationId' => (int)$systemSource->constellationID,
'regionId' => (int)$systemSource->regionId,
'trueSec' => $systemSource->security,
];
}
if( !in_array((int)$systemTarget->id, (array)$jumpData[$systemSource->id]['jumpNodes']) ){
$jumpData[$systemSource->id]['jumpNodes'][] = (int)$systemTarget->id;
}
}
};
foreach((array)$connectionsData['connections'] as $connectionData){
$enrichJumpData($connectionData, 'source', 'target');
$enrichJumpData($connectionData, 'target', 'source');
}
if(!empty($jumpData)){
$this->getF3()->set(self::CACHE_KEY_THERA_JUMP_DATA, $jumpData, $this->theraJumpDataCacheTime);
}
}
}
$this->updateJumpData($jumpData);
}
/**
* update jump data for this instance
* -> data is either coming from CCPs [SDE] OR from map specific data
* @param array $rows
*/
private function updateJumpData(&$rows = []){
foreach($rows as &$row){
$regionId = (int)$row['regionId'];
$constId = (int)$row['constellationId'];
@@ -285,7 +337,7 @@ class Route extends Controller\AccessController {
if( !is_array($this->jumpArray[$systemId]) ){
$this->jumpArray[$systemId] = [];
}
$this->jumpArray[$systemId] = array_merge($row['jumpNodes'], $this->jumpArray[$systemId]);
$this->jumpArray[$systemId] = array_merge((array)$row['jumpNodes'], $this->jumpArray[$systemId]);
// add systemName to end (if not already there)
if(end($this->jumpArray[$systemId]) != $systemName){
@@ -448,7 +500,7 @@ class Route extends Controller\AccessController {
// Endpoint return http:404 in case no route find (e.g. from inside a wh)
// we thread that error "no route found" as a valid response! -> no fallback to custom search
if( !empty($routeData['error']) && strtolower($routeData['error']) !== 'no route found' ){
if(!empty($routeData['error']) && strtolower($routeData['error']) !== 'no route found'){
// ESI route search has errors -> fallback to custom search implementation
$routeData = $this->searchRouteCustom($systemFromId, $systemToId, $searchDepth, $mapIds, $filterData);
}
@@ -484,6 +536,11 @@ class Route extends Controller\AccessController {
// add map specific data
$this->setDynamicJumpData($mapIds, $filterData);
// add current Thera connections data
if($filterData['wormholesThera']){
$this->setTheraJumpData();
}
// filter jump data (e.g. remove some systems (0.0, LS)
// --> don´t filter some systems (e.g. systemFrom, systemTo) even if they are are WH,LS,0.0
$this->filterJumpData($filterData, [$systemFromId, $systemToId]);
@@ -494,10 +551,10 @@ class Route extends Controller\AccessController {
$jumpNum = 0;
$depthSearched = 0;
if( isset($this->jumpArray[$systemFromId]) ){
if(isset($this->jumpArray[$systemFromId])){
// check if the system we are looking for is a direct neighbour
foreach( $this->jumpArray[$systemFromId] as $n ) {
if ($n == $systemToId) {
foreach($this->jumpArray[$systemFromId] as $n){
if($n == $systemToId){
$jumpNum = 2;
$routeData['route'][] = $this->getJumpNodeData($n);
break;
@@ -505,23 +562,23 @@ class Route extends Controller\AccessController {
}
// system is not a direct neighbour -> search recursive its neighbours
if ($jumpNum == 0) {
if($jumpNum == 0){
$searchResult = $this->graph_find_path( $this->jumpArray, $systemFromId, $systemToId, $searchDepth );
$depthSearched = $searchResult['depth'];
foreach( $searchResult['path'] as $systemId ) {
if ($jumpNum > 0) {
foreach($searchResult['path'] as $systemId){
if($jumpNum > 0){
$routeData['route'][] = $this->getJumpNodeData($systemId);
}
$jumpNum++;
}
}
if ($jumpNum > 0) {
if($jumpNum > 0){
// route found
$routeData['routePossible'] = true;
// insert "from" system on top
array_unshift($routeData['route'], $this->getJumpNodeData($systemFromId));
} else {
}else{
// route not found
$routeData['routePossible'] = false;
}
@@ -566,6 +623,11 @@ class Route extends Controller\AccessController {
// add map specific data
$this->setDynamicJumpData($mapIds, $filterData);
// add current Thera connections data
if($filterData['wormholesThera']){
$this->setTheraJumpData();
}
// filter jump data (e.g. remove some systems (0.0, LS)
// --> don´t filter some systems (e.g. systemFrom, systemTo) even if they are are WH,LS,0.0
$this->filterJumpData($filterData, [$systemFromId, $systemToId]);
@@ -576,7 +638,7 @@ class Route extends Controller\AccessController {
if($count > 1){
// ... should always > 1
// loop all connections for current source system
foreach($jumpData as $systemTargetId) {
foreach($jumpData as $systemTargetId){
// skip last entry
if(--$count <= 0){
break;
@@ -606,7 +668,7 @@ class Route extends Controller\AccessController {
'connections' => $connections
];
$result = $this->getF3()->ccpClient()->getRouteData($systemFromId, $systemToId, $options);
$result = $this->getF3()->ccpClient()->send('getRoute', $systemFromId, $systemToId, $options);
// format result ------------------------------------------------------------------------------------------
@@ -660,9 +722,7 @@ class Route extends Controller\AccessController {
];
$keyParts += $filterData;
$key = 'route_' . hash('md5', implode('_', $keyParts));
return $key;
return 'route_' . hash('md5', implode('_', $keyParts));
}
/**
@@ -670,8 +730,8 @@ class Route extends Controller\AccessController {
* @param \Base $f3
* @throws \Exception
*/
public function search($f3){
$requestData = (array)$f3->get('POST');
public function post(\Base $f3){
$requestData = $this->getRequestData($f3);
$activeCharacter = $this->getCharacter();
@@ -736,6 +796,7 @@ class Route extends Controller\AccessController {
'wormholesReduced' => (bool) $routeData['wormholesReduced'],
'wormholesCritical' => (bool) $routeData['wormholesCritical'],
'wormholesEOL' => (bool) $routeData['wormholesEOL'],
'wormholesThera' => (bool) $routeData['wormholesThera'],
'wormholesSizeMin' => (string) $routeData['wormholesSizeMin'],
'excludeTypes' => (array) $routeData['excludeTypes'],
'endpointsBubble' => (bool) $routeData['endpointsBubble'],
@@ -791,21 +852,6 @@ class Route extends Controller\AccessController {
}
}
echo json_encode($return);
$this->out($return);
}
}
}

View File

@@ -6,10 +6,10 @@
* Time: 16:20
*/
namespace Controller\Api\Rest;
namespace Exodus4D\Pathfinder\Controller\Api\Rest;
use Model\Pathfinder;
use Exodus4D\Pathfinder\Model\Pathfinder;
class Signature extends AbstractRestController {

View File

@@ -6,11 +6,11 @@
* Time: 16:44
*/
namespace Controller\Api\Rest;
namespace Exodus4D\Pathfinder\Controller\Api\Rest;
use Model\Pathfinder;
use lib\Config;
use Exodus4D\Pathfinder\Model\Pathfinder;
use Exodus4D\Pathfinder\Lib\Config;
class SignatureHistory extends AbstractRestController {

View File

@@ -6,10 +6,10 @@
* Time: 23:29
*/
namespace Controller\Api\Rest;
namespace Exodus4D\Pathfinder\Controller\Api\Rest;
use Model\Pathfinder;
use Exodus4D\Pathfinder\Model\Pathfinder;
class Structure extends AbstractRestController {

View File

@@ -6,10 +6,10 @@
* Time: 12:34
*/
namespace Controller\Api\Rest;
namespace Exodus4D\Pathfinder\Controller\Api\Rest;
use Model\Pathfinder;
use Exodus4D\Pathfinder\Model\Pathfinder;
class System extends AbstractRestController {

View File

@@ -1,40 +1,28 @@
<?php
/**
* Created by PhpStorm.
* User: exodus4d
* Date: 08.02.15
* Time: 20:23
*/
namespace Controller\Api;
use Controller;
use lib\Config;
use Model\Pathfinder;
namespace Exodus4D\Pathfinder\Controller\Api\Rest;
class System extends Controller\AccessController {
use Exodus4D\Pathfinder\Lib\Config;
use Exodus4D\Pathfinder\Model\Pathfinder;
// cache keys
class SystemGraph extends AbstractRestController {
/**
* cache key for HTTP response
*/
const CACHE_KEY_GRAPH = 'CACHED_SYSTEM_GRAPH_%s';
/**
* get system graph cache key
* @param int $systemId
* @return string
*/
protected function getSystemGraphCacheKey(int $systemId): string {
return sprintf(self::CACHE_KEY_GRAPH, 'SYSTEM_' . $systemId);
}
/**
* get system log data from CCP API import
* system Kills, Jumps,....
* get graphs data for system(s)
* @param \Base $f3
* @param $params
* @throws \Exception
*/
public function graphData(\Base $f3){
public function get(\Base $f3, $params){
$requestData = $this->getRequestData($f3);
$systemIds = (array)$requestData['systemIds'];
$graphsData = [];
$systemIds = (array)$f3->get('GET.systemIds');
// valid response (data found) should be cached by server + client
$cacheResponse = false;
@@ -108,84 +96,17 @@ class System extends Controller\AccessController {
$f3->expire(Config::ttlLeft($exists, $ttl));
}
echo json_encode($graphsData);
$this->out($graphsData);
}
// ----------------------------------------------------------------------------------------------------------------
/**
* set destination for system, station or structure
* @param \Base $f3
* @throws \Exception
* get system graph cache key
* @param int $systemId
* @return string
*/
public function setDestination(\Base $f3){
$postData = (array)$f3->get('POST');
$return = (object) [];
$return->error = [];
$return->destData = [];
if(!empty($destData = (array)$postData['destData'])){
$activeCharacter = $this->getCharacter();
$return->clearOtherWaypoints = (bool)$postData['clearOtherWaypoints'];
$return->first = (bool)$postData['first'];
if($accessToken = $activeCharacter->getAccessToken()){
$options = [
'clearOtherWaypoints' => $return->clearOtherWaypoints,
'addToBeginning' => $return->first,
];
foreach($destData as $data){
$response = $f3->ccpClient()->setWaypoint((int)$data['id'], $accessToken, $options);
if(empty($response)){
$return->destData[] = $data;
}else{
$error = (object) [];
$error->type = 'error';
$error->message = $response['error'];
$return->error[] = $error;
}
}
}
}
echo json_encode($return);
protected function getSystemGraphCacheKey(int $systemId): string {
return sprintf(self::CACHE_KEY_GRAPH, 'SYSTEM_' . $systemId);
}
/**
* send Rally Point poke
* @param \Base $f3
* @throws \Exception
*/
public function pokeRally(\Base $f3){
$rallyData = (array)$f3->get('POST');
$systemId = (int)$rallyData['systemId'];
$return = (object) [];
if($systemId){
$activeCharacter = $this->getCharacter();
/**
* @var $system Pathfinder\SystemModel
*/
$system = Pathfinder\AbstractPathfinderModel::getNew('SystemModel');
$system->getById($systemId);
if($system->hasAccess($activeCharacter)){
$rallyData['pokeDesktop'] = $rallyData['pokeDesktop'] === '1';
$rallyData['pokeMail'] = $rallyData['pokeMail'] === '1';
$rallyData['pokeSlack'] = $rallyData['pokeSlack'] === '1';
$rallyData['pokeDiscord'] = $rallyData['pokeDiscord'] === '1';
$rallyData['message'] = trim($rallyData['message']);
$system->sendRallyPoke($rallyData, $activeCharacter);
}
}
echo json_encode($return);
}
}
}

View File

@@ -0,0 +1,131 @@
<?php
namespace Exodus4D\Pathfinder\Controller\Api\Rest;
use Exodus4D\Pathfinder\Lib\Config;
class SystemThera extends AbstractRestController {
/**
* cache key for HTTP response
*/
const CACHE_KEY_THERA_CONNECTIONS = 'CACHED_THERA_CONNECTIONS';
/**
* get Thera connections data from Eve-Scout
* @param \Base $f3
*/
public function get(\Base $f3){
$ttl = 60 * 3;
if(!$exists = $f3->exists(self::CACHE_KEY_THERA_CONNECTIONS, $connectionsData)){
$connectionsData = $this->getEveScoutTheraConnections();
$f3->set(self::CACHE_KEY_THERA_CONNECTIONS, $connectionsData, $ttl);
}
$f3->expire(Config::ttlLeft($exists, $ttl));
$this->out($connectionsData);
}
/**
* get Thera connections data from EveScout API
* -> map response to Pathfinder format
* @return array
*/
protected function getEveScoutTheraConnections() : array {
$connectionsData = [];
/**
* map system data from eveScout response to Pathfinder´s 'system' format
* @param string $key
* @param array $eveScoutConnection
* @param array $connectionData
*/
$enrichWithSystemData = function(string $key, array $eveScoutConnection, array &$connectionData) : void {
$eveScoutSystem = (array)$eveScoutConnection[$key];
$systemData = [
'id' => (int)$eveScoutSystem['id'],
'name' => (string)$eveScoutSystem['name'],
'trueSec' => round((float)$eveScoutSystem['security'], 4)
];
if(!empty($eveScoutSystem['constellationID'])){
$systemData['constellation'] = ['id' => (int)$eveScoutSystem['constellationID']];
}
if(!empty($region = (array)$eveScoutSystem['region']) && !empty($region['id'])){
$systemData['region'] = ['id' => (int)$region['id'], 'name' => (string)$region['name']];
}
$connectionData[$key] = $systemData;
};
/**
* @param string $key
* @param array $eveScoutConnection
* @param array $connectionData
*/
$enrichWithSignatureData = function(string $key, array $eveScoutConnection, array &$connectionData) : void {
$eveScoutSignature = (array)$eveScoutConnection[$key];
$signatureData = [
'name' => $eveScoutSignature['name'] ? : null
];
if(!empty($sigType = (array)$eveScoutSignature['type']) && !empty($sigType['name'])){
$signatureData['type'] = ['name' => strtoupper((string)$sigType['name'])];
}
$connectionData[$key] = $signatureData;
};
/**
* map wormhole data from eveScout to Pathfinder´s connection format
* @param array $wormholeData
* @param array $connectionsData
*/
$enrichWithWormholeData = function(array $wormholeData, array &$connectionsData) : void {
$type = [];
if($wormholeData['mass'] === 'reduced'){
$type[] = 'wh_reduced';
}else if($wormholeData['mass'] === 'critical'){
$type[] = 'wh_critical';
}else{
$type[] = 'wh_fresh';
}
if($wormholeData['eol'] === 'critical'){
$type[] = 'wh_eol';
}
$connectionsData['type'] = $type;
$connectionsData['estimatedEol'] = $wormholeData['estimatedEol'];
};
$eveScoutResponse = $this->getF3()->eveScoutClient()->send('getTheraConnections');
if(!empty($eveScoutResponse) && !isset($eveScoutResponse['error'])){
foreach((array)$eveScoutResponse['connections'] as $eveScoutConnection){
if(
$eveScoutConnection['type'] === 'wormhole' &&
isset($eveScoutConnection['source']) && isset($eveScoutConnection['target'])
){
try{
$data = [
'id' => (int)$eveScoutConnection['id'],
'scope' => 'wh',
'created' => [
'created' => (new \DateTime($eveScoutConnection['created']))->getTimestamp(),
'character' => (array)$eveScoutConnection['character']
],
'updated' => (new \DateTime($eveScoutConnection['updated']))->getTimestamp()
];
$enrichWithWormholeData((array)$eveScoutConnection['wormhole'], $data);
$enrichWithSystemData('source', $eveScoutConnection, $data);
$enrichWithSystemData('target', $eveScoutConnection, $data);
$enrichWithSignatureData('sourceSignature', $eveScoutConnection, $data);
$enrichWithSignatureData('targetSignature', $eveScoutConnection, $data);
$connectionsData[] = $data;
}catch(\Exception $e){
// new \DateTime Exception -> skip this data
}
}
}
}
return $connectionsData;
}
}

View File

@@ -6,12 +6,13 @@
* Time: 14:17
*/
namespace Controller\Api;
namespace Exodus4D\Pathfinder\Controller\Api;
use Controller;
use lib\Config;
use lib\Cron;
use Model;
use Exodus4D\Pathfinder\Lib\Config;
use Exodus4D\Pathfinder\Lib\Cron;
use Exodus4D\Pathfinder\Lib\Format\Number;
use Exodus4D\Pathfinder\Controller;
use Exodus4D\Pathfinder\Model;
class Setup extends Controller\Controller {
@@ -91,7 +92,7 @@ class Setup extends Controller\Controller {
],
'tplCounter' => $this->counter(),
'tplConvertBytes' => function(){
return call_user_func_array([\lib\format\Number::instance(), 'bytesToString'], func_get_args());
return call_user_func_array([Number::instance(), 'bytesToString'], func_get_args());
}
];
return \Template::instance()->render('templates/ui/cron_table_row.html', null, $tplData, 0);

View File

@@ -6,11 +6,11 @@
* Time: 00:29
*/
namespace controller\api;
namespace Exodus4D\Pathfinder\Controller\Api;
use Controller;
use lib\Config;
use Model\Pathfinder\CharacterModel;
use Exodus4D\Pathfinder\Lib\Config;
use Exodus4D\Pathfinder\Controller;
use Exodus4D\Pathfinder\Model\Pathfinder\CharacterModel;
class Statistic extends Controller\AccessController {

View File

@@ -0,0 +1,94 @@
<?php
/**
* Created by PhpStorm.
* User: exodus4d
* Date: 08.02.15
* Time: 20:23
*/
namespace Exodus4D\Pathfinder\Controller\Api;
use Exodus4D\Pathfinder\Lib\Config;
use Exodus4D\Pathfinder\Controller;
use Exodus4D\Pathfinder\Model\Pathfinder;
class System extends Controller\AccessController {
/**
* set destination for system, station or structure
* @param \Base $f3
* @throws \Exception
*/
public function setDestination(\Base $f3){
$postData = (array)$f3->get('POST');
$return = (object) [];
$return->error = [];
$return->destData = [];
if(!empty($destData = (array)$postData['destData'])){
$activeCharacter = $this->getCharacter();
$return->clearOtherWaypoints = (bool)$postData['clearOtherWaypoints'];
$return->first = (bool)$postData['first'];
if($accessToken = $activeCharacter->getAccessToken()){
$options = [
'clearOtherWaypoints' => $return->clearOtherWaypoints,
'addToBeginning' => $return->first,
];
foreach($destData as $data){
$response = $f3->ccpClient()->send('setWaypoint', (int)$data['id'], $accessToken, $options);
if(empty($response)){
$return->destData[] = $data;
}else{
$error = (object) [];
$error->type = 'error';
$error->text = $response['error'];
$return->error[] = $error;
}
}
}
}
echo json_encode($return);
}
/**
* send Rally Point poke
* @param \Base $f3
* @throws \Exception
*/
public function pokeRally(\Base $f3){
$rallyData = (array)$f3->get('POST');
$systemId = (int)$rallyData['systemId'];
$return = (object) [];
if($systemId){
$activeCharacter = $this->getCharacter();
/**
* @var $system Pathfinder\SystemModel
*/
$system = Pathfinder\AbstractPathfinderModel::getNew('SystemModel');
$system->getById($systemId);
if($system->hasAccess($activeCharacter)){
$rallyData['pokeDesktop'] = $rallyData['pokeDesktop'] === '1';
$rallyData['pokeMail'] = $rallyData['pokeMail'] === '1';
$rallyData['pokeSlack'] = $rallyData['pokeSlack'] === '1';
$rallyData['pokeDiscord'] = $rallyData['pokeDiscord'] === '1';
$rallyData['message'] = trim($rallyData['message']);
$system->sendRallyPoke($rallyData, $activeCharacter);
}
}
echo json_encode($return);
}
}

View File

@@ -6,11 +6,11 @@
* Time: 15:49
*/
namespace Controller\Api;
namespace Exodus4D\Pathfinder\Controller\Api;
use Controller;
use Controller\Ccp as Ccp;
use Model;
use Exodus4D\Pathfinder\Controller;
use Exodus4D\Pathfinder\Controller\Ccp as Ccp;
use Exodus4D\Pathfinder\Model;
class Universe extends Controller\AccessController {

View File

@@ -6,13 +6,13 @@
* Time: 20:50
*/
namespace Controller\Api;
namespace Exodus4D\Pathfinder\Controller\Api;
use Controller;
use lib\Config;
use Model\Pathfinder;
use Exception;
use Exodus4D\Pathfinder\Lib\Config;
use Exodus4D\Pathfinder\Controller;
use Exodus4D\Pathfinder\Model\Pathfinder;
use Exodus4D\Pathfinder\Exception;
class User extends Controller\Controller{
@@ -46,7 +46,7 @@ class User extends Controller\Controller{
* login a valid character
* @param Pathfinder\CharacterModel $character
* @return bool
* @throws Exception
* @throws \Exception
*/
protected function loginByCharacter(Pathfinder\CharacterModel &$character) : bool {
$login = false;
@@ -113,7 +113,7 @@ class User extends Controller\Controller{
* validate cookie character information
* -> return character data (if valid)
* @param \Base $f3
* @throws Exception
* @throws \Exception
*/
public function getCookieCharacter(\Base $f3){
$data = $f3->get('POST');
@@ -140,7 +140,7 @@ class User extends Controller\Controller{
}else{
$characterError = (object) [];
$characterError->type = 'warning';
$characterError->message = 'This can happen through "invalid cookies(SSO)", "login restrictions", "ESI problems".';
$characterError->text = 'This can happen through "invalid cookies(SSO)", "login restrictions", "ESI problems".';
$return->error[] = $characterError;
}
}
@@ -184,7 +184,7 @@ class User extends Controller\Controller{
}else{
$captchaError = (object) [];
$captchaError->type = 'error';
$captchaError->message = 'Could not create captcha image';
$captchaError->text = 'Could not create captcha image';
$return->error[] = $captchaError;
}
@@ -194,17 +194,20 @@ class User extends Controller\Controller{
/**
* log the current user out + clear character system log data
* @param \Base $f3
* @throws Exception
* @throws \Exception
*/
public function logout(\Base $f3){
$this->logoutCharacter($f3, false, true, true, true);
$data = $f3->get('POST');
$deleteCookie = (bool)$data['deleteCookie'];
$this->logoutCharacter($f3, false, true, true, $deleteCookie, 200);
}
/**
* remote open ingame information window (character, corporation or alliance) Id
* -> the type is auto-recognized by CCP
* @param \Base $f3
* @throws Exception
* @throws \Exception
*/
public function openIngameWindow(\Base $f3){
$data = $f3->get('POST');
@@ -215,14 +218,14 @@ class User extends Controller\Controller{
if( $targetId = (int)$data['targetId']){
$activeCharacter = $this->getCharacter();
$response = $f3->ccpClient()->openWindow($targetId, $activeCharacter->getAccessToken());
$response = $f3->ccpClient()->send('openWindow', $targetId, $activeCharacter->getAccessToken());
if(empty($response)){
$return->targetId = $targetId;
}else{
$error = (object) [];
$error->type = 'error';
$error->message = $response['error'];
$error->text = $response['error'];
$return->error[] = $error;
}
}
@@ -235,12 +238,12 @@ class User extends Controller\Controller{
* -> a fresh user automatically generated on first login with a new character
* -> see SSO login
* @param \Base $f3
* @throws Exception
* @throws \Exception
*/
public function saveAccount(\Base $f3){
$data = $f3->get('POST');
$return = (object) [];
$return = (object)[];
$return->error = [];
$captcha = $f3->get(self::SESSION_CAPTCHA_ACCOUNT_UPDATE);
@@ -250,7 +253,7 @@ class User extends Controller\Controller{
$newUserData = null;
if( isset($data['formData']) ){
if(isset($data['formData'])){
$formData = $data['formData'];
try{
@@ -258,18 +261,12 @@ class User extends Controller\Controller{
$user = $activeCharacter->getUser();
// captcha is send -> check captcha ---------------------------------------------------------------
if(
isset($formData['captcha']) &&
!empty($formData['captcha'])
){
if(isset($formData['captcha']) && !empty($formData['captcha'])){
if($formData['captcha'] === $captcha){
// change/set sensitive user data requires captcha!
// set username
if(
isset($formData['name']) &&
!empty($formData['name'])
){
if(isset($formData['name']) && !empty($formData['name'])){
$user->name = $formData['name'];
}
@@ -290,9 +287,9 @@ class User extends Controller\Controller{
}else{
// captcha was send but not valid -> return error
$captchaError = (object) [];
$captchaError = (object)[];
$captchaError->type = 'error';
$captchaError->message = 'Captcha does not match';
$captchaError->text = 'Captcha does not match';
$return->error[] = $captchaError;
}
}
@@ -348,7 +345,7 @@ class User extends Controller\Controller{
/**
* delete current user account from DB
* @param \Base $f3
* @throws Exception
* @throws \Exception
*/
public function deleteAccount(\Base $f3){
$data = $f3->get('POST.formData');
@@ -373,14 +370,14 @@ class User extends Controller\Controller{
sprintf(self::LOG_DELETE_ACCOUNT, $user->id, $user->name)
);
$this->logoutCharacter($f3, true, true, true, true);
$this->logoutCharacter($f3, true, true, true, true, 200);
$user->erase();
}
}else{
// captcha not valid -> return error
$captchaError = (object) [];
$captchaError->type = 'error';
$captchaError->message = 'Captcha does not match';
$captchaError->text = 'Captcha does not match';
$return->error[] = $captchaError;
}

View File

@@ -6,11 +6,12 @@
* Time: 21:27
*/
namespace Controller;
namespace Exodus4D\Pathfinder\Controller;
use Controller\Ccp as Ccp;
use lib\Config;
use lib\Resource;
use Exodus4D\Pathfinder\Controller\Ccp as Ccp;
use Exodus4D\Pathfinder\Lib\Config;
use Exodus4D\Pathfinder\Lib\Resource;
class AppController extends Controller {
@@ -67,10 +68,8 @@ class AppController extends Controller {
$resource = Resource::instance();
$resource->register('script', 'app/login');
$resource->register('script', 'app/mappage', 'prefetch');
$resource->register('image', 'pf-bg.jpg');
$resource->register('image', 'pf-header-bg.jpg');
$resource->register('image', 'landing/eve_sso_login_buttons_large_black.png');
$resource->register('image', 'landing/eve_sso_login_buttons_large_black_hover.png');
$resource->register('image', 'sso/signature.png');
$resource->register('image', 'sso/gameplay.png');
}
}

View File

@@ -11,12 +11,12 @@
* - Check "PATHFINDER.API" in "pathfinder.ini" for correct API URLs
*/
namespace Controller\Ccp;
namespace Exodus4D\Pathfinder\Controller\Ccp;
use Controller;
use Controller\Api as Api;
use Model\Pathfinder;
use Lib;
use Exodus4D\Pathfinder\Controller;
use Exodus4D\Pathfinder\Controller\Api as Api;
use Exodus4D\Pathfinder\Model\Pathfinder;
use Exodus4D\Pathfinder\Lib;
class Sso extends Api\User{
@@ -390,7 +390,7 @@ class Sso extends Api\User{
$accessData->refreshToken = null;
$accessData->esiAccessTokenExpires = 0;
$authCodeRequestData = $this->getF3()->ssoClient()->getAccessData($this->getAuthorizationData(), $requestParams);
$authCodeRequestData = $this->getF3()->ssoClient()->send('getAccess', $this->getAuthorizationData(), $requestParams);
if( !empty($authCodeRequestData) ){
if( !empty($authCodeRequestData['accessToken']) ){
@@ -429,7 +429,7 @@ class Sso extends Api\User{
* @return array
*/
public function verifyCharacterData(string $accessToken) : array {
$characterData = $this->getF3()->ssoClient()->getVerifyCharacterData($accessToken);
$characterData = $this->getF3()->ssoClient()->send('getVerifyCharacter', $accessToken);
if( !empty($characterData) ){
// convert string with scopes to array
@@ -451,8 +451,7 @@ class Sso extends Api\User{
$characterData = (object) [];
if($characterId){
$characterDataBasic = $this->getF3()->ccpClient()->getCharacterData($characterId);
$characterDataBasic = $this->getF3()->ccpClient()->send('getCharacter', $characterId);
if( !empty($characterDataBasic) ){
// remove some "unwanted" data -> not relevant for Pathfinder
$characterData->character = array_filter($characterDataBasic, function($key){

View File

@@ -6,13 +6,13 @@
* Time: 11:31
*/
namespace Controller\Ccp;
namespace Exodus4D\Pathfinder\Controller\Ccp;
use Controller\Controller;
use lib\Util;
use Model;
use Exodus4D\Pathfinder\Controller;
use Exodus4D\Pathfinder\Lib\Util;
use Exodus4D\Pathfinder\Model;
class Universe extends Controller {
class Universe extends Controller\Controller {
const SESSION_KEY_SYSTEM_IDS = 'SESSION.SETUP.SYSTEM_IDS';
@@ -22,7 +22,7 @@ class Universe extends Controller {
$regionsWhitelist = [
10000002 // The Forge (13 constellations -> 93 systems)
];
$regionIds = $f3->ccpClient()->getUniverseRegions();
$regionIds = $f3->ccpClient()->send('getUniverseRegions');
$regionIds = array_intersect($regionsWhitelist, $regionIds);
$region = Model\Universe\AbstractUniverseModel::getNew('RegionModel');
@@ -43,7 +43,7 @@ class Universe extends Controller {
$constellationsWhitelist = [
20000014 // Mal (11 systems)
];
$constellationIds = $f3->ccpClient()->getUniverseConstellations();
$constellationIds = $f3->ccpClient()->send('getUniverseConstellations');
$constellationIds = array_intersect($constellationsWhitelist, $constellationIds);
$constellation = Model\Universe\AbstractUniverseModel::getNew('ConstellationModel');
foreach($constellationIds as $constellationId){
@@ -306,13 +306,13 @@ class Universe extends Controller {
$f3 = \Base::instance();
$universeNameData = [];
if( !empty($categories) && !empty($search)){
$universeIds = $f3->ccpClient()->search($categories, $search, $strict);
$universeIds = $f3->ccpClient()->send('search', $categories, $search, $strict);
if(isset($universeIds['error'])){
// ESI error
$universeNameData = $universeIds;
}elseif( !empty($universeIds) ){
$universeIds = Util::arrayFlattenByValue($universeIds);
$universeNameData = $f3->ccpClient()->getUniverseNamesData($universeIds);
$universeNameData = $f3->ccpClient()->send('getUniverseNames', $universeIds);
}
}
return $universeNameData;

View File

@@ -6,22 +6,30 @@
* Time: 23:48
*/
namespace Controller;
namespace Exodus4D\Pathfinder\Controller;
use Controller\Api as Api;
use Exception\PathfinderException;
use lib\api\CcpClient;
use lib\Config;
use lib\db\SQL;
use lib\Resource;
use lib\Monolog;
use lib\Util;
use Model\AbstractModel;
use Model\Pathfinder;
use DB;
use Exodus4D\Pathfinder\Controller\Api as Api;
use Exodus4D\Pathfinder\Lib\Api\CcpClient;
use Exodus4D\Pathfinder\Lib\Config;
use Exodus4D\Pathfinder\Lib\Db\Sql;
use Exodus4D\Pathfinder\Lib\Resource;
use Exodus4D\Pathfinder\Lib\Monolog;
use Exodus4D\Pathfinder\Lib\Util;
use Exodus4D\Pathfinder\Lib\Format;
use Exodus4D\Pathfinder\Model\AbstractModel;
use Exodus4D\Pathfinder\Model\Pathfinder;
use Exodus4D\Pathfinder\Db\Sql\Mysql;
use Exodus4D\Pathfinder\Exception\PathfinderException;
class Controller {
/**
* default HTTP response status for users that logged out
* -> if it is a "graceful" logout (e.g. user clicks "logout" button, we use 200)
*/
const DEFAULT_STATUS_LOGOUT = 403;
// cookie specific keys (names)
const COOKIE_NAME_STATE = 'cookie';
const COOKIE_PREFIX_CHARACTER = 'char';
@@ -91,12 +99,12 @@ class Controller {
header('Pf-Maintenance: ' . $modeMaintenance);
}
}else{
$this->initResource($f3);
$f3->set('tplResource', $this->initResource($f3));
$this->setTemplate(Config::getPathfinderData('view.index'));
$f3->set('tplImage', \lib\format\Image::instance());
$f3->set('tplImage', Format\Image::instance());
}
return true;
@@ -132,11 +140,11 @@ class Controller {
$f3->get('SESSION_CACHE') === 'mysql' &&
($db = $f3->DB->getDB('PF')) instanceof SQL
){
if(!headers_sent() && session_status()!=PHP_SESSION_ACTIVE){
if(!headers_sent() && session_status() != PHP_SESSION_ACTIVE){
/**
* callback() for suspect sessions
* @param $session
* @param $sid
* @param \DB\SQL\Session $session
* @param string $sid
* @return bool
*/
$onSuspect = function($session, $sid){
@@ -151,7 +159,7 @@ class Controller {
return false;
};
new DB\SQL\MySQL\Session($db, 'sessions', true, $onSuspect);
new Mysql\Session($db, 'sessions', true, $onSuspect);
}
}
}
@@ -159,15 +167,18 @@ class Controller {
/**
* init new Resource handler
* @param \Base $f3
* @return Resource
*/
protected function initResource(\Base $f3){
$resource = Resource::instance();
$resource->setOption('basePath', $f3->get('BASE'));
$resource->setOption('filePath', [
'style' => $f3->get('BASE') . '/public/css/' . Config::getPathfinderData('version'),
'script' => $f3->get('BASE') . '/public/js/' . Config::getPathfinderData('version'),
'font' => $f3->get('BASE') . '/public/fonts',
'document' => $f3->get('BASE') . '/public/templates',
'image' => $f3->get('BASE') . '/public/img'
'style' => sprintf('/%scss/%s', $f3->get('UI'), Config::getPathfinderData('version')),
'script' => sprintf('/%sjs/%s', $f3->get('UI'), Config::getPathfinderData('version')),
'font' => sprintf('/%sfonts', $f3->get('UI')),
'document' => sprintf('/%stemplates', $f3->get('UI')),
'image' => sprintf('/%simg/%s', $f3->get('UI'), Config::getPathfinderData('version')),
'favicon' => $f3->get('FAVICON')
], true);
$resource->register('style', 'pathfinder');
@@ -185,7 +196,7 @@ class Controller {
$resource->register('url', Config::getPathfinderData('api.ccp_image_server'), 'dns-prefetch');
$resource->register('url', '//i.ytimg.com', 'dns-prefetch'); // YouTube tiny embed domain
$f3->set('tplResource', $resource);
return $resource;
}
/**
@@ -476,9 +487,17 @@ class Controller {
* @param bool $deleteSession
* @param bool $deleteLog
* @param bool $deleteCookie
* @param int $statusCode
* @throws \Exception
*/
protected function logoutCharacter(\Base $f3, bool $all = false, bool $deleteSession = true, bool $deleteLog = true, bool $deleteCookie = false){
protected function logoutCharacter(
\Base $f3,
bool $all = false,
bool $deleteSession = true,
bool $deleteLog = true,
bool $deleteCookie = false,
int $statusCode = self::DEFAULT_STATUS_LOGOUT
){
$sessionCharacterData = (array)$f3->get(Api\User::SESSION_KEY_CHARACTERS);
if($sessionCharacterData){
@@ -507,12 +526,11 @@ class Controller {
}
if($f3->get('AJAX')){
$status = 403;
$f3->status($status);
$f3->status($statusCode);
$return = (object) [];
$return->reroute = rtrim(self::getEnvironmentData('URL'), '/') . $f3->alias('login');
$return->error[] = $this->getErrorObject($status, Config::getMessageFromHTTPStatus($status));
$return->error[] = $this->getErrorObject($statusCode, Config::getHttpStatusByCode($statusCode), 'Access denied: User not found');
echo json_encode($return);
}else{
@@ -560,7 +578,7 @@ class Controller {
'routes' => []
];
$serverStatus = $client->getServerStatus();
$serverStatus = $client->send('getServerStatus');
if( !isset($serverStatus['error']) ){
$statusData = $serverStatus['status'];
// calculate time diff since last server restart
@@ -582,7 +600,7 @@ class Controller {
$return->error[] = (new PathfinderException($serverStatus['error'], 500))->getError();
}
$apiStatus = $client->getStatusForRoutes('latest');
$apiStatus = $client->send('getStatus', 'latest', true);
if( !isset($apiStatus['error']) ){
// find top status
$status = 'OK';
@@ -621,18 +639,18 @@ class Controller {
/**
* @param int $code
* @param string $message
* @param string $status
* @param string $text
* @param null $trace
* @return \stdClass
*/
protected function getErrorObject(int $code, string $message = '', string $status = '', $trace = null): \stdClass{
protected function getErrorObject(int $code, string $status = '', string $text = '', $trace = null) : \stdClass {
$object = (object) [];
$object->type = 'error';
$object->code = $code;
$object->status = empty($status) ? @constant('Base::HTTP_' . $code) : $status;
if(!empty($message)){
$object->message = $message;
if(!empty($text)){
$object->text = $text;
}
if(!empty($trace)){
$object->trace = $trace;
@@ -642,15 +660,15 @@ class Controller {
/**
* @param string $title
* @param string $message
* @param string $text
* @param string $type
* @return \stdClass
*/
protected function getNotificationObject(string $title, $message = '', $type = 'danger') : \stdClass {
protected function getNotificationObject(string $title, $text = '', $type = 'danger') : \stdClass {
$notification = (object) [];
$notification->type = in_array($type, self::NOTIFICATION_TYPES) ? $type : 'danger';
$notification->title = $title;
$notification->message = $message;
$notification->text = $text;
return $notification;
}
@@ -744,7 +762,7 @@ class Controller {
if(count($matches) === 2){
$error->field = $matches[1][1];
$error->message = 'Value "' . $matches[0][1] . '" already exists';
$error->text = 'Value "' . $matches[0][1] . '" already exists';
}
}

View File

@@ -6,12 +6,12 @@
* Time: 15:24
*/
namespace controller;
namespace Exodus4D\Pathfinder\Controller;
use lib\Config;
use lib\logging\MapLog;
use Model\Pathfinder;
use Exodus4D\Pathfinder\Lib\Config;
use Exodus4D\Pathfinder\Lib\Logging\MapLog;
use Exodus4D\Pathfinder\Model\Pathfinder;
class LogController extends \Prefab {

View File

@@ -6,11 +6,11 @@
* Time: 21:18
*/
namespace Controller;
namespace Exodus4D\Pathfinder\Controller;
use lib\Config;
use lib\Resource;
use Exodus4D\Pathfinder\Lib\Config;
use Exodus4D\Pathfinder\Lib\Resource;
class MapController extends AccessController {

View File

@@ -6,17 +6,20 @@
* Time: 10:59
*/
namespace Controller;
namespace Exodus4D\Pathfinder\Controller;
use Controller\Ccp\Universe as UniverseController;
use data\filesystem\Search;
use DB\SQL\Schema;
use DB\SQL\MySQL as MySQL;
use lib\Config;
use lib\Cron;
use lib\Util;
use Model\Pathfinder;
use Model\Universe;
use Exodus4D\Pathfinder\Db\Sql\Mysql;
use Exodus4D\Pathfinder\Lib\Db\Sql;
use Exodus4D\Pathfinder\Lib\Config;
use Exodus4D\Pathfinder\Lib\Cron;
use Exodus4D\Pathfinder\Lib\Util;
use Exodus4D\Pathfinder\Lib\Format\Number;
use Exodus4D\Pathfinder\Model\Pathfinder;
use Exodus4D\Pathfinder\Model\Universe;
use Exodus4D\Pathfinder\Controller\Ccp\Universe as UniverseController;
use Exodus4D\Pathfinder\Data\Filesystem\Search;
class Setup extends Controller {
@@ -145,7 +148,7 @@ class Setup extends Controller {
* @return bool
*/
function beforeroute(\Base $f3, $params): bool {
$this->initResource($f3);
$f3->set('tplResource', $this->initResource($f3));
// page title
$f3->set('tplPageTitle', 'Setup | ' . Config::getPathfinderData('name'));
@@ -172,7 +175,7 @@ class Setup extends Controller {
$f3->set('tplCounter', $this->counter());
$f3->set('tplConvertBytes', function(){
return call_user_func_array([\lib\format\Number::instance(), 'bytesToString'], func_get_args());
return call_user_func_array([Number::instance(), 'bytesToString'], func_get_args());
});
// render view
@@ -275,7 +278,7 @@ class Setup extends Controller {
* @return array
*/
protected function getNavigationConfig() : array {
$config = [
return [
'server' => [
'icon' => 'fa-home'
],
@@ -301,8 +304,6 @@ class Setup extends Controller {
'icon' => 'fa-wrench'
]
];
return $config;
}
/**
@@ -351,7 +352,7 @@ class Setup extends Controller {
* @return array
*/
protected function getServerInformation(\Base $f3) : array {
$serverInfo = [
return [
'time' => [
'label' => 'Time',
'value' => date('Y/m/d H:i:s') . ' - (' . $f3->get('TZ') . ')'
@@ -389,8 +390,6 @@ class Setup extends Controller {
'value' => $f3->get('SERVER.SERVER_PROTOCOL') . ' - ' . $f3->get('SCHEME')
]
];
return $serverInfo;
}
/**
@@ -399,7 +398,7 @@ class Setup extends Controller {
* @return array
*/
protected function getDirectoryConfig(\Base $f3) : array {
$directoryData = [
return [
'TEMP' => [
'label' => 'TEMP',
'value' => $f3->get('TEMP'),
@@ -465,8 +464,6 @@ class Setup extends Controller {
'tooltip' => 'Folder for custom *.ini files. (e.g. when overwriting of default values in app/*.ini)'
]
];
return $directoryData;
}
/**
@@ -639,7 +636,7 @@ class Setup extends Controller {
$maxExecutionTime = (int)ini_get('max_execution_time'); // 0 == infinite
$htmlErrors = (int)ini_get('html_errors');
$phpConfig = [
return [
'exec' => [
'label' => 'exec()',
'required' => $f3->get('REQUIREMENTS.PHP.EXEC'),
@@ -697,8 +694,6 @@ class Setup extends Controller {
'tooltip' => 'PHP Session name.'
]
];
return $phpConfig;
}
/**
@@ -717,14 +712,23 @@ class Setup extends Controller {
// collection of DSN specific $conf array (host, port, db,..)
$dsnData = [];
/**
* @param int $dbNum
* @param string $tag
* @return string
*/
$getDbLabel = function(int $dbNum, string $tag) : string {
return '<i class="fas fa-fw fa-database"></i> db(' . $dbNum . ') : ' . $tag;
};
/**
* get client information for a Redis client
* @param \Redis $client
* @param array $conf
* @param array $conf
* @return array
*/
$getClientInfo = function(\Redis $client, array $conf) : array {
$redisInfo = [
return [
'dsn' => [
'label' => 'DSN',
'value' => $conf['host'] . ':' . $conf['port']
@@ -734,8 +738,6 @@ class Setup extends Controller {
'value' => $client->isConnected()
]
];
return $redisInfo;
};
/**
@@ -746,7 +748,7 @@ class Setup extends Controller {
$getClientStats = function(\Redis $client) use ($f3) : array {
$redisStats = [];
if($client->isConnected()){
if($client->isConnected() && !$client->getLastError()){
$redisServerInfo = (array)$client->info('SERVER');
$redisClientsInfo = (array)$client->info('CLIENTS');
$redisMemoryInfo = (array)$client->info('MEMORY');
@@ -762,20 +764,20 @@ class Setup extends Controller {
],
'maxMemory' => [
'label' => 'maxmemory',
'required' => \lib\format\Number::instance()->bytesToString($f3->get('REQUIREMENTS.REDIS.MAX_MEMORY')),
'version' => \lib\format\Number::instance()->bytesToString($redisMemoryInfo['maxmemory']),
'required' => Number::instance()->bytesToString($f3->get('REQUIREMENTS.REDIS.MAX_MEMORY')),
'version' => Number::instance()->bytesToString($redisMemoryInfo['maxmemory']),
'check' => $redisMemoryInfo['maxmemory'] >= $f3->get('REQUIREMENTS.REDIS.MAX_MEMORY'),
'tooltip' => 'Max memory limit for Redis'
],
'usedMemory' => [
'label' => 'used_memory',
'version' => \lib\format\Number::instance()->bytesToString($redisMemoryInfo['used_memory']),
'version' => Number::instance()->bytesToString($redisMemoryInfo['used_memory']),
'check' => $redisMemoryInfo['used_memory'] < $redisMemoryInfo['maxmemory'],
'tooltip' => 'Current memory used by Redis'
],
'usedMemoryPeak' => [
'label' => 'used_memory_peak',
'version' => \lib\format\Number::instance()->bytesToString($redisMemoryInfo['used_memory_peak']),
'version' => Number::instance()->bytesToString($redisMemoryInfo['used_memory_peak']),
'check' => $redisMemoryInfo['used_memory_peak'] <= $redisMemoryInfo['maxmemory'],
'tooltip' => 'Peak memory used by Redis'
],
@@ -819,14 +821,14 @@ class Setup extends Controller {
* @param string $tag
* @return array
*/
$getDatabaseStatus = function(\Redis $client, string $tag) : array {
$getDatabaseStatus = function(\Redis $client, string $tag) use ($getDbLabel) : array {
$redisDatabases = [];
if($client->isConnected()){
if($client->isConnected() && !$client->getLastError()){
$dbNum = $client->getDbNum();
$dbSize = $client->dbSize();
$redisDatabases = [
'db_' . $dbNum => [
'label' => '<i class="fas fa-fw fa-database"></i> db(' . $dbNum . ') : ' . $tag,
'label' => $getDbLabel($dbNum, $tag),
'version' => $dbSize . ' keys',
'check' => $dbSize > 0,
'tooltip' => 'Keys in db(' . $dbNum . ')',
@@ -854,23 +856,28 @@ class Setup extends Controller {
* build (modify) $redisConfig with DNS $conf data
* @param array $conf
*/
$buildRedisConfig = function(array $conf) use (&$redisConfig, $getClientInfo, $getClientStats, $getDatabaseStatus){
$buildRedisConfig = function(array $conf) use (&$redisConfig, $getDbLabel, $getClientInfo, $getClientStats, $getDatabaseStatus){
if($conf['type'] == 'redis'){
// is Redis -> group all DNS by host:port
$client = new \Redis();
$uid = $conf['host'] . ':' . $conf['port'];
$client = new \Redis();
try{
$client->pconnect($conf['host'], $conf['port'], 0.3);
if(!empty($conf['auth'])){
$client->auth($conf['auth']);
}
if(isset($conf['db'])) {
$client->select($conf['db']);
}
$conf['db'] = $client->getDbNum();
}catch(\RedisException $e){
// connection failed
// connection failed, getLastError() is called further down
}
if(!array_key_exists($uid = $conf['host'] . ':' . $conf['port'], $redisConfig)){
if(!array_key_exists($uid, $redisConfig)){
$redisConfig[$uid] = $getClientInfo($client, $conf);
$redisConfig[$uid]['status'] = $getClientStats($client) + $getDatabaseStatus($client, $conf['tag']);
}elseif(!array_key_exists($uidDb = 'db_' . $conf['db'], $redisConfig[$uid]['status'])){
@@ -879,6 +886,13 @@ class Setup extends Controller {
$redisConfig[$uid]['status'][$uidDb]['label'] .= '; ' . $conf['tag'];
}
if($error = $client->getLastError()){
$redisConfig[$uid]['errors'][] = [
'label' => $getDbLabel((int)$conf['db'], $conf['tag']),
'error' => $error
];
}
$client->close();
}
};
@@ -910,6 +924,7 @@ class Setup extends Controller {
'host' => $parts['host'],
'port' => $parts['port'],
'db' => !empty($params['database']) ? (int)$params['database'] : 0,
'auth' => !empty($params['auth']) ? $params['auth'] : null,
'tag' => 'SESSION'
];
$dsnData[] = $conf;
@@ -937,14 +952,11 @@ class Setup extends Controller {
protected function checkSystemConfig(\Base $f3): array {
$systemConf = [];
if(function_exists('exec')){
$gitOut = $composerOut = $rubyOut = $rubyGemsOut = $compassOut = $nodeOut = $npmOut = [];
$gitStatus = $composerStatus = $rubyStatus = $rubyGemsStatus = $compassStatus = $nodeStatus = $npmStatus = 1;
$gitOut = $composerOut = $nodeOut = $npmOut = [];
$gitStatus = $composerStatus = $nodeStatus = $npmStatus = 1;
exec('git --version', $gitOut, $gitStatus);
exec('composer -V', $composerOut, $composerStatus);
exec('ruby -v', $rubyOut, $rubyStatus);
exec('gem -v', $rubyGemsOut, $rubyGemsStatus);
exec('compass -v', $compassOut, $compassStatus);
exec('node -v', $nodeOut, $nodeStatus);
exec('npm -v', $npmOut, $npmStatus);
@@ -965,24 +977,6 @@ class Setup extends Controller {
'check' => $composerStatus == 0,
'tooltip' => 'Composer # composer -V : ' . $composerOut[0]
],
'Ruby' => [
'label' => 'Ruby',
'version' => $rubyOut[0] ? 'installed' : 'missing',
'check' => $rubyStatus == 0,
'tooltip' => 'Ruby # ruby -v : ' . $rubyOut[0]
],
'rubyGems' => [
'label' => 'Ruby gem',
'version' => $normalizeVersion($rubyGemsOut[0]) ?: 'missing',
'check' => $rubyGemsStatus == 0,
'tooltip' => 'gem # gem -v'
],
'compass' => [
'label' => 'Compass',
'version' => $compassOut[0] ? 'installed' : 'missing',
'check' => $compassStatus == 0,
'tooltip' => 'Compass # compass -v : ' . $compassOut[0]
],
'node' => [
'label' => 'NodeJs',
'required' => number_format((float)$f3->get('REQUIREMENTS.PATH.NODE'), 1, '.', ''),
@@ -1110,7 +1104,7 @@ class Setup extends Controller {
// collection for errors
$dbErrors = [];
/**
* @var $db \lib\db\SQL
* @var $db Sql
*/
$db = $f3->DB->getDB($dbAlias);
@@ -1133,7 +1127,7 @@ class Setup extends Controller {
// get table data from model
foreach($dbData['models'] as $model){
$tableConfig = call_user_func($model . '::resolveConfiguration');
$tableConfig = call_user_func(Config::withNamespace($model) . '::resolveConfiguration');
$requiredTables[$tableConfig['table']] = [
'model' => $model,
'name' => $tableConfig['table'],
@@ -1172,7 +1166,7 @@ class Setup extends Controller {
// Table exists
$tableExists = true;
// get existing table columns and column related constraints (if exists)
$tableModifierTemp = new MySQL\TableModifier($requiredTableName, $schema);
$tableModifierTemp = new Mysql\TableModifier($requiredTableName, $schema);
$currentColumns = $tableModifierTemp->getCols(true);
// get row count
$tableRows = $db->getRowCount($requiredTableName);
@@ -1220,16 +1214,16 @@ class Setup extends Controller {
// column exists
// get tableModifier -> possible column update
$tableModifier = new MySQL\TableModifier($requiredTableName, $schema);
$tableModifier = new Mysql\TableModifier($requiredTableName, $schema);
// get new column and copy Schema from existing column
$col = new MySQL\Column($columnName, $tableModifier);
$col = new Mysql\Column($columnName, $tableModifier);
$col->copyfrom($currentColumns[$columnName]);
$currentColType = $currentColumns[$columnName]['type'];
$currentNullable = $currentColumns[$columnName]['nullable'];
$hasNullable = $currentNullable ? '1' : '0';
$currentColIndexData = call_user_func($data['model'] . '::indexExists', [$columnName]);
$currentColIndexData = call_user_func(Config::withNamespace($data['model']) . '::indexExists', [$columnName]);
$currentColIndex = is_array($currentColIndexData);
$hasIndex = ($currentColIndex) ? '1' : '0';
$hasUnique = ($currentColIndexData['unique']) ? '1' : '0';
@@ -1441,10 +1435,10 @@ class Setup extends Controller {
/**
* check MySQL params
* @param \Base $f3
* @param \lib\db\SQL $db
* @param Sql $db
* @return array
*/
protected function checkDBConfig(\Base $f3, \lib\db\SQL $db) : array {
protected function checkDBConfig(\Base $f3, Sql $db) : array {
$checkAll = true;
// some db like "Maria DB" have some strange version strings....
$dbVersionString = $db->version();
@@ -1555,7 +1549,7 @@ class Setup extends Controller {
// setup tables
foreach($this->databases[$dbAlias]['models'] as $modelClass){
$checkTables[] = call_user_func($modelClass . '::setup', $db);
$checkTables[] = call_user_func(Config::withNamespace($modelClass) . '::setup', $db);
}
}
return $checkTables;
@@ -1624,7 +1618,7 @@ class Setup extends Controller {
$setStats((array)$payload['stats']);
});
$socketInformation = [
return [
'tcpSocket' => [
'label' => 'TCP-Socket (intern)',
'icon' => 'fa-exchange-alt',
@@ -1669,8 +1663,6 @@ class Setup extends Controller {
]
]
];
return $socketInformation;
}
/**
@@ -1710,13 +1702,11 @@ class Setup extends Controller {
]
];
$config = [
return [
'checkCronConfig' => $cronConf,
'settings' => $f3->constants($cron, 'DEFAULT_'),
'jobs' => $cron->getJobsConfig()
];
return $config;
}
/**
@@ -1950,7 +1940,7 @@ class Setup extends Controller {
}
$bytesAll += $bytes;
$dirAll[$key]['size'] = ($maxHit ? '>' : '') . \lib\format\Number::instance()->bytesToString($bytes);
$dirAll[$key]['size'] = ($maxHit ? '>' : '') . Number::instance()->bytesToString($bytes);
$dirAll[$key]['task'] = [
[
'action' => http_build_query([
@@ -1965,7 +1955,7 @@ class Setup extends Controller {
}
return [
'sizeAll' => ($maxHitAll ? '>' : '') . \lib\format\Number::instance()->bytesToString($bytesAll),
'sizeAll' => ($maxHitAll ? '>' : '') . Number::instance()->bytesToString($bytesAll),
'dirAll' => $dirAll
];
}

View File

@@ -6,9 +6,10 @@
* Time: 12:13
*/
namespace cron;
namespace Exodus4D\Pathfinder\Cron;
use Model\Pathfinder;
use Exodus4D\Pathfinder\Lib\Format\Number;
use Exodus4D\Pathfinder\Model\Pathfinder;
abstract class AbstractCron {
@@ -90,7 +91,7 @@ abstract class AbstractCron {
protected function logStart(string $job, bool $logging = true){
$this->setMaxExecutionTime();
$cron = \lib\Cron::instance();
$cron = \Exodus4D\Pathfinder\Lib\Cron::instance();
if(isset($cron->jobs[$job])){
// set "start" date for current cronjob
$jobConf = $cron->getJobDataFromConf($cron->jobs[$job]);
@@ -201,7 +202,7 @@ abstract class AbstractCron {
$text = sprintf(self::LOG_TEXT_BASE,
$state['count'], $state['importCount'], $percent, $state['total'],
\lib\format\Number::instance()->bytesToString($memPeak), $duration
Number::instance()->bytesToString($memPeak), $duration
);
$text .= $logText ? $logText: '';

View File

@@ -6,9 +6,9 @@
* Time: 14:59
*/
namespace cron;
namespace Exodus4D\Pathfinder\Cron;
use data\filesystem\Search;
use Exodus4D\Pathfinder\Data\Filesystem\Search;
class Cache extends AbstractCron {

View File

@@ -6,8 +6,10 @@
* Time: 21:31
*/
namespace Cron;
use lib\db\SQL;
namespace Exodus4D\Pathfinder\Cron;
use Exodus4D\Pathfinder\Lib\Db\Sql;
class CcpSystemsUpdate extends AbstractCron {
@@ -29,11 +31,11 @@ class CcpSystemsUpdate extends AbstractCron {
/**
* checks if a table exists in DB or not
* @param SQL$db
* @param Sql $db
* @param string $table
* @return bool
*/
protected function tableExists (SQL $db, string $table) : bool {
protected function tableExists (Sql $db, string $table) : bool {
return !empty($db->exec('SHOW TABLES LIKE :table', [':table' => $table]));
}
@@ -111,19 +113,19 @@ class CcpSystemsUpdate extends AbstractCron {
// switch DB for data import..
/**
* @var $pfDB SQL
* @var $pfDB Sql
*/
$pfDB = $f3->DB->getDB('PF');
// get current jump data --------------------------------------------------------------------------------------
$time_start = microtime(true);
$jumpData = $f3->ccpClient()->getUniverseJumps();
$jumpData = $f3->ccpClient()->send('getUniverseJumps');
$time_end = microtime(true);
$execTimeGetJumpData = $time_end - $time_start;
// get current kill data --------------------------------------------------------------------------------------
$time_start = microtime(true);
$killData = $f3->ccpClient()->getUniverseKills();
$killData = $f3->ccpClient()->send('getUniverseKills');
$time_end = microtime(true);
$execTimeGetKillData = $time_end - $time_start;

View File

@@ -6,10 +6,10 @@
* Time: 19:35
*/
namespace Cron;
namespace Exodus4D\Pathfinder\Cron;
use Model\Pathfinder;
use Exodus4D\Pathfinder\Model\Pathfinder;
class CharacterUpdate extends AbstractCron {

View File

@@ -6,11 +6,11 @@
* Time: 15:48
*/
namespace Cron;
namespace Exodus4D\Pathfinder\Cron;
use data\mapper\SortingIterator;
use data\file\FileHandler;
use data\filesystem\Search;
use Exodus4D\Pathfinder\Data\Mapper\SortingIterator;
use Exodus4D\Pathfinder\Data\File\FileHandler;
use Exodus4D\Pathfinder\Data\Filesystem\Search;
class MapHistory extends AbstractCron {

View File

@@ -6,11 +6,11 @@
* Time: 17:54
*/
namespace cron;
namespace Exodus4D\Pathfinder\Cron;
use lib\Config;
use Model\Pathfinder;
use Exodus4D\Pathfinder\Lib\Config;
use Exodus4D\Pathfinder\Model\Pathfinder;
class MapUpdate extends AbstractCron {

View File

@@ -6,7 +6,7 @@
* Time: 21:31
*/
namespace cron;
namespace Exodus4D\Pathfinder\Cron;
class StatisticsUpdate extends AbstractCron {

View File

@@ -6,9 +6,10 @@
* Time: 03:46
*/
namespace Cron;
namespace Exodus4D\Pathfinder\Cron;
use Model;
use Exodus4D\Pathfinder\Model;
class Universe extends AbstractCron {
@@ -185,7 +186,7 @@ class Universe extends AbstractCron {
switch($type){
case 'system':
// load systems + dependencies (planets, star, types,...)
$ids = $f3->ccpClient()->getUniverseSystems();
$ids = $f3->ccpClient()->send('getUniverseSystems');
$modelClass = 'SystemModel';
$setupModel = function(Model\Universe\SystemModel &$model, int $id){
$model->loadById($id);
@@ -194,7 +195,7 @@ class Universe extends AbstractCron {
break;
case 'stargate':
// load all stargates. Systems must be present first!
$ids = $f3->ccpClient()->getUniverseSystems();
$ids = $f3->ccpClient()->send('getUniverseSystems');
$modelClass = 'SystemModel';
$setupModel = function(Model\Universe\SystemModel &$model, int $id){
$model->loadById($id);
@@ -202,7 +203,7 @@ class Universe extends AbstractCron {
};
break;
case 'station':
$ids = $f3->ccpClient()->getUniverseSystems();
$ids = $f3->ccpClient()->send('getUniverseSystems');
$modelClass = 'SystemModel';
$setupModel = function(Model\Universe\SystemModel &$model, int $id){
if($model->getById($id)){
@@ -215,7 +216,7 @@ class Universe extends AbstractCron {
break;
case 'sovereignty':
// load sovereignty map data. Systems must be present first!
$sovData = $f3->ccpClient()->getSovereigntyMap();
$sovData = $f3->ccpClient()->send('getSovereigntyMap');
$ids = !empty($sovData = $sovData['map']) ? array_keys($sovData): [];
$modelClass = 'SystemModel';
$setupModel = function(Model\Universe\SystemModel &$model, int $id) use ($sovData) {
@@ -228,7 +229,7 @@ class Universe extends AbstractCron {
};
break;
case 'faction_war_systems':
$fwSystems = $f3->ccpClient()->getFactionWarSystems();
$fwSystems = $f3->ccpClient()->send('getFactionWarSystems');
$ids = !empty($fwSystems = $fwSystems['systems']) ? array_keys($fwSystems): [];
$modelClass = 'SystemModel';
$setupModel = function(Model\Universe\SystemModel &$model, int $id) use ($fwSystems) {
@@ -242,7 +243,7 @@ class Universe extends AbstractCron {
break;
case 'index_system':
// setup system index, Systems must be present first!
$ids = $f3->ccpClient()->getUniverseSystems();
$ids = $f3->ccpClient()->send('getUniverseSystems');
$modelClass = 'SystemModel';
$setupModel = function(Model\Universe\SystemModel &$model, int $id){
$model->getById($id); // no loadById() here! would take "forever" when system not exists and must be build up first...
@@ -309,8 +310,8 @@ class Universe extends AbstractCron {
*/
$system = Model\Universe\AbstractUniverseModel::getNew('SystemModel');
$sovData = $f3->ccpClient()->getSovereigntyMap();
$fwSystems = $f3->ccpClient()->getFactionWarSystems();
$sovData = $f3->ccpClient()->send('getSovereigntyMap');
$fwSystems = $f3->ccpClient()->send('getFactionWarSystems');
$fwSystems = $fwSystems['systems'];
$ids = !empty($sovData = $sovData['map']) ? array_keys($sovData): [];
sort($ids, SORT_NUMERIC);

View File

@@ -6,7 +6,7 @@
* Time: 18:47
*/
namespace data\file;
namespace Exodus4D\Pathfinder\Data\File;
class FileHandler extends \Prefab {

View File

@@ -6,7 +6,7 @@
* Time: 18:42
*/
namespace data\file;
namespace Exodus4D\Pathfinder\Data\File;
class ReverseSplFileObject extends \SplFileObject{

View File

@@ -6,7 +6,7 @@
* Time: 16:58
*/
namespace data\filesystem;
namespace Exodus4D\Pathfinder\Data\Filesystem;
class Search {

View File

@@ -6,9 +6,9 @@
* Time: 04:06
*/
namespace data\mapper;
namespace Exodus4D\Pathfinder\Data\Mapper;
use lib\Util;
use Exodus4D\Pathfinder\Lib\Util;
class AbstractIterator extends \RecursiveArrayIterator {
@@ -26,7 +26,10 @@ class AbstractIterator extends \RecursiveArrayIterator {
*/
protected static $removeUnmapped = true;
/**
* AbstractIterator constructor.
* @param $data
*/
function __construct($data){
parent::__construct($data, \RecursiveIteratorIterator::SELF_FIRST);
}
@@ -52,10 +55,10 @@ class AbstractIterator extends \RecursiveArrayIterator {
/**
* recursive iterator function called on every node
* @param $iterator
* @return mixed
* @param AbstractIterator $iterator
* @return AbstractIterator
*/
static function recursiveIterator($iterator){
static function recursiveIterator(AbstractIterator $iterator){
$keyWhitelist = array_keys(static::$map);

View File

@@ -6,7 +6,7 @@
* Time: 00:55
*/
namespace data\mapper;
namespace Exodus4D\Pathfinder\Data\Mapper;
class SortingIterator extends \ArrayIterator {

View File

@@ -6,12 +6,19 @@
* Time: 15:40
*/
namespace DB\SQL\MySQL;
namespace Exodus4D\Pathfinder\Db\Sql\Mysql;
class Session extends \DB\SQL\Session {
/**
* Session constructor.
* @param \DB\SQL $db
* @param string $table
* @param bool $force
* @param callback $onsuspect
* @param string $key
*/
function __construct(\DB\SQL $db, string $table = 'sessions', bool $force = true, $onsuspect = null, $key = null){
if($force){
// create sessions table

View File

@@ -12,7 +12,9 @@
* - FOREIGN KEY CONSTRAINTS (single column key)
*/
namespace DB\SQL\MySQL;
namespace Exodus4D\Pathfinder\Db\Sql\Mysql;
use DB\SQL;
class TableModifier extends SQL\TableModifier {
@@ -23,7 +25,7 @@ class TableModifier extends SQL\TableModifier {
/**
* return table foreign key constraints as assoc array
* -> if §constraint is passed, constraints are limited to that column
* @param null| SQL\MySQL\Constraint $constraint
* @param null| Constraint $constraint
* @return Constraint[]
*/
public function listConstraint($constraint = null){
@@ -65,7 +67,7 @@ class TableModifier extends SQL\TableModifier {
/**
* checks whether a constraint name exists or not
* -> does not check constraint params
* @param SQL\MySQL\Constraint $constraint
* @param Constraint $constraint
* @return bool
*/
public function constraintExists($constraint){
@@ -75,7 +77,7 @@ class TableModifier extends SQL\TableModifier {
/**
* drop foreign key constraint
* @param SQL\MySQL\Constraint $constraint
* @param Constraint $constraint
*/
public function dropConstraint($constraint){
if($constraint->isValid()){
@@ -88,7 +90,7 @@ class TableModifier extends SQL\TableModifier {
/**
* Add/Update foreign key constraint
* @param SQL\MySQL\Constraint $constraint
* @param Constraint $constraint
*/
public function addConstraint($constraint){
@@ -131,7 +133,6 @@ class Column extends SQL\Column {
}
/**
* @see \DB\SQL\MySQL\TableModifier->constraintExists();
* @param Constraint $constraint
* @return mixed
*/
@@ -147,7 +148,7 @@ class Column extends SQL\Column {
* $constraintData['on-update'] => ON UPDATE action (optional) default: see \DB\SQL\MySQL\Constraint const
*
* @param array $constraintData
* @return SQL\MySQL\Constraint
* @return Constraint
*/
public function newConstraint($constraintData){

View File

@@ -6,11 +6,14 @@
* Time: 18:53
*/
namespace Exception;
namespace Exodus4D\Pathfinder\Exception;
class ConfigException extends PathfinderException {
/**
* @var array
*/
protected $codes = [
1000 => 500
];

View File

@@ -6,14 +6,22 @@
* Time: 20:31
*/
namespace Exception;
namespace Exodus4D\Pathfinder\Exception;
class DatabaseException extends PathfinderException {
/**
* @var array
*/
protected $codes = [
1500 => 500
];
/**
* DatabaseException constructor.
* @param string $message
*/
public function __construct(string $message){
parent::__construct($message, 1500);
}

View File

@@ -6,10 +6,14 @@
* Time: 18:12
*/
namespace Exception;
namespace Exodus4D\Pathfinder\Exception;
class DateException extends PathfinderException {
/**
* @var array
*/
protected $codes = [
3000 => 500 // invalid DateRange
];

View File

@@ -6,9 +6,10 @@
* Time: 00:41
*/
namespace Exception;
namespace Exodus4D\Pathfinder\Exception;
use lib\Config;
use Exodus4D\Pathfinder\Lib\Config;
class PathfinderException extends \Exception {
@@ -26,6 +27,11 @@ class PathfinderException extends \Exception {
0 => self::DEFAULT_RESPONSECODE
];
/**
* PathfinderException constructor.
* @param string $message
* @param int $code
*/
public function __construct(string $message, int $code = 0){
if( !array_key_exists($code, $this->codes) ){
// exception code not specified by child class
@@ -43,7 +49,7 @@ class PathfinderException extends \Exception {
$error->type = 'error';
$error->code = $this->getResponseCode();
$error->status = Config::getHttpStatusByCode($this->getResponseCode());
$error->message = $this->getMessage();
$error->text = $this->getMessage();
if(\Base::instance()->get('DEBUG') >= 1){
$error->trace = preg_split('/\R/', $this->getTraceAsString()); // no $this->>getTrace() here -> to much data
}

View File

@@ -6,11 +6,14 @@
* Time: 21:21
*/
namespace Exception;
namespace Exodus4D\Pathfinder\Exception;
class RegistrationException extends PathfinderException{
/**
* @var array
*/
protected $codes = [
2000 => 403
];
@@ -21,6 +24,11 @@ class RegistrationException extends PathfinderException{
*/
private $field;
/**
* RegistrationException constructor.
* @param string $message
* @param string $field
*/
public function __construct(string $message, string $field = ''){
parent::__construct($message, 2000);
$this->field = $field;

View File

@@ -6,11 +6,14 @@
* Time: 00:12
*/
namespace Exception;
namespace Exodus4D\Pathfinder\Exception;
class ValidationException extends PathfinderException {
/**
* @var array
*/
protected $codes = [
2000 => 422
];
@@ -21,6 +24,11 @@ class ValidationException extends PathfinderException {
*/
private $field;
/**
* ValidationException constructor.
* @param string $message
* @param string $field
*/
public function __construct(string $message, string $field = ''){
parent::__construct($message, 2000);
$this->field = $field;

View File

@@ -6,7 +6,7 @@
* Time: 17:41
*/
namespace lib\api;
namespace Exodus4D\Pathfinder\Lib\Api;
use Cache\Adapter\Filesystem\FilesystemCachePool;
use Cache\Adapter\PHPArray\ArrayCachePool;
@@ -14,10 +14,10 @@ use Cache\Adapter\Redis\RedisCachePool;
use Cache\Namespaced\NamespacedCachePool;
use League\Flysystem\Adapter\Local;
use League\Flysystem\Filesystem;
use lib\Config;
use lib\Util;
use lib\logging;
use controller\LogController;
use Exodus4D\Pathfinder\Lib\Config;
use Exodus4D\Pathfinder\Lib\Util;
use Exodus4D\Pathfinder\Lib\Logging;
use Exodus4D\Pathfinder\Controller\LogController;
use Exodus4D\ESI\Client\ApiInterface;
use Psr\Cache\CacheItemPoolInterface;
use Psr\Http\Message\RequestInterface;
@@ -89,8 +89,8 @@ abstract class AbstractClient extends \Prefab {
* @return \Closure
*/
protected function newLog() : \Closure {
return function(string $action, string $level = 'warning') : logging\LogInterface {
$log = new logging\ApiLog($action, $level);
return function(string $action, string $level = 'warning') : Logging\LogInterface {
$log = new Logging\ApiLog($action, $level);
$log->addHandler('stream', 'json', $this->getStreamConfig($action));
return $log;
};
@@ -134,6 +134,9 @@ abstract class AbstractClient extends \Prefab {
Config::REDIS_OPT_READ_TIMEOUT
)
){
if(!empty($poolConfig['auth'])){
$client->auth($poolConfig['auth']);
}
if(isset($poolConfig['tag'])){
$name = 'pathfinder|php|tag:' . strtolower($poolConfig['tag']) . '|pid:' . getmypid();
@@ -298,8 +301,8 @@ abstract class AbstractClient extends \Prefab {
public function __call(string $name, array $arguments = []){
$return = [];
if(is_object($this->client)){
if( method_exists($this->client, $name) ){
$return = call_user_func_array([$this->client, $name], $arguments);
if(method_exists($this->client, $name)){
$return = call_user_func_array([$this->client, $name], $arguments);
}else{
$errorMsg = $this->getMissingMethodError(get_class($this->client), $name);
$this->getLogger('ERROR')->write($errorMsg);
@@ -336,18 +339,20 @@ abstract class AbstractClient extends \Prefab {
$client->setNewLog($this->newLog());
$client->setIsLoggable($this->isLoggable($f3));
$client->setLogStats(true); // add cURL stats (e.g. transferTime) to logged requests
$client->setLogCache(true); // add cache info (e.g. from cached) to logged requests
//$client->setLogAllStatus(true); // log all requests regardless of response HTTP status code
$client->setLogFile('esi_requests');//
$client->setLogStats(true); // add cURL stats (e.g. transferTime) to loggable requests
$client->setLogCache(true); // add cache info (e.g. from cached) to loggable requests
$client->setLogAllStatus(false); // log all requests regardless of response HTTP status code
$client->setLogRequestHeaders(false); // add request HTTP headers to loggable requests
$client->setLogResponseHeaders(false); // add response HTTP headers to loggable requests
$client->setLogFile('esi_requests');
$client->setRetryLogFile('esi_retry_requests');
$client->setCacheDebug(true);
$client->setCachePool($this->getCachePool($f3));
// use local proxy server for debugging requests
//$client->setProxy('127.0.0.1:8888');
//$client->setProxy('127.0.0.1:8888'); // use local proxy server for debugging requests
// disable SSL certificate verification -> allow proxy to decode(view) request
//$client->setVerify(false);

View File

@@ -6,20 +6,18 @@
* Time: 17:43
*/
namespace lib\api;
namespace Exodus4D\Pathfinder\Lib\Api;
use lib\Config;
use Exodus4D\ESI\Client\ESI as Client;
use Exodus4D\Pathfinder\Lib\Config;
use Exodus4D\ESI\Client\ApiInterface;
use Exodus4D\ESI\Client\EsiInterface;
use Exodus4D\ESI\Client\Ccp\Esi\Esi as Client;
/**
* Class CcpClient
* @package lib\api
*
* @method EsiInterface getServerStatus()
* @method EsiInterface getStatusForRoutes(string $version)
* @method ApiInterface send(string $requestHandler, ...$handlerParams)
* @method ApiInterface sendBatch(array $configs)
*/
class CcpClient extends AbstractClient {

View File

@@ -0,0 +1,38 @@
<?php
namespace Exodus4D\Pathfinder\Lib\Api;
use Exodus4D\Pathfinder\Lib\Config;
use Exodus4D\ESI\Client\ApiInterface;
use Exodus4D\ESI\Client\EveScout\EveScout as Client;
/**
* Class EveScoutClient
* @package lib\api
*
* @method ApiInterface send(string $requestHandler, ...$handlerParams)
* @method ApiInterface sendBatch(array $configs)
*/
class EveScoutClient extends AbstractClient {
/**
* @var string
*/
const CLIENT_NAME = 'eveScoutClient';
/**
* @param \Base $f3
* @return ApiInterface|null
*/
protected function getClient(\Base $f3) : ?ApiInterface {
$client = null;
if(class_exists(Client::class)){
$client = new Client(Config::getPathfinderData('api.eve_scout'));
}else{
$this->getLogger()->write($this->getMissingClassError(Client::class));
}
return $client;
}
}

View File

@@ -6,12 +6,19 @@
* Time: 22:23
*/
namespace lib\api;
namespace Exodus4D\Pathfinder\Lib\Api;
use lib\Config;
use Exodus4D\ESI\Client\Github as Client;
use Exodus4D\Pathfinder\Lib\Config;
use Exodus4D\ESI\Client\ApiInterface;
use Exodus4D\ESI\Client\GitHub\GitHub as Client;
/**
* Class GitHubClient
* @package lib\api
*
* @method ApiInterface send(string $requestHandler, ...$handlerParams)
* @method ApiInterface sendBatch(array $configs)
*/
class GitHubClient extends AbstractClient {
/**

View File

@@ -6,12 +6,16 @@
* Time: 17:39
*/
namespace lib\api;
namespace Exodus4D\Pathfinder\Lib\Api;
use lib\Config;
use Exodus4D\ESI\Client\SSO as Client;
use Exodus4D\Pathfinder\Lib\Config;
use Exodus4D\ESI\Client\ApiInterface;
use Exodus4D\ESI\Client\Ccp\Sso\Sso as Client;
/**
* Class SsoClient
* @package lib\api
*/
class SsoClient extends AbstractClient {
/**

View File

@@ -6,16 +6,16 @@
* Time: 16:05
*/
namespace lib;
namespace Exodus4D\Pathfinder\Lib;
use lib\db\Pool;
use lib\api\CcpClient;
use lib\api\GitHubClient;
use lib\api\SsoClient;
use lib\socket\AbstractSocket;
use lib\socket\SocketInterface;
use lib\socket\TcpSocket;
use Exodus4D\Pathfinder\Lib\Db\Pool;
use Exodus4D\Pathfinder\Lib\Api\CcpClient;
use Exodus4D\Pathfinder\Lib\Api\GitHubClient;
use Exodus4D\Pathfinder\Lib\Api\SsoClient;
use Exodus4D\Pathfinder\Lib\Api\EveScoutClient;
use Exodus4D\Pathfinder\Lib\Socket\AbstractSocket;
use Exodus4D\Pathfinder\Lib\Socket\SocketInterface;
use Exodus4D\Pathfinder\Lib\Socket\TcpSocket;
class Config extends \Prefab {
@@ -39,6 +39,11 @@ class Config extends \Prefab {
*/
const HIVE_KEY_ENVIRONMENT = 'ENVIRONMENT';
/**
* Hive key for custom plugins (js map modules)
*/
const HIVE_KEY_PLUGIN = 'PLUGIN';
/**
* Hive key for Socket validation check
*/
@@ -127,7 +132,7 @@ class Config extends \Prefab {
* custom HTTP status codes
*/
const
HTTP_422='Unprocessable Entity';
HTTP_422 = 'Unprocessable Entity';
/**
* all environment data
@@ -177,6 +182,7 @@ class Config extends \Prefab {
$f3->set(SsoClient::CLIENT_NAME, SsoClient::instance());
$f3->set(CcpClient::CLIENT_NAME, CcpClient::instance());
$f3->set(GitHubClient::CLIENT_NAME, GitHubClient::instance());
$f3->set(EveScoutClient::CLIENT_NAME, EveScoutClient::instance());
// Socket connectors ------------------------------------------------------------------------------------------
$f3->set(TcpSocket::SOCKET_NAME, function(array $options = ['timeout' => 1]) : SocketInterface {
@@ -373,7 +379,7 @@ class Config extends \Prefab {
* get SMTP config values
* @return \stdClass
*/
static function getSMTPConfig(): \stdClass{
static function getSMTPConfig() : \stdClass{
$config = new \stdClass();
$config->host = self::getEnvironmentData('SMTP_HOST');
$config->port = self::getEnvironmentData('SMTP_PORT');
@@ -391,9 +397,9 @@ class Config extends \Prefab {
* @param \stdClass $config
* @return bool
*/
static function isValidSMTPConfig(\stdClass $config): bool {
static function isValidSMTPConfig(\stdClass $config) : bool {
// validate email from either an configured array or plain string
$validateMailConfig = function($mailConf = null): bool {
$validateMailConfig = function($mailConf = null) : bool {
$email = null;
if(is_array($mailConf)){
reset($mailConf);
@@ -436,19 +442,25 @@ class Config extends \Prefab {
}
/**
* get custom $message for a a HTTP $status
* -> use this in addition to the very general Base::HTTP_XXX labels
* @param int $status
* @return string
* get Plugin config from `plugin.ini`
* @param string|null $key
* @param bool $checkEnabled
* @return array|null
*/
static function getMessageFromHTTPStatus(int $status): string {
switch($status){
case 403:
$message = 'Access denied: User not found'; break;
default:
$message = '';
static function getPluginConfig(?string $key, bool $checkEnabled = true) : ?array {
$isEnabled = $checkEnabled ?
filter_var(\Base::instance()->get(
self::HIVE_KEY_PLUGIN . '.' . strtoupper($key) . '_ENABLED'),
FILTER_VALIDATE_BOOLEAN
) :
true;
$data = null;
if($isEnabled){
$hiveKey = self::HIVE_KEY_PLUGIN . '.' . strtoupper($key);
$data = (array)\Base::instance()->get($hiveKey);
}
return $message;
return $data;
}
/**
@@ -541,7 +553,7 @@ class Config extends \Prefab {
}
/**
* get HTTP status message by HTTP return code
* get HTTP status by HTTP return code
* -> either from F3 or from self::Config constants
* @param int $code
* @return string
@@ -568,7 +580,7 @@ class Config extends \Prefab {
if($matches = (bool)preg_match('/^(\w+)\h*=\h*(.+)/', strtolower(trim($dsn)), $parts)){
$conf['type'] = $parts[1];
if($conf['type'] == 'redis'){
list($conf['host'], $conf['port'], $conf['db']) = explode(':', $parts[2]) + [1 => 6379, 2 => null];
[$conf['host'], $conf['port'], $conf['db'], $conf['auth']] = explode(':', $parts[2]) + [1 => 6379, 2 => null, 3 => null];
}elseif($conf['type'] == 'folder'){
$conf['folder'] = $parts[2];
}
@@ -640,6 +652,11 @@ class Config extends \Prefab {
return $format;
}
/**
* @param $fromExists
* @param int $ttlMax
* @return int
*/
static function ttlLeft($fromExists, int $ttlMax) : int {
$ttlMax = max($ttlMax, 0);
if($fromExists){
@@ -654,4 +671,16 @@ class Config extends \Prefab {
return $ttlMax;
}
}
/**
* @param string|null $class
* @return string
*/
static function withNamespace(?string $class) : string {
$path = [\Base::instance()->get('NAMESPACE')];
if($class){
$path[] = $class;
}
return implode('\\', $path);
}
}

View File

@@ -1,9 +1,9 @@
<?php
namespace lib;
namespace Exodus4D\Pathfinder\Lib;
use Model\Pathfinder;
use Exodus4D\Pathfinder\Model\Pathfinder;
/**
* Class Cron
@@ -104,13 +104,19 @@ class Cron extends \Cron {
* @return mixed|void
*/
public function registerJob(string $name, array $jobConf){
if($job = $this->getJob($name)){
if($job->dry()){
$job->name = $name;
// method is called from /setup page -> DB might not be created at this point!
// -> check if DB exists here. Otherwise Cortex()->__construct()
\Base::instance()->DB->setSilent(true);
if(\Base::instance()->DB->getDB(Pathfinder\AbstractPathfinderModel::DB_ALIAS)){
if($job = $this->getJob($name)){
if($job->dry()){
$job->name = $name;
}
$job->setData($jobConf);
return $job->save();
}
$job->setData($jobConf);
return $job->save();
}
\Base::instance()->DB->setSilent(false);
}
/**

View File

@@ -6,9 +6,9 @@
* Time: 18:06
*/
namespace lib;
namespace Exodus4D\Pathfinder\Lib;
use Exception\DateException;
use Exodus4D\Pathfinder\Exception\DateException;
class DateRange {

View File

@@ -1,12 +1,12 @@
<?php
namespace lib\db;
namespace Exodus4D\Pathfinder\Lib\Db;
use DB\SQL\Schema;
use controller\LogController;
use Exception\ConfigException;
use Exodus4D\Pathfinder\Controller\LogController;
use Exodus4D\Pathfinder\Exception\ConfigException;
class Pool extends \Prefab {
@@ -22,7 +22,7 @@ class Pool extends \Prefab {
const ERROR_SCHEME = 'DB Scheme "%s" is not supported for DB alias "%s"';
/**
* @var SQL[]
* @var Sql[]
*/
private $connectionStore = [];
@@ -83,9 +83,9 @@ class Pool extends \Prefab {
* connect to the DB server itself -> NO database is used
* -> can be used to check if a certain DB exists without connecting to it directly
* @param string $alias
* @return SQL|null
* @return Sql|null
*/
public function connectToServer(string $alias) : ?SQL {
public function connectToServer(string $alias) : ?Sql {
$config = ($this->getConfig)($alias);
$config['NAME'] = '';
return $this->newDB($config);
@@ -95,9 +95,9 @@ class Pool extends \Prefab {
* tries to create a database if not exists
* -> DB user needs rights to create a DB
* @param string $alias
* @return SQL|null
* @return Sql|null
*/
public function createDB(string $alias) : ?SQL {
public function createDB(string $alias) : ?Sql {
$db = null;
$config = ($this->getConfig)($alias);
// remove database from $dsn (we want to crate it)
@@ -135,9 +135,9 @@ class Pool extends \Prefab {
/**
* get active connection from store or init new connection
* @param string $alias
* @return SQL|null
* @return Sql|null
*/
public function getDB(string $alias) : ?SQL {
public function getDB(string $alias) : ?Sql {
if(!isset($this->connectionStore[$alias])){
$db = $this->newDB(($this->getConfig)($alias));
if(!is_null($db)){
@@ -175,14 +175,14 @@ class Pool extends \Prefab {
/**
* @param array $config
* @return SQL|null
* @return Sql|null
*/
protected function newDB(array $config) : ?SQL {
protected function newDB(array $config) : ?Sql {
$db = null;
if($config['SCHEME'] == 'mysql'){
try{
$db = new SQL($this->buildDnsFromConfig($config), $config['USER'], $config['PASS'], $config['OPTIONS']);
$db = new Sql($this->buildDnsFromConfig($config), $config['USER'], $config['PASS'], $config['OPTIONS']);
}catch(\PDOException $e){
$this->pushError($config['ALIAS'], $e);

View File

@@ -1,12 +1,12 @@
<?php
namespace lib\db;
namespace Exodus4D\Pathfinder\Lib\Db;
use DB\SQL\Schema;
class SQL extends \DB\SQL {
class Sql extends \DB\SQL {
/**
* SQL constructor.

View File

@@ -1,10 +1,10 @@
<?php
namespace lib\format;
namespace Exodus4D\Pathfinder\Lib\Format;
use lib\Config;
use Exodus4D\Pathfinder\Lib\Config;
class Image extends \Prefab {

View File

@@ -1,7 +1,7 @@
<?php
namespace lib\format;
namespace Exodus4D\Pathfinder\Lib\Format;
class Number extends \Prefab {

View File

@@ -6,7 +6,7 @@
* Time: 22:13
*/
namespace lib\logging;
namespace Exodus4D\Pathfinder\Lib\Logging;
abstract class AbstractChannelLog extends AbstractLog {

View File

@@ -6,10 +6,10 @@
* Time: 19:05
*/
namespace lib\logging;
namespace Exodus4D\Pathfinder\Lib\Logging;
use lib\Config;
use Model\Pathfinder\CharacterModel;
use Exodus4D\Pathfinder\Lib\Config;
use Exodus4D\Pathfinder\Model\Pathfinder\CharacterModel;
abstract class AbstractCharacterLog extends AbstractChannelLog {

View File

@@ -6,19 +6,44 @@
* Time: 22:13
*/
namespace lib\logging;
namespace Exodus4D\Pathfinder\Lib\Logging;
use lib\Monolog;
use Exodus4D\Pathfinder\Lib\Monolog;
use Monolog\Logger;
abstract class AbstractLog implements LogInterface {
/**
* error message invalid log level
*/
const ERROR_LEVEL = 'Invalid log level "%s"';
/**
* error message invalid log tag
*/
const ERROR_TAG = 'Invalid log tag "%s"';
/**
* error message unknown Handler key
*/
const ERROR_HANDLER_KEY = 'Handler key "%s" not found in handlerConfig (%s)';
/**
* error message undefined Handler params
*/
const ERROR_HANDLER_PARAMS = 'No handler parameters found for handler key "%s"';
/**
* error message unknown Processor key
*/
const ERROR_PROCESSOR_KEY = 'Processor key "%s" not found in processorConfig (%s)';
/**
* error message undefined Processor params
*/
const ERROR_PROCESSOR_PARAMS = 'No processor parameters found for processor key "%s"';
/**
* PSR-3 log levels
*/
@@ -55,6 +80,15 @@ abstract class AbstractLog implements LogInterface {
*/
protected $handlerParamsConfig = [];
/**
* some processor need individual configuration parameters
* -> see $processorConfig end getProcessorParams()
* @var array
*/
protected $processorParamsConfig = [
'psr' => ['Y-m-d\A\TH:i:s.uP', false]
];
/**
* multiple Log() objects can be marked as "grouped"
* -> Logs with Slack Handler should be grouped by map (send multiple log data in once
@@ -110,6 +144,10 @@ abstract class AbstractLog implements LogInterface {
private $buffer = true;
/**
* AbstractLog constructor.
* @param string $action
*/
public function __construct(string $action){
$this->setF3();
$this->action = $action;
@@ -176,7 +214,7 @@ abstract class AbstractLog implements LogInterface {
* @param array $data
* @return LogInterface
*/
public function setData(array $data) : LogInterface{
public function setData(array $data) : LogInterface {
$this->data = $data;
return $this;
}
@@ -185,7 +223,7 @@ abstract class AbstractLog implements LogInterface {
* @param array $data
* @return LogInterface
*/
public function setTempData(array $data) : LogInterface{
public function setTempData(array $data) : LogInterface {
$this->tmpData = $data;
return $this;
}
@@ -227,7 +265,7 @@ abstract class AbstractLog implements LogInterface {
/**
* @return array
*/
public function getHandlerConfig() : array{
public function getHandlerConfig() : array {
return $this->handlerConfig;
}
@@ -238,8 +276,6 @@ abstract class AbstractLog implements LogInterface {
* @throws \Exception
*/
public function getHandlerParams(string $handlerKey) : array {
$params = [];
if($this->hasHandlerKey($handlerKey)){
switch($handlerKey){
case 'stream': $params = $this->getHandlerParamsStream();
@@ -255,10 +291,10 @@ abstract class AbstractLog implements LogInterface {
$params = $this->getHandlerParamsSlack($handlerKey);
break;
default:
throw new \Exception( sprintf(self::ERROR_HANDLER_PARAMS, $handlerKey));
throw new \Exception(sprintf(self::ERROR_HANDLER_PARAMS, $handlerKey));
}
}else{
throw new \Exception( sprintf(self::ERROR_HANDLER_KEY, $handlerKey, implode(', ', array_flip($this->handlerConfig))));
throw new \Exception(sprintf(self::ERROR_HANDLER_KEY, $handlerKey, implode(', ', array_flip($this->handlerConfig))));
}
return $params;
@@ -278,58 +314,79 @@ abstract class AbstractLog implements LogInterface {
return $this->processorConfig;
}
/**
* get __construct() parameters for a given $processorKey
* @param string $processorKey
* @return array
* @throws \Exception
*/
public function getProcessorParams(string $processorKey) : array {
if($this->hasProcessorKey($processorKey)){
switch($processorKey){
case 'psr': $params = $this->getProcessorParamsPsr();
break;
default:
throw new \Exception(sprintf(self::ERROR_PROCESSOR_PARAMS, $processorKey));
}
}else{
throw new \Exception(sprintf(self::ERROR_PROCESSOR_KEY, $processorKey, implode(', ', array_flip($this->processorConfig))));
}
return $params;
}
/**
* @return string
*/
public function getMessage() : string{
public function getMessage() : string {
return $this->message;
}
/**
* @return string
*/
public function getAction() : string{
public function getAction() : string {
return $this->action;
}
/**
* @return string
*/
public function getChannelType() : string{
public function getChannelType() : string {
return $this->channelType;
}
/**
* @return string
*/
public function getChannelName() : string{
public function getChannelName() : string {
return $this->getChannelType();
}
/**
* @return string
*/
public function getLevel() : string{
public function getLevel() : string {
return $this->level;
}
/**
* @return string
*/
public function getTag() : string{
public function getTag() : string {
return $this->tag;
}
/**
* @return array
*/
public function getData() : array{
public function getData() : array {
return $this->data;
}
/**
* @return array
*/
public function getContext() : array{
public function getContext() : array {
$context = [
'data' => $this->getData(),
'tag' => $this->getTag()
@@ -351,7 +408,7 @@ abstract class AbstractLog implements LogInterface {
/**
* @return array
*/
public function getHandlerGroups() : array{
public function getHandlerGroups() : array {
return $this->handlerGroups;
}
@@ -372,7 +429,7 @@ abstract class AbstractLog implements LogInterface {
* @param string $handlerKey
* @return bool
*/
public function hasHandlerKey(string $handlerKey) : bool{
public function hasHandlerKey(string $handlerKey) : bool {
return array_key_exists($handlerKey, $this->handlerConfig);
}
@@ -380,21 +437,29 @@ abstract class AbstractLog implements LogInterface {
* @param string $handlerKey
* @return bool
*/
public function hasHandlerGroupKey(string $handlerKey) : bool{
public function hasHandlerGroupKey(string $handlerKey) : bool {
return in_array($handlerKey, $this->getHandlerGroups());
}
/**
* @param string $processorKey
* @return bool
*/
public function hasProcessorKey(string $processorKey) : bool {
return array_key_exists($processorKey, $this->processorConfig);
}
/**
* @return bool
*/
public function hasBuffer() : bool{
public function hasBuffer() : bool {
return $this->buffer;
}
/**
* @return bool
*/
public function isGrouped() : bool{
public function isGrouped() : bool {
return !empty($this->getHandlerGroups());
}
@@ -415,12 +480,12 @@ abstract class AbstractLog implements LogInterface {
unset($this->handlerParamsConfig[$handlerKey]);
}
// Handler parameters for Monolog\Handler\AbstractHandler ---------------------------------------------------------
// Handler parameters for Monolog\Handler\* instances -------------------------------------------------------------
/**
* @return array
*/
protected function getHandlerParamsStream() : array{
protected function getHandlerParamsStream() : array {
$params = [];
if( !empty($conf = $this->handlerParamsConfig['stream']) ){
$params[] = $conf->stream;
@@ -541,6 +606,16 @@ abstract class AbstractLog implements LogInterface {
return $params;
}
// Processor parameters for Monolog\Processor\* instances ---------------------------------------------------------
/**
* get __construct() params for PsrLogMessageProcessor() call
* @return array
*/
protected function getProcessorParamsPsr() : array {
return !empty($conf = $this->processorParamsConfig['psr']) ? $conf : [];
}
/**
* send this Log to global log buffer storage
*/

View File

@@ -6,7 +6,7 @@
* Time: 16:42
*/
namespace lib\logging;
namespace Exodus4D\Pathfinder\Lib\Logging;
class ApiLog extends AbstractLog {
@@ -20,8 +20,17 @@ class ApiLog extends AbstractLog {
//'stream' => 'json'
];
/**
* @var string
*/
protected $channelType = 'api';
/**
* ApiLog constructor.
* @param string $action
* @param string $level
* @throws \Exception
*/
public function __construct(string $action, string $level){
parent::__construct($action);

View File

@@ -6,7 +6,7 @@
* Time: 22:08
*/
namespace lib\logging;
namespace Exodus4D\Pathfinder\Lib\Logging;
class DefaultLog extends AbstractLog {

View File

@@ -6,13 +6,17 @@
* Time: 14:49
*/
namespace lib\logging\formatter;
namespace Exodus4D\Pathfinder\Lib\Logging\Formatter;
use lib\Config;
use Exodus4D\Pathfinder\Lib\Config;
use Monolog\Formatter;
class MailFormatter implements Formatter\FormatterInterface {
/**
* @param array $record
* @return mixed|string
*/
public function format(array $record){
$tplDefaultData = [
@@ -34,6 +38,10 @@ class MailFormatter implements Formatter\FormatterInterface {
return \Template::instance()->render('templates/mail/basic_inline.html', 'text/html', $tplData);
}
/**
* @param array $records
* @return mixed|string
*/
public function formatBatch(array $records){
$message = '';
foreach ($records as $key => $record) {

View File

@@ -6,9 +6,9 @@
* Time: 10:18
*/
namespace lib\logging\handler;
namespace Exodus4D\Pathfinder\Lib\Logging\Handler;
use lib\Util;
use Exodus4D\Pathfinder\Lib\Util;
abstract class AbstractMapWebhookHandler extends AbstractWebhookHandler {

View File

@@ -6,10 +6,10 @@
* Time: 10:09
*/
namespace lib\logging\handler;
namespace Exodus4D\Pathfinder\Lib\Logging\Handler;
use League\HTMLToMarkdown\HtmlConverter;
use lib\Util;
use Exodus4D\Pathfinder\Lib\Util;
abstract class AbstractRallyWebhookHandler extends AbstractWebhookHandler {
@@ -150,7 +150,6 @@ abstract class AbstractRallyWebhookHandler extends AbstractWebhookHandler {
protected function htmlToMarkdown($html){
$converter = new HtmlConverter();
$converter->getConfig()->setOption('strip_tags', true);
$markdown = $converter->convert($html);
return $markdown;
return $converter->convert($html);
}
}

View File

@@ -6,9 +6,9 @@
* Time: 20:08
*/
namespace lib\logging\handler;
namespace Exodus4D\Pathfinder\Lib\Logging\Handler;
use lib\Config;
use Exodus4D\Pathfinder\Lib\Config;
use Monolog\Handler;
use Monolog\Logger;
@@ -127,7 +127,7 @@ abstract class AbstractWebhookHandler extends Handler\AbstractProcessingHandler
*
* @param array $record
*/
protected function write(array $record){
protected function write(array $record) : void {
$record = $this->excludeFields($record);
$postData = $this->getSlackData($record);

View File

@@ -6,7 +6,7 @@
* Time: 10:23
*/
namespace lib\logging\handler;
namespace Exodus4D\Pathfinder\Lib\Logging\Handler;
class DiscordMapWebhookHandler extends AbstractMapWebhookHandler {

View File

@@ -6,11 +6,15 @@
* Time: 10:13
*/
namespace lib\logging\handler;
namespace Exodus4D\Pathfinder\Lib\Logging\Handler;
class DiscordRallyWebhookHandler extends AbstractRallyWebhookHandler {
/**
* @param $html
* @return string
*/
protected function htmlToMarkdown($html){
$markdown = parent::htmlToMarkdown($html);
// Discord supports syntax highlighting for MarkDown

View File

@@ -6,9 +6,9 @@
* Time: 20:52
*/
namespace lib\logging\handler;
namespace Exodus4D\Pathfinder\Lib\Logging\Handler;
class SlackMapWebhookHandler extends AbstractMapWebhookHandler {
}

View File

@@ -6,12 +6,9 @@
* Time: 17:32
*/
namespace lib\logging\handler;
namespace Exodus4D\Pathfinder\Lib\Logging\Handler;
class SlackRallyWebhookHandler extends AbstractRallyWebhookHandler {
}

View File

@@ -6,7 +6,7 @@
* Time: 19:11
*/
namespace lib\logging\handler;
namespace Exodus4D\Pathfinder\Lib\Logging\Handler;
use Monolog\Logger;
@@ -19,6 +19,13 @@ class SocketHandler extends \Monolog\Handler\SocketHandler {
*/
protected $metaData = [];
/**
* SocketHandler constructor.
* @param $connectionString
* @param int $level
* @param bool $bubble
* @param array $metaData
*/
public function __construct($connectionString, $level = Logger::DEBUG, $bubble = true, $metaData = []){
$this->metaData = $metaData;
@@ -31,7 +38,7 @@ class SocketHandler extends \Monolog\Handler\SocketHandler {
* @param array $record
* @return bool
*/
public function handle(array $record){
public function handle(array $record) : bool {
if (!$this->isHandling($record)) {
return false;
}

View File

@@ -6,7 +6,7 @@
* Time: 11:23
*/
namespace lib\logging;
namespace Exodus4D\Pathfinder\Lib\Logging;
class LogCollection extends AbstractLog {
@@ -32,6 +32,10 @@ class LogCollection extends AbstractLog {
*/
private $collection = null;
/**
* LogCollection constructor.
* @param string $action
*/
public function __construct(string $action){
parent::__construct($action);

View File

@@ -0,0 +1,71 @@
<?php
/**
* Created by PhpStorm.
* User: Exodus 4D
* Date: 05.08.2017
* Time: 14:10
*/
namespace Exodus4D\Pathfinder\Lib\Logging;
interface LogInterface {
public function setMessage(string $message);
public function setLevel(string $level);
public function setTag(string $tag);
public function setData(array $data) : LogInterface;
public function setTempData(array $data) : LogInterface;
public function addHandler(string $handlerKey, string $formatterKey = null, \stdClass $handlerParams = null) : LogInterface;
public function addHandlerGroup(string $handlerKey) : LogInterface;
public function getHandlerConfig() : array;
public function getHandlerParamsConfig() : array;
public function getProcessorConfig() : array;
public function getProcessorParams(string $processorKey) : array;
public function getHandlerParams(string $handlerKey) : array;
public function getMessage() : string;
public function getAction() : string;
public function getChannelType() : string;
public function getChannelName() : string;
public function getLevel() : string;
public function getData() : array;
public function getContext() : array;
public function getHandlerGroups() : array;
public function getGroupHash() : string;
public function hasHandlerKey(string $handlerKey) : bool;
public function hasHandlerGroupKey(string $handlerKey) : bool;
public function hasProcessorKey(string $processorKey) : bool;
public function hasBuffer() : bool;
public function isGrouped() : bool;
public function removeHandlerGroups();
public function removeHandlerGroup(string $handlerKey);
public function buffer();
}

View File

@@ -6,10 +6,10 @@
* Time: 22:08
*/
namespace lib\logging;
namespace Exodus4D\Pathfinder\Lib\Logging;
use controller\LogController;
use Exodus4D\Pathfinder\Controller\LogController;
class MapLog extends AbstractCharacterLog {
@@ -34,7 +34,12 @@ class MapLog extends AbstractCharacterLog {
*/
protected $logActivity = false;
/**
* MapLog constructor.
* @param string $action
* @param array $objectData
* @throws \Exception
*/
public function __construct(string $action, array $objectData){
parent::__construct($action, $objectData);

View File

@@ -6,9 +6,10 @@
* Time: 16:50
*/
namespace lib\logging;
namespace Exodus4D\Pathfinder\Lib\Logging;
use lib\Config;
use Exodus4D\Pathfinder\Lib\Config;
class RallyLog extends AbstractCharacterLog {
@@ -27,7 +28,12 @@ class RallyLog extends AbstractCharacterLog {
*/
protected $channelType = 'rally';
/**
* RallyLog constructor.
* @param string $action
* @param array $objectData
* @throws \Exception
*/
public function __construct(string $action, array $objectData){
parent::__construct($action, $objectData);

View File

@@ -6,7 +6,7 @@
* Time: 14:15
*/
namespace lib\logging;
namespace Exodus4D\Pathfinder\Lib\Logging;
class UserLog extends AbstractChannelLog {
@@ -25,6 +25,12 @@ class UserLog extends AbstractChannelLog {
*/
protected $channelType = 'user';
/**
* UserLog constructor.
* @param string $action
* @param array $objectData
* @throws \Exception
*/
public function __construct(string $action, array $objectData){
parent::__construct($action, $objectData);

View File

@@ -6,12 +6,13 @@
* Time: 20:17
*/
namespace lib;
namespace Exodus4D\Pathfinder\Lib;
use controller\LogController;
use lib\logging;
use Exodus4D\Pathfinder\Controller\LogController;
use Exodus4D\Pathfinder\Lib\Logging;
use Monolog\Registry;
use Monolog\Processor\ProcessorInterface;
use Monolog\Formatter\FormatterInterface;
use Monolog\Handler\HandlerInterface;
use Monolog\Handler\BufferHandler;
@@ -20,27 +21,47 @@ use Monolog\Logger;
class Monolog extends \Prefab {
/**
* error message for unknown formatter
*/
const ERROR_FORMATTER = 'Unknown log formatter for key "%s"';
/**
* error message for unknown handler
*/
const ERROR_HANDLER = 'Unknown log handler for key "%s"';
/**
* error message for unknown processor
*/
const ERROR_PROCESSOR = 'Unknown log processor for key "%s"';
/**
* available formatters
*/
const FORMATTER = [
'line' => 'Monolog\Formatter\LineFormatter',
'json' => 'Monolog\Formatter\JsonFormatter',
'html' => 'Monolog\Formatter\HtmlFormatter',
'mail' => 'lib\logging\formatter\MailFormatter'
'mail' => 'Exodus4D\Pathfinder\Lib\Logging\Formatter\MailFormatter'
];
/**
* available handlers
*/
const HANDLER = [
'stream' => 'Monolog\Handler\StreamHandler',
'mail' => 'Monolog\Handler\SwiftMailerHandler',
'socket' => 'lib\logging\handler\SocketHandler',
'slackMap' => 'lib\logging\handler\SlackMapWebhookHandler',
'slackRally' => 'lib\logging\handler\SlackRallyWebhookHandler',
'discordMap' => 'lib\logging\handler\DiscordMapWebhookHandler',
'discordRally' => 'lib\logging\handler\DiscordRallyWebhookHandler'
'socket' => 'Exodus4D\Pathfinder\Lib\Logging\Handler\SocketHandler',
'slackMap' => 'Exodus4D\Pathfinder\Lib\Logging\Handler\SlackMapWebhookHandler',
'slackRally' => 'Exodus4D\Pathfinder\Lib\Logging\Handler\SlackRallyWebhookHandler',
'discordMap' => 'Exodus4D\Pathfinder\Lib\Logging\Handler\DiscordMapWebhookHandler',
'discordRally' => 'Exodus4D\Pathfinder\Lib\Logging\Handler\DiscordRallyWebhookHandler'
];
/**
* available processors
*/
const PROCESSOR = [
'psr' => 'Monolog\Processor\PsrLogMessageProcessor'
];
@@ -54,12 +75,7 @@ class Monolog extends \Prefab {
];
public function __construct(){
// set timezone for all Logger instances
if(class_exists(Logger::class)){
if( is_callable($getTimezone = \Base::instance()->get('getTimeZone')) ){
Logger::setTimezone($getTimezone());
};
}else{
if(!class_exists(Logger::class)){
LogController::getLogger('ERROR')->write(sprintf(Config::ERROR_CLASS_NOT_EXISTS_COMPOSER, Logger::class));
}
}
@@ -107,6 +123,10 @@ class Monolog extends \Prefab {
}else{
$logger = new Logger($log->getChannelName());
if(is_callable($getTimezone = \Base::instance()->get('getTimeZone'))){
$logger->setTimezone($getTimezone());
}
// disable microsecond timestamps (seconds should be fine)
$logger->useMicrosecondTimestamps(true);
@@ -143,7 +163,8 @@ class Monolog extends \Prefab {
$logger->pushProcessor($processorCallback);
}else{
// get Monolog Processor class
$processor = $this->getProcessor($processorKey);
$processorParams = $log->getProcessorParams($processorKey);
$processor = $this->getProcessor($processorKey, $processorParams);
$logger->pushProcessor($processor);
}
}
@@ -187,7 +208,7 @@ class Monolog extends \Prefab {
* @return HandlerInterface
* @throws \Exception
*/
private function getHandler(string $handlerKey, array $handlerParams = []): HandlerInterface{
private function getHandler(string $handlerKey, array $handlerParams = []) : HandlerInterface{
if(array_key_exists($handlerKey, self::HANDLER)){
$handlerClass = self::HANDLER[$handlerKey];
$handler = new $handlerClass(...$handlerParams);
@@ -201,13 +222,14 @@ class Monolog extends \Prefab {
/**
* get Monolog Processor instance by key
* @param string $processorKey
* @return callable
* @param array $processorParams
* @return ProcessorInterface
* @throws \Exception
*/
private function getProcessor(string $processorKey): callable {
private function getProcessor(string $processorKey, array $processorParams = []) : ProcessorInterface {
if(array_key_exists($processorKey, self::PROCESSOR)){
$ProcessorClass = self::PROCESSOR[$processorKey];
$processor = new $ProcessorClass();
$processor = new $ProcessorClass(...$processorParams);
}else{
throw new \Exception(sprintf(self::ERROR_PROCESSOR, $processorKey));
}

View File

@@ -1,7 +1,7 @@
<?php
namespace lib;
namespace Exodus4D\Pathfinder\Lib;
class PriorityCacheStore {

View File

@@ -6,7 +6,7 @@
* Time: 10:58
*/
namespace lib;
namespace Exodus4D\Pathfinder\Lib;
class Resource extends \Prefab {
@@ -15,45 +15,52 @@ class Resource extends \Prefab {
* default link "rel" attribute
* @link https://w3c.github.io/preload/#x2.link-type-preload
*/
const ATTR_REL = 'preload';
const ATTR_REL = 'preload';
/**
* default link "as" attributes
*/
const ATTR_AS = [
'style' => 'style',
'script' => 'script',
'font' => 'font',
'document' => 'document',
'image' => 'image',
'url' => ''
'style' => 'style',
'script' => 'script',
'font' => 'font',
'document' => 'document',
'image' => 'image',
'url' => ''
];
/**
* default link "type" attributes
*/
const ATTR_TYPE = [
'font' => 'font/woff2'
'font' => 'font/woff2'
];
/**
* default additional attributes by $group
*/
const ATTR_ADD = [
'font' => ['crossorigin' => 'anonymous']
'font' => ['crossorigin' => 'anonymous']
];
/**
* BASE path
* @var string
*/
private $basePath = '';
/**
* absolute file path -> use setOption() for update
* @var array
*/
private $filePath = [
'style' => '',
'script' => '',
'font' => '',
'document' => '',
'image' => '',
'url' => ''
'style' => '',
'script' => '',
'font' => '',
'document' => '',
'image' => '',
'favicon' => '',
'url' => ''
];
/**
@@ -62,10 +69,10 @@ class Resource extends \Prefab {
* @var array
*/
private $fileExt = [
'style' => 'css',
'script' => 'js',
'document' => 'html',
'font' => 'woff2'
'style' => 'css',
'script' => 'js',
'document' => 'html',
'font' => 'woff2'
];
/**
@@ -76,7 +83,7 @@ class Resource extends \Prefab {
* @see buildHeader()
* @var string
*/
private $output = 'inline';
private $output = 'inline';
/**
* resource file cache
@@ -134,7 +141,7 @@ class Resource extends \Prefab {
* @return string
*/
public function getPath(string $group) : string {
return $this->filePath[$group];
return rtrim($this->basePath, '/\\') . $this->filePath[$group];
}
/**

View File

@@ -6,7 +6,7 @@
* Time: 19:13
*/
namespace lib\socket;
namespace Exodus4D\Pathfinder\Lib\Socket;
use React\EventLoop;
@@ -237,12 +237,10 @@ abstract class AbstractSocket implements SocketInterface {
* @return array
*/
protected function newPayload(string $task, $load = null) : array {
$payload = [
return [
'task' => $task,
'load' => $load
];
return $payload;
}
/**

View File

@@ -6,7 +6,7 @@
* Time: 23:22
*/
namespace lib\socket;
namespace Exodus4D\Pathfinder\Lib\Socket;
use React\Socket;

View File

@@ -6,10 +6,9 @@
* Time: 11:26
*/
namespace lib\socket;
namespace Exodus4D\Pathfinder\Lib\Socket;
use React\EventLoop;
use React\Promise;
interface SocketInterface {

View File

@@ -6,7 +6,7 @@
* Time: 10:04
*/
namespace lib\socket;
namespace Exodus4D\Pathfinder\Lib\Socket;
use React\Socket;

View File

@@ -6,7 +6,8 @@
* Time: 17:32
*/
namespace lib;
namespace Exodus4D\Pathfinder\Lib;
class Util {

View File

@@ -6,16 +6,17 @@
* Time: 22:11
*/
namespace Model;
namespace Exodus4D\Pathfinder\Model;
use DB\Cortex;
use DB\CortexCollection;
use DB\SQL\Schema;
use lib\Util;
use lib\logging;
use Controller;
use Exception\ValidationException;
use Exception\DatabaseException;
use Exodus4D\Pathfinder\Lib\Util;
use Exodus4D\Pathfinder\Lib\Logging;
use Exodus4D\Pathfinder\Controller;
use Exodus4D\Pathfinder\Db\Sql\Mysql;
use Exodus4D\Pathfinder\Exception\ValidationException;
use Exodus4D\Pathfinder\Exception\DatabaseException;
abstract class AbstractModel extends Cortex {
@@ -326,7 +327,7 @@ abstract class AbstractModel extends Cortex {
$valid = $this->$method($key, $val);
}else{
self::getF3()->error(501, 'Method ' . get_class($this) . '->' . $method . '() is not implemented');
};
}
}
}
@@ -1053,13 +1054,12 @@ abstract class AbstractModel extends Cortex {
/**
* get tableModifier class for this table
* @return bool|\DB\SQL\TableModifier
* @return bool|Mysql\TableModifier
*/
public static function getTableModifier(){
$df = parent::resolveConfiguration();
$schema = new Schema($df['db']);
$tableModifier = $schema->alterTable($df['table']);
return $tableModifier;
return $schema->alterTable($df['table']);
}
/**

View File

@@ -6,9 +6,10 @@
* Time: 18:45
*/
namespace Model\Pathfinder;
namespace Exodus4D\Pathfinder\Model\Pathfinder;
use DB\SQL\Schema;
use Exodus4D\Pathfinder\Exception;
abstract class AbstractMapTrackingModel extends AbstractPathfinderModel implements LogModelInterface {
@@ -19,7 +20,7 @@ abstract class AbstractMapTrackingModel extends AbstractPathfinderModel implemen
'createdCharacterId' => [
'type' => Schema::DT_INT,
'index' => true,
'belongs-to-one' => 'Model\Pathfinder\CharacterModel',
'belongs-to-one' => 'Exodus4D\Pathfinder\Model\Pathfinder\CharacterModel',
'constraint' => [
[
'table' => 'character',
@@ -31,7 +32,7 @@ abstract class AbstractMapTrackingModel extends AbstractPathfinderModel implemen
'updatedCharacterId' => [
'type' => Schema::DT_INT,
'index' => true,
'belongs-to-one' => 'Model\Pathfinder\CharacterModel',
'belongs-to-one' => 'Exodus4D\Pathfinder\Model\Pathfinder\CharacterModel',
'constraint' => [
[
'table' => 'character',
@@ -70,7 +71,7 @@ abstract class AbstractMapTrackingModel extends AbstractPathfinderModel implemen
/**
* validates all required columns of this class
* @return bool
* @throws \Exception\DatabaseException
* @throws Exception\DatabaseException
*/
public function isValid(): bool {
if($valid = parent::isValid()){

View File

@@ -1,10 +1,9 @@
<?php
namespace Model\Pathfinder;
namespace Exodus4D\Pathfinder\Model\Pathfinder;
use Model\AbstractModel;
use Exodus4D\Pathfinder\Model\AbstractModel;
abstract class AbstractPathfinderModel extends AbstractModel {
@@ -55,21 +54,6 @@ abstract class AbstractPathfinderModel extends AbstractModel {
return true;
}
/**
* set "updated" field to current timestamp
* this is useful to mark a row as "changed"
*/
protected function setUpdated(){
if($this->_id > 0){
$this->db->exec(
["UPDATE " . $this->table . " SET updated=NOW() WHERE id=:id"],
[
[':id' => $this->_id]
]
);
}
}
/**
* get old and new value from field, in case field is configured with 'activity-log'
* @return array
@@ -79,7 +63,7 @@ abstract class AbstractPathfinderModel extends AbstractModel {
if($this->enableActivityLogging){
// filter fields, where "activity" (changes) should be logged
$fieldConf = array_filter($this->fieldConf, function($fieldConf, $key) {
$fieldConf = array_filter($this->fieldConf, function($fieldConf, $key){
return isset($fieldConf['activity-log']) ? (bool)$fieldConf['activity-log'] : false;
}, ARRAY_FILTER_USE_BOTH);

View File

@@ -6,7 +6,7 @@
* Time: 22:11
*/
namespace Model\Pathfinder;
namespace Exodus4D\Pathfinder\Model\Pathfinder;
use DB\SQL\Schema;

View File

@@ -6,14 +6,20 @@
* Time: 15:11
*/
namespace Model\Pathfinder;
namespace Exodus4D\Pathfinder\Model\Pathfinder;
use DB\SQL\Schema;
class ActivityLogModel extends AbstractPathfinderModel {
/**
* @var string
*/
protected $table = 'activity_log';
/**
* @var array
*/
protected $fieldConf = [
'active' => [
'type' => Schema::DT_BOOL,
@@ -24,7 +30,7 @@ class ActivityLogModel extends AbstractPathfinderModel {
'characterId' => [
'type' => Schema::DT_INT,
'index' => true,
'belongs-to-one' => 'Model\Pathfinder\CharacterModel',
'belongs-to-one' => 'Exodus4D\Pathfinder\Model\Pathfinder\CharacterModel',
'constraint' => [
[
'table' => 'character',
@@ -35,7 +41,7 @@ class ActivityLogModel extends AbstractPathfinderModel {
'mapId' => [
'type' => Schema::DT_INT,
'index' => true,
'belongs-to-one' => 'Model\Pathfinder\MapModel',
'belongs-to-one' => 'Exodus4D\Pathfinder\Model\Pathfinder\MapModel',
'constraint' => [
[
'table' => 'map',
@@ -129,6 +135,13 @@ class ActivityLogModel extends AbstractPathfinderModel {
],
];
/**
* ActivityLogModel constructor.
* @param null $db
* @param null $table
* @param null $fluid
* @param int $ttl
*/
public function __construct($db = NULL, $table = NULL, $fluid = NULL, $ttl = 0){
$this->addStaticDateFieldConfig();

View File

@@ -6,7 +6,7 @@
* Time: 20:14
*/
namespace Model\Pathfinder;
namespace Exodus4D\Pathfinder\Model\Pathfinder;
use DB\SQL\Schema;
@@ -30,7 +30,7 @@ class AllianceMapModel extends AbstractPathfinderModel {
'allianceId' => [
'type' => Schema::DT_INT,
'index' => true,
'belongs-to-one' => 'Model\Pathfinder\AllianceModel',
'belongs-to-one' => 'Exodus4D\Pathfinder\Model\Pathfinder\AllianceModel',
'constraint' => [
[
'table' => 'alliance',
@@ -41,7 +41,7 @@ class AllianceMapModel extends AbstractPathfinderModel {
'mapId' => [
'type' => Schema::DT_INT,
'index' => true,
'belongs-to-one' => 'Model\Pathfinder\MapModel',
'belongs-to-one' => 'Exodus4D\Pathfinder\Model\Pathfinder\MapModel',
'constraint' => [
[
'table' => 'map',

View File

@@ -6,10 +6,10 @@
* Time: 20:43
*/
namespace Model\Pathfinder;
namespace Exodus4D\Pathfinder\Model\Pathfinder;
use DB\SQL\Schema;
use lib\Config;
use Exodus4D\Pathfinder\Lib\Config;
class AllianceModel extends AbstractPathfinderModel {
@@ -44,10 +44,10 @@ class AllianceModel extends AbstractPathfinderModel {
'default' => 0
],
'allianceCharacters' => [
'has-many' => ['Model\Pathfinder\CharacterModel', 'allianceId']
'has-many' => ['Exodus4D\Pathfinder\Model\Pathfinder\CharacterModel', 'allianceId']
],
'mapAlliances' => [
'has-many' => ['Model\Pathfinder\AllianceMapModel', 'allianceId']
'has-many' => ['Exodus4D\Pathfinder\Model\Pathfinder\AllianceMapModel', 'allianceId']
]
];
@@ -63,7 +63,7 @@ class AllianceModel extends AbstractPathfinderModel {
$allianceData->shared = $this->shared;
return $allianceData;
}/** @noinspection PhpHierarchyChecksInspection */
}
/**
* Event "Hook" function
@@ -150,7 +150,7 @@ class AllianceModel extends AbstractPathfinderModel {
$loaded = parent::getById($id, $ttl, $isActive);
if($this->isOutdated()){
// request alliance data
$allianceData = self::getF3()->ccpClient()->getAllianceData($id);
$allianceData = self::getF3()->ccpClient()->send('getAlliance', $id);
if(!empty($allianceData) && !isset($allianceData['error'])){
$this->copyfrom($allianceData, ['id', 'name', 'ticker']);
$this->save();

View File

@@ -6,15 +6,21 @@
* Time: 19:33
*/
namespace Model\Pathfinder;
namespace Exodus4D\Pathfinder\Model\Pathfinder;
use DB\SQL\Schema;
use Controller;
use Exodus4D\Pathfinder\Controller;
class CharacterAuthenticationModel extends AbstractPathfinderModel{
/**
* @var string
*/
protected $table = 'character_authentication';
/**
* @var array
*/
protected $fieldConf = [
'active' => [
'type' => Schema::DT_BOOL,
@@ -25,7 +31,7 @@ class CharacterAuthenticationModel extends AbstractPathfinderModel{
'characterId' => [
'type' => Schema::DT_INT,
'index' => true,
'belongs-to-one' => 'Model\Pathfinder\CharacterModel',
'belongs-to-one' => 'Exodus4D\Pathfinder\Model\Pathfinder\CharacterModel',
'constraint' => [
[
'table' => 'character',

View File

@@ -6,7 +6,7 @@
* Time: 00:04
*/
namespace Model\Pathfinder;
namespace Exodus4D\Pathfinder\Model\Pathfinder;
use DB\SQL\Schema;
@@ -37,7 +37,7 @@ class CharacterLogModel extends AbstractPathfinderModel {
'type' => Schema::DT_INT,
'index' => true,
'unique' => true,
'belongs-to-one' => 'Model\Pathfinder\CharacterModel',
'belongs-to-one' => 'Exodus4D\Pathfinder\Model\Pathfinder\CharacterModel',
'constraint' => [
[
'table' => 'character',

Some files were not shown because too many files have changed in this diff Show More