- new "logging" system for map/system/signature/connection changes, closed #271

- new map change log to Slack channel
- new "rally point" logging to Slack channel
- new "rally point" poke options (e.g. custom message), closed #295
- new log options for WebSocket installations
- added ship "mass" logging (backend only), #313
- added map logging to Slack, #326
- added "ESI error rate" limit detection
- added "Monolog" as new logging library (Composer dependency)
- added "Swiftmailer" as new eMail library (Composer dependency)
- added Support for Redis session hander (performance boost)
- improved character select panels (visible "online" status)
- improved "activity logging" (more DB columns added to check)
- improved eMail logging (HTML template support)
- improved "delete map" now become "inactive" for some days before delete
- improved character logout handling
- improved /setup page for DB bootstrap (new button for DB create if not exists)
- fixed broken ship tracking (ship name re-added)
- fixed broken ship tracking for multiple chars on different browser tabs
- fixed broken cursor coordinates, closed #518
- fixed null pointer "charactermodel.php->isActive():925" closed #529
- fixed broken "scroll offset", closed #533 closed #534
- Updated "validation" library JS v0.10.1 -> v0.11.9
- Updated ORM Mapper _Cortex_ v1.5.0-dev -> v1.5.0
- and many more....
This commit is contained in:
Exodus4D
2017-10-22 17:58:33 +02:00
parent d00e550972
commit a8edf39697
235 changed files with 10571 additions and 3515 deletions

View File

@@ -9,9 +9,11 @@
namespace Model;
use DB\SQL\Schema;
use Exception;
use Controller;
use DB;
use Lib\Logging;
use Exception\ValidationException;
use Exception\DatabaseException;
abstract class BasicModel extends \DB\Cortex {
@@ -19,7 +21,7 @@ abstract class BasicModel extends \DB\Cortex {
* Hive key with DB object
* @var string
*/
protected $db = 'DB_PF';
protected $db = 'DB_PF';
/**
* caching time of field schema - seconds
@@ -27,26 +29,20 @@ abstract class BasicModel extends \DB\Cortex {
* -> leave this at a higher value
* @var int
*/
protected $ttl = 120;
protected $ttl = 60;
/**
* caching for relational data
* @var int
*/
protected $rel_ttl = 0;
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
*/
protected $validate = [];
protected $addStaticFields = true;
/**
* enables check for $fieldChanges on update/insert
@@ -54,7 +50,7 @@ abstract class BasicModel extends \DB\Cortex {
* in $fieldConf config
* @var bool
*/
protected $enableActivityLogging = true;
protected $enableActivityLogging = true;
/**
* enables change for "active" column
@@ -62,40 +58,53 @@ abstract class BasicModel extends \DB\Cortex {
* -> $this->active = false; will NOT work (prevent abuse)!
* @var bool
*/
private $allowActiveChange = false;
private $allowActiveChange = false;
/**
* getData() cache key prefix
* -> do not change, otherwise cached data is lost
* @var string
*/
private $dataCacheKeyPrefix = 'DATACACHE';
private $dataCacheKeyPrefix = 'DATACACHE';
/**
* enables data export for this table
* -> can be overwritten in child models
* @var bool
*/
public static $enableDataExport = false;
public static $enableDataExport = false;
/**
* enables data import for this table
* -> can be overwritten in child models
* @var bool
*/
public static $enableDataImport = false;
public static $enableDataImport = false;
/**
* changed fields (columns) on update/insert
* -> e.g. for character "activity logging"
* @var array
*/
protected $fieldChanges = [];
protected $fieldChanges = [];
/**
* default TTL for getData(); cache
* collection for validation errors
* @var array
*/
const DEFAULT_CACHE_TTL = 120;
protected $validationError = [];
/**
* default caching time of field schema - seconds
*/
const DEFAULT_TTL = 86400;
/**
* default TTL for getData(); cache - seconds
*/
const DEFAULT_CACHE_TTL = 120;
const ERROR_INVALID_MODEL_CLASS = 'Model class (%s) not found';
public function __construct($db = NULL, $table = NULL, $fluid = NULL, $ttl = 0){
@@ -135,8 +144,8 @@ abstract class BasicModel extends \DB\Cortex {
/**
* @param string $key
* @param mixed $val
* @return mixed|void
* @throws Exception\ValidationException
* @return mixed
* @throws ValidationException
*/
public function set($key, $val){
if(
@@ -167,15 +176,13 @@ abstract class BasicModel extends \DB\Cortex {
$val = trim($val);
}
$valid = $this->validateField($key, $val);
if(!$valid){
$this->throwValidationError($key);
if( !$this->validateField($key, $val) ){
$this->throwValidationException($key);
}else{
$this->checkFieldForActivityLogging($key, $val);
return parent::set($key, $val);
}
return parent::set($key, $val);
}
/**
@@ -206,15 +213,25 @@ abstract class BasicModel extends \DB\Cortex {
$val = (int)$val;
}
if(is_object($val)){
$val = $val->_id;
}
if( $fieldConf['type'] === self::DT_JSON){
$currentValue = $this->get($key);
}else{
$currentValue = $this->get($key, true);
}
if($currentValue !== $val){
// field has changed
in_array($key, $this->fieldChanges) ?: $this->fieldChanges[] = $key;
if( !array_key_exists($key, $this->fieldChanges) ){
$this->fieldChanges[$key] = [
'old' => $currentValue,
'new' => $val
];
}
}
}
}
@@ -239,11 +256,12 @@ abstract class BasicModel extends \DB\Cortex {
}
/**
* extent the fieldConf Array with static fields for each table
* get static fields for this model instance
* @return array
*/
private function addStaticFieldConfig(){
protected function getStaticFieldConf(): array {
$staticFieldConfig = [];
// add static fields to this mapper
// static tables (fixed data) do not require them...
if($this->addStaticFields){
$staticFieldConfig = [
@@ -258,61 +276,37 @@ abstract class BasicModel extends \DB\Cortex {
'index' => true
]
];
$this->fieldConf = array_merge($staticFieldConfig, $this->fieldConf);
}
return $staticFieldConfig;
}
/**
* extent the fieldConf Array with static fields for each table
*/
private function addStaticFieldConfig(){
$this->fieldConf = array_merge($this->getStaticFieldConf(), $this->fieldConf);
}
/**
* validates a table column based on validation settings
* @param $col
* @param string $key
* @param $val
* @return bool
*/
private function validateField($col, $val){
protected function validateField(string $key, $val): bool {
$valid = true;
if(array_key_exists($col, $this->validate)){
$fieldValidationOptions = $this->validate[$col];
foreach($fieldValidationOptions as $validateKey => $validateOption ){
if(is_array($fieldValidationOptions[$validateKey])){
$fieldSubValidationOptions = $fieldValidationOptions[$validateKey];
foreach($fieldSubValidationOptions as $validateSubKey => $validateSubOption ){
switch($validateKey){
case 'length':
switch($validateSubKey){
case 'min';
if(strlen($val) < $validateSubOption){
$valid = false;
}
break;
case 'max';
if(strlen($val) > $validateSubOption){
$valid = false;
}
break;
}
break;
}
}
if($fieldConf = $this->fieldConf[$key]){
if($method = $this->fieldConf[$key]['validate']){
if( !is_string($method)){
$method = 'validate_' . $key;
}
if(method_exists($this, $method)){
// validate $key (column) with this method...
$valid = $this->$method($key, $val);
}else{
switch($validateKey){
case 'regex':
$valid = (bool)preg_match($fieldValidationOptions[$validateKey], $val);
break;
}
}
// a validation rule failed
if(!$valid){
break;
}
self::getF3()->error(501, 'Method ' . get_class($this) . '->' . $method . '() is not implemented');
};
}
}
@@ -428,13 +422,22 @@ abstract class BasicModel extends \DB\Cortex {
}
/**
* Throws a validation error for a giben column
* @param $col
* @throws \Exception\ValidationException
* throw validation exception for a model property
* @param string $col
* @param string $msg
* @throws ValidationException
*/
protected function throwValidationError($col){
throw new Exception\ValidationException('Validation failed: "' . $col . '".', $col);
protected function throwValidationException(string $col, string $msg = ''){
$msg = empty($msg) ? 'Validation failed: "' . $col . '".' : $msg;
throw new ValidationException($msg, $col);
}
/**
* @param string $msg
* @throws DatabaseException
*/
protected function throwDbException(string $msg){
throw new DatabaseException($msg);
}
/**
@@ -458,11 +461,11 @@ abstract class BasicModel extends \DB\Cortex {
* get single dataSet by id
* @param $id
* @param int $ttl
* @param bool $isActive
* @return \DB\Cortex
*/
public function getById($id, $ttl = 3) {
return $this->getByForeignKey('id', (int)$id, ['limit' => 1], $ttl);
public function getById(int $id, int $ttl = 3, bool $isActive = true){
return $this->getByForeignKey('id', (int)$id, ['limit' => 1], $ttl, $isActive);
}
/**
@@ -492,10 +495,10 @@ abstract class BasicModel extends \DB\Cortex {
* @param $value
* @param array $options
* @param int $ttl
* @param bool $isActive
* @return \DB\Cortex
*/
public function getByForeignKey($key, $value, $options = [], $ttl = 60){
public function getByForeignKey($key, $value, $options = [], $ttl = 0, $isActive = true){
$querySet = [];
$query = [];
if($this->exists($key)){
@@ -504,7 +507,7 @@ abstract class BasicModel extends \DB\Cortex {
}
// check active column
if($this->exists('active')){
if($isActive && $this->exists('active')){
$query[] = "active = :active";
$querySet[':active'] = 1;
}
@@ -594,7 +597,7 @@ abstract class BasicModel extends \DB\Cortex {
* function should be overwritten in parent classes
* @return bool
*/
public function isValid(){
public function isValid(): bool {
return true;
}
@@ -678,7 +681,7 @@ abstract class BasicModel extends \DB\Cortex {
$status = $this->importStaticData($tableData);
$this->getF3()->status(202);
}else{
$this->getF3()->error(502, 'File could not be read');
$this->getF3()->error(500, 'File could not be read');
}
}else{
$this->getF3()->error(404, 'File not found: ' . $filePath);
@@ -727,15 +730,54 @@ abstract class BasicModel extends \DB\Cortex {
}
/**
* buffer a new activity (action) logging
* -> increment buffered counter
* -> log character activity create/update/delete events
* @param int $characterId
* @param int $mapId
* get "default" logging object for this kind of model
* -> can be overwritten
* @param string $action
* @return Logging\LogInterface
*/
protected function bufferActivity($characterId, $mapId, $action){
Controller\LogController::instance()->bufferActivity($characterId, $mapId, $action);
protected function newLog($action = ''): Logging\LogInterface{
return new Logging\DefaultLog($action);
}
/**
* get formatter callback function for parsed logs
* @return null
*/
protected function getLogFormatter(){
return null;
}
/**
* add new validation error
* @param ValidationException $e
*/
protected function setValidationError(ValidationException $e){
$this->validationError[] = $e->getError();
}
/**
* get all validation errors
* @return array
*/
public function getErrors(): array {
return $this->validationError;
}
public function save(){
try{
return parent::save();
}catch(ValidationException $e){
$this->setValidationError($e);
}catch(DatabaseException $e){
self::getF3()->error($e->getCode(), $e->getMessage(), $e->getTrace());
}
}
/**
* @return string
*/
public function __toString(){
return $this->getTable();
}
/**
@@ -755,14 +797,14 @@ abstract class BasicModel extends \DB\Cortex {
* @return BasicModel
* @throws \Exception
*/
public static function getNew($model, $ttl = 86400){
public static function getNew($model, $ttl = self::DEFAULT_TTL){
$class = null;
$model = '\\' . __NAMESPACE__ . '\\' . $model;
if(class_exists($model)){
$class = new $model( null, null, null, $ttl );
}else{
throw new \Exception('No model class found');
throw new \Exception(sprintf(self::ERROR_INVALID_MODEL_CLASS, $model));
}
return $class;