1
0
mirror of https://github.com/flarum/core.git synced 2025-08-16 05:14:20 +02:00

Compare commits

..

4 Commits

Author SHA1 Message Date
luceos
43f379093c Apply fixes from StyleCI
[ci skip] [skip ci]
2021-05-31 13:45:05 +00:00
Daniel Klabbers
f5c602c234 wip 2021-05-31 15:44:37 +02:00
luceos
0727f3d6d4 Apply fixes from StyleCI
[ci skip] [skip ci]
2021-05-30 09:53:09 +00:00
Daniël Klabbers
979a471214 modifying migrator and moving files 2021-05-30 11:52:30 +02:00
108 changed files with 438 additions and 903 deletions

1
.gitattributes vendored
View File

@@ -12,6 +12,5 @@ tests export-ignore
js/dist/* -diff js/dist/* -diff
js/dist/* linguist-generated js/dist/* linguist-generated
js/dist-typings/* linguist-generated
* text=auto eol=lf * text=auto eol=lf

1
.github/FUNDING.yml vendored
View File

@@ -1,2 +1,3 @@
github: flarum github: flarum
open_collective: flarum open_collective: flarum
tidelift: packagist/flarum/core

14
.github/SECURITY.md vendored
View File

@@ -1,13 +1,13 @@
# Security Policy # Security Policy
## Versions ## Supported Versions
Due to the nature of our project - being open source - we have decided to patch only the latest major release (currently v1.x) for security vulnerabilities. We will only patch security vulnerabilities in the stable 1.x release.
## How to disclose ## Reporting a Vulnerability
Please use [huntr.dev](https://huntr.dev/) for security issues that affect our project. If you believe you have found a vulnerability, please disclose it via [this form](https://huntr.dev/bounties/disclose/?target=https://github.com/flarum/core). If you discover a security vulnerability within Flarum, please send an email to security@flarum.org so we can address it promptly.
This will enable us to **review** the vulnerability, **fix** it promptly, and **reward** you for your efforts. We will get back to you as time allows.
Discussions may commence internally, so you may not hear back immediately.
If you have any questions about the process, feel free to reach out to security@huntr.dev or security@flarum.org. When reporting a vulnerability, please provide your GitHub username (if available), so that we can invite you to collaborate on a [security advisory on GitHub](https://help.github.com/en/articles/about-maintainer-security-advisories).

View File

@@ -1,29 +1,5 @@
# Changelog # Changelog
## [1.0.3](https://github.com/flarum/core/compare/v1.0.2...v1.0.3)
### Changed
- Removed [forum] prefix from Request Password and Email Confirmation emails ([a4a81c0](https://github.com/flarum/core/commit/a4a81c0ec237476cd6e7ca00c1ed9465493af476))
- Adopt huntr.dev for handling our security vulnerability reports (https://github.com/flarum/core/pull/2918)
- Maintenance handler can now be replaced through the service container (ioc) ([4acff91](https://github.com/flarum/core/commit/4acff91f8063fcced9bf8c9a76fbb510d06823c0))
- The colors on the auto generated avatars are now based on the Display Name of the user (https://github.com/flarum/core/pull/2873)
### Fixed
- Avatar in notifications list are incorrectly aligned (https://github.com/flarum/core/pull/2906)
- FilesystemManager is not compatible with upstream Laravel implementation (https://github.com/flarum/core/pull/2936)
## [1.0.2](https://github.com/flarum/core/compare/v1.0.1...v1.0.2)
### Fixed
- Critical XSS vulnerability
## [1.0.1](https://github.com/flarum/core/compare/v1.0.0...v1.0.1)
### Fixed
- Installation fails on environments without proc_* functions enabled or mysql client binary (https://github.com/flarum/core/issues/2890)
## [1.0.0](https://github.com/flarum/core/compare/v0.1.0-beta.16...v1.0.0) ## [1.0.0](https://github.com/flarum/core/compare/v0.1.0-beta.16...v1.0.0)
### Added ### Added

View File

@@ -5,7 +5,6 @@
<a href="https://packagist.org/packages/flarum/core"><img src="https://img.shields.io/packagist/dt/flarum/core" alt="Total Downloads"></a> <a href="https://packagist.org/packages/flarum/core"><img src="https://img.shields.io/packagist/dt/flarum/core" alt="Total Downloads"></a>
<a href="https://packagist.org/packages/flarum/core"><img src="https://img.shields.io/github/v/release/flarum/core?sort=semver" alt="Latest Version"></a> <a href="https://packagist.org/packages/flarum/core"><img src="https://img.shields.io/github/v/release/flarum/core?sort=semver" alt="Latest Version"></a>
<a href="https://packagist.org/packages/flarum/core"><img src="https://img.shields.io/packagist/l/flarum/core" alt="License"></a> <a href="https://packagist.org/packages/flarum/core"><img src="https://img.shields.io/packagist/l/flarum/core" alt="License"></a>
<a href="https://huntr.dev/bounties/disclose/?target=https://github.com/flarum/core"><img src="https://cdn.huntr.dev/huntr_security_badge_mono.svg" alt="huntr"></a>
<a href="https://github.styleci.io/repos/28257573"><img src="https://github.styleci.io/repos/28257573/shield?style=flat" alt="StyleCI"></a> <a href="https://github.styleci.io/repos/28257573"><img src="https://github.styleci.io/repos/28257573/shield?style=flat" alt="StyleCI"></a>
</p> </p>

View File

@@ -14,26 +14,10 @@
"homepage": "https://flarum.org/team" "homepage": "https://flarum.org/team"
} }
], ],
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/flarum"
},
{
"type": "github",
"url": "https://github.com/sponsors/flarum"
},
{
"type": "other",
"url": "https://flarum.org/donate"
}
],
"support": { "support": {
"issues": "https://github.com/flarum/core/issues", "issues": "https://github.com/flarum/core/issues",
"source": "https://github.com/flarum/core", "source": "https://github.com/flarum/core",
"docs": "https://docs.flarum.org", "docs": "https://flarum.org/docs/"
"forum": "https://discuss.flarum.org",
"chat": "https://flarum.org/chat"
}, },
"require": { "require": {
"php": ">=7.3", "php": ">=7.3",

2
js/dist/admin.js generated vendored

File diff suppressed because one or more lines are too long

2
js/dist/admin.js.map generated vendored

File diff suppressed because one or more lines are too long

2
js/dist/forum.js generated vendored

File diff suppressed because one or more lines are too long

2
js/dist/forum.js.map generated vendored

File diff suppressed because one or more lines are too long

12
js/package-lock.json generated
View File

@@ -7552,9 +7552,9 @@
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
}, },
"node_modules/ws": { "node_modules/ws": {
"version": "7.4.6", "version": "7.4.5",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.5.tgz",
"integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", "integrity": "sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g==",
"dev": true, "dev": true,
"engines": { "engines": {
"node": ">=8.3.0" "node": ">=8.3.0"
@@ -13723,9 +13723,9 @@
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
}, },
"ws": { "ws": {
"version": "7.4.6", "version": "7.4.5",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.5.tgz",
"integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", "integrity": "sha512-xzyu3hFvomRfXKH8vOFMU3OguG6oOvhXMo3xsGy3xWExqaM2dxBbVxuD99O7m3ZUFMvvscsZDqxfgMaRr/Nr1g==",
"dev": true, "dev": true,
"requires": {} "requires": {}
}, },

View File

@@ -48,23 +48,12 @@ export default class Translator {
// future there should be a hook here to inspect the user and change the // future there should be a hook here to inspect the user and change the
// translation key. This will allow a gender property to determine which // translation key. This will allow a gender property to determine which
// translation key is used. // translation key is used.
if ('user' in parameters) { if ('user' in parameters) {
const user = extract(parameters, 'user'); const user = extract(parameters, 'user');
if (!parameters.username) parameters.username = username(user); if (!parameters.username) parameters.username = username(user);
} }
return parameters;
const escapedParameters: TranslatorParameters = {};
for (const param in parameters) {
const paramValue = parameters[param];
if (typeof paramValue === 'string') escapedParameters[param] = <>{parameters[param]}</>;
else escapedParameters[param] = parameters[param];
}
return escapedParameters;
} }
trans(id: string, parameters: TranslatorParameters = {}) { trans(id: string, parameters: TranslatorParameters = {}) {

View File

@@ -35,11 +35,11 @@ Object.assign(User.prototype, {
canDelete: Model.attribute('canDelete'), canDelete: Model.attribute('canDelete'),
avatarColor: null, avatarColor: null,
color: computed('displayName', 'avatarUrl', 'avatarColor', function (displayName, avatarUrl, avatarColor) { color: computed('username', 'avatarUrl', 'avatarColor', function (username, avatarUrl, avatarColor) {
// If we've already calculated and cached the dominant color of the user's // If we've already calculated and cached the dominant color of the user's
// avatar, then we can return that in RGB format. If we haven't, we'll want // avatar, then we can return that in RGB format. If we haven't, we'll want
// to calculate it. Unless the user doesn't have an avatar, in which case // to calculate it. Unless the user doesn't have an avatar, in which case
// we generate a color from their display name. // we generate a color from their username.
if (avatarColor) { if (avatarColor) {
return 'rgb(' + avatarColor.join(', ') + ')'; return 'rgb(' + avatarColor.join(', ') + ')';
} else if (avatarUrl) { } else if (avatarUrl) {
@@ -47,7 +47,7 @@ Object.assign(User.prototype, {
return ''; return '';
} }
return '#' + stringToColor(displayName); return '#' + stringToColor(username);
}), }),
/** /**

View File

@@ -136,14 +136,6 @@
.Avatar--size(24px); .Avatar--size(24px);
grid-area: avatar; grid-area: avatar;
} }
// Since images don't have baselines, aligning against the baseline won't work.
// Instead we need to do some manual hackery to fix then, otherwise they won't
// be correctly vertically aligned.
img.Avatar {
align-self: flex-start;
margin-top: -2px;
}
&-icon { &-icon {
font-size: 14px; font-size: 14px;

View File

@@ -1,367 +0,0 @@
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
DROP TABLE IF EXISTS `db_prefix_access_tokens`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `db_prefix_access_tokens` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`token` varchar(40) COLLATE utf8mb4_unicode_ci NOT NULL,
`user_id` int(10) unsigned NOT NULL,
`last_activity_at` datetime NOT NULL,
`created_at` datetime NOT NULL,
`type` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`title` varchar(150) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`last_ip_address` varchar(45) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`last_user_agent` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `db_prefix_access_tokens_token_unique` (`token`),
KEY `db_prefix_access_tokens_user_id_foreign` (`user_id`),
KEY `db_prefix_access_tokens_type_index` (`type`),
CONSTRAINT `db_prefix_access_tokens_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `db_prefix_users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
DROP TABLE IF EXISTS `db_prefix_api_keys`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `db_prefix_api_keys` (
`key` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`allowed_ips` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`scopes` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`user_id` int(10) unsigned DEFAULT NULL,
`created_at` datetime NOT NULL,
`last_activity_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `db_prefix_api_keys_key_unique` (`key`),
KEY `db_prefix_api_keys_user_id_foreign` (`user_id`),
CONSTRAINT `db_prefix_api_keys_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `db_prefix_users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
DROP TABLE IF EXISTS `db_prefix_discussion_user`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `db_prefix_discussion_user` (
`user_id` int(10) unsigned NOT NULL,
`discussion_id` int(10) unsigned NOT NULL,
`last_read_at` datetime DEFAULT NULL,
`last_read_post_number` int(10) unsigned DEFAULT NULL,
PRIMARY KEY (`user_id`,`discussion_id`),
KEY `db_prefix_discussion_user_discussion_id_foreign` (`discussion_id`),
CONSTRAINT `db_prefix_discussion_user_discussion_id_foreign` FOREIGN KEY (`discussion_id`) REFERENCES `db_prefix_discussions` (`id`) ON DELETE CASCADE,
CONSTRAINT `db_prefix_discussion_user_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `db_prefix_users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
DROP TABLE IF EXISTS `db_prefix_discussions`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `db_prefix_discussions` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(200) COLLATE utf8mb4_unicode_ci NOT NULL,
`comment_count` int(11) NOT NULL DEFAULT 1,
`participant_count` int(10) unsigned NOT NULL DEFAULT 0,
`post_number_index` int(10) unsigned NOT NULL DEFAULT 0,
`created_at` datetime NOT NULL,
`user_id` int(10) unsigned DEFAULT NULL,
`first_post_id` int(10) unsigned DEFAULT NULL,
`last_posted_at` datetime DEFAULT NULL,
`last_posted_user_id` int(10) unsigned DEFAULT NULL,
`last_post_id` int(10) unsigned DEFAULT NULL,
`last_post_number` int(10) unsigned DEFAULT NULL,
`hidden_at` datetime DEFAULT NULL,
`hidden_user_id` int(10) unsigned DEFAULT NULL,
`slug` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`is_private` tinyint(1) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
KEY `db_prefix_discussions_hidden_user_id_foreign` (`hidden_user_id`),
KEY `db_prefix_discussions_first_post_id_foreign` (`first_post_id`),
KEY `db_prefix_discussions_last_post_id_foreign` (`last_post_id`),
KEY `db_prefix_discussions_last_posted_at_index` (`last_posted_at`),
KEY `db_prefix_discussions_last_posted_user_id_index` (`last_posted_user_id`),
KEY `db_prefix_discussions_created_at_index` (`created_at`),
KEY `db_prefix_discussions_user_id_index` (`user_id`),
KEY `db_prefix_discussions_comment_count_index` (`comment_count`),
KEY `db_prefix_discussions_participant_count_index` (`participant_count`),
KEY `db_prefix_discussions_hidden_at_index` (`hidden_at`),
FULLTEXT KEY `title` (`title`),
CONSTRAINT `db_prefix_discussions_first_post_id_foreign` FOREIGN KEY (`first_post_id`) REFERENCES `db_prefix_posts` (`id`) ON DELETE SET NULL,
CONSTRAINT `db_prefix_discussions_hidden_user_id_foreign` FOREIGN KEY (`hidden_user_id`) REFERENCES `db_prefix_users` (`id`) ON DELETE SET NULL,
CONSTRAINT `db_prefix_discussions_last_post_id_foreign` FOREIGN KEY (`last_post_id`) REFERENCES `db_prefix_posts` (`id`) ON DELETE SET NULL,
CONSTRAINT `db_prefix_discussions_last_posted_user_id_foreign` FOREIGN KEY (`last_posted_user_id`) REFERENCES `db_prefix_users` (`id`) ON DELETE SET NULL,
CONSTRAINT `db_prefix_discussions_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `db_prefix_users` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
DROP TABLE IF EXISTS `db_prefix_email_tokens`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `db_prefix_email_tokens` (
`token` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`email` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL,
`user_id` int(10) unsigned NOT NULL,
`created_at` datetime DEFAULT NULL,
PRIMARY KEY (`token`),
KEY `db_prefix_email_tokens_user_id_foreign` (`user_id`),
CONSTRAINT `db_prefix_email_tokens_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `db_prefix_users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
DROP TABLE IF EXISTS `db_prefix_group_permission`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `db_prefix_group_permission` (
`group_id` int(10) unsigned NOT NULL,
`permission` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (`group_id`,`permission`),
CONSTRAINT `db_prefix_group_permission_group_id_foreign` FOREIGN KEY (`group_id`) REFERENCES `db_prefix_groups` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
DROP TABLE IF EXISTS `db_prefix_group_user`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `db_prefix_group_user` (
`user_id` int(10) unsigned NOT NULL,
`group_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`user_id`,`group_id`),
KEY `db_prefix_group_user_group_id_foreign` (`group_id`),
CONSTRAINT `db_prefix_group_user_group_id_foreign` FOREIGN KEY (`group_id`) REFERENCES `db_prefix_groups` (`id`) ON DELETE CASCADE,
CONSTRAINT `db_prefix_group_user_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `db_prefix_users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
DROP TABLE IF EXISTS `db_prefix_groups`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `db_prefix_groups` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name_singular` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`name_plural` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`color` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`icon` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`is_hidden` tinyint(1) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
DROP TABLE IF EXISTS `db_prefix_login_providers`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `db_prefix_login_providers` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(10) unsigned NOT NULL,
`provider` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`identifier` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`created_at` datetime DEFAULT NULL,
`last_login_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `db_prefix_login_providers_provider_identifier_unique` (`provider`,`identifier`),
KEY `db_prefix_login_providers_user_id_foreign` (`user_id`),
CONSTRAINT `db_prefix_login_providers_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `db_prefix_users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
DROP TABLE IF EXISTS `db_prefix_migrations`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `db_prefix_migrations` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`migration` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`extension` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
DROP TABLE IF EXISTS `db_prefix_notifications`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `db_prefix_notifications` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(10) unsigned NOT NULL,
`from_user_id` int(10) unsigned DEFAULT NULL,
`type` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`subject_id` int(10) unsigned DEFAULT NULL,
`data` blob DEFAULT NULL,
`created_at` datetime NOT NULL,
`is_deleted` tinyint(1) NOT NULL DEFAULT 0,
`read_at` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `db_prefix_notifications_from_user_id_foreign` (`from_user_id`),
KEY `db_prefix_notifications_user_id_index` (`user_id`),
CONSTRAINT `db_prefix_notifications_from_user_id_foreign` FOREIGN KEY (`from_user_id`) REFERENCES `db_prefix_users` (`id`) ON DELETE SET NULL,
CONSTRAINT `db_prefix_notifications_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `db_prefix_users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
DROP TABLE IF EXISTS `db_prefix_password_tokens`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `db_prefix_password_tokens` (
`token` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`user_id` int(10) unsigned NOT NULL,
`created_at` datetime DEFAULT NULL,
PRIMARY KEY (`token`),
KEY `db_prefix_password_tokens_user_id_foreign` (`user_id`),
CONSTRAINT `db_prefix_password_tokens_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `db_prefix_users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
DROP TABLE IF EXISTS `db_prefix_post_user`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `db_prefix_post_user` (
`post_id` int(10) unsigned NOT NULL,
`user_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`post_id`,`user_id`),
KEY `db_prefix_post_user_user_id_foreign` (`user_id`),
CONSTRAINT `db_prefix_post_user_post_id_foreign` FOREIGN KEY (`post_id`) REFERENCES `db_prefix_posts` (`id`) ON DELETE CASCADE,
CONSTRAINT `db_prefix_post_user_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `db_prefix_users` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
DROP TABLE IF EXISTS `db_prefix_posts`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `db_prefix_posts` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`discussion_id` int(10) unsigned NOT NULL,
`number` int(10) unsigned DEFAULT NULL,
`created_at` datetime NOT NULL,
`user_id` int(10) unsigned DEFAULT NULL,
`type` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`content` mediumtext COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT ' ',
`edited_at` datetime DEFAULT NULL,
`edited_user_id` int(10) unsigned DEFAULT NULL,
`hidden_at` datetime DEFAULT NULL,
`hidden_user_id` int(10) unsigned DEFAULT NULL,
`ip_address` varchar(45) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`is_private` tinyint(1) NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `db_prefix_posts_discussion_id_number_unique` (`discussion_id`,`number`),
KEY `db_prefix_posts_edited_user_id_foreign` (`edited_user_id`),
KEY `db_prefix_posts_hidden_user_id_foreign` (`hidden_user_id`),
KEY `db_prefix_posts_discussion_id_number_index` (`discussion_id`,`number`),
KEY `db_prefix_posts_discussion_id_created_at_index` (`discussion_id`,`created_at`),
KEY `db_prefix_posts_user_id_created_at_index` (`user_id`,`created_at`),
FULLTEXT KEY `content` (`content`),
CONSTRAINT `db_prefix_posts_discussion_id_foreign` FOREIGN KEY (`discussion_id`) REFERENCES `db_prefix_discussions` (`id`) ON DELETE CASCADE,
CONSTRAINT `db_prefix_posts_edited_user_id_foreign` FOREIGN KEY (`edited_user_id`) REFERENCES `db_prefix_users` (`id`) ON DELETE SET NULL,
CONSTRAINT `db_prefix_posts_hidden_user_id_foreign` FOREIGN KEY (`hidden_user_id`) REFERENCES `db_prefix_users` (`id`) ON DELETE SET NULL,
CONSTRAINT `db_prefix_posts_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `db_prefix_users` (`id`) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
DROP TABLE IF EXISTS `db_prefix_registration_tokens`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `db_prefix_registration_tokens` (
`token` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`payload` text COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`created_at` datetime DEFAULT NULL,
`provider` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`identifier` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`user_attributes` text COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`token`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
DROP TABLE IF EXISTS `db_prefix_settings`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `db_prefix_settings` (
`key` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`value` text COLLATE utf8mb4_unicode_ci DEFAULT NULL,
PRIMARY KEY (`key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
DROP TABLE IF EXISTS `db_prefix_users`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `db_prefix_users` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`email` varchar(150) COLLATE utf8mb4_unicode_ci NOT NULL,
`is_email_confirmed` tinyint(1) NOT NULL DEFAULT 0,
`password` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`avatar_url` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`preferences` blob DEFAULT NULL,
`joined_at` datetime DEFAULT NULL,
`last_seen_at` datetime DEFAULT NULL,
`marked_all_as_read_at` datetime DEFAULT NULL,
`read_notifications_at` datetime DEFAULT NULL,
`discussion_count` int(10) unsigned NOT NULL DEFAULT 0,
`comment_count` int(10) unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `db_prefix_users_username_unique` (`username`),
UNIQUE KEY `db_prefix_users_email_unique` (`email`),
KEY `db_prefix_users_joined_at_index` (`joined_at`),
KEY `db_prefix_users_last_seen_at_index` (`last_seen_at`),
KEY `db_prefix_users_discussion_count_index` (`discussion_count`),
KEY `db_prefix_users_comment_count_index` (`comment_count`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
INSERT INTO `db_prefix_migrations` VALUES (1,'2015_02_24_000000_create_access_tokens_table',NULL);
INSERT INTO `db_prefix_migrations` VALUES (2,'2015_02_24_000000_create_api_keys_table',NULL);
INSERT INTO `db_prefix_migrations` VALUES (3,'2015_02_24_000000_create_config_table',NULL);
INSERT INTO `db_prefix_migrations` VALUES (4,'2015_02_24_000000_create_discussions_table',NULL);
INSERT INTO `db_prefix_migrations` VALUES (5,'2015_02_24_000000_create_email_tokens_table',NULL);
INSERT INTO `db_prefix_migrations` VALUES (6,'2015_02_24_000000_create_groups_table',NULL);
INSERT INTO `db_prefix_migrations` VALUES (7,'2015_02_24_000000_create_notifications_table',NULL);
INSERT INTO `db_prefix_migrations` VALUES (8,'2015_02_24_000000_create_password_tokens_table',NULL);
INSERT INTO `db_prefix_migrations` VALUES (9,'2015_02_24_000000_create_permissions_table',NULL);
INSERT INTO `db_prefix_migrations` VALUES (10,'2015_02_24_000000_create_posts_table',NULL);
INSERT INTO `db_prefix_migrations` VALUES (11,'2015_02_24_000000_create_users_discussions_table',NULL);
INSERT INTO `db_prefix_migrations` VALUES (12,'2015_02_24_000000_create_users_groups_table',NULL);
INSERT INTO `db_prefix_migrations` VALUES (13,'2015_02_24_000000_create_users_table',NULL);
INSERT INTO `db_prefix_migrations` VALUES (14,'2015_09_15_000000_create_auth_tokens_table',NULL);
INSERT INTO `db_prefix_migrations` VALUES (15,'2015_09_20_224327_add_hide_to_discussions',NULL);
INSERT INTO `db_prefix_migrations` VALUES (16,'2015_09_22_030432_rename_notification_read_time',NULL);
INSERT INTO `db_prefix_migrations` VALUES (17,'2015_10_07_130531_rename_config_to_settings',NULL);
INSERT INTO `db_prefix_migrations` VALUES (18,'2015_10_24_194000_add_ip_address_to_posts',NULL);
INSERT INTO `db_prefix_migrations` VALUES (19,'2015_12_05_042721_change_access_tokens_columns',NULL);
INSERT INTO `db_prefix_migrations` VALUES (20,'2015_12_17_194247_change_settings_value_column_to_text',NULL);
INSERT INTO `db_prefix_migrations` VALUES (21,'2016_02_04_095452_add_slug_to_discussions',NULL);
INSERT INTO `db_prefix_migrations` VALUES (22,'2017_04_07_114138_add_is_private_to_discussions',NULL);
INSERT INTO `db_prefix_migrations` VALUES (23,'2017_04_07_114138_add_is_private_to_posts',NULL);
INSERT INTO `db_prefix_migrations` VALUES (24,'2018_01_11_093900_change_access_tokens_columns',NULL);
INSERT INTO `db_prefix_migrations` VALUES (25,'2018_01_11_094000_change_access_tokens_add_foreign_keys',NULL);
INSERT INTO `db_prefix_migrations` VALUES (26,'2018_01_11_095000_change_api_keys_columns',NULL);
INSERT INTO `db_prefix_migrations` VALUES (27,'2018_01_11_101800_rename_auth_tokens_to_registration_tokens',NULL);
INSERT INTO `db_prefix_migrations` VALUES (28,'2018_01_11_102000_change_registration_tokens_rename_id_to_token',NULL);
INSERT INTO `db_prefix_migrations` VALUES (29,'2018_01_11_102100_change_registration_tokens_created_at_to_datetime',NULL);
INSERT INTO `db_prefix_migrations` VALUES (30,'2018_01_11_120604_change_posts_table_to_innodb',NULL);
INSERT INTO `db_prefix_migrations` VALUES (31,'2018_01_11_155200_change_discussions_rename_columns',NULL);
INSERT INTO `db_prefix_migrations` VALUES (32,'2018_01_11_155300_change_discussions_add_foreign_keys',NULL);
INSERT INTO `db_prefix_migrations` VALUES (33,'2018_01_15_071700_rename_users_discussions_to_discussion_user',NULL);
INSERT INTO `db_prefix_migrations` VALUES (34,'2018_01_15_071800_change_discussion_user_rename_columns',NULL);
INSERT INTO `db_prefix_migrations` VALUES (35,'2018_01_15_071900_change_discussion_user_add_foreign_keys',NULL);
INSERT INTO `db_prefix_migrations` VALUES (36,'2018_01_15_072600_change_email_tokens_rename_id_to_token',NULL);
INSERT INTO `db_prefix_migrations` VALUES (37,'2018_01_15_072700_change_email_tokens_add_foreign_keys',NULL);
INSERT INTO `db_prefix_migrations` VALUES (38,'2018_01_15_072800_change_email_tokens_created_at_to_datetime',NULL);
INSERT INTO `db_prefix_migrations` VALUES (39,'2018_01_18_130400_rename_permissions_to_group_permission',NULL);
INSERT INTO `db_prefix_migrations` VALUES (40,'2018_01_18_130500_change_group_permission_add_foreign_keys',NULL);
INSERT INTO `db_prefix_migrations` VALUES (41,'2018_01_18_130600_rename_users_groups_to_group_user',NULL);
INSERT INTO `db_prefix_migrations` VALUES (42,'2018_01_18_130700_change_group_user_add_foreign_keys',NULL);
INSERT INTO `db_prefix_migrations` VALUES (43,'2018_01_18_133000_change_notifications_columns',NULL);
INSERT INTO `db_prefix_migrations` VALUES (44,'2018_01_18_133100_change_notifications_add_foreign_keys',NULL);
INSERT INTO `db_prefix_migrations` VALUES (45,'2018_01_18_134400_change_password_tokens_rename_id_to_token',NULL);
INSERT INTO `db_prefix_migrations` VALUES (46,'2018_01_18_134500_change_password_tokens_add_foreign_keys',NULL);
INSERT INTO `db_prefix_migrations` VALUES (47,'2018_01_18_134600_change_password_tokens_created_at_to_datetime',NULL);
INSERT INTO `db_prefix_migrations` VALUES (48,'2018_01_18_135000_change_posts_rename_columns',NULL);
INSERT INTO `db_prefix_migrations` VALUES (49,'2018_01_18_135100_change_posts_add_foreign_keys',NULL);
INSERT INTO `db_prefix_migrations` VALUES (50,'2018_01_30_112238_add_fulltext_index_to_discussions_title',NULL);
INSERT INTO `db_prefix_migrations` VALUES (51,'2018_01_30_220100_create_post_user_table',NULL);
INSERT INTO `db_prefix_migrations` VALUES (52,'2018_01_30_222900_change_users_rename_columns',NULL);
INSERT INTO `db_prefix_migrations` VALUES (55,'2018_09_15_041340_add_users_indicies',NULL);
INSERT INTO `db_prefix_migrations` VALUES (56,'2018_09_15_041828_add_discussions_indicies',NULL);
INSERT INTO `db_prefix_migrations` VALUES (57,'2018_09_15_043337_add_notifications_indices',NULL);
INSERT INTO `db_prefix_migrations` VALUES (58,'2018_09_15_043621_add_posts_indices',NULL);
INSERT INTO `db_prefix_migrations` VALUES (59,'2018_09_22_004100_change_registration_tokens_columns',NULL);
INSERT INTO `db_prefix_migrations` VALUES (60,'2018_09_22_004200_create_login_providers_table',NULL);
INSERT INTO `db_prefix_migrations` VALUES (61,'2018_10_08_144700_add_shim_prefix_to_group_icons',NULL);
INSERT INTO `db_prefix_migrations` VALUES (62,'2019_10_12_195349_change_posts_add_discussion_foreign_key',NULL);
INSERT INTO `db_prefix_migrations` VALUES (63,'2020_03_19_134512_change_discussions_default_comment_count',NULL);
INSERT INTO `db_prefix_migrations` VALUES (64,'2020_04_21_130500_change_permission_groups_add_is_hidden',NULL);
INSERT INTO `db_prefix_migrations` VALUES (65,'2021_03_02_040000_change_access_tokens_add_type',NULL);
INSERT INTO `db_prefix_migrations` VALUES (66,'2021_03_02_040500_change_access_tokens_add_id',NULL);
INSERT INTO `db_prefix_migrations` VALUES (67,'2021_03_02_041000_change_access_tokens_add_title_ip_agent',NULL);
INSERT INTO `db_prefix_migrations` VALUES (68,'2021_04_18_040500_change_migrations_add_id_primary_key',NULL);
INSERT INTO `db_prefix_migrations` VALUES (69,'2021_04_18_145100_change_posts_content_column_to_mediumtext',NULL);

View File

@@ -0,0 +1,28 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
use Illuminate\Database\Schema\Builder;
return [
'up' => function (Builder $schema) {
$db = $schema->getConnection();
$db->table('migrations')
->whereNull('extension')
->update(['migration' => $db->raw("CONCAT('v0.1/', migration)")]);
},
'down' => function (Builder $schema) {
$db = $schema->getConnection();
$db->table('migrations')
->whereNull('extension')
->update(['migration' => $db->raw("REPLACE('v0.1/', '')")]);
}
];

View File

@@ -0,0 +1,48 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
use Flarum\Post\Post;
use Flarum\User\User;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Schema\Builder;
return [
'up' => function (Builder $schema) {
$schema->create('discussions', function (Blueprint $table) {
$table->increments('id');
$table->string('title', 200);
$table->unsignedInteger('comments_count')->default(0);
$table->unsignedInteger('participants_count')->default(0);
$table->unsignedInteger('post_number_index')->default(0);
$table->dateTime('created_at');
$table->foreignIdFor(User::class, 'user_id')->nullable();
$table->foreignIdFor(Post::class, 'first_post_id')->nullable();
$table->dateTime('last_posted_at')->nullable();
$table->foreignIdFor(User::class, 'last_posted_user_id')->nullable();
$table->foreignIdFor(Post::class, 'last_post_id')->nullable();
$table->unsignedInteger('last_post_number')->nullable();
$table->dateTime('hidden_at')->nullable();
$table->foreignIdFor(User::class, 'hidden_user_id')->nullable();
$table->string('slug', 200);
$table->boolean('is_private')->default(0);
});
$connection = $schema->getConnection();
$prefix = $connection->getTablePrefix();
$connection->statement('ALTER TABLE '.$prefix.'discussions ADD FULLTEXT title (title)');
},
'down' => function (Builder $schema) {
$schema->drop('discussions');
},
];

View File

@@ -0,0 +1,48 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
use Flarum\Discussion\Discussion;
use Flarum\User\User;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Schema\Builder;
// We need a full custom migration here, because we need to add the fulltext
// index for the content with a raw SQL statement after creating the table.
return [
'up' => function (Builder $schema) {
$schema->create('posts', function (Blueprint $table) {
$table->increments('id');
$table->foreignIdFor(Discussion::class, 'discussion_id');
$table->unsignedInteger('number')->nullable();
$table->dateTime('created_at');
$table->foreignIdFor(User::class, 'user_id')->nullable();
$table->string('type', 100)->nullable();
$table->mediumText('content')->nullable();
$table->dateTime('edited_at')->nullable();
$table->foreignIdFor(User::class, 'edited_user_id')->nullable();
$table->dateTime('hidden_at')->nullable();
$table->foreignIdFor(User::class, 'hidden_user_id')->nullable();
$table->string('ip_address', 45)->nullable();
$table->boolean('is_private');
$table->unique(['discussion_id', 'number']);
});
$connection = $schema->getConnection();
$prefix = $connection->getTablePrefix();
$connection->statement('ALTER TABLE '.$prefix.'posts ADD FULLTEXT content (content)');
},
'down' => function (Builder $schema) {
$schema->drop('posts');
}
];

View File

@@ -0,0 +1,19 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
use Flarum\Database\Migration;
use Illuminate\Database\Schema\Blueprint;
return Migration::createTable(
'settings',
function (Blueprint $table) {
$table->string('key', 100)->primary();
$table->binary('value')->nullable();
}
);

View File

@@ -0,0 +1,35 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
use Flarum\Database\Migration;
use Illuminate\Database\Schema\Blueprint;
return Migration::createTable(
'users',
function (Blueprint $table) {
$table->increments('id');
$table->string('username', 100)->unique();
$table->string('email', 150)->unique();
$table->boolean('is_email_confirmed')->default(0);
$table->string('password', 100);
$table->string('avatar_url', 100)->nullable();
$table->text('preferences')->nullable();
$table->dateTime('join_time')->nullable();
$table->dateTime('last_seen_time')->nullable();
$table->dateTime('read_time')->nullable();
$table->dateTime('notification_read_time')->nullable();
$table->integer('discussions_count')->unsigned()->default(0);
$table->integer('comments_count')->unsigned()->default(0);
$table->index('joined_at');
$table->index('last_seen_at');
$table->index('discussion_count');
$table->index('comment_count');
}
);

View File

@@ -64,8 +64,6 @@ class ConsoleServiceProvider extends AbstractServiceProvider
ResetCommand::class, ResetCommand::class,
ScheduleListCommand::class, ScheduleListCommand::class,
ScheduleRunCommand::class ScheduleRunCommand::class
// Used internally to create DB dumps before major releases.
// \Flarum\Database\Console\GenerateDumpCommand::class
]; ];
}); });

View File

@@ -1,87 +0,0 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Database\Console;
use Flarum\Console\AbstractCommand;
use Flarum\Foundation\Paths;
use Illuminate\Database\Connection;
class GenerateDumpCommand extends AbstractCommand
{
/**
* @var Connection
*/
protected $connection;
/**
* @var Paths
*/
protected $paths;
/**
* @param Connection $connection
* @param Paths $paths
*/
public function __construct(Connection $connection, Paths $paths)
{
$this->connection = $connection;
$this->paths = $paths;
parent::__construct();
}
/**
* {@inheritdoc}
*/
protected function configure()
{
$this
->setName('schema:dump')
->setDescription('Dump DB schema');
}
/**
* {@inheritdoc}
*/
protected function fire()
{
$dumpPath = __DIR__.'/../../../migrations/install.dump';
/** @var Connection */
$connection = resolve('db.connection');
$connection
->getSchemaState()
->withMigrationTable($connection->getTablePrefix().'migrations')
->handleOutputUsing(function ($type, $buffer) {
$this->output->write($buffer);
})
->dump($connection, $dumpPath);
// We need to remove any data migrations, as those won't be captured
// in the schema dump, and must be run separately.
$coreDataMigrations = [
'2018_07_21_000000_seed_default_groups',
'2018_07_21_000100_seed_default_group_permissions',
];
$newDump = [];
$dump = file($dumpPath);
foreach ($dump as $line) {
foreach ($coreDataMigrations as $excludeMigrationId) {
if (strpos($line, $excludeMigrationId) !== false) {
continue 2;
}
}
$newDump[] = $line;
}
file_put_contents($dumpPath, implode($newDump));
}
}

View File

@@ -88,6 +88,22 @@ class DatabaseMigrationRepository implements MigrationRepositoryInterface
$query->delete(); $query->delete();
} }
/**
* Create the migration repository data store.
*
* @return void
*/
public function createRepository()
{
$schema = $this->connection->getSchemaBuilder();
$schema->create($this->table, function ($table) {
$table->increments('id');
$table->string('migration');
$table->string('extension')->nullable();
});
}
/** /**
* Determine if the migration repository exists. * Determine if the migration repository exists.
* *

View File

@@ -37,6 +37,13 @@ interface MigrationRepositoryInterface
*/ */
public function delete($file, $extension = null); public function delete($file, $extension = null);
/**
* Create the migration repository data store.
*
* @return void
*/
public function createRepository();
/** /**
* Determine if the migration repository exists. * Determine if the migration repository exists.
* *

View File

@@ -0,0 +1,141 @@
<?php
/*
* This file is part of Flarum.
*
* For detailed copyright and license information, please view the
* LICENSE file that was distributed with this source code.
*/
namespace Flarum\Database;
use Flarum\Extension\Extension;
use Flarum\Foundation\Application;
use Illuminate\Database\ConnectionInterface;
use Illuminate\Support\Str;
class MigrationSourceRepository
{
protected $connection;
public function __construct(ConnectionInterface $connection)
{
$this->connection = $connection;
}
public function flarum(): array
{
if (! $this->databaseVersion()) {
return $this->wrap($this->install());
}
return $this->wrap($this->upgrade());
}
public function extension(Extension $extension): array
{
if (! $extension->hasMigrations()) {
return [];
}
return $this->wrap(glob($extension->getPath().'/migrations/*_*.php'));
}
protected function install(): array
{
// We read every file from the latest major/minor version migrations directory.
// Including the create_<table>_table statements.
$files = glob(__DIR__.'/../../migrations/'.$this->installedVersion(true).'/[0-9_]**.php');
// Sort by timestamp.
sort($files);
// Read and prepend the create_<table>_table statements.
$create = glob(__DIR__.'/../../migrations/'.$this->installedVersion(true).'/create_*_table.php');
return array_merge($create, $files);
}
protected function upgrade(): array
{
$files = [];
$add = false;
$directories = glob(__DIR__.'/../../migrations/*', GLOB_ONLYDIR);
sort($directories, SORT_NATURAL);
// Upgrade
// Loop over all version migrations directory until we find the version that is currently active.
foreach ($directories as $directory) {
$directoryVersion = substr(basename($directory), 1);
// We have found the directory matching the version database version. Start adding files.
if ($directoryVersion === $this->databaseVersion(true)) {
$add = true;
}
if ($add) {
// Selectively add files, but only include those matching the format YYYY_MM_DD_HHIISS_<something>.php
// This excludes the create_<table>_table.
$files = array_merge($files, glob(realpath($directory).'/[0-9_]**.php'));
}
// Once we found the version that is installed, we can quit.
// Theoretically this should never be necessary, it could just loop over all remaining ones.
if ($directoryVersion === $this->installedVersion(true)) {
break;
}
}
// Sort by timestamp.
sort($files);
return $files;
}
protected function shortVersion(string $version): string
{
if (preg_match('~(?<version>^[0-9]+\.[0-9]+)~', $version, $m)) {
return $m['version'];
}
return $version;
}
protected function installedVersion(bool $short = false): string
{
$version = Application::VERSION;
if ($short && $version) {
return $this->shortVersion($version);
}
return $version;
}
protected function databaseVersion(bool $short = false): ?string
{
$version = $this->connection->getSchemaBuilder()->hasTable('settings')
? $this->connection->table('settings')->where('key', 'version')->value('value')
: null;
if ($short && $version) {
return $this->shortVersion($version);
}
return $version;
}
protected function wrap(array $migrations): array
{
return collect($migrations)
->mapWithKeys(function (string $path) {
$path = realpath($path);
$path = Str::after($path, 'migrations/');
$basename = Str::before($path, '.php');
return [$path => $basename];
})
->toArray();
}
}

View File

@@ -12,9 +12,8 @@ namespace Flarum\Database;
use Exception; use Exception;
use Flarum\Extension\Extension; use Flarum\Extension\Extension;
use Illuminate\Database\ConnectionInterface; use Illuminate\Database\ConnectionInterface;
use Illuminate\Database\MySqlConnection; use Illuminate\Database\Schema\Builder;
use Illuminate\Filesystem\Filesystem; use Illuminate\Filesystem\Filesystem;
use InvalidArgumentException;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
/** /**
@@ -36,6 +35,13 @@ class Migrator
*/ */
protected $files; protected $files;
/**
* The database schema builder instance.
*
* @var Builder
*/
protected $schemaBuilder;
/** /**
* The output interface implementation. * The output interface implementation.
* *
@@ -43,9 +49,9 @@ class Migrator
*/ */
protected $output; protected $output;
/** /**
* @var ConnectionInterface|MySqlConnection * @var MigrationSourceRepository
*/ */
protected $connection; protected $source;
/** /**
* Create a new migrator instance. * Create a new migrator instance.
@@ -62,11 +68,8 @@ class Migrator
$this->files = $files; $this->files = $files;
$this->repository = $repository; $this->repository = $repository;
if (! ($connection instanceof MySqlConnection)) { $this->source = new MigrationSourceRepository($connection);
throw new InvalidArgumentException('Only MySQL connections are supported'); $this->schemaBuilder = $connection->getSchemaBuilder();
}
$this->connection = $connection;
// Workaround for https://github.com/laravel/framework/issues/1186 // Workaround for https://github.com/laravel/framework/issues/1186
$connection->getDoctrineSchemaManager()->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'string'); $connection->getDoctrineSchemaManager()->getDatabasePlatform()->registerDoctrineTypeMapping('enum', 'string');
@@ -75,13 +78,13 @@ class Migrator
/** /**
* Run the outstanding migrations at a given path. * Run the outstanding migrations at a given path.
* *
* @param string $path * @param string $path
* @param Extension $extension * @param Extension|null $extension
* @return void * @return void
*/ */
public function run($path, Extension $extension = null) public function run(string $path, Extension $extension = null)
{ {
$files = $this->getMigrationFiles($path); $files = $this->getMigrationFiles($extension);
$ran = $this->repository->getRan($extension ? $extension->getId() : null); $ran = $this->repository->getRan($extension ? $extension->getId() : null);
@@ -93,12 +96,12 @@ class Migrator
/** /**
* Run an array of migrations. * Run an array of migrations.
* *
* @param string $path * @param string $path
* @param array $migrations * @param array $migrations
* @param Extension $extension * @param Extension|null $extension
* @return void * @return void
*/ */
public function runMigrationList($path, $migrations, Extension $extension = null) public function runMigrationList(string $path, array $migrations, Extension $extension = null)
{ {
// First we will just make sure that there are any migrations to run. If there // First we will just make sure that there are any migrations to run. If there
// aren't, we will just make a note of it to the developer so they're aware // aren't, we will just make a note of it to the developer so they're aware
@@ -120,13 +123,13 @@ class Migrator
/** /**
* Run "up" a migration instance. * Run "up" a migration instance.
* *
* @param string $path * @param string $path
* @param string $file * @param string $file
* @param string $path * @param Extension|null $extension
* @param Extension $extension
* @return void * @return void
* @throws Exception
*/ */
protected function runUp($path, $file, Extension $extension = null) protected function runUp(string $path, string $file, Extension $extension = null)
{ {
$migration = $this->resolve($path, $file); $migration = $this->resolve($path, $file);
@@ -199,36 +202,15 @@ class Migrator
protected function runClosureMigration($migration, $direction = 'up') protected function runClosureMigration($migration, $direction = 'up')
{ {
if (is_array($migration) && array_key_exists($direction, $migration)) { if (is_array($migration) && array_key_exists($direction, $migration)) {
call_user_func($migration[$direction], $this->connection->getSchemaBuilder()); call_user_func($migration[$direction], $this->schemaBuilder);
} else { } else {
throw new Exception('Migration file should contain an array with up/down.'); throw new Exception('Migration file should contain an array with up/down.');
} }
} }
/** public function getMigrationFiles(Extension $extension = null): array
* Get all of the migration files in a given path.
*
* @param string $path
* @return array
*/
public function getMigrationFiles($path)
{ {
$files = $this->files->glob($path.'/*_*.php'); return $extension ? $this->source->extension($extension) : $this->source->flarum();
if ($files === false) {
return [];
}
$files = array_map(function ($file) {
return str_replace('.php', '', basename($file));
}, $files);
// Once we have all of the formatted file names we will sort them and since
// they all start with a timestamp this should give us the migrations in
// the order they were actually created by the application developers.
sort($files);
return $files;
} }
/** /**
@@ -247,42 +229,6 @@ class Migrator
} }
} }
/**
* Initialize the Flarum database from a schema dump.
*
* @param string $path to the directory containing the dump.
*/
public function installFromSchema(string $path)
{
$schemaPath = "$path/install.dump";
$startTime = microtime(true);
$dump = file_get_contents($schemaPath);
$this->connection->getSchemaBuilder()->disableForeignKeyConstraints();
foreach (explode(';', $dump) as $statement) {
$statement = trim($statement);
if (empty($statement) || substr($statement, 0, 2) === '/*') {
continue;
}
$statement = str_replace(
'db_prefix_',
$this->connection->getTablePrefix(),
$statement
);
$this->connection->statement($statement);
}
$this->connection->getSchemaBuilder()->enableForeignKeyConstraints();
$runTime = number_format((microtime(true) - $startTime) * 1000, 2);
$this->note('<info>Loaded stored database schema.</info> ('.$runTime.'ms)');
}
/** /**
* Set the output implementation that should be used by the console. * Set the output implementation that should be used by the console.
* *
@@ -309,6 +255,16 @@ class Migrator
} }
} }
/**
* Get the migration repository instance.
*
* @return MigrationRepositoryInterface
*/
public function getRepository()
{
return $this->repository;
}
/** /**
* Determine if the migration repository exists. * Determine if the migration repository exists.
* *
@@ -318,4 +274,14 @@ class Migrator
{ {
return $this->repository->repositoryExists(); return $this->repository->repositoryExists();
} }
/**
* Get the file system instance.
*
* @return \Illuminate\Filesystem\Filesystem
*/
public function getFilesystem()
{
return $this->files;
}
} }

View File

@@ -459,20 +459,7 @@ class Extension implements Arrayable
} }
} }
/** public function migrate(Migrator $migrator, string $direction)
* Tests whether the extension has migrations.
*
* @return bool
*/
public function hasMigrations()
{
return realpath($this->path.'/migrations/') !== false;
}
/**
* @internal
*/
public function migrate(Migrator $migrator, $direction = 'up')
{ {
if (! $this->hasMigrations()) { if (! $this->hasMigrations()) {
return; return;
@@ -485,6 +472,16 @@ class Extension implements Arrayable
} }
} }
/**
* Tests whether the extension has migrations.
*
* @return bool
*/
public function hasMigrations()
{
return realpath($this->path.'/migrations/') !== false;
}
/** /**
* Generates an array result for the object. * Generates an array result for the object.
* *

View File

@@ -35,16 +35,16 @@ class FilesystemManager extends LaravelFilesystemManager
/** /**
* @inheritDoc * @inheritDoc
*/ */
protected function resolve($name, $config = null): Filesystem protected function resolve($name): Filesystem
{ {
$localConfig = $config ?? $this->getLocalConfig($name); $driver = $this->getDriver($name);
$localConfig = $this->getLocalConfig($name);
if (empty($localConfig)) { if (empty($localConfig)) {
throw new InvalidArgumentException("Disk [{$name}] has not been declared. Use the Filesystem extender to do this."); throw new InvalidArgumentException("Disk [{$name}] has not been declared. Use the Filesystem extender to do this.");
} }
$driver = $config['driver'] ?? $this->getDriver($name);
if ($driver === 'local') { if ($driver === 'local') {
return $this->createLocalDriver($localConfig); return $this->createLocalDriver($localConfig);
} }

View File

@@ -21,7 +21,7 @@ class Application
* *
* @var string * @var string
*/ */
const VERSION = '1.0.4-dev'; const VERSION = '1.0.1-dev';
/** /**
* The IoC container for the Flarum application. * The IoC container for the Flarum application.

View File

@@ -48,7 +48,7 @@ class InstalledApp implements AppInterface
public function getRequestHandler() public function getRequestHandler()
{ {
if ($this->config->inMaintenanceMode()) { if ($this->config->inMaintenanceMode()) {
return $this->container->make('flarum.maintenance.handler'); return new MaintenanceModeHandler();
} elseif ($this->needsUpdate()) { } elseif ($this->needsUpdate()) {
return $this->getUpdaterHandler(); return $this->getUpdaterHandler();
} }

Some files were not shown because too many files have changed in this diff Show More