Add new "Setup" routine for database bootstrapping (closes #6, closes), fixed redirect (closes #79), removed registration mail (closes #80), some minor bugfixes
@@ -11,10 +11,13 @@ 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.
|
||||
# Now, rewrite any request to the wrong domain 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]
|
||||
|
||||
|
||||
|
||||
@@ -1,36 +1,39 @@
|
||||
; 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/
|
||||
|
||||
60
app/environment.ini
Normal file
@@ -0,0 +1,60 @@
|
||||
; Environment Config
|
||||
|
||||
[ENVIRONMENT]
|
||||
; project environment (DEVELOP, PRODUCTION).
|
||||
; This effects: DB connection, Mail-Server connection
|
||||
; configuration below
|
||||
SERVER = DEVELOP
|
||||
|
||||
[ENVIRONMENT.DEVELOP]
|
||||
;BASE = /pathfinder <= default: "auto-detect"
|
||||
; 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_empty
|
||||
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/w0128162/www.pathfinder.exodus4d.de
|
||||
; deployment URL
|
||||
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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -102,9 +91,9 @@ class Route extends \Controller\AccessController {
|
||||
array_push($this->jumpArray[$systemName],$systemId);
|
||||
}
|
||||
|
||||
$this->f3->set($cacheKeyNamedArray, $this->nameArray, $this->jumpDataCacheTime);
|
||||
$this->f3->set($cacheKeyJumpArray, $this->jumpArray, $this->jumpDataCacheTime);
|
||||
$this->f3->set($cacheKeyIdArray, $this->idArray, $this->jumpDataCacheTime);
|
||||
$f3->set($cacheKeyNamedArray, $this->nameArray, $this->jumpDataCacheTime);
|
||||
$f3->set($cacheKeyJumpArray, $this->jumpArray, $this->jumpDataCacheTime);
|
||||
$f3->set($cacheKeyIdArray, $this->idArray, $this->jumpDataCacheTime);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,6 +191,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 +259,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 +281,9 @@ class Route extends \Controller\AccessController {
|
||||
!empty($systemFrom) &&
|
||||
!empty($systemTo)
|
||||
){
|
||||
|
||||
$this->setSystemJumpData();
|
||||
|
||||
$from = strtoupper( $systemFrom );
|
||||
$to = strtoupper( $systemTo );
|
||||
|
||||
@@ -377,7 +370,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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -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
|
||||
@@ -471,12 +466,6 @@ class User extends Controller\Controller{
|
||||
// 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,9 +16,8 @@ class AppController extends Controller {
|
||||
* @param $f3
|
||||
*/
|
||||
public function showLandingpage($f3) {
|
||||
|
||||
// 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');
|
||||
@@ -29,7 +28,7 @@ class AppController extends Controller {
|
||||
// JS main file
|
||||
$f3->set('jsView', 'landingpage');
|
||||
|
||||
$this->setTemplate('templates/view/index.html');
|
||||
$this->setTemplate( $f3->get('PATHFINDER.VIEW.INDEX') );
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,9 +24,9 @@ class CcpApiController extends Controller{
|
||||
protected function getUserAgent(){
|
||||
$userAgent = '';
|
||||
|
||||
$userAgent .= $this->f3->get('PATHFINDER.NAME');
|
||||
$userAgent .= ' - ' . $this->f3->get('PATHFINDER.VERSION');
|
||||
$userAgent .= ' | ' . $this->f3->get('PATHFINDER.CONTACT');
|
||||
$userAgent .= $this->getF3()->get('PATHFINDER.NAME');
|
||||
$userAgent .= ' - ' . $this->getF3()->get('PATHFINDER.VERSION');
|
||||
$userAgent .= ' | ' . $this->getF3()->get('PATHFINDER.CONTACT');
|
||||
$userAgent .= ' (' . $_SERVER['SERVER_NAME'] . ')';
|
||||
|
||||
return $userAgent;
|
||||
@@ -55,7 +55,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"
|
||||
@@ -45,6 +51,11 @@ class Controller {
|
||||
*/
|
||||
function beforeroute($f3) {
|
||||
|
||||
$this->getF3($f3);
|
||||
|
||||
// initiate DB connection
|
||||
DB\Database::instance('PF');
|
||||
|
||||
// init user session
|
||||
$this->initSession();
|
||||
|
||||
@@ -56,12 +67,12 @@ class Controller {
|
||||
}
|
||||
|
||||
/**
|
||||
* event handler
|
||||
* event handler after routing
|
||||
* -> render view
|
||||
*/
|
||||
function afterroute() {
|
||||
public function afterroute($f3) {
|
||||
if($this->template){
|
||||
echo \Template::instance()->render( $this->template );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +106,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 +131,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 = self::getEnvironmentData('URL') . $f3->alias('landing');
|
||||
}else{
|
||||
// no reroute -> errors can be shown
|
||||
$return->error[] = $this->getUserLoggedOffError();
|
||||
}
|
||||
|
||||
echo json_encode($return);
|
||||
die();
|
||||
@@ -242,7 +261,6 @@ class Controller {
|
||||
return $isIGB;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* get error object is a user is not found/logged of
|
||||
* @return object
|
||||
@@ -290,8 +308,8 @@ 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) ){
|
||||
@@ -301,61 +319,80 @@ class Controller {
|
||||
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';
|
||||
}
|
||||
|
||||
/**
|
||||
* onError() callback function
|
||||
* @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);
|
||||
}else{
|
||||
// render error in template
|
||||
$f3->set('errorData', [$error]);
|
||||
|
||||
// show Errors in Dev environment
|
||||
if( !self::isProduction() ){
|
||||
var_dump($error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for framework "unload"
|
||||
* -> 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,11 +10,6 @@ namespace Controller;
|
||||
|
||||
class MapController extends \Controller\AccessController {
|
||||
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
|
||||
public function showMap($f3) {
|
||||
|
||||
$f3->set('pageContent', false);
|
||||
@@ -28,7 +23,7 @@ class MapController extends \Controller\AccessController {
|
||||
// JS main file
|
||||
$this->f3->set('jsView', 'mappage');
|
||||
|
||||
$this->setTemplate('templates/view/index.html');
|
||||
$this->setTemplate( $f3->get('PATHFINDER.VIEW.INDEX') );
|
||||
}
|
||||
|
||||
}
|
||||
696
app/main/controller/setup.php
Normal file
@@ -0,0 +1,696 @@
|
||||
<?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) {
|
||||
// load "requirements" info in "setup" route only
|
||||
$f3->config('app/requirements.ini');
|
||||
}
|
||||
|
||||
public function afterroute($f3) {
|
||||
// body element class
|
||||
$f3->set('bodyClass', 'pf-body pf-landing');
|
||||
|
||||
// main page content
|
||||
$f3->set('pageContent', $f3->get('PATHFINDER.VIEW.SETUP'));
|
||||
|
||||
// js path (build/minified or raw uncompressed files)
|
||||
$f3->set('pathJs', 'public/js/' . $f3->get('PATHFINDER.VERSION') );
|
||||
|
||||
// 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['export']) &&
|
||||
isset($params['table']) &&
|
||||
!empty($params['table'])
|
||||
){
|
||||
$f3->set('errorData', $this->exportTableData($params['table']));
|
||||
}elseif(
|
||||
isset($params['import']) &&
|
||||
isset($params['table']) &&
|
||||
!empty($params['table'])
|
||||
){
|
||||
$f3->set('successData', $this->importTableData($params['table']));
|
||||
}
|
||||
|
||||
if(
|
||||
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));
|
||||
}
|
||||
|
||||
/**
|
||||
* import/upload table data from *.csv
|
||||
* path: export/db/$tableName.svg
|
||||
* @param $tableIndex
|
||||
* @return array
|
||||
*/
|
||||
protected function importTableData($tableIndex){
|
||||
$importStatus = [];
|
||||
|
||||
// check if tableIndex exists as model class
|
||||
if(array_key_exists($tableIndex, $this->databases['PF']['models'])){
|
||||
$db = DB\Database::instance()->getDB('PF');
|
||||
$modelClass = $this->databases['PF']['models'][$tableIndex];
|
||||
$model = new $modelClass($db);
|
||||
$status = $model->importData();
|
||||
|
||||
if($status){
|
||||
$importStatus[] = [
|
||||
'status' => $model->getTable(),
|
||||
'message' => 'Added: ' . $status['added'] . ' ' .
|
||||
'Updated: ' . $status['updated'] . ' ' .
|
||||
'Deleted: ' . $status['deleted']
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $importStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* export/download table data as *.csv
|
||||
* target dir export/db/$tableName.svg
|
||||
* @param $tableIndex
|
||||
* @return array
|
||||
*/
|
||||
protected function exportTableData($tableIndex){
|
||||
$exportStatus = [];
|
||||
|
||||
// check if tableIndex exists as model class
|
||||
if(array_key_exists($tableIndex, $this->databases['PF']['models'])){
|
||||
$db = DB\Database::instance()->getDB('PF');
|
||||
$modelClass = $this->databases['PF']['models'][$tableIndex];
|
||||
$model = new $modelClass($db);
|
||||
$status = $model->exportData();
|
||||
|
||||
if( !$status ){
|
||||
// error
|
||||
$error = (object) [];
|
||||
$error->code = 503;
|
||||
$error->status = $model->getTable();
|
||||
$error->message = 'No data for export found. Table empty?';
|
||||
$exportStatus[] = $error;
|
||||
}
|
||||
}
|
||||
|
||||
return $exportStatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 ------------------------------------------------------------------
|
||||
$serverType = '???';
|
||||
$serverVersion = '???';
|
||||
$requiredServerVersion = '???';
|
||||
if(strpos('nginx', $_SERVER['SERVER_SOFTWARE']) !== 1){
|
||||
$serverType = reset(explode('/', $_SERVER['SERVER_SOFTWARE']));
|
||||
$serverVersion = end(explode('/', $_SERVER['SERVER_SOFTWARE']));
|
||||
|
||||
$requiredServerVersion = $f3->get('REQUIREMENTS.SERVER.NGINX.VERSION');
|
||||
}else{
|
||||
print_r('TODO Apache');
|
||||
}
|
||||
|
||||
|
||||
$checkRequirements = [
|
||||
'servertype' => [
|
||||
'label' => 'Server type',
|
||||
'version' => $serverType,
|
||||
'check' => true
|
||||
],
|
||||
'serverversion' => [
|
||||
'label' => 'Server version',
|
||||
'required' => $requiredServerVersion,
|
||||
'version' => $serverVersion,
|
||||
'check' => version_compare( $serverVersion, $requiredServerVersion, '>=')
|
||||
],
|
||||
'php' => [
|
||||
'label' => 'PHP',
|
||||
'required' => $f3->get('REQUIREMENTS.PHP.VERSION'),
|
||||
'version' => phpversion(),
|
||||
'prefix' => 'v.',
|
||||
'check' => version_compare( phpversion(), $f3->get('REQUIREMENTS.PHP.VERSION'), '>=')
|
||||
],
|
||||
'pcre' => [
|
||||
'label' => 'PCRE',
|
||||
'required' => $f3->get('REQUIREMENTS.PHP.PCRE_VERSION'),
|
||||
'version' => strstr(PCRE_VERSION, ' ', true),
|
||||
'prefix' => 'v.',
|
||||
'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($serverType != 'nginx'){
|
||||
// mod_rewrite check ------------------------------------------------------------
|
||||
$modRewriteCheck = false;
|
||||
$modRewriteVersion = 'disabled';
|
||||
if(function_exists('apache_get_modules')){
|
||||
if(in_array('mod_rewrite',apache_get_modules())){
|
||||
$modRewriteCheck = true;
|
||||
$modRewriteVersion = 'enabled';
|
||||
}
|
||||
}else{
|
||||
// e.g. Nginx server
|
||||
$modRewriteVersion = '???';
|
||||
}
|
||||
|
||||
$checkRequirements['mod_rewrite'] = [
|
||||
'label' => 'mod_rewrite',
|
||||
'required' => 'enabled',
|
||||
'version' => $modRewriteVersion,
|
||||
'check' => $modRewriteCheck
|
||||
];
|
||||
|
||||
// mod_headers check ------------------------------------------------------------
|
||||
$modHeadersCheck = false;
|
||||
$modHeadersVersion = 'disabled';
|
||||
if(function_exists('apache_get_modules')){
|
||||
if(in_array('mod_headers',apache_get_modules())){
|
||||
$modHeadersCheck = true;
|
||||
$modHeadersVersion = 'enabled';
|
||||
}
|
||||
}else{
|
||||
// e.g. Nginx server
|
||||
$modHeadersVersion = '???';
|
||||
}
|
||||
|
||||
$checkRequirements['mod_headers'] = [
|
||||
'label' => 'mod_headers',
|
||||
'required' => 'enabled',
|
||||
'version' => $modHeadersVersion,
|
||||
'check' => $modHeadersCheck
|
||||
];
|
||||
}
|
||||
|
||||
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 = '???';
|
||||
// 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....
|
||||
$dbVersion = $db->version();
|
||||
if(strpos('maria', $dbVersion) !== 1){
|
||||
$dbTempVersion = explode('-', $dbVersion);
|
||||
if(count($dbTempVersion) > 2){
|
||||
$dbVersion = $dbTempVersion[1];
|
||||
}else{
|
||||
$dbVersion = $dbTempVersion[0];
|
||||
}
|
||||
}
|
||||
|
||||
$dbConfig = [
|
||||
'version' => [
|
||||
'label' => 'DB version',
|
||||
'required' => 'v.' . $f3->get('REQUIREMENTS.MYSQL.VERSION'),
|
||||
'version' => 'v.' . $dbVersion,
|
||||
'check' => version_compare($dbVersion, $f3->get('REQUIREMENTS.MYSQL.VERSION'), '>=' )
|
||||
]
|
||||
];
|
||||
|
||||
// get specific MySQL config Value
|
||||
$getDBConfigValue = function($db, $param){
|
||||
$result = $db->exec('SELECT @@' . $param);
|
||||
return !empty($result)? reset(reset($result)) : '???';
|
||||
};
|
||||
|
||||
$mySQLConfigParams = $f3->get('REQUIREMENTS.MYSQL.OPTIONS');
|
||||
foreach($mySQLConfigParams as $param => $requiredValue){
|
||||
$value = $getDBConfigValue($db, $param);
|
||||
$dbConfig[] = [
|
||||
'label' => $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){
|
||||
foreach($this->databases[$dbKey]['models'] as $modelClass){
|
||||
$checkTables[] = call_user_func($modelClass . '::setup');
|
||||
}
|
||||
}
|
||||
return $checkTables;
|
||||
}
|
||||
}
|
||||
@@ -51,15 +51,17 @@ class Database extends \Prefab {
|
||||
){
|
||||
$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;');
|
||||
// disable innoDB schema (relevant vor MySql 5.5)
|
||||
// not necessary for MySql > v.5.6
|
||||
// $db->exec('SET GLOBAL innodb_stats_on_metadata = OFF;');
|
||||
|
||||
// store DB object
|
||||
$f3->set($dbHiveKey, $db);
|
||||
// store DB object
|
||||
$f3->set($dbHiveKey, $db);
|
||||
}
|
||||
|
||||
return $db;
|
||||
}else{
|
||||
@@ -104,6 +106,8 @@ class Database extends \Prefab {
|
||||
*/
|
||||
protected function connect($dns, $name, $user, $password){
|
||||
|
||||
$db = null;
|
||||
|
||||
try {
|
||||
$db = new SQL(
|
||||
$dns . $name,
|
||||
@@ -115,6 +119,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' => ''
|
||||
],
|
||||
'sharing' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => 0
|
||||
],
|
||||
'allianceCharacters' => [
|
||||
'has-many' => ['Model\CharacterModel', 'allianceId']
|
||||
],
|
||||
|
||||
@@ -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,24 +8,59 @@
|
||||
|
||||
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' => self::DT_JSON
|
||||
],
|
||||
'type' => [
|
||||
'type' => self::DT_JSON
|
||||
'type' => Schema::DT_VARCHAR128,
|
||||
'nullable' => false,
|
||||
'default' => ''
|
||||
]
|
||||
];
|
||||
|
||||
@@ -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' => ''
|
||||
],
|
||||
'sharing' => [
|
||||
'type' => Schema::DT_BOOL,
|
||||
'nullable' => false,
|
||||
'default' => 0
|
||||
],
|
||||
'corporationCharacters' => [
|
||||
'has-many' => ['Model\CharacterModel', 'corporationId']
|
||||
],
|
||||
|
||||
@@ -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,39 @@ 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,
|
||||
'unique' => true
|
||||
],
|
||||
'name' => [
|
||||
'type' => Schema::DT_VARCHAR256,
|
||||
'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']
|
||||
@@ -180,7 +212,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,96 @@
|
||||
; Main Config
|
||||
|
||||
[PATHFINDER]
|
||||
NAME = "PATHFINDER"
|
||||
NAME = PATHFINDER
|
||||
; installed version (used for CSS/JS cache busting)
|
||||
VERSION = "v0.0.16"
|
||||
VERSION = v0.0.17
|
||||
; 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"
|
||||
|
||||
[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)
|
||||
[PATHFINDER.VIEW]
|
||||
; Server side template
|
||||
; Main
|
||||
INDEX = templates/view/index.html
|
||||
SETUP = templates/view/setup.html
|
||||
LANDINGPAGE = templates/view/landingpage.html
|
||||
|
||||
; MAP =============================================================================================
|
||||
[PATHFINDER.MAP.PRIVATE]
|
||||
LIFETIME = 7
|
||||
LIFETIME = 7
|
||||
|
||||
[PATHFINDER.MAP.CORPORATION]
|
||||
LIFETIME = 99999
|
||||
LIFETIME = 99999
|
||||
|
||||
[PATHFINDER.MAP.ALLIANCE]
|
||||
LIFETIME = 99999
|
||||
; ======================================================================================================
|
||||
LIFETIME = 99999
|
||||
|
||||
; CACHE ===========================================================================================
|
||||
[PATHFINDER.CACHE]
|
||||
|
||||
; cache character log informations in seconds. This is ignored if ship/system switch was detected
|
||||
CHARACTER_LOG = 300
|
||||
|
||||
CHARACTER_LOG = 300
|
||||
; cache time for all system data within a constellation (this will never change) 30d
|
||||
CONSTELLATION_SYSTEMS = 2592000
|
||||
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
|
||||
|
||||
; ======================================================================================================
|
||||
; 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
|
||||
|
||||
31
app/requirements.ini
Normal file
@@ -0,0 +1,31 @@
|
||||
; 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.4
|
||||
|
||||
; "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.OPTIONS]
|
||||
STORAGE_ENGINE = InnoDB
|
||||
CHARACTER_SET_SERVER = utf8
|
||||
LOWER_CASE_TABLE_NAMES = 2
|
||||
FOREIGN_KEY_CHECKS = 1
|
||||
|
||||
|
||||
@@ -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 |
20
gulpfile.js
@@ -73,6 +73,7 @@ gulp.task('requirejs', ['jshint'], function() {
|
||||
* http://jshint.com/docs/options/
|
||||
*/
|
||||
gulp.task('jshint', function(){
|
||||
|
||||
return gulp.src([
|
||||
_src.JS_SRC,
|
||||
'!' + _src.JS_LIBS
|
||||
@@ -153,19 +154,8 @@ gulp.task('watch', function(tag) {
|
||||
_src.JS_SRC,
|
||||
'!' + _src.JS_LIBS,
|
||||
], ['jshint', 'copyBuildFiles']);
|
||||
|
||||
|
||||
});
|
||||
|
||||
/**
|
||||
* clear all backend (fat free framework) cache files
|
||||
*/
|
||||
gulp.task('clearCache', function() {
|
||||
'use strict';
|
||||
return gulp.src( _src.CACHE ).pipe( clean() );
|
||||
});
|
||||
|
||||
|
||||
/*******************************************/
|
||||
// Default Tasks
|
||||
|
||||
@@ -203,4 +193,12 @@ gulp.task('default', function(tag) {
|
||||
'copyBuildFiles',
|
||||
'watch'
|
||||
);
|
||||
});
|
||||
|
||||
/**
|
||||
* clear all backend (fat free framework) cache files
|
||||
*/
|
||||
gulp.task('clearCache', function() {
|
||||
'use strict';
|
||||
return gulp.src( _src.CACHE ).pipe( clean() );
|
||||
});
|
||||
@@ -8,6 +8,9 @@ $f3->config('app/config.ini');
|
||||
// load route config
|
||||
$f3->config('app/routes.ini');
|
||||
|
||||
// load environment config
|
||||
$f3->config('app/environment.ini');
|
||||
|
||||
// load pathfinder config
|
||||
$f3->config('app/pathfinder.ini');
|
||||
|
||||
|
||||
@@ -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/
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -22,8 +22,9 @@ define([
|
||||
'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)
|
||||
@@ -66,7 +67,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({
|
||||
@@ -444,7 +449,7 @@ define([
|
||||
};
|
||||
|
||||
/**
|
||||
* main init landing page
|
||||
* main init "landing" page
|
||||
*/
|
||||
$(function(){
|
||||
|
||||
@@ -454,6 +459,8 @@ define([
|
||||
// show log off message
|
||||
var isLogOut = location.search.split('logout')[1];
|
||||
if(isLogOut !== undefined){
|
||||
|
||||
console.log(location.search);
|
||||
// show logout dialog
|
||||
var options = {
|
||||
buttons: {
|
||||
|
||||
@@ -16,6 +16,9 @@ define([
|
||||
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* main init "map" page
|
||||
*/
|
||||
$(function(){
|
||||
// load page
|
||||
$('body').loadPageStructure();
|
||||
|
||||
@@ -612,7 +612,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)
|
||||
|
||||
@@ -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);
|
||||
6
js/lib/velocity.min.js
vendored
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<metadata></metadata>
|
||||
<defs>
|
||||
<font id="fontawesomeregular" horiz-adv-x="1536" >
|
||||
@@ -219,8 +219,8 @@
|
||||
<glyph unicode="" horiz-adv-x="1792" d="M640 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM256 640h384v256h-158q-13 0 -22 -9l-195 -195q-9 -9 -9 -22v-30zM1536 128q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM1792 1216v-1024q0 -15 -4 -26.5t-13.5 -18.5 t-16.5 -11.5t-23.5 -6t-22.5 -2t-25.5 0t-22.5 0.5q0 -106 -75 -181t-181 -75t-181 75t-75 181h-384q0 -106 -75 -181t-181 -75t-181 75t-75 181h-64q-3 0 -22.5 -0.5t-25.5 0t-22.5 2t-23.5 6t-16.5 11.5t-13.5 18.5t-4 26.5q0 26 19 45t45 19v320q0 8 -0.5 35t0 38 t2.5 34.5t6.5 37t14 30.5t22.5 30l198 198q19 19 50.5 32t58.5 13h160v192q0 26 19 45t45 19h1024q26 0 45 -19t19 -45z" />
|
||||
<glyph unicode="" d="M1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103q-111 0 -218 32q59 93 78 164q9 34 54 211q20 -39 73 -67.5t114 -28.5q121 0 216 68.5t147 188.5t52 270q0 114 -59.5 214t-172.5 163t-255 63q-105 0 -196 -29t-154.5 -77t-109 -110.5t-67 -129.5t-21.5 -134 q0 -104 40 -183t117 -111q30 -12 38 20q2 7 8 31t8 30q6 23 -11 43q-51 61 -51 151q0 151 104.5 259.5t273.5 108.5q151 0 235.5 -82t84.5 -213q0 -170 -68.5 -289t-175.5 -119q-61 0 -98 43.5t-23 104.5q8 35 26.5 93.5t30 103t11.5 75.5q0 50 -27 83t-77 33 q-62 0 -105 -57t-43 -142q0 -73 25 -122l-99 -418q-17 -70 -13 -177q-206 91 -333 281t-127 423q0 209 103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
|
||||
<glyph unicode="" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-725q85 122 108 210q9 34 53 209q21 -39 73.5 -67t112.5 -28q181 0 295.5 147.5t114.5 373.5q0 84 -35 162.5t-96.5 139t-152.5 97t-197 36.5q-104 0 -194.5 -28.5t-153 -76.5 t-107.5 -109.5t-66.5 -128t-21.5 -132.5q0 -102 39.5 -180t116.5 -110q13 -5 23.5 0t14.5 19q10 44 15 61q6 23 -11 42q-50 62 -50 150q0 150 103.5 256.5t270.5 106.5q149 0 232.5 -81t83.5 -210q0 -168 -67.5 -286t-173.5 -118q-60 0 -97 43.5t-23 103.5q8 34 26.5 92.5 t29.5 102t11 74.5q0 49 -26.5 81.5t-75.5 32.5q-61 0 -103.5 -56.5t-42.5 -139.5q0 -72 24 -121l-98 -414q-24 -100 -7 -254h-183q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960z" />
|
||||
<glyph unicode="" d="M829 318q0 -76 -58.5 -112.5t-139.5 -36.5q-41 0 -80.5 9.5t-75.5 28.5t-58 53t-22 78q0 46 25 80t65.5 51.5t82 25t84.5 7.5q20 0 31 -2q2 -1 23 -16.5t26 -19t23 -18t24.5 -22t19 -22.5t17 -26t9 -26.5t4.5 -31.5zM755 863q0 -60 -33 -99.5t-92 -39.5q-53 0 -93 42.5 t-57.5 96.5t-17.5 106q0 61 32 104t92 43q53 0 93.5 -45t58 -101t17.5 -107zM861 1120l88 64h-265q-85 0 -161 -32t-127.5 -98t-51.5 -153q0 -93 64.5 -154.5t158.5 -61.5q22 0 43 3q-13 -29 -13 -54q0 -44 40 -94q-175 -12 -257 -63q-47 -29 -75.5 -73t-28.5 -95 q0 -43 18.5 -77.5t48.5 -56.5t69 -37t77.5 -21t76.5 -6q60 0 120.5 15.5t113.5 46t86 82.5t33 117q0 49 -20 89.5t-49 66.5t-58 47.5t-49 44t-20 44.5t15.5 42.5t37.5 39.5t44 42t37.5 59.5t15.5 82.5q0 60 -22.5 99.5t-72.5 90.5h83zM1152 672h128v64h-128v128h-64v-128 h-128v-64h128v-160h64v160zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
|
||||
<glyph unicode="" horiz-adv-x="1664" d="M735 740q0 -36 32 -70.5t77.5 -68t90.5 -73.5t77 -104t32 -142q0 -90 -48 -173q-72 -122 -211 -179.5t-298 -57.5q-132 0 -246.5 41.5t-171.5 137.5q-37 60 -37 131q0 81 44.5 150t118.5 115q131 82 404 100q-32 42 -47.5 74t-15.5 73q0 36 21 85q-46 -4 -68 -4 q-148 0 -249.5 96.5t-101.5 244.5q0 82 36 159t99 131q77 66 182.5 98t217.5 32h418l-138 -88h-131q74 -63 112 -133t38 -160q0 -72 -24.5 -129.5t-59 -93t-69.5 -65t-59.5 -61.5t-24.5 -66zM589 836q38 0 78 16.5t66 43.5q53 57 53 159q0 58 -17 125t-48.5 129.5 t-84.5 103.5t-117 41q-42 0 -82.5 -19.5t-65.5 -52.5q-47 -59 -47 -160q0 -46 10 -97.5t31.5 -103t52 -92.5t75 -67t96.5 -26zM591 -37q58 0 111.5 13t99 39t73 73t27.5 109q0 25 -7 49t-14.5 42t-27 41.5t-29.5 35t-38.5 34.5t-36.5 29t-41.5 30t-36.5 26q-16 2 -48 2 q-53 0 -105 -7t-107.5 -25t-97 -46t-68.5 -74.5t-27 -105.5q0 -70 35 -123.5t91.5 -83t119 -44t127.5 -14.5zM1401 839h213v-108h-213v-219h-105v219h-212v108h212v217h105v-217z" />
|
||||
<glyph unicode="" d="M917 631q0 26 -6 64h-362v-132h217q-3 -24 -16.5 -50t-37.5 -53t-66.5 -44.5t-96.5 -17.5q-99 0 -169 71t-70 171t70 171t169 71q92 0 153 -59l104 101q-108 100 -257 100q-160 0 -272 -112.5t-112 -271.5t112 -271.5t272 -112.5q165 0 266.5 105t101.5 270zM1262 585 h109v110h-109v110h-110v-110h-110v-110h110v-110h110v110zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
|
||||
<glyph unicode="" horiz-adv-x="2304" d="M1437 623q0 -208 -87 -370.5t-248 -254t-369 -91.5q-149 0 -285 58t-234 156t-156 234t-58 285t58 285t156 234t234 156t285 58q286 0 491 -192l-199 -191q-117 113 -292 113q-123 0 -227.5 -62t-165.5 -168.5t-61 -232.5t61 -232.5t165.5 -168.5t227.5 -62 q83 0 152.5 23t114.5 57.5t78.5 78.5t49 83t21.5 74h-416v252h692q12 -63 12 -122zM2304 745v-210h-209v-209h-210v209h-209v210h209v209h210v-209h209z" />
|
||||
<glyph unicode="" horiz-adv-x="1920" d="M768 384h384v96h-128v448h-114l-148 -137l77 -80q42 37 55 57h2v-288h-128v-96zM1280 640q0 -70 -21 -142t-59.5 -134t-101.5 -101t-138 -39t-138 39t-101.5 101t-59.5 134t-21 142t21 142t59.5 134t101.5 101t138 39t138 -39t101.5 -101t59.5 -134t21 -142zM1792 384 v512q-106 0 -181 75t-75 181h-1152q0 -106 -75 -181t-181 -75v-512q106 0 181 -75t75 -181h1152q0 106 75 181t181 75zM1920 1216v-1152q0 -26 -19 -45t-45 -19h-1792q-26 0 -45 19t-19 45v1152q0 26 19 45t45 19h1792q26 0 45 -19t19 -45z" />
|
||||
<glyph unicode="" horiz-adv-x="1024" d="M1024 832q0 -26 -19 -45l-448 -448q-19 -19 -45 -19t-45 19l-448 448q-19 19 -19 45t19 45t45 19h896q26 0 45 -19t19 -45z" />
|
||||
<glyph unicode="" horiz-adv-x="1024" d="M1024 320q0 -26 -19 -45t-45 -19h-896q-26 0 -45 19t-19 45t19 45l448 448q19 19 45 19t45 -19l448 -448q19 -19 19 -45z" />
|
||||
@@ -362,7 +362,7 @@
|
||||
<glyph unicode="" d="M685 771q0 1 -126 222q-21 34 -52 34h-184q-18 0 -26 -11q-7 -12 1 -29l125 -216v-1l-196 -346q-9 -14 0 -28q8 -13 24 -13h185q31 0 50 36zM1309 1268q-7 12 -24 12h-187q-30 0 -49 -35l-411 -729q1 -2 262 -481q20 -35 52 -35h184q18 0 25 12q8 13 -1 28l-260 476v1 l409 723q8 16 0 28zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
|
||||
<glyph unicode="" horiz-adv-x="1792" d="M1280 640q0 37 -30 54l-512 320q-31 20 -65 2q-33 -18 -33 -56v-640q0 -38 33 -56q16 -8 31 -8q20 0 34 10l512 320q30 17 30 54zM1792 640q0 -96 -1 -150t-8.5 -136.5t-22.5 -147.5q-16 -73 -69 -123t-124 -58q-222 -25 -671 -25t-671 25q-71 8 -124.5 58t-69.5 123 q-14 65 -21.5 147.5t-8.5 136.5t-1 150t1 150t8.5 136.5t22.5 147.5q16 73 69 123t124 58q222 25 671 25t671 -25q71 -8 124.5 -58t69.5 -123q14 -65 21.5 -147.5t8.5 -136.5t1 -150z" />
|
||||
<glyph unicode="" horiz-adv-x="1792" d="M402 829l494 -305l-342 -285l-490 319zM1388 274v-108l-490 -293v-1l-1 1l-1 -1v1l-489 293v108l147 -96l342 284v2l1 -1l1 1v-2l343 -284zM554 1418l342 -285l-494 -304l-338 270zM1390 829l338 -271l-489 -319l-343 285zM1239 1418l489 -319l-338 -270l-494 304z" />
|
||||
<glyph unicode="" horiz-adv-x="1408" d="M928 135v-151l-707 -1v151zM1169 481v-701l-1 -35v-1h-1132l-35 1h-1v736h121v-618h928v618h120zM241 393l704 -65l-13 -150l-705 65zM309 709l683 -183l-39 -146l-683 183zM472 1058l609 -360l-77 -130l-609 360zM832 1389l398 -585l-124 -85l-399 584zM1285 1536 l121 -697l-149 -26l-121 697z" />
|
||||
<glyph unicode="" d="M1289 -96h-1118v480h-160v-640h1438v640h-160v-480zM347 428l33 157l783 -165l-33 -156zM450 802l67 146l725 -339l-67 -145zM651 1158l102 123l614 -513l-102 -123zM1048 1536l477 -641l-128 -96l-477 641zM330 65v159h800v-159h-800z" />
|
||||
<glyph unicode="" d="M1362 110v648h-135q20 -63 20 -131q0 -126 -64 -232.5t-174 -168.5t-240 -62q-197 0 -337 135.5t-140 327.5q0 68 20 131h-141v-648q0 -26 17.5 -43.5t43.5 -17.5h1069q25 0 43 17.5t18 43.5zM1078 643q0 124 -90.5 211.5t-218.5 87.5q-127 0 -217.5 -87.5t-90.5 -211.5 t90.5 -211.5t217.5 -87.5q128 0 218.5 87.5t90.5 211.5zM1362 1003v165q0 28 -20 48.5t-49 20.5h-174q-29 0 -49 -20.5t-20 -48.5v-165q0 -29 20 -49t49 -20h174q29 0 49 20t20 49zM1536 1211v-1142q0 -81 -58 -139t-139 -58h-1142q-81 0 -139 58t-58 139v1142q0 81 58 139 t139 58h1142q81 0 139 -58t58 -139z" />
|
||||
<glyph unicode="" d="M1248 1408q119 0 203.5 -84.5t84.5 -203.5v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960zM698 640q0 88 -62 150t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150zM1262 640q0 88 -62 150 t-150 62t-150 -62t-62 -150t62 -150t150 -62t150 62t62 150z" />
|
||||
<glyph unicode="" d="M768 914l201 -306h-402zM1133 384h94l-459 691l-459 -691h94l104 160h522zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
|
||||
@@ -410,7 +410,7 @@
|
||||
<glyph unicode="" horiz-adv-x="2048" d="M960 1536l960 -384v-128h-128q0 -26 -20.5 -45t-48.5 -19h-1526q-28 0 -48.5 19t-20.5 45h-128v128zM256 896h256v-768h128v768h256v-768h128v768h256v-768h128v768h256v-768h59q28 0 48.5 -19t20.5 -45v-64h-1664v64q0 26 20.5 45t48.5 19h59v768zM1851 -64 q28 0 48.5 -19t20.5 -45v-128h-1920v128q0 26 20.5 45t48.5 19h1782z" />
|
||||
<glyph unicode="" horiz-adv-x="2304" d="M1774 700l18 -316q4 -69 -82 -128t-235 -93.5t-323 -34.5t-323 34.5t-235 93.5t-82 128l18 316l574 -181q22 -7 48 -7t48 7zM2304 1024q0 -23 -22 -31l-1120 -352q-4 -1 -10 -1t-10 1l-652 206q-43 -34 -71 -111.5t-34 -178.5q63 -36 63 -109q0 -69 -58 -107l58 -433 q2 -14 -8 -25q-9 -11 -24 -11h-192q-15 0 -24 11q-10 11 -8 25l58 433q-58 38 -58 107q0 73 65 111q11 207 98 330l-333 104q-22 8 -22 31t22 31l1120 352q4 1 10 1t10 -1l1120 -352q22 -8 22 -31z" />
|
||||
<glyph unicode="" d="M859 579l13 -707q-62 11 -105 11q-41 0 -105 -11l13 707q-40 69 -168.5 295.5t-216.5 374.5t-181 287q58 -15 108 -15q43 0 111 15q63 -111 133.5 -229.5t167 -276.5t138.5 -227q37 61 109.5 177.5t117.5 190t105 176t107 189.5q54 -14 107 -14q56 0 114 14v0 q-28 -39 -60 -88.5t-49.5 -78.5t-56.5 -96t-49 -84q-146 -248 -353 -610z" />
|
||||
<glyph unicode="" horiz-adv-x="1280" d="M981 197q0 25 -7 49t-14.5 42t-27 41.5t-29.5 35t-38.5 34.5t-36.5 29t-41.5 30t-36.5 26q-16 2 -49 2q-53 0 -104.5 -7t-107 -25t-97 -46t-68.5 -74.5t-27 -105.5q0 -56 23.5 -102t61 -75.5t87 -50t100 -29t101.5 -8.5q58 0 111.5 13t99 39t73 73t27.5 109zM864 1055 q0 59 -17 125.5t-48 129t-84 103.5t-117 41q-42 0 -82.5 -19.5t-66.5 -52.5q-46 -59 -46 -160q0 -46 10 -97.5t31.5 -103t52 -92.5t75 -67t96.5 -26q37 0 77.5 16.5t65.5 43.5q53 56 53 159zM752 1536h417l-137 -88h-132q75 -63 113 -133t38 -160q0 -72 -24.5 -129.5 t-59.5 -93t-69.5 -65t-59 -61.5t-24.5 -66q0 -36 32 -70.5t77 -68t90.5 -73.5t77.5 -104t32 -142q0 -91 -49 -173q-71 -122 -209.5 -179.5t-298.5 -57.5q-132 0 -246.5 41.5t-172.5 137.5q-36 59 -36 131q0 81 44.5 150t118.5 115q131 82 404 100q-32 41 -47.5 73.5 t-15.5 73.5q0 40 21 85q-46 -4 -68 -4q-148 0 -249.5 96.5t-101.5 244.5q0 82 36 159t99 131q76 66 182 98t218 32z" />
|
||||
<glyph unicode="" d="M768 750h725q12 -67 12 -128q0 -217 -91 -387.5t-259.5 -266.5t-386.5 -96q-157 0 -299 60.5t-245 163.5t-163.5 245t-60.5 299t60.5 299t163.5 245t245 163.5t299 60.5q300 0 515 -201l-209 -201q-123 119 -306 119q-129 0 -238.5 -65t-173.5 -176.5t-64 -243.5 t64 -243.5t173.5 -176.5t238.5 -65q87 0 160 24t120 60t82 82t51.5 87t22.5 78h-436v264z" />
|
||||
<glyph unicode="" horiz-adv-x="1792" d="M1095 369q16 -16 0 -31q-62 -62 -199 -62t-199 62q-16 15 0 31q6 6 15 6t15 -6q48 -49 169 -49q120 0 169 49q6 6 15 6t15 -6zM788 550q0 -37 -26 -63t-63 -26t-63.5 26t-26.5 63q0 38 26.5 64t63.5 26t63 -26.5t26 -63.5zM1183 550q0 -37 -26.5 -63t-63.5 -26t-63 26 t-26 63t26 63.5t63 26.5t63.5 -26t26.5 -64zM1434 670q0 49 -35 84t-85 35t-86 -36q-130 90 -311 96l63 283l200 -45q0 -37 26 -63t63 -26t63.5 26.5t26.5 63.5t-26.5 63.5t-63.5 26.5q-54 0 -80 -50l-221 49q-19 5 -25 -16l-69 -312q-180 -7 -309 -97q-35 37 -87 37 q-50 0 -85 -35t-35 -84q0 -35 18.5 -64t49.5 -44q-6 -27 -6 -56q0 -142 140 -243t337 -101q198 0 338 101t140 243q0 32 -7 57q30 15 48 43.5t18 63.5zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191 t348 71t348 -71t286 -191t191 -286t71 -348z" />
|
||||
<glyph unicode="" d="M939 407q13 -13 0 -26q-53 -53 -171 -53t-171 53q-13 13 0 26q5 6 13 6t13 -6q42 -42 145 -42t145 42q5 6 13 6t13 -6zM676 563q0 -31 -23 -54t-54 -23t-54 23t-23 54q0 32 22.5 54.5t54.5 22.5t54.5 -22.5t22.5 -54.5zM1014 563q0 -31 -23 -54t-54 -23t-54 23t-23 54 q0 32 22.5 54.5t54.5 22.5t54.5 -22.5t22.5 -54.5zM1229 666q0 42 -30 72t-73 30q-42 0 -73 -31q-113 78 -267 82l54 243l171 -39q1 -32 23.5 -54t53.5 -22q32 0 54.5 22.5t22.5 54.5t-22.5 54.5t-54.5 22.5q-48 0 -69 -43l-189 42q-17 5 -21 -13l-60 -268q-154 -6 -265 -83 q-30 32 -74 32q-43 0 -73 -30t-30 -72q0 -30 16 -55t42 -38q-5 -25 -5 -48q0 -122 120 -208.5t289 -86.5q170 0 290 86.5t120 208.5q0 25 -6 49q25 13 40.5 37.5t15.5 54.5zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960 q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
|
||||
<glyph unicode="" d="M866 697l90 27v62q0 79 -58 135t-138 56t-138 -55.5t-58 -134.5v-283q0 -20 -14 -33.5t-33 -13.5t-32.5 13.5t-13.5 33.5v120h-151v-122q0 -82 57.5 -139t139.5 -57q81 0 138.5 56.5t57.5 136.5v280q0 19 13.5 33t33.5 14q19 0 32.5 -14t13.5 -33v-54zM1199 502v122h-150 v-126q0 -20 -13.5 -33.5t-33.5 -13.5q-19 0 -32.5 14t-13.5 33v123l-90 -26l-60 28v-123q0 -80 58 -137t139 -57t138.5 57t57.5 139zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103 t385.5 -103t279.5 -279.5t103 -385.5z" />
|
||||
@@ -454,7 +454,7 @@
|
||||
<glyph unicode="" horiz-adv-x="1792" d="M216 367l603 -402v359l-334 223zM154 511l193 129l-193 129v-258zM973 -35l603 402l-269 180l-334 -223v-359zM896 458l272 182l-272 182l-272 -182zM485 733l334 223v359l-603 -402zM1445 640l193 -129v258zM1307 733l269 180l-603 402v-359zM1792 913v-546 q0 -41 -34 -64l-819 -546q-21 -13 -43 -13t-43 13l-819 546q-34 23 -34 64v546q0 41 34 64l819 546q21 13 43 13t43 -13l819 -546q34 -23 34 -64z" />
|
||||
<glyph unicode="" horiz-adv-x="2048" d="M1800 764q111 -46 179.5 -145.5t68.5 -221.5q0 -164 -118 -280.5t-285 -116.5q-4 0 -11.5 0.5t-10.5 0.5h-1209h-1h-2h-5q-170 10 -288 125.5t-118 280.5q0 110 55 203t147 147q-12 39 -12 82q0 115 82 196t199 81q95 0 172 -58q75 154 222.5 248t326.5 94 q166 0 306 -80.5t221.5 -218.5t81.5 -301q0 -6 -0.5 -18t-0.5 -18zM468 498q0 -122 84 -193t208 -71q137 0 240 99q-16 20 -47.5 56.5t-43.5 50.5q-67 -65 -144 -65q-55 0 -93.5 33.5t-38.5 87.5q0 53 38.5 87t91.5 34q44 0 84.5 -21t73 -55t65 -75t69 -82t77 -75t97 -55 t121.5 -21q121 0 204.5 71.5t83.5 190.5q0 121 -84 192t-207 71q-143 0 -241 -97q14 -16 29.5 -34t34.5 -40t29 -34q66 64 142 64q52 0 92 -33t40 -84q0 -57 -37 -91.5t-94 -34.5q-43 0 -82.5 21t-72 55t-65.5 75t-69.5 82t-77.5 75t-96.5 55t-118.5 21q-122 0 -207 -70.5 t-85 -189.5z" />
|
||||
<glyph unicode="" horiz-adv-x="1792" d="M896 1536q182 0 348 -71t286 -191t191 -286t71 -348t-71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71zM896 1408q-190 0 -361 -90l194 -194q82 28 167 28t167 -28l194 194q-171 90 -361 90zM218 279l194 194 q-28 82 -28 167t28 167l-194 194q-90 -171 -90 -361t90 -361zM896 -128q190 0 361 90l-194 194q-82 -28 -167 -28t-167 28l-194 -194q171 -90 361 -90zM896 256q159 0 271.5 112.5t112.5 271.5t-112.5 271.5t-271.5 112.5t-271.5 -112.5t-112.5 -271.5t112.5 -271.5 t271.5 -112.5zM1380 473l194 -194q90 171 90 361t-90 361l-194 -194q28 -82 28 -167t-28 -167z" />
|
||||
<glyph unicode="" horiz-adv-x="1792" d="M1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348q0 222 101 414.5t276.5 317t390.5 155.5v-260q-221 -45 -366.5 -221t-145.5 -406q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5t136.5 204t51 248.5 q0 230 -145.5 406t-366.5 221v260q215 -31 390.5 -155.5t276.5 -317t101 -414.5z" />
|
||||
<glyph unicode="" horiz-adv-x="1792" d="M1760 640q0 -176 -68.5 -336t-184 -275.5t-275.5 -184t-336 -68.5t-336 68.5t-275.5 184t-184 275.5t-68.5 336q0 213 97 398.5t265 305.5t374 151v-228q-221 -45 -366.5 -221t-145.5 -406q0 -130 51 -248.5t136.5 -204t204 -136.5t248.5 -51t248.5 51t204 136.5 t136.5 204t51 248.5q0 230 -145.5 406t-366.5 221v228q206 -31 374 -151t265 -305.5t97 -398.5z" />
|
||||
<glyph unicode="" horiz-adv-x="1792" d="M19 662q8 217 116 406t305 318h5q0 -1 -1 -3q-8 -8 -28 -33.5t-52 -76.5t-60 -110.5t-44.5 -135.5t-14 -150.5t39 -157.5t108.5 -154q50 -50 102 -69.5t90.5 -11.5t69.5 23.5t47 32.5l16 16q39 51 53 116.5t6.5 122.5t-21 107t-26.5 80l-14 29q-10 25 -30.5 49.5t-43 41 t-43.5 29.5t-35 19l-13 6l104 115q39 -17 78 -52t59 -61l19 -27q1 48 -18.5 103.5t-40.5 87.5l-20 31l161 183l160 -181q-33 -46 -52.5 -102.5t-22.5 -90.5l-4 -33q22 37 61.5 72.5t67.5 52.5l28 17l103 -115q-44 -14 -85 -50t-60 -65l-19 -29q-31 -56 -48 -133.5t-7 -170 t57 -156.5q33 -45 77.5 -60.5t85 -5.5t76 26.5t57.5 33.5l21 16q60 53 96.5 115t48.5 121.5t10 121.5t-18 118t-37 107.5t-45.5 93t-45 72t-34.5 47.5l-13 17q-14 13 -7 13l10 -3q40 -29 62.5 -46t62 -50t64 -58t58.5 -65t55.5 -77t45.5 -88t38 -103t23.5 -117t10.5 -136 q3 -259 -108 -465t-312 -321t-456 -115q-185 0 -351 74t-283.5 198t-184 293t-60.5 353z" />
|
||||
<glyph unicode="" horiz-adv-x="1792" d="M874 -102v-66q-208 6 -385 109.5t-283 275.5l58 34q29 -49 73 -99l65 57q148 -168 368 -212l-17 -86q65 -12 121 -13zM276 428l-83 -28q22 -60 49 -112l-57 -33q-98 180 -98 385t98 385l57 -33q-30 -56 -49 -112l82 -28q-35 -100 -35 -212q0 -109 36 -212zM1528 251 l58 -34q-106 -172 -283 -275.5t-385 -109.5v66q56 1 121 13l-17 86q220 44 368 212l65 -57q44 50 73 99zM1377 805l-233 -80q14 -42 14 -85t-14 -85l232 -80q-31 -92 -98 -169l-185 162q-57 -67 -147 -85l48 -241q-52 -10 -98 -10t-98 10l48 241q-90 18 -147 85l-185 -162 q-67 77 -98 169l232 80q-14 42 -14 85t14 85l-233 80q33 93 99 169l185 -162q59 68 147 86l-48 240q44 10 98 10t98 -10l-48 -240q88 -18 147 -86l185 162q66 -76 99 -169zM874 1448v-66q-65 -2 -121 -13l17 -86q-220 -42 -368 -211l-65 56q-38 -42 -73 -98l-57 33 q106 172 282 275.5t385 109.5zM1705 640q0 -205 -98 -385l-57 33q27 52 49 112l-83 28q36 103 36 212q0 112 -35 212l82 28q-19 56 -49 112l57 33q98 -180 98 -385zM1585 1063l-57 -33q-35 56 -73 98l-65 -56q-148 169 -368 211l17 86q-56 11 -121 13v66q209 -6 385 -109.5 t282 -275.5zM1748 640q0 173 -67.5 331t-181.5 272t-272 181.5t-331 67.5t-331 -67.5t-272 -181.5t-181.5 -272t-67.5 -331t67.5 -331t181.5 -272t272 -181.5t331 -67.5t331 67.5t272 181.5t181.5 272t67.5 331zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71 t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
|
||||
<glyph unicode="" d="M582 228q0 -66 -93 -66q-107 0 -107 63q0 64 98 64q102 0 102 -61zM546 694q0 -85 -74 -85q-77 0 -77 84q0 90 77 90q36 0 55 -25.5t19 -63.5zM712 769v125q-78 -29 -135 -29q-50 29 -110 29q-86 0 -145 -57t-59 -143q0 -50 29.5 -102t73.5 -67v-3q-38 -17 -38 -85 q0 -53 41 -77v-3q-113 -37 -113 -139q0 -45 20 -78.5t54 -51t72 -25.5t81 -8q224 0 224 188q0 67 -48 99t-126 46q-27 5 -51.5 20.5t-24.5 39.5q0 44 49 52q77 15 122 70t45 134q0 24 -10 52q37 9 49 13zM771 350h137q-2 27 -2 82v387q0 46 2 69h-137q3 -23 3 -71v-392 q0 -50 -3 -75zM1280 366v121q-30 -21 -68 -21q-53 0 -53 82v225h52q9 0 26.5 -1t26.5 -1v117h-105q0 82 3 102h-140q4 -24 4 -55v-47h-60v-117q36 3 37 3q3 0 11 -0.5t12 -0.5v-2h-2v-217q0 -37 2.5 -64t11.5 -56.5t24.5 -48.5t43.5 -31t66 -12q64 0 108 24zM924 1072 q0 36 -24 63.5t-60 27.5t-60.5 -27t-24.5 -64q0 -36 25 -62.5t60 -26.5t59.5 27t24.5 62zM1536 1120v-960q0 -119 -84.5 -203.5t-203.5 -84.5h-960q-119 0 -203.5 84.5t-84.5 203.5v960q0 119 84.5 203.5t203.5 84.5h960q119 0 203.5 -84.5t84.5 -203.5z" />
|
||||
@@ -555,7 +555,7 @@
|
||||
<glyph unicode="" d="M1536 1536l-192 -448h192v-192h-274l-55 -128h329v-192h-411l-357 -832l-357 832h-411v192h329l-55 128h-274v192h192l-192 448h256l323 -768h378l323 768h256zM768 320l108 256h-216z" />
|
||||
<glyph unicode="" d="M1088 1536q185 0 316.5 -93.5t131.5 -226.5v-896q0 -130 -125.5 -222t-305.5 -97l213 -202q16 -15 8 -35t-30 -20h-1056q-22 0 -30 20t8 35l213 202q-180 5 -305.5 97t-125.5 222v896q0 133 131.5 226.5t316.5 93.5h640zM768 192q80 0 136 56t56 136t-56 136t-136 56 t-136 -56t-56 -136t56 -136t136 -56zM1344 768v512h-1152v-512h1152z" />
|
||||
<glyph unicode="" d="M1088 1536q185 0 316.5 -93.5t131.5 -226.5v-896q0 -130 -125.5 -222t-305.5 -97l213 -202q16 -15 8 -35t-30 -20h-1056q-22 0 -30 20t8 35l213 202q-180 5 -305.5 97t-125.5 222v896q0 133 131.5 226.5t316.5 93.5h640zM288 224q66 0 113 47t47 113t-47 113t-113 47 t-113 -47t-47 -113t47 -113t113 -47zM704 768v512h-544v-512h544zM1248 224q66 0 113 47t47 113t-47 113t-113 47t-113 -47t-47 -113t47 -113t113 -47zM1408 768v512h-576v-512h576z" />
|
||||
<glyph unicode="" horiz-adv-x="1792" d="M1792 204v-209h-642v209h134v926h-6l-314 -1135h-243l-310 1135h-8v-926h135v-209h-538v209h69q21 0 43 19.5t22 37.5v881q0 18 -22 40t-43 22h-69v209h672l221 -821h6l223 821h670v-209h-71q-19 0 -41 -22t-22 -40v-881q0 -18 21.5 -37.5t41.5 -19.5h71z" />
|
||||
<glyph unicode="" horiz-adv-x="1792" d="M597 1115v-1173q0 -25 -12.5 -42.5t-36.5 -17.5q-17 0 -33 8l-465 233q-21 10 -35.5 33.5t-14.5 46.5v1140q0 20 10 34t29 14q14 0 44 -15l511 -256q3 -3 3 -5zM661 1014l534 -866l-534 266v600zM1792 996v-1054q0 -25 -14 -40.5t-38 -15.5t-47 13l-441 220zM1789 1116 q0 -3 -256.5 -419.5t-300.5 -487.5l-390 634l324 527q17 28 52 28q14 0 26 -6l541 -270q4 -2 4 -6z" />
|
||||
<glyph unicode="" d="M809 532l266 499h-112l-157 -312q-24 -48 -44 -92l-42 92l-155 312h-120l263 -493v-324h101v318zM1536 1408v-1536h-1536v1536h1536z" />
|
||||
<glyph unicode="" horiz-adv-x="2296" d="M478 -139q-8 -16 -27 -34.5t-37 -25.5q-25 -9 -51.5 3.5t-28.5 31.5q-1 22 40 55t68 38q23 4 34 -21.5t2 -46.5zM1819 -139q7 -16 26 -34.5t38 -25.5q25 -9 51.5 3.5t27.5 31.5q2 22 -39.5 55t-68.5 38q-22 4 -33 -21.5t-2 -46.5zM1867 -30q13 -27 56.5 -59.5t77.5 -41.5 q45 -13 82 4.5t37 50.5q0 46 -67.5 100.5t-115.5 59.5q-40 5 -63.5 -37.5t-6.5 -76.5zM428 -30q-13 -27 -56 -59.5t-77 -41.5q-45 -13 -82 4.5t-37 50.5q0 46 67.5 100.5t115.5 59.5q40 5 63 -37.5t6 -76.5zM1158 1094h1q-41 0 -76 -15q27 -8 44 -30.5t17 -49.5 q0 -35 -27 -60t-65 -25q-52 0 -80 43q-5 -23 -5 -42q0 -74 56 -126.5t135 -52.5q80 0 136 52.5t56 126.5t-56 126.5t-136 52.5zM1462 1312q-99 109 -220.5 131.5t-245.5 -44.5q27 60 82.5 96.5t118 39.5t121.5 -17t99.5 -74.5t44.5 -131.5zM2212 73q8 -11 -11 -42 q7 -23 7 -40q1 -56 -44.5 -112.5t-109.5 -91.5t-118 -37q-48 -2 -92 21.5t-66 65.5q-687 -25 -1259 0q-23 -41 -66.5 -65t-92.5 -22q-86 3 -179.5 80.5t-92.5 160.5q2 22 7 40q-19 31 -11 42q6 10 31 1q14 22 41 51q-7 29 2 38q11 10 39 -4q29 20 59 34q0 29 13 37 q23 12 51 -16q35 5 61 -2q18 -4 38 -19v73q-11 0 -18 2q-53 10 -97 44.5t-55 87.5q-9 38 0 81q15 62 93 95q2 17 19 35.5t36 23.5t33 -7.5t19 -30.5h13q46 -5 60 -23q3 -3 5 -7q10 1 30.5 3.5t30.5 3.5q-15 11 -30 17q-23 40 -91 43q0 6 1 10q-62 2 -118.5 18.5t-84.5 47.5 q-32 36 -42.5 92t-2.5 112q16 126 90 179q23 16 52 4.5t32 -40.5q0 -1 1.5 -14t2.5 -21t3 -20t5.5 -19t8.5 -10q27 -14 76 -12q48 46 98 74q-40 4 -162 -14l47 46q61 58 163 111q145 73 282 86q-20 8 -41 15.5t-47 14t-42.5 10.5t-47.5 11t-43 10q595 126 904 -139 q98 -84 158 -222q85 -10 121 9h1q5 3 8.5 10t5.5 19t3 19.5t3 21.5l1 14q3 28 32 40t52 -5q73 -52 91 -178q7 -57 -3.5 -113t-42.5 -91q-28 -32 -83.5 -48.5t-115.5 -18.5v-10q-71 -2 -95 -43q-14 -5 -31 -17q11 -1 32 -3.5t30 -3.5q1 4 5 8q16 18 60 23h13q5 18 19 30t33 8 t36 -23t19 -36q79 -32 93 -95q9 -40 1 -81q-12 -53 -56 -88t-97 -44q-10 -2 -17 -2q0 -49 -1 -73q20 15 38 19q26 7 61 2q28 28 51 16q14 -9 14 -37q33 -16 59 -34q27 13 38 4q10 -10 2 -38q28 -30 41 -51q23 8 31 -1zM1937 1025q0 -29 -9 -54q82 -32 112 -132 q4 37 -9.5 98.5t-41.5 90.5q-20 19 -36 17t-16 -20zM1859 925q35 -42 47.5 -108.5t-0.5 -124.5q67 13 97 45q13 14 18 28q-3 64 -31 114.5t-79 66.5q-15 -15 -52 -21zM1822 921q-30 0 -44 1q42 -115 53 -239q21 0 43 3q16 68 1 135t-53 100zM258 839q30 100 112 132 q-9 25 -9 54q0 18 -16.5 20t-35.5 -17q-28 -29 -41.5 -90.5t-9.5 -98.5zM294 737q29 -31 97 -45q-13 58 -0.5 124.5t47.5 108.5v0q-37 6 -52 21q-51 -16 -78.5 -66t-31.5 -115q9 -17 18 -28zM471 683q14 124 73 235q-19 -4 -55 -18l-45 -19v1q-46 -89 -20 -196q25 -3 47 -3z M1434 644q8 -38 16.5 -108.5t11.5 -89.5q3 -18 9.5 -21.5t23.5 4.5q40 20 62 85.5t23 125.5q-24 2 -146 4zM1152 1285q-116 0 -199 -82.5t-83 -198.5q0 -117 83 -199.5t199 -82.5t199 82.5t83 199.5q0 116 -83 198.5t-199 82.5zM1380 646q-106 2 -211 0v1q-1 -27 2.5 -86 t13.5 -66q29 -14 93.5 -14.5t95.5 10.5q9 3 11 39t-0.5 69.5t-4.5 46.5zM1112 447q8 4 9.5 48t-0.5 88t-4 63v1q-212 -3 -214 -3q-4 -20 -7 -62t0 -83t14 -46q34 -15 101 -16t101 10zM718 636q-16 -59 4.5 -118.5t77.5 -84.5q15 -8 24 -5t12 21q3 16 8 90t10 103 q-69 -2 -136 -6zM591 510q3 -23 -34 -36q132 -141 271.5 -240t305.5 -154q172 49 310.5 146t293.5 250q-33 13 -30 34l3 9v1v-1q-17 2 -50 5.5t-48 4.5q-26 -90 -82 -132q-51 -38 -82 1q-5 6 -9 14q-7 13 -17 62q-2 -5 -5 -9t-7.5 -7t-8 -5.5t-9.5 -4l-10 -2.5t-12 -2 l-12 -1.5t-13.5 -1t-13.5 -0.5q-106 -9 -163 11q-4 -17 -10 -26.5t-21 -15t-23 -7t-36 -3.5q-2 0 -3 -0.5t-3 -0.5h-3q-179 -17 -203 40q-2 -63 -56 -54q-47 8 -91 54q-12 13 -20 26q-17 29 -26 65q-58 -6 -87 -10q1 -2 4 -10zM507 -118q3 14 3 30q-17 71 -51 130t-73 70 q-41 12 -101.5 -14.5t-104.5 -80t-39 -107.5q35 -53 100 -93t119 -42q51 -2 94 28t53 79zM510 53q23 -63 27 -119q195 113 392 174q-98 52 -180.5 120t-179.5 165q-6 -4 -29 -13q0 -2 -1 -5t-1 -4q31 -18 22 -37q-12 -23 -56 -34q-10 -13 -29 -24h-1q-2 -83 1 -150 q19 -34 35 -73zM579 -113q532 -21 1145 0q-254 147 -428 196q-76 -35 -156 -57q-8 -3 -16 0q-65 21 -129 49q-208 -60 -416 -188h-1v-1q1 0 1 1zM1763 -67q4 54 28 120q14 38 33 71l-1 -1q3 77 3 153q-15 8 -30 25q-42 9 -56 33q-9 20 22 38q-2 4 -2 9q-16 4 -28 12 q-204 -190 -383 -284q198 -59 414 -176zM2155 -90q5 54 -39 107.5t-104 80t-102 14.5q-38 -11 -72.5 -70.5t-51.5 -129.5q0 -16 3 -30q10 -49 53 -79t94 -28q54 2 119 42t100 93z" />
|
||||
<glyph unicode="" horiz-adv-x="2304" d="M1524 -25q0 -68 -48 -116t-116 -48t-116.5 48t-48.5 116t48.5 116.5t116.5 48.5t116 -48.5t48 -116.5zM775 -25q0 -68 -48.5 -116t-116.5 -48t-116 48t-48 116t48 116.5t116 48.5t116.5 -48.5t48.5 -116.5zM0 1469q57 -60 110.5 -104.5t121 -82t136 -63t166 -45.5 t200 -31.5t250 -18.5t304 -9.5t372.5 -2.5q139 0 244.5 -5t181 -16.5t124 -27.5t71 -39.5t24 -51.5t-19.5 -64t-56.5 -76.5t-89.5 -91t-116 -104.5t-139 -119q-185 -157 -286 -247q29 51 76.5 109t94 105.5t94.5 98.5t83 91.5t54 80.5t13 70t-45.5 55.5t-116.5 41t-204 23.5 t-304 5q-168 -2 -314 6t-256 23t-204.5 41t-159.5 51.5t-122.5 62.5t-91.5 66.5t-68 71.5t-50.5 69.5t-40 68t-36.5 59.5z" />
|
||||
@@ -600,11 +600,11 @@
|
||||
<glyph unicode="" horiz-adv-x="1792" d="M949 643q0 -26 -16.5 -45t-41.5 -19q-26 0 -45 16.5t-19 41.5q0 26 17 45t42 19t44 -16.5t19 -41.5zM964 585l350 581q-9 -8 -67.5 -62.5t-125.5 -116.5t-136.5 -127t-117 -110.5t-50.5 -51.5l-349 -580q7 7 67 62t126 116.5t136 127t117 111t50 50.5zM1611 640 q0 -201 -104 -371q-3 2 -17 11t-26.5 16.5t-16.5 7.5q-13 0 -13 -13q0 -10 59 -44q-74 -112 -184.5 -190.5t-241.5 -110.5l-16 67q-1 10 -15 10q-5 0 -8 -5.5t-2 -9.5l16 -68q-72 -15 -146 -15q-199 0 -372 105q1 2 13 20.5t21.5 33.5t9.5 19q0 13 -13 13q-6 0 -17 -14.5 t-22.5 -34.5t-13.5 -23q-113 75 -192 187.5t-110 244.5l69 15q10 3 10 15q0 5 -5.5 8t-10.5 2l-68 -15q-14 72 -14 139q0 206 109 379q2 -1 18.5 -12t30 -19t17.5 -8q13 0 13 12q0 6 -12.5 15.5t-32.5 21.5l-20 12q77 112 189 189t244 107l15 -67q2 -10 15 -10q5 0 8 5.5 t2 10.5l-15 66q71 13 134 13q204 0 379 -109q-39 -56 -39 -65q0 -13 12 -13q11 0 48 64q111 -75 187.5 -186t107.5 -241l-56 -12q-10 -2 -10 -16q0 -5 5.5 -8t9.5 -2l57 13q14 -72 14 -140zM1696 640q0 163 -63.5 311t-170.5 255t-255 170.5t-311 63.5t-311 -63.5 t-255 -170.5t-170.5 -255t-63.5 -311t63.5 -311t170.5 -255t255 -170.5t311 -63.5t311 63.5t255 170.5t170.5 255t63.5 311zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71t348 -71t286 -191 t191 -286t71 -348z" />
|
||||
<glyph unicode="" horiz-adv-x="1792" d="M893 1536q240 2 451 -120q232 -134 352 -372l-742 39q-160 9 -294 -74.5t-185 -229.5l-276 424q128 159 311 245.5t383 87.5zM146 1131l337 -663q72 -143 211 -217t293 -45l-230 -451q-212 33 -385 157.5t-272.5 316t-99.5 411.5q0 267 146 491zM1732 962 q58 -150 59.5 -310.5t-48.5 -306t-153 -272t-246 -209.5q-230 -133 -498 -119l405 623q88 131 82.5 290.5t-106.5 277.5zM896 942q125 0 213.5 -88.5t88.5 -213.5t-88.5 -213.5t-213.5 -88.5t-213.5 88.5t-88.5 213.5t88.5 213.5t213.5 88.5z" />
|
||||
<glyph unicode="" horiz-adv-x="1792" d="M903 -256q-283 0 -504.5 150.5t-329.5 398.5q-58 131 -67 301t26 332.5t111 312t179 242.5l-11 -281q11 14 68 15.5t70 -15.5q42 81 160.5 138t234.5 59q-54 -45 -119.5 -148.5t-58.5 -163.5q25 -8 62.5 -13.5t63 -7.5t68 -4t50.5 -3q15 -5 9.5 -45.5t-30.5 -75.5 q-5 -7 -16.5 -18.5t-56.5 -35.5t-101 -34l15 -189l-139 67q-18 -43 -7.5 -81.5t36 -66.5t65.5 -41.5t81 -6.5q51 9 98 34.5t83.5 45t73.5 17.5q61 -4 89.5 -33t19.5 -65q-1 -2 -2.5 -5.5t-8.5 -12.5t-18 -15.5t-31.5 -10.5t-46.5 -1q-60 -95 -144.5 -135.5t-209.5 -29.5 q74 -61 162.5 -82.5t168.5 -6t154.5 52t128 87.5t80.5 104q43 91 39 192.5t-37.5 188.5t-78.5 125q87 -38 137 -79.5t77 -112.5q15 170 -57.5 343t-209.5 284q265 -77 412 -279.5t151 -517.5q2 -127 -40.5 -255t-123.5 -238t-189 -196t-247.5 -135.5t-288.5 -49.5z" />
|
||||
<glyph unicode="" d="M768 -92q77 0 139.5 63t100.5 166t59 234.5t21 268.5t-21 268.5t-59 234.5t-100.5 166t-139.5 63t-139.5 -63t-100.5 -166t-59 -234.5t-21 -268.5t21 -268.5t59 -234.5t100.5 -166t139.5 -63zM768 -256q-184 0 -333 77t-240 203t-141 287t-50 329t50 329t141 287t240 203 t333 77q148 0 274 -50t214.5 -136t151.5 -201t92.5 -244t29.5 -265t-29.5 -265t-92.5 -244t-151.5 -201t-214.5 -136t-274 -50z" />
|
||||
<glyph unicode="" horiz-adv-x="1792" d="M716 -69q-143 35 -261.5 114t-197.5 191q-139 -300 -17 -398q26 -21 85 -24.5t127.5 9.5t141 41.5t122.5 66.5zM693 762h452q0 108 -61.5 169t-168.5 61q-103 0 -162.5 -62.5t-59.5 -167.5zM1724 1137h-34q26 102 22.5 170t-25 110t-63.5 57t-93.5 11t-115 -26.5 t-128.5 -56.5t-134 -79q129 -37 238.5 -113.5t185 -179t110 -231.5t15.5 -262h-1005q0 -60 10 -106t34 -85t69.5 -60t112.5 -21q87 0 142.5 44t72.5 122h540q-71 -230 -281.5 -377t-477.5 -147q-83 0 -159 15q-35 -40 -151 -94t-248 -78t-219 35q-78 60 -100 159t7 214 t88 242t143.5 248t173.5 226.5t177.5 183.5t156.5 112v24q-120 -37 -258.5 -137.5t-240.5 -207t-159 -195.5q4 106 34 201t80 169t118 135.5t147.5 100.5t168 65.5t180.5 29.5t185 -8q310 186 503 189h7q57 0 103 -18q80 -30 98 -132.5t-30 -248.5z" />
|
||||
<glyph unicode="" horiz-adv-x="1792" d="M1493 1308q-165 110 -359 110q-155 0 -293 -73t-240 -200q-75 -93 -119.5 -218t-48.5 -266v-42q4 -141 48.5 -266t119.5 -218q102 -127 240 -200t293 -73q194 0 359 110q-121 -108 -274.5 -168t-322.5 -60q-29 0 -43 1q-175 8 -333 82t-272 193t-181 281t-67 339 q0 182 71 348t191 286t286 191t348 71h3q168 -1 320.5 -60.5t273.5 -167.5zM1792 640q0 -192 -77 -362.5t-213 -296.5q-104 -63 -222 -63q-137 0 -255 84q154 56 253.5 233t99.5 405q0 227 -99 404t-253 234q119 83 254 83q119 0 226 -65q135 -125 210.5 -295t75.5 -361z " />
|
||||
<glyph unicode="" horiz-adv-x="1792" d="M1792 599q0 -56 -7 -104h-1151q0 -146 109.5 -244.5t257.5 -98.5q99 0 185.5 46.5t136.5 130.5h423q-56 -159 -170.5 -281t-267.5 -188.5t-321 -66.5q-187 0 -356 83q-228 -116 -394 -116q-237 0 -237 263q0 115 45 275q17 60 109 229q199 360 475 606 q-184 -79 -427 -354q63 274 283.5 449.5t501.5 175.5q30 0 45 -1q255 117 433 117q64 0 116 -13t94.5 -40.5t66.5 -76.5t24 -115q0 -116 -75 -286q101 -182 101 -390zM1722 1239q0 83 -53 132t-137 49q-108 0 -254 -70q121 -47 222.5 -131.5t170.5 -195.5q51 135 51 216z M128 2q0 -86 48.5 -132.5t134.5 -46.5q115 0 266 83q-122 72 -213.5 183t-137.5 245q-98 -205 -98 -332zM632 715h728q-5 142 -113 237t-251 95q-144 0 -251.5 -95t-112.5 -237z" />
|
||||
<glyph unicode="" horiz-adv-x="2048" d="M1792 288v960q0 13 -9.5 22.5t-22.5 9.5h-1600q-13 0 -22.5 -9.5t-9.5 -22.5v-960q0 -13 9.5 -22.5t22.5 -9.5h1600q13 0 22.5 9.5t9.5 22.5zM1920 1248v-960q0 -66 -47 -113t-113 -47h-736v-128h352q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-832q-14 0 -23 9t-9 23 v64q0 14 9 23t23 9h352v128h-736q-66 0 -113 47t-47 113v960q0 66 47 113t113 47h1600q66 0 113 -47t47 -113z" />
|
||||
<glyph unicode="" horiz-adv-x="1792" d="M138 1408h197q-70 -64 -126 -149q-36 -56 -59 -115t-30 -125.5t-8.5 -120t10.5 -132t21 -126t28 -136.5q4 -19 6 -28q51 -238 81 -329q57 -171 152 -275h-272q-48 0 -82 34t-34 82v1304q0 48 34 82t82 34zM1346 1408h308q48 0 82 -34t34 -82v-1304q0 -48 -34 -82t-82 -34 h-178q212 210 196 565l-469 -101q-2 -45 -12 -82t-31 -72t-59.5 -59.5t-93.5 -36.5q-123 -26 -199 40q-32 27 -53 61t-51.5 129t-64.5 258q-35 163 -45.5 263t-5.5 139t23 77q20 41 62.5 73t102.5 45q45 12 83.5 6.5t67 -17t54 -35t43 -48t34.5 -56.5l468 100 q-68 175 -180 287z" />
|
||||
<glyph unicode="" horiz-adv-x="2304" d="M1391 390v0l-1 1q-15 18 -34.5 37.5t-62.5 57.5t-93.5 62t-95.5 24q-48 0 -83 -21.5t-51 -54t-23 -59t-7 -47.5v0v0q0 -21 7 -48t23 -59t51 -53.5t83 -21.5q45 0 95.5 24t94 62.5t62 57t34.5 37.5zM2103 390q0 21 -7 47.5t-23 59t-51 54t-83 21.5q-45 0 -95.5 -24 t-94 -62.5t-62 -57t-34.5 -37.5l-1 -1v0v0l1 -1q15 -18 34.5 -37.5t62.5 -57.5t93.5 -62t95.5 -24q48 0 83 21.5t51 53.5t23 59t7 48zM2304 393q0 -69 -24 -137.5t-68 -126t-116 -93.5t-159 -36q-68 0 -134 24t-113.5 58.5t-84.5 69.5t-59.5 59t-25.5 24t-22.5 -24 t-54.5 -58.5t-81.5 -69.5t-115 -59t-143.5 -24q-65 0 -123.5 22.5t-96.5 54t-66.5 66.5t-41 59.5t-12.5 32.5q0 -8 -8.5 -26.5t-25 -45.5t-47 -55t-69 -52.5t-96.5 -40t-125 -15.5q-71 0 -130 15.5t-98.5 39.5t-70.5 56.5t-48 63.5t-27.5 63.5t-14 54t-3.5 36.5h217 q0 -55 49 -107.5t126 -52.5q79 0 134.5 67t55.5 148q0 80 -52 136.5t-138 56.5q-5 0 -13 -0.5t-31 -5t-43 -12t-42 -24.5t-34 -40h-195l102 583h602v-174h-445q-27 -159 -41 -248q4 0 16.5 13t31.5 28.5t65 28.5t108 13t114 -20.5t82.5 -49.5t51.5 -58.5t31 -50t11 -20.5 t13 25t36.5 60.5t60.5 71.5t97 61t133 25t140.5 -25t115.5 -60.5t83.5 -71.5t56.5 -61t21 -25q2 0 22 25t56 60.5t83.5 71.5t115.5 61t140 25q92 0 164.5 -35t115.5 -93t65 -125t22 -137z" />
|
||||
<glyph unicode="" d="M1401 -11l-6 -6q-113 -114 -259 -175q-154 -64 -317 -64q-165 0 -317 64q-148 63 -259 175q-113 112 -175 258q-42 103 -54 189q-4 28 48 36q51 8 56 -20q1 -1 1 -4q18 -90 46 -159q50 -124 152 -226q98 -98 226 -152q132 -56 276 -56q143 0 276 56q128 55 225 152l6 6 q10 10 25 6q12 -3 33 -22q36 -37 17 -58zM929 604l-66 -66l63 -63q21 -21 -7 -49q-17 -17 -32 -17q-10 0 -19 10l-62 61l-66 -66q-5 -5 -15 -5q-15 0 -31 16l-2 2q-18 15 -18 29q0 7 8 17l66 65l-66 66q-16 16 14 45q18 18 31 18q6 0 13 -5l65 -66l65 65q18 17 48 -13 q27 -27 11 -44zM1400 547q0 -118 -46 -228q-45 -105 -126 -186q-80 -80 -187 -126t-228 -46t-228 46t-187 126q-82 82 -125 186q-15 32 -15 40h-1q-9 27 43 44q50 16 60 -12q37 -99 97 -167h1v339v2q3 136 102 232q105 103 253 103q147 0 251 -103t104 -249 q0 -147 -104.5 -251t-250.5 -104q-58 0 -112 16q-28 11 -13 61q16 51 44 43l14 -3q14 -3 32.5 -6t30.5 -3q104 0 176 71.5t72 174.5q0 101 -72 171q-71 71 -175 71q-107 0 -178 -80q-64 -72 -64 -160v-413q110 -67 242 -67q96 0 185 36.5t156 103.5t103.5 155t36.5 183 q0 198 -141 339q-140 140 -339 140q-200 0 -340 -140q-53 -53 -77 -87l-2 -2q-8 -11 -13 -15.5t-21.5 -9.5t-38.5 3q-21 5 -36.5 16.5t-15.5 26.5v680q0 15 10.5 26.5t27.5 11.5h877q30 0 30 -55t-30 -55h-811v-483h1q40 42 102 84t108 61q109 46 231 46q121 0 228 -46 t187 -126q81 -81 126 -186q46 -112 46 -229zM1369 1128q9 -8 9 -18t-5.5 -18t-16.5 -21q-26 -26 -39 -26q-9 0 -16 7q-106 91 -207 133q-128 56 -276 56q-133 0 -262 -49q-27 -10 -45 37q-9 25 -8 38q3 16 16 20q130 57 299 57q164 0 316 -64q137 -58 235 -152z" />
|
||||
<glyph unicode="" horiz-adv-x="1792" d="M1551 60q15 6 26 3t11 -17.5t-15 -33.5q-13 -16 -44 -43.5t-95.5 -68t-141 -74t-188 -58t-229.5 -24.5q-119 0 -238 31t-209 76.5t-172.5 104t-132.5 105t-84 87.5q-8 9 -10 16.5t1 12t8 7t11.5 2t11.5 -4.5q192 -117 300 -166q389 -176 799 -90q190 40 391 135z M1758 175q11 -16 2.5 -69.5t-28.5 -102.5q-34 -83 -85 -124q-17 -14 -26 -9t0 24q21 45 44.5 121.5t6.5 98.5q-5 7 -15.5 11.5t-27 6t-29.5 2.5t-35 0t-31.5 -2t-31 -3t-22.5 -2q-6 -1 -13 -1.5t-11 -1t-8.5 -1t-7 -0.5h-5.5h-4.5t-3 0.5t-2 1.5l-1.5 3q-6 16 47 40t103 30 q46 7 108 1t76 -24zM1364 618q0 -31 13.5 -64t32 -58t37.5 -46t33 -32l13 -11l-227 -224q-40 37 -79 75.5t-58 58.5l-19 20q-11 11 -25 33q-38 -59 -97.5 -102.5t-127.5 -63.5t-140 -23t-137.5 21t-117.5 65.5t-83 113t-31 162.5q0 84 28 154t72 116.5t106.5 83t122.5 57 t130 34.5t119.5 18.5t99.5 6.5v127q0 65 -21 97q-34 53 -121 53q-6 0 -16.5 -1t-40.5 -12t-56 -29.5t-56 -59.5t-48 -96l-294 27q0 60 22 119t67 113t108 95t151.5 65.5t190.5 24.5q100 0 181 -25t129.5 -61.5t81 -83t45 -86t12.5 -73.5v-589zM692 597q0 -86 70 -133 q66 -44 139 -22q84 25 114 123q14 45 14 101v162q-59 -2 -111 -12t-106.5 -33.5t-87 -71t-32.5 -114.5z" />
|
||||
<glyph unicode="" horiz-adv-x="1792" d="M1536 1280q52 0 90 -38t38 -90v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h128zM1152 1376v-288q0 -14 9 -23t23 -9 h64q14 0 23 9t9 23v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM384 1376v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23zM1536 -128v1024h-1408v-1024h1408zM896 448h224q14 0 23 -9t9 -23v-64q0 -14 -9 -23t-23 -9h-224 v-224q0 -14 -9 -23t-23 -9h-64q-14 0 -23 9t-9 23v224h-224q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h224v224q0 14 9 23t23 9h64q14 0 23 -9t9 -23v-224z" />
|
||||
<glyph unicode="" horiz-adv-x="1792" d="M1152 416v-64q0 -14 -9 -23t-23 -9h-576q-14 0 -23 9t-9 23v64q0 14 9 23t23 9h576q14 0 23 -9t9 -23zM128 -128h1408v1024h-1408v-1024zM512 1088v288q0 14 -9 23t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1280 1088v288q0 14 -9 23 t-23 9h-64q-14 0 -23 -9t-9 -23v-288q0 -14 9 -23t23 -9h64q14 0 23 9t9 23zM1664 1152v-1280q0 -52 -38 -90t-90 -38h-1408q-52 0 -90 38t-38 90v1280q0 52 38 90t90 38h128v96q0 66 47 113t113 47h64q66 0 113 -47t47 -113v-96h384v96q0 66 47 113t113 47h64q66 0 113 -47 t47 -113v-96h128q52 0 90 -38t38 -90z" />
|
||||
@@ -621,20 +621,35 @@
|
||||
<glyph unicode="" horiz-adv-x="1792" d="M1709 1018q-10 -236 -332 -651q-333 -431 -562 -431q-142 0 -240 263q-44 160 -132 482q-72 262 -157 262q-18 0 -127 -76l-77 98q24 21 108 96.5t130 115.5q156 138 241 146q95 9 153 -55.5t81 -203.5q44 -287 66 -373q55 -249 120 -249q51 0 154 161q101 161 109 246 q13 139 -109 139q-57 0 -121 -26q120 393 459 382q251 -8 236 -326z" />
|
||||
<glyph unicode="" d="M0 1408h1536v-1536h-1536v1536zM1085 293l-221 631l221 297h-634l221 -297l-221 -631l317 -304z" />
|
||||
<glyph unicode="" d="M0 1408h1536v-1536h-1536v1536zM908 1088l-12 -33l75 -83l-31 -114l25 -25l107 57l107 -57l25 25l-31 114l75 83l-12 33h-95l-53 96h-32l-53 -96h-95zM641 925q32 0 44.5 -16t11.5 -63l174 21q0 55 -17.5 92.5t-50.5 56t-69 25.5t-85 7q-133 0 -199 -57.5t-66 -182.5v-72 h-96v-128h76q20 0 20 -8v-382q0 -14 -5 -20t-18 -7l-73 -7v-88h448v86l-149 14q-6 1 -8.5 1.5t-3.5 2.5t-0.5 4t1 7t0.5 10v387h191l38 128h-231q-6 0 -2 6t4 9v80q0 27 1.5 40.5t7.5 28t19.5 20t36.5 5.5zM1248 96v86l-54 9q-7 1 -9.5 2.5t-2.5 3t1 7.5t1 12v520h-275 l-23 -101l83 -22q23 -7 23 -27v-370q0 -14 -6 -18.5t-20 -6.5l-70 -9v-86h352z" />
|
||||
<glyph unicode="" horiz-adv-x="1792" />
|
||||
<glyph unicode="" horiz-adv-x="1792" />
|
||||
<glyph unicode="" horiz-adv-x="1792" />
|
||||
<glyph unicode="" horiz-adv-x="1792" />
|
||||
<glyph unicode="" horiz-adv-x="1792" />
|
||||
<glyph unicode="" horiz-adv-x="1792" />
|
||||
<glyph unicode="" horiz-adv-x="1792" />
|
||||
<glyph unicode="" horiz-adv-x="1792" />
|
||||
<glyph unicode="" horiz-adv-x="1792" />
|
||||
<glyph unicode="" horiz-adv-x="1792" />
|
||||
<glyph unicode="" horiz-adv-x="1792" />
|
||||
<glyph unicode="" horiz-adv-x="1792" />
|
||||
<glyph unicode="" horiz-adv-x="1792" />
|
||||
<glyph unicode="" horiz-adv-x="1792" />
|
||||
<glyph unicode="" horiz-adv-x="1792" d="M1792 690q0 -58 -29.5 -105.5t-79.5 -72.5q12 -46 12 -96q0 -155 -106.5 -287t-290.5 -208.5t-400 -76.5t-399.5 76.5t-290 208.5t-106.5 287q0 47 11 94q-51 25 -82 73.5t-31 106.5q0 82 58 140.5t141 58.5q85 0 145 -63q218 152 515 162l116 521q3 13 15 21t26 5 l369 -81q18 37 54 59.5t79 22.5q62 0 106 -43.5t44 -105.5t-44 -106t-106 -44t-105.5 43.5t-43.5 105.5l-334 74l-104 -472q300 -9 519 -160q58 61 143 61q83 0 141 -58.5t58 -140.5zM418 491q0 -62 43.5 -106t105.5 -44t106 44t44 106t-44 105.5t-106 43.5q-61 0 -105 -44 t-44 -105zM1228 136q11 11 11 26t-11 26q-10 10 -25 10t-26 -10q-41 -42 -121 -62t-160 -20t-160 20t-121 62q-11 10 -26 10t-25 -10q-11 -10 -11 -25.5t11 -26.5q43 -43 118.5 -68t122.5 -29.5t91 -4.5t91 4.5t122.5 29.5t118.5 68zM1225 341q62 0 105.5 44t43.5 106 q0 61 -44 105t-105 44q-62 0 -106 -43.5t-44 -105.5t44 -106t106 -44z" />
|
||||
<glyph unicode="" horiz-adv-x="1792" d="M69 741h1q16 126 58.5 241.5t115 217t167.5 176t223.5 117.5t276.5 43q231 0 414 -105.5t294 -303.5q104 -187 104 -442v-188h-1125q1 -111 53.5 -192.5t136.5 -122.5t189.5 -57t213 -3t208 46.5t173.5 84.5v-377q-92 -55 -229.5 -92t-312.5 -38t-316 53 q-189 73 -311.5 249t-124.5 372q-3 242 111 412t325 268q-48 -60 -78 -125.5t-46 -159.5h635q8 77 -8 140t-47 101.5t-70.5 66.5t-80.5 41t-75 20.5t-56 8.5l-22 1q-135 -5 -259.5 -44.5t-223.5 -104.5t-176 -140.5t-138 -163.5z" />
|
||||
<glyph unicode="" horiz-adv-x="2304" d="M0 32v608h2304v-608q0 -66 -47 -113t-113 -47h-1984q-66 0 -113 47t-47 113zM640 256v-128h384v128h-384zM256 256v-128h256v128h-256zM2144 1408q66 0 113 -47t47 -113v-224h-2304v224q0 66 47 113t113 47h1984z" />
|
||||
<glyph unicode="" horiz-adv-x="1792" d="M1549 857q55 0 85.5 -28.5t30.5 -83.5t-34 -82t-91 -27h-136v-177h-25v398h170zM1710 267l-4 -11l-5 -10q-113 -230 -330.5 -366t-474.5 -136q-182 0 -348 71t-286 191t-191 286t-71 348t71 348t191 286t286 191t348 71q244 0 454.5 -124t329.5 -338l2 -4l8 -16 q-30 -15 -136.5 -68.5t-163.5 -84.5q-6 -3 -479 -268q384 -183 799 -366zM896 -234q250 0 462.5 132.5t322.5 357.5l-287 129q-72 -140 -206 -222t-292 -82q-151 0 -280 75t-204 204t-75 280t75 280t204 204t280 75t280 -73.5t204 -204.5l280 143q-116 208 -321 329 t-443 121q-119 0 -232.5 -31.5t-209 -87.5t-176.5 -137t-137 -176.5t-87.5 -209t-31.5 -232.5t31.5 -232.5t87.5 -209t137 -176.5t176.5 -137t209 -87.5t232.5 -31.5z" />
|
||||
<glyph unicode="" horiz-adv-x="1792" d="M1427 827l-614 386l92 151h855zM405 562l-184 116v858l1183 -743zM1424 697l147 -95v-858l-532 335zM1387 718l-500 -802h-855l356 571z" />
|
||||
<glyph unicode="" horiz-adv-x="1792" d="M640 528v224q0 16 -16 16h-96q-16 0 -16 -16v-224q0 -16 16 -16h96q16 0 16 16zM1152 528v224q0 16 -16 16h-96q-16 0 -16 -16v-224q0 -16 16 -16h96q16 0 16 16zM1664 496v-752h-640v320q0 80 -56 136t-136 56t-136 -56t-56 -136v-320h-640v752q0 16 16 16h96 q16 0 16 -16v-112h128v624q0 16 16 16h96q16 0 16 -16v-112h128v112q0 16 16 16h96q16 0 16 -16v-112h128v112q0 16 16 16h16v393q-32 19 -32 55q0 26 19 45t45 19t45 -19t19 -45q0 -36 -32 -55v-9h272q16 0 16 -16v-224q0 -16 -16 -16h-272v-128h16q16 0 16 -16v-112h128 v112q0 16 16 16h96q16 0 16 -16v-112h128v112q0 16 16 16h96q16 0 16 -16v-624h128v112q0 16 16 16h96q16 0 16 -16z" />
|
||||
<glyph unicode="" horiz-adv-x="2304" d="M2288 731q16 -8 16 -27t-16 -27l-320 -192q-8 -5 -16 -5q-9 0 -16 4q-16 10 -16 28v128h-858q37 -58 83 -165q16 -37 24.5 -55t24 -49t27 -47t27 -34t31.5 -26t33 -8h96v96q0 14 9 23t23 9h320q14 0 23 -9t9 -23v-320q0 -14 -9 -23t-23 -9h-320q-14 0 -23 9t-9 23v96h-96 q-32 0 -61 10t-51 23.5t-45 40.5t-37 46t-33.5 57t-28.5 57.5t-28 60.5q-23 53 -37 81.5t-36 65t-44.5 53.5t-46.5 17h-360q-22 -84 -91 -138t-157 -54q-106 0 -181 75t-75 181t75 181t181 75q88 0 157 -54t91 -138h104q24 0 46.5 17t44.5 53.5t36 65t37 81.5q19 41 28 60.5 t28.5 57.5t33.5 57t37 46t45 40.5t51 23.5t61 10h107q21 57 70 92.5t111 35.5q80 0 136 -56t56 -136t-56 -136t-136 -56q-62 0 -111 35.5t-70 92.5h-107q-17 0 -33 -8t-31.5 -26t-27 -34t-27 -47t-24 -49t-24.5 -55q-46 -107 -83 -165h1114v128q0 18 16 28t32 -1z" />
|
||||
<glyph unicode="" horiz-adv-x="1792" d="M1150 774q0 -56 -39.5 -95t-95.5 -39h-253v269h253q56 0 95.5 -39.5t39.5 -95.5zM1329 774q0 130 -91.5 222t-222.5 92h-433v-896h180v269h253q130 0 222 91.5t92 221.5zM1792 640q0 -182 -71 -348t-191 -286t-286 -191t-348 -71t-348 71t-286 191t-191 286t-71 348 t71 348t191 286t286 191t348 71t348 -71t286 -191t191 -286t71 -348z" />
|
||||
<glyph unicode="" horiz-adv-x="2304" d="M1645 438q0 59 -34 106.5t-87 68.5q-7 -45 -23 -92q-7 -24 -27.5 -38t-44.5 -14q-12 0 -24 3q-31 10 -45 38.5t-4 58.5q23 71 23 143q0 123 -61 227.5t-166 165.5t-228 61q-134 0 -247 -73t-167 -194q108 -28 188 -106q22 -23 22 -55t-22 -54t-54 -22t-55 22 q-75 75 -180 75q-106 0 -181 -74.5t-75 -180.5t75 -180.5t181 -74.5h1046q79 0 134.5 55.5t55.5 133.5zM1798 438q0 -142 -100.5 -242t-242.5 -100h-1046q-169 0 -289 119.5t-120 288.5q0 153 100 267t249 136q62 184 221 298t354 114q235 0 408.5 -158.5t196.5 -389.5 q116 -25 192.5 -118.5t76.5 -214.5zM2048 438q0 -175 -97 -319q-23 -33 -64 -33q-24 0 -43 13q-26 17 -32 48.5t12 57.5q71 104 71 233t-71 233q-18 26 -12 57t32 49t57.5 11.5t49.5 -32.5q97 -142 97 -318zM2304 438q0 -244 -134 -443q-23 -34 -64 -34q-23 0 -42 13 q-26 18 -32.5 49t11.5 57q108 164 108 358q0 195 -108 357q-18 26 -11.5 57.5t32.5 48.5q26 18 57 12t49 -33q134 -198 134 -442z" />
|
||||
<glyph unicode="" d="M1500 -13q0 -89 -63 -152.5t-153 -63.5t-153.5 63.5t-63.5 152.5q0 90 63.5 153.5t153.5 63.5t153 -63.5t63 -153.5zM1267 268q-115 -15 -192.5 -102.5t-77.5 -205.5q0 -74 33 -138q-146 -78 -379 -78q-109 0 -201 21t-153.5 54.5t-110.5 76.5t-76 85t-44.5 83 t-23.5 66.5t-6 39.5q0 19 4.5 42.5t18.5 56t36.5 58t64 43.5t94.5 18t94 -17.5t63 -41t35.5 -53t17.5 -49t4 -33.5q0 -34 -23 -81q28 -27 82 -42t93 -17l40 -1q115 0 190 51t75 133q0 26 -9 48.5t-31.5 44.5t-49.5 41t-74 44t-93.5 47.5t-119.5 56.5q-28 13 -43 20 q-116 55 -187 100t-122.5 102t-72 125.5t-20.5 162.5q0 78 20.5 150t66 137.5t112.5 114t166.5 77t221.5 28.5q120 0 220 -26t164.5 -67t109.5 -94t64 -105.5t19 -103.5q0 -46 -15 -82.5t-36.5 -58t-48.5 -36t-49 -19.5t-39 -5h-8h-32t-39 5t-44 14t-41 28t-37 46t-24 70.5 t-10 97.5q-15 16 -59 25.5t-81 10.5l-37 1q-68 0 -117.5 -31t-70.5 -70t-21 -76q0 -24 5 -43t24 -46t53 -51t97 -53.5t150 -58.5q76 -25 138.5 -53.5t109 -55.5t83 -59t60.5 -59.5t41 -62.5t26.5 -62t14.5 -63.5t6 -62t1 -62.5z" />
|
||||
<glyph unicode="" d="M704 352v576q0 14 -9 23t-23 9h-256q-14 0 -23 -9t-9 -23v-576q0 -14 9 -23t23 -9h256q14 0 23 9t9 23zM1152 352v576q0 14 -9 23t-23 9h-256q-14 0 -23 -9t-9 -23v-576q0 -14 9 -23t23 -9h256q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103 t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5t103 -385.5z" />
|
||||
<glyph unicode="" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM768 96q148 0 273 73t198 198t73 273t-73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273 t73 -273t198 -198t273 -73zM864 320q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-192zM480 320q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h192q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-192z" />
|
||||
<glyph unicode="" d="M1088 352v576q0 14 -9 23t-23 9h-576q-14 0 -23 -9t-9 -23v-576q0 -14 9 -23t23 -9h576q14 0 23 9t9 23zM1536 640q0 -209 -103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103t385.5 -103t279.5 -279.5 t103 -385.5z" />
|
||||
<glyph unicode="" d="M768 1408q209 0 385.5 -103t279.5 -279.5t103 -385.5t-103 -385.5t-279.5 -279.5t-385.5 -103t-385.5 103t-279.5 279.5t-103 385.5t103 385.5t279.5 279.5t385.5 103zM768 96q148 0 273 73t198 198t73 273t-73 273t-198 198t-273 73t-273 -73t-198 -198t-73 -273 t73 -273t198 -198t273 -73zM480 320q-14 0 -23 9t-9 23v576q0 14 9 23t23 9h576q14 0 23 -9t9 -23v-576q0 -14 -9 -23t-23 -9h-576z" />
|
||||
<glyph unicode="" horiz-adv-x="1792" d="M1757 128l35 -313q3 -28 -16 -50q-19 -21 -48 -21h-1664q-29 0 -48 21q-19 22 -16 50l35 313h1722zM1664 967l86 -775h-1708l86 775q3 24 21 40.5t43 16.5h256v-128q0 -53 37.5 -90.5t90.5 -37.5t90.5 37.5t37.5 90.5v128h384v-128q0 -53 37.5 -90.5t90.5 -37.5 t90.5 37.5t37.5 90.5v128h256q25 0 43 -16.5t21 -40.5zM1280 1152v-256q0 -26 -19 -45t-45 -19t-45 19t-19 45v256q0 106 -75 181t-181 75t-181 -75t-75 -181v-256q0 -26 -19 -45t-45 -19t-45 19t-19 45v256q0 159 112.5 271.5t271.5 112.5t271.5 -112.5t112.5 -271.5z" />
|
||||
<glyph unicode="" horiz-adv-x="2048" d="M1920 768q53 0 90.5 -37.5t37.5 -90.5t-37.5 -90.5t-90.5 -37.5h-15l-115 -662q-8 -46 -44 -76t-82 -30h-1280q-46 0 -82 30t-44 76l-115 662h-15q-53 0 -90.5 37.5t-37.5 90.5t37.5 90.5t90.5 37.5h1792zM485 -32q26 2 43.5 22.5t15.5 46.5l-32 416q-2 26 -22.5 43.5 t-46.5 15.5t-43.5 -22.5t-15.5 -46.5l32 -416q2 -25 20.5 -42t43.5 -17h5zM896 32v416q0 26 -19 45t-45 19t-45 -19t-19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45zM1280 32v416q0 26 -19 45t-45 19t-45 -19t-19 -45v-416q0 -26 19 -45t45 -19t45 19t19 45zM1632 27l32 416 q2 26 -15.5 46.5t-43.5 22.5t-46.5 -15.5t-22.5 -43.5l-32 -416q-2 -26 15.5 -46.5t43.5 -22.5h5q25 0 43.5 17t20.5 42zM476 1244l-93 -412h-132l101 441q19 88 89 143.5t160 55.5h167q0 26 19 45t45 19h384q26 0 45 -19t19 -45h167q90 0 160 -55.5t89 -143.5l101 -441 h-132l-93 412q-11 44 -45.5 72t-79.5 28h-167q0 -26 -19 -45t-45 -19h-384q-26 0 -45 19t-19 45h-167q-45 0 -79.5 -28t-45.5 -72z" />
|
||||
<glyph unicode="" horiz-adv-x="1792" d="M991 512l64 256h-254l-64 -256h254zM1759 1016l-56 -224q-7 -24 -31 -24h-327l-64 -256h311q15 0 25 -12q10 -14 6 -28l-56 -224q-5 -24 -31 -24h-327l-81 -328q-7 -24 -31 -24h-224q-16 0 -26 12q-9 12 -6 28l78 312h-254l-81 -328q-7 -24 -31 -24h-225q-15 0 -25 12 q-9 12 -6 28l78 312h-311q-15 0 -25 12q-9 12 -6 28l56 224q7 24 31 24h327l64 256h-311q-15 0 -25 12q-10 14 -6 28l56 224q5 24 31 24h327l81 328q7 24 32 24h224q15 0 25 -12q9 -12 6 -28l-78 -312h254l81 328q7 24 32 24h224q15 0 25 -12q9 -12 6 -28l-78 -312h311 q15 0 25 -12q9 -12 6 -28z" />
|
||||
<glyph unicode="" d="M841 483l148 -148l-149 -149zM840 1094l149 -149l-148 -148zM710 -130l464 464l-306 306l306 306l-464 464v-611l-255 255l-93 -93l320 -321l-320 -321l93 -93l255 255v-611zM1429 640q0 -209 -32 -365.5t-87.5 -257t-140.5 -162.5t-181.5 -86.5t-219.5 -24.5 t-219.5 24.5t-181.5 86.5t-140.5 162.5t-87.5 257t-32 365.5t32 365.5t87.5 257t140.5 162.5t181.5 86.5t219.5 24.5t219.5 -24.5t181.5 -86.5t140.5 -162.5t87.5 -257t32 -365.5z" />
|
||||
<glyph unicode="" horiz-adv-x="1024" d="M596 113l173 172l-173 172v-344zM596 823l173 172l-173 172v-344zM628 640l356 -356l-539 -540v711l-297 -296l-108 108l372 373l-372 373l108 108l297 -296v711l539 -540z" />
|
||||
<glyph unicode="" d="M1280 256q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM512 1024q0 52 -38 90t-90 38t-90 -38t-38 -90t38 -90t90 -38t90 38t38 90zM1536 256q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5t271.5 -112.5 t112.5 -271.5zM1440 1344q0 -20 -13 -38l-1056 -1408q-19 -26 -51 -26h-160q-26 0 -45 19t-19 45q0 20 13 38l1056 1408q19 26 51 26h160q26 0 45 -19t19 -45zM768 1024q0 -159 -112.5 -271.5t-271.5 -112.5t-271.5 112.5t-112.5 271.5t112.5 271.5t271.5 112.5 t271.5 -112.5t112.5 -271.5z" />
|
||||
<glyph unicode="" horiz-adv-x="1792" />
|
||||
<glyph unicode="" horiz-adv-x="1792" />
|
||||
<glyph unicode="" horiz-adv-x="1792" />
|
||||
<glyph unicode="" horiz-adv-x="1792" />
|
||||
<glyph unicode="" horiz-adv-x="1792" />
|
||||
<glyph unicode="" horiz-adv-x="1792" />
|
||||
<glyph unicode="" horiz-adv-x="1792" />
|
||||
<glyph unicode="" horiz-adv-x="1792" />
|
||||
<glyph unicode="" horiz-adv-x="1792" />
|
||||
<glyph unicode="" horiz-adv-x="1792" />
|
||||
</font>
|
||||
</defs></svg>
|
||||
|
Before Width: | Height: | Size: 348 KiB After Width: | Height: | Size: 357 KiB |
@@ -1,2 +0,0 @@
|
||||
var mainScriptPath=document.body.getAttribute("data-script"),jsBaseUrl=document.body.getAttribute("data-js-path");requirejs.config({baseUrl:"js",paths:{layout:"layout",config:"app/config",dialog:"app/ui/dialog",templates:"../../templates",img:"../../img",landingpage:"./app/landingpage",mappage:"./app/mappage",jquery:"lib/jquery-1.11.3.min",bootstrap:"lib/bootstrap.min",text:"lib/requirejs/text",mustache:"lib/mustache.min",velocity:"lib/velocity.min",velocityUI:"lib/velocity.ui.min",slidebars:"lib/slidebars",jsPlumb:"lib/dom.jsPlumb-1.7.6-min",farahey:"lib/farahey-0.5",customScrollbar:"lib/jquery.mCustomScrollbar.concat.min",datatables:"lib/datatables/jquery.dataTables.min",datatablesResponsive:"lib/datatables/extensions/responsive/dataTables.responsive",datatablesTableTools:"lib/datatables/extensions/tabletools/js/dataTables.tableTools",xEditable:"lib/bootstrap-editable.min",morris:"lib/morris.min",raphael:"lib/raphael-min",bootbox:"lib/bootbox.min",easyPieChart:"lib/jquery.easypiechart.min",dragToSelect:"lib/jquery.dragToSelect",hoverIntent:"lib/jquery.hoverIntent.minified",fullScreen:"lib/jquery.fullscreen.min",select2:"lib/select2.min",validator:"lib/validator.min",lazylinepainter:"lib/jquery.lazylinepainter-1.5.1.min",blueImpGallery:"lib/blueimp-gallery",blueImpGalleryHelper:"lib/blueimp-helper",blueImpGalleryBootstrap:"lib/bootstrap-image-gallery",bootstrapConfirmation:"lib/bootstrap-confirmation",bootstrapToggle:"lib/bootstrap2-toggle.min",easePack:"lib/EasePack.min",tweenLite:"lib/TweenLite.min",pnotify:"lib/pnotify/pnotify.core","pnotify.buttons":"lib/pnotify/pnotify.buttons","pnotify.confirm":"lib/pnotify/pnotify.confirm","pnotify.nonblock":"lib/pnotify/pnotify.nonblock","pnotify.desktop":"lib/pnotify/pnotify.desktop","pnotify.history":"lib/pnotify/pnotify.history","pnotify.callbacks":"lib/pnotify/pnotify.callbacks","pnotify.reference":"lib/pnotify/pnotify.reference"},shim:{bootstrap:{deps:["jquery"]},farahey:{deps:["jsPlumb"]},velocity:{deps:["jquery"]},velocityUI:{deps:["velocity"]},slidebars:{deps:["jquery"]},customScrollbar:{deps:["jquery"]},datatables:{deps:["jquery"]},datatablesBootstrap:{deps:["datatables"]},datatablesResponsive:{deps:["datatables"]},datatablesTableTools:{deps:["datatables"]},xEditable:{deps:["bootstrap"]},bootbox:{deps:["jquery","bootstrap"],exports:"bootbox"},morris:{deps:["jquery","raphael"],exports:"Morris"},pnotify:{deps:["jquery"]},easyPieChart:{deps:["jquery"]},dragToSelect:{deps:["jquery"]},hoverIntent:{deps:["jquery"]},fullScreen:{deps:["jquery"]},select2:{deps:["jquery"],exports:"Select2"},validator:{deps:["jquery","bootstrap"]},lazylinepainter:{deps:["jquery","bootstrap"]},blueImpGallery:{deps:["jquery"]},bootstrapConfirmation:{deps:["bootstrap"]},bootstrapToggle:{deps:["jquery"]}}});require.config({baseUrl:jsBaseUrl});requirejs([mainScriptPath]);
|
||||
//# sourceMappingURL=app.js.map
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"app.js.map","sources":["app.js.src.js"],"names":["mainScriptPath","document","body","getAttribute","jsBaseUrl","requirejs","config","baseUrl","paths","layout","dialog","templates","img","landingpage","mappage","jquery","bootstrap","text","mustache","velocity","velocityUI","slidebars","jsPlumb","farahey","customScrollbar","datatables","datatablesResponsive","datatablesTableTools","xEditable","morris","raphael","bootbox","easyPieChart","dragToSelect","hoverIntent","fullScreen","select2","validator","lazylinepainter","blueImpGallery","blueImpGalleryHelper","blueImpGalleryBootstrap","bootstrapConfirmation","bootstrapToggle","easePack","tweenLite","pnotify","pnotify.buttons","pnotify.confirm","pnotify.nonblock","pnotify.desktop","pnotify.history","pnotify.callbacks","pnotify.reference","shim","deps","datatablesBootstrap","exports","require"],"mappings":"AACA,GAAIA,gBAAiBC,SAASC,KAAKC,aAAa,eAI5CC,UAAYH,SAASC,KAAKC,aAAa,eAG3CE,WAAUC,QACNC,QAAS,KAETC,OACIC,OAAQ,SACRH,OAAQ,aACRI,OAAQ,gBACRC,UAAW,kBACXC,IAAK,YAGLC,YAAa,oBACbC,QAAS,gBAETC,OAAQ,wBACRC,UAAW,oBACXC,KAAM,qBACNC,SAAU,mBACVC,SAAU,mBACVC,WAAY,sBACZC,UAAW,gBACXC,QAAS,4BACTC,QAAS,kBACTC,gBAAiB,yCACjBC,WAAY,uCAEZC,qBAAsB,6DAEtBC,qBAAsB,gEACtBC,UAAW,6BACXC,OAAQ,iBACRC,QAAS,kBACTC,QAAS,kBACTC,aAAc,8BACdC,aAAc,0BACdC,YAAa,kCACbC,WAAY,4BACZC,QAAS,kBACTC,UAAW,oBACXC,gBAAiB,uCACjBC,eAAgB,sBAChBC,qBAAsB,qBACtBC,wBAAyB,8BACzBC,sBAAuB,6BACvBC,gBAAiB,4BAGjBC,SAAU,mBACVC,UAAW,oBAGXC,QAAS,2BACTC,kBAAmB,8BACnBC,kBAAmB,8BACnBC,mBAAoB,+BACpBC,kBAAmB,8BACnBC,kBAAmB,8BACnBC,oBAAqB,gCACrBC,oBAAqB,iCAGzBC,MACItC,WACIuC,MAAO,WAEXhC,SACIgC,MAAO,YAEXpC,UACIoC,MAAO,WAEXnC,YACImC,MAAO,aAEXlC,WACIkC,MAAO,WAEX/B,iBACI+B,MAAO,WAEX9B,YACI8B,MAAO,WAEXC,qBACID,MAAO,eAEX7B,sBACI6B,MAAO,eAEX5B,sBACI4B,MAAO,eAEX3B,WACI2B,MAAO,cAEXxB,SACIwB,MAAO,SAAU,aACjBE,QAAS,WAEb5B,QACI0B,MAAO,SAAU,WACjBE,QAAS,UAEbX,SACIS,MAAQ,WAEZvB,cACIuB,MAAQ,WAEZtB,cACIsB,MAAQ,WAEZrB,aACIqB,MAAQ,WAEZpB,YACIoB,MAAQ,WAEZnB,SACImB,MAAQ,UACRE,QAAS,WAEbpB,WACIkB,MAAQ,SAAU,cAEtBjB,iBACIiB,MAAQ,SAAU,cAEtBhB,gBACIgB,MAAQ,WAEZb,uBACIa,MAAQ,cAEZZ,iBACIY,MAAQ,aAQpBG,SAAQpD,QACJC,QAASH,WAIbC,YAAYL"}
|
||||