1
.gitignore
vendored
@@ -49,3 +49,4 @@ Temporary Items
|
||||
.idea
|
||||
.sass-cache
|
||||
.usage
|
||||
*.gz
|
||||
|
||||
35
.htaccess
@@ -1,7 +1,10 @@
|
||||
# Enable rewrite engine and route requests to framework
|
||||
# HTTPS over SSL version
|
||||
# Information: https://github.com/exodus4d/pathfinder/wiki/Apache
|
||||
|
||||
# Enable rewrite engine and route requests to framework ===========================================
|
||||
RewriteEngine On
|
||||
|
||||
# HTTP to HTTPS ----------------------------------------------------------------
|
||||
# HTTP to HTTPS ===================================================================================
|
||||
RewriteCond %{HTTPS} off
|
||||
RewriteCond %{HTTP_HOST} !^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$
|
||||
RewriteCond %{HTTP_HOST} !=localhost
|
||||
@@ -11,22 +14,25 @@ RewriteCond %{HTTP_HOST} !=localhost
|
||||
# the subsequent rule will catch it.
|
||||
RewriteRule .* https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
|
||||
|
||||
# Now, rewrite any request to the wrong domain to use www.
|
||||
# Rewrite NONE www. to force www. =================================================================
|
||||
RewriteCond %{HTTP_HOST} !^www\.
|
||||
# skip "localhost" (dev environment)...
|
||||
RewriteCond %{HTTP_HOST} !=localhost
|
||||
# skip IP calls (dev environment)
|
||||
RewriteCond %{HTTP_HOST} !^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$
|
||||
# rewrite everything else to "https://" and "www."
|
||||
RewriteRule .* https://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
|
||||
|
||||
|
||||
# Some servers require you to specify the `RewriteBase` directive
|
||||
# In such cases, it should be the path (relative to the document root)
|
||||
# containing this .htaccess file
|
||||
#
|
||||
#RewriteBase /app/
|
||||
# containing this .htaccess file:
|
||||
# RewriteBase /app/
|
||||
|
||||
# Protect system files ============================================================================
|
||||
RewriteCond %{ENV:REDIRECT_STATUS} ^$
|
||||
RewriteRule ^(lib|tmp)\/|\.(ini|php)$ - [R=404]
|
||||
|
||||
# Rewrite "everything" to index.php (dispatcher) ==================================================
|
||||
RewriteCond %{REQUEST_FILENAME} !-l
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
@@ -34,18 +40,19 @@ RewriteRule .* index.php [L,QSA]
|
||||
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
|
||||
|
||||
|
||||
# PHP global Vars
|
||||
# PHP global Vars (can be set in php.ini as well,...) =============================================
|
||||
php_value max_input_vars 5000
|
||||
php_value suhosin.get.max_vars 5000
|
||||
php_value suhosin.post.max_vars 5000
|
||||
php_value suhosin.request.max_vars 5000
|
||||
|
||||
|
||||
# PHP error logs
|
||||
# Activate PHP error log ==========================================================================
|
||||
php_flag log_errors on
|
||||
# php_value error_log "/www/htdocs/w0128162/www.pathfinder.exodus4d.de/logs/php_errors.log"
|
||||
# php_value error_log "/www/htdocs/www.pathfinder-w.space/logs/php_errors.log"
|
||||
|
||||
# caching
|
||||
# Cache Header ====================================================================================
|
||||
# You should not change anything in here!
|
||||
# New versioned files come with a unique path (e.g. ../js/v1.0.0/..) to force client cache busting.
|
||||
<ifmodule mod_expires.c>
|
||||
# fonts
|
||||
<Filesmatch "\.(eot|woff2|woff|ttf|ttf|svg)$">
|
||||
@@ -83,6 +90,4 @@ php_flag log_errors on
|
||||
ExpiresActive on
|
||||
ExpiresDefault "access plus 1 week"
|
||||
</Filesmatch>
|
||||
</ifmodule>
|
||||
|
||||
|
||||
</ifmodule>
|
||||
82
.htaccess_HTTP
Normal file
@@ -0,0 +1,82 @@
|
||||
# HTTP version
|
||||
# Information: https://github.com/exodus4d/pathfinder/wiki/Apache
|
||||
|
||||
# Enable rewrite engine and route requests to framework ===========================================
|
||||
RewriteEngine On
|
||||
|
||||
# Rewrite NONE www. to force www. =================================================================
|
||||
RewriteCond %{HTTP_HOST} !^www\.
|
||||
# skip "localhost" (dev environment)...
|
||||
RewriteCond %{HTTP_HOST} !=localhost
|
||||
# skip IP calls (dev environment) e.g. 127.0.0.1
|
||||
RewriteCond %{HTTP_HOST} !^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$
|
||||
# rewrite everything else to "http://" and "www."
|
||||
RewriteRule .* http://www.%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
|
||||
|
||||
# Some servers require you to specify the `RewriteBase` directive
|
||||
# In such cases, it should be the path (relative to the document root)
|
||||
# containing this .htaccess file:
|
||||
# RewriteBase /app/
|
||||
|
||||
# Protect system files ============================================================================
|
||||
RewriteCond %{ENV:REDIRECT_STATUS} ^$
|
||||
RewriteRule ^(lib|tmp)\/|\.(ini|php)$ - [R=404]
|
||||
|
||||
# Rewrite "everything" to index.php (dispatcher) ==================================================
|
||||
RewriteCond %{REQUEST_FILENAME} !-l
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
RewriteRule .* index.php [L,QSA]
|
||||
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization},L]
|
||||
|
||||
# PHP global Vars (can be set in php.ini as well,...) =============================================
|
||||
php_value max_input_vars 5000
|
||||
php_value suhosin.get.max_vars 5000
|
||||
php_value suhosin.post.max_vars 5000
|
||||
php_value suhosin.request.max_vars 5000
|
||||
|
||||
# Activate PHP error log ==========================================================================
|
||||
php_flag log_errors on
|
||||
php_value error_log "/www/htdocs/w0128162/www.pathfinder-dev.exodus4d.de/logs/php_errors.log"
|
||||
|
||||
# Cache Header ====================================================================================
|
||||
# You should not change anything in here!
|
||||
# New versioned files come with a unique path (e.g. ../js/v1.0.0/..) to force client cache busting.
|
||||
<ifmodule mod_expires.c>
|
||||
# fonts
|
||||
<Filesmatch "\.(eot|woff2|woff|ttf|ttf|svg)$">
|
||||
ExpiresActive on
|
||||
ExpiresDefault "access plus 1 month"
|
||||
Header append Cache-Control "public"
|
||||
</Filesmatch>
|
||||
|
||||
# images/vector graphics
|
||||
<Filesmatch "\.(jpg|jpeg|png|gif|swf|ico|svg)$">
|
||||
ExpiresActive on
|
||||
ExpiresDefault "access plus 1 year"
|
||||
Header append Cache-Control "public"
|
||||
FileETag None
|
||||
Header unset ETag
|
||||
</Filesmatch>
|
||||
|
||||
# css
|
||||
<Filesmatch "\.(css)$">
|
||||
ExpiresActive on
|
||||
ExpiresDefault "access plus 1 month"
|
||||
</Filesmatch>
|
||||
|
||||
## js/source maps
|
||||
<Filesmatch "\.(js|map)$">
|
||||
ExpiresActive on
|
||||
ExpiresDefault "access plus 1 year"
|
||||
Header append Cache-Control "public"
|
||||
FileETag None
|
||||
Header unset ETag
|
||||
</Filesmatch>
|
||||
|
||||
# html templates
|
||||
<Filesmatch "\.(htm|html)$">
|
||||
ExpiresActive on
|
||||
ExpiresDefault "access plus 1 week"
|
||||
</Filesmatch>
|
||||
</ifmodule>
|
||||
27
README.md
@@ -1,29 +1,38 @@
|
||||
## *PATHFINDER*
|
||||
Mapping tool for [*EVE ONLINE*](https://www.eveonline.com)
|
||||
|
||||
- Project [https://www.pathfinder.exodus4d.de](https://www.pathfinder.exodus4d.de)
|
||||
- Project [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)
|
||||
- Video [youtube.com](https://www.youtube.com/channel/UC7HU7XEoMbqRwqxDTbMjSPg)
|
||||
- Community [google +](https://plus.google.com/u/0/b/110257318165279088853/110257318165279088853)
|
||||
- Licence [MIT](http://opensource.org/licenses/MIT)
|
||||
|
||||
##### IMPORTANT Information
|
||||
**This project is still in beta phase and is not officially released! Feel free to check the code for bugs and security issues. Issues should be reported in the [Issue](https://github.com/exodus4d/pathfinder/issues) section.**
|
||||
##### IMPORTANT Information:
|
||||
**The setup and installation process in ``1.0.0RC1`` and is not backwards compatible with previous beta releases (check wiki)!**
|
||||
|
||||
If you are looking for installation help, please check the [wiki](https://github.com/exodus4d/pathfinder/wiki) (DRAFT). More information will be added once the beta is over and the first stable build is released.
|
||||
**Feel free to check the code for bugs and security issues.
|
||||
Issues should be reported in the [Issue](https://github.com/exodus4d/pathfinder/issues) section.**
|
||||
|
||||
If you are looking for installation help, please check the [wiki](https://github.com/exodus4d/pathfinder/wiki).
|
||||
More information will be added once the beta is over and the first stable build is released.
|
||||
|
||||
## Project structure
|
||||
|
||||
```
|
||||
|-- (0755) app --> backend [*.php]
|
||||
|-- (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
|
||||
|-- pathfinder.ini --> config pathfinder
|
||||
|-- routes.ini --> config routes
|
||||
|-- cron.ini --> config - cronjobs
|
||||
|-- environment.ini --> config - system environment
|
||||
|-- pathfinder.ini --> config - pathfinder
|
||||
|-- requirements.ini --> config - system requirements
|
||||
|-- routes.ini --> config - routes
|
||||
|-- (0755) export --> DB export data
|
||||
|-- sql --> static DB data for import (pathfinder.sql)
|
||||
|-- (0755) favicon --> Favicons
|
||||
|-- (0755) js --> JS source files (raw)
|
||||
|-- app --> "PASTHFINDER" core files (not used for production )
|
||||
|-- lib --> 3rd partie extension/library (not used for production )
|
||||
@@ -42,7 +51,7 @@ If you are looking for installation help, please check the [wiki](https://github
|
||||
|-- ...
|
||||
|-- (0777) tmp --> cache folder
|
||||
|-- ...
|
||||
|-- (0755) .htaccess --> reroute/caching rules
|
||||
|-- (0755) .htaccess --> reroute/caching rules ("Apache" only!)
|
||||
|-- (0755) index.php
|
||||
|
||||
--------------------------
|
||||
|
||||
@@ -1,36 +1,47 @@
|
||||
; Global Framework Config
|
||||
|
||||
[globals]
|
||||
; Default Verbosity level of the stack trace.
|
||||
; Assign values between 0 to 3 for increasing verbosity levels. Check "PATHFINDER" config for overwriting
|
||||
DEBUG = 0
|
||||
; Assign values between 0 to 3 for increasing verbosity levels. Check (environment.ini) config for overwriting
|
||||
DEBUG = 0
|
||||
|
||||
; If TRUE, the framework, after having logged stack trace and errors, stops execution (die without any status) when a non-fatal error is detected.
|
||||
HALT = FALSE
|
||||
; If TRUE, the framework, after having logged stack trace and errors, stops execution
|
||||
; -> (die without any status) when a non-fatal error is detected.
|
||||
HALT = FALSE
|
||||
|
||||
; Timezone to use. Sync program with eve server time
|
||||
TZ = "UTC"
|
||||
TZ = UTC
|
||||
|
||||
; Cache backend. Can handle Memcache module, APC, WinCache, XCache and a filesystem-based cache.
|
||||
CACHE = TRUE
|
||||
CACHE = TRUE
|
||||
|
||||
; Callback functions ===================================================================================
|
||||
ONERROR = "Controller\Controller->showError"
|
||||
; Callback functions ==============================================================================
|
||||
ONERROR = Controller\Controller->showError
|
||||
|
||||
UNLOAD = "Controller\Controller->unload"
|
||||
UNLOAD = Controller\Controller->unload
|
||||
|
||||
; Path configurations ==================================================================================
|
||||
; Path configurations =============================================================================
|
||||
; relative to "BASE" dir
|
||||
|
||||
; Temporary folder for cache, filesystem locks, compiled F3 templates, etc.
|
||||
TEMP = tmp/
|
||||
TEMP = tmp/
|
||||
|
||||
; Log file folder
|
||||
LOGS = logs/
|
||||
LOGS = logs/
|
||||
|
||||
; Search path for user interface files used by the View and Template classes' render() method.
|
||||
UI = public/
|
||||
UI = public/
|
||||
|
||||
; Search path(s) for user-defined PHP classes that the framework will attempt to autoload at runtime
|
||||
AUTOLOAD = app/main/
|
||||
|
||||
AUTOLOAD = app/main/
|
||||
|
||||
; path to favicons folder
|
||||
FAVICON = /favicon
|
||||
|
||||
; load additional config files
|
||||
[configs]
|
||||
app/routes.ini = true
|
||||
app/environment.ini = true
|
||||
app/pathfinder.ini = true
|
||||
app/requirements.ini = true
|
||||
app/cron.ini = true
|
||||
@@ -21,4 +21,4 @@ deactivateMapData = Cron\MapUpdate->deactivateMapData, @hourly
|
||||
deleteMapData = Cron\MapUpdate->deleteMapData, @downtime
|
||||
|
||||
; delete character log data
|
||||
deleteLogData = Cron\CharacterUpdate->deleteLogData, @instant
|
||||
deleteLogData = Cron\CharacterUpdate->deleteLogData, @hourly
|
||||
64
app/environment.ini
Normal file
@@ -0,0 +1,64 @@
|
||||
; Environment Config
|
||||
|
||||
[ENVIRONMENT]
|
||||
; project environment (DEVELOP, PRODUCTION).
|
||||
; This effects: DB connection, Mail-Server connection
|
||||
; configuration below
|
||||
SERVER = DEVELOP
|
||||
|
||||
[ENVIRONMENT.DEVELOP]
|
||||
; base dir (Default: "auto-detect"
|
||||
BASE =
|
||||
; deployment URL e.g. http://localhost
|
||||
URL = http://pathfinder.local
|
||||
; Verbosity level of the stack trace
|
||||
DEBUG = 3
|
||||
; main db
|
||||
DB_DNS = mysql:host=localhost;port=3306;dbname=
|
||||
DB_NAME = pathfinder
|
||||
DB_USER = root
|
||||
DB_PASS =
|
||||
|
||||
; EVE-Online CCP Database export
|
||||
DB_CCP_DNS = mysql:host=localhost;port=3306;dbname=
|
||||
DB_CCP_NAME = eve_parallax_min
|
||||
DB_CCP_USER = root
|
||||
DB_CCP_PASS =
|
||||
|
||||
; SMTP settings
|
||||
SMTP_HOST = localhost
|
||||
SMTP_PORT = 25
|
||||
SMTP_SCHEME = ""
|
||||
SMTP_USER = pathfinder
|
||||
SMTP_PASS = root
|
||||
|
||||
SMTP_FROM = pathfinder@localhost.com
|
||||
SMTP_ERROR = pathfinder@localhost.com
|
||||
|
||||
[ENVIRONMENT.PRODUCTION]
|
||||
BASE = /www/htdocs/www.pathfinder-w.space
|
||||
; deployment URL
|
||||
URL = https://www.pathfinder-w.space
|
||||
; Verbosity level of the stack trace
|
||||
DEBUG = 0
|
||||
; main db
|
||||
DB_DNS = mysql:host=localhost;port=3306;dbname=
|
||||
DB_NAME =
|
||||
DB_USER =
|
||||
DB_PASS =
|
||||
|
||||
; EVE-Online CCP Database export
|
||||
DB_CCP_DNS = mysql:host=localhost;port=3306;dbname=
|
||||
DB_CCP_NAME =
|
||||
DB_CCP_USER =
|
||||
DB_CCP_PASS =
|
||||
|
||||
; SMTP settings
|
||||
SMTP_HOST = localhost
|
||||
SMTP_PORT = 25
|
||||
SMTP_SCHEME = TLS
|
||||
SMTP_USER =
|
||||
SMTP_PASS =
|
||||
|
||||
SMTP_FROM = registration@pathfinder-w.space
|
||||
SMTP_ERROR = admin@pathfinder-w.space
|
||||
125
app/lib/cron.php
@@ -6,27 +6,33 @@ class Cron extends \Prefab {
|
||||
const
|
||||
E_Undefined='Undefined property: %s::$%s',
|
||||
E_Invalid='"%s" is not a valid name: it should only contain alphanumeric characters',
|
||||
E_NotFound='Job %s doesn\' exist',
|
||||
E_Callable='Job %s cannot be called';
|
||||
//@}
|
||||
|
||||
//@{ Log message
|
||||
const
|
||||
L_Execution='%s (%.3F s)';
|
||||
//@}
|
||||
|
||||
/** @var bool */
|
||||
public $log=FALSE;
|
||||
|
||||
/** @var bool */
|
||||
public $cli=TRUE;
|
||||
|
||||
/** @var bool */
|
||||
public $web=FALSE;
|
||||
|
||||
/** @var string */
|
||||
public $clipath;
|
||||
/** @var bool */
|
||||
public $silent=TRUE;
|
||||
|
||||
/** @var string Script path */
|
||||
public $script='index.php';
|
||||
|
||||
/** @var string PHP CLI path */
|
||||
protected $binary;
|
||||
|
||||
/** @var array */
|
||||
protected $jobs=array();
|
||||
|
||||
/** @var bool */
|
||||
protected $async=FALSE;
|
||||
|
||||
/** @var array */
|
||||
protected $presets=array(
|
||||
'yearly'=>'0 0 1 1 *',
|
||||
@@ -37,6 +43,20 @@ class Cron extends \Prefab {
|
||||
'hourly'=>'0 * * * *',
|
||||
);
|
||||
|
||||
/**
|
||||
* Set binary path after checking that it can be executed and is CLI
|
||||
* @param string $path
|
||||
* @return string
|
||||
*/
|
||||
function binary($path) {
|
||||
if (function_exists('exec')) {
|
||||
exec($path.' -v 2>&1',$out,$ret);
|
||||
if ($ret==0 && preg_match('/cli/',@$out[0],$out))
|
||||
$this->binary=$path;
|
||||
}
|
||||
return $this->binary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedule a job
|
||||
* @param string $job
|
||||
@@ -67,7 +87,6 @@ class Cron extends \Prefab {
|
||||
function isDue($job,$time) {
|
||||
if (!isset($this->jobs[$job]) || !$parts=$this->parseExpr($this->jobs[$job][1]))
|
||||
return FALSE;
|
||||
|
||||
foreach($this->parseTimestamp($time) as $i=>$k)
|
||||
if (!in_array($k,$parts[$i]))
|
||||
return FALSE;
|
||||
@@ -78,51 +97,50 @@ class Cron extends \Prefab {
|
||||
* Execute a job
|
||||
* @param string $job
|
||||
* @param bool $async
|
||||
* @return bool TRUE = job has been executed / FALSE = job has been delegated to a background process
|
||||
*/
|
||||
function execute($job,$async=TRUE) {
|
||||
if (!isset($this->jobs[$job]))
|
||||
return;
|
||||
user_error(sprintf(self::E_NotFound,$job),E_USER_ERROR);
|
||||
$f3=\Base::instance();
|
||||
if (is_string($func=$this->jobs[$job][0])){
|
||||
if (is_string($func=$this->jobs[$job][0]))
|
||||
$func=$f3->grab($func);
|
||||
}
|
||||
|
||||
if (!is_callable($func))
|
||||
return;
|
||||
if ($async && $this->async) {
|
||||
user_error(sprintf(self::E_Callable,$job),E_USER_ERROR);
|
||||
if ($async && isset($this->binary)) {
|
||||
// PHP docs: If a program is started with this function, in order for it to continue running in the background,
|
||||
// the output of the program must be redirected to a file or another output stream.
|
||||
// Failing to do so will cause PHP to hang until the execution of the program ends.
|
||||
$dir='';
|
||||
$file='index.php';
|
||||
if ($this->clipath) {
|
||||
$dir=dirname($this->clipath);
|
||||
$file=basename($this->clipath);
|
||||
}
|
||||
$dir=dirname($this->script);
|
||||
$file=basename($this->script);
|
||||
if (@$dir[0]!='/')
|
||||
$dir=getcwd().'/'.$dir;
|
||||
exec(sprintf('cd "%s";php %s /cron/%s > /dev/null 2>/dev/null &',$dir,$file,$job));
|
||||
} else {
|
||||
$start=microtime(TRUE);
|
||||
call_user_func_array($func,array($f3));
|
||||
if ($this->log) {
|
||||
$log=new Log('cron.log');
|
||||
$log->write(sprintf(self::L_Execution,$job,microtime(TRUE)-$start));
|
||||
}
|
||||
exec(sprintf('cd "%s";%s %s /cron/%s > /dev/null 2>/dev/null &',$dir,$this->binary,$file,$job));
|
||||
return FALSE;
|
||||
}
|
||||
$start=microtime(TRUE);
|
||||
call_user_func_array($func,array($f3));
|
||||
if ($this->log) {
|
||||
$log=new Log('cron.log');
|
||||
$log->write(sprintf(self::L_Execution,$job,microtime(TRUE)-$start));
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run scheduler, i.e executes all due jobs at a given time
|
||||
* @param int $time
|
||||
* @param bool $async
|
||||
* @return array List of executed jobs
|
||||
*/
|
||||
function run($time=NULL,$async=TRUE) {
|
||||
if (!isset($time))
|
||||
$time=time();
|
||||
$exec=array();
|
||||
foreach(array_keys($this->jobs) as $job)
|
||||
if ($this->isDue($job,$time))
|
||||
$this->execute($job,$async);
|
||||
$exec[$job]=$this->execute($job,$async);
|
||||
return $exec;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,16 +149,18 @@ class Cron extends \Prefab {
|
||||
* @param array $params
|
||||
*/
|
||||
function route($f3,$params) {
|
||||
|
||||
if (PHP_SAPI=='cli'?!$this->cli:!$this->web)
|
||||
if (PHP_SAPI!='cli' && !$this->web)
|
||||
$f3->error(404);
|
||||
if (isset($params['job']))
|
||||
$this->execute($params['job'],FALSE);
|
||||
else{
|
||||
// IMPORTANT! async does not work on Windows
|
||||
// -> my development environment is Windows :((
|
||||
$async = FALSE;
|
||||
$this->run(NULL, $async);
|
||||
$exec=isset($params['job'])?
|
||||
array($params['job']=>$this->execute($params['job'],FALSE)):
|
||||
$this->run();
|
||||
if (!$this->silent) {
|
||||
if (PHP_SAPI!='cli')
|
||||
header('Content-Type: text/plain');
|
||||
if (!$exec)
|
||||
die('Nothing to do');
|
||||
foreach($exec as $job=>$ok)
|
||||
echo sprintf('%s [%s]',$job,$ok?'OK':'async')."\r\n";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,8 +215,10 @@ class Cron extends \Prefab {
|
||||
|
||||
//! Read-only public properties
|
||||
function __get($name) {
|
||||
if (in_array($name,array('jobs','async','presets')))
|
||||
if (in_array($name,array('binary','jobs','presets')))
|
||||
return $this->$name;
|
||||
if ($name=='clipath') // alias for script [deprecated]
|
||||
return $this->script;
|
||||
trigger_error(sprintf(self::E_Undefined,__CLASS__,$name));
|
||||
}
|
||||
|
||||
@@ -204,13 +226,13 @@ class Cron extends \Prefab {
|
||||
function __construct() {
|
||||
$f3=\Base::instance();
|
||||
$config=(array)$f3->get('CRON');
|
||||
|
||||
foreach(array('log','cli','web') as $k)
|
||||
if (isset($config[$k]))
|
||||
$this->$k=(bool)$config[$k];
|
||||
foreach(array('clipath') as $k)
|
||||
if (isset($config[$k]))
|
||||
$this->$k=(string)$config[$k];
|
||||
foreach(array('log','web','script','silent') as $k)
|
||||
if (isset($config[$k])) {
|
||||
settype($config[$k],gettype($this->$k));
|
||||
$this->$k=$config[$k];
|
||||
}
|
||||
if (isset($config['binary']))
|
||||
$this->binary($config['binary']);
|
||||
if (isset($config['jobs']))
|
||||
foreach($config['jobs'] as $job=>$arr) {
|
||||
$handler=array_shift($arr);
|
||||
@@ -219,10 +241,11 @@ class Cron extends \Prefab {
|
||||
if (isset($config['presets']))
|
||||
foreach($config['presets'] as $name=>$expr)
|
||||
$this->preset($name,is_array($expr)?implode(',',$expr):$expr);
|
||||
if (function_exists('exec') && exec('php -r "echo 1+3;"')=='4')
|
||||
$this->async=TRUE;
|
||||
if ($this->cli || $this->web)
|
||||
$f3->route(array('GET /cron','GET /cron/@job'),array($this,'route'));
|
||||
if (!isset($this->binary))
|
||||
foreach(array('php','php-cli') as $path) // try to guess the binary name
|
||||
if ($this->binary($path))
|
||||
break;
|
||||
$f3->route(array('GET /cron','GET /cron/@job'),array($this,'route'));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,7 +18,7 @@
|
||||
* https://github.com/ikkez/F3-Sugar/
|
||||
*
|
||||
* @package DB
|
||||
* @version 1.4.0
|
||||
* @version 1.4.1-dev
|
||||
* @since 24.04.2012
|
||||
* @date 04.06.2015
|
||||
*/
|
||||
@@ -111,7 +111,8 @@ class Cortex extends Cursor {
|
||||
$this->primary = '_id';
|
||||
elseif (!$this->primary)
|
||||
$this->primary = 'id';
|
||||
if (!$this->table && !$this->fluid)
|
||||
$this->table = $this->getTable();
|
||||
if (!$this->table)
|
||||
trigger_error(self::E_NO_TABLE);
|
||||
$this->ttl = $ttl ?: 60;
|
||||
if (!$this->rel_ttl)
|
||||
@@ -119,7 +120,7 @@ class Cortex extends Cursor {
|
||||
$this->_ttl = $this->rel_ttl ?: 0;
|
||||
if (static::$init == TRUE) return;
|
||||
if ($this->fluid)
|
||||
static::setup($this->db,$this->getTable(),array());
|
||||
static::setup($this->db,$this->table,array());
|
||||
$this->initMapper();
|
||||
}
|
||||
|
||||
@@ -264,7 +265,7 @@ class Cortex extends Cursor {
|
||||
*/
|
||||
public function getTable()
|
||||
{
|
||||
if (!$this->table && $this->fluid)
|
||||
if (!$this->table && ($this->fluid || static::$init))
|
||||
$this->table = strtolower(get_class($this));
|
||||
return $this->table;
|
||||
}
|
||||
@@ -305,30 +306,30 @@ class Cortex extends Cursor {
|
||||
// check m:m relation
|
||||
if (array_key_exists('has-many', $field)) {
|
||||
// m:m relation conf [class,to-key,from-key]
|
||||
if (!is_array($relConf = $field['has-many'])) {
|
||||
unset($fields[$key]);
|
||||
continue;
|
||||
}
|
||||
$rel = $relConf[0]::resolveConfiguration();
|
||||
// check if foreign conf matches m:m
|
||||
if (array_key_exists($relConf[1],$rel['fieldConf'])
|
||||
&& !is_null($rel['fieldConf'][$relConf[1]])
|
||||
&& $relConf['hasRel'] == 'has-many') {
|
||||
// compute mm table name
|
||||
$mmTable = isset($relConf[2]) ? $relConf[2] :
|
||||
static::getMMTableName(
|
||||
$rel['table'], $relConf[1], $table, $key,
|
||||
$rel['fieldConf'][$relConf[1]]['has-many']);
|
||||
if (!in_array($mmTable,$schema->getTables())) {
|
||||
$mmt = $schema->createTable($mmTable);
|
||||
$mmt->addColumn($relConf[1])->type($relConf['relFieldType']);
|
||||
$mmt->addColumn($key)->type($field['type']);
|
||||
$index = array($relConf[1],$key);
|
||||
sort($index);
|
||||
$mmt->addIndex($index);
|
||||
$mmt->build();
|
||||
if (is_array($relConf = $field['has-many'])) {
|
||||
$rel = $relConf[0]::resolveConfiguration();
|
||||
// check if foreign conf matches m:m
|
||||
if (array_key_exists($relConf[1],$rel['fieldConf'])
|
||||
&& !is_null($rel['fieldConf'][$relConf[1]])
|
||||
&& $relConf['hasRel'] == 'has-many') {
|
||||
// compute mm table name
|
||||
$mmTable = isset($relConf[2]) ? $relConf[2] :
|
||||
static::getMMTableName(
|
||||
$rel['table'], $relConf[1], $table, $key,
|
||||
$rel['fieldConf'][$relConf[1]]['has-many']);
|
||||
if (!in_array($mmTable,$schema->getTables())) {
|
||||
$mmt = $schema->createTable($mmTable);
|
||||
$mmt->addColumn($relConf[1])->type($relConf['relFieldType']);
|
||||
$mmt->addColumn($key)->type($field['type']);
|
||||
$index = array($relConf[1],$key);
|
||||
sort($index);
|
||||
$mmt->addIndex($index);
|
||||
$mmt->build();
|
||||
}
|
||||
}
|
||||
}
|
||||
unset($fields[$key]);
|
||||
continue;
|
||||
}
|
||||
// skip virtual fields with no type
|
||||
if (!array_key_exists('type', $field)) {
|
||||
@@ -468,7 +469,7 @@ class Cortex extends Cursor {
|
||||
// compute mm table name
|
||||
$mmTable = isset($conf[2]) ? $conf[2] :
|
||||
static::getMMTableName($conf['relTable'],
|
||||
$conf['relField'], $this->getTable(), $key, $fConf);
|
||||
$conf['relField'], $this->table, $key, $fConf);
|
||||
$this->fieldConf[$key]['has-many']['refTable'] = $mmTable;
|
||||
} else
|
||||
$mmTable = $conf['refTable'];
|
||||
@@ -697,7 +698,7 @@ class Cortex extends Cursor {
|
||||
$fromConf[1] = $rel['primary'];
|
||||
$hasJoin[] = $this->_hasJoin_sql($key,$rel['table'],$hasCond,$filter,$options);
|
||||
} elseif ($result = $this->_hasRefsIn($key,$has_filter,$has_options,$ttl))
|
||||
$addToFilter = array($key.' IN ?', $result);
|
||||
$addToFilter = array($key.' IN ?', $result);
|
||||
break;
|
||||
default:
|
||||
trigger_error(self::E_HAS_COND);
|
||||
@@ -711,7 +712,7 @@ class Cortex extends Cursor {
|
||||
$filter[0] .= ' and ';
|
||||
$cond = array_shift($addToFilter);
|
||||
if ($this->dbsType=='sql')
|
||||
$cond = $this->_sql_quoteCondition($cond,$this->db->quotekey($this->getTable()));
|
||||
$cond = $this->_sql_quoteCondition($cond,$this->db->quotekey($this->table));
|
||||
$filter[0] .= '('.$cond.')';
|
||||
$filter = array_merge($filter, $addToFilter);
|
||||
}
|
||||
@@ -962,7 +963,7 @@ class Cortex extends Cursor {
|
||||
$filter = array($whereClause);
|
||||
elseif (!empty($filter[0]))
|
||||
$filter[0] = '('.$this->_sql_quoteCondition($filter[0],
|
||||
$this->db->quotekey($this->table)).') and '.$whereClause;
|
||||
$this->db->quotekey($this->table)).') and '.$whereClause;
|
||||
$filter = array_merge($filter, $cond[0]);
|
||||
}
|
||||
if ($cond[1] && isset($cond[1]['group'])) {
|
||||
@@ -1024,14 +1025,29 @@ class Cortex extends Cursor {
|
||||
{
|
||||
if (array_key_exists($key, $this->relFilter) &&
|
||||
!empty($this->relFilter[$key][0]))
|
||||
{
|
||||
$filter = $this->relFilter[$key][0];
|
||||
$crit[0] .= ' and '.array_shift($filter);
|
||||
$crit = array_merge($crit, $filter);
|
||||
}
|
||||
$crit=$this->mergeFilter(array($this->relFilter[$key][0],$crit));
|
||||
return $crit;
|
||||
}
|
||||
|
||||
/**
|
||||
* merge multiple filters
|
||||
* @param $filters
|
||||
* @param string $glue
|
||||
* @return array
|
||||
*/
|
||||
public function mergeFilter($filters,$glue='and') {
|
||||
$crit = array();
|
||||
$params = array();
|
||||
if ($filters) {
|
||||
foreach($filters as $filter) {
|
||||
$crit[] = array_shift($filter);
|
||||
$params = array_merge($params,$filter);
|
||||
}
|
||||
array_unshift($params,'( '.implode(' ) '.$glue.' ( ',$crit).' )');
|
||||
}
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns the option condition for a relation filter, if defined
|
||||
* @param string $key
|
||||
@@ -1047,12 +1063,14 @@ class Cortex extends Cursor {
|
||||
/**
|
||||
* Delete object/s and reset ORM
|
||||
* @param $filter
|
||||
* @return void
|
||||
* @return bool
|
||||
*/
|
||||
public function erase($filter = null)
|
||||
{
|
||||
$filter = $this->queryParser->prepareFilter($filter, $this->dbsType);
|
||||
if (!$filter && $this->emit('beforeerase')!==false) {
|
||||
if (!$filter) {
|
||||
if ($this->emit('beforeerase')===false)
|
||||
return false;
|
||||
if ($this->fieldConf) {
|
||||
foreach($this->fieldConf as $field => $conf)
|
||||
if (isset($conf['has-many']) &&
|
||||
@@ -1064,6 +1082,7 @@ class Cortex extends Cursor {
|
||||
$this->emit('aftererase');
|
||||
} elseif($filter)
|
||||
$this->mapper->erase($filter);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1072,6 +1091,14 @@ class Cortex extends Cursor {
|
||||
**/
|
||||
function save()
|
||||
{
|
||||
// update changed collections
|
||||
$fields = $this->fieldConf;
|
||||
if ($fields)
|
||||
foreach($fields as $key=>$conf)
|
||||
if (!empty($this->fieldsCache[$key]) && $this->fieldsCache[$key] instanceof CortexCollection
|
||||
&& $this->fieldsCache[$key]->hasChanged())
|
||||
$this->set($key,$this->fieldsCache[$key]->getAll('_id',true));
|
||||
// perform event & save operations
|
||||
if ($new = $this->dry()) {
|
||||
if ($this->emit('beforeinsert')===false)
|
||||
return false;
|
||||
@@ -1081,14 +1108,6 @@ class Cortex extends Cursor {
|
||||
return false;
|
||||
$result=$this->update();
|
||||
}
|
||||
// update changed collections
|
||||
$fields = $this->fieldConf;
|
||||
if ($fields)
|
||||
foreach($fields as $key=>$conf)
|
||||
if (!empty($this->fieldsCache[$key]) && $this->fieldsCache[$key] instanceof CortexCollection
|
||||
&& $this->fieldsCache[$key]->hasChanged())
|
||||
$this->set($key,$this->fieldsCache[$key]->getAll('_id',true));
|
||||
|
||||
// m:m save cascade
|
||||
if (!empty($this->saveCsd)) {
|
||||
foreach($this->saveCsd as $key => $val) {
|
||||
@@ -1164,12 +1183,12 @@ class Cortex extends Cursor {
|
||||
trigger_error('Cannot add direct relational counter.');
|
||||
} elseif($this->fieldConf[$key]['relType'] == 'has-many') {
|
||||
$relConf=$this->fieldConf[$key]['has-many'];
|
||||
if ($relConf['hasRel']=='has-many') {
|
||||
if ($relConf['hasRel']=='has-many') {
|
||||
// many-to-many
|
||||
if ($this->dbsType == 'sql') {
|
||||
$mmTable = $this->mmTable($relConf,$key);
|
||||
$filter = array($this->db->quotekey($mmTable).'.'.$this->db->quotekey($relConf['relField'])
|
||||
.' = '.$this->db->quotekey($this->getTable()).'.'.$this->db->quotekey($this->primary));
|
||||
.' = '.$this->db->quotekey($this->table).'.'.$this->db->quotekey($this->primary));
|
||||
$from=$mmTable;
|
||||
if (array_key_exists($key, $this->relFilter) &&
|
||||
!empty($this->relFilter[$key][0])) {
|
||||
@@ -1196,7 +1215,7 @@ class Cortex extends Cursor {
|
||||
$fKey=$this->db->quotekey($fConf['primary']);
|
||||
$rKey=$this->db->quotekey($relConf[1]);
|
||||
$pKey=$this->db->quotekey($this->primary);
|
||||
$table=$this->db->quotekey($this->getTable());
|
||||
$table=$this->db->quotekey($this->table);
|
||||
$crit = $fTable.'.'.$rKey.' = '.$table.'.'.$pKey;
|
||||
$filter = $this->mergeWithRelFilter($key,array($crit));
|
||||
$filter = $this->queryParser->prepareFilter($filter,$this->dbsType,$this->fieldConf);
|
||||
@@ -1204,7 +1223,7 @@ class Cortex extends Cursor {
|
||||
if (count($filter)>0)
|
||||
$this->preBinds+=$filter;
|
||||
$this->set('count_'.$key,'(select count('.$fTable.'.'.$fKey.') from '.$fTable.' where '.
|
||||
$crit.' group by '.$fTable.'.'.$rKey.')');
|
||||
$crit.' group by '.$fTable.'.'.$rKey.')');
|
||||
} else {
|
||||
// count rel
|
||||
$this->countFields[]=$key;
|
||||
@@ -1240,7 +1259,7 @@ class Cortex extends Cursor {
|
||||
&& isset($this->fieldConf[$key]['type'])) {
|
||||
$type = $this->fieldConf[$key]['type'];
|
||||
$date = ($this->dbsType=='sql' && preg_match('/mssql|sybase|dblib|odbc|sqlsrv/',
|
||||
$this->db->driver())) ? 'Ymd' : 'Y-m-d';
|
||||
$this->db->driver())) ? 'Ymd' : 'Y-m-d';
|
||||
if ($type == Schema::DT_DATETIME || Schema::DT_TIMESTAMP)
|
||||
$this->set($key,date($date.' H:i:s'));
|
||||
elseif ($type == Schema::DT_DATE)
|
||||
@@ -1307,6 +1326,7 @@ class Cortex extends Cursor {
|
||||
$val = $this->emit('set_'.$key, $val);
|
||||
$val = $this->getForeignKeysArray($val,'_id',$key);
|
||||
$this->saveCsd[$key] = $val; // array of keys
|
||||
$this->fieldsCache[$key] = $val;
|
||||
return $val;
|
||||
} elseif ($relConf['hasRel'] == 'belongs-to-one') {
|
||||
// TODO: many-to-one, bidirectional, inverse way
|
||||
@@ -1495,7 +1515,8 @@ class Cortex extends Cursor {
|
||||
trigger_error(sprintf(self::E_REL_CONF_INC, $key));
|
||||
$rel = $this->getRelInstance($fromConf[0],null,$key,true);
|
||||
$relFieldConf = $rel->getFieldConfiguration();
|
||||
$relType = key($relFieldConf[$fromConf[1]]);
|
||||
$relType = isset($relFieldConf[$fromConf[1]]['belongs-to-one']) ?
|
||||
'belongs-to-one' : 'has-many';
|
||||
// one-to-*, bidirectional, inverse way
|
||||
if ($relType == 'belongs-to-one') {
|
||||
$toConf = $relFieldConf[$fromConf[1]]['belongs-to-one'];
|
||||
@@ -1810,7 +1831,7 @@ class Cortex extends Cursor {
|
||||
$rd = isset($rel_depths[$key]) ? $rel_depths[$key] : $rel_depths['*'];
|
||||
if ((is_array($rd) || $rd >= 0) && $type=preg_grep('/[belongs|has]-(to-)*[one|many]/',
|
||||
array_keys($this->fieldConf[$key]))) {
|
||||
$relType=$type[0];
|
||||
$relType=current($type);
|
||||
// cast relations
|
||||
$val = (($relType == 'belongs-to-one' || $relType == 'belongs-to-many')
|
||||
&& !$mp->exists($key)) ? NULL : $mp->get($key);
|
||||
@@ -1852,7 +1873,7 @@ class Cortex extends Cursor {
|
||||
|
||||
/**
|
||||
* cast a related collection of mappers
|
||||
* @param string|array $key array of mapper objects, or field name
|
||||
* @param string $key field name
|
||||
* @param int $rel_depths depths to resolve relations
|
||||
* @return array array of associative arrays
|
||||
*/
|
||||
@@ -1991,7 +2012,7 @@ class Cortex extends Cursor {
|
||||
function exists($key, $relField = false) {
|
||||
if (!$this->dry() && $key == '_id') return true;
|
||||
return $this->mapper->exists($key) ||
|
||||
($relField && isset($this->fieldConf[$key]['relType']));
|
||||
($relField && isset($this->fieldConf[$key]['relType']));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2131,7 +2152,10 @@ class CortexQueryParser extends \Prefab {
|
||||
}
|
||||
unset($part);
|
||||
}
|
||||
array_unshift($ncond, implode(' ', $parts));
|
||||
array_unshift($ncond, array_reduce($parts,function($out,$part){
|
||||
return $out.((!$out||in_array($part,array('(',')'))
|
||||
||preg_match('/\($/',$out))?'':' ').$part;
|
||||
},''));
|
||||
break;
|
||||
default:
|
||||
trigger_error(self::E_ENGINEERROR);
|
||||
@@ -2202,6 +2226,7 @@ class CortexQueryParser extends \Prefab {
|
||||
if (is_int(strpos($part, '?'))) {
|
||||
$val = array_shift($args);
|
||||
preg_match('/(@\w+)/i', $part, $match);
|
||||
$skipVal=false;
|
||||
// find like operator
|
||||
if (is_int(strpos($upart = strtoupper($part), ' @LIKE '))) {
|
||||
if ($not = is_int($npos = strpos($upart, '@NOT')))
|
||||
@@ -2209,16 +2234,18 @@ class CortexQueryParser extends \Prefab {
|
||||
$val = $this->_likeValueToRegEx($val);
|
||||
$part = ($not ? '!' : '').'preg_match(?,'.$match[0].')';
|
||||
} // find IN operator
|
||||
else if (is_int($pos = strpos($upart, ' @IN '))) {
|
||||
elseif (is_int($pos = strpos($upart, ' @IN '))) {
|
||||
if ($not = is_int($npos = strpos($upart, '@NOT')))
|
||||
$pos = $npos;
|
||||
$part = ($not ? '!' : '').'in_array('.substr($part, 0, $pos).
|
||||
',array(\''.implode('\',\'', $val).'\'))';
|
||||
unset($val);
|
||||
$skipVal=true;
|
||||
}
|
||||
// add existence check
|
||||
$part = '(isset('.$match[0].') && '.$part.')';
|
||||
if (isset($val))
|
||||
$part = ($val===null && !$skipVal)
|
||||
? '(array_key_exists(\''.ltrim($match[0],'@').'\',$_row) && '.$part.')'
|
||||
: '(isset('.$match[0].') && '.$part.')';
|
||||
if (!$skipVal)
|
||||
$ncond[] = $val;
|
||||
} elseif ($count >= 1) {
|
||||
// field comparison
|
||||
@@ -2331,7 +2358,7 @@ class CortexQueryParser extends \Prefab {
|
||||
$opr = str_replace(array('<>', '<', '>', '!', '='),
|
||||
array('$ne', '$lt', '$gt', '$n', 'e'), $match[0]);
|
||||
$var = array($opr => (strtolower($var) == 'null') ? null :
|
||||
(is_object($var) ? $var : (is_numeric($var) ? $var + 0 : $var)));
|
||||
(is_object($var) ? $var : (is_numeric($var) ? $var + 0 : $var)));
|
||||
}
|
||||
return array($key => $var);
|
||||
}
|
||||
@@ -2347,14 +2374,14 @@ class CortexQueryParser extends \Prefab {
|
||||
$lC = substr($var, -1, 1);
|
||||
// %var% -> /var/
|
||||
if ($var[0] == '%' && $lC == '%')
|
||||
$var = '/'.substr($var, 1, -1).'/';
|
||||
$var = substr($var, 1, -1);
|
||||
// var% -> /^var/
|
||||
elseif ($lC == '%')
|
||||
$var = '/^'.substr($var, 0, -1).'/';
|
||||
$var = '^'.substr($var, 0, -1);
|
||||
// %var -> /var$/
|
||||
elseif ($var[0] == '%')
|
||||
$var = '/'.substr($var, 1).'$/';
|
||||
return $var;
|
||||
$var = substr($var, 1).'$';
|
||||
return '/'.$var.'/iu';
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2513,11 +2540,12 @@ class CortexCollection extends \ArrayIterator {
|
||||
{
|
||||
$out = array();
|
||||
foreach ($this->getArrayCopy() as $model) {
|
||||
if ($model->exists($prop,true)) {
|
||||
if ($model instanceof Cortex && $model->exists($prop,true)) {
|
||||
$val = $model->get($prop, $raw);
|
||||
if (!empty($val))
|
||||
$out[] = $val;
|
||||
}
|
||||
} elseif($raw)
|
||||
$out[] = $model;
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
@@ -13,12 +13,12 @@
|
||||
* | | < | <| -__|-- __|
|
||||
* |__|__|__||__|__|_____|_____|
|
||||
*
|
||||
* Copyright (c) 2014 by ikkez
|
||||
* Copyright (c) 2015 by ikkez
|
||||
* Christian Knuth <ikkez0n3@gmail.com>
|
||||
* https://github.com/ikkez/F3-Sugar/
|
||||
*
|
||||
* @package DB
|
||||
* @version 2.1.1
|
||||
* @version 2.2.0-dev
|
||||
**/
|
||||
|
||||
|
||||
@@ -30,76 +30,86 @@ class Schema extends DB_Utils {
|
||||
|
||||
public
|
||||
$dataTypes = array(
|
||||
'BOOLEAN' => array('mysql|sqlite2?|pgsql' => 'BOOLEAN',
|
||||
'mssql|sybase|dblib|odbc|sqlsrv' => 'bit',
|
||||
'ibm' => 'numeric(1,0)',
|
||||
),
|
||||
'INT1' => array('mysql' => 'TINYINT UNSIGNED',
|
||||
'sqlite2?' => 'integer',
|
||||
'mssql|sybase|dblib|odbc|sqlsrv' => 'tinyint',
|
||||
'pgsql|ibm' => 'smallint',
|
||||
),
|
||||
'INT2' => array('mysql' => 'SMALLINT',
|
||||
'sqlite2?' => 'integer',
|
||||
'pgsql|ibm|mssql|sybase|dblib|odbc|sqlsrv' => 'smallint',
|
||||
),
|
||||
'INT4' => array('sqlite2?|pgsql|sybase|odbc|sqlsrv|imb' => 'integer',
|
||||
'mysql|mssql|dblib' => 'int',
|
||||
),
|
||||
'INT8' => array('sqlite2?' => 'integer',
|
||||
'pgsql|mysql|mssql|sybase|dblib|odbc|sqlsrv|imb' => 'bigint',
|
||||
),
|
||||
'FLOAT' => array('mysql|sqlite2?' => 'FLOAT',
|
||||
'pgsql' => 'double precision',
|
||||
'mssql|sybase|dblib|odbc|sqlsrv' => 'float',
|
||||
'imb' => 'decfloat'
|
||||
),
|
||||
'DOUBLE' => array('mysql|sqlite2?|ibm' => 'DOUBLE',
|
||||
'pgsql|sybase|odbc|sqlsrv' => 'double precision',
|
||||
'mssql|dblib' => 'decimal',
|
||||
),
|
||||
'VARCHAR128' => array('mysql|pgsql|sqlite2?|ibm|mssql|sybase|dblib|odbc|sqlsrv' => 'varchar(128)',
|
||||
),
|
||||
'VARCHAR256' => array('mysql|pgsql|sqlite2?|ibm|mssql|sybase|dblib|odbc|sqlsrv' => 'varchar(255)',
|
||||
),
|
||||
'VARCHAR512' => array('mysql|pgsql|sqlite2?|ibm|mssql|sybase|dblib|odbc|sqlsrv' => 'varchar(512)',
|
||||
),
|
||||
'TEXT' => array('mysql|sqlite2?|pgsql|mssql' => 'text',
|
||||
'sybase|dblib|odbc|sqlsrv' => 'nvarchar(max)',
|
||||
'ibm' => 'BLOB SUB_TYPE TEXT',
|
||||
),
|
||||
'LONGTEXT' => array('mysql' => 'LONGTEXT',
|
||||
'sqlite2?|pgsql|mssql' => 'text',
|
||||
'sybase|dblib|odbc|sqlsrv' => 'nvarchar(max)',
|
||||
'ibm' => 'CLOB(2000000000)',
|
||||
),
|
||||
'DATE' => array('mysql|sqlite2?|pgsql|mssql|sybase|dblib|odbc|sqlsrv|ibm' => 'date',
|
||||
),
|
||||
'DATETIME' => array('pgsql' => 'timestamp without time zone',
|
||||
'mysql|sqlite2?|mssql|sybase|dblib|odbc|sqlsrv' => 'datetime',
|
||||
'ibm' => 'timestamp',
|
||||
),
|
||||
'TIMESTAMP' => array('mysql|ibm' => 'timestamp',
|
||||
'pgsql|odbc' => 'timestamp without time zone',
|
||||
'sqlite2?|mssql|sybase|dblib|sqlsrv'=>'DATETIME',
|
||||
),
|
||||
'BLOB' => array('mysql|odbc|sqlite2?|ibm' => 'blob',
|
||||
'pgsql' => 'bytea',
|
||||
'mssql|sybase|dblib' => 'image',
|
||||
'sqlsrv' => 'varbinary(max)',
|
||||
),
|
||||
'BOOLEAN' => array('mysql' => 'tinyint(1)',
|
||||
'sqlite2?|pgsql' => 'BOOLEAN',
|
||||
'mssql|sybase|dblib|odbc|sqlsrv' => 'bit',
|
||||
'ibm' => 'numeric(1,0)',
|
||||
),
|
||||
'INT1' => array('mysql' => 'tinyint(4)',
|
||||
'sqlite2?' => 'integer(4)',
|
||||
'mssql|sybase|dblib|odbc|sqlsrv' => 'tinyint',
|
||||
'pgsql|ibm' => 'smallint',
|
||||
),
|
||||
'INT2' => array('mysql' => 'smallint(6)',
|
||||
'sqlite2?' => 'integer(6)',
|
||||
'pgsql|ibm|mssql|sybase|dblib|odbc|sqlsrv' => 'smallint',
|
||||
),
|
||||
'INT4' => array('sqlite2?' => 'integer(11)',
|
||||
'pgsql|imb' => 'integer',
|
||||
'mysql' => 'int(11)',
|
||||
'mssql|dblib|sybase|odbc|sqlsrv' => 'int',
|
||||
),
|
||||
'INT8' => array('sqlite2?' => 'integer(20)',
|
||||
'pgsql|mssql|sybase|dblib|odbc|sqlsrv|imb' => 'bigint',
|
||||
'mysql' => 'bigint(20)',
|
||||
),
|
||||
'FLOAT' => array('mysql|sqlite2?' => 'FLOAT',
|
||||
'pgsql' => 'double precision',
|
||||
'mssql|sybase|dblib|odbc|sqlsrv' => 'float',
|
||||
'imb' => 'decfloat'
|
||||
),
|
||||
'DOUBLE' => array('mysql|sqlite2?|ibm' => 'DOUBLE',
|
||||
'pgsql' => 'double precision',
|
||||
'mssql|dblib|sybase|odbc|sqlsrv' => 'decimal',
|
||||
),
|
||||
'VARCHAR128' => array('mysql|sqlite2?|ibm|mssql|sybase|dblib|odbc|sqlsrv' => 'varchar(128)',
|
||||
'pgsql' => 'character varying(128)',
|
||||
),
|
||||
'VARCHAR256' => array('mysql|sqlite2?|ibm|mssql|sybase|dblib|odbc|sqlsrv' => 'varchar(255)',
|
||||
'pgsql' => 'character varying(255)',
|
||||
),
|
||||
'VARCHAR512' => array('mysql|sqlite2?|ibm|mssql|sybase|dblib|odbc|sqlsrv' => 'varchar(512)',
|
||||
'pgsql' => 'character varying(512)',
|
||||
),
|
||||
'TEXT' => array('mysql|sqlite2?|pgsql|mssql' => 'text',
|
||||
'sybase|dblib|odbc|sqlsrv' => 'nvarchar(max)',
|
||||
'ibm' => 'BLOB SUB_TYPE TEXT',
|
||||
),
|
||||
'LONGTEXT' => array('mysql' => 'LONGTEXT',
|
||||
'sqlite2?|pgsql|mssql' => 'text',
|
||||
'sybase|dblib|odbc|sqlsrv' => 'nvarchar(max)',
|
||||
'ibm' => 'CLOB(2000000000)',
|
||||
),
|
||||
'DATE' => array('mysql|sqlite2?|pgsql|mssql|sybase|dblib|odbc|sqlsrv|ibm' => 'date',
|
||||
),
|
||||
'DATETIME' => array('pgsql' => 'timestamp without time zone',
|
||||
'mysql|sqlite2?|mssql|sybase|dblib|odbc|sqlsrv' => 'datetime',
|
||||
'ibm' => 'timestamp',
|
||||
),
|
||||
'TIMESTAMP' => array('mysql|ibm' => 'timestamp',
|
||||
'pgsql|odbc' => 'timestamp without time zone',
|
||||
'sqlite2?|mssql|sybase|dblib|sqlsrv'=>'DATETIME',
|
||||
),
|
||||
'BLOB' => array('mysql|odbc|sqlite2?|ibm' => 'blob',
|
||||
'pgsql' => 'bytea',
|
||||
'mssql|sybase|dblib' => 'image',
|
||||
'sqlsrv' => 'varbinary(max)',
|
||||
),
|
||||
),
|
||||
$defaultTypes = array(
|
||||
'CUR_STAMP' => array('mysql' => 'CURRENT_TIMESTAMP',
|
||||
'mssql|sybase|dblib|odbc|sqlsrv' => 'getdate()',
|
||||
'pgsql' => 'LOCALTIMESTAMP(0)',
|
||||
'sqlite2?' => "(datetime('now','localtime'))",
|
||||
),
|
||||
);
|
||||
'CUR_STAMP' => array('mysql' => 'CURRENT_TIMESTAMP',
|
||||
'mssql|sybase|dblib|odbc|sqlsrv' => 'getdate()',
|
||||
'pgsql' => 'LOCALTIMESTAMP(0)',
|
||||
'sqlite2?' => "(datetime('now','localtime'))",
|
||||
),
|
||||
);
|
||||
|
||||
public
|
||||
$name;
|
||||
|
||||
public static
|
||||
$strict = FALSE;
|
||||
|
||||
/** @var \Base */
|
||||
protected $fw;
|
||||
|
||||
@@ -257,12 +267,47 @@ class Schema extends DB_Utils {
|
||||
return ($exec) ? $this->db->exec($query) : $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* clear a table
|
||||
* @param $name
|
||||
* @param bool $exec
|
||||
* @return array|bool|FALSE|int|string
|
||||
*/
|
||||
public function truncateTable($name, $exec = true) {
|
||||
if (is_object($name) && $name instanceof TableBuilder)
|
||||
$name = $name->name;
|
||||
$cmd = array(
|
||||
'mysql|ibm|pgsql|sybase|dblib|mssql|sqlsrv|odbc' =>
|
||||
'TRUNCATE TABLE '.$this->db->quotekey($name).';',
|
||||
'sqlite2?' => array(
|
||||
'DELETE FROM '.$this->db->quotekey($name).';',
|
||||
'UPDATE SQLITE_SEQUENCE SET seq = 0 WHERE name = '.$this->db->quotekey($name).';',
|
||||
),
|
||||
);
|
||||
$query = $this->findQuery($cmd);
|
||||
return ($exec) ? $this->db->exec($query) : $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* check if a data type is compatible with a given column definition
|
||||
* @param string $colType (i.e: BOOLEAN)
|
||||
* @param string $colDef (i.e: tinyint(1))
|
||||
* @return int
|
||||
*/
|
||||
public function isCompatible($colType,$colDef) {
|
||||
$raw_type=$this->findQuery($this->dataTypes[strtoupper($colType)]);
|
||||
preg_match_all('/(?P<type>\w+)($|\((?P<length>(\d+|(.*)))\))/', $raw_type, $match);
|
||||
return (bool) preg_match_all('/'.preg_quote($match['type'][0]).'($|\('.
|
||||
preg_quote($match['length'][0]).'\))/i',$colDef);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class TableBuilder extends DB_Utils {
|
||||
|
||||
protected $columns, $pkeys, $queries, $increments, $rebuild_cmd, $suppress;
|
||||
public $name, $schema;
|
||||
public $name;
|
||||
/** @var Schema */
|
||||
public $schema;
|
||||
|
||||
const
|
||||
TEXT_NoDefaultForTEXT = "Column `%s` of type TEXT can't have a default value.",
|
||||
@@ -499,6 +544,7 @@ class TableModifier extends TableBuilder {
|
||||
*/
|
||||
public function build($exec = TRUE)
|
||||
{
|
||||
|
||||
// check if table exists
|
||||
if (!in_array($this->name, $this->schema->getTables()))
|
||||
trigger_error(sprintf(self::TEXT_TableNotExisting, $this->name));
|
||||
@@ -511,6 +557,7 @@ class TableModifier extends TableBuilder {
|
||||
$this->queries = array();
|
||||
// add new columns
|
||||
foreach ($this->columns as $cname => $column) {
|
||||
/** @var Column $column */
|
||||
// not nullable fields should have a default value, when altering a table
|
||||
if ($column->default === false && $column->nullable === false) {
|
||||
trigger_error(sprintf(self::TEXT_NotNullFieldNeedsDefault, $column->name));
|
||||
@@ -573,7 +620,7 @@ class TableModifier extends TableBuilder {
|
||||
$after[$column->after][] = $cname;
|
||||
// find rename commands
|
||||
$rename = (!empty($this->rebuild_cmd) && array_key_exists('rename',$this->rebuild_cmd))
|
||||
? $this->rebuild_cmd['rename'] : array();
|
||||
? $this->rebuild_cmd['rename'] : array();
|
||||
// get primary-key fields
|
||||
foreach ($existing_columns as $key => $col)
|
||||
if ($col['pkey'])
|
||||
@@ -617,7 +664,7 @@ class TableModifier extends TableBuilder {
|
||||
unset($indexes[$col]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// create new table
|
||||
$oname = $this->name;
|
||||
$this->queries[] = $this->rename($oname.'_temp', false);
|
||||
@@ -627,8 +674,13 @@ class TableModifier extends TableBuilder {
|
||||
$colName = array_key_exists($name, $rename) ? $rename[$name] : $name;
|
||||
// update column datatype
|
||||
if (array_key_exists('update',$this->rebuild_cmd)
|
||||
&& in_array($name,array_keys($this->rebuild_cmd['update'])))
|
||||
$col['type']=$this->rebuild_cmd['update'][$name];
|
||||
&& in_array($name,array_keys($this->rebuild_cmd['update']))) {
|
||||
$cdat = $this->rebuild_cmd['update'][$name];
|
||||
if ($cdat instanceof Column)
|
||||
$col = $cdat->getColumnArray();
|
||||
else
|
||||
$col['type'] = $cdat;
|
||||
}
|
||||
$newTable->addColumn($colName, $col)->passThrough();
|
||||
// add new fields with after flag
|
||||
if (array_key_exists($name,$after))
|
||||
@@ -644,7 +696,7 @@ class TableModifier extends TableBuilder {
|
||||
// add existing indexes
|
||||
foreach (array_reverse($indexes) as $name=>$conf) {
|
||||
if (is_int(strpos($name, '___')))
|
||||
list($tname,$name) = explode('___', $name);
|
||||
list($tname,$name) = explode('___', $name);
|
||||
if (is_int(strpos($name, '__')))
|
||||
$name = explode('__', $name);
|
||||
if ($exec) {
|
||||
@@ -683,11 +735,11 @@ class TableModifier extends TableBuilder {
|
||||
$triggerName = $this->db->quotekey($this->name.'_insert');
|
||||
$queries[] = "DROP TRIGGER IF EXISTS $triggerName;";
|
||||
$queries[] = 'CREATE TRIGGER '.$triggerName.' AFTER INSERT ON '.$table.
|
||||
' WHEN (NEW.'.$pkey.' IS NULL) BEGIN'.
|
||||
' UPDATE '.$table.' SET '.$pkey.' = ('.
|
||||
' select coalesce( max( '.$pkey.' ), 0 ) + 1 from '.$table.
|
||||
') WHERE ROWID = NEW.ROWID;'.
|
||||
' END;';
|
||||
' WHEN (NEW.'.$pkey.' IS NULL) BEGIN'.
|
||||
' UPDATE '.$table.' SET '.$pkey.' = ('.
|
||||
' select coalesce( max( '.$pkey.' ), 0 ) + 1 from '.$table.
|
||||
') WHERE ROWID = NEW.ROWID;'.
|
||||
' END;';
|
||||
return $queries;
|
||||
}
|
||||
|
||||
@@ -705,9 +757,9 @@ class TableModifier extends TableBuilder {
|
||||
foreach ($schema as $name => &$cols) {
|
||||
$default = ($cols['default'] === '') ? null : $cols['default'];
|
||||
if (!is_null($default) && (
|
||||
(is_int(strpos($curdef=$this->findQuery($this->schema->defaultTypes['CUR_STAMP']),
|
||||
$default)) || is_int(strpos($default,$curdef)))
|
||||
|| $default == "('now'::text)::timestamp(0) without time zone"))
|
||||
(is_int(strpos($curdef=$this->findQuery($this->schema->defaultTypes['CUR_STAMP']),
|
||||
$default)) || is_int(strpos($default,$curdef)))
|
||||
|| $default == "('now'::text)::timestamp(0) without time zone"))
|
||||
{
|
||||
$default = 'CUR_STAMP';
|
||||
} elseif (!is_null($default)) {
|
||||
@@ -729,6 +781,17 @@ class TableModifier extends TableBuilder {
|
||||
return $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* check if a data type is compatible with an existing column type
|
||||
* @param string $colType (i.e: BOOLEAN)
|
||||
* @param string $column (i.e: active)
|
||||
* @return bool
|
||||
*/
|
||||
public function isCompatible($colType,$column) {
|
||||
$cols = $this->getCols(true);
|
||||
return $this->schema->isCompatible($colType,$cols[$column]['type']);
|
||||
}
|
||||
|
||||
/**
|
||||
* removes a column from a table
|
||||
* @param string $name
|
||||
@@ -771,7 +834,7 @@ class TableModifier extends TableBuilder {
|
||||
trigger_error('cannot rename column. it does not exist.');
|
||||
if (in_array($new_name, array_keys($existing_columns)))
|
||||
trigger_error('cannot rename column. new column already exist.');
|
||||
|
||||
|
||||
if (preg_match('/sqlite2?/', $this->db->driver()))
|
||||
// SQlite does not support drop or rename column directly
|
||||
$this->rebuild_cmd['rename'][$name] = $new_name;
|
||||
@@ -801,28 +864,55 @@ class TableModifier extends TableBuilder {
|
||||
|
||||
/**
|
||||
* modifies column datatype
|
||||
* @param $name
|
||||
* @param $datatype
|
||||
* @param string $name
|
||||
* @param string|Column $datatype
|
||||
* @param bool $force
|
||||
* @return bool
|
||||
*/
|
||||
public function updateColumn($name, $datatype, $force = false)
|
||||
{
|
||||
if ($datatype instanceof Column) {
|
||||
$col = $datatype;
|
||||
$datatype = $col->type;
|
||||
$force = $col->passThrough;
|
||||
}
|
||||
if(!$force)
|
||||
$datatype = $this->findQuery($this->schema->dataTypes[strtoupper($datatype)]);
|
||||
$table = $this->db->quotekey($this->name);
|
||||
$column = $this->db->quotekey($name);
|
||||
if (preg_match('/sqlite2?/', $this->db->driver())){
|
||||
$this->rebuild_cmd['update'][$name] = $datatype;
|
||||
$this->rebuild_cmd['update'][$name] = isset($col)?$col:$datatype;
|
||||
} else {
|
||||
$dat = isset($col) ? $col->getColumnQuery() :
|
||||
$column.' '.$datatype;
|
||||
$cmd = array(
|
||||
'mysql' =>
|
||||
"ALTER TABLE $table MODIFY COLUMN $column $datatype;",
|
||||
'pgsql' =>
|
||||
"ALTER TABLE $table ALTER COLUMN $column TYPE $datatype;",
|
||||
'sqlsrv|mssql|sybase|dblib|ibm' =>
|
||||
"ALTER TABLE $table ALTER COLUMN $column $datatype;",
|
||||
'mysql' =>
|
||||
"ALTER TABLE $table MODIFY COLUMN $dat;",
|
||||
'pgsql' =>
|
||||
"ALTER TABLE $table ALTER COLUMN $column TYPE $datatype;",
|
||||
'sqlsrv|mssql|sybase|dblib|ibm' =>
|
||||
"ALTER TABLE $table ALTER COLUMN $column $datatype;",
|
||||
);
|
||||
if (isset($col)) {
|
||||
$cmd['pgsql'] = array($cmd['pgsql']);
|
||||
$cmd['pgsql'][] = "ALTER TABLE $table ALTER COLUMN $column SET DEFAULT ".$col->getDefault().";";
|
||||
if ($col->nullable)
|
||||
$cmd['pgsql'][] = "ALTER TABLE $table ALTER COLUMN $column DROP NOT NULL;";
|
||||
else
|
||||
$cmd['pgsql'][] = "ALTER TABLE $table ALTER COLUMN $column SET NOT NULL;";
|
||||
$df_key = 'DF_'.$this->name.'_'.$name;
|
||||
$cmd['sqlsrv|mssql|sybase|dblib|ibm'] = array(
|
||||
"ALTER TABLE $table ALTER COLUMN $column $datatype ".$col->getNullable().";",
|
||||
"DECLARE @ConstraintName nvarchar(200)
|
||||
SELECT @ConstraintName = Name FROM SYS.DEFAULT_CONSTRAINTS WHERE PARENT_OBJECT_ID = OBJECT_ID('$this->name')
|
||||
AND PARENT_COLUMN_ID = (SELECT column_id FROM sys.columns WHERE NAME = N'$name'
|
||||
AND object_id = OBJECT_ID(N'$this->name'))
|
||||
IF @ConstraintName IS NOT NULL
|
||||
EXEC('ALTER TABLE $this->name DROP CONSTRAINT ' + @ConstraintName)
|
||||
",
|
||||
"ALTER TABLE $table ADD CONSTRAINT $df_key DEFAULT ".$col->getDefault()." FOR $column;",
|
||||
);
|
||||
}
|
||||
$this->queries[] = $this->findQuery($cmd);
|
||||
}
|
||||
}
|
||||
@@ -937,10 +1027,10 @@ class TableModifier extends TableBuilder {
|
||||
class Column extends DB_Utils {
|
||||
|
||||
public $name, $type, $nullable, $default, $after, $index, $unique, $passThrough, $pkey;
|
||||
protected $table, $schema;
|
||||
protected $table, $schema, $type_val;
|
||||
|
||||
const
|
||||
TEXT_NoDataType = 'The specified datatype %s is not defined in %s driver',
|
||||
TEXT_NoDataType = 'The specified datatype %s is not defined in %s driver. Add passThrough option to enforce this datatype.',
|
||||
TEXT_CurrentStampDataType = 'Current timestamp as column default is only possible for TIMESTAMP datatype';
|
||||
|
||||
/**
|
||||
@@ -1072,14 +1162,24 @@ class Column extends DB_Utils {
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* feed column from array or hive key
|
||||
* @param string|array $args
|
||||
*/
|
||||
public function copyfrom($args) {
|
||||
if (($args || \Base::instance()->exists($args,$args))
|
||||
&& is_array($args))
|
||||
foreach ($args as $arg => $val)
|
||||
$this->{$arg} = $val;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns an array of this column configuration
|
||||
* @return array
|
||||
*/
|
||||
public function getColumnArray()
|
||||
{
|
||||
public function getColumnArray() {
|
||||
$fields = array('name','type','passThrough','default','nullable',
|
||||
'index','unique','after','pkey');
|
||||
'index','unique','after','pkey');
|
||||
$fields = array_flip($fields);
|
||||
foreach($fields as $key => &$val)
|
||||
$val = $this->{$key};
|
||||
@@ -1087,55 +1187,55 @@ class Column extends DB_Utils {
|
||||
return $fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* return resolved column datatype
|
||||
* @return bool|string
|
||||
*/
|
||||
public function getTypeVal() {
|
||||
if (!$this->type)
|
||||
trigger_error(sprintf('Cannot build a column query for `%s`: no column type set',$this->name));
|
||||
if ($this->passThrough)
|
||||
$this->type_val = $this->type;
|
||||
else {
|
||||
$this->type_val = $this->findQuery($this->schema->dataTypes[strtoupper($this->type)]);
|
||||
if (!$this->type_val) {
|
||||
if (Schema::$strict) {
|
||||
trigger_error(sprintf(self::TEXT_NoDataType, strtoupper($this->type),
|
||||
$this->db->driver()));
|
||||
return FALSE;
|
||||
} else {
|
||||
// auto pass-through if not found
|
||||
$this->type_val = $this->type;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this->type_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* generate SQL column definition query
|
||||
* @return bool|string
|
||||
*/
|
||||
public function getColumnQuery()
|
||||
{
|
||||
if (!$this->type)
|
||||
trigger_error(sprintf('Cannot build a column query for `%s`: no column type set',$this->name));
|
||||
public function getColumnQuery() {
|
||||
// prepare column types
|
||||
if ($this->passThrough)
|
||||
$type_val = $this->type;
|
||||
else {
|
||||
$type_val = $this->findQuery($this->schema->dataTypes[strtoupper($this->type)]);
|
||||
if (!$type_val) {
|
||||
trigger_error(sprintf(self::TEXT_NoDataType, strtoupper($this->type),
|
||||
$this->db->driver()));
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
$type_val = $this->getTypeVal();
|
||||
// build query
|
||||
$query = $this->db->quotekey($this->name).' '.$type_val.' '.
|
||||
($this->nullable ? 'NULL' : 'NOT NULL');
|
||||
$this->getNullable();
|
||||
// unify default for booleans
|
||||
if (preg_match('/bool/i', $type_val) && $this->default!==null)
|
||||
$this->default = (int) $this->default;
|
||||
// default value
|
||||
if ($this->default !== false) {
|
||||
$def_cmds = array(
|
||||
'sqlite2?|mysql|pgsql|mssql|sybase|dblib|odbc|sqlsrv' => 'DEFAULT',
|
||||
'sqlite2?|mysql|pgsql' => 'DEFAULT',
|
||||
'mssql|sybase|dblib|odbc|sqlsrv' => 'constraint DF_'.$this->table->name.'_'.$this->name.' DEFAULT',
|
||||
'ibm' => 'WITH DEFAULT',
|
||||
);
|
||||
$def_cmd = $this->findQuery($def_cmds).' ';
|
||||
// timestamp default
|
||||
if ($this->default === Schema::DF_CURRENT_TIMESTAMP) {
|
||||
// check for right datatpye
|
||||
$stamp_type = $this->findQuery($this->schema->dataTypes['TIMESTAMP']);
|
||||
if ($this->type != 'TIMESTAMP' && // TODO: check that condition
|
||||
($this->passThrough && strtoupper($this->type) != strtoupper($stamp_type))
|
||||
)
|
||||
trigger_error(self::TEXT_CurrentStampDataType);
|
||||
$def_cmd .= $this->findQuery($this->schema->defaultTypes[strtoupper($this->default)]);
|
||||
} else {
|
||||
// static defaults
|
||||
$pdo_type = preg_match('/int|bool/i', $type_val, $parts) ?
|
||||
constant('\PDO::PARAM_'.strtoupper($parts[0])) : \PDO::PARAM_STR;
|
||||
$def_cmd .= ($this->default === NULL ? 'NULL' :
|
||||
$this->db->quote(htmlspecialchars($this->default, ENT_QUOTES,
|
||||
$this->f3->get('ENCODING')), $pdo_type));
|
||||
}
|
||||
$def_cmd = $this->findQuery($def_cmds).' '.$this->getDefault();
|
||||
$query .= ' '.$def_cmd;
|
||||
}
|
||||
if (!empty($this->after)) {
|
||||
if (!empty($this->after) && $this->table instanceof TableModifier) {
|
||||
// `after` feature only works for mysql
|
||||
if (preg_match('/mysql/', $this->db->driver())) {
|
||||
$after_cmd = 'AFTER '.$this->db->quotekey($this->after);
|
||||
@@ -1144,6 +1244,39 @@ class Column extends DB_Utils {
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
|
||||
/**
|
||||
* return query part for nullable
|
||||
* @return string
|
||||
*/
|
||||
public function getNullable() {
|
||||
return $this->nullable ? 'NULL' : 'NOT NULL';
|
||||
}
|
||||
|
||||
/**
|
||||
* return query part for default value
|
||||
* @return string
|
||||
*/
|
||||
public function getDefault() {
|
||||
// timestamp default
|
||||
if ($this->default === Schema::DF_CURRENT_TIMESTAMP) {
|
||||
// check for right datatpye
|
||||
$stamp_type = $this->findQuery($this->schema->dataTypes['TIMESTAMP']);
|
||||
if ($this->type != 'TIMESTAMP' &&
|
||||
($this->passThrough && strtoupper($this->type) != strtoupper($stamp_type))
|
||||
)
|
||||
trigger_error(self::TEXT_CurrentStampDataType);
|
||||
return $this->findQuery($this->schema->defaultTypes[strtoupper($this->default)]);
|
||||
} else {
|
||||
// static defaults
|
||||
$type_val = $this->getTypeVal();
|
||||
$pdo_type = preg_match('/int|bool/i', $type_val, $parts) ?
|
||||
constant('\PDO::PARAM_'.strtoupper($parts[0])) : \PDO::PARAM_STR;
|
||||
return ($this->default === NULL ? 'NULL' :
|
||||
$this->db->quote(htmlspecialchars($this->default, ENT_QUOTES,
|
||||
$this->f3->get('ENCODING')), $pdo_type));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1164,19 +1297,11 @@ class DB_Utils {
|
||||
* @param $cmd array
|
||||
* @return bool|string
|
||||
*/
|
||||
protected function findQuery($cmd)
|
||||
{
|
||||
$match = FALSE;
|
||||
public function findQuery($cmd) {
|
||||
foreach ($cmd as $backend => $val)
|
||||
if (preg_match('/'.$backend.'/', $this->db->driver())) {
|
||||
$match = TRUE;
|
||||
break;
|
||||
}
|
||||
if (!$match) {
|
||||
trigger_error(sprintf(self::TEXT_ENGINE_NOT_SUPPORTED, $this->db->driver()));
|
||||
return FALSE;
|
||||
}
|
||||
return $val;
|
||||
if (preg_match('/'.$backend.'/', $this->db->driver()))
|
||||
return $val;
|
||||
trigger_error(sprintf(self::TEXT_ENGINE_NOT_SUPPORTED, $this->db->driver()));
|
||||
}
|
||||
|
||||
public function __construct(SQL $db) {
|
||||
|
||||
216
app/lib/sheet.php
Normal file
@@ -0,0 +1,216 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Sheet - CSV and Excel tools
|
||||
*
|
||||
* The contents of this file are subject to the terms of the GNU General
|
||||
* Public License Version 3.0. You may not use this file except in
|
||||
* compliance with the license. Any of the license terms and conditions
|
||||
* can be waived if you get permission from the copyright holder.
|
||||
*
|
||||
* (c) Christian Knuth
|
||||
*
|
||||
* @date: 16.03.2015
|
||||
* @version 0.4.1
|
||||
*/
|
||||
|
||||
|
||||
class Sheet extends \Prefab {
|
||||
|
||||
/**
|
||||
* multiline-aware CSV parser
|
||||
* @param $filepath
|
||||
* @param string $delimiter
|
||||
* @param string $enclosure
|
||||
* @return array|bool
|
||||
*/
|
||||
public function parseCSV($filepath,$delimiter=";",$enclosure='"') {
|
||||
if (!is_file($filepath)) {
|
||||
user_error('File not found: '.$filepath);
|
||||
return false;
|
||||
}
|
||||
$data = \Base::instance()->read($filepath,true);
|
||||
|
||||
if(!preg_match_all('/((?:.*?)'.$delimiter.'(?:'.$enclosure.'.*?'.
|
||||
$enclosure.'|['.$delimiter.'(?:\d|\.|\/)*\d])*\n)/s',$data,$matches))
|
||||
user_error('no rows found');
|
||||
|
||||
$out = array_map(function($val) use($delimiter,$enclosure) {
|
||||
return str_getcsv($val,$delimiter,$enclosure);
|
||||
},$matches[0]);
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* use specified headers or first row as label for each row item key
|
||||
* @param $rows
|
||||
* @param null $headers
|
||||
* @return array
|
||||
*/
|
||||
public function applyHeader($rows,$headers=null) {
|
||||
if (!$headers)
|
||||
$headers=array_shift($rows);
|
||||
return array_map(function($row) use($headers) {
|
||||
return array_combine(array_values($headers),array_values($row));
|
||||
},$rows);
|
||||
}
|
||||
|
||||
/**
|
||||
* build and return xls file data
|
||||
* @param $rows
|
||||
* @param $headers
|
||||
* @return string
|
||||
*/
|
||||
public function dumpXLS($rows,$headers) {
|
||||
$numColumns = count($headers);
|
||||
$numRows = count($rows);
|
||||
foreach($headers as $key=>$val)
|
||||
if (is_numeric($key)) {
|
||||
$headers[$val]=ucfirst($val);
|
||||
unset($headers[$key]);
|
||||
}
|
||||
$xls = $this->xlsBOF();
|
||||
for ($i = 0; $i <= $numRows; $i++) {
|
||||
for ($c = 0; $c <= $numColumns; $c++) {
|
||||
$ckey = key($headers);
|
||||
$val='';
|
||||
if ($i==0)
|
||||
$val = current($headers);
|
||||
elseif (isset($rows[$i-1][$ckey]))
|
||||
$val = trim($rows[$i-1][$ckey]);
|
||||
if (is_array($val))
|
||||
$val = json_encode($val);
|
||||
$xls.= (is_int($val)
|
||||
|| (ctype_digit($val) && ($val[0]!='0' && strlen($val)>1)))
|
||||
? $this->xlsWriteNumber($i,$c,$val)
|
||||
: $this->xlsWriteString($i,$c,utf8_decode($val));
|
||||
next($headers);
|
||||
}
|
||||
reset($headers);
|
||||
}
|
||||
$xls .= $this->xlsEOF();
|
||||
return $xls;
|
||||
}
|
||||
|
||||
/**
|
||||
* render xls file and send to HTTP client
|
||||
* @param $rows
|
||||
* @param $headers
|
||||
* @param $filename
|
||||
*/
|
||||
function renderXLS($rows,$headers,$filename) {
|
||||
$data = $this->dumpXLS($rows,$headers);
|
||||
header("Expires: 0");
|
||||
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
|
||||
header('Content-Type: application/xls');
|
||||
header("Content-Disposition: attachment;filename=".$filename);
|
||||
header("Content-Transfer-Encoding: binary");
|
||||
echo $data;
|
||||
exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* start file
|
||||
* @return string
|
||||
*/
|
||||
protected function xlsBOF() {
|
||||
return pack("ssssss", 0x809, 0x8, 0x0, 0x10, 0x0, 0x0);
|
||||
}
|
||||
|
||||
/**
|
||||
* end file
|
||||
* @return string
|
||||
*/
|
||||
protected function xlsEOF() {
|
||||
return pack("ss", 0x0A, 0x00);
|
||||
}
|
||||
|
||||
/**
|
||||
* put number
|
||||
* @param $row
|
||||
* @param $col
|
||||
* @param $val
|
||||
* @return string
|
||||
*/
|
||||
protected function xlsWriteNumber($row, $col, $val) {
|
||||
$out = pack("sssss", 0x203, 14, $row, $col, 0x0);
|
||||
$out.= pack("d", $val);
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* put string
|
||||
* @param $row
|
||||
* @param $col
|
||||
* @param $val
|
||||
* @return string
|
||||
*/
|
||||
protected function xlsWriteString($row, $col, $val ) {
|
||||
$l = strlen($val);
|
||||
$out = pack("ssssss", 0x204, 8+$l, $row, $col, 0x0, $l);
|
||||
$out.= $val;
|
||||
return $out;
|
||||
}
|
||||
|
||||
/**
|
||||
* build and return CSV data sheet
|
||||
* @param $rows
|
||||
* @param $headers
|
||||
* @param string $delimiter
|
||||
* @param string $enclosure
|
||||
* @param bool $encloseAll
|
||||
* @return string
|
||||
*/
|
||||
public function dumpCSV($rows,$headers,$delimiter=';',$enclosure='"',$encloseAll=true) {
|
||||
$numColumns = count($headers);
|
||||
$numRows = count($rows);
|
||||
foreach($headers as $key=>$val)
|
||||
if (is_numeric($key)) {
|
||||
$headers[$val]=ucfirst($val);
|
||||
unset($headers[$key]);
|
||||
}
|
||||
$out = array();
|
||||
for ($i = 0; $i <= $numRows; $i++) {
|
||||
$line = array();
|
||||
for ($c = 0; $c <= $numColumns; $c++) {
|
||||
$ckey = key($headers);
|
||||
$field='';
|
||||
if ($i==0)
|
||||
$field = current($headers);
|
||||
elseif (isset($rows[$i-1][$ckey]))
|
||||
$field = trim($rows[$i-1][$ckey]);
|
||||
if (is_array($field))
|
||||
$field = json_encode($field);
|
||||
if (empty($field) && $field !== 0)
|
||||
$line[] = '';
|
||||
elseif ($encloseAll || preg_match('/(?:'.preg_quote($delimiter, '/').'|'.
|
||||
preg_quote($enclosure, '/').'|\s)/', $field))
|
||||
$line[] = $enclosure.str_replace($enclosure, $enclosure.$enclosure, $field).$enclosure;
|
||||
else
|
||||
$line[] = $field;
|
||||
next($headers);
|
||||
}
|
||||
$out[] = implode($delimiter, $line);
|
||||
reset($headers);
|
||||
}
|
||||
return implode("\n",$out);
|
||||
}
|
||||
|
||||
/**
|
||||
* send CSV file to client
|
||||
* @param $rows
|
||||
* @param $headers
|
||||
* @param $filename
|
||||
*/
|
||||
function renderCSV($rows,$headers,$filename) {
|
||||
$data = $this->dumpCSV($rows,$headers);
|
||||
header("Expires: 0");
|
||||
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
|
||||
header('Content-Type: text/csv;charset=UTF-16LE');
|
||||
header("Content-Disposition: attachment;filename=".$filename);
|
||||
header("Content-Transfer-Encoding: binary");
|
||||
echo "\xFF"."\xFE".mb_convert_encoding($data, 'UTF-16LE', 'UTF-8');
|
||||
exit();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -11,10 +11,6 @@ use Model;
|
||||
|
||||
class AccessController extends Controller {
|
||||
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* event handler
|
||||
* @param $f3
|
||||
|
||||
@@ -58,7 +58,7 @@ class Access extends \Controller\AccessController {
|
||||
$accessList = $accessModel->find( array(
|
||||
"LOWER(name) LIKE :token AND " .
|
||||
"active = 1 AND " .
|
||||
"sharing = 1 ",
|
||||
"shared = 1 ",
|
||||
':token' => '%' . $searchToken . '%'
|
||||
));
|
||||
|
||||
|
||||
82
app/main/controller/api/github.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: exodus4d
|
||||
* Date: 16.01.16
|
||||
* Time: 03:34
|
||||
*/
|
||||
|
||||
namespace Controller\Api;
|
||||
use Model;
|
||||
use Controller;
|
||||
|
||||
|
||||
/**
|
||||
* Github controller
|
||||
* Class Route
|
||||
* @package Controller\Api
|
||||
*/
|
||||
class GitHub extends Controller\Controller {
|
||||
|
||||
/**
|
||||
* get HTTP request options for API (curl) request
|
||||
* @return array
|
||||
*/
|
||||
protected function getRequestOptions(){
|
||||
$requestOptions = [
|
||||
'timeout' => 8,
|
||||
'method' => 'GET',
|
||||
'user_agent' => $this->getUserAgent(),
|
||||
'follow_location' => false // otherwise CURLOPT_FOLLOWLOCATION will fail
|
||||
];
|
||||
|
||||
return $requestOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* get release information from GitHub
|
||||
* @param $f3
|
||||
*/
|
||||
public function releases($f3){
|
||||
$cacheKey = 'CACHE_GITHUB_RELEASES';
|
||||
$ttl = 60 * 30; // 30min
|
||||
$releaseCount = 5;
|
||||
|
||||
if( !$f3->exists($cacheKey) ){
|
||||
$apiPath = $this->getF3()->get('PATHFINDER.API.GIT_HUB') . '/repos/exodus4d/pathfinder/releases';
|
||||
|
||||
// build request URL
|
||||
$options = $this->getRequestOptions();
|
||||
$apiResponse = \Web::instance()->request($apiPath, $options );
|
||||
|
||||
if($apiResponse['body']){
|
||||
// request succeeded -> format "Markdown" to "HTML"
|
||||
// result is JSON formed
|
||||
$releasesData = (array)json_decode($apiResponse['body']);
|
||||
|
||||
// check max release count
|
||||
if(count($releasesData) > $releaseCount){
|
||||
$releasesData = array_slice($releasesData, 0, $releaseCount);
|
||||
}
|
||||
|
||||
$md = \Markdown::instance();
|
||||
foreach($releasesData as &$releaseData){
|
||||
if(isset($releaseData->body)){
|
||||
$releaseData->body = $md->convert( $releaseData->body );
|
||||
}
|
||||
}
|
||||
$f3->set($cacheKey, $releasesData, $ttl);
|
||||
}else{
|
||||
// request failed -> cache failed result (respect API request limit)
|
||||
$f3->set($cacheKey, false, 60 * 5);
|
||||
}
|
||||
}
|
||||
|
||||
// set 503 if service unavailable or temp cached data = false
|
||||
if( !$f3->get($cacheKey) ){
|
||||
$f3->status(503);
|
||||
}
|
||||
|
||||
echo json_encode($f3->get($cacheKey));
|
||||
}
|
||||
}
|
||||
@@ -318,7 +318,7 @@ class Map extends \Controller\AccessController {
|
||||
|
||||
if(
|
||||
!$tempUser->dry() &&
|
||||
$tempUser->sharing == 1 // check if map sharing is enabled
|
||||
$tempUser->shared == 1 // check if map shared is enabled
|
||||
){
|
||||
$map->setAccess($tempUser);
|
||||
}
|
||||
@@ -355,7 +355,7 @@ class Map extends \Controller\AccessController {
|
||||
|
||||
if(
|
||||
!$tempCorporation->dry() &&
|
||||
$tempCorporation->sharing == 1 // check if map sharing is enabled
|
||||
$tempCorporation->shared == 1 // check if map shared is enabled
|
||||
){
|
||||
$map->setAccess($tempCorporation);
|
||||
}
|
||||
@@ -393,7 +393,7 @@ class Map extends \Controller\AccessController {
|
||||
|
||||
if(
|
||||
!$tempAlliance->dry() &&
|
||||
$tempAlliance->sharing == 1 // check if map sharing is enabled
|
||||
$tempAlliance->shared == 1 // check if map shared is enabled
|
||||
){
|
||||
$map->setAccess($tempAlliance);
|
||||
}
|
||||
@@ -465,7 +465,7 @@ class Map extends \Controller\AccessController {
|
||||
$responseTTL = $f3->get('PATHFINDER.TIMER.UPDATE_SERVER_MAP.DELAY') / 1000;
|
||||
$mapData = (array)$f3->get('POST.mapData');
|
||||
|
||||
$user = $this->_getUser(0);
|
||||
$user = $this->_getUser();
|
||||
$return = (object) [];
|
||||
$return->error = [];
|
||||
|
||||
@@ -628,7 +628,7 @@ class Map extends \Controller\AccessController {
|
||||
$return = (object) [];
|
||||
$return->error = [];
|
||||
|
||||
$user = $this->_getUser(0);
|
||||
$user = $this->_getUser();
|
||||
|
||||
if($user){
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ class Route extends \Controller\AccessController {
|
||||
* cache time for static jump data
|
||||
* @var int
|
||||
*/
|
||||
private $jumpDataCacheTime = 0;
|
||||
private $jumpDataCacheTime = 86400;
|
||||
|
||||
/**
|
||||
* array system information grouped by systemId
|
||||
@@ -41,19 +41,6 @@ class Route extends \Controller\AccessController {
|
||||
*/
|
||||
private $idArray = [];
|
||||
|
||||
|
||||
|
||||
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
|
||||
// set cache time for static jump data
|
||||
$this->jumpDataCacheTime = 60 * 60 * 24;
|
||||
|
||||
// set static system jump data
|
||||
$this->setSystemJumpData();
|
||||
}
|
||||
|
||||
/**
|
||||
* set static system jump data for this instance
|
||||
* the data is fixed and should not change
|
||||
@@ -61,20 +48,22 @@ class Route extends \Controller\AccessController {
|
||||
private function setSystemJumpData(){
|
||||
$cacheKey = 'staticJumpData';
|
||||
|
||||
$f3 = $this->getF3();
|
||||
|
||||
$cacheKeyNamedArray = $cacheKey . '.nameArray';
|
||||
$cacheKeyJumpArray = $cacheKey . '.jumpArray';
|
||||
$cacheKeyIdArray = $cacheKey . '.idArray';
|
||||
|
||||
if(
|
||||
$this->f3->exists($cacheKeyNamedArray) &&
|
||||
$this->f3->exists($cacheKeyJumpArray) &&
|
||||
$this->f3->exists($cacheKeyIdArray)
|
||||
$f3->exists($cacheKeyNamedArray) &&
|
||||
$f3->exists($cacheKeyJumpArray) &&
|
||||
$f3->exists($cacheKeyIdArray)
|
||||
){
|
||||
// get cached values
|
||||
|
||||
$this->nameArray = $this->f3->get($cacheKeyNamedArray);
|
||||
$this->jumpArray = $this->f3->get($cacheKeyJumpArray);
|
||||
$this->idArray = $this->f3->get($cacheKeyIdArray);
|
||||
$this->nameArray = $f3->get($cacheKeyNamedArray);
|
||||
$this->jumpArray = $f3->get($cacheKeyJumpArray);
|
||||
$this->idArray = $f3->get($cacheKeyIdArray);
|
||||
}else{
|
||||
// nothing cached
|
||||
|
||||
@@ -84,27 +73,29 @@ class Route extends \Controller\AccessController {
|
||||
|
||||
$rows = $pfDB->exec($query, null, $this->jumpDataCacheTime);
|
||||
|
||||
foreach($rows as $row){
|
||||
$regionId = $row['regionId'];
|
||||
$constId = $row['constellationId'];
|
||||
$systemName = strtoupper($row['systemName']);
|
||||
$systemId = $row['systemId'];
|
||||
$secStatus = $row['trueSec'];
|
||||
if(count($rows) > 0){
|
||||
foreach($rows as $row){
|
||||
$regionId = $row['regionId'];
|
||||
$constId = $row['constellationId'];
|
||||
$systemName = strtoupper($row['systemName']);
|
||||
$systemId = $row['systemId'];
|
||||
$secStatus = $row['trueSec'];
|
||||
|
||||
$this->nameArray[$systemId][0] = $systemName;
|
||||
$this->nameArray[$systemId][1] = $regionId;
|
||||
$this->nameArray[$systemId][2] = $constId;
|
||||
$this->nameArray[$systemId][3] = $secStatus;
|
||||
$this->nameArray[$systemId][0] = $systemName;
|
||||
$this->nameArray[$systemId][1] = $regionId;
|
||||
$this->nameArray[$systemId][2] = $constId;
|
||||
$this->nameArray[$systemId][3] = $secStatus;
|
||||
|
||||
$this->idArray[strtoupper($systemName)] = $systemId;
|
||||
$this->idArray[strtoupper($systemName)] = $systemId;
|
||||
|
||||
$this->jumpArray[$systemName]= explode(":", strtoupper($row['jumpNodes']));
|
||||
array_push($this->jumpArray[$systemName],$systemId);
|
||||
$this->jumpArray[$systemName]= explode(":", strtoupper($row['jumpNodes']));
|
||||
array_push($this->jumpArray[$systemName],$systemId);
|
||||
}
|
||||
|
||||
$f3->set($cacheKeyNamedArray, $this->nameArray, $this->jumpDataCacheTime);
|
||||
$f3->set($cacheKeyJumpArray, $this->jumpArray, $this->jumpDataCacheTime);
|
||||
$f3->set($cacheKeyIdArray, $this->idArray, $this->jumpDataCacheTime);
|
||||
}
|
||||
|
||||
$this->f3->set($cacheKeyNamedArray, $this->nameArray, $this->jumpDataCacheTime);
|
||||
$this->f3->set($cacheKeyJumpArray, $this->jumpArray, $this->jumpDataCacheTime);
|
||||
$this->f3->set($cacheKeyIdArray, $this->idArray, $this->jumpDataCacheTime);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,6 +193,7 @@ class Route extends \Controller\AccessController {
|
||||
* This function is just for setting up the cache table 'system_neighbour' which is used
|
||||
* for system jump calculation. Call this function manually if CCP adds Systems/Stargates
|
||||
*/
|
||||
/*
|
||||
private function setupSystemJumpTable(){
|
||||
|
||||
$pfDB = $this->getDB('PF');
|
||||
@@ -269,7 +261,7 @@ class Route extends \Controller\AccessController {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
/**
|
||||
* find a route between two systems (system names)
|
||||
* $searchDepth for recursive route search (5000 would be best but slow)
|
||||
@@ -291,6 +283,9 @@ class Route extends \Controller\AccessController {
|
||||
!empty($systemFrom) &&
|
||||
!empty($systemTo)
|
||||
){
|
||||
|
||||
$this->setSystemJumpData();
|
||||
|
||||
$from = strtoupper( $systemFrom );
|
||||
$to = strtoupper( $systemTo );
|
||||
|
||||
@@ -377,7 +372,14 @@ class Route extends \Controller\AccessController {
|
||||
}else{
|
||||
// no cached route data found
|
||||
$foundRoutData = $this->findRoute($routeData['systemFrom'], $routeData['systemTo']);
|
||||
$f3->set($cacheKey, $foundRoutData, $this->jumpDataCacheTime);
|
||||
|
||||
// cache if route was found
|
||||
if(
|
||||
isset($foundRoutData['routePossible']) &&
|
||||
$foundRoutData['routePossible'] === true
|
||||
){
|
||||
$f3->set($cacheKey, $foundRoutData, $this->jumpDataCacheTime);
|
||||
}
|
||||
|
||||
$return->routesData[] = $foundRoutData;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ class User extends Controller\Controller{
|
||||
$user->updateApiData();
|
||||
|
||||
// route user to map app
|
||||
$return->reroute = self::getEnvironmentData('URL') . $f3->alias('map');
|
||||
$return->reroute = rtrim(self::getEnvironmentData('URL'), '/') . $f3->alias('map');
|
||||
}
|
||||
|
||||
echo json_encode($return);
|
||||
@@ -108,16 +108,19 @@ class User extends Controller\Controller{
|
||||
){
|
||||
$reason = $data['reason'];
|
||||
|
||||
$img = new \Image();
|
||||
$im = imagecreatetruecolor(1, 1);
|
||||
$colorText = imagecolorallocate($im, 102, 200, 79);
|
||||
$colorBG = imagecolorallocate($im, 49, 51, 53);
|
||||
|
||||
$img = new \Image();
|
||||
$imgDump = $img->captcha(
|
||||
'fonts/oxygen-bold-webfont.ttf',
|
||||
14,
|
||||
6,
|
||||
'SESSION.' . $reason,
|
||||
'',
|
||||
'0x66C84F',
|
||||
'0x313335'
|
||||
$colorText,
|
||||
$colorBG
|
||||
)->dump();
|
||||
|
||||
$return->img = $f3->base64( $imgDump, 'image/png');
|
||||
@@ -157,8 +160,7 @@ class User extends Controller\Controller{
|
||||
*/
|
||||
public function logOut($f3){
|
||||
$this->deleteLog($f3);
|
||||
|
||||
return parent::logOut($f3);
|
||||
parent::logOut($f3);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -196,7 +198,7 @@ class User extends Controller\Controller{
|
||||
}
|
||||
}
|
||||
|
||||
$user->sharing = $privateSharing;
|
||||
$user->shared = $privateSharing;
|
||||
$user->save();
|
||||
|
||||
// update corp/ally ---------------------------------------------------------------
|
||||
@@ -208,12 +210,12 @@ class User extends Controller\Controller{
|
||||
$alliance = $activeUserCharacter->getCharacter()->getAlliance();
|
||||
|
||||
if(is_object($corporation)){
|
||||
$corporation->sharing = $corporationSharing;
|
||||
$corporation->shared = $corporationSharing;
|
||||
$corporation->save();
|
||||
}
|
||||
|
||||
if(is_object($alliance)){
|
||||
$alliance->sharing = $allianceSharing;
|
||||
$alliance->shared = $allianceSharing;
|
||||
$alliance->save();
|
||||
}
|
||||
}
|
||||
@@ -279,10 +281,10 @@ class User extends Controller\Controller{
|
||||
}
|
||||
|
||||
/**
|
||||
* save/update user data
|
||||
* save/update user account data
|
||||
* @param $f3
|
||||
*/
|
||||
public function saveConfig($f3){
|
||||
public function saveAccount($f3){
|
||||
$data = $f3->get('POST');
|
||||
|
||||
$return = (object) [];
|
||||
@@ -298,9 +300,6 @@ class User extends Controller\Controller{
|
||||
// check for new user
|
||||
$loginAfterSave = false;
|
||||
|
||||
// send registration mail
|
||||
$sendRegistrationMail = false;
|
||||
|
||||
// valid registration key Model is required for new registration
|
||||
// if "invite" feature is enabled
|
||||
$registrationKeyModel = false;
|
||||
@@ -335,7 +334,6 @@ class User extends Controller\Controller{
|
||||
// new user registration
|
||||
$user = $mapType = Model\BasicModel::getNew('UserModel');
|
||||
$loginAfterSave = true;
|
||||
$sendRegistrationMail = true;
|
||||
|
||||
// set username
|
||||
if(
|
||||
@@ -366,9 +364,6 @@ class User extends Controller\Controller{
|
||||
$settingsData['password'] == $settingsData['password_confirm']
|
||||
){
|
||||
$user->password = $settingsData['password'];
|
||||
|
||||
// pw changed -> send mail
|
||||
$sendRegistrationMail = true;
|
||||
}
|
||||
}else{
|
||||
// captcha was send but not valid -> return error
|
||||
@@ -465,18 +460,12 @@ class User extends Controller\Controller{
|
||||
$this->logUserIn( $user->name, $settingsData['password'] );
|
||||
|
||||
// return reroute path
|
||||
$return->reroute = self::getEnvironmentData('URL') . $this->f3->alias('map');
|
||||
$return->reroute = rtrim(self::getEnvironmentData('URL'), '/') . $this->f3->alias('map');
|
||||
}
|
||||
|
||||
// get fresh updated user object
|
||||
$user = $this->_getUser(0);
|
||||
$newUserData = $user->getData();
|
||||
|
||||
// send registration mail with account information
|
||||
if($sendRegistrationMail){
|
||||
$this->sendRegistration($user, $settingsData['password']);
|
||||
}
|
||||
|
||||
}
|
||||
}catch(Exception\ValidationException $e){
|
||||
$validationError = (object) [];
|
||||
@@ -499,23 +488,6 @@ class User extends Controller\Controller{
|
||||
echo json_encode($return);
|
||||
}
|
||||
|
||||
/**
|
||||
* send registration mail to user
|
||||
* @param $user
|
||||
* @param $password
|
||||
* @return mixed
|
||||
*/
|
||||
protected function sendRegistration($user, $password){
|
||||
|
||||
$msg = 'Username: ' . $user->name . '<br>';
|
||||
$msg .= 'Password: ' . $password . '<br>';
|
||||
|
||||
$mailController = new MailController();
|
||||
$status = $mailController->sendRegistration($user->email, $msg);
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* send mail with registration key
|
||||
* -> check INVITE in pathfinder.ini
|
||||
|
||||
@@ -16,20 +16,20 @@ class AppController extends Controller {
|
||||
* @param $f3
|
||||
*/
|
||||
public function showLandingpage($f3) {
|
||||
// page title
|
||||
$f3->set('pageTitle', 'Login');
|
||||
|
||||
// main page content
|
||||
$f3->set('pageContent','templates/view/landingpage.html');
|
||||
$f3->set('pageContent', $f3->get('PATHFINDER.VIEW.LANDINGPAGE'));
|
||||
|
||||
// body element class
|
||||
$this->f3->set('bodyClass', 'pf-body pf-landing');
|
||||
$f3->set('bodyClass', 'pf-body pf-landing');
|
||||
|
||||
// landing page is always IGB trusted
|
||||
$f3->set('trusted', 1);
|
||||
|
||||
// JS main file
|
||||
$f3->set('jsView', 'landingpage');
|
||||
|
||||
$this->setTemplate('templates/view/index.html');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,22 +16,6 @@ use Model;
|
||||
*/
|
||||
class CcpApiController extends Controller{
|
||||
|
||||
/**
|
||||
* get a custom userAgent string for API calls
|
||||
* (recommended by CCP)
|
||||
* @return string
|
||||
*/
|
||||
protected function getUserAgent(){
|
||||
$userAgent = '';
|
||||
|
||||
$userAgent .= $this->f3->get('PATHFINDER.NAME');
|
||||
$userAgent .= ' - ' . $this->f3->get('PATHFINDER.VERSION');
|
||||
$userAgent .= ' | ' . $this->f3->get('PATHFINDER.CONTACT');
|
||||
$userAgent .= ' (' . $_SERVER['SERVER_NAME'] . ')';
|
||||
|
||||
return $userAgent;
|
||||
}
|
||||
|
||||
/**
|
||||
* get HTTP request options for API (curl) request
|
||||
* @return array
|
||||
@@ -55,7 +39,7 @@ class CcpApiController extends Controller{
|
||||
*/
|
||||
public function requestCharacters($keyID, $vCode){
|
||||
|
||||
$apiPath = $this->f3->get('PATHFINDER.API.CCP_XML') . '/account/APIKeyInfo.xml.aspx';
|
||||
$apiPath = $this->getF3()->get('PATHFINDER.API.CCP_XML') . '/account/APIKeyInfo.xml.aspx';
|
||||
|
||||
$xml = false;
|
||||
|
||||
|
||||
@@ -15,14 +15,6 @@ class Controller {
|
||||
protected $f3;
|
||||
private $template;
|
||||
|
||||
function __construct(){
|
||||
|
||||
$this->f3 = \Base::instance();
|
||||
|
||||
// initiate DB connection
|
||||
DB\Database::instance('PF');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $template
|
||||
*/
|
||||
@@ -37,6 +29,20 @@ class Controller {
|
||||
return $this->template;
|
||||
}
|
||||
|
||||
/**
|
||||
* set global f3 instance
|
||||
* @param null $f3
|
||||
* @return null|static
|
||||
*/
|
||||
protected function getF3($f3 = null){
|
||||
if(is_object($f3)){
|
||||
$this->f3 = $f3;
|
||||
}else{
|
||||
$this->f3 = \Base::instance();
|
||||
}
|
||||
|
||||
return $this->f3;
|
||||
}
|
||||
|
||||
/**
|
||||
* event handler for all "views"
|
||||
@@ -44,24 +50,35 @@ class Controller {
|
||||
* @param $f3
|
||||
*/
|
||||
function beforeroute($f3) {
|
||||
$this->getF3($f3);
|
||||
|
||||
// initiate DB connection
|
||||
DB\Database::instance('PF');
|
||||
|
||||
// init user session
|
||||
$this->initSession();
|
||||
|
||||
// check if user is in game
|
||||
$f3->set('isIngame', self::isIGB() );
|
||||
if( !$f3->get('AJAX') ){
|
||||
// set page parameters for static page render
|
||||
// check if user is in game (IGB active)
|
||||
$f3->set('isIngame', self::isIGB() );
|
||||
|
||||
// js path (build/minified or raw uncompressed files)
|
||||
$f3->set('pathJs', 'public/js/' . $f3->get('PATHFINDER.VERSION') );
|
||||
// js path (build/minified or raw uncompressed files)
|
||||
$f3->set('pathJs', 'public/js/' . $f3->get('PATHFINDER.VERSION') );
|
||||
|
||||
$this->setTemplate( $f3->get('PATHFINDER.VIEW.INDEX') );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* event handler
|
||||
* event handler after routing
|
||||
* -> render view
|
||||
*/
|
||||
function afterroute() {
|
||||
if($this->template){
|
||||
echo \Template::instance()->render( $this->template );
|
||||
|
||||
public function afterroute($f3){
|
||||
if($this->getTemplate()){
|
||||
// Ajax calls don´t need a page render..
|
||||
// this happens on client side
|
||||
echo \Template::instance()->render( $this->getTemplate() );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +96,9 @@ class Controller {
|
||||
*/
|
||||
protected function initSession(){
|
||||
// init DB Session (not file based)
|
||||
new \DB\SQL\Session($this->getDB('PF'));
|
||||
if( $this->getDB('PF') instanceof \DB\SQL){
|
||||
new \DB\SQL\Session($this->getDB('PF'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,7 +114,7 @@ class Controller {
|
||||
$userId = (int)$this->f3->get('SESSION.user.id');
|
||||
|
||||
if($userId > 0){
|
||||
$userModel = Model\BasicModel::getNew('UserModel');
|
||||
$userModel = Model\BasicModel::getNew('UserModel', $ttl);
|
||||
$userModel->getById($userId, $ttl);
|
||||
|
||||
if( !$userModel->dry() ){
|
||||
@@ -120,9 +139,17 @@ class Controller {
|
||||
// redirect to landing page
|
||||
$f3->reroute('@landing');
|
||||
}else{
|
||||
$params = $f3->get('POST');
|
||||
$return = (object) [];
|
||||
$return->reroute = self::getEnvironmentData('URL') . $f3->alias('landing');
|
||||
$return->error[] = $this->getUserLoggedOffError();
|
||||
if(
|
||||
isset($params['reroute']) &&
|
||||
(bool)$params['reroute']
|
||||
){
|
||||
$return->reroute = rtrim(self::getEnvironmentData('URL'), '/') . $f3->alias('landing');
|
||||
}else{
|
||||
// no reroute -> errors can be shown
|
||||
$return->error[] = $this->getUserLoggedOffError();
|
||||
}
|
||||
|
||||
echo json_encode($return);
|
||||
die();
|
||||
@@ -208,11 +235,16 @@ class Controller {
|
||||
static function getRequestHeaders(){
|
||||
$headers = [];
|
||||
|
||||
if(function_exists('apache_request_headers') ){
|
||||
$serverData = self::getServerData();
|
||||
|
||||
if(
|
||||
function_exists('apache_request_headers') &&
|
||||
$serverData->type === 'apache'
|
||||
){
|
||||
// Apache Webserver
|
||||
$headers = apache_request_headers();
|
||||
}else{
|
||||
// Other webserver, e.g. nginx
|
||||
// Other webserver, e.g. Nginx
|
||||
// Unfortunately this "fallback" does not work for me (Apache)
|
||||
// Therefore we can´t use this for all servers
|
||||
// https://github.com/exodus4d/pathfinder/issues/58
|
||||
@@ -222,10 +254,54 @@ class Controller {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* get some server information
|
||||
* @param int $ttl cache time (default: 1h)
|
||||
* @return object
|
||||
*/
|
||||
static function getServerData($ttl = 3600){
|
||||
$f3 = \Base::instance();
|
||||
$cacheKey = 'PF_SERVER_INFO';
|
||||
|
||||
if( !$f3->exists($cacheKey) ){
|
||||
$serverData = (object) [];
|
||||
$serverData->type = 'unknown';
|
||||
$serverData->version = 'unknown';
|
||||
$serverData->requiredVersion = 'unknown';
|
||||
$serverData->phpInterfaceType = php_sapi_name();
|
||||
|
||||
if(strpos(strtolower($_SERVER['SERVER_SOFTWARE']), 'nginx' ) !== false){
|
||||
// Nginx server
|
||||
$serverSoftwareArgs = explode('/', strtolower( $_SERVER['SERVER_SOFTWARE']) );
|
||||
$serverData->type = reset($serverSoftwareArgs);
|
||||
$serverData->version = end($serverSoftwareArgs);
|
||||
$serverData->requiredVersion = $f3->get('REQUIREMENTS.SERVER.NGINX.VERSION');
|
||||
}elseif(strpos(strtolower($_SERVER['SERVER_SOFTWARE']), 'apache' ) !== false){
|
||||
// Apache server
|
||||
$serverData->type = 'apache';
|
||||
$serverData->requiredVersion = $f3->get('REQUIREMENTS.SERVER.APACHE.VERSION');
|
||||
|
||||
// try to get the apache version...
|
||||
if(function_exists('apache_get_version')){
|
||||
// function does not exists if PHP is running as CGI/FPM module!
|
||||
$matches = preg_split('/[\s,\/ ]+/', strtolower( apache_get_version() ) );
|
||||
if(count($matches) > 1){
|
||||
$serverData->version = $matches[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// cache data for one day
|
||||
$f3->set($cacheKey, $serverData, $ttl);
|
||||
}
|
||||
|
||||
return $f3->get($cacheKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* check if the current request was send from inGame
|
||||
* @return bool
|
||||
@@ -242,7 +318,6 @@ class Controller {
|
||||
return $isIGB;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get error object is a user is not found/logged of
|
||||
* @return object
|
||||
@@ -290,72 +365,155 @@ class Controller {
|
||||
*/
|
||||
static function getEnvironmentData($key){
|
||||
$f3 = \Base::instance();
|
||||
$environment = $f3->get('PATHFINDER.ENVIRONMENT.SERVER');
|
||||
$environmentKey = 'PATHFINDER.ENVIRONMENT[' . $environment . '][' . $key . ']';
|
||||
$environment = self::getEnvironment();
|
||||
$environmentKey = 'ENVIRONMENT[' . $environment . '][' . $key . ']';
|
||||
$data = null;
|
||||
|
||||
if( $f3->exists($environmentKey) ){
|
||||
$data = $f3->get($environmentKey);
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* get current server environment status
|
||||
* -> "DEVELOP" or "PRODUCTION"
|
||||
* @return mixed
|
||||
*/
|
||||
static function getEnvironment(){
|
||||
$f3 = \Base::instance();
|
||||
return $f3->get('ENVIRONMENT.SERVER');
|
||||
}
|
||||
|
||||
/**
|
||||
* function is called on each error
|
||||
* check if current server is "PRODUCTION"
|
||||
* @return bool
|
||||
*/
|
||||
static function isProduction(){
|
||||
return self::getEnvironment() == 'PRODUCTION';
|
||||
}
|
||||
|
||||
/**
|
||||
* get required MySQL variable value
|
||||
* @param $key
|
||||
* @return mixed|null
|
||||
*/
|
||||
static function getRequiredMySqlVariables($key){
|
||||
$f3 = \Base::instance();
|
||||
$requiredMySqlVarKey = 'REQUIREMENTS[MYSQL][VARS][' . $key . ']';
|
||||
$data = null;
|
||||
|
||||
if( $f3->exists($requiredMySqlVarKey) ){
|
||||
$data = $f3->get($requiredMySqlVarKey);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* get a program URL by alias
|
||||
* -> if no $alias given -> get "default" route (index.php)
|
||||
* @param null $alias
|
||||
* @return bool
|
||||
*/
|
||||
protected function getRouteUrl($alias = null){
|
||||
$url = false;
|
||||
|
||||
if(!empty($alias)){
|
||||
// check given alias is a valid (registered) route
|
||||
if(array_key_exists($alias, $this->getF3()->get('ALIASES'))){
|
||||
$url = $this->getF3()->alias($alias);
|
||||
}
|
||||
}elseif($this->getF3()->get('ALIAS')){
|
||||
// get current URL
|
||||
$url = $this->getF3()->alias( $this->getF3()->get('ALIAS') );
|
||||
}else{
|
||||
// get main (index.php) URL
|
||||
$url = $this->getF3()->alias('landing');
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* get a custom userAgent string for API calls
|
||||
* @return string
|
||||
*/
|
||||
protected function getUserAgent(){
|
||||
$userAgent = '';
|
||||
|
||||
$userAgent .= $this->getF3()->get('PATHFINDER.NAME');
|
||||
$userAgent .= ' - ' . $this->getF3()->get('PATHFINDER.VERSION');
|
||||
$userAgent .= ' | ' . $this->getF3()->get('PATHFINDER.CONTACT');
|
||||
$userAgent .= ' (' . $_SERVER['SERVER_NAME'] . ')';
|
||||
|
||||
return $userAgent;
|
||||
}
|
||||
|
||||
/**
|
||||
* onError() callback function
|
||||
* -> on AJAX request -> return JSON with error information
|
||||
* -> on HTTP request -> render error page
|
||||
* @param $f3
|
||||
*/
|
||||
public function showError($f3){
|
||||
|
||||
// set HTTP status
|
||||
$errorCode = $f3->get('ERROR.code');
|
||||
if(!empty($errorCode)){
|
||||
$f3->status($errorCode);
|
||||
}
|
||||
|
||||
if($f3->get('AJAX')){
|
||||
// error on ajax call
|
||||
header('Content-type: application/json');
|
||||
// collect error info ---------------------------------------
|
||||
$return = (object) [];
|
||||
$error = (object) [];
|
||||
$error->type = 'error';
|
||||
$error->code = $errorCode;
|
||||
$error->status = $f3->get('ERROR.status');
|
||||
$error->message = $f3->get('ERROR.text');
|
||||
|
||||
$return = (object) [];
|
||||
$error = (object) [];
|
||||
$error->type = 'error';
|
||||
$error->code = $errorCode;
|
||||
$error->status = $f3->get('ERROR.status');
|
||||
$error->message = $f3->get('ERROR.text');
|
||||
|
||||
// append stack trace for greater debug level
|
||||
if( $f3->get('DEBUG') === 3){
|
||||
$error->trace = $f3->get('ERROR.trace');
|
||||
}
|
||||
|
||||
// check if error is a PDO Exception
|
||||
if(strpos(strtolower( $f3->get('ERROR.text') ), 'duplicate') !== false){
|
||||
preg_match_all('/\'([^\']+)\'/', $f3->get('ERROR.text'), $matches, PREG_SET_ORDER);
|
||||
|
||||
if(count($matches) === 2){
|
||||
$error->field = $matches[1][1];
|
||||
$error->message = 'Value "' . $matches[0][1] . '" already exists';
|
||||
}
|
||||
}
|
||||
|
||||
$return->error[] = $error;
|
||||
|
||||
echo json_encode($return);
|
||||
}else{
|
||||
echo $f3->get('ERROR.text');
|
||||
// append stack trace for greater debug level
|
||||
if( $f3->get('DEBUG') === 3){
|
||||
$error->trace = $f3->get('ERROR.trace');
|
||||
}
|
||||
|
||||
die();
|
||||
// check if error is a PDO Exception
|
||||
if(strpos(strtolower( $f3->get('ERROR.text') ), 'duplicate') !== false){
|
||||
preg_match_all('/\'([^\']+)\'/', $f3->get('ERROR.text'), $matches, PREG_SET_ORDER);
|
||||
|
||||
if(count($matches) === 2){
|
||||
$error->field = $matches[1][1];
|
||||
$error->message = 'Value "' . $matches[0][1] . '" already exists';
|
||||
}
|
||||
}
|
||||
$return->error[] = $error;
|
||||
|
||||
// return error information ---------------------------------
|
||||
if($f3->get('AJAX')){
|
||||
header('Content-type: application/json');
|
||||
echo json_encode($return);
|
||||
die();
|
||||
}else{
|
||||
// set error data for template rendering
|
||||
$error->redirectUrl = $this->getRouteUrl();
|
||||
$f3->set('errorData', $error);
|
||||
|
||||
if( preg_match('/^4[0-9]{2}$/', $error->code) ){
|
||||
// 4xx error -> render error page
|
||||
$f3->set('pageContent', $f3->get('PATHFINDER.STATUS.4XX'));
|
||||
}elseif( preg_match('/^5[0-9]{2}$/', $error->code) ){
|
||||
$f3->set('pageContent', $f3->get('PATHFINDER.STATUS.5XX'));
|
||||
}
|
||||
|
||||
echo \Template::instance()->render( $f3->get('PATHFINDER.VIEW.INDEX') );
|
||||
die();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for framework "unload"
|
||||
* -> config.ini
|
||||
* check -> config.ini
|
||||
*/
|
||||
public function unload(){
|
||||
|
||||
public function unload($f3){
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -27,21 +27,6 @@ class MailController extends \SMTP{
|
||||
$this->set('Content-Type', 'text/html; charset=ISO-8859-1');
|
||||
}
|
||||
|
||||
/**
|
||||
* send registration mail
|
||||
* @param $to
|
||||
* @param $msg
|
||||
* @return bool
|
||||
*/
|
||||
public function sendRegistration($to, $msg){
|
||||
$this->set('To', '<' . $to . '>');
|
||||
$this->set('From', 'Pathfinder <' . Controller::getEnvironmentData('SMTP_FROM') . '>');
|
||||
$this->set('Subject', 'Account information');
|
||||
$status = $this->send($msg);
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* send invite key mail
|
||||
* @param $to
|
||||
|
||||
@@ -10,25 +10,22 @@ namespace Controller;
|
||||
|
||||
class MapController extends \Controller\AccessController {
|
||||
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
|
||||
public function showMap($f3) {
|
||||
|
||||
// page title
|
||||
$f3->set('pageTitle', 'Maps');
|
||||
|
||||
// main page content
|
||||
$f3->set('pageContent', false);
|
||||
|
||||
// body element class
|
||||
$this->f3->set('bodyClass', 'pf-body');
|
||||
$f3->set('bodyClass', 'pf-body');
|
||||
|
||||
// set trust attribute to template
|
||||
$this->f3->set('trusted', (int)self::isIGBTrusted());
|
||||
$f3->set('trusted', (int)self::isIGBTrusted());
|
||||
|
||||
// JS main file
|
||||
$this->f3->set('jsView', 'mappage');
|
||||
|
||||
$this->setTemplate('templates/view/index.html');
|
||||
$f3->set('jsView', 'mappage');
|
||||
}
|
||||
|
||||
}
|
||||
639
app/main/controller/setup.php
Normal file
@@ -0,0 +1,639 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Exodus
|
||||
* Date: 22.11.2015
|
||||
* Time: 10:59
|
||||
*/
|
||||
|
||||
namespace Controller;
|
||||
|
||||
use DB;
|
||||
use DB\SQL;
|
||||
use DB\SQL\MySQL as MySQL;
|
||||
|
||||
use Model;
|
||||
|
||||
class Setup extends Controller {
|
||||
|
||||
protected $databases = [
|
||||
'PF' => [
|
||||
'info' => [],
|
||||
'models' => [
|
||||
'Model\UserModel',
|
||||
'Model\AllianceModel',
|
||||
'Model\CorporationModel',
|
||||
'Model\MapModel',
|
||||
'Model\MapScopeModel',
|
||||
'Model\MapTypeModel',
|
||||
'Model\SystemTypeModel',
|
||||
'Model\SystemStatusModel',
|
||||
'Model\SystemNeighbourModel',
|
||||
'Model\WormholeModel',
|
||||
'Model\RegistrationKeyModel',
|
||||
|
||||
'Model\CharacterStatusModel',
|
||||
'Model\ConnectionScopeModel',
|
||||
|
||||
'Model\UserMapModel',
|
||||
'Model\AllianceMapModel',
|
||||
'Model\CorporationMapModel',
|
||||
|
||||
'Model\UserApiModel',
|
||||
'Model\UserCharacterModel',
|
||||
'Model\CharacterModel',
|
||||
'Model\CharacterLogModel',
|
||||
|
||||
'Model\SystemModel',
|
||||
'Model\SystemWormholeModel',
|
||||
|
||||
'Model\ConnectionModel',
|
||||
'Model\SystemSignatureModel',
|
||||
|
||||
'Model\SystemShipKillModel',
|
||||
'Model\SystemPodKillModel',
|
||||
'Model\SystemFactionKillModel',
|
||||
'Model\SystemJumpModel'
|
||||
],
|
||||
'tables' => []
|
||||
],
|
||||
'CCP' => [
|
||||
'info' => [],
|
||||
'models' => [],
|
||||
'tables' => [
|
||||
'invTypes',
|
||||
'mapConstellations',
|
||||
'mapDenormalize',
|
||||
'mapLocationWormholeClasses',
|
||||
'mapRegions',
|
||||
'mapSolarSystemJumps',
|
||||
'mapSolarSystems'
|
||||
]
|
||||
|
||||
]
|
||||
];
|
||||
|
||||
/**
|
||||
* event handler for all "views"
|
||||
* some global template variables are set in here
|
||||
* @param $f3
|
||||
*/
|
||||
function beforeroute($f3) {
|
||||
// page title
|
||||
$f3->set('pageTitle', 'Setup');
|
||||
|
||||
// main page content
|
||||
$f3->set('pageContent', $f3->get('PATHFINDER.VIEW.SETUP'));
|
||||
|
||||
// body element class
|
||||
$f3->set('bodyClass', 'pf-body pf-landing');
|
||||
|
||||
// js path (build/minified or raw uncompressed files)
|
||||
$f3->set('pathJs', 'public/js/' . $f3->get('PATHFINDER.VERSION') );
|
||||
}
|
||||
|
||||
public function afterroute($f3) {
|
||||
// js view (file)
|
||||
$f3->set('jsView', 'setup');
|
||||
|
||||
// render view
|
||||
echo \Template::instance()->render( $f3->get('PATHFINDER.VIEW.INDEX') );
|
||||
}
|
||||
|
||||
/**
|
||||
* main setup route handler
|
||||
* works as dispatcher for setup functions
|
||||
* @param $f3
|
||||
*/
|
||||
public function init($f3){
|
||||
$params = $f3->get('GET');
|
||||
|
||||
// enables automatic column fix
|
||||
$fixColumns = false;
|
||||
|
||||
// bootstrap database from model class definition
|
||||
if(
|
||||
isset($params['db']) &&
|
||||
!empty($params['db'])
|
||||
){
|
||||
$this->bootstrapDB($params['db']);
|
||||
|
||||
// reload page
|
||||
// -> remove GET param
|
||||
$f3->reroute('@setup');
|
||||
return;
|
||||
}elseif(
|
||||
isset($params['fixCols']) &&
|
||||
!empty($params['fixCols'])
|
||||
){
|
||||
$fixColumns = true;
|
||||
}
|
||||
|
||||
// set server information for page render
|
||||
$f3->set('serverInformation', $this->getServerInformation($f3));
|
||||
|
||||
// set requirement check information for page render
|
||||
$f3->set('checkRequirements', $this->checkRequirements($f3));
|
||||
|
||||
// set database connection information for page render
|
||||
$f3->set('checkDatabase', $this->checkDatabase($f3, $fixColumns));
|
||||
}
|
||||
|
||||
/**
|
||||
* get server information
|
||||
* @param $f3
|
||||
* @return array
|
||||
*/
|
||||
protected function getServerInformation($f3){
|
||||
$serverInfo = [
|
||||
'time' => [
|
||||
'label' => 'Time',
|
||||
'value' => date('Y/m/d H:i:s') . ' - (' . date_default_timezone_get() . ')'
|
||||
],
|
||||
'os' => [
|
||||
'label' => 'OS',
|
||||
'value' => php_uname('s')
|
||||
],
|
||||
'name' => [
|
||||
'label' => 'Host name',
|
||||
'value' => php_uname('n')
|
||||
],
|
||||
'release' => [
|
||||
'label' => 'Release name',
|
||||
'value' => php_uname('r')
|
||||
],
|
||||
'version' => [
|
||||
'label' => 'Version info',
|
||||
'value' => php_uname('v')
|
||||
],
|
||||
'machine' => [
|
||||
'label' => 'Machine type',
|
||||
'value' => php_uname('m')
|
||||
]
|
||||
];
|
||||
|
||||
return $serverInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* check all required backend requirements
|
||||
* (Fat Free Framework)
|
||||
* @param $f3
|
||||
* @return array
|
||||
*/
|
||||
protected function checkRequirements($f3){
|
||||
|
||||
|
||||
// server type ------------------------------------------------------------------
|
||||
$serverData = self::getServerData(0);
|
||||
|
||||
$checkRequirements = [
|
||||
'serverType' => [
|
||||
'label' => 'Server type',
|
||||
'version' => $serverData->type,
|
||||
'check' => true
|
||||
],
|
||||
'serverVersion' => [
|
||||
'label' => 'Server version',
|
||||
'required' => $serverData->requiredVersion,
|
||||
'version' => $serverData->version,
|
||||
'check' => version_compare( $serverData->version, $serverData->requiredVersion, '>='),
|
||||
'tooltip' => 'If not specified, please check your \'ServerTokens\' server config. (not critical)'
|
||||
],
|
||||
'phpInterface' => [
|
||||
'label' => 'PHP interface type',
|
||||
'version' => $serverData->phpInterfaceType,
|
||||
'check' => empty($serverData->phpInterfaceType) ? false : true
|
||||
],
|
||||
'php' => [
|
||||
'label' => 'PHP',
|
||||
'required' => $f3->get('REQUIREMENTS.PHP.VERSION'),
|
||||
'version' => phpversion(),
|
||||
'check' => version_compare( phpversion(), $f3->get('REQUIREMENTS.PHP.VERSION'), '>=')
|
||||
],
|
||||
'pcre' => [
|
||||
'label' => 'PCRE',
|
||||
'required' => $f3->get('REQUIREMENTS.PHP.PCRE_VERSION'),
|
||||
'version' => strstr(PCRE_VERSION, ' ', true),
|
||||
'check' => version_compare( strstr(PCRE_VERSION, ' ', true), $f3->get('REQUIREMENTS.PHP.PCRE_VERSION'), '>=')
|
||||
],
|
||||
'gd' => [
|
||||
'label' => 'GD Library (for Image plugin)',
|
||||
'required' => 'installed',
|
||||
'version' => (extension_loaded('gd') && function_exists('gd_info')) ? 'installed' : 'not installed',
|
||||
'check' => (extension_loaded('gd') && function_exists('gd_info'))
|
||||
],
|
||||
'curl' => [
|
||||
'label' => 'cURL (for Web plugin)',
|
||||
'required' => 'installed',
|
||||
'version' => (extension_loaded('curl') && function_exists('curl_version')) ? 'installed' : 'not installed',
|
||||
'check' => (extension_loaded('curl') && function_exists('curl_version'))
|
||||
]
|
||||
];
|
||||
|
||||
if($serverData->type != 'nginx'){
|
||||
// default msg if module status not available
|
||||
$modNotFoundMsg = 'Module status can not be identified. '
|
||||
. 'This can happen if PHP runs as \'FastCGI\'. Please check manual! ';
|
||||
|
||||
// mod_rewrite check ------------------------------------------------------------
|
||||
$modRewriteCheck = false;
|
||||
$modRewriteVersion = 'disabled';
|
||||
$modRewriteTooltip = false;
|
||||
if(function_exists('apache_get_modules')){
|
||||
if(in_array('mod_rewrite',apache_get_modules())){
|
||||
$modRewriteCheck = true;
|
||||
$modRewriteVersion = 'enabled';
|
||||
}
|
||||
}else{
|
||||
// e.g. Nginx server
|
||||
$modRewriteVersion = 'unknown';
|
||||
$modRewriteTooltip = $modNotFoundMsg;
|
||||
}
|
||||
|
||||
$checkRequirements['mod_rewrite'] = [
|
||||
'label' => 'mod_rewrite',
|
||||
'required' => 'enabled',
|
||||
'version' => $modRewriteVersion,
|
||||
'check' => $modRewriteCheck,
|
||||
'tooltip' => $modRewriteTooltip
|
||||
];
|
||||
|
||||
// mod_headers check ------------------------------------------------------------
|
||||
$modHeadersCheck = false;
|
||||
$modHeadersVersion = 'disabled';
|
||||
$modHeadersTooltip = false;
|
||||
if(function_exists('apache_get_modules')){
|
||||
if(in_array('mod_headers',apache_get_modules())){
|
||||
$modHeadersCheck = true;
|
||||
$modHeadersVersion = 'enabled';
|
||||
}
|
||||
}else{
|
||||
// e.g. Nginx server
|
||||
$modHeadersVersion = 'unknown';
|
||||
$modHeadersTooltip = $modNotFoundMsg;
|
||||
}
|
||||
|
||||
$checkRequirements['mod_headers'] = [
|
||||
'label' => 'mod_headers',
|
||||
'required' => 'enabled',
|
||||
'version' => $modHeadersVersion,
|
||||
'check' => $modHeadersCheck,
|
||||
'tooltip' => $modHeadersTooltip
|
||||
];
|
||||
}
|
||||
|
||||
return $checkRequirements;
|
||||
}
|
||||
|
||||
/**
|
||||
* get database connection information
|
||||
* @param $f3
|
||||
* @param bool|false $exec
|
||||
* @return array
|
||||
*/
|
||||
protected function checkDatabase($f3, $exec = false){
|
||||
|
||||
foreach($this->databases as $dbKey => $dbData){
|
||||
|
||||
$dbLabel = '';
|
||||
$dbName = '';
|
||||
$dbUser = '';
|
||||
$dbConfig = [];
|
||||
|
||||
// DB connection status
|
||||
$dbConnected = false;
|
||||
// DB type (e.g. MySql,..)
|
||||
$dbDriver = 'unknown';
|
||||
// enable database ::setup() function in UI
|
||||
$dbSetupEnable = false;
|
||||
// check of everything is OK (connection, tables, columns, indexes,..)
|
||||
$dbStatusCheckCount = 0;
|
||||
// db queries for column fixes (types, indexes, unique)
|
||||
$dbColumnQueries = [];
|
||||
// tables that should exist in this DB
|
||||
$requiredTables = [];
|
||||
// check DB for valid connection
|
||||
$db = DB\Database::instance()->getDB($dbKey);
|
||||
|
||||
switch($dbKey){
|
||||
case 'PF':
|
||||
$dbLabel = 'Pathfinder';
|
||||
$dbName = Controller::getEnvironmentData('DB_NAME');
|
||||
$dbUser = Controller::getEnvironmentData('DB_USER');
|
||||
|
||||
// enable (table) setup for this DB
|
||||
$dbSetupEnable = true;
|
||||
|
||||
// get table data from model
|
||||
foreach($dbData['models'] as $model){
|
||||
$tableConfig = call_user_func($model . '::resolveConfiguration');
|
||||
$requiredTables[$tableConfig['table']] = [
|
||||
'model' => $model,
|
||||
'name' => $tableConfig['table'],
|
||||
'fieldConf' => $tableConfig['fieldConf'],
|
||||
'exists' => false,
|
||||
'empty' => true,
|
||||
'foreignKeys' => []
|
||||
];
|
||||
}
|
||||
break;
|
||||
case 'CCP':
|
||||
$dbLabel = 'EVE-Online [SDE]';
|
||||
$dbName = Controller::getEnvironmentData('DB_CCP_NAME');
|
||||
$dbUser = Controller::getEnvironmentData('DB_CCP_USER');
|
||||
|
||||
// get table model from static table array
|
||||
foreach($dbData['tables'] as $tableName){
|
||||
$requiredTables[$tableName] = [
|
||||
'exists' => false,
|
||||
'empty' => true
|
||||
];
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if($db){
|
||||
// db connect was successful
|
||||
$dbConnected = true;
|
||||
$dbDriver = $db->driver();
|
||||
$dbConfig = $this->checkDBConfig($f3, $db);
|
||||
|
||||
// get tables
|
||||
$schema = new SQL\Schema($db);
|
||||
$currentTables = $schema->getTables();
|
||||
|
||||
// check each table for changes
|
||||
foreach($requiredTables as $requiredTableName => $data){
|
||||
|
||||
$tableExists = false;
|
||||
$tableEmpty = true;
|
||||
// Check if table status is OK (no errors/warnings,..)
|
||||
$tableStatusCheckCount = 0;
|
||||
|
||||
$currentColumns = [];
|
||||
if(in_array($requiredTableName, $currentTables)){
|
||||
// Table exists
|
||||
$tableExists = true;
|
||||
// get existing table columns and column related constraints (if exists)
|
||||
$tableModifierTemp = new MySQL\TableModifier($requiredTableName, $schema);
|
||||
$currentColumns = $tableModifierTemp->getCols(true);
|
||||
// get row count
|
||||
$countRes = $db->exec("SELECT COUNT(*) `num` FROM " . $db->quotekey($requiredTableName) );
|
||||
$tableEmpty = $countRes[0]['num'] > 0 ? false : true;
|
||||
}else{
|
||||
// table missing
|
||||
$dbStatusCheckCount++;
|
||||
$tableStatusCheckCount++;
|
||||
}
|
||||
|
||||
foreach((array)$data['fieldConf'] as $columnName => $fieldConf){
|
||||
|
||||
$columnStatusCheck = true;
|
||||
$foreignKeyStatusCheck = true;
|
||||
$requiredTables[$requiredTableName]['fieldConf'][$columnName]['requiredType'] = $fieldConf['type'];
|
||||
$requiredTables[$requiredTableName]['fieldConf'][$columnName]['requiredIndex'] = ($fieldConf['index']) ? '1' : '0';
|
||||
$requiredTables[$requiredTableName]['fieldConf'][$columnName]['requiredUnique'] = ($fieldConf['unique']) ? '1' : '0';
|
||||
|
||||
if(array_key_exists($columnName, $currentColumns)){
|
||||
// column exists
|
||||
|
||||
// get tableModifier -> possible column update
|
||||
$tableModifier = new MySQL\TableModifier($requiredTableName, $schema);
|
||||
|
||||
// get new column and copy Schema from existing column
|
||||
$col = new MySQL\Column($columnName, $tableModifier);
|
||||
$col->copyfrom($currentColumns[$columnName]);
|
||||
|
||||
$currentColType = $currentColumns[$columnName]['type'];
|
||||
$currentColIndexData = call_user_func($data['model'] . '::indexExists', [$columnName]);
|
||||
$currentColIndex = is_array($currentColIndexData);
|
||||
$hasIndex = ($currentColIndex) ? '1' : '0';
|
||||
$hasUnique = ($currentColIndexData['unique']) ? '1' : '0';
|
||||
$changedType = false;
|
||||
$changedUnique = false;
|
||||
$changedIndex = false;
|
||||
|
||||
// set (new) column information -------------------------------------------------------
|
||||
$requiredTables[$requiredTableName]['fieldConf'][$columnName]['exists'] = true;
|
||||
$requiredTables[$requiredTableName]['fieldConf'][$columnName]['currentType'] = $currentColType;
|
||||
$requiredTables[$requiredTableName]['fieldConf'][$columnName]['currentIndex'] = $hasIndex;
|
||||
$requiredTables[$requiredTableName]['fieldConf'][$columnName]['currentUnique'] = $hasUnique;
|
||||
|
||||
// check constraint -------------------------------------------------------------------
|
||||
if(isset($fieldConf['constraint'])){
|
||||
// add or update constraints
|
||||
foreach((array)$fieldConf['constraint'] as $constraintData){
|
||||
$constraint = $col->newConstraint($constraintData);
|
||||
|
||||
$foreignKeyExists = $col->constraintExists($constraint);
|
||||
$requiredTables[$requiredTableName]['foreignKeys'][] = [
|
||||
'exists' => $foreignKeyExists,
|
||||
'keyName' => $constraint->getConstraintName()
|
||||
];
|
||||
|
||||
$col->addConstraint($constraint);
|
||||
|
||||
if(!$foreignKeyExists){
|
||||
$tableStatusCheckCount++;
|
||||
$foreignKeyStatusCheck = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check type changed -----------------------------------------------------------------
|
||||
if(
|
||||
$fieldConf['type'] !== 'JSON' &&
|
||||
!$schema->isCompatible($fieldConf['type'], $currentColType)
|
||||
){
|
||||
// column type has changed
|
||||
$changedType = true;
|
||||
$columnStatusCheck = false;
|
||||
$tableStatusCheckCount++;
|
||||
}
|
||||
|
||||
// check if column unique changed -----------------------------------------------------
|
||||
$indexUpdate = false;
|
||||
$indexKey = (bool)$hasIndex;
|
||||
$indexUnique = (bool)$hasUnique;
|
||||
|
||||
if($currentColIndexData['unique'] != $fieldConf['unique']){
|
||||
$changedUnique = true;
|
||||
$columnStatusCheck = false;
|
||||
$tableStatusCheckCount++;
|
||||
|
||||
$indexUpdate = true;
|
||||
$indexUnique =(bool)$fieldConf['unique'];
|
||||
}
|
||||
|
||||
// check if column index changed ------------------------------------------------------
|
||||
if($currentColIndex != $fieldConf['index']){
|
||||
$changedIndex = true;
|
||||
$columnStatusCheck = false;
|
||||
$tableStatusCheckCount++;
|
||||
|
||||
$indexUpdate = true;
|
||||
$indexKey = (bool) $fieldConf['index'];
|
||||
}
|
||||
// build table with changed columns ---------------------------------------------------
|
||||
if(!$columnStatusCheck || !$foreignKeyStatusCheck){
|
||||
|
||||
if(!$columnStatusCheck ){
|
||||
// IMPORTANT: setType is always required! Even if type has not changed
|
||||
$col->type($fieldConf['type']);
|
||||
|
||||
// update/change/delete index/unique keys
|
||||
if($indexUpdate){
|
||||
if($hasIndex){
|
||||
$tableModifier->dropIndex($columnName);
|
||||
}
|
||||
|
||||
if($indexKey){
|
||||
$tableModifier->addIndex($columnName, $indexUnique);
|
||||
}
|
||||
}
|
||||
$tableModifier->updateColumn($columnName, $col);
|
||||
}
|
||||
|
||||
$buildStatus = $tableModifier->build($exec);
|
||||
|
||||
if(
|
||||
is_array($buildStatus) ||
|
||||
is_string($buildStatus)
|
||||
){
|
||||
// query strings for change available
|
||||
$dbColumnQueries = array_merge($dbColumnQueries, (array)$buildStatus);
|
||||
}
|
||||
}
|
||||
|
||||
// set (new) column information -------------------------------------------------------
|
||||
$requiredTables[$requiredTableName]['fieldConf'][$columnName]['changedType'] = $changedType;
|
||||
$requiredTables[$requiredTableName]['fieldConf'][$columnName]['changedUnique'] = $changedUnique;
|
||||
$requiredTables[$requiredTableName]['fieldConf'][$columnName]['changedIndex'] = $changedIndex;
|
||||
|
||||
}elseif(
|
||||
!isset($fieldConf['has-manny']) &&
|
||||
isset($fieldConf['type'])
|
||||
){
|
||||
// column not exists but it is required!
|
||||
// columns that do not match this criteria ("mas-manny") are "virtual" fields
|
||||
// and can be ignored
|
||||
$requiredTables[$requiredTableName]['fieldConf'][$columnName]['currentType'] = '';
|
||||
$columnStatusCheck = false;
|
||||
$tableStatusCheckCount++;
|
||||
}
|
||||
$requiredTables[$requiredTableName]['fieldConf'][$columnName]['statusCheck'] = $columnStatusCheck;
|
||||
}
|
||||
|
||||
$dbStatusCheckCount += $tableStatusCheckCount;
|
||||
$requiredTables[$requiredTableName]['empty'] = $tableEmpty;
|
||||
$requiredTables[$requiredTableName]['exists'] = $tableExists;
|
||||
$requiredTables[$requiredTableName]['statusCheckCount'] = $tableStatusCheckCount;
|
||||
}
|
||||
|
||||
}else{
|
||||
// DB connection failed
|
||||
$dbStatusCheckCount++;
|
||||
}
|
||||
|
||||
if($exec){
|
||||
$f3->reroute('@setup');
|
||||
}
|
||||
|
||||
$this->databases[$dbKey]['info'] = [
|
||||
'db' => $db,
|
||||
'label' => $dbLabel,
|
||||
'driver' => $dbDriver,
|
||||
'name' => $dbName,
|
||||
'user' => $dbUser,
|
||||
'dbConfig' => $dbConfig,
|
||||
'setupEnable' => $dbSetupEnable,
|
||||
'connected' => $dbConnected,
|
||||
'statusCheckCount' => $dbStatusCheckCount,
|
||||
'columnQueries' => $dbColumnQueries,
|
||||
'tableData' => $requiredTables
|
||||
];
|
||||
}
|
||||
|
||||
return $this->databases;
|
||||
}
|
||||
|
||||
/** check MySQL params
|
||||
* @param $f3
|
||||
* @param $db
|
||||
* @return array
|
||||
*/
|
||||
protected function checkDBConfig($f3, $db){
|
||||
|
||||
// some db like "Maria DB" have some strange version strings....
|
||||
$dbVersionString = $db->version();
|
||||
$dbVersionParts = explode('-', $dbVersionString);
|
||||
$dbVersion = 'unknown';
|
||||
foreach($dbVersionParts as $dbVersionPart){
|
||||
// check if this is a valid version number
|
||||
// hint: MariaDB´s version is always the last valid version number...
|
||||
if( version_compare( $dbVersionPart, '0.0.1', '>=' ) > 0 ){
|
||||
$dbVersion = $dbVersionPart;
|
||||
}
|
||||
}
|
||||
|
||||
$dbConfig = [
|
||||
'version' => [
|
||||
'label' => 'DB version',
|
||||
'required' => $f3->get('REQUIREMENTS.MYSQL.VERSION'),
|
||||
'version' => $dbVersion,
|
||||
'check' => version_compare($dbVersion, $f3->get('REQUIREMENTS.MYSQL.VERSION'), '>=' )
|
||||
]
|
||||
];
|
||||
|
||||
// get specific MySQL config Value
|
||||
$getDBConfigValue = function($db, $param){
|
||||
$result = $db->exec([
|
||||
//"USE " . $db->name(),
|
||||
"SHOW VARIABLES LIKE '" . strtolower($param) . "'"
|
||||
]);
|
||||
$tmpResult = reset($result);
|
||||
return !empty($result)? end($tmpResult) : 'unknown';
|
||||
};
|
||||
|
||||
$mySQLConfigParams = $f3->get('REQUIREMENTS.MYSQL.VARS');
|
||||
foreach($mySQLConfigParams as $param => $requiredValue){
|
||||
$value = $getDBConfigValue($db, $param);
|
||||
$dbConfig[] = [
|
||||
'label' => strtolower($param),
|
||||
'required' => $requiredValue,
|
||||
'version' => $value,
|
||||
'check' => !empty($requiredValue) ? ($requiredValue == $value) : true
|
||||
];
|
||||
}
|
||||
|
||||
return $dbConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* init the complete database
|
||||
* - create tables
|
||||
* - create indexes
|
||||
* - set default static values
|
||||
* @param $dbKey
|
||||
* @return array
|
||||
*/
|
||||
protected function bootstrapDB($dbKey){
|
||||
$db = DB\Database::instance()->getDB($dbKey);
|
||||
|
||||
$checkTables = [];
|
||||
if($db){
|
||||
// set/change default "character set" and "collation"
|
||||
$db->exec('ALTER DATABASE ' . $db->name()
|
||||
. ' CHARACTER SET ' . self::getRequiredMySqlVariables('CHARACTER_SET_DATABASE')
|
||||
. ' COLLATE ' . self::getRequiredMySqlVariables('COLLATION_DATABASE')
|
||||
);
|
||||
|
||||
// setup tables
|
||||
foreach($this->databases[$dbKey]['models'] as $modelClass){
|
||||
$checkTables[] = call_user_func($modelClass . '::setup');
|
||||
}
|
||||
}
|
||||
return $checkTables;
|
||||
}
|
||||
}
|
||||
@@ -145,6 +145,7 @@ class CcpSystemsUpdate {
|
||||
$sql = "UPDATE
|
||||
" . $tableName . "
|
||||
SET
|
||||
updated = now(),
|
||||
value24 = value23,
|
||||
value23 = value22,
|
||||
value22 = value21,
|
||||
|
||||
@@ -30,36 +30,35 @@ class Database extends \Prefab {
|
||||
// "Hive" Key for DB storage
|
||||
$dbHiveKey = $this->getDbHiveKey($database);
|
||||
|
||||
if($database === 'CCP'){
|
||||
// CCP DB
|
||||
$dns = Controller\Controller::getEnvironmentData('DB_CCP_DNS');
|
||||
$name = Controller\Controller::getEnvironmentData('DB_CCP_NAME');
|
||||
$user = Controller\Controller::getEnvironmentData('DB_CCP_USER');
|
||||
$password = Controller\Controller::getEnvironmentData('DB_CCP_PASS');
|
||||
}else{
|
||||
// Pathfinder(PF) DB
|
||||
$dns = Controller\Controller::getEnvironmentData('DB_DNS');
|
||||
$name = Controller\Controller::getEnvironmentData('DB_NAME');
|
||||
$user = Controller\Controller::getEnvironmentData('DB_USER');
|
||||
$password = Controller\Controller::getEnvironmentData('DB_PASS');
|
||||
}
|
||||
|
||||
// check if DB connection already exists
|
||||
if(
|
||||
!$f3->exists( $dbHiveKey ) ||
|
||||
$name !== $f3->get( $dbHiveKey )->name()
|
||||
){
|
||||
if( !$f3->exists( $dbHiveKey ) ){
|
||||
if($database === 'CCP'){
|
||||
// CCP DB
|
||||
$dns = Controller\Controller::getEnvironmentData('DB_CCP_DNS');
|
||||
$name = Controller\Controller::getEnvironmentData('DB_CCP_NAME');
|
||||
$user = Controller\Controller::getEnvironmentData('DB_CCP_USER');
|
||||
$password = Controller\Controller::getEnvironmentData('DB_CCP_PASS');
|
||||
}else{
|
||||
// Pathfinder(PF) DB
|
||||
$dns = Controller\Controller::getEnvironmentData('DB_DNS');
|
||||
$name = Controller\Controller::getEnvironmentData('DB_NAME');
|
||||
$user = Controller\Controller::getEnvironmentData('DB_USER');
|
||||
$password = Controller\Controller::getEnvironmentData('DB_PASS');
|
||||
}
|
||||
|
||||
$db = $this->connect($dns, $name, $user, $password);
|
||||
|
||||
// set DB timezone to UTC +00:00 (eve server time)
|
||||
$db->exec('SET @@session.time_zone = "+00:00";');
|
||||
if( !is_null($db) ){
|
||||
// set DB timezone to UTC +00:00 (eve server time)
|
||||
$db->exec('SET @@session.time_zone = "+00:00";');
|
||||
|
||||
// disable innoDB schema (relevant vor MySql 5.5)
|
||||
// not necessary for MySql > v.5.6
|
||||
// $db->exec('SET GLOBAL innodb_stats_on_metadata = OFF;');
|
||||
// set default storage engine
|
||||
$db->exec('SET @@session.default_storage_engine = "' .
|
||||
Controller\Controller::getRequiredMySqlVariables('DEFAULT_STORAGE_ENGINE') . '"');
|
||||
|
||||
// store DB object
|
||||
$f3->set($dbHiveKey, $db);
|
||||
// store DB object
|
||||
$f3->set($dbHiveKey, $db);
|
||||
}
|
||||
|
||||
return $db;
|
||||
}else{
|
||||
@@ -104,6 +103,8 @@ class Database extends \Prefab {
|
||||
*/
|
||||
protected function connect($dns, $name, $user, $password){
|
||||
|
||||
$db = null;
|
||||
|
||||
try {
|
||||
$db = new SQL(
|
||||
$dns . $name,
|
||||
@@ -115,6 +116,7 @@ class Database extends \Prefab {
|
||||
);
|
||||
}catch(\PDOException $e){
|
||||
// DB connection error
|
||||
// -> log it
|
||||
LogController::getLogger('error')->write($e->getMessage());
|
||||
}
|
||||
|
||||
|
||||
333
app/main/db/sql/mysql/tablemodifier.php
Normal file
@@ -0,0 +1,333 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Exodus
|
||||
* Date: 19.12.2015
|
||||
* Time: 12:47
|
||||
*
|
||||
* This is an "on top" extension for "Schema Builder"
|
||||
* see: https://github.com/ikkez/f3-schema-builder
|
||||
*
|
||||
* Features:
|
||||
* - FOREIGN KEY CONSTRAINTS (single column key)
|
||||
*/
|
||||
|
||||
namespace DB\SQL\MySQL;
|
||||
use DB\SQL;
|
||||
|
||||
class TableModifier extends SQL\TableModifier {
|
||||
|
||||
const TEXT_ConstraintNotValid = 'Constraint `%s` is not valid';
|
||||
|
||||
|
||||
/**
|
||||
* return table foreign key constraints as assoc array
|
||||
* -> if §constraint is passed, constraints are limited to that column
|
||||
* @param null| \DB\SQL\MySQL\Constraint $constraint
|
||||
* @return Constraint[]
|
||||
*/
|
||||
public function listConstraint($constraint = null){
|
||||
|
||||
$constraintName = '%';
|
||||
$keys = [];
|
||||
if($constraint instanceof Constraint){
|
||||
// list constraints for given column in this table
|
||||
$constraintName = $constraint->getConstraintName() . '%';
|
||||
$keys = $constraint->getKeys();
|
||||
}
|
||||
|
||||
$this->db->exec("USE information_schema");
|
||||
$constraintsData = $this->db->exec("
|
||||
SELECT
|
||||
*
|
||||
FROM
|
||||
referential_constraints
|
||||
WHERE
|
||||
constraint_schema = :db AND
|
||||
table_name = :table AND
|
||||
constraint_name LIKE :constraint_name
|
||||
", [
|
||||
':db' => $this->db->name(),
|
||||
':table' => $this->name,
|
||||
':constraint_name' => $constraintName
|
||||
]);
|
||||
// switch back to current DB
|
||||
$this->db->exec("USE " . $this->db->name());
|
||||
|
||||
$constraints = [];
|
||||
foreach($constraintsData as $data){
|
||||
$constraints[$data['CONSTRAINT_NAME']] = new Constraint($this, $keys, $data['REFERENCED_TABLE_NAME'] );
|
||||
}
|
||||
|
||||
return $constraints;
|
||||
}
|
||||
|
||||
/**
|
||||
* checks whether a constraint name exists or not
|
||||
* -> does not check constraint params
|
||||
* @param \DB\SQL\MySQL\Constraint $constraint
|
||||
* @return bool
|
||||
*/
|
||||
public function constraintExists($constraint){
|
||||
$constraints = $this->listConstraint();
|
||||
return array_key_exists($constraint->getConstraintName(), $constraints);
|
||||
}
|
||||
|
||||
/**
|
||||
* drop foreign key constraint
|
||||
* @param \DB\SQL\MySQL\Constraint $constraint
|
||||
*/
|
||||
public function dropConstraint($constraint){
|
||||
if($constraint->isValid()){
|
||||
$this->queries[] = "ALTER TABLE " . $this->db->quotekey($this->name) . "
|
||||
DROP FOREIGN KEY " . $this->db->quotekey($constraint->getConstraintName());
|
||||
}else{
|
||||
trigger_error(sprintf(self::TEXT_ConstraintNotValid, 'table: ' . $this->name . ' constraintName: ' . $constraint->getConstraintName()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add/Update foreign key constraint
|
||||
* @param \DB\SQL\MySQL\Constraint $constraint
|
||||
*/
|
||||
public function addConstraint($constraint){
|
||||
|
||||
if($constraint->isValid()){
|
||||
if($this->constraintExists($constraint)){
|
||||
// drop constraint and re-add in case something has changed
|
||||
$this->dropConstraint($constraint);
|
||||
}
|
||||
|
||||
$this->queries[] = "
|
||||
ALTER TABLE " . $this->db->quotekey($this->name) . "
|
||||
ADD CONSTRAINT " . $this->db->quotekey($constraint->getConstraintName()) . "
|
||||
FOREIGN KEY (" . implode(', ', $constraint->getKeys()) . ")
|
||||
REFERENCES " . $this->db->quotekey($constraint->getReferencedTable()) . " (" . implode(', ', $constraint->getReferencedCols()) . ")
|
||||
ON DELETE " . $constraint->getOnDelete() . "
|
||||
ON UPDATE " . $constraint->getOnUpdate();
|
||||
}else{
|
||||
trigger_error(sprintf(self::TEXT_ConstraintNotValid, 'table: ' . $this->name . ' constraintName: ' . $constraint->getConstraintName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class Column
|
||||
* @package DB\SQL\MySQL
|
||||
*/
|
||||
class Column extends SQL\Column {
|
||||
|
||||
const TEXT_TableNameMissing = 'Table name missing for FOREIGN KEY in `%s`';
|
||||
|
||||
/**
|
||||
* ass constraint to this column
|
||||
* @param Constraint $constraint
|
||||
*/
|
||||
public function addConstraint(Constraint $constraint){
|
||||
$this->table->addConstraint($constraint);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \DB\SQL\MySQL\TableModifier->constraintExists();
|
||||
* @param Constraint $constraint
|
||||
* @return mixed
|
||||
*/
|
||||
public function constraintExists(Constraint $constraint){
|
||||
return $this->table->constraintExists($constraint);
|
||||
}
|
||||
|
||||
/**
|
||||
* get a new column based constraint
|
||||
* $constraintData['table'] => referenceTable name (required)
|
||||
* $constraintData['id'] => referenceColumns (optional) default: ['id']
|
||||
* $constraintData['on-delete'] => ON DELETE action (optional) default: see \DB\SQL\MySQL\Constraint const
|
||||
* $constraintData['on-update'] => ON UPDATE action (optional) default: see \DB\SQL\MySQL\Constraint const
|
||||
*
|
||||
* @param array $constraintData
|
||||
* @return \DB\SQL\MySQL\Constraint
|
||||
*/
|
||||
public function newConstraint($constraintData){
|
||||
|
||||
$constraint = null;
|
||||
|
||||
if(isset($constraintData['table'])){
|
||||
if(isset($constraintData['column'])){
|
||||
$constraintData['column'] = (array)$constraintData['column'];
|
||||
}else{
|
||||
$constraintData['column'] = ['id'];
|
||||
}
|
||||
|
||||
$constraint = new Constraint($this->table, $this->name, $constraintData['table'], $constraintData['column']);
|
||||
|
||||
if(isset($constraintData['on-delete'])){
|
||||
$constraint->setOnDelete($constraintData['on-delete']);
|
||||
}
|
||||
|
||||
if(isset($constraintData['on-update'])){
|
||||
$constraint->setOnUpdate($constraintData['on-update']);
|
||||
}
|
||||
|
||||
}else{
|
||||
trigger_error(sprintf(self::TEXT_TableNameMissing, $this->table->name . '->' . $this->name));
|
||||
}
|
||||
|
||||
return $constraint;
|
||||
}
|
||||
}
|
||||
|
||||
class Constraint {
|
||||
|
||||
// available actions
|
||||
const ACTIONS_DELETE = ['RESTRICT', 'CASCADE', 'SET NULL', 'NO ACTION'];
|
||||
const ACTIONS_UPDATE = ['RESTRICT', 'CASCADE', 'SET NULL', 'NO ACTION'];
|
||||
|
||||
// default actions
|
||||
const ACTION_DELETE = 'RESTRICT';
|
||||
const ACTION_UPDATE = 'RESTRICT';
|
||||
|
||||
const TEXT_ActionNotSupported = 'Constraint action `%s` is not supported.';
|
||||
|
||||
protected $table;
|
||||
protected $keys = [];
|
||||
protected $referencedTable = '';
|
||||
protected $referencedCols = [];
|
||||
protected $onDelete = self::ACTION_DELETE;
|
||||
protected $onUpdate = self::ACTION_UPDATE;
|
||||
|
||||
/**
|
||||
* Constraint constructor.
|
||||
* @param SQL\TableBuilder $table
|
||||
* @param array $keys
|
||||
* @param string $referencedTable
|
||||
* @param array $referencedCols
|
||||
*/
|
||||
public function __construct(SQL\TableBuilder $table, $keys = [], $referencedTable = '', $referencedCols = ['id']){
|
||||
$this->table = &$table;
|
||||
$this->setKeys($keys);
|
||||
$this->setReferencedTable($referencedTable);
|
||||
$this->setReferencedCols($referencedCols);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $keys
|
||||
*/
|
||||
public function setKeys($keys){
|
||||
$this->keys = (array)$keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $referencedTable
|
||||
*/
|
||||
public function setReferencedTable($referencedTable){
|
||||
$this->referencedTable = $referencedTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $referencedCols
|
||||
*/
|
||||
public function setReferencedCols($referencedCols){
|
||||
$this->referencedCols = (array)$referencedCols;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $onDelete
|
||||
*/
|
||||
public function setOnDelete($onDelete){
|
||||
if( in_array($onDelete, self::ACTIONS_DELETE) ){
|
||||
$this->onDelete = $onDelete;
|
||||
}else{
|
||||
trigger_error(sprintf(self::TEXT_ActionNotSupported, $onDelete));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $onUpdate
|
||||
*/
|
||||
public function setOnUpdate($onUpdate){
|
||||
if( in_array($onUpdate, self::ACTIONS_UPDATE) ){
|
||||
$this->onUpdate = $onUpdate;
|
||||
}else{
|
||||
trigger_error(sprintf(self::TEXT_ActionNotSupported, $onUpdate));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getKeys(){
|
||||
return $this->keys;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getReferencedTable(){
|
||||
return $this->referencedTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getReferencedCols(){
|
||||
return $this->referencedCols;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getOnDelete(){
|
||||
return $this->onDelete;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getOnUpdate(){
|
||||
return $this->onUpdate;
|
||||
}
|
||||
|
||||
/**
|
||||
* get a constraint name for this table.
|
||||
* This can either be used to generate unique constraint names for foreign keys in parent tables
|
||||
* or generate a "part" of a name. e.g. for db-Query all constraints of this table (ignore columns)
|
||||
* by "LIKE" selecting "information_schema"
|
||||
* -> To get a certain constraint or generate a unique constraint, ALL params are required!
|
||||
* @return string
|
||||
*/
|
||||
public function getConstraintName(){
|
||||
$constraintName = 'fk_' . $this->table->name;
|
||||
|
||||
if(!empty($this->getKeys())){
|
||||
$constraintName .= '___' . implode('__', $this->getKeys());
|
||||
if(!empty($this->getReferencedTable())){
|
||||
$constraintName .= '___' . $this->getReferencedTable();
|
||||
if(!empty($this->getReferencedCols())){
|
||||
$constraintName .= '___' . implode('__', $this->getReferencedCols());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $constraintName;
|
||||
}
|
||||
|
||||
/**
|
||||
* checks if constraint is valid
|
||||
* -> all required members must be set!
|
||||
* @return bool
|
||||
*/
|
||||
public function isValid(){
|
||||
$valid = false;
|
||||
|
||||
if(
|
||||
!empty($this->getKeys()) &&
|
||||
!empty($this->getReferencedTable()) &&
|
||||
!empty($this->getReferencedCols())
|
||||
){
|
||||
$valid = true;
|
||||
}
|
||||
|
||||
return $valid;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -8,18 +8,40 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class AllianceMapModel extends BasicModel {
|
||||
|
||||
|
||||
protected $table = 'alliance_map';
|
||||
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => true,
|
||||
'index' => true
|
||||
],
|
||||
'allianceId' => [
|
||||
'belongs-to-one' => 'Model\AllianceModel'
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\AllianceModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'alliance',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
],
|
||||
'mapId' => [
|
||||
'belongs-to-one' => 'Model\MapModel'
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\MapModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'map',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
@@ -32,4 +54,21 @@ class AllianceMapModel extends BasicModel {
|
||||
// clear map cache as well
|
||||
$this->mapId->clearCacheData();
|
||||
}
|
||||
|
||||
/**
|
||||
* overwrites parent
|
||||
* @param null $db
|
||||
* @param null $table
|
||||
* @param null $fields
|
||||
* @return bool
|
||||
*/
|
||||
public static function setup($db=null, $table=null, $fields=null){
|
||||
$status = parent::setup($db,$table,$fields);
|
||||
|
||||
if($status === true){
|
||||
$status = parent::setMultiColumnIndex(['allianceId', 'mapId'], true);
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
}
|
||||
@@ -8,11 +8,29 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class AllianceModel extends BasicModel {
|
||||
|
||||
protected $table = 'alliance';
|
||||
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => true,
|
||||
'index' => true
|
||||
],
|
||||
'name' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'shared' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => 0
|
||||
],
|
||||
'allianceCharacters' => [
|
||||
'has-many' => ['Model\CharacterModel', 'allianceId']
|
||||
],
|
||||
@@ -30,7 +48,7 @@ class AllianceModel extends BasicModel {
|
||||
|
||||
$allianceData->id = $this->id;
|
||||
$allianceData->name = $this->name;
|
||||
$allianceData->sharing = $this->sharing;
|
||||
$allianceData->shared = $this->shared;
|
||||
|
||||
return $allianceData;
|
||||
}
|
||||
|
||||
@@ -35,6 +35,13 @@ class BasicModel extends \DB\Cortex {
|
||||
*/
|
||||
protected $rel_ttl = 0;
|
||||
|
||||
/**
|
||||
* ass static columns for this table
|
||||
* -> can be overwritten in child models
|
||||
* @var bool
|
||||
*/
|
||||
protected $addStaticFields = true;
|
||||
|
||||
/**
|
||||
* field validation array
|
||||
* @var array
|
||||
@@ -48,10 +55,23 @@ class BasicModel extends \DB\Cortex {
|
||||
*/
|
||||
private $dataCacheKeyPrefix = 'DATACACHE';
|
||||
|
||||
/**
|
||||
* enables data export for this table
|
||||
* -> can be overwritten in child models
|
||||
* @var bool
|
||||
*/
|
||||
public static $enableDataExport = false;
|
||||
|
||||
/**
|
||||
* enables data import for this table
|
||||
* -> can be overwritten in child models
|
||||
* @var bool
|
||||
*/
|
||||
public static $enableDataImport = false;
|
||||
|
||||
|
||||
public function __construct($db = NULL, $table = NULL, $fluid = NULL, $ttl = 0){
|
||||
|
||||
// add static fields to this mapper
|
||||
$this->addStaticFieldConfig();
|
||||
|
||||
parent::__construct($db, $table, $fluid, $ttl);
|
||||
@@ -120,18 +140,24 @@ class BasicModel extends \DB\Cortex {
|
||||
*/
|
||||
private function addStaticFieldConfig(){
|
||||
|
||||
if(is_array($this->fieldConf)){
|
||||
|
||||
// add static fields to this mapper
|
||||
// static tables (fixed data) do not require them...
|
||||
if($this->addStaticFields){
|
||||
$staticFieldConfig = [
|
||||
'created' => [
|
||||
'type' => Schema::DT_TIMESTAMP
|
||||
'type' => Schema::DT_TIMESTAMP,
|
||||
'default' => Schema::DF_CURRENT_TIMESTAMP,
|
||||
'index' => true
|
||||
],
|
||||
'updated' => [
|
||||
'type' => Schema::DF_CURRENT_TIMESTAMP
|
||||
'type' => Schema::DT_TIMESTAMP,
|
||||
'default' => Schema::DF_CURRENT_TIMESTAMP,
|
||||
'index' => true
|
||||
]
|
||||
];
|
||||
|
||||
$this->fieldConf = array_merge($this->fieldConf, $staticFieldConfig);
|
||||
|
||||
$this->fieldConf = array_merge($staticFieldConfig, $this->fieldConf);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,13 +289,7 @@ class BasicModel extends \DB\Cortex {
|
||||
* @return bool
|
||||
*/
|
||||
public function isActive(){
|
||||
$isActive = false;
|
||||
|
||||
if($this->active === 1){
|
||||
$isActive = true;
|
||||
}
|
||||
|
||||
return $isActive;
|
||||
return (bool)$this->active;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -395,6 +415,16 @@ class BasicModel extends \DB\Cortex {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get the current class name
|
||||
* -> namespace not included
|
||||
* @return string
|
||||
*/
|
||||
public static function getClassName(){
|
||||
$parts = explode('\\', static::class);
|
||||
return end($parts);
|
||||
}
|
||||
|
||||
/**
|
||||
* factory for all Models
|
||||
* @param $model
|
||||
@@ -429,7 +459,171 @@ class BasicModel extends \DB\Cortex {
|
||||
*/
|
||||
public static function log($text){
|
||||
Controller\LogController::getLogger('debug')->write($text);
|
||||
}
|
||||
|
||||
/**
|
||||
* export and download table data as *.csv
|
||||
* this is primarily used for static tables
|
||||
* @return bool
|
||||
*/
|
||||
public function exportData(){
|
||||
$status = false;
|
||||
|
||||
if(static::$enableDataExport){
|
||||
$tableModifier = static::getTableModifier();
|
||||
$headers = $tableModifier->getCols();
|
||||
|
||||
// just get the records with existing columns
|
||||
// -> no "virtual" fields or "new" columns
|
||||
$this->fields($headers);
|
||||
$allRecords = $this->find();
|
||||
|
||||
if($allRecords){
|
||||
$tableData = $allRecords->castAll();
|
||||
|
||||
// format data -> "id" must be first key
|
||||
foreach($tableData as &$rowData){
|
||||
$rowData = [$this->primary => $rowData['_id']] + $rowData;
|
||||
unset($rowData['_id']);
|
||||
}
|
||||
|
||||
$sheet = \Sheet::instance();
|
||||
$data = $sheet->dumpCSV($tableData, $headers);
|
||||
|
||||
header('Expires: 0');
|
||||
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
|
||||
header('Content-Type: text/csv;charset=UTF-8');
|
||||
header('Content-Disposition: attachment;filename=' . $this->getTable() . '.csv');
|
||||
echo $data;
|
||||
exit();
|
||||
}
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* import table data from a *.csv file
|
||||
* @return bool
|
||||
*/
|
||||
public function importData(){
|
||||
$status = false;
|
||||
|
||||
if(static::$enableDataImport){
|
||||
$filePath = 'export/sql/' . $this->getTable() . '.csv';
|
||||
|
||||
if(is_file($filePath)){
|
||||
$handle = @fopen($filePath, 'r');
|
||||
$keys = array_map('lcfirst', array_filter(fgetcsv($handle, 0, ';')));
|
||||
|
||||
if(count($keys) > 0){
|
||||
$tableData = [];
|
||||
while (!feof($handle)) {
|
||||
$tableData[] = array_combine($keys, array_filter(fgetcsv($handle, 0, ';')));
|
||||
}
|
||||
// import row data
|
||||
$status = $this->importStaticData($tableData);
|
||||
$this->getF3()->status(202);
|
||||
}else{
|
||||
$this->getF3()->error(502, 'File could not be read');
|
||||
}
|
||||
}else{
|
||||
$this->getF3()->error(404, 'File not found: ' . $filePath);
|
||||
}
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* insert/update static data into this table
|
||||
* WARNING: rows will be deleted if not part of $tableData !
|
||||
* @param array $tableData
|
||||
* @return array
|
||||
*/
|
||||
protected function importStaticData($tableData = []){
|
||||
$rowIDs = [];
|
||||
|
||||
$addedCount = 0;
|
||||
$updatedCount = 0;
|
||||
$deletedCount = 0;
|
||||
|
||||
foreach($tableData as $rowData){
|
||||
// search for existing record and update columns
|
||||
$this->getById($rowData['id']);
|
||||
if($this->dry()){
|
||||
$addedCount++;
|
||||
}else{
|
||||
$updatedCount++;
|
||||
}
|
||||
$this->copyfrom($rowData);
|
||||
$this->save();
|
||||
$rowIDs[] = $this->id;
|
||||
$this->reset();
|
||||
}
|
||||
|
||||
// remove old data
|
||||
$oldRows = $this->find('id NOT IN (' . implode(',', $rowIDs) . ')');
|
||||
if($oldRows){
|
||||
foreach($oldRows as $oldRow){
|
||||
$oldRow->erase();
|
||||
$deletedCount++;
|
||||
}
|
||||
}
|
||||
return ['added' => $addedCount, 'updated' => $updatedCount, 'deleted' => $deletedCount];
|
||||
}
|
||||
|
||||
/**
|
||||
* get tableModifier class for this table
|
||||
* @return bool|DB\SQL\TableModifier
|
||||
*/
|
||||
public static function getTableModifier(){
|
||||
$df = parent::resolveConfiguration();
|
||||
$schema = new Schema($df['db']);
|
||||
$tableModifier = $schema->alterTable( $df['table'] );
|
||||
return $tableModifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a (multi)-column index exists or not on a table
|
||||
* related to this model
|
||||
* @param array $fields
|
||||
* @return bool|array
|
||||
*/
|
||||
public static function indexExists(array $fields=array()){
|
||||
$tableModifier = self::getTableModifier();
|
||||
$df = parent::resolveConfiguration();
|
||||
|
||||
$check = false;
|
||||
$indexKey = $df['table'] . '___' . implode('__', $fields);
|
||||
$indexList = $tableModifier->listIndex();
|
||||
if(array_key_exists( $indexKey, $indexList)){
|
||||
$check = $indexList[$indexKey];
|
||||
}
|
||||
|
||||
return $check;
|
||||
}
|
||||
|
||||
/**
|
||||
* set a multi-column index for this table
|
||||
* @param array $fields
|
||||
* @param bool $unique
|
||||
* @param int $length
|
||||
* @return bool
|
||||
*/
|
||||
public static function setMultiColumnIndex(array $fields=array(), $unique = false, $length = 20){
|
||||
$status = false;
|
||||
$tableModifier = self::getTableModifier();
|
||||
|
||||
if( self::indexExists($fields) === false ){
|
||||
$tableModifier->addIndex($fields, $unique, $length);
|
||||
$buildStatus = $tableModifier->build();
|
||||
if($buildStatus === 0){
|
||||
$status = true;
|
||||
}
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,14 +8,53 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class CharacterLogModel extends BasicModel {
|
||||
|
||||
protected $table = 'character_log';
|
||||
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => true,
|
||||
'index' => true
|
||||
],
|
||||
'characterId' => [
|
||||
'belongs-to-one' => 'Model\CharacterModel'
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'unique' => true,
|
||||
'belongs-to-one' => 'Model\CharacterModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'character',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
],
|
||||
'systemId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true
|
||||
],
|
||||
'systemName' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'shipId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true
|
||||
],
|
||||
'shipName' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'shipTypeName' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
]
|
||||
];
|
||||
|
||||
|
||||
@@ -8,17 +8,54 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class CharacterModel extends BasicModel {
|
||||
|
||||
protected $table = 'character';
|
||||
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => true,
|
||||
'index' => true
|
||||
],
|
||||
'name' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'corporationId' => [
|
||||
'belongs-to-one' => 'Model\CorporationModel'
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\CorporationModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'corporation',
|
||||
'on-delete' => 'SET NULL'
|
||||
]
|
||||
]
|
||||
],
|
||||
'allianceId' => [
|
||||
'belongs-to-one' => 'Model\AllianceModel'
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\AllianceModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'alliance',
|
||||
'on-delete' => 'SET NULL'
|
||||
]
|
||||
]
|
||||
],
|
||||
'factionId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true
|
||||
],
|
||||
'factionName' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'characterLog' => [
|
||||
'has-one' => ['Model\CharacterLogModel', 'characterId']
|
||||
|
||||
@@ -8,8 +8,65 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class CharacterStatusModel extends BasicModel {
|
||||
|
||||
protected $table = 'character_status';
|
||||
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => true,
|
||||
'index' => true
|
||||
],
|
||||
'name' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'class' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
]
|
||||
];
|
||||
|
||||
protected static $tableData = [
|
||||
[
|
||||
'id' => 1,
|
||||
'name' => 'corporation',
|
||||
'class' => 'pf-user-status-corp'
|
||||
],
|
||||
[
|
||||
'id' => 2,
|
||||
'name' => 'alliance',
|
||||
'class' => 'pf-user-status-ally'
|
||||
],
|
||||
[
|
||||
'id' => 3,
|
||||
'name' => 'own',
|
||||
'class' => 'pf-user-status-own'
|
||||
]
|
||||
];
|
||||
|
||||
/**
|
||||
* overwrites parent
|
||||
* @param null $db
|
||||
* @param null $table
|
||||
* @param null $fields
|
||||
* @return bool
|
||||
*/
|
||||
public static function setup($db=null, $table=null, $fields=null){
|
||||
$status = parent::setup($db,$table,$fields);
|
||||
|
||||
// set static default values
|
||||
if($status === true){
|
||||
$model = self::getNew(self::getClassName(), 0);
|
||||
$model->importStaticData(self::$tableData);
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
}
|
||||
@@ -8,21 +8,56 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class ConnectionModel extends BasicModel{
|
||||
|
||||
protected $table = 'connection';
|
||||
|
||||
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => true,
|
||||
'index' => true
|
||||
],
|
||||
'mapId' => [
|
||||
'belongs-to-one' => 'Model\MapModel'
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\MapModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'map',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
],
|
||||
'source' => [
|
||||
'belongs-to-one' => 'Model\SystemModel'
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\SystemModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'system',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
],
|
||||
'target' => [
|
||||
'belongs-to-one' => 'Model\SystemModel'
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\SystemModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'system',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
],
|
||||
'scope' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'type' => [
|
||||
'type' => self::DT_JSON
|
||||
@@ -114,4 +149,20 @@ class ConnectionModel extends BasicModel{
|
||||
$this->mapId->clearCacheData();
|
||||
}
|
||||
|
||||
/**
|
||||
* overwrites parent
|
||||
* @param null $db
|
||||
* @param null $table
|
||||
* @param null $fields
|
||||
* @return bool
|
||||
*/
|
||||
public static function setup($db=null, $table=null, $fields=null){
|
||||
$status = parent::setup($db,$table,$fields);
|
||||
|
||||
if($status === true){
|
||||
$status = parent::setMultiColumnIndex(['source', 'target', 'scope']);
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,74 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class ConnectionScopeModel extends BasicModel{
|
||||
|
||||
protected $table = 'connection_scope';
|
||||
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => true,
|
||||
'index' => true
|
||||
],
|
||||
'name' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'label' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'connectorDefinition' => [
|
||||
'type' => Schema::DT_VARCHAR256,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
]
|
||||
];
|
||||
|
||||
protected static $tableData = [
|
||||
[
|
||||
'id' => 1,
|
||||
'name' => 'wh',
|
||||
'label' => 'wormhole',
|
||||
'connectorDefinition' => '[ "Bezier", { "curviness": 40 } ]'
|
||||
],
|
||||
[
|
||||
'id' => 2,
|
||||
'name' => 'stargate',
|
||||
'label' => 'stargate',
|
||||
'connectorDefinition' => '[ "Flowchart", { "stub": [20, 20], "gap": 0, "cornerRadius": 5, "alwaysRespectStubs": false } ]'
|
||||
],
|
||||
[
|
||||
'id' => 3,
|
||||
'name' => 'jumpbridge',
|
||||
'label' => 'jumpbridge',
|
||||
'connectorDefinition' => '[ "Straight", { "stub": [5, 5], "gap": 0 } ]'
|
||||
]
|
||||
|
||||
];
|
||||
|
||||
/**
|
||||
* overwrites parent
|
||||
* @param null $db
|
||||
* @param null $table
|
||||
* @param null $fields
|
||||
* @return bool
|
||||
*/
|
||||
public static function setup($db=null, $table=null, $fields=null){
|
||||
$status = parent::setup($db,$table,$fields);
|
||||
|
||||
// set static default values
|
||||
if($status === true){
|
||||
$model = self::getNew(self::getClassName(), 0);
|
||||
$model->importStaticData(self::$tableData);
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
}
|
||||
@@ -8,17 +8,40 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class CorporationMapModel extends BasicModel {
|
||||
|
||||
protected $table = 'corporation_map';
|
||||
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => true,
|
||||
'index' => true
|
||||
],
|
||||
'corporationId' => [
|
||||
'belongs-to-one' => 'Model\CorporationModel'
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\CorporationModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'corporation',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
],
|
||||
'mapId' => [
|
||||
'belongs-to-one' => 'Model\MapModel'
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\MapModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'map',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
@@ -32,4 +55,20 @@ class CorporationMapModel extends BasicModel {
|
||||
$this->mapId->clearCacheData();
|
||||
}
|
||||
|
||||
/**
|
||||
* overwrites parent
|
||||
* @param null $db
|
||||
* @param null $table
|
||||
* @param null $fields
|
||||
* @return bool
|
||||
*/
|
||||
public static function setup($db=null, $table=null, $fields=null){
|
||||
$status = parent::setup($db,$table,$fields);
|
||||
|
||||
if($status === true){
|
||||
$status = parent::setMultiColumnIndex(['corporationId', 'mapId'], true);
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
}
|
||||
@@ -8,11 +8,29 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class CorporationModel extends BasicModel {
|
||||
|
||||
protected $table = 'corporation';
|
||||
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => true,
|
||||
'index' => true
|
||||
],
|
||||
'name' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'shared' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => 0
|
||||
],
|
||||
'corporationCharacters' => [
|
||||
'has-many' => ['Model\CharacterModel', 'corporationId']
|
||||
],
|
||||
@@ -30,7 +48,7 @@ class CorporationModel extends BasicModel {
|
||||
|
||||
$cooperationData->id = $this->id;
|
||||
$cooperationData->name = $this->name;
|
||||
$cooperationData->sharing = $this->sharing;
|
||||
$cooperationData->shared = $this->shared;
|
||||
|
||||
return $cooperationData;
|
||||
}
|
||||
|
||||
@@ -8,16 +8,51 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class MapModel extends BasicModel {
|
||||
|
||||
protected $table = 'map';
|
||||
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => true,
|
||||
'index' => true,
|
||||
'after' => 'updated'
|
||||
],
|
||||
'scopeId' => [
|
||||
'belongs-to-one' => 'Model\MapScopeModel'
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\MapScopeModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'map_scope',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
],
|
||||
'typeId' => [
|
||||
'belongs-to-one' => 'Model\MapTypeModel'
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\MapTypeModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'map_type',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
],
|
||||
'name' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'icon' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'systems' => [
|
||||
'has-many' => ['Model\SystemModel', 'mapId']
|
||||
@@ -31,8 +66,8 @@ class MapModel extends BasicModel {
|
||||
'mapCorporations' => [
|
||||
'has-many' => ['Model\CorporationMapModel', 'mapId']
|
||||
],
|
||||
'mapAlliances' => ['has-many' => [
|
||||
'Model\AllianceMapModel', 'mapId']
|
||||
'mapAlliances' => [
|
||||
'has-many' => ['Model\AllianceMapModel', 'mapId']
|
||||
]
|
||||
];
|
||||
|
||||
|
||||
@@ -8,9 +8,55 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class MapScopeModel extends BasicModel{
|
||||
|
||||
protected $table = 'map_scope';
|
||||
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => true,
|
||||
'index' => true
|
||||
],
|
||||
'name' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'label' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
]
|
||||
];
|
||||
|
||||
protected static $tableData = [
|
||||
[
|
||||
'id' => 1,
|
||||
'name' => 'wh',
|
||||
'label' => 'w-space'
|
||||
]
|
||||
];
|
||||
|
||||
/**
|
||||
* overwrites parent
|
||||
* @param null $db
|
||||
* @param null $table
|
||||
* @param null $fields
|
||||
* @return bool
|
||||
*/
|
||||
public static function setup($db=null, $table=null, $fields=null){
|
||||
$status = parent::setup($db,$table,$fields);
|
||||
|
||||
// set static default values
|
||||
if($status === true){
|
||||
$model = self::getNew(self::getClassName(), 0);
|
||||
$model->importStaticData(self::$tableData);
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
}
|
||||
@@ -8,9 +8,96 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class MapTypeModel extends BasicModel{
|
||||
|
||||
protected $table = 'map_type';
|
||||
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => true,
|
||||
'index' => true
|
||||
],
|
||||
'name' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'label' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'class' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'classTab' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
]
|
||||
];
|
||||
|
||||
protected static $tableData = [
|
||||
[
|
||||
'id' => 1,
|
||||
'name' => 'standard',
|
||||
'label' => '',
|
||||
'class' => '',
|
||||
'classTab' => 'pf-map-type-tab-default'
|
||||
],
|
||||
[
|
||||
'id' => 2,
|
||||
'name' => 'private',
|
||||
'label' => 'private',
|
||||
'class' => 'pf-map-type-private',
|
||||
'classTab' => 'pf-map-type-tab-private'
|
||||
],
|
||||
[
|
||||
'id' => 3,
|
||||
'name' => 'corporation',
|
||||
'label' => 'corporation',
|
||||
'class' => 'pf-map-type-corporation',
|
||||
'classTab' => 'pf-map-type-tab-corporation'
|
||||
],
|
||||
[
|
||||
'id' => 4,
|
||||
'name' => 'alliance',
|
||||
'label' => 'alliance',
|
||||
'class' => 'pf-map-type-alliance',
|
||||
'classTab' => 'pf-map-type-tab-alliance'
|
||||
],
|
||||
[
|
||||
'id' => 5,
|
||||
'name' => 'globald',
|
||||
'label' => 'global',
|
||||
'class' => 'pf-map-type-global',
|
||||
'classTab' => 'pf-map-type-tab-global'
|
||||
]
|
||||
];
|
||||
|
||||
/**
|
||||
* overwrites parent
|
||||
* @param null $db
|
||||
* @param null $table
|
||||
* @param null $fields
|
||||
* @return bool
|
||||
*/
|
||||
public static function setup($db=null, $table=null, $fields=null){
|
||||
$status = parent::setup($db,$table,$fields);
|
||||
|
||||
// set static default values
|
||||
if($status === true){
|
||||
$model = self::getNew(self::getClassName(), 0);
|
||||
$model->importStaticData(self::$tableData);
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,9 +8,42 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class RegistrationKeyModel extends BasicModel {
|
||||
|
||||
protected $table = 'registration_key';
|
||||
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => true,
|
||||
'index' => true
|
||||
],
|
||||
'ip' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'used' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => 0
|
||||
],
|
||||
'email' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => '',
|
||||
'index' => true
|
||||
],
|
||||
'registrationKey' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => '',
|
||||
'index' => true,
|
||||
'unique' => true
|
||||
]
|
||||
];
|
||||
|
||||
}
|
||||
42
app/main/model/systemapibasicmodel.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: exodus4d
|
||||
* Date: 25.11.15
|
||||
* Time: 22:11
|
||||
*/
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class SystemApiBasicModel extends BasicModel {
|
||||
|
||||
public function __construct($db = NULL, $table = NULL, $fluid = NULL, $ttl = 0){
|
||||
|
||||
$this->addStaticKillFieldConfig();
|
||||
|
||||
parent::__construct($db, $table, $fluid, $ttl);
|
||||
}
|
||||
|
||||
/**
|
||||
* extent the fieldConf Array with static fields for each table
|
||||
*/
|
||||
private function addStaticKillFieldConfig(){
|
||||
|
||||
if(is_array($this->fieldConf)){
|
||||
|
||||
$staticFieldConfig = [];
|
||||
for($i = 1; $i <= 24; $i++){
|
||||
$staticFieldConfig['value' . $i] = [
|
||||
'type' => Schema::DT_INT,
|
||||
'nullable' => false,
|
||||
'default' => 0,
|
||||
];
|
||||
}
|
||||
|
||||
$this->fieldConf = array_merge($this->fieldConf, $staticFieldConfig);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,8 +8,23 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class SystemFactionKillModel extends BasicModel {
|
||||
class SystemFactionKillModel extends SystemApiBasicModel {
|
||||
|
||||
protected $table = 'system_kills_factions';
|
||||
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => true,
|
||||
'index' => true
|
||||
],
|
||||
'systemId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'unique' => true
|
||||
]
|
||||
];
|
||||
}
|
||||
@@ -8,8 +8,23 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class SystemJumpModel extends BasicModel {
|
||||
class SystemJumpModel extends SystemApiBasicModel {
|
||||
|
||||
protected $table = 'system_jumps';
|
||||
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => true,
|
||||
'index' => true
|
||||
],
|
||||
'systemId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'unique' => true
|
||||
]
|
||||
];
|
||||
}
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class SystemModel extends BasicModel {
|
||||
|
||||
@@ -17,24 +18,144 @@ class SystemModel extends BasicModel {
|
||||
protected $table = 'system';
|
||||
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => true,
|
||||
'index' => true
|
||||
],
|
||||
'mapId' => [
|
||||
'belongs-to-one' => 'Model\MapModel'
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\MapModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'map',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
],
|
||||
'systemId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
],
|
||||
'name' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'alias' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'regionId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
],
|
||||
'region' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'constellationId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
],
|
||||
'constellation' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'effect' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'typeId' => [
|
||||
'belongs-to-one' => 'Model\SystemTypeModel'
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\SystemTypeModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'system_type',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
],
|
||||
'security' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'trueSec' => [
|
||||
'type' => Schema::DT_FLOAT,
|
||||
'nullable' => false,
|
||||
'default' => 1
|
||||
],
|
||||
'statusId' => [
|
||||
'belongs-to-one' => 'Model\SystemStatusModel'
|
||||
'type' => Schema::DT_INT,
|
||||
'nullable' => false,
|
||||
'default' => 1,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\SystemStatusModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'system_status',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
],
|
||||
'locked' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => 0
|
||||
],
|
||||
'rally' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => 0
|
||||
],
|
||||
'description' => [
|
||||
'type' => Schema::DT_VARCHAR512,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'posX' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'nullable' => false,
|
||||
'default' => 0
|
||||
],
|
||||
'posY' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'nullable' => false,
|
||||
'default' => 0
|
||||
],
|
||||
'createdCharacterId' => [
|
||||
'belongs-to-one' => 'Model\CharacterModel'
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\CharacterModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'character',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
],
|
||||
'updatedCharacterId' => [
|
||||
'belongs-to-one' => 'Model\CharacterModel'
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\CharacterModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'character',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
],
|
||||
'signatures' => [
|
||||
'has-many' => ['Model\SystemSignatureModel', 'systemId']
|
||||
],
|
||||
]
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -333,4 +454,21 @@ class SystemModel extends BasicModel {
|
||||
$this->mapId->clearCacheData();
|
||||
}
|
||||
|
||||
/**
|
||||
* overwrites parent
|
||||
* @param null $db
|
||||
* @param null $table
|
||||
* @param null $fields
|
||||
* @return bool
|
||||
*/
|
||||
public static function setup($db=null, $table=null, $fields=null){
|
||||
$status = parent::setup($db,$table,$fields);
|
||||
|
||||
if($status === true){
|
||||
$status = parent::setMultiColumnIndex(['mapId', 'systemId'], true);
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
}
|
||||
49
app/main/model/systemneighbourmodel.php
Normal file
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: Exodus
|
||||
* Date: 24.12.2015
|
||||
* Time: 00:59
|
||||
*/
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class SystemNeighbourModel extends BasicModel {
|
||||
|
||||
protected $table = 'system_neighbour';
|
||||
|
||||
protected $fieldConf = [
|
||||
'regionId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true
|
||||
],
|
||||
'constellationId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true
|
||||
],
|
||||
'systemName' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'default' => ''
|
||||
],
|
||||
'systemId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true
|
||||
],
|
||||
'jumpNodes' => [
|
||||
'type' => Schema::DT_VARCHAR512,
|
||||
'default' => ''
|
||||
],
|
||||
'trueSec' => [
|
||||
'type' => Schema::DT_DECIMAL,
|
||||
'default' => 0
|
||||
]
|
||||
];
|
||||
|
||||
/**
|
||||
* No static columns added
|
||||
* @var bool
|
||||
*/
|
||||
protected $addStaticFields = false;
|
||||
}
|
||||
@@ -8,8 +8,23 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class SystemPodKillModel extends BasicModel {
|
||||
class SystemPodKillModel extends SystemApiBasicModel {
|
||||
|
||||
protected $table = 'system_kills_pods';
|
||||
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => true,
|
||||
'index' => true
|
||||
],
|
||||
'systemId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'unique' => true
|
||||
]
|
||||
];
|
||||
}
|
||||
@@ -8,8 +8,24 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class SystemShipKillModel extends BasicModel {
|
||||
class SystemShipKillModel extends SystemApiBasicModel {
|
||||
|
||||
protected $table = 'system_kills_ships';
|
||||
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => true,
|
||||
'index' => true
|
||||
],
|
||||
'systemId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'unique' => true
|
||||
]
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
@@ -8,20 +8,73 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class SystemSignatureModel extends BasicModel {
|
||||
|
||||
protected $table = 'system_signature';
|
||||
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => true,
|
||||
'index' => true
|
||||
],
|
||||
'systemId' => [
|
||||
'belongs-to-one' => 'Model\SystemModel'
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\SystemModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'system',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
],
|
||||
'groupId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'nullable' => false,
|
||||
'default' => 1,
|
||||
'index' => true,
|
||||
],
|
||||
'typeId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'nullable' => false,
|
||||
'default' => 1,
|
||||
'index' => true,
|
||||
],
|
||||
'name' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'description' => [
|
||||
'type' => Schema::DT_VARCHAR512,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'createdCharacterId' => [
|
||||
'belongs-to-one' => 'Model\CharacterModel'
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\CharacterModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'character',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
],
|
||||
'updatedCharacterId' => [
|
||||
'belongs-to-one' => 'Model\CharacterModel'
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\CharacterModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'character',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
@@ -114,4 +167,21 @@ class SystemSignatureModel extends BasicModel {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* overwrites parent
|
||||
* @param null $db
|
||||
* @param null $table
|
||||
* @param null $fields
|
||||
* @return bool
|
||||
*/
|
||||
public static function setup($db=null, $table=null, $fields=null){
|
||||
$status = parent::setup($db,$table,$fields);
|
||||
|
||||
if($status === true){
|
||||
$status = parent::setMultiColumnIndex(['systemId', 'typeId', 'groupId']);
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,91 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class SystemStatusModel extends BasicModel {
|
||||
|
||||
protected $table = 'system_status';
|
||||
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => true,
|
||||
'index' => true
|
||||
],
|
||||
'name' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'label' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'class' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
]
|
||||
];
|
||||
|
||||
protected static $tableData = [
|
||||
[
|
||||
'id' => 1,
|
||||
'name' => 'unknown',
|
||||
'label' => 'unknown',
|
||||
'class' => 'pf-system-status-unknown'
|
||||
],
|
||||
[
|
||||
'id' => 2,
|
||||
'name' => 'friendly',
|
||||
'label' => 'friendly',
|
||||
'class' => 'pf-system-status-friendly'
|
||||
],
|
||||
[
|
||||
'id' => 3,
|
||||
'name' => 'occupied',
|
||||
'label' => 'occupied',
|
||||
'class' => 'pf-system-status-occupied'
|
||||
],
|
||||
[
|
||||
'id' => 4,
|
||||
'name' => 'hostile',
|
||||
'label' => 'hostile',
|
||||
'class' => 'pf-system-status-hostile'
|
||||
],
|
||||
[
|
||||
'id' => 5,
|
||||
'name' => 'empty',
|
||||
'label' => 'empty',
|
||||
'class' => 'pf-system-status-empty'
|
||||
],
|
||||
[
|
||||
'id' => 6,
|
||||
'name' => 'unscanned',
|
||||
'label' => 'unscanned',
|
||||
'class' => 'pf-system-status-unscanned'
|
||||
]
|
||||
];
|
||||
|
||||
/**
|
||||
* overwrites parent
|
||||
* @param null $db
|
||||
* @param null $table
|
||||
* @param null $fields
|
||||
* @return bool
|
||||
*/
|
||||
public static function setup($db=null, $table=null, $fields=null){
|
||||
$status = parent::setup($db,$table,$fields);
|
||||
|
||||
// set static default values
|
||||
if($status === true){
|
||||
$model = self::getNew(self::getClassName(), 0);
|
||||
$model->importStaticData(self::$tableData);
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
}
|
||||
@@ -8,8 +8,53 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class SystemTypeModel extends BasicModel {
|
||||
|
||||
protected $table = 'system_type';
|
||||
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => true,
|
||||
'index' => true
|
||||
],
|
||||
'name' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
]
|
||||
];
|
||||
|
||||
protected static $tableData = [
|
||||
[
|
||||
'id' => 1,
|
||||
'name' => 'w-space'
|
||||
],
|
||||
[
|
||||
'id' => 2,
|
||||
'name' => 'k-space'
|
||||
]
|
||||
];
|
||||
|
||||
/**
|
||||
* overwrites parent
|
||||
* @param null $db
|
||||
* @param null $table
|
||||
* @param null $fields
|
||||
* @return bool
|
||||
*/
|
||||
public static function setup($db=null, $table=null, $fields=null){
|
||||
$status = parent::setup($db,$table,$fields);
|
||||
|
||||
// set static default values
|
||||
if($status === true){
|
||||
$model = self::getNew(self::getClassName(), 0);
|
||||
$model->importStaticData(self::$tableData);
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
}
|
||||
@@ -8,15 +8,28 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class SystemWormholeModel extends BasicModel {
|
||||
|
||||
protected $table = 'system_wormhole';
|
||||
|
||||
protected $fieldConf = [
|
||||
'constellationId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
],
|
||||
'wormholeId' => [
|
||||
'belongs-to-one' => 'Model\WormholeModel'
|
||||
]
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\WormholeModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'wormhole',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
*/
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
use Controller;
|
||||
|
||||
class UserApiModel extends BasicModel {
|
||||
@@ -14,12 +16,36 @@ class UserApiModel extends BasicModel {
|
||||
protected $table = 'user_api';
|
||||
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => true,
|
||||
'index' => true
|
||||
],
|
||||
'userId' => [
|
||||
'belongs-to-one' => 'Model\UserModel'
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\UserModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'user',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
],
|
||||
'keyId' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'unique' => true
|
||||
],
|
||||
'vCode' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => '',
|
||||
],
|
||||
'userCharacters' => [
|
||||
'has-many' => ['Model\UserCharacterModel', 'apiId']
|
||||
]
|
||||
],
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,20 +8,57 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class UserCharacterModel extends BasicModel {
|
||||
|
||||
protected $table = 'user_character';
|
||||
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => true,
|
||||
'index' => true
|
||||
],
|
||||
'userId' => [
|
||||
'belongs-to-one' => 'Model\UserModel'
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\UserModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'user',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
],
|
||||
'apiId' => [
|
||||
'belongs-to-one' => 'Model\UserApiModel'
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\UserApiModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'user_api',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
],
|
||||
'characterId' => [
|
||||
'belongs-to-one' => 'Model\CharacterModel'
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\CharacterModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'character',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
],
|
||||
'isMain' => [
|
||||
'type' => Schema::DT_BOOLEAN,
|
||||
'nullable' => false,
|
||||
'default' => false,
|
||||
'index' => true
|
||||
]
|
||||
];
|
||||
|
||||
@@ -98,4 +135,24 @@ class UserCharacterModel extends BasicModel {
|
||||
return $this->characterId;
|
||||
}
|
||||
|
||||
/**
|
||||
* overwrites parent
|
||||
* @param null $db
|
||||
* @param null $table
|
||||
* @param null $fields
|
||||
* @return bool
|
||||
*/
|
||||
public static function setup($db=null, $table=null, $fields=null){
|
||||
$status = parent::setup($db,$table,$fields);
|
||||
|
||||
if($status === true){
|
||||
$status = parent::setMultiColumnIndex(['userId', 'apiId', 'characterId'], true);
|
||||
if($status === true){
|
||||
$status = parent::setMultiColumnIndex(['userId', 'apiId']);
|
||||
}
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,17 +8,40 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class UserMapModel extends BasicModel {
|
||||
|
||||
protected $table = 'user_map';
|
||||
|
||||
protected $fieldConf = [
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => true,
|
||||
'index' => true
|
||||
],
|
||||
'userId' => [
|
||||
'belongs-to-one' => 'Model\UserModel'
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\UserModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'user',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
],
|
||||
'mapId' => [
|
||||
'belongs-to-one' => 'Model\MapModel'
|
||||
'type' => Schema::DT_INT,
|
||||
'index' => true,
|
||||
'belongs-to-one' => 'Model\MapModel',
|
||||
'constraint' => [
|
||||
[
|
||||
'table' => 'map',
|
||||
'on-delete' => 'CASCADE'
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
|
||||
@@ -32,4 +55,21 @@ class UserMapModel extends BasicModel {
|
||||
$this->mapId->clearCacheData();
|
||||
}
|
||||
|
||||
/**
|
||||
* overwrites parent
|
||||
* @param null $db
|
||||
* @param null $table
|
||||
* @param null $fields
|
||||
* @return bool
|
||||
*/
|
||||
public static function setup($db=null, $table=null, $fields=null){
|
||||
$status = parent::setup($db,$table,$fields);
|
||||
|
||||
if($status === true){
|
||||
$status = parent::setMultiColumnIndex(['userId', 'mapId'], true);
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,7 +18,38 @@ class UserModel extends BasicModel {
|
||||
|
||||
protected $fieldConf = [
|
||||
'lastLogin' => [
|
||||
'type' => Schema::DT_TIMESTAMP
|
||||
'type' => Schema::DT_TIMESTAMP,
|
||||
'index' => true
|
||||
],
|
||||
'active' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => true,
|
||||
'index' => true
|
||||
],
|
||||
'name' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => '',
|
||||
'index' => true,
|
||||
'unique' => true
|
||||
],
|
||||
'email' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => '',
|
||||
'index' => true,
|
||||
'unique' => true
|
||||
],
|
||||
'password' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'shared' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => '0'
|
||||
],
|
||||
'apis' => [
|
||||
'has-many' => ['Model\UserApiModel', 'userId']
|
||||
@@ -64,8 +95,8 @@ class UserModel extends BasicModel {
|
||||
// add sensitive user data
|
||||
$userData->email = $this->email;
|
||||
|
||||
// user sharing info
|
||||
$userData->sharing = $this->sharing;
|
||||
// user shared info
|
||||
$userData->shared = $this->shared;
|
||||
|
||||
// api data
|
||||
$APIs = $this->getAPIs();
|
||||
@@ -180,7 +211,6 @@ class UserModel extends BasicModel {
|
||||
* @return array
|
||||
*/
|
||||
public function getMaps(){
|
||||
|
||||
$f3 = self::getF3();
|
||||
|
||||
$this->filter(
|
||||
|
||||
@@ -8,10 +8,54 @@
|
||||
|
||||
namespace Model;
|
||||
|
||||
use DB\SQL\Schema;
|
||||
|
||||
class WormholeModel extends BasicModel {
|
||||
|
||||
protected $table = 'wormhole';
|
||||
|
||||
protected $fieldConf = [
|
||||
'name' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => '',
|
||||
'index' => true,
|
||||
'unique' => true
|
||||
],
|
||||
'security' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'massTotal' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'massIndividual' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'massRegeneration' => [
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
],
|
||||
'maxStableTime' => [
|
||||
'type' => Schema::DT_INT,
|
||||
'nullable' => false,
|
||||
'default' => 1,
|
||||
'index' => true,
|
||||
]
|
||||
];
|
||||
|
||||
/**
|
||||
* No static columns added
|
||||
* @var bool
|
||||
*/
|
||||
protected $addStaticFields = false;
|
||||
|
||||
/**
|
||||
* format mass values
|
||||
* - no decimal separator
|
||||
@@ -57,4 +101,5 @@ class WormholeModel extends BasicModel {
|
||||
|
||||
return $systemStaticData;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,161 +1,107 @@
|
||||
; Main Config
|
||||
|
||||
[PATHFINDER]
|
||||
NAME = "PATHFINDER"
|
||||
NAME = PATHFINDER
|
||||
; installed version (used for CSS/JS cache busting)
|
||||
VERSION = "v0.0.16"
|
||||
VERSION = v1.0.0RC1
|
||||
; contact information (DO NOT CHANGE)
|
||||
CONTACT = "https://github.com/exodus4d"
|
||||
CONTACT = https://github.com/exodus4d
|
||||
; source code (DO NOT CHANGE)
|
||||
REPO = "https://github.com/exodus4d/pathfinder"
|
||||
REPO = https://github.com/exodus4d/pathfinder
|
||||
|
||||
; Max number of maps an entity can create
|
||||
MAX_MAPS_PRIVATE = 3
|
||||
MAX_MAPS_CORPORATION = 3
|
||||
MAX_MAPS_ALLIANCE = 3
|
||||
MAX_MAPS_PRIVATE = 3
|
||||
MAX_MAPS_CORPORATION = 3
|
||||
MAX_MAPS_ALLIANCE = 3
|
||||
|
||||
; Max number of shared entities per map
|
||||
MAX_SHARED_USER = 10
|
||||
MAX_SHARED_CORPORATION = 3
|
||||
MAX_SHARED_ALLIANCE = 2
|
||||
MAX_SHARED_USER = 10
|
||||
MAX_SHARED_CORPORATION = 3
|
||||
MAX_SHARED_ALLIANCE = 2
|
||||
|
||||
[PATHFINDER.ENVIRONMENT]
|
||||
; project environment ("DEVELOP", "PRODUCTION").
|
||||
; This affects: DB connection, JS build path
|
||||
SERVER = "DEVELOP"
|
||||
; show warning on "login" form if /setup route is active
|
||||
; DO NOT disable this warning unless /setup route is protected by e.g. WebAuth
|
||||
SHOW_SETUP_WARNING = 1
|
||||
|
||||
[PATHFINDER.ENVIRONMENT.DEVELOP]
|
||||
BASE = /exodus4d/pathfinder
|
||||
|
||||
; deployment URL (what you type in the browser
|
||||
URL = http://localhost/exodus4d/pathfinder
|
||||
|
||||
; Verbosity level of the stack trace
|
||||
DEBUG = 3
|
||||
|
||||
; main db
|
||||
DB_DNS = mysql:host=localhost;port=3306;dbname=
|
||||
DB_NAME = pathfinder
|
||||
DB_USER = root
|
||||
DB_PASS =
|
||||
|
||||
; EVE-Online CCP Database export
|
||||
DB_CCP_DNS = mysql:host=localhost;port=3306;dbname=
|
||||
DB_CCP_NAME = eve_parallax_min
|
||||
DB_CCP_USER = root
|
||||
DB_CCP_PASS =
|
||||
|
||||
; SMTP settings
|
||||
SMTP_HOST = localhost
|
||||
SMTP_PORT = 25
|
||||
SMTP_SCHEME = ""
|
||||
SMTP_USER = pathfinder
|
||||
SMTP_PASS = root
|
||||
|
||||
SMTP_FROM = pathfinder@localhost.com
|
||||
SMTP_ERROR = pathfinder@localhost.com
|
||||
|
||||
[PATHFINDER.ENVIRONMENT.PRODUCTION]
|
||||
BASE = /www/htdocs/w0128162/www.pathfinder.exodus4d.de
|
||||
|
||||
; deployment URL (what you type in the browser
|
||||
URL = https://www.pathfinder.exodus4d.de
|
||||
|
||||
; Verbosity level of the stack trace
|
||||
DEBUG = 0
|
||||
|
||||
; main db
|
||||
DB_DNS = mysql:host=localhost;port=3306;dbname=
|
||||
DB_NAME =
|
||||
DB_USER =
|
||||
DB_PASS =
|
||||
|
||||
; EVE-Online CCP Database export
|
||||
DB_CCP_DNS = mysql:host=localhost;port=3306;dbname=
|
||||
DB_CCP_NAME =
|
||||
DB_CCP_USER =
|
||||
DB_CCP_PASS =
|
||||
|
||||
; SMTP settings
|
||||
SMTP_HOST = localhost
|
||||
SMTP_PORT = 25
|
||||
SMTP_SCHEME = TLS
|
||||
SMTP_USER =
|
||||
SMTP_PASS =
|
||||
|
||||
SMTP_FROM = registration.pathfinder@exodus4d.de
|
||||
SMTP_ERROR = pathfinder@exodus4d.de
|
||||
|
||||
; ======================================================================================================
|
||||
; REGISTRATION ====================================================================================
|
||||
[PATHFINDER.REGISTRATION]
|
||||
; registration status (0=disabled, 1=enabled)
|
||||
STATUS = 1
|
||||
; registration status (for new users) (0=disabled, 1=enabled)
|
||||
STATUS = 1
|
||||
; disabled message
|
||||
MSG_DISABLED = "User registration is currently not allowed"
|
||||
|
||||
; use the invite system e.g. beta testing. A "registration key" is required (0=disabled, 1=enabled)
|
||||
INVITE = 0
|
||||
|
||||
MSG_DISABLED = User registration is currently not allowed
|
||||
; use the invite system (for new users) e.g. beta testing. A "registration key" is required (0=disabled, 1=enabled)
|
||||
INVITE = 0
|
||||
; the limit of registration keys. Increase it to hand out more keys
|
||||
INVITE_LIMIT = 50
|
||||
INVITE_LIMIT = 50
|
||||
|
||||
; ======================================================================================================
|
||||
; Lifetime for map types (days)
|
||||
; View ============================================================================================
|
||||
[PATHFINDER.VIEW]
|
||||
; static page templates
|
||||
INDEX = templates/view/index.html
|
||||
SETUP = templates/view/setup.html
|
||||
LANDINGPAGE = templates/view/landingpage.html
|
||||
|
||||
; HTTP status pages ===============================================================================
|
||||
[PATHFINDER.STATUS]
|
||||
; error pages
|
||||
4XX = templates/status/4xx.html
|
||||
5XX = templates/status/5xx.html
|
||||
|
||||
; MAP =============================================================================================
|
||||
[PATHFINDER.MAP.PRIVATE]
|
||||
LIFETIME = 7
|
||||
LIFETIME = 7
|
||||
|
||||
[PATHFINDER.MAP.CORPORATION]
|
||||
LIFETIME = 99999
|
||||
LIFETIME = 99999
|
||||
|
||||
[PATHFINDER.MAP.ALLIANCE]
|
||||
LIFETIME = 99999
|
||||
; ======================================================================================================
|
||||
[PATHFINDER.CACHE]
|
||||
LIFETIME = 99999
|
||||
|
||||
; cache character log informations in seconds. This is ignored if ship/system switch was detected
|
||||
CHARACTER_LOG = 300
|
||||
|
||||
; cache time for all system data within a constellation (this will never change) 30d
|
||||
CONSTELLATION_SYSTEMS = 2592000
|
||||
|
||||
; ======================================================================================================
|
||||
; TIMER ===========================================================================================
|
||||
[PATHFINDER.TIMER]
|
||||
; login time (minutes)
|
||||
LOGGED = 240
|
||||
|
||||
LOGGED = 240
|
||||
; double click timer (ms)
|
||||
DBL_CLICK = 250
|
||||
|
||||
DBL_CLICK = 250
|
||||
; time for status change visibility in header (ms)
|
||||
PROGRAM_STATUS_VISIBLE = 5000
|
||||
PROGRAM_STATUS_VISIBLE = 5000
|
||||
|
||||
; main map update ping (ajax) (ms)
|
||||
[PATHFINDER.TIMER.UPDATE_SERVER_MAP]
|
||||
DELAY = 5000
|
||||
EXECUTION_LIMIT = 200
|
||||
DELAY = 5000
|
||||
EXECUTION_LIMIT = 200
|
||||
|
||||
; update client map data (ms)
|
||||
[PATHFINDER.TIMER.UPDATE_CLIENT_MAP]
|
||||
EXECUTION_LIMIT = 50
|
||||
EXECUTION_LIMIT = 50
|
||||
|
||||
; map user update ping (ajax) (ms)
|
||||
[PATHFINDER.TIMER.UPDATE_SERVER_USER_DATA]
|
||||
DELAY = 5000
|
||||
EXECUTION_LIMIT = 200
|
||||
DELAY = 5000
|
||||
EXECUTION_LIMIT = 200
|
||||
|
||||
; update client user data (ms)
|
||||
[PATHFINDER.TIMER.UPDATE_CLIENT_USER_DATA]
|
||||
EXECUTION_LIMIT = 50
|
||||
EXECUTION_LIMIT = 50
|
||||
|
||||
; ======================================================================================================
|
||||
; CACHE ===========================================================================================
|
||||
[PATHFINDER.CACHE]
|
||||
; cache character log informations in seconds. This is ignored if ship/system switch was detected
|
||||
CHARACTER_LOG = 300
|
||||
; cache time for all system data within a constellation (this will never change) 30d
|
||||
CONSTELLATION_SYSTEMS = 2592000
|
||||
|
||||
; LOGGING =========================================================================================
|
||||
[PATHFINDER.LOGFILES]
|
||||
; just for manuel debug during development
|
||||
DEBUG = "debug"
|
||||
|
||||
DEBUG = debug
|
||||
; user login information
|
||||
LOGIN = "login"
|
||||
|
||||
LOGIN = login
|
||||
; account deleted
|
||||
DELETE_ACCOUNT = "delete_account"
|
||||
DELETE_ACCOUNT = delete_account
|
||||
|
||||
; API =============================================================================================
|
||||
[PATHFINDER.API]
|
||||
; Path for CCPs XML APIv2
|
||||
CCP_XML = "https://api.eveonline.com"
|
||||
CCP_XML = https://api.eveonline.com
|
||||
GIT_HUB = https://api.github.com
|
||||
|
||||
37
app/requirements.ini
Normal file
@@ -0,0 +1,37 @@
|
||||
; Requirements Config (Do not change!)
|
||||
[REQUIREMENTS]
|
||||
|
||||
[REQUIREMENTS.SERVER]
|
||||
; Apache
|
||||
APACHE.VERSION = 2.5
|
||||
|
||||
; Nginx
|
||||
NGINX.VERSION = 1.9
|
||||
|
||||
[REQUIREMENTS.PHP]
|
||||
; recommended is >= 5.6
|
||||
VERSION = 5.6
|
||||
|
||||
; "Perl-Compatible Regular Expressions"
|
||||
; usually shipped with PHP package,
|
||||
; but needs to be additionally updated on CentOS or Red Hat systems
|
||||
PCRE_VERSION = 8.02
|
||||
|
||||
[REQUIREMENTS.MYSQL]
|
||||
; min MySQL Version
|
||||
; newer "deviation" of MySQL like "MariaDB" > 10.1 are recommended
|
||||
VERSION = 5.6
|
||||
|
||||
[REQUIREMENTS.MYSQL.VARS]
|
||||
; MySql variables. Values are auto. set as 'SESSION' vars
|
||||
; https://dev.mysql.com/doc/refman/5.5/en/show-variables.html
|
||||
DEFAULT_STORAGE_ENGINE = InnoDB
|
||||
CHARACTER_SET_DATABASE = utf8
|
||||
CHARACTER_SET_CLIENT = utf8
|
||||
CHARACTER_SET_RESULTS = utf8
|
||||
CHARACTER_SET_CONNECTION = utf8
|
||||
COLLATION_DATABASE = utf8_general_ci
|
||||
COLLATION_CONNECTION = utf8_general_ci
|
||||
FOREIGN_KEY_CHECKS = ON
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
[routes]
|
||||
; DB setup setup
|
||||
; IMPORTANT: remove/comment this line after setup/update is finished!
|
||||
GET @setup: /setup = Controller\Setup->init, 0
|
||||
|
||||
; static routes (main views) default cache: 86400
|
||||
GET|POST @landing: /= Controller\AppController->showLandingpage, 0
|
||||
|
||||
5
build.js
@@ -87,6 +87,11 @@
|
||||
excludeShallow: [
|
||||
'app'
|
||||
]
|
||||
},{
|
||||
name: 'setup',
|
||||
excludeShallow: [
|
||||
'app'
|
||||
]
|
||||
},{
|
||||
name: 'app/notification',
|
||||
excludeShallow: [
|
||||
|
||||
596
export/sql/pathfinder.sql
Normal file
BIN
favicon/apple-touch-icon-114x114.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
favicon/apple-touch-icon-120x120.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
favicon/apple-touch-icon-144x144.png
Normal file
|
After Width: | Height: | Size: 5.4 KiB |
BIN
favicon/apple-touch-icon-152x152.png
Normal file
|
After Width: | Height: | Size: 5.6 KiB |
BIN
favicon/apple-touch-icon-180x180.png
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
BIN
favicon/apple-touch-icon-57x57.png
Normal file
|
After Width: | Height: | Size: 2.0 KiB |
BIN
favicon/apple-touch-icon-60x60.png
Normal file
|
After Width: | Height: | Size: 2.1 KiB |
BIN
favicon/apple-touch-icon-72x72.png
Normal file
|
After Width: | Height: | Size: 2.6 KiB |
BIN
favicon/apple-touch-icon-76x76.png
Normal file
|
After Width: | Height: | Size: 2.7 KiB |
BIN
favicon/apple-touch-icon-precomposed.png
Normal file
|
After Width: | Height: | Size: 7.9 KiB |
BIN
favicon/apple-touch-icon.png
Normal file
|
After Width: | Height: | Size: 6.8 KiB |
12
favicon/browserconfig.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<browserconfig>
|
||||
<msapplication>
|
||||
<tile>
|
||||
<square70x70logo src="/mstile-70x70.png"/>
|
||||
<square150x150logo src="/mstile-150x150.png"/>
|
||||
<square310x310logo src="/mstile-310x310.png"/>
|
||||
<wide310x150logo src="/mstile-310x150.png"/>
|
||||
<TileColor>#da532c</TileColor>
|
||||
</tile>
|
||||
</msapplication>
|
||||
</browserconfig>
|
||||
BIN
favicon/favicon-160x160.png
Normal file
|
After Width: | Height: | Size: 7.1 KiB |
BIN
favicon/favicon-16x16.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
favicon/favicon-192x192.png
Normal file
|
After Width: | Height: | Size: 8.7 KiB |
BIN
favicon/favicon-32x32.png
Normal file
|
After Width: | Height: | Size: 1.4 KiB |
BIN
favicon/favicon-96x96.png
Normal file
|
After Width: | Height: | Size: 4.2 KiB |
BIN
favicon/favicon.ico
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
favicon/logo.png
Normal file
|
After Width: | Height: | Size: 199 KiB |
BIN
favicon/mstile-144x144.png
Normal file
|
After Width: | Height: | Size: 6.3 KiB |
BIN
favicon/mstile-150x150.png
Normal file
|
After Width: | Height: | Size: 6.5 KiB |
BIN
favicon/mstile-310x150.png
Normal file
|
After Width: | Height: | Size: 7.1 KiB |
BIN
favicon/mstile-310x310.png
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
favicon/mstile-70x70.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
113
gulpfile.js
@@ -3,8 +3,10 @@ var gulp = require('gulp-param')(require('gulp'), process.argv);
|
||||
var jshint = require('gulp-jshint');
|
||||
var notify = require('gulp-notify');
|
||||
var plumber = require('gulp-plumber');
|
||||
var gzip = require('gulp-gzip');
|
||||
var gulpif = require('gulp-if');
|
||||
var clean = require('gulp-clean');
|
||||
var critical = require('critical');
|
||||
|
||||
var runSequence = require('run-sequence');
|
||||
var exec = require('child_process').exec;
|
||||
@@ -21,12 +23,16 @@ var _src = {
|
||||
JS_LIBS: './js/lib/**/*',
|
||||
JS_BUILD: './build_js',
|
||||
JS_DIST: './public/js',
|
||||
CSS_SRC: './public/css/*.css',
|
||||
CSS_DIST: './public/css',
|
||||
PACKAGE: './package.json',
|
||||
CACHE: './tmp/**/*.*'
|
||||
};
|
||||
|
||||
// Gulp plumber error handler
|
||||
var onError = function(err) {
|
||||
'use strict';
|
||||
|
||||
console.log(err);
|
||||
};
|
||||
|
||||
@@ -45,6 +51,7 @@ var tagVersion = null;
|
||||
* RequireJS build task using the r.js optimizer.
|
||||
*/
|
||||
gulp.task('requirejs', ['jshint'], function() {
|
||||
'use strict';
|
||||
|
||||
var rjsPath = path.resolve(__dirname, './node_modules/requirejs/bin/r.js');
|
||||
var oPath = path.resolve(__dirname, './build.js');
|
||||
@@ -59,8 +66,9 @@ gulp.task('requirejs', ['jshint'], function() {
|
||||
}
|
||||
|
||||
runSequence(
|
||||
'copyBuildFiles',
|
||||
'removeBuildFiles'
|
||||
'copyJSBuildFiles',
|
||||
'removeBuildFiles',
|
||||
'gzipJS'
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -73,6 +81,8 @@ gulp.task('requirejs', ['jshint'], function() {
|
||||
* http://jshint.com/docs/options/
|
||||
*/
|
||||
gulp.task('jshint', function(){
|
||||
'use strict';
|
||||
|
||||
return gulp.src([
|
||||
_src.JS_SRC,
|
||||
'!' + _src.JS_LIBS
|
||||
@@ -95,7 +105,8 @@ gulp.task('jshint', function(){
|
||||
* Copy optimized/uglyfied js files from "js_build" folder to "public/js/x.x.x/*" folder
|
||||
* for release deployment (cache busting)
|
||||
*/
|
||||
gulp.task('copyBuildFiles', ['removeDistFiles'], function () {
|
||||
gulp.task('copyJSBuildFiles', ['removeDistFiles'], function () {
|
||||
'use strict';
|
||||
|
||||
// raw files
|
||||
var source = _src.JS_SRC;
|
||||
@@ -113,11 +124,11 @@ gulp.task('copyBuildFiles', ['removeDistFiles'], function () {
|
||||
gulp.dest( _src.JS_DIST + '/' + tagVersion )
|
||||
)
|
||||
).pipe(notify({
|
||||
icon: path.resolve(__dirname, _src.ICON),
|
||||
title: 'Copy JS to dist',
|
||||
message: 'Task complete',
|
||||
onLast: true
|
||||
}));
|
||||
icon: path.resolve(__dirname, _src.ICON),
|
||||
title: 'Copy JS to dist',
|
||||
message: 'Task complete',
|
||||
onLast: true
|
||||
}));
|
||||
});
|
||||
|
||||
/**
|
||||
@@ -125,7 +136,6 @@ gulp.task('copyBuildFiles', ['removeDistFiles'], function () {
|
||||
*/
|
||||
gulp.task('removeBuildFiles', function () {
|
||||
'use strict';
|
||||
|
||||
return gulp.src( _src.JS_BUILD ).pipe( clean( _src.JS_BUILD ) );
|
||||
});
|
||||
|
||||
@@ -134,16 +144,42 @@ gulp.task('removeBuildFiles', function () {
|
||||
*/
|
||||
gulp.task('removeDistFiles', function () {
|
||||
'use strict';
|
||||
|
||||
var dist = _src.JS_DIST + '/' + tagVersion;
|
||||
|
||||
return gulp.src(dist).pipe( clean(dist) );
|
||||
});
|
||||
|
||||
/**
|
||||
* create *.gz version from minimized *.css
|
||||
*/
|
||||
gulp.task('gzipCSS', function() {
|
||||
'use strict';
|
||||
|
||||
return gulp.src(_src.CSS_SRC)
|
||||
.pipe(gzip({
|
||||
gzipOptions: { level: 8 }
|
||||
}))
|
||||
.pipe(gulp.dest(_src.CSS_DIST));
|
||||
});
|
||||
|
||||
/**
|
||||
* create *.gz version from minimized *.js
|
||||
*/
|
||||
gulp.task('gzipJS', function() {
|
||||
'use strict';
|
||||
|
||||
return gulp.src(_src.JS_DIST + '/' + tagVersion + '/**/*.js')
|
||||
.pipe(gzip({
|
||||
gzipOptions: { level: 8 }
|
||||
}))
|
||||
.pipe(gulp.dest(_src.JS_DIST + '/' + tagVersion));
|
||||
});
|
||||
|
||||
/*******************************************/
|
||||
// Watch
|
||||
// execute only during continuous development!
|
||||
gulp.task('watch', function(tag) {
|
||||
gulp.task('watchJSFiles', function(tag) {
|
||||
'use strict';
|
||||
|
||||
if(tag){
|
||||
tagVersion = tag;
|
||||
@@ -152,19 +188,20 @@ gulp.task('watch', function(tag) {
|
||||
gulp.watch([
|
||||
_src.JS_SRC,
|
||||
'!' + _src.JS_LIBS,
|
||||
], ['jshint', 'copyBuildFiles']);
|
||||
|
||||
|
||||
], ['jshint', 'copyJSBuildFiles']);
|
||||
});
|
||||
|
||||
/**
|
||||
* clear all backend (fat free framework) cache files
|
||||
*/
|
||||
gulp.task('clearCache', function() {
|
||||
gulp.task('watchCSSFiles', function(tag) {
|
||||
'use strict';
|
||||
return gulp.src( _src.CACHE ).pipe( clean() );
|
||||
});
|
||||
|
||||
if(tag){
|
||||
tagVersion = tag;
|
||||
}
|
||||
|
||||
gulp.watch([
|
||||
_src.CSS_SRC,
|
||||
], ['gzipCSS']);
|
||||
});
|
||||
|
||||
/*******************************************/
|
||||
// Default Tasks
|
||||
@@ -175,6 +212,7 @@ gulp.task('clearCache', function() {
|
||||
* WARNING: DO NOT REMOVE THIS TASK!!!
|
||||
*/
|
||||
gulp.task('production', function(tag) {
|
||||
'use strict';
|
||||
|
||||
if(tag !== null){
|
||||
tagVersion = tag;
|
||||
@@ -182,6 +220,7 @@ gulp.task('production', function(tag) {
|
||||
|
||||
// use run-sequence until gulp v4.0 is released
|
||||
runSequence(
|
||||
'gzipCSS',
|
||||
'requirejs'
|
||||
);
|
||||
}
|
||||
@@ -193,14 +232,44 @@ gulp.task('production', function(tag) {
|
||||
* WARNING: DO NOT REMOVE THIS TASK!!!
|
||||
*/
|
||||
gulp.task('default', function(tag) {
|
||||
'use strict';
|
||||
|
||||
if(tag){
|
||||
tagVersion = tag;
|
||||
}
|
||||
|
||||
runSequence(
|
||||
'gzipCSS',
|
||||
'jshint',
|
||||
'copyBuildFiles',
|
||||
'watch'
|
||||
'copyJSBuildFiles',
|
||||
'watchJSFiles',
|
||||
'watchCSSFiles'
|
||||
);
|
||||
});
|
||||
|
||||
/*
|
||||
// This removes all CSS styles "above the fold" from *.css and inlines them
|
||||
// -> to improve pagespeed. The remaining (main) css file will be lazy loaded afterwards...
|
||||
// https://github.com/addyosmani/critical
|
||||
gulp.task('critical', function (cb) {
|
||||
critical.generate({
|
||||
inline: true,
|
||||
base: './',
|
||||
src: './public/templates/view/index.html',
|
||||
dest: './public/templates/view/index-critical.html',
|
||||
extract: true,
|
||||
minify: true,
|
||||
width: 2560,
|
||||
height: 1440
|
||||
});
|
||||
});
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* clear all backend (fat free framework) cache files
|
||||
*/
|
||||
gulp.task('clearCache', function() {
|
||||
'use strict';
|
||||
return gulp.src( _src.CACHE ).pipe( clean() );
|
||||
});
|
||||
10
index.php
@@ -1,19 +1,9 @@
|
||||
<?php
|
||||
|
||||
$f3 = require('app/lib/base.php');
|
||||
|
||||
// load main config
|
||||
$f3->config('app/config.ini');
|
||||
|
||||
// load route config
|
||||
$f3->config('app/routes.ini');
|
||||
|
||||
// load pathfinder config
|
||||
$f3->config('app/pathfinder.ini');
|
||||
|
||||
// load cron config
|
||||
$f3->config('app/cron.ini');
|
||||
|
||||
// set base dir
|
||||
$f3->set('BASE', \Controller\Controller::getEnvironmentData('BASE'));
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ requirejs.config({
|
||||
// main views
|
||||
landingpage: './app/landingpage', // initial start "landing page" view
|
||||
mappage: './app/mappage', // initial start "map page" view
|
||||
setup: './app/setup', // initial start "setup page" view
|
||||
|
||||
jquery: 'lib/jquery-1.11.3.min', // v1.11.3 jQuery
|
||||
bootstrap: 'lib/bootstrap.min', // v3.3.0 Bootstrap js code - http://getbootstrap.com/javascript/
|
||||
@@ -27,7 +28,7 @@ requirejs.config({
|
||||
velocity: 'lib/velocity.min', // v1.2.2 animation engine - http://julian.com/research/velocity/
|
||||
velocityUI: 'lib/velocity.ui.min', // v5.0.4 plugin for velocity - http://julian.com/research/velocity/#uiPack
|
||||
slidebars: 'lib/slidebars', // v0.10 Slidebars - side menu plugin http://plugins.adchsm.me/slidebars/
|
||||
jsPlumb: 'lib/dom.jsPlumb-1.7.6-min', // v1.7.6 jsPlumb (Vanilla)- main map draw plugin https://jsplumbtoolkit.com/
|
||||
jsPlumb: 'lib/jsPlumb-2.0.5-min', // v2.0.5 jsPlumb (Vanilla)- main map draw plugin https://jsplumbtoolkit.com/
|
||||
farahey: 'lib/farahey-0.5', // v0.5 jsPlumb "magnetizing" extension - https://github.com/jsplumb/farahey
|
||||
customScrollbar: 'lib/jquery.mCustomScrollbar.concat.min', // v3.0.9 Custom scroll bars - http://manos.malihu.gr/
|
||||
datatables: 'lib/datatables/jquery.dataTables.min', // v1.10.7 DataTables - https://datatables.net/
|
||||
@@ -51,6 +52,7 @@ requirejs.config({
|
||||
blueImpGalleryBootstrap: 'lib/bootstrap-image-gallery', // v3.1.1 Bootstrap extension for Blue Imp Gallery - https://blueimp.github.io/Bootstrap-Image-Gallery/
|
||||
bootstrapConfirmation: 'lib/bootstrap-confirmation', // v1.0.1 Bootstrap extension for inline confirm dialog - https://github.com/tavicu/bs-confirmation
|
||||
bootstrapToggle: 'lib/bootstrap2-toggle.min', // v2.2.0 Bootstrap Toggle (Checkbox) - http://www.bootstraptoggle.com/
|
||||
lazyload: 'lib/jquery.lazyload.min', // v1.9.5 LazyLoader images - http://www.appelsiini.net/projects/lazyload
|
||||
|
||||
// header animation
|
||||
easePack: 'lib/EasePack.min',
|
||||
@@ -142,6 +144,9 @@ requirejs.config({
|
||||
},
|
||||
bootstrapToggle: {
|
||||
deps : ['jquery']
|
||||
},
|
||||
lazyload: {
|
||||
deps : ['jquery']
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -15,7 +15,7 @@ define(['jquery'], function($) {
|
||||
logIn: 'api/user/logIn', // ajax URL - login
|
||||
logOut: 'api/user/logOut', // ajax URL - logout
|
||||
deleteLog: 'api/user/deleteLog', // ajax URL - delete character log
|
||||
saveUserConfig: 'api/user/saveConfig', // ajax URL - saves custom configuration
|
||||
saveUserConfig: 'api/user/saveAccount', // ajax URL - saves/update user account
|
||||
saveSharingConfig: 'api/user/saveSharingConfig', // ajax URL - save "sharing settings" dialog
|
||||
deleteAccount: 'api/user/deleteAccount', // ajax URL - delete Account data
|
||||
// access API
|
||||
@@ -43,7 +43,9 @@ define(['jquery'], function($) {
|
||||
saveSignatureData: 'api/signature/save', // ajax URL - save signature data for system
|
||||
deleteSignatureData: 'api/signature/delete', // ajax URL - delete signature data for system
|
||||
// route API
|
||||
searchRoute: 'api/route/search' // ajax URL - search system routes
|
||||
searchRoute: 'api/route/search', // ajax URL - search system routes
|
||||
// GitHub API
|
||||
gitHubReleases: 'api/github/releases' // ajax URL - get release info from GitHub
|
||||
},
|
||||
url: {
|
||||
ccpImageServer: 'https://image.eveonline.com/', // CCP image Server
|
||||
|
||||
@@ -10,20 +10,23 @@ define([
|
||||
'app/ccp',
|
||||
'blueImpGallery',
|
||||
'bootbox',
|
||||
'lazyload',
|
||||
'app/ui/header',
|
||||
'app/ui/logo',
|
||||
'app/ui/demo_map',
|
||||
'dialog/account_settings',
|
||||
'dialog/notification',
|
||||
'dialog/manual',
|
||||
'dialog/releases',
|
||||
'dialog/credit'
|
||||
], function($, Init, Util, Render, CCP, Gallery, bootbox) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var config = {
|
||||
// header
|
||||
splashOverlayClass: 'pf-splash', // class for "splash" overlay
|
||||
|
||||
// header
|
||||
headerContainerId: 'pf-header-container', // id for header container
|
||||
logoContainerId: 'pf-logo-container', // id for main header logo container
|
||||
headHeaderMapId: 'pf-header-map', // id for header image (svg animation)
|
||||
@@ -37,7 +40,8 @@ define([
|
||||
// navigation
|
||||
navigationElementId: 'pf-navbar', // id for navbar element
|
||||
navigationLinkManualClass: 'pf-navbar-manual', // class for "manual" trigger link
|
||||
navigationLinkLicenseClass : 'pf-navbar-license', // class for "license" trigger link
|
||||
navigationLinkLicenseClass: 'pf-navbar-license', // class for "license" trigger link
|
||||
navigationVersionLinkClass: 'pf-navbar-version-info', // class for "version information"
|
||||
|
||||
// login form
|
||||
loginFormId: 'pf-login-form', // id for login form
|
||||
@@ -47,6 +51,7 @@ define([
|
||||
|
||||
// gallery
|
||||
galleryId: 'pf-gallery', // id for gallery container
|
||||
galleryThumbImageClass: 'pf-landing-image-preview', // class for gallery thumb images
|
||||
galleryThumbContainerId: 'pf-landing-gallery-thumb-container', // id for gallery thumb images
|
||||
galleryCarouselId: 'pf-landing-gallery-carousel', // id for "carousel" element
|
||||
|
||||
@@ -66,7 +71,11 @@ define([
|
||||
e.preventDefault();
|
||||
|
||||
// logout current user (if there e.g. to register a second account)
|
||||
Util.logout();
|
||||
Util.logout({
|
||||
ajaxData: {
|
||||
reroute: 0
|
||||
}
|
||||
});
|
||||
|
||||
// show register/settings dialog
|
||||
$.fn.showSettingsDialog({
|
||||
@@ -75,7 +84,6 @@ define([
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// login buttons ------------------------------------------------
|
||||
var loginForm = $('#' + config.loginFormId);
|
||||
|
||||
@@ -103,7 +111,6 @@ define([
|
||||
data: loginData,
|
||||
dataType: 'json'
|
||||
}).done(function(data){
|
||||
|
||||
// login error
|
||||
if(data.error !== undefined){
|
||||
$('.' + config.splashOverlayClass).hideSplashOverlay();
|
||||
@@ -125,6 +132,11 @@ define([
|
||||
}
|
||||
});
|
||||
|
||||
// releases -----------------------------------------------------
|
||||
$('.' + config.navigationVersionLinkClass).on('click', function(e){
|
||||
$.fn.releasesDialog();
|
||||
});
|
||||
|
||||
// manual -------------------------------------------------------
|
||||
$('.' + config.navigationLinkManualClass).on('click', function(e){
|
||||
e.preventDefault();
|
||||
@@ -397,6 +409,35 @@ define([
|
||||
});
|
||||
};
|
||||
|
||||
var initYoutube = function(){
|
||||
|
||||
$(".youtube").each(function() {
|
||||
// Based on the YouTube ID, we can easily find the thumbnail image
|
||||
$(this).css('background-image', 'url(https://i.ytimg.com/vi/' + this.id + '/sddefault.jpg)');
|
||||
|
||||
// Overlay the Play icon to make it look like a video player
|
||||
$(this).append($('<div/>', {'class': 'play'}));
|
||||
|
||||
$(document).delegate('#'+this.id, 'click', function() {
|
||||
// Create an iFrame with autoplay set to true
|
||||
var iframe_url = "https://www.youtube.com/embed/" + this.id + "?autoplay=1&autohide=1";
|
||||
if ($(this).data('params')) iframe_url+='&'+$(this).data('params');
|
||||
|
||||
// The height and width of the iFrame should be the same as parent
|
||||
var iframe = $('<iframe/>', {
|
||||
frameborder: '0',
|
||||
src: iframe_url,
|
||||
width: $(this).width(),
|
||||
height: $(this).height(),
|
||||
class: 'pricing-big'
|
||||
});
|
||||
|
||||
// Replace the YouTube thumbnail with YouTube HTML5 Player
|
||||
$(this).replaceWith(iframe);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* init scrollspy for navigation bar
|
||||
@@ -444,7 +485,7 @@ define([
|
||||
};
|
||||
|
||||
/**
|
||||
* main init landing page
|
||||
* main init "landing" page
|
||||
*/
|
||||
$(function(){
|
||||
|
||||
@@ -454,6 +495,7 @@ define([
|
||||
// show log off message
|
||||
var isLogOut = location.search.split('logout')[1];
|
||||
if(isLogOut !== undefined){
|
||||
|
||||
// show logout dialog
|
||||
var options = {
|
||||
buttons: {
|
||||
@@ -488,8 +530,10 @@ define([
|
||||
showRequestRegistrationKeyDialog();
|
||||
}
|
||||
|
||||
// init scrollspy
|
||||
initScrollspy();
|
||||
// init "lazy loading" for images
|
||||
$('.' + config.galleryThumbImageClass).lazyload({
|
||||
threshold : 300
|
||||
});
|
||||
|
||||
// hide splash loading animation
|
||||
$('.' + config.splashOverlayClass).hideSplashOverlay();
|
||||
@@ -497,9 +541,15 @@ define([
|
||||
// init carousel
|
||||
initCarousel();
|
||||
|
||||
// init scrollspy
|
||||
initScrollspy();
|
||||
|
||||
// init gallery
|
||||
initGallery();
|
||||
|
||||
// init youtube videos
|
||||
initYoutube();
|
||||
|
||||
// show logo -> hide animation in IGB
|
||||
if( !CCP.isInGameBrowser() ){
|
||||
$('#' + config.logoContainerId).drawLogo(function(){
|
||||
@@ -511,7 +561,6 @@ define([
|
||||
}, false);
|
||||
}
|
||||
|
||||
|
||||
setPageObserver();
|
||||
|
||||
});
|
||||
|
||||
@@ -98,19 +98,23 @@ define([
|
||||
dragOptions:{
|
||||
},
|
||||
connectionsDetachable: true, // dragOptions are set -> allow detaching them
|
||||
maxConnections: 10 // due to isTarget is true, this is the max count of !out!-going connections
|
||||
maxConnections: 10, // due to isTarget is true, this is the max count of !out!-going connections
|
||||
// isSource:true,
|
||||
anchor: 'Continuous'
|
||||
},
|
||||
target: {
|
||||
filter: '.' + config.systemHeadNameClass,
|
||||
isSource:true,
|
||||
//isTarget:true,
|
||||
allowLoopback: false, // loopback connections are not allowed
|
||||
//allowLoopback: false, // loopback connections are not allowed
|
||||
cssClass: config.endpointTargetClass,
|
||||
dropOptions: {
|
||||
tolerance: 'touch',
|
||||
hoverClass: config.systemActiveClass,
|
||||
activeClass: 'dragActive',
|
||||
}
|
||||
activeClass: 'dragActive'
|
||||
},
|
||||
// isTarget:true,
|
||||
// uniqueEndpoint: false,
|
||||
anchor: 'Continuous'
|
||||
},
|
||||
connectionTypes: Init.connectionTypes
|
||||
};
|
||||
@@ -317,7 +321,6 @@ define([
|
||||
|
||||
/**
|
||||
* show/hide systems tooltip
|
||||
* @param systems
|
||||
* @param show
|
||||
* @param options
|
||||
*/
|
||||
@@ -350,7 +353,7 @@ define([
|
||||
}else if(show === 'show'){
|
||||
|
||||
// check if tooltip is currently visible
|
||||
var tooltipActive = (system.attr('aria-describedby') !== undefined ? true : false);
|
||||
var tooltipActive = (system.attr('aria-describedby') !== undefined);
|
||||
|
||||
if(options === undefined){
|
||||
options = {};
|
||||
@@ -858,9 +861,9 @@ define([
|
||||
mapElement.getMapOverlay('timer').startMapUpdateCounter();
|
||||
|
||||
var systemElements = mapElement.find('.' + config.systemClass);
|
||||
var endpointElements = mapElement.find('._jsPlumb_endpoint');
|
||||
var connectorElements = mapElement.find('._jsPlumb_connector');
|
||||
var overlayElements = mapElement.find('._jsPlumb_overlay, .tooltip');
|
||||
var endpointElements = mapElement.find('.jsplumb-endpoint');
|
||||
var connectorElements = mapElement.find('.jsplumb-connector');
|
||||
var overlayElements = mapElement.find('.jsplumb-overlay, .tooltip');
|
||||
|
||||
// if map empty (no systems), execute callback and return
|
||||
// no visual effects in IGB (glitches)
|
||||
@@ -1004,9 +1007,9 @@ define([
|
||||
|
||||
/**
|
||||
* draw a system with its data to a map
|
||||
* @param map object
|
||||
* @param map
|
||||
* @param systemData
|
||||
* @param {String[]} optional Systems for connection
|
||||
* @param connectedSystem
|
||||
*/
|
||||
var drawSystem = function(map, systemData, connectedSystem){
|
||||
|
||||
@@ -1165,7 +1168,6 @@ define([
|
||||
|
||||
/**
|
||||
* update z-index for a system (dragged systems should be always on top)
|
||||
* @param system
|
||||
*/
|
||||
$.fn.updateSystemZIndex = function(){
|
||||
return this.each(function(){
|
||||
@@ -1333,6 +1335,7 @@ define([
|
||||
/**
|
||||
* delete a connection and all related data
|
||||
* @param connections
|
||||
* @param callback
|
||||
*/
|
||||
$.fn.deleteConnections = function(connections, callback){
|
||||
if(connections.length > 0){
|
||||
@@ -1660,7 +1663,7 @@ define([
|
||||
{subIcon: 'fa-info', subAction: 'ingame_show_info', subText: 'show info'},
|
||||
{subDivider: true, action: 'ingame'},
|
||||
{subIcon: 'fa-flag', subAction: 'ingame_add_waypoint', subText: 'add waypoint'},
|
||||
{subIcon: 'fa-flag-checkered', subAction: 'ingame_set_destination', subText: 'set destination'},
|
||||
{subIcon: 'fa-flag-checkered', subAction: 'ingame_set_destination', subText: 'set destination'}
|
||||
]},
|
||||
{divider: true, action: 'delete_system'},
|
||||
{icon: 'fa-eraser', action: 'delete_system', text: 'delete system'}
|
||||
@@ -1746,32 +1749,31 @@ define([
|
||||
// show tooltip
|
||||
dragSystem.toggleSystemTooltip('show', {show: true});
|
||||
|
||||
// mark as "changed"
|
||||
dragSystem.markAsChanged();
|
||||
|
||||
// set new position for popover edit field (system name)
|
||||
var newPosition = dragSystem.position();
|
||||
|
||||
var placement = 'top';
|
||||
if(newPosition.top < 100){
|
||||
placement = 'bottom';
|
||||
}
|
||||
if(newPosition.left < 100){
|
||||
placement = 'right';
|
||||
}
|
||||
dragSystem.find('.' + config.systemHeadNameClass).editable('option', 'placement', placement);
|
||||
|
||||
// drag system is not always selected
|
||||
var selectedSystems = mapContainer.getSelectedSystems().get();
|
||||
selectedSystems = selectedSystems.concat( dragSystem.get() );
|
||||
selectedSystems = $.unique( selectedSystems );
|
||||
|
||||
|
||||
for(var i = 0; i < selectedSystems.length; i++){
|
||||
var tempSystem = $(selectedSystems[i]);
|
||||
|
||||
// set all selected systems as "changes" for update
|
||||
tempSystem.markAsChanged();
|
||||
|
||||
// set new position for popover edit field (system name)
|
||||
var tempPosition = tempSystem.position();
|
||||
|
||||
var placement = 'top';
|
||||
if(tempPosition.top < 100){
|
||||
placement = 'bottom';
|
||||
}
|
||||
if(tempPosition.left < 100){
|
||||
placement = 'right';
|
||||
}
|
||||
|
||||
tempSystem.find('.' + config.systemHeadNameClass).editable('option', 'placement', placement);
|
||||
// repaint connections -> just in case something fails...
|
||||
map.revalidate( tempSystem.attr('id') );
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1964,7 +1966,7 @@ define([
|
||||
break;
|
||||
case 'delete_system':
|
||||
// confirm dialog
|
||||
var systemDeleteDialog = bootbox.confirm('Delete system and all its connections?', function(result) {
|
||||
bootbox.confirm('Delete system and all its connections?', function(result) {
|
||||
if(result){
|
||||
var systemName = currentSystem.getSystemInfo(['alias']);
|
||||
deleteSystems(map, [currentSystem], function(){
|
||||
@@ -2130,12 +2132,8 @@ define([
|
||||
* @returns {*}
|
||||
*/
|
||||
$.fn.getSelectedSystems = function(){
|
||||
|
||||
var mapElement = $(this);
|
||||
|
||||
var systems = mapElement.find('.' + config.systemSelectedClass);
|
||||
|
||||
return systems;
|
||||
return mapElement.find('.' + config.systemSelectedClass);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -2436,7 +2434,6 @@ define([
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// catch events =========================================================
|
||||
|
||||
// toggle global map option (e.g. "grid snap", "magnetization"
|
||||
@@ -3362,15 +3359,14 @@ define([
|
||||
var newJsPlumbInstance = jsPlumb.getInstance({
|
||||
Anchor: 'Continuous', // anchors on each site
|
||||
Container: null, // will be set as soon as container is connected to DOM
|
||||
PaintStyle:{
|
||||
PaintStyle: {
|
||||
lineWidth: 4, // width of a Connector's line. An integer.
|
||||
strokeStyle: 'red', // color for a Connector
|
||||
outlineColor: 'red', // color of the outline for an Endpoint or Connector. see fillStyle examples.
|
||||
outlineWidth: 2 // width of the outline for an Endpoint or Connector. An integer.
|
||||
},
|
||||
Connector:[ 'Bezier', { curviness: 40 } ], // default connector style (this is not used!) all connections have their own style (by scope)
|
||||
Endpoints: [ [ 'Dot', { radius: 5 } ], [ 'Dot', { radius: 5 } ] ],
|
||||
// Endpoint: 'Blank', // does not work... :(
|
||||
Connector: [ 'Bezier', { curviness: 40 } ], // default connector style (this is not used!) all connections have their own style (by scope)
|
||||
Endpoint: [ 'Dot', { radius: 5 } ],
|
||||
ReattachConnections: false, // re-attach connection if dragged with mouse to "nowhere"
|
||||
Scope: Init.defaultMapScope, // default map scope for connections
|
||||
LogEnabled: true
|
||||
|
||||
@@ -16,6 +16,9 @@ define([
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* main init "map" page
|
||||
*/
|
||||
$(function(){
|
||||
// load page
|
||||
$('body').loadPageStructure();
|
||||
|
||||
@@ -481,7 +481,8 @@ define([
|
||||
|
||||
var moduleData = {
|
||||
id: config.pageFooterId,
|
||||
footerLicenceLinkClass: config.footerLicenceLinkClass
|
||||
footerLicenceLinkClass: config.footerLicenceLinkClass,
|
||||
currentYear: new Date().getFullYear()
|
||||
};
|
||||
|
||||
var headRendered = Mustache.render(TplFooter, moduleData);
|
||||
@@ -612,7 +613,11 @@ define([
|
||||
|
||||
$(document).on('pf:menuLogout', function(e, data){
|
||||
// logout
|
||||
Util.logout();
|
||||
Util.logout({
|
||||
ajaxData: {
|
||||
reroute: 1
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
|
||||
53
js/app/setup.js
Normal file
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Main landingPage application
|
||||
*/
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util'
|
||||
], function($, Init, Util) {
|
||||
'use strict';
|
||||
|
||||
var config = {
|
||||
splashOverlayClass: 'pf-splash' // class for "splash" overlay
|
||||
};
|
||||
|
||||
/**
|
||||
* set page observer
|
||||
*/
|
||||
var setPageObserver = function(){
|
||||
|
||||
// collapse ---------------------------------------
|
||||
$('body').find('[data-toggle="collapse"]').css({cursor: 'pointer'}).on('click', function(){
|
||||
$(this).find('.pf-animate-rotate').toggleClass('right');
|
||||
});
|
||||
|
||||
// buttons ----------------------------------------
|
||||
$('body').find('.btn').on('click', function(e){
|
||||
$('.' + config.splashOverlayClass).showSplashOverlay();
|
||||
});
|
||||
|
||||
// tooltips ---------------------------------------
|
||||
$('body').initTooltips();
|
||||
|
||||
// change url (remove logout parameter)
|
||||
if (history.pushState) {
|
||||
history.pushState({}, '', location.protocol + '//' + location.host + location.pathname);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* main init "setup" page
|
||||
*/
|
||||
$(function(){
|
||||
|
||||
// show app information in browser console --------
|
||||
Util.showVersionInfo();
|
||||
|
||||
// hide splash loading animation ------------------
|
||||
$('.' + config.splashOverlayClass).hideSplashOverlay();
|
||||
|
||||
setPageObserver();
|
||||
});
|
||||
});
|
||||
@@ -225,20 +225,17 @@ define([
|
||||
currentActiveLink.addClass('btn-primary');
|
||||
|
||||
currentActiveTab.next('li').find('a').tab('show');
|
||||
|
||||
};
|
||||
|
||||
// validate form
|
||||
form.validator('validate');
|
||||
var formValid = form.isValidForm();
|
||||
|
||||
|
||||
if(!formValid){
|
||||
currentActiveTab.removeClass('disabled');
|
||||
currentActiveLink.removeClass('btn-default btn-primary');
|
||||
currentActiveLink.addClass('btn-danger');
|
||||
}else{
|
||||
|
||||
var tabFormValues = form.getFormValues();
|
||||
|
||||
if(! $.isEmptyObject(tabFormValues) ){
|
||||
@@ -299,7 +296,7 @@ define([
|
||||
selectCharacterDialog.find('.modal-content').hideLoadingAnimation();
|
||||
|
||||
var reason = status + ' ' + error;
|
||||
Util.showNotify({title: jqXHR.status + ': saveConfig', text: reason, type: 'error'});
|
||||
Util.showNotify({title: jqXHR.status + ': saveAccount', text: reason, type: 'error'});
|
||||
|
||||
// set new captcha for any request
|
||||
// captcha is required for sensitive data (not for all)
|
||||
|
||||
100
js/app/ui/dialog/releases.js
Normal file
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* releases dialog (GitHub API repository information)
|
||||
*/
|
||||
|
||||
define([
|
||||
'jquery',
|
||||
'app/init',
|
||||
'app/util',
|
||||
'app/render',
|
||||
'bootbox'
|
||||
], function($, Init, Util, Render, bootbox) {
|
||||
'use strict';
|
||||
|
||||
var config = {
|
||||
releasesDialogClass: 'pf-releases-dialog' // class for "Releases" dialog
|
||||
};
|
||||
|
||||
/**
|
||||
* load release information in dialog
|
||||
* @param releasesDialog
|
||||
*/
|
||||
var loadDialogData = function(releasesDialog){
|
||||
|
||||
// lock dialog
|
||||
var dialogContent = releasesDialog.find('.modal-content');
|
||||
dialogContent.showLoadingAnimation();
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: Init.path.gitHubReleases,
|
||||
// data: updatedMapData,
|
||||
dataType: 'json'
|
||||
}).done(function(releasesData){
|
||||
requirejs(['text!templates/ui/timeline_element.html', 'mustache'], function(template, Mustache) {
|
||||
for(var i = 0; i < releasesData.length; i++){
|
||||
var releaseData = releasesData[i];
|
||||
|
||||
// template vars
|
||||
var data = {
|
||||
isFirst: (i === 0),
|
||||
isOdd: (i % 2 !== 0),
|
||||
releaseDate: releaseData.published_at.substr(0, 10),
|
||||
releaseData: releaseData
|
||||
};
|
||||
|
||||
var content = Mustache.render(template, data);
|
||||
releasesDialog.find('ul.timeline').append(content);
|
||||
}
|
||||
|
||||
// console.log()
|
||||
|
||||
$('.timeline > li').velocity('transition.expandIn', {
|
||||
stagger: 300,
|
||||
duration: 240,
|
||||
//display: 'auto',
|
||||
complete: function(){
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
}).fail(function( jqXHR, status, error) {
|
||||
var reason = status + ' ' + jqXHR.status + ': ' + error;
|
||||
Util.showNotify({title: jqXHR.status + ': login', text: reason, type: 'error'});
|
||||
}).always(function() {
|
||||
dialogContent.hideLoadingAnimation();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* show releases dialog
|
||||
*/
|
||||
$.fn.releasesDialog = function(){
|
||||
|
||||
requirejs(['text!templates/dialog/releases.html', 'mustache'], function(template, Mustache) {
|
||||
|
||||
var data = {
|
||||
test: 'blaBla'
|
||||
};
|
||||
|
||||
var content = Mustache.render(template, data);
|
||||
|
||||
var releasesDialog = bootbox.dialog({
|
||||
className: config.releasesDialogClass,
|
||||
title: 'Releases',
|
||||
size: 'large',
|
||||
message: content
|
||||
});
|
||||
|
||||
// after modal is shown =======================================================================
|
||||
releasesDialog.on('shown.bs.modal', function(e) {
|
||||
|
||||
loadDialogData(releasesDialog);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
};
|
||||
});
|
||||
@@ -72,7 +72,7 @@ define([
|
||||
}
|
||||
},
|
||||
trust: {
|
||||
label: '<i class="fa fa-fw fa-lock"></i> trust set',
|
||||
label: '<i class="fa fa-fw fa-lock"></i> set "Trust"',
|
||||
className: 'btn-primary',
|
||||
callback: function(){
|
||||
var dialog = $(this);
|
||||
|
||||
@@ -489,7 +489,6 @@ define([
|
||||
tooltipData.created.character &&
|
||||
tooltipData.updated.character
|
||||
){
|
||||
|
||||
var createdData = tooltipData.created;
|
||||
var updatedData = tooltipData.updated;
|
||||
|
||||
@@ -1626,7 +1625,10 @@ define([
|
||||
var currentUrl = document.URL;
|
||||
|
||||
if(url !== currentUrl){
|
||||
if(params.length > 0){
|
||||
if(
|
||||
params &&
|
||||
params.length > 0
|
||||
){
|
||||
url += '?' + params.join('&');
|
||||
}
|
||||
window.location = url;
|
||||
@@ -1635,16 +1637,24 @@ define([
|
||||
|
||||
/**
|
||||
* send logout request
|
||||
* @param params
|
||||
*/
|
||||
var logout = function(){
|
||||
var logout = function(params){
|
||||
var data = {};
|
||||
if(
|
||||
params &&
|
||||
params.ajaxData
|
||||
){
|
||||
data = params.ajaxData;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
type: 'POST',
|
||||
url: Init.path.logOut,
|
||||
data: {},
|
||||
data: data,
|
||||
dataType: 'json'
|
||||
}).done(function(data){
|
||||
if(data.reroute !== undefined){
|
||||
if(data.reroute){
|
||||
redirect(data.reroute, ['logout']);
|
||||
}
|
||||
}).fail(function( jqXHR, status, error) {
|
||||
|
||||
3
js/lib/bootstrap2-toggle.min.js
vendored
@@ -5,5 +5,4 @@
|
||||
* Copyright 2014 Min Hur, The New York Times Company
|
||||
* Licensed under MIT
|
||||
* ======================================================================== */
|
||||
+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.toggle"),f="object"==typeof b&&b;e||d.data("bs.toggle",e=new c(this,f)),"string"==typeof b&&e[b]&&e[b]()})}var c=function(b,c){this.$element=a(b),this.options=a.extend({},this.defaults(),c),this.render()};c.VERSION="2.2.0",c.DEFAULTS={on:"On",off:"Off",onstyle:"primary",offstyle:"default",size:"normal",style:"",width:null,height:null},c.prototype.defaults=function(){return{on:this.$element.attr("data-on")||c.DEFAULTS.on,off:this.$element.attr("data-off")||c.DEFAULTS.off,onstyle:this.$element.attr("data-onstyle")||c.DEFAULTS.onstyle,offstyle:this.$element.attr("data-offstyle")||c.DEFAULTS.offstyle,size:this.$element.attr("data-size")||c.DEFAULTS.size,style:this.$element.attr("data-style")||c.DEFAULTS.style,width:this.$element.attr("data-width")||c.DEFAULTS.width,height:this.$element.attr("data-height")||c.DEFAULTS.height}},c.prototype.render=function(){this._onstyle="btn-"+this.options.onstyle,this._offstyle="btn-"+this.options.offstyle;var b="large"===this.options.size?"btn-large":"small"===this.options.size?"btn-small":"mini"===this.options.size?"btn-mini":"",c=a('<label class="btn">').html(this.options.on).addClass(this._onstyle+" "+b),d=a('<label class="btn">').html(this.options.off).addClass(this._offstyle+" "+b+" active"),e=a('<span class="toggle-handle btn btn-default">').addClass(b),f=a('<div class="toggle-group">').append(c,d,e),g=a('<div class="toggle btn" data-toggle="toggle">').addClass(this.$element.prop("checked")?this._onstyle:this._offstyle+" off").addClass(b).addClass(this.options.style);this.$element.wrap(g),a.extend(this,{$toggle:this.$element.parent(),$toggleOn:c,$toggleOff:d,$toggleGroup:f}),this.$toggle.append(f);var h=this.options.width||Math.max(c.width(),d.width())+e.outerWidth()/2,i=this.options.height||Math.max(c.height(),d.height());c.addClass("toggle-on"),d.addClass("toggle-off"),this.$toggle.css({width:h,height:i}),this.options.height&&(c.css("line-height",c.height()+"px"),d.css("line-height",d.height()+"px")),this.update(!0),this.trigger(!0)},c.prototype.toggle=function(){this.$element.prop("checked")?this.off():this.on()},c.prototype.on=function(a){return this.$element.prop("disabled")?!1:(this.$toggle.removeClass(this._offstyle+" off").addClass(this._onstyle),this.$element.prop("checked",!0),void(a||this.trigger()))},c.prototype.off=function(a){return this.$element.prop("disabled")?!1:(this.$toggle.removeClass(this._onstyle).addClass(this._offstyle+" off"),this.$element.prop("checked",!1),void(a||this.trigger()))},c.prototype.enable=function(){this.$toggle.removeAttr("disabled"),this.$element.prop("disabled",!1)},c.prototype.disable=function(){this.$toggle.attr("disabled","disabled"),this.$element.prop("disabled",!0)},c.prototype.update=function(a){this.$element.prop("disabled")?this.disable():this.enable(),this.$element.prop("checked")?this.on(a):this.off(a)},c.prototype.trigger=function(b){this.$element.off("change.bs.toggle"),b||this.$element.change(),this.$element.on("change.bs.toggle",a.proxy(function(){this.update()},this))},c.prototype.destroy=function(){this.$element.off("change.bs.toggle"),this.$toggleGroup.remove(),this.$element.removeData("bs.toggle"),this.$element.unwrap()};var d=a.fn.bootstrapToggle;a.fn.bootstrapToggle=b,a.fn.bootstrapToggle.Constructor=c,a.fn.toggle.noConflict=function(){return a.fn.bootstrapToggle=d,this},a(function(){a("input[type=checkbox][data-toggle^=toggle]").bootstrapToggle()}),a(document).on("click.bs.toggle","div[data-toggle^=toggle]",function(b){var c=a(this).find("input[type=checkbox]");c.bootstrapToggle("toggle"),b.preventDefault()})}(jQuery);
|
||||
//# sourceMappingURL=bootstrap2-toggle.min.js.map
|
||||
+function(a){"use strict";function b(b){return this.each(function(){var d=a(this),e=d.data("bs.toggle"),f="object"==typeof b&&b;e||d.data("bs.toggle",e=new c(this,f)),"string"==typeof b&&e[b]&&e[b]()})}var c=function(b,c){this.$element=a(b),this.options=a.extend({},this.defaults(),c),this.render()};c.VERSION="2.2.0",c.DEFAULTS={on:"On",off:"Off",onstyle:"primary",offstyle:"default",size:"normal",style:"",width:null,height:null},c.prototype.defaults=function(){return{on:this.$element.attr("data-on")||c.DEFAULTS.on,off:this.$element.attr("data-off")||c.DEFAULTS.off,onstyle:this.$element.attr("data-onstyle")||c.DEFAULTS.onstyle,offstyle:this.$element.attr("data-offstyle")||c.DEFAULTS.offstyle,size:this.$element.attr("data-size")||c.DEFAULTS.size,style:this.$element.attr("data-style")||c.DEFAULTS.style,width:this.$element.attr("data-width")||c.DEFAULTS.width,height:this.$element.attr("data-height")||c.DEFAULTS.height}},c.prototype.render=function(){this._onstyle="btn-"+this.options.onstyle,this._offstyle="btn-"+this.options.offstyle;var b="large"===this.options.size?"btn-large":"small"===this.options.size?"btn-small":"mini"===this.options.size?"btn-mini":"",c=a('<label class="btn">').html(this.options.on).addClass(this._onstyle+" "+b),d=a('<label class="btn">').html(this.options.off).addClass(this._offstyle+" "+b+" active"),e=a('<span class="toggle-handle btn btn-default">').addClass(b),f=a('<div class="toggle-group">').append(c,d,e),g=a('<div class="toggle btn" data-toggle="toggle">').addClass(this.$element.prop("checked")?this._onstyle:this._offstyle+" off").addClass(b).addClass(this.options.style);this.$element.wrap(g),a.extend(this,{$toggle:this.$element.parent(),$toggleOn:c,$toggleOff:d,$toggleGroup:f}),this.$toggle.append(f);var h=this.options.width||Math.max(c.width(),d.width())+e.outerWidth()/2,i=this.options.height||Math.max(c.height(),d.height());c.addClass("toggle-on"),d.addClass("toggle-off"),this.$toggle.css({width:h,height:i}),this.options.height&&(c.css("line-height",c.height()+"px"),d.css("line-height",d.height()+"px")),this.update(!0),this.trigger(!0)},c.prototype.toggle=function(){this.$element.prop("checked")?this.off():this.on()},c.prototype.on=function(a){return this.$element.prop("disabled")?!1:(this.$toggle.removeClass(this._offstyle+" off").addClass(this._onstyle),this.$element.prop("checked",!0),void(a||this.trigger()))},c.prototype.off=function(a){return this.$element.prop("disabled")?!1:(this.$toggle.removeClass(this._onstyle).addClass(this._offstyle+" off"),this.$element.prop("checked",!1),void(a||this.trigger()))},c.prototype.enable=function(){this.$toggle.removeAttr("disabled"),this.$element.prop("disabled",!1)},c.prototype.disable=function(){this.$toggle.attr("disabled","disabled"),this.$element.prop("disabled",!0)},c.prototype.update=function(a){this.$element.prop("disabled")?this.disable():this.enable(),this.$element.prop("checked")?this.on(a):this.off(a)},c.prototype.trigger=function(b){this.$element.off("change.bs.toggle"),b||this.$element.change(),this.$element.on("change.bs.toggle",a.proxy(function(){this.update()},this))},c.prototype.destroy=function(){this.$element.off("change.bs.toggle"),this.$toggleGroup.remove(),this.$element.removeData("bs.toggle"),this.$element.unwrap()};var d=a.fn.bootstrapToggle;a.fn.bootstrapToggle=b,a.fn.bootstrapToggle.Constructor=c,a.fn.toggle.noConflict=function(){return a.fn.bootstrapToggle=d,this},a(function(){a("input[type=checkbox][data-toggle^=toggle]").bootstrapToggle()}),a(document).on("click.bs.toggle","div[data-toggle^=toggle]",function(b){var c=a(this).find("input[type=checkbox]");c.bootstrapToggle("toggle"),b.preventDefault()})}(jQuery);
|
||||