diff --git a/community_server/src/Controller/AppController.php b/community_server/src/Controller/AppController.php index 1cdcf4418..80690b238 100644 --- a/community_server/src/Controller/AppController.php +++ b/community_server/src/Controller/AppController.php @@ -156,8 +156,24 @@ class AppController extends Controller } } + protected function checkForMigration($html = true) + { + $migrationsTable = TableRegistry::getTableLocator()->get('Migrations'); + $last_migration = $migrationsTable->find()->last(); + $current_db_version = 1; + if($last_migration) { + $current_db_version = $last_migration->db_version; + } + $php_data_version = 2; + if($current_db_version < $php_data_version) { + $this->redirect(['controller' => 'Migrations', 'action' => 'migrate', $html, $current_db_version]); + } + } + + protected function requestLogin($sessionId = 0, $redirect = true) { + $this->checkForMigration($redirect); $session = $this->getRequest()->getSession(); // check login // disable encryption for cookies diff --git a/community_server/src/Controller/MigrationsController.php b/community_server/src/Controller/MigrationsController.php index 93a1b8044..c2febef0f 100644 --- a/community_server/src/Controller/MigrationsController.php +++ b/community_server/src/Controller/MigrationsController.php @@ -2,6 +2,7 @@ namespace App\Controller; use App\Controller\AppController; +use Cake\ORM\TableRegistry; /** * Migrations Controller @@ -23,6 +24,52 @@ class MigrationsController extends AppController $this->set(compact('migrations')); } + + protected function callFunctions(array $callables) + { + foreach($callables as $callable) { + $result = call_user_func($callable); + if(!$result['success']) { + return $result; + } + } + return ['success' => true]; + } + + public function migrate($html, $current_db_version) + { + $startTime = microtime(true); + $stateUserTransactionsTable = TableRegistry::getTableLocator()->get('StateUserTransactions'); + $transactionsTable = TableRegistry::getTableLocator()->get('Transactions'); + $stateBalancesTable = TableRegistry::getTableLocator()->get('StateBalances'); + + $new_db_version = 1; + + $commands = []; + // migrate from version 1 to 2 + if($current_db_version == 1) { + $stateUserTransactionsTable->truncate(); + $commands = [ + [$transactionsTable, 'fillStateUserTransactions'], + [$stateBalancesTable, 'updateAllBalances'] + ]; + $new_db_version = 2; + } + + $migration_result = $this->callFunctions($commands); + if($migration_result['success']) { + $migration_entity = $this->Migrations->newEntity(); + $migration_entity->db_version = $new_db_version; + $this->Migrations->save($migration_entity); + } + if(!$html) { + return $this->returnJson($migration_result); + } else { + $this->set('db_version', $current_db_version); + $this->set('result', $migration_result); + $this->set('timeUsed', microtime(true) - $startTime); + } + } /** * View method diff --git a/community_server/src/Controller/StateBalancesController.php b/community_server/src/Controller/StateBalancesController.php index 3994b989a..655dbc026 100644 --- a/community_server/src/Controller/StateBalancesController.php +++ b/community_server/src/Controller/StateBalancesController.php @@ -62,7 +62,7 @@ class StateBalancesController extends AppController $user = $session->read('StateUser'); $update_balance_result = $this->StateBalances->updateBalances($user['id']); - if($update_balance_result !== true) { + if($update_balance_result['success'] !== true) { $this->addAdminError('StateBalances', 'overview', $update_balance_result, $user['id']); } // sendRequestGDT diff --git a/community_server/src/Model/Table/AppTable.php b/community_server/src/Model/Table/AppTable.php new file mode 100644 index 000000000..3a281afcc --- /dev/null +++ b/community_server/src/Model/Table/AppTable.php @@ -0,0 +1,23 @@ +schema()->truncateSql($this->connection()); + foreach ($truncateCommands as $truncateCommand) { + $this->connection()->query($truncateCommand); + } + } +} diff --git a/community_server/src/Model/Table/StateBalancesTable.php b/community_server/src/Model/Table/StateBalancesTable.php index 4e91c2948..87e961c5d 100644 --- a/community_server/src/Model/Table/StateBalancesTable.php +++ b/community_server/src/Model/Table/StateBalancesTable.php @@ -113,6 +113,20 @@ class StateBalancesTable extends Table } + public function updateAllBalances() + { + $stateUserTable = TableRegistry::getTableLocator()->get('StateUsers'); + $state_users = $stateUserTable->find()->select(['id'])->contain([]); + foreach($state_users as $state_user) { + $result = $this->updateBalances($state_user->id); + if($result['success'] === false) { + $result['state_user_id'] = $state_user->id; + return $result; + } + } + return ['success' => true]; + } + public function updateBalances($stateUserId) { $stateUserTransactionsTable = TableRegistry::getTableLocator()->get('StateUserTransactions'); @@ -128,7 +142,7 @@ class StateBalancesTable extends Table ; if(!$state_user_transactions || !$state_user_transactions->count()) { - return true; + return ['success' => true]; } // first: decide what todo @@ -222,40 +236,27 @@ class StateBalancesTable extends Table $transaction = $transactions_indiced[$state_user_transaction->transaction_id]; if($transaction->transaction_type_id > 2) { continue; - } - //echo "transaction id: ".$transaction->id . "
"; - $amount_date = null; + } $amount = 0; if($transaction->transaction_type_id == 1) { // creation - $temp = $transaction->transaction_creation; - - /*$balance_temp = $this->newEntity(); - $balance_temp->amount = $temp->amount; - $balance_temp->record_date = $temp->target_date; - */ - $amount = intval($temp->amount);//$balance_temp->partDecay($transaction->received); - $amount_date = $temp->target_date; - - //$amount_date = + $amount = intval($transaction->transaction_creation->amount); } else if($transaction->transaction_type_id == 2) { // transfer - $temp = $transaction->transaction_send_coin; $amount = intval($temp->amount); // reverse if sender if($stateUserId == $temp->state_user_id) { $amount *= -1.0; } - $amount_date = $transaction->received; - } + $amount_date = $transaction->received; if($i == 0) { $balance_cursor->amount = $amount; } else { //$balance_cursor->amount = $balance_cursor->partDecay($amount_date) + $amount; $balance_cursor->amount = - $this->calculateDecay($balance_cursor->amount, $balance_cursor->recordDate, $amount_date) + $this->calculateDecay($balance_cursor->amount, $balance_cursor->record_date, $amount_date) + $amount; } //echo "new balance: " . $balance_cursor->amount . "
"; @@ -294,7 +295,7 @@ class StateBalancesTable extends Table return ['success' => false, 'error' => 'error saving state balance', 'details' => $state_balance->getErrors()]; } } - return true; + return ['success' => true]; } diff --git a/community_server/src/Model/Table/StateUserTransactionsTable.php b/community_server/src/Model/Table/StateUserTransactionsTable.php index 6cfe94a23..2c984d964 100644 --- a/community_server/src/Model/Table/StateUserTransactionsTable.php +++ b/community_server/src/Model/Table/StateUserTransactionsTable.php @@ -22,7 +22,7 @@ use Cake\Validation\Validator; * @method \App\Model\Entity\StateUserTransaction[] patchEntities($entities, array $data, array $options = []) * @method \App\Model\Entity\StateUserTransaction findOrCreate($search, callable $callback = null, $options = []) */ -class StateUserTransactionsTable extends Table +class StateUserTransactionsTable extends AppTable { /** * Initialize method diff --git a/community_server/src/Model/Table/TransactionsTable.php b/community_server/src/Model/Table/TransactionsTable.php index 71d301722..9ae2fe02a 100644 --- a/community_server/src/Model/Table/TransactionsTable.php +++ b/community_server/src/Model/Table/TransactionsTable.php @@ -335,4 +335,108 @@ class TransactionsTable extends Table } return $transaction->first()->received; } + + public function fillStateUserTransactions() + { + $missing_transaction_ids = []; + $transaction_ids = $this + ->find('all') + ->select(['id', 'transaction_type_id']) + ->order(['id']) + ->all() + ; + $state_user_transaction_ids = $this->StateUserTransactions + ->find('all') + ->select(['transaction_id']) + ->group(['transaction_id']) + ->order(['transaction_id']) + ->toArray() + ; + $i2 = 0; + $count = count($state_user_transaction_ids); + foreach($transaction_ids as $tr_id) { + //echo "$i1: "; + if($i2 >= $count) { + $missing_transaction_ids[] = $tr_id; + //echo "adding to missing: $tr_id, continue
"; + continue; + } + $stu_id = $state_user_transaction_ids[$i2]; + if($tr_id->id == $stu_id->transaction_id) { + $i2++; + //echo "after i2++: $i2
"; + } else if($tr_id->id < $stu_id->transaction_id) { + $missing_transaction_ids[] = $tr_id; + //echo "adding to missing: $tr_id
"; + } + } + + + $tablesForType = [ + 1 => $this->TransactionCreations, + 2 => $this->TransactionSendCoins, + 3 => $this->TransactionGroupCreates, + 4 => $this->TransactionGroupAddaddress, + 5 => $this->TransactionGroupAddaddress + ]; + $idsForType = []; + foreach($missing_transaction_ids as $i => $transaction) { + if(!isset($idsForType[$transaction->transaction_type_id])) { + $idsForType[$transaction->transaction_type_id] = []; + } + $idsForType[$transaction->transaction_type_id][] = $transaction->id; + } + $entities = []; + $state_user_ids = []; + foreach($idsForType as $type_id => $transaction_ids) { + $specific_transactions = $tablesForType[$type_id]->find('all')->where(['transaction_id IN' => $transaction_ids])->toArray(); + $keys = $tablesForType[$type_id]->getSchema()->columns(); + //var_dump($keys); + foreach($specific_transactions as $specific) { + + foreach($keys as $key) { + if(preg_match('/_user_id/', $key)) { + $entity = $this->StateUserTransactions->newEntity(); + $entity->transaction_id = $specific['transaction_id']; + $entity->transaction_type_id = $type_id; + $entity->state_user_id = $specific[$key]; + if(!in_array($entity->state_user_id, $state_user_ids)) { + array_push($state_user_ids, $entity->state_user_id); + } + $entities[] = $entity; + } + } + } + } + //var_dump($entities); + $stateUsersTable = TableRegistry::getTableLocator()->get('StateUsers'); + $existingStateUsers = $stateUsersTable->find('all')->select(['id'])->where(['id IN' => $state_user_ids])->order(['id'])->all(); + $existing_state_user_ids = []; + $finalEntities = []; + foreach($existingStateUsers as $stateUser) { + $existing_state_user_ids[] = $stateUser->id; + } + foreach($entities as $entity) { + if(in_array($entity->state_user_id, $existing_state_user_ids)) { + array_push($finalEntities, $entity); + } + } + + $results = $this->StateUserTransactions->saveMany($finalEntities); + $errors = []; + foreach($results as $i => $res) { + if($res == false) { + $errors[] = $finalEntities[$i]->getErrors(); + } + } + if(count($errors) == 0) { + $result = ['success' => true]; + } else { + $result = ['success' => false, 'msg' => 'error by saving at least one state user transaction', 'errors' => $errors]; + } + + + + return $result; + } } diff --git a/community_server/src/Template/Migrations/migrate.ctp b/community_server/src/Template/Migrations/migrate.ctp new file mode 100644 index 000000000..6ceeec81c --- /dev/null +++ b/community_server/src/Template/Migrations/migrate.ctp @@ -0,0 +1,18 @@ +

Migrate DB

+

Migrate from Version

+ +

Success

+ +

Error

+

+ +

Html->link('Back to Dashboard', ['controller' => 'Dashboard', 'action' => 'index']) ?>

+);