src/Console/Controllers/MessageController.php
protected function saveMessagesToDb($messages, $db, $sourceMessageTable, $messageTable, $removeUnused, $languages, $markUnused)
    {
        $currentMessages = [];
        $currentLanguages = [];
        $missingLanguages = [];
        $currentPromises = [
            'messages' => (new Query())->select(['id', 'category', 'message'])->from($sourceMessageTable)->all($db),
            'languages' => (new Query())->select(['language'])->from($messageTable)->groupBy('language')->all($db),
        ];

        $newMessages = [];
        $obsoleteMessages = [];
        $savedFlag = false;

        //Get current messages and languages
        return all($currentPromises)
            ->then(function($results) use (&$currentMessages, &$currentLanguages, &$missingLanguages, $languages) {
                if (!empty($results['messages'])) {
                    foreach ($results['messages'] as $row) {
                        $currentMessages[$row['category']][$row['id']] = $row['message'];
                    }
                }
                if (!empty($results['languages'])) {
                    foreach ($results['languages'] as $row) {
                        $currentLanguages[] = $row['language'];
                    }
                }
                if (!empty($currentLanguages)) {
                    $missingLanguages = array_diff($languages, $currentLanguages);
                }
                return true;
            //Extract from $messages array New and Obsolete messages
            })->then(function() use (&$currentMessages, &$newMessages, &$obsoleteMessages, $messages, $removeUnused) {
                foreach ($messages as $category => $msgs) {
                    $msgs = array_unique($msgs);

                    if (isset($currentMessages[$category])) {
                        $newMessages[$category] = array_diff($msgs, $currentMessages[$category]);
                        $obsoleteMessages += array_diff($currentMessages[$category], $msgs);
                    } else {
                        $newMessages[$category] = $msgs;
                    }
                }

                foreach (array_diff(array_keys($currentMessages), array_keys($messages)) as $category) {
                    $obsoleteMessages += $currentMessages[$category];
                }

                if (!$removeUnused) {
                    foreach ($obsoleteMessages as $pk => $msg) {
                        if (mb_substr($msg, 0, 2) === '@@' && mb_substr($msg, -2) === '@@') {
                            unset($obsoleteMessages[$pk]);
                        }
                    }
                }
                $obsoleteMessages = array_keys($obsoleteMessages);
                return [$newMessages, $obsoleteMessages];
            //Insert new messages to DB
            })->then(function() use (&$newMessages, &$savedFlag, &$db, $sourceMessageTable, $messageTable, $languages) {
                $srcInsertPromises = [];
                foreach ($newMessages as $category => $msgs) {
                    foreach ($msgs as $msg) {
                        $savedFlag = true;
                        $srcInsertPromises[] = $db->getSchema()
                            ->insert($sourceMessageTable, ['category' => $category, 'message' => $msg])
                            ->then(function($lastPk) use (&$db, $languages, $messageTable) {
                                $promises = [];
                                foreach ($languages as $language) {
                                    $promises[] = $db->createCommand()
                                        ->insert($messageTable, ['id' => $lastPk['id'], 'language' => $language])
                                        ->execute();
                                }
                                return allInOrder($promises);
                            });
                    }
                }
                return !empty($srcInsertPromises) ? all($srcInsertPromises) : resolve(true);
            //Remove or mark unused messages
            })->then(function() use (&$db, &$savedFlag, &$obsoleteMessages, $removeUnused, $markUnused, $sourceMessageTable) {
                $this->stdout($savedFlag ? "saved.\n" : "Nothing to save.\n");
                $this->stdout($removeUnused ? 'Deleting obsoleted messages...' : 'Updating obsoleted messages...');

                if (empty($obsoleteMessages)) {
                    $this->stdout("Nothing obsoleted...skipped.\n");
                    return resolve(true);
                }

                if ($removeUnused) {
                    return $db->createCommand()
                        ->delete($sourceMessageTable, ['in', 'id', $obsoleteMessages])
                        ->execute()
                        ->then(function() {
                            $this->stdout("deleted.\n");
                            return true;
                        });
                } elseif ($markUnused) {
                    return (new Query())
                        ->select(['id', 'message'])
                        ->from($sourceMessageTable)
                        ->where(['in', 'id', $obsoleteMessages])
                        ->all($db)
                        ->then(function($rows) use (&$db, $sourceMessageTable) {
                            $promises = [];
                            foreach ($rows as $row) {
                                $promises[] = $db->createCommand()->update(
                                    $sourceMessageTable,
                                    ['message' => '@@' . $row['message'] . '@@'],
                                    ['id' => $row['id']]
                                )->execute();
                            }
                            return allInOrder($promises);
                        })->then(function() {
                            $this->stdout("updated.\n");
                            return true;
                        });
                } else {
                    $this->stdout("kept untouched.\n");
                    return resolve(true);
                }
            });
    }
protected function saveMessagesToDb($messages, $db, $sourceMessageTable, $messageTable, $removeUnused, $languages, $markUnused)
    {
        $currentMessages = [];
        $currentLanguages = [];
        $missingLanguages = [];
        $currentPromises = [
            'messages' => (new Query())->select(['id', 'category', 'message'])->from($sourceMessageTable)->all($db),
            'languages' => (new Query())->select(['language'])->from($messageTable)->groupBy('language')->all($db),
        ];

        $newMessages = [];
        $obsoleteMessages = [];
        $savedFlag = false;

        //Get current messages and languages
        return all($currentPromises)
            ->then(function($results) use (&$currentMessages, &$currentLanguages, &$missingLanguages, $languages) {
                if (!empty($results['messages'])) {
                    foreach ($results['messages'] as $row) {
                        $currentMessages[$row['category']][$row['id']] = $row['message'];
                    }
                }
                if (!empty($results['languages'])) {
                    foreach ($results['languages'] as $row) {
                        $currentLanguages[] = $row['language'];
                    }
                }
                if (!empty($currentLanguages)) {
                    $missingLanguages = array_diff($languages, $currentLanguages);
                }
                return true;
            //Extract from $messages array New and Obsolete messages
            })->then(function() use (&$currentMessages, &$newMessages, &$obsoleteMessages, $messages, $removeUnused) {
                foreach ($messages as $category => $msgs) {
                    $msgs = array_unique($msgs);

                    if (isset($currentMessages[$category])) {
                        $newMessages[$category] = array_diff($msgs, $currentMessages[$category]);
                        $obsoleteMessages += array_diff($currentMessages[$category], $msgs);
                    } else {
                        $newMessages[$category] = $msgs;
                    }
                }

                foreach (array_diff(array_keys($currentMessages), array_keys($messages)) as $category) {
                    $obsoleteMessages += $currentMessages[$category];
                }

                if (!$removeUnused) {
                    foreach ($obsoleteMessages as $pk => $msg) {
                        if (mb_substr($msg, 0, 2) === '@@' && mb_substr($msg, -2) === '@@') {
                            unset($obsoleteMessages[$pk]);
                        }
                    }
                }
                $obsoleteMessages = array_keys($obsoleteMessages);
                return [$newMessages, $obsoleteMessages];
            //Insert new messages to DB
            })->then(function() use (&$newMessages, &$savedFlag, &$db, $sourceMessageTable, $messageTable, $languages) {
                $srcInsertPromises = [];
                foreach ($newMessages as $category => $msgs) {
                    foreach ($msgs as $msg) {
                        $savedFlag = true;
                        $srcInsertPromises[] = $db->getSchema()
                            ->insert($sourceMessageTable, ['category' => $category, 'message' => $msg])
                            ->then(function($lastPk) use (&$db, $languages, $messageTable) {
                                $promises = [];
                                foreach ($languages as $language) {
                                    $promises[] = $db->createCommand()
                                        ->insert($messageTable, ['id' => $lastPk['id'], 'language' => $language])
                                        ->execute();
                                }
                                return allInOrder($promises);
                            });
                    }
                }
                return !empty($srcInsertPromises) ? all($srcInsertPromises) : resolve(true);
            //Remove or mark unused messages
            })->then(function() use (&$db, &$savedFlag, &$obsoleteMessages, $removeUnused, $markUnused, $sourceMessageTable) {
                $this->stdout($savedFlag ? "saved.\n" : "Nothing to save.\n");
                $this->stdout($removeUnused ? 'Deleting obsoleted messages...' : 'Updating obsoleted messages...');

                if (empty($obsoleteMessages)) {
                    $this->stdout("Nothing obsoleted...skipped.\n");
                    return resolve(true);
                }

                if ($removeUnused) {
                    return $db->createCommand()
                        ->delete($sourceMessageTable, ['in', 'id', $obsoleteMessages])
                        ->execute()
                        ->then(function() {
                            $this->stdout("deleted.\n");
                            return true;
                        });
                } elseif ($markUnused) {
                    return (new Query())
                        ->select(['id', 'message'])
                        ->from($sourceMessageTable)
                        ->where(['in', 'id', $obsoleteMessages])
                        ->all($db)
                        ->then(function($rows) use (&$db, $sourceMessageTable) {
                            $promises = [];
                            foreach ($rows as $row) {
                                $promises[] = $db->createCommand()->update(
                                    $sourceMessageTable,
                                    ['message' => '@@' . $row['message'] . '@@'],
                                    ['id' => $row['id']]
                                )->execute();
                            }
                            return allInOrder($promises);
                        })->then(function() {
                            $this->stdout("updated.\n");
                            return true;
                        });
                } else {
                    $this->stdout("kept untouched.\n");
                    return resolve(true);
                }
            });
    }
Saves messages to database.

@param array $messages
@param DatabaseInterface $db
@param string $sourceMessageTable
@param string $messageTable
@param bool $removeUnused
@param array $languages
@param bool $markUnused
@return ExtendedPromiseInterface