feat: misc additions

- Detect extensions that didn't update between updates
- Add composer why not command where approriate (when extension didn't update, when major update failed)
- Detect incompatible extensions in major update failure and show the extensions in the frontend
- Create last update run setting value which holds the state of the latest update runs
- Other fixes
This commit is contained in:
SychO9 2021-11-23 23:02:56 +01:00
parent c8b8dacb67
commit f4bb8158ef
31 changed files with 1877 additions and 1007 deletions

View File

@ -17,6 +17,8 @@ use Flarum\PackageManager\Exception\ExceptionHandler;
use Flarum\PackageManager\Exception\ComposerRequireFailedException;
use Flarum\PackageManager\Exception\ComposerUpdateFailedException;
use Flarum\PackageManager\Exception\MajorUpdateFailedException;
use Flarum\PackageManager\Settings\LastUpdateCheck;
use Flarum\PackageManager\Settings\LastUpdateRun;
return [
(new Extend\Routes('api'))
@ -24,6 +26,7 @@ return [
->patch('/package-manager/extensions/{id}', 'package-manager.extensions.update', Api\Controller\UpdateExtensionController::class)
->delete('/package-manager/extensions/{id}', 'package-manager.extensions.remove', Api\Controller\RemoveExtensionController::class)
->post('/package-manager/check-for-updates', 'package-manager.check-for-updates', Api\Controller\CheckForUpdatesController::class)
->post('/package-manager/why-not', 'package-manager.why-not', Api\Controller\WhyNotController::class)
->post('/package-manager/minor-update', 'package-manager.minor-update', Api\Controller\MinorUpdateController::class)
->post('/package-manager/major-update', 'package-manager.major-update', Api\Controller\MajorUpdateController::class)
->post('/package-manager/global-update', 'package-manager.global-update', Api\Controller\GlobalUpdateController::class),
@ -38,19 +41,13 @@ return [
&& is_writable($paths->storage.'/.composer')
&& is_writable($paths->base.'/composer.json')
&& is_writable($paths->base.'/composer.lock');
$document->payload['lastUpdateCheck'] = resolve(LastUpdateCheck::class)->get();
}),
new Extend\Locales(__DIR__ . '/locale'),
(new Extend\Settings())
->default('flarum-package-manager.last_update_check', json_encode([
'checkedAt' => null,
'updates' => [
'installed' => [],
],
])),
->default(LastUpdateCheck::key(), json_encode(LastUpdateCheck::default()))
->default(LastUpdateRun::key(), json_encode(LastUpdateRun::default())),
(new Extend\ServiceProvider)
->register(PackageManagerServiceProvider::class),

View File

@ -101,6 +101,34 @@ __webpack_require__.r(__webpack_exports__);
/***/ }),
/***/ "./node_modules/@babel/runtime/helpers/esm/createClass.js":
/*!****************************************************************!*\
!*** ./node_modules/@babel/runtime/helpers/esm/createClass.js ***!
\****************************************************************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return _createClass; });
function _defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
return Constructor;
}
/***/ }),
/***/ "./node_modules/@babel/runtime/helpers/esm/inheritsLoose.js":
/*!******************************************************************!*\
!*** ./node_modules/@babel/runtime/helpers/esm/inheritsLoose.js ***!
@ -140,6 +168,114 @@ function _setPrototypeOf(o, p) {
return _setPrototypeOf(o, p);
}
/***/ }),
/***/ "./src/admin/components/ExtensionItem.tsx":
/*!************************************************!*\
!*** ./src/admin/components/ExtensionItem.tsx ***!
\************************************************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return ExtensionItem; });
/* harmony import */ var _babel_runtime_helpers_esm_inheritsLoose__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babel/runtime/helpers/esm/inheritsLoose */ "./node_modules/@babel/runtime/helpers/esm/inheritsLoose.js");
/* harmony import */ var flarum_admin_app__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! flarum/admin/app */ "flarum/admin/app");
/* harmony import */ var flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(flarum_admin_app__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var flarum_common_Component__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! flarum/common/Component */ "flarum/common/Component");
/* harmony import */ var flarum_common_Component__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(flarum_common_Component__WEBPACK_IMPORTED_MODULE_2__);
/* harmony import */ var flarum_common_utils_classList__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! flarum/common/utils/classList */ "flarum/common/utils/classList");
/* harmony import */ var flarum_common_utils_classList__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(flarum_common_utils_classList__WEBPACK_IMPORTED_MODULE_3__);
/* harmony import */ var flarum_common_helpers_icon__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! flarum/common/helpers/icon */ "flarum/common/helpers/icon");
/* harmony import */ var flarum_common_helpers_icon__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(flarum_common_helpers_icon__WEBPACK_IMPORTED_MODULE_4__);
/* harmony import */ var flarum_common_components_Tooltip__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! flarum/common/components/Tooltip */ "flarum/common/components/Tooltip");
/* harmony import */ var flarum_common_components_Tooltip__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(flarum_common_components_Tooltip__WEBPACK_IMPORTED_MODULE_5__);
/* harmony import */ var flarum_common_components_Button__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! flarum/common/components/Button */ "flarum/common/components/Button");
/* harmony import */ var flarum_common_components_Button__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(flarum_common_components_Button__WEBPACK_IMPORTED_MODULE_6__);
/* harmony import */ var _WhyNotModal__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./WhyNotModal */ "./src/admin/components/WhyNotModal.tsx");
/*
* @todo fix in core
*/
var ExtensionItem = /*#__PURE__*/function (_Component) {
Object(_babel_runtime_helpers_esm_inheritsLoose__WEBPACK_IMPORTED_MODULE_0__["default"])(ExtensionItem, _Component);
function ExtensionItem() {
return _Component.apply(this, arguments) || this;
}
var _proto = ExtensionItem.prototype;
_proto.view = function view(vnode) {
var _this$attrs = this.attrs,
extension = _this$attrs.extension,
updates = _this$attrs.updates,
onClickUpdate = _this$attrs.onClickUpdate,
whyNotWarning = _this$attrs.whyNotWarning,
isCore = _this$attrs.isCore,
isDanger = _this$attrs.isDanger;
return m("div", {
className: flarum_common_utils_classList__WEBPACK_IMPORTED_MODULE_3___default()({
'PackageManager-extension': true,
'PackageManager-extension--core': isCore,
'PackageManager-extension--danger': isDanger
})
}, m("div", {
className: "PackageManager-extension-icon ExtensionIcon",
style: extension.icon
}, extension.icon ? flarum_common_helpers_icon__WEBPACK_IMPORTED_MODULE_4___default()(extension.icon.name) : ''), m("div", {
className: "PackageManager-extension-info"
}, m("div", {
className: "PackageManager-extension-name"
}, extension.extra['flarum-extension'].title), m("div", {
className: "PackageManager-extension-version"
}, m("span", {
className: "PackageManager-extension-version-current"
}, this.version(extension.version)), updates['latest-minor'] ? m("span", {
className: "PackageManager-extension-version-latest PackageManager-extension-version-latest--minor"
}, this.version(updates['latest-minor'])) : null, updates['latest-major'] && !isCore ? m("span", {
className: "PackageManager-extension-version-latest PackageManager-extension-version-latest--major"
}, this.version(updates['latest-major'])) : null)), m("div", {
className: "PackageManager-extension-controls"
}, onClickUpdate ? m(flarum_common_components_Tooltip__WEBPACK_IMPORTED_MODULE_5___default.a, {
text: flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.translator.trans('flarum-package-manager.admin.extensions.update')
}, m(flarum_common_components_Button__WEBPACK_IMPORTED_MODULE_6___default.a, {
icon: "fas fa-arrow-alt-circle-up",
className: "Button Button--icon Button--flat",
onclick: onClickUpdate,
"aria-label": flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.translator.trans('flarum-package-manager.admin.extensions.update')
})) : null, whyNotWarning ? m(flarum_common_components_Tooltip__WEBPACK_IMPORTED_MODULE_5___default.a, {
text: flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.translator.trans('flarum-package-manager.admin.extensions.check_why_it_failed_updating')
}, m(flarum_common_components_Button__WEBPACK_IMPORTED_MODULE_6___default.a, {
icon: "fas fa-exclamation-circle",
className: "Button Button--icon Button--flat Button--danger",
onclick: function onclick() {
return flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.modal.show(_WhyNotModal__WEBPACK_IMPORTED_MODULE_7__["default"], {
"package": extension.name
});
},
"aria-label": flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.translator.trans('flarum-package-manager.admin.extensions.check_why_it_failed_updating')
})) : null));
};
_proto.version = function version(v) {
return 'v' + v.replace('v', '');
};
return ExtensionItem;
}(flarum_common_Component__WEBPACK_IMPORTED_MODULE_2___default.a);
/***/ }),
/***/ "./src/admin/components/Installer.tsx":
@ -284,6 +420,13 @@ __webpack_require__.r(__webpack_exports__);
/* harmony import */ var flarum_admin_components_LoadingModal__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! flarum/admin/components/LoadingModal */ "flarum/admin/components/LoadingModal");
/* harmony import */ var flarum_admin_components_LoadingModal__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(flarum_admin_components_LoadingModal__WEBPACK_IMPORTED_MODULE_5__);
/* harmony import */ var _utils_errorHandler__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ../utils/errorHandler */ "./src/admin/utils/errorHandler.ts");
/* harmony import */ var flarum_common_components_Alert__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! flarum/common/components/Alert */ "flarum/common/components/Alert");
/* harmony import */ var flarum_common_components_Alert__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(flarum_common_components_Alert__WEBPACK_IMPORTED_MODULE_7__);
/* harmony import */ var _WhyNotModal__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./WhyNotModal */ "./src/admin/components/WhyNotModal.tsx");
/* harmony import */ var _ExtensionItem__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./ExtensionItem */ "./src/admin/components/ExtensionItem.tsx");
@ -304,14 +447,22 @@ var MajorUpdater = /*#__PURE__*/function (_Component) {
_this = _Component.call.apply(_Component, [this].concat(args)) || this;
_this.isLoading = null;
_this.updateState = void 0;
return _this;
}
var _proto = MajorUpdater.prototype;
_proto.oninit = function oninit(vnode) {
_Component.prototype.oninit.call(this, vnode);
this.updateState = this.attrs.updateState;
};
_proto.view = function view(vnode) {
// @todo move Form-group--danger class to core for reuse
return m("div", {
className: "Form-group PackageManager-majorUpdate"
className: "Form-group Form-group--danger PackageManager-majorUpdate"
}, m("img", {
alt: "flarum logo",
src: flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.forum.attribute('baseUrl') + '/assets/extensions/flarum-package-manager/flarum.svg'
@ -328,10 +479,34 @@ var MajorUpdater = /*#__PURE__*/function (_Component) {
icon: "fas fa-vial",
onclick: this.update.bind(this, true)
}, flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.translator.trans('flarum-package-manager.admin.major_updater.dry_run'))), m(flarum_common_components_Button__WEBPACK_IMPORTED_MODULE_3___default.a, {
className: "Button",
className: "Button Button--danger",
icon: "fas fa-play",
onclick: this.update.bind(this, false)
}, flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.translator.trans('flarum-package-manager.admin.major_updater.update'))));
}, flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.translator.trans('flarum-package-manager.admin.major_updater.update'))), this.updateState.incompatibleExtensions.length ? m("div", {
className: "PackageManager-majorUpdate-incompatibleExtensions PackageManager-extensions-grid"
}, this.updateState.incompatibleExtensions.map(function (extension) {
return m(_ExtensionItem__WEBPACK_IMPORTED_MODULE_9__["default"], {
extension: flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.data.extensions[extension.replace('flarum-', '').replace('flarum-ext-', '').replace('/', '-')],
updates: {},
onClickUpdate: null,
isDanger: true
});
})) : null, this.updateState.status === 'failure' ? m(flarum_common_components_Alert__WEBPACK_IMPORTED_MODULE_7___default.a, {
type: "error",
className: "PackageManager-majorUpdate-failure",
dismissible: false,
controls: [m(flarum_common_components_Button__WEBPACK_IMPORTED_MODULE_3___default.a, {
className: "Button Button--text PackageManager-majorUpdate-failure-details",
icon: "fas fa-question-circle",
onclick: function onclick() {
return flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.modal.show(_WhyNotModal__WEBPACK_IMPORTED_MODULE_8__["default"], {
"package": 'flarum/core'
});
}
}, flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.translator.trans('flarum-package-manager.admin.major_updater.failure.why'))]
}, m("p", {
className: "PackageManager-majorUpdate-failure-desc"
}, flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.translator.trans('flarum-package-manager.admin.major_updater.failure.desc'))) : null);
};
_proto.update = function update(dryRun) {
@ -353,6 +528,12 @@ var MajorUpdater = /*#__PURE__*/function (_Component) {
type: 'success'
}, flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.translator.trans('flarum-package-manager.admin.update_successful'));
window.location.reload();
})["catch"](function (e) {
var _e$response, _e$response$errors, _e$response$errors$po;
flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.modal.close();
_this2.updateState.status = 'failure';
_this2.updateState.incompatibleExtensions = (_e$response = e.response) == null ? void 0 : (_e$response$errors = _e$response.errors) == null ? void 0 : (_e$response$errors$po = _e$response$errors.pop()) == null ? void 0 : _e$response$errors$po.incompatible_extensions;
})["finally"](function () {
_this2.isLoading = null;
m.redraw();
@ -376,28 +557,23 @@ var MajorUpdater = /*#__PURE__*/function (_Component) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return Updater; });
/* harmony import */ var _babel_runtime_helpers_esm_inheritsLoose__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babel/runtime/helpers/esm/inheritsLoose */ "./node_modules/@babel/runtime/helpers/esm/inheritsLoose.js");
/* harmony import */ var flarum_admin_app__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! flarum/admin/app */ "flarum/admin/app");
/* harmony import */ var flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(flarum_admin_app__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var flarum_common_Component__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! flarum/common/Component */ "flarum/common/Component");
/* harmony import */ var flarum_common_Component__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(flarum_common_Component__WEBPACK_IMPORTED_MODULE_2__);
/* harmony import */ var flarum_common_helpers_icon__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! flarum/common/helpers/icon */ "flarum/common/helpers/icon");
/* harmony import */ var flarum_common_helpers_icon__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(flarum_common_helpers_icon__WEBPACK_IMPORTED_MODULE_3__);
/* harmony import */ var _babel_runtime_helpers_esm_createClass__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babel/runtime/helpers/esm/createClass */ "./node_modules/@babel/runtime/helpers/esm/createClass.js");
/* harmony import */ var _babel_runtime_helpers_esm_inheritsLoose__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @babel/runtime/helpers/esm/inheritsLoose */ "./node_modules/@babel/runtime/helpers/esm/inheritsLoose.js");
/* harmony import */ var flarum_admin_app__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! flarum/admin/app */ "flarum/admin/app");
/* harmony import */ var flarum_admin_app__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(flarum_admin_app__WEBPACK_IMPORTED_MODULE_2__);
/* harmony import */ var flarum_common_Component__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! flarum/common/Component */ "flarum/common/Component");
/* harmony import */ var flarum_common_Component__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(flarum_common_Component__WEBPACK_IMPORTED_MODULE_3__);
/* harmony import */ var flarum_common_components_Button__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! flarum/common/components/Button */ "flarum/common/components/Button");
/* harmony import */ var flarum_common_components_Button__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(flarum_common_components_Button__WEBPACK_IMPORTED_MODULE_4__);
/* harmony import */ var flarum_common_helpers_humanTime__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! flarum/common/helpers/humanTime */ "flarum/common/helpers/humanTime");
/* harmony import */ var flarum_common_helpers_humanTime__WEBPACK_IMPORTED_MODULE_5___default = /*#__PURE__*/__webpack_require__.n(flarum_common_helpers_humanTime__WEBPACK_IMPORTED_MODULE_5__);
/* harmony import */ var flarum_admin_components_LoadingModal__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! flarum/admin/components/LoadingModal */ "flarum/admin/components/LoadingModal");
/* harmony import */ var flarum_admin_components_LoadingModal__WEBPACK_IMPORTED_MODULE_6___default = /*#__PURE__*/__webpack_require__.n(flarum_admin_components_LoadingModal__WEBPACK_IMPORTED_MODULE_6__);
/* harmony import */ var flarum_common_components_Tooltip__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! flarum/common/components/Tooltip */ "flarum/common/components/Tooltip");
/* harmony import */ var flarum_common_components_Tooltip__WEBPACK_IMPORTED_MODULE_7___default = /*#__PURE__*/__webpack_require__.n(flarum_common_components_Tooltip__WEBPACK_IMPORTED_MODULE_7__);
/* harmony import */ var _utils_errorHandler__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ../utils/errorHandler */ "./src/admin/utils/errorHandler.ts");
/* harmony import */ var flarum_common_utils_classList__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! flarum/common/utils/classList */ "flarum/common/utils/classList");
/* harmony import */ var flarum_common_utils_classList__WEBPACK_IMPORTED_MODULE_9___default = /*#__PURE__*/__webpack_require__.n(flarum_common_utils_classList__WEBPACK_IMPORTED_MODULE_9__);
/* harmony import */ var flarum_common_components_LoadingIndicator__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! flarum/common/components/LoadingIndicator */ "flarum/common/components/LoadingIndicator");
/* harmony import */ var flarum_common_components_LoadingIndicator__WEBPACK_IMPORTED_MODULE_10___default = /*#__PURE__*/__webpack_require__.n(flarum_common_components_LoadingIndicator__WEBPACK_IMPORTED_MODULE_10__);
/* harmony import */ var _MajorUpdater__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./MajorUpdater */ "./src/admin/components/MajorUpdater.tsx");
/* harmony import */ var _utils_errorHandler__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ../utils/errorHandler */ "./src/admin/utils/errorHandler.ts");
/* harmony import */ var flarum_common_components_LoadingIndicator__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! flarum/common/components/LoadingIndicator */ "flarum/common/components/LoadingIndicator");
/* harmony import */ var flarum_common_components_LoadingIndicator__WEBPACK_IMPORTED_MODULE_8___default = /*#__PURE__*/__webpack_require__.n(flarum_common_components_LoadingIndicator__WEBPACK_IMPORTED_MODULE_8__);
/* harmony import */ var _MajorUpdater__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./MajorUpdater */ "./src/admin/components/MajorUpdater.tsx");
/* harmony import */ var _ExtensionItem__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./ExtensionItem */ "./src/admin/components/ExtensionItem.tsx");
@ -411,7 +587,7 @@ __webpack_require__.r(__webpack_exports__);
var Updater = /*#__PURE__*/function (_Component) {
Object(_babel_runtime_helpers_esm_inheritsLoose__WEBPACK_IMPORTED_MODULE_0__["default"])(Updater, _Component);
Object(_babel_runtime_helpers_esm_inheritsLoose__WEBPACK_IMPORTED_MODULE_1__["default"])(Updater, _Component);
function Updater() {
var _this;
@ -422,8 +598,8 @@ var Updater = /*#__PURE__*/function (_Component) {
_this = _Component.call.apply(_Component, [this].concat(args)) || this;
_this.isLoading = null;
_this.lastUpdateCheck = flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.data.lastUpdateCheck || {};
_this.packageUpdates = {};
_this.lastUpdateCheck = JSON.parse(flarum_admin_app__WEBPACK_IMPORTED_MODULE_2___default.a.data.settings['flarum-package-manager.last_update_check']);
return _this;
}
@ -439,35 +615,35 @@ var Updater = /*#__PURE__*/function (_Component) {
var extensions = this.getExtensionUpdates();
var coreUpdate = this.getCoreUpdate();
var core = null;
var core;
if (coreUpdate) {
core = {
id: "flarum-core",
version: flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.data.settings.version,
id: 'flarum-core',
name: 'flarum/core',
version: flarum_admin_app__WEBPACK_IMPORTED_MODULE_2___default.a.data.settings.version,
icon: {
backgroundImage: "url(" + flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.forum.attribute('baseUrl') + "/assets/extensions/flarum-package-manager/flarum.svg"
backgroundImage: "url(" + flarum_admin_app__WEBPACK_IMPORTED_MODULE_2___default.a.forum.attribute('baseUrl') + "/assets/extensions/flarum-package-manager/flarum.svg"
},
extra: {
'flarum-extension': {
title: flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.translator.trans('flarum-package-manager.admin.updater.flarum')
title: flarum_admin_app__WEBPACK_IMPORTED_MODULE_2___default.a.translator.trans('flarum-package-manager.admin.updater.flarum')
}
}
};
this.packageUpdates['flarum-core'] = coreUpdate;
}
return [m("div", {
className: "Form-group"
}, m("label", null, flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.translator.trans('flarum-package-manager.admin.updater.updater_title')), m("p", {
}, m("label", null, flarum_admin_app__WEBPACK_IMPORTED_MODULE_2___default.a.translator.trans('flarum-package-manager.admin.updater.updater_title')), m("p", {
className: "helpText"
}, flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.translator.trans('flarum-package-manager.admin.updater.updater_help')), Object.keys(this.lastUpdateCheck).length ? m("p", {
}, flarum_admin_app__WEBPACK_IMPORTED_MODULE_2___default.a.translator.trans('flarum-package-manager.admin.updater.updater_help')), ((_this$lastUpdateCheck = this.lastUpdateCheck) == null ? void 0 : _this$lastUpdateCheck.checkedAt) && m("p", {
className: "PackageManager-lastUpdatedAt"
}, m("span", {
className: "PackageManager-lastUpdatedAt-label"
}, flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.translator.trans('flarum-package-manager.admin.updater.last_update_checked_at')), m("span", {
}, flarum_admin_app__WEBPACK_IMPORTED_MODULE_2___default.a.translator.trans('flarum-package-manager.admin.updater.last_update_checked_at')), m("span", {
className: "PackageManager-lastUpdatedAt-value"
}, flarum_common_helpers_humanTime__WEBPACK_IMPORTED_MODULE_5___default()((_this$lastUpdateCheck = this.lastUpdateCheck) == null ? void 0 : _this$lastUpdateCheck.checkedAt))) : null, m("div", {
}, flarum_common_helpers_humanTime__WEBPACK_IMPORTED_MODULE_5___default()(this.lastUpdateCheck.checkedAt))), m("div", {
className: "PackageManager-updaterControls"
}, m(flarum_common_components_Button__WEBPACK_IMPORTED_MODULE_4___default.a, {
className: "Button",
@ -475,66 +651,37 @@ var Updater = /*#__PURE__*/function (_Component) {
onclick: this.checkForUpdates.bind(this),
loading: this.isLoading === 'check',
disabled: this.isLoading !== null && this.isLoading !== 'check'
}, flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.translator.trans('flarum-package-manager.admin.updater.check_for_updates')), m(flarum_common_components_Button__WEBPACK_IMPORTED_MODULE_4___default.a, {
}, flarum_admin_app__WEBPACK_IMPORTED_MODULE_2___default.a.translator.trans('flarum-package-manager.admin.updater.check_for_updates')), m(flarum_common_components_Button__WEBPACK_IMPORTED_MODULE_4___default.a, {
className: "Button",
icon: "fas fa-play",
onclick: this.updateGlobally.bind(this),
loading: this.isLoading === 'global-update',
disabled: this.isLoading !== null && this.isLoading !== 'global-update'
}, flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.translator.trans('flarum-package-manager.admin.updater.run_global_update'))), this.isLoading !== null ? m("div", {
}, flarum_admin_app__WEBPACK_IMPORTED_MODULE_2___default.a.translator.trans('flarum-package-manager.admin.updater.run_global_update'))), this.isLoading !== null ? m("div", {
className: "PackageManager-extensions"
}, m(flarum_common_components_LoadingIndicator__WEBPACK_IMPORTED_MODULE_10___default.a, null)) : extensions.length || core ? m("div", {
}, m(flarum_common_components_LoadingIndicator__WEBPACK_IMPORTED_MODULE_8___default.a, null)) : extensions.length || core ? m("div", {
className: "PackageManager-extensions"
}, m("div", {
className: "PackageManager-extensions-grid"
}, core ? this.extensionItem(core, true) : null, extensions.map(function (extension) {
return _this2.extensionItem(extension);
}))) : null), coreUpdate && coreUpdate['latest-major'] ? m(_MajorUpdater__WEBPACK_IMPORTED_MODULE_11__["default"], {
coreUpdate: coreUpdate
}, core ? m(_ExtensionItem__WEBPACK_IMPORTED_MODULE_10__["default"], {
extension: core,
updates: coreUpdate,
isCore: true,
onClickUpdate: this.updateCoreMinor.bind(this),
whyNotWarning: this.lastUpdateRun.limitedPackages().includes('flarum/core')
}) : null, extensions.map(function (extension) {
return m(_ExtensionItem__WEBPACK_IMPORTED_MODULE_10__["default"], {
extension: extension,
updates: _this2.packageUpdates[extension.id],
onClickUpdate: _this2.updateExtension.bind(_this2, extension),
whyNotWarning: _this2.lastUpdateRun.limitedPackages().includes(extension.name)
});
}))) : null), coreUpdate && coreUpdate['latest-major'] ? m(_MajorUpdater__WEBPACK_IMPORTED_MODULE_9__["default"], {
coreUpdate: coreUpdate,
updateState: this.lastUpdateRun.major
}) : null];
};
_proto.extensionItem = function extensionItem(extension, isCore) {
if (isCore === void 0) {
isCore = false;
}
return m("div", {
className: flarum_common_utils_classList__WEBPACK_IMPORTED_MODULE_9___default()({
'PackageManager-extension': true,
'PackageManager-extension--core': isCore
})
}, m("div", {
className: "PackageManager-extension-icon ExtensionIcon",
style: extension.icon
}, extension.icon ? flarum_common_helpers_icon__WEBPACK_IMPORTED_MODULE_3___default()(extension.icon.name) : ''), m("div", {
className: "PackageManager-extension-info"
}, m("div", {
className: "PackageManager-extension-name"
}, extension.extra['flarum-extension'].title), m("div", {
className: "PackageManager-extension-version"
}, m("span", {
className: "PackageManager-extension-version-current"
}, this.version(extension.version)), this.packageUpdates[extension.id]['latest-minor'] ? m("span", {
className: "PackageManager-extension-version-latest PackageManager-extension-version-latest--minor"
}, this.version(this.packageUpdates[extension.id]['latest-minor'])) : null, this.packageUpdates[extension.id]['latest-major'] && !isCore ? m("span", {
className: "PackageManager-extension-version-latest PackageManager-extension-version-latest--major"
}, this.version(this.packageUpdates[extension.id]['latest-major'])) : null)), m("div", {
className: "PackageManager-extension-controls"
}, m(flarum_common_components_Tooltip__WEBPACK_IMPORTED_MODULE_7___default.a, {
text: flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.translator.trans('flarum-package-manager.admin.extensions.update')
}, m(flarum_common_components_Button__WEBPACK_IMPORTED_MODULE_4___default.a, {
icon: "fas fa-arrow-alt-circle-up",
className: "Button Button--icon Button--flat",
onclick: isCore ? this.updateCoreMinor.bind(this) : this.updateExtension.bind(this, extension),
"aria-label": flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.translator.trans('flarum-package-manager.admin.extensions.update')
}))));
};
_proto.version = function version(v) {
return 'v' + v.replace('v', '');
};
_proto.getExtensionUpdates = function getExtensionUpdates() {
var _this$lastUpdateCheck2,
_this$lastUpdateCheck3,
@ -542,7 +689,8 @@ var Updater = /*#__PURE__*/function (_Component) {
_this3 = this;
(_this$lastUpdateCheck2 = this.lastUpdateCheck) == null ? void 0 : (_this$lastUpdateCheck3 = _this$lastUpdateCheck2.updates) == null ? void 0 : (_this$lastUpdateCheck4 = _this$lastUpdateCheck3.installed) == null ? void 0 : _this$lastUpdateCheck4.filter(function (composerPackage) {
var extension = flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.data.extensions[composerPackage.name.replace('/', '-').replace(/(flarum-ext-)|(flarum-)/, '')];
var id = composerPackage.name.replace('/', '-').replace(/(flarum-ext-)|(flarum-)/, '');
var extension = flarum_admin_app__WEBPACK_IMPORTED_MODULE_2___default.a.data.extensions[id];
var safeToUpdate = ['semver-safe-update', 'update-possible'].includes(composerPackage['latest-status']);
if (extension && safeToUpdate) {
@ -551,7 +699,7 @@ var Updater = /*#__PURE__*/function (_Component) {
return extension && safeToUpdate;
});
return Object.values(flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.data.extensions).filter(function (extension) {
return Object.values(flarum_admin_app__WEBPACK_IMPORTED_MODULE_2___default.a.data.extensions).filter(function (extension) {
return _this3.packageUpdates[extension.id];
});
};
@ -568,10 +716,10 @@ var Updater = /*#__PURE__*/function (_Component) {
var _this4 = this;
this.isLoading = 'check';
flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.request({
flarum_admin_app__WEBPACK_IMPORTED_MODULE_2___default.a.request({
method: 'POST',
url: flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.forum.attribute('apiUrl') + "/package-manager/check-for-updates",
errorHandler: _utils_errorHandler__WEBPACK_IMPORTED_MODULE_8__["default"]
url: flarum_admin_app__WEBPACK_IMPORTED_MODULE_2___default.a.forum.attribute('apiUrl') + "/package-manager/check-for-updates",
errorHandler: _utils_errorHandler__WEBPACK_IMPORTED_MODULE_7__["default"]
}).then(function (response) {
_this4.lastUpdateCheck = response;
})["finally"](function () {
@ -583,17 +731,17 @@ var Updater = /*#__PURE__*/function (_Component) {
_proto.updateCoreMinor = function updateCoreMinor() {
var _this5 = this;
if (confirm(flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.translator.trans('flarum-package-manager.admin.minor_update_confirmation.content'))) {
flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.modal.show(flarum_admin_components_LoadingModal__WEBPACK_IMPORTED_MODULE_6___default.a);
if (confirm(flarum_admin_app__WEBPACK_IMPORTED_MODULE_2___default.a.translator.trans('flarum-package-manager.admin.minor_update_confirmation.content'))) {
flarum_admin_app__WEBPACK_IMPORTED_MODULE_2___default.a.modal.show(flarum_admin_components_LoadingModal__WEBPACK_IMPORTED_MODULE_6___default.a);
this.isLoading = 'minor-update';
flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.request({
flarum_admin_app__WEBPACK_IMPORTED_MODULE_2___default.a.request({
method: 'POST',
url: flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.forum.attribute('apiUrl') + "/package-manager/minor-update",
errorHandler: _utils_errorHandler__WEBPACK_IMPORTED_MODULE_8__["default"]
url: flarum_admin_app__WEBPACK_IMPORTED_MODULE_2___default.a.forum.attribute('apiUrl') + "/package-manager/minor-update",
errorHandler: _utils_errorHandler__WEBPACK_IMPORTED_MODULE_7__["default"]
}).then(function () {
flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.alerts.show({
flarum_admin_app__WEBPACK_IMPORTED_MODULE_2___default.a.alerts.show({
type: 'success'
}, flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.translator.trans('flarum-package-manager.admin.update_successful'));
}, flarum_admin_app__WEBPACK_IMPORTED_MODULE_2___default.a.translator.trans('flarum-package-manager.admin.update_successful'));
window.location.reload();
})["finally"](function () {
_this5.isLoading = null;
@ -605,16 +753,16 @@ var Updater = /*#__PURE__*/function (_Component) {
_proto.updateExtension = function updateExtension(extension) {
var _this6 = this;
flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.modal.show(flarum_admin_components_LoadingModal__WEBPACK_IMPORTED_MODULE_6___default.a);
flarum_admin_app__WEBPACK_IMPORTED_MODULE_2___default.a.modal.show(flarum_admin_components_LoadingModal__WEBPACK_IMPORTED_MODULE_6___default.a);
this.isLoading = 'extension-update';
flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.request({
flarum_admin_app__WEBPACK_IMPORTED_MODULE_2___default.a.request({
method: 'PATCH',
url: flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.forum.attribute('apiUrl') + "/package-manager/extensions/" + extension.id,
errorHandler: _utils_errorHandler__WEBPACK_IMPORTED_MODULE_8__["default"]
url: flarum_admin_app__WEBPACK_IMPORTED_MODULE_2___default.a.forum.attribute('apiUrl') + "/package-manager/extensions/" + extension.id,
errorHandler: _utils_errorHandler__WEBPACK_IMPORTED_MODULE_7__["default"]
}).then(function () {
flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.alerts.show({
flarum_admin_app__WEBPACK_IMPORTED_MODULE_2___default.a.alerts.show({
type: 'success'
}, flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.translator.trans('flarum-package-manager.admin.extensions.successful_update', {
}, flarum_admin_app__WEBPACK_IMPORTED_MODULE_2___default.a.translator.trans('flarum-package-manager.admin.extensions.successful_update', {
extension: extension.extra['flarum-extension'].title
}));
window.location.reload();
@ -627,16 +775,16 @@ var Updater = /*#__PURE__*/function (_Component) {
_proto.updateGlobally = function updateGlobally() {
var _this7 = this;
flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.modal.show(flarum_admin_components_LoadingModal__WEBPACK_IMPORTED_MODULE_6___default.a);
flarum_admin_app__WEBPACK_IMPORTED_MODULE_2___default.a.modal.show(flarum_admin_components_LoadingModal__WEBPACK_IMPORTED_MODULE_6___default.a);
this.isLoading = 'global-update';
flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.request({
flarum_admin_app__WEBPACK_IMPORTED_MODULE_2___default.a.request({
method: 'POST',
url: flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.forum.attribute('apiUrl') + "/package-manager/global-update",
errorHandler: _utils_errorHandler__WEBPACK_IMPORTED_MODULE_8__["default"]
url: flarum_admin_app__WEBPACK_IMPORTED_MODULE_2___default.a.forum.attribute('apiUrl') + "/package-manager/global-update",
errorHandler: _utils_errorHandler__WEBPACK_IMPORTED_MODULE_7__["default"]
}).then(function () {
flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.alerts.show({
flarum_admin_app__WEBPACK_IMPORTED_MODULE_2___default.a.alerts.show({
type: 'success'
}, flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.translator.trans('flarum-package-manager.admin.updater.global_update_successful'));
}, flarum_admin_app__WEBPACK_IMPORTED_MODULE_2___default.a.translator.trans('flarum-package-manager.admin.updater.global_update_successful'));
window.location.reload();
})["finally"](function () {
_this7.isLoading = null;
@ -644,8 +792,111 @@ var Updater = /*#__PURE__*/function (_Component) {
});
};
Object(_babel_runtime_helpers_esm_createClass__WEBPACK_IMPORTED_MODULE_0__["default"])(Updater, [{
key: "lastUpdateRun",
get: function get() {
var lastUpdateRun = JSON.parse(flarum_admin_app__WEBPACK_IMPORTED_MODULE_2___default.a.data.settings['flarum-package-manager.last_update_run']);
lastUpdateRun.limitedPackages = function () {
return [].concat(lastUpdateRun.major.limitedPackages, lastUpdateRun.minor.limitedPackages, lastUpdateRun.global.limitedPackages);
};
return lastUpdateRun;
}
}]);
return Updater;
}(flarum_common_Component__WEBPACK_IMPORTED_MODULE_2___default.a);
}(flarum_common_Component__WEBPACK_IMPORTED_MODULE_3___default.a);
/***/ }),
/***/ "./src/admin/components/WhyNotModal.tsx":
/*!**********************************************!*\
!*** ./src/admin/components/WhyNotModal.tsx ***!
\**********************************************/
/*! exports provided: default */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "default", function() { return WhyNotModal; });
/* harmony import */ var _babel_runtime_helpers_esm_inheritsLoose__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @babel/runtime/helpers/esm/inheritsLoose */ "./node_modules/@babel/runtime/helpers/esm/inheritsLoose.js");
/* harmony import */ var flarum_admin_app__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! flarum/admin/app */ "flarum/admin/app");
/* harmony import */ var flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(flarum_admin_app__WEBPACK_IMPORTED_MODULE_1__);
/* harmony import */ var flarum_common_components_Modal__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! flarum/common/components/Modal */ "flarum/common/components/Modal");
/* harmony import */ var flarum_common_components_Modal__WEBPACK_IMPORTED_MODULE_2___default = /*#__PURE__*/__webpack_require__.n(flarum_common_components_Modal__WEBPACK_IMPORTED_MODULE_2__);
/* harmony import */ var flarum_common_components_LoadingIndicator__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! flarum/common/components/LoadingIndicator */ "flarum/common/components/LoadingIndicator");
/* harmony import */ var flarum_common_components_LoadingIndicator__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(flarum_common_components_LoadingIndicator__WEBPACK_IMPORTED_MODULE_3__);
/* harmony import */ var _utils_errorHandler__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ../utils/errorHandler */ "./src/admin/utils/errorHandler.ts");
var WhyNotModal = /*#__PURE__*/function (_Modal) {
Object(_babel_runtime_helpers_esm_inheritsLoose__WEBPACK_IMPORTED_MODULE_0__["default"])(WhyNotModal, _Modal);
function WhyNotModal() {
var _this;
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
_this = _Modal.call.apply(_Modal, [this].concat(args)) || this;
_this.loading = true;
_this.whyNot = null;
return _this;
}
var _proto = WhyNotModal.prototype;
_proto.className = function className() {
return 'Modal--large WhyNotModal';
};
_proto.title = function title() {
return flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.translator.trans('flarum-package-manager.admin.why_not_modal.title');
};
_proto.oncreate = function oncreate(vnode) {
_Modal.prototype.oncreate.call(this, vnode);
this.requestWhyNot();
};
_proto.content = function content() {
return m("div", {
className: "Modal-body"
}, this.loading ? m(flarum_common_components_LoadingIndicator__WEBPACK_IMPORTED_MODULE_3___default.a, null) : m("pre", {
className: "WhyNotModal-contents"
}, this.whyNot));
};
_proto.requestWhyNot = function requestWhyNot() {
var _this2 = this;
flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.request({
method: 'POST',
url: flarum_admin_app__WEBPACK_IMPORTED_MODULE_1___default.a.forum.attribute('apiUrl') + "/package-manager/why-not",
body: {
data: {
"package": this.attrs["package"]
}
},
errorHandler: _utils_errorHandler__WEBPACK_IMPORTED_MODULE_4__["default"]
}).then(function (response) {
_this2.loading = false;
_this2.whyNot = response.data.whyNot;
m.redraw();
});
};
return WhyNotModal;
}(flarum_common_components_Modal__WEBPACK_IMPORTED_MODULE_2___default.a);
@ -766,6 +1017,10 @@ __webpack_require__.r(__webpack_exports__);
type: 'error'
}, flarum_admin_app__WEBPACK_IMPORTED_MODULE_0___default.a.translator.trans("flarum-package-manager.admin.exceptions.guessed_cause." + error.guessed_cause));
flarum_admin_app__WEBPACK_IMPORTED_MODULE_0___default.a.modal.close();
} else {
flarum_admin_app__WEBPACK_IMPORTED_MODULE_0___default.a.alerts.show({
type: 'error'
}, flarum_admin_app__WEBPACK_IMPORTED_MODULE_0___default.a.translator.trans('flarum-package-manager.admin.exceptions.composer_command_failure'));
}
break;
@ -875,6 +1130,17 @@ module.exports = flarum.core.compat['common/components/LoadingIndicator'];
/***/ }),
/***/ "flarum/common/components/Modal":
/*!****************************************************************!*\
!*** external "flarum.core.compat['common/components/Modal']" ***!
\****************************************************************/
/*! no static exports found */
/***/ (function(module, exports) {
module.exports = flarum.core.compat['common/components/Modal'];
/***/ }),
/***/ "flarum/common/components/Tooltip":
/*!******************************************************************!*\
!*** external "flarum.core.compat['common/components/Tooltip']" ***!

File diff suppressed because one or more lines are too long

View File

@ -4,9 +4,9 @@
"private": true,
"prettier": "@flarum/prettier-config",
"dependencies": {
"flarum-webpack-config": "^1.0.0",
"flarum-tsconfig": "^1.0.0",
"@flarum/prettier-config": "^1.0.0",
"flarum-tsconfig": "^1.0.0",
"flarum-webpack-config": "^1.0.0",
"webpack": "^4.26.0",
"webpack-cli": "^3.0.7"
},

View File

@ -0,0 +1,89 @@
import Mithril from 'mithril';
import app from 'flarum/admin/app';
import Component, { ComponentAttrs } from 'flarum/common/Component';
import classList from 'flarum/common/utils/classList';
import icon from 'flarum/common/helpers/icon';
import Tooltip from 'flarum/common/components/Tooltip';
import Button from 'flarum/common/components/Button';
import { Extension as BaseExtension } from 'flarum/admin/AdminApplication';
import { UpdatedPackage } from './Updater';
import WhyNotModal from './WhyNotModal';
/*
* @todo fix in core
*/
export type Extension = BaseExtension & {
name: string;
};
export interface ExtensionItemAttrs extends ComponentAttrs {
extension: Extension;
updates: UpdatedPackage;
onClickUpdate: CallableFunction;
whyNotWarning?: boolean;
isCore?: boolean;
updatable?: boolean;
isDanger?: boolean;
}
export default class ExtensionItem<Attrs extends ExtensionItemAttrs = ExtensionItemAttrs> extends Component<Attrs> {
view(vnode: Mithril.Vnode<Attrs, this>): Mithril.Children {
const { extension, updates, onClickUpdate, whyNotWarning, isCore, isDanger } = this.attrs;
return (
<div
className={classList({
'PackageManager-extension': true,
'PackageManager-extension--core': isCore,
'PackageManager-extension--danger': isDanger,
})}
>
<div className="PackageManager-extension-icon ExtensionIcon" style={extension.icon}>
{extension.icon ? icon(extension.icon.name) : ''}
</div>
<div className="PackageManager-extension-info">
<div className="PackageManager-extension-name">{extension.extra['flarum-extension'].title}</div>
<div className="PackageManager-extension-version">
<span className="PackageManager-extension-version-current">{this.version(extension.version)}</span>
{updates['latest-minor'] ? (
<span className="PackageManager-extension-version-latest PackageManager-extension-version-latest--minor">
{this.version(updates['latest-minor']!)}
</span>
) : null}
{updates['latest-major'] && !isCore ? (
<span className="PackageManager-extension-version-latest PackageManager-extension-version-latest--major">
{this.version(updates['latest-major']!)}
</span>
) : null}
</div>
</div>
<div className="PackageManager-extension-controls">
{onClickUpdate ? (
<Tooltip text={app.translator.trans('flarum-package-manager.admin.extensions.update')}>
<Button
icon="fas fa-arrow-alt-circle-up"
className="Button Button--icon Button--flat"
onclick={onClickUpdate}
aria-label={app.translator.trans('flarum-package-manager.admin.extensions.update')}
/>
</Tooltip>
) : null}
{whyNotWarning ? (
<Tooltip text={app.translator.trans('flarum-package-manager.admin.extensions.check_why_it_failed_updating')}>
<Button
icon="fas fa-exclamation-circle"
className="Button Button--icon Button--flat Button--danger"
onclick={() => app.modal.show(WhyNotModal, { package: extension.name })}
aria-label={app.translator.trans('flarum-package-manager.admin.extensions.check_why_it_failed_updating')}
/>
</Tooltip>
) : null}
</div>
</div>
);
}
private version(v: string): string {
return 'v' + v.replace('v', '');
}
}

View File

@ -3,20 +3,33 @@ import Component, { ComponentAttrs } from 'flarum/common/Component';
import Mithril from 'mithril';
import Button from 'flarum/common/components/Button';
import Tooltip from 'flarum/common/components/Tooltip';
import { UpdatedPackage } from './Updater';
import { UpdatedPackage, UpdateState } from './Updater';
import LoadingModal from 'flarum/admin/components/LoadingModal';
import errorHandler from '../utils/errorHandler';
import Alert from 'flarum/common/components/Alert';
import WhyNotModal from './WhyNotModal';
import RequestError from 'flarum/common/utils/RequestError';
import ExtensionItem, { Extension } from './ExtensionItem';
interface MajorUpdaterAttrs extends ComponentAttrs {
coreUpdate: UpdatedPackage;
updateState: UpdateState;
}
export default class MajorUpdater<T extends MajorUpdaterAttrs = MajorUpdaterAttrs> extends Component<T> {
isLoading: string | null = null;
updateState!: UpdateState;
view(vnode: Mithril.Vnode<ComponentAttrs, this>): Mithril.Children {
oninit(vnode: Mithril.Vnode<T, this>) {
super.oninit(vnode);
this.updateState = this.attrs.updateState;
}
view(vnode: Mithril.Vnode<T, this>): Mithril.Children {
// @todo move Form-group--danger class to core for reuse
return (
<div className="Form-group PackageManager-majorUpdate">
<div className="Form-group Form-group--danger PackageManager-majorUpdate">
<img alt="flarum logo" src={app.forum.attribute('baseUrl') + '/assets/extensions/flarum-package-manager/flarum.svg'} />
<label>{app.translator.trans('flarum-package-manager.admin.major_updater.title', { version: this.attrs.coreUpdate['latest-major'] })}</label>
<p className="helpText">{app.translator.trans('flarum-package-manager.admin.major_updater.description')}</p>
@ -26,10 +39,42 @@ export default class MajorUpdater<T extends MajorUpdaterAttrs = MajorUpdaterAttr
{app.translator.trans('flarum-package-manager.admin.major_updater.dry_run')}
</Button>
</Tooltip>
<Button className="Button" icon="fas fa-play" onclick={this.update.bind(this, false)}>
<Button className="Button Button--danger" icon="fas fa-play" onclick={this.update.bind(this, false)}>
{app.translator.trans('flarum-package-manager.admin.major_updater.update')}
</Button>
</div>
{this.updateState.incompatibleExtensions.length ? (
<div className="PackageManager-majorUpdate-incompatibleExtensions PackageManager-extensions-grid">
{this.updateState.incompatibleExtensions.map((extension: string) => (
<ExtensionItem
extension={app.data.extensions[extension.replace('flarum-', '').replace('flarum-ext-', '').replace('/', '-')]}
updates={{}}
onClickUpdate={null}
isDanger={true}
/>
))}
</div>
) : null}
{this.updateState.status === 'failure' ? (
<Alert
type="error"
className="PackageManager-majorUpdate-failure"
dismissible={false}
controls={[
<Button
className="Button Button--text PackageManager-majorUpdate-failure-details"
icon="fas fa-question-circle"
onclick={() => app.modal.show(WhyNotModal, { package: 'flarum/core' })}
>
{app.translator.trans('flarum-package-manager.admin.major_updater.failure.why')}
</Button>,
]}
>
<p className="PackageManager-majorUpdate-failure-desc">
{app.translator.trans('flarum-package-manager.admin.major_updater.failure.desc')}
</p>
</Alert>
) : null}
</div>
);
}
@ -51,6 +96,11 @@ export default class MajorUpdater<T extends MajorUpdaterAttrs = MajorUpdaterAttr
app.alerts.show({ type: 'success' }, app.translator.trans('flarum-package-manager.admin.update_successful'));
window.location.reload();
})
.catch((e: RequestError) => {
app.modal.close();
this.updateState.status = 'failure';
this.updateState.incompatibleExtensions = e.response?.errors?.pop()?.incompatible_extensions as string[];
})
.finally(() => {
this.isLoading = null;
m.redraw();

View File

@ -1,16 +1,13 @@
import Mithril from "mithril";
import Mithril from 'mithril';
import app from 'flarum/admin/app';
import Component from 'flarum/common/Component';
import icon from 'flarum/common/helpers/icon';
import Button from 'flarum/common/components/Button';
import humanTime from 'flarum/common/helpers/humanTime';
import LoadingModal from 'flarum/admin/components/LoadingModal';
import Tooltip from 'flarum/common/components/Tooltip';
import errorHandler from '../utils/errorHandler';
import classList from 'flarum/common/utils/classList';
import LoadingIndicator from 'flarum/common/components/LoadingIndicator';
import MajorUpdater from './MajorUpdater';
import {Extension} from "flarum/admin/AdminApplication";
import ExtensionItem, { Extension } from './ExtensionItem';
export type UpdatedPackage = {
name: string;
@ -27,27 +24,54 @@ export type ComposerUpdates = {
};
export type LastUpdateCheck = {
checkedAt: Date;
checkedAt: Date | null;
updates: ComposerUpdates;
};
type UpdateType = 'major' | 'minor' | 'global';
type UpdateStatus = 'success' | 'failure' | null;
export type UpdateState = {
ranAt: Date | null;
status: UpdateStatus;
limitedPackages: string[];
incompatibleExtensions: string[];
};
export type LastUpdateRun = {
[key in UpdateType]: UpdateState;
} & {
limitedPackages: () => string[];
};
export default class Updater<Attrs> extends Component<Attrs> {
isLoading: string | null = null;
lastUpdateCheck: LastUpdateCheck = (app.data.lastUpdateCheck as LastUpdateCheck) || {};
packageUpdates: Record<string, UpdatedPackage> = {};
lastUpdateCheck: LastUpdateCheck = JSON.parse(app.data.settings['flarum-package-manager.last_update_check']) as LastUpdateCheck;
get lastUpdateRun(): LastUpdateRun {
const lastUpdateRun = JSON.parse(app.data.settings['flarum-package-manager.last_update_run']) as LastUpdateRun;
lastUpdateRun.limitedPackages = () => [
...lastUpdateRun.major.limitedPackages,
...lastUpdateRun.minor.limitedPackages,
...lastUpdateRun.global.limitedPackages,
];
return lastUpdateRun;
}
oninit(vnode: Mithril.Vnode<Attrs, this>) {
super.oninit(vnode);
}
view() {
const extensions: any = this.getExtensionUpdates();
const coreUpdate: UpdatedPackage | undefined = this.getCoreUpdate();
let core: any = null;
const extensions = this.getExtensionUpdates();
let coreUpdate: UpdatedPackage | undefined = this.getCoreUpdate();
let core: any;
if (coreUpdate) {
core = {
id: "flarum-core",
id: 'flarum-core',
name: 'flarum/core',
version: app.data.settings.version,
icon: {
backgroundImage: `url(${app.forum.attribute('baseUrl')}/assets/extensions/flarum-package-manager/flarum.svg`,
@ -55,25 +79,23 @@ export default class Updater<Attrs> extends Component<Attrs> {
extra: {
'flarum-extension': {
title: app.translator.trans('flarum-package-manager.admin.updater.flarum'),
}
}
},
},
};
this.packageUpdates['flarum-core'] = coreUpdate;
}
return [
<div className="Form-group">
<label>{app.translator.trans('flarum-package-manager.admin.updater.updater_title')}</label>
<p className="helpText">{app.translator.trans('flarum-package-manager.admin.updater.updater_help')}</p>
{Object.keys(this.lastUpdateCheck).length ? (
{this.lastUpdateCheck?.checkedAt && (
<p className="PackageManager-lastUpdatedAt">
<span className="PackageManager-lastUpdatedAt-label">
{app.translator.trans('flarum-package-manager.admin.updater.last_update_checked_at')}
</span>
<span className="PackageManager-lastUpdatedAt-value">{humanTime(this.lastUpdateCheck?.checkedAt)}</span>
<span className="PackageManager-lastUpdatedAt-value">{humanTime(this.lastUpdateCheck.checkedAt)}</span>
</p>
) : null}
)}
<div className="PackageManager-updaterControls">
<Button
className="Button"
@ -101,64 +123,36 @@ export default class Updater<Attrs> extends Component<Attrs> {
) : extensions.length || core ? (
<div className="PackageManager-extensions">
<div className="PackageManager-extensions-grid">
{core ? this.extensionItem(core, true) : null}
{extensions.map((extension: any) => this.extensionItem(extension))}
{core ? (
<ExtensionItem
extension={core}
updates={coreUpdate}
isCore={true}
onClickUpdate={this.updateCoreMinor.bind(this)}
whyNotWarning={this.lastUpdateRun.limitedPackages().includes('flarum/core')}
/>
) : null}
{extensions.map((extension: Extension) => (
<ExtensionItem
extension={extension}
updates={this.packageUpdates[extension.id]}
onClickUpdate={this.updateExtension.bind(this, extension)}
whyNotWarning={this.lastUpdateRun.limitedPackages().includes(extension.name)}
/>
))}
</div>
</div>
) : null}
</div>,
coreUpdate && coreUpdate['latest-major'] ? <MajorUpdater coreUpdate={coreUpdate} /> : null,
coreUpdate && coreUpdate['latest-major'] ? <MajorUpdater coreUpdate={coreUpdate} updateState={this.lastUpdateRun.major} /> : null,
];
}
extensionItem(extension: Extension, isCore: boolean = false) {
return (
<div
className={classList({
'PackageManager-extension': true,
'PackageManager-extension--core': isCore,
})}
>
<div className="PackageManager-extension-icon ExtensionIcon" style={extension.icon}>
{extension.icon ? icon(extension.icon.name) : ''}
</div>
<div className="PackageManager-extension-info">
<div className="PackageManager-extension-name">{extension.extra['flarum-extension'].title}</div>
<div className="PackageManager-extension-version">
<span className="PackageManager-extension-version-current">{this.version(extension.version)}</span>
{this.packageUpdates[extension.id]['latest-minor'] ? (
<span className="PackageManager-extension-version-latest PackageManager-extension-version-latest--minor">
{this.version(this.packageUpdates[extension.id]['latest-minor']!)}
</span>
) : null}
{this.packageUpdates[extension.id]['latest-major'] && !isCore ? (
<span className="PackageManager-extension-version-latest PackageManager-extension-version-latest--major">
{this.version(this.packageUpdates[extension.id]['latest-major']!)}
</span>
) : null}
</div>
</div>
<div className="PackageManager-extension-controls">
<Tooltip text={app.translator.trans('flarum-package-manager.admin.extensions.update')}>
<Button
icon="fas fa-arrow-alt-circle-up"
className="Button Button--icon Button--flat"
onclick={isCore ? this.updateCoreMinor.bind(this) : this.updateExtension.bind(this, extension)}
aria-label={app.translator.trans('flarum-package-manager.admin.extensions.update')}
/>
</Tooltip>
</div>
</div>
);
}
version(v: string) {
return 'v' + v.replace('v', '');
}
getExtensionUpdates() {
getExtensionUpdates(): Extension[] {
this.lastUpdateCheck?.updates?.installed?.filter((composerPackage: UpdatedPackage) => {
const extension = app.data.extensions[composerPackage.name.replace('/', '-').replace(/(flarum-ext-)|(flarum-)/, '')];
const id = composerPackage.name.replace('/', '-').replace(/(flarum-ext-)|(flarum-)/, '');
const extension = app.data.extensions[id];
const safeToUpdate = ['semver-safe-update', 'update-possible'].includes(composerPackage['latest-status']);
if (extension && safeToUpdate) {
@ -168,7 +162,7 @@ export default class Updater<Attrs> extends Component<Attrs> {
return extension && safeToUpdate;
});
return Object.values(app.data.extensions).filter((extension: any) => this.packageUpdates[extension.id]);
return (Object.values(app.data.extensions) as Extension[]).filter((extension: Extension) => this.packageUpdates[extension.id]);
}
getCoreUpdate(): UpdatedPackage | undefined {

View File

@ -0,0 +1,51 @@
import app from 'flarum/admin/app';
import Mithril from 'mithril';
import Modal, { IInternalModalAttrs } from 'flarum/common/components/Modal';
import LoadingIndicator from 'flarum/common/components/LoadingIndicator';
import errorHandler from '../utils/errorHandler';
export interface WhyNotModalAttrs extends IInternalModalAttrs {
package: string;
}
export default class WhyNotModal<Attrs extends WhyNotModalAttrs = WhyNotModalAttrs> extends Modal<Attrs> {
loading: boolean = true;
whyNot: string | null = null;
className() {
return 'Modal--large WhyNotModal';
}
title() {
return app.translator.trans('flarum-package-manager.admin.why_not_modal.title');
}
oncreate(vnode: Mithril.VnodeDOM<Attrs, this>) {
super.oncreate(vnode);
this.requestWhyNot();
}
content() {
return <div className="Modal-body">{this.loading ? <LoadingIndicator /> : <pre className="WhyNotModal-contents">{this.whyNot}</pre>}</div>;
}
requestWhyNot(): void {
app
.request({
method: 'POST',
url: `${app.forum.attribute('apiUrl')}/package-manager/why-not`,
body: {
data: {
package: this.attrs.package,
},
},
errorHandler,
})
.then((response: any) => {
this.loading = false;
this.whyNot = response.data.whyNot;
m.redraw();
});
}
}

View File

@ -10,8 +10,10 @@ export default function (e: any) {
switch (error.code) {
case 'composer_command_failure':
if (error.guessed_cause) {
app.alerts.show({type: 'error'}, app.translator.trans(`flarum-package-manager.admin.exceptions.guessed_cause.${error.guessed_cause}`))
app.alerts.show({ type: 'error' }, app.translator.trans(`flarum-package-manager.admin.exceptions.guessed_cause.${error.guessed_cause}`));
app.modal.close();
} else {
app.alerts.show({ type: 'error' }, app.translator.trans('flarum-package-manager.admin.exceptions.composer_command_failure'));
}
break;

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,7 @@
}
.PackageManager-lastUpdatedAt {
color: @control-color;
color: var(--control-color);
&-label {
font-weight: bold;
@ -42,9 +42,9 @@
display: flex;
align-items: center;
gap: 8px;
background-color: @control-bg;
background-color: var(--control-bg);
padding: 8px;
border-radius: @border-radius;
border-radius: var(--border-radius);
&-controls {
margin-left: auto;
@ -69,22 +69,28 @@
font-weight: bold;
&--minor {
background-color: @alert-success-bg;
color: @alert-success-color;
background-color: var(--alert-success-bg);
color: var(--alert-success-color);
}
&--major {
background-color: @alert-bg;
color: @alert-color;
background-color: var(--alert-bg);
color: var(--alert-color);
}
}
}
&--core {
--bg-hover: darken(#e7672e, 5);
background-color: #e7672e;
color: #fff;
--button-color: #fff;
--button-bg-hover: darken(#e7672e, 5);
--button-bg-hover: var(--bg-hover);
.Button--danger {
color: #fff;
--button-bg-hover: var(--bg-hover);
}
}
&--core &-icon {
@ -92,19 +98,23 @@
background-color: transparent;
filter: grayscale(1) brightness(3.5);
}
&--danger {
background-color: var(--control-danger-bg);
}
}
.PackageManager-majorUpdate {
border: 2px solid @control-danger-color;
border-radius: @border-radius;
padding: 16px;
background-color: lighten(@control-danger-bg, 5.5);
--space: 16px;
padding: var(--space);
display: grid;
grid-template-areas:
"logo title"
"logo helpText"
"logo controls";
grid-gap: 0 16px;
"title logo"
"helpText logo"
"controls logo"
"extensions extensions"
"failure failure";
grid-gap: 0 var(--space);
align-items: center;
> img {
@ -118,4 +128,30 @@
> .helpText {
grid-area: helpText;
}
&-failure {
--border-radius: 0;
grid-area: failure;
margin: calc(~"0px - var(--space)");
margin-top: var(--space);
}
&-incompatibleExtensions {
grid-area: extensions;
margin-top: var(--space);
padding-top: var(--space);
border-top: 1px solid var(--control-bg);
}
}
.Form-group--danger {
border: 2px solid var(--alert-error-bg);
border-radius: var(--border-radius);
background-color: transparent;
}
.WhyNotModal {
&-contents {
overflow-x: auto;
}
}

View File

@ -1,6 +1,7 @@
flarum-package-manager:
admin:
exceptions:
composer_command_failure: Failed to execute. Check the composer logs in storage/logs/composer.
extension_already_installed: Extension is already installed.
extension_not_installed: Extension not found.
@ -11,6 +12,7 @@ flarum-package-manager:
Please wait until the extensions are updated to be compatible by the authors, or remove them before proceeding.
extensions:
check_why_it_failed_updating: Show why it did not update to the latest.
install: Install a new extension
install_help: Fill in the extension package name to proceed. Visit {extiverse} to browse extensions.
proceed: Proceed
@ -26,6 +28,10 @@ flarum-package-manager:
description: Major Flarum updates are not backwards compatible, meaning that some of your currently installed extensions, and manually made modifications might not work with this new version.
dry_run: Dry Run
dry_run_help: A dry run emulates the update to see if your current setup can safely update, this does not mean that your manual made custom modifications will work in the newer version.
failure:
desc: The last major update failed, some installed extensions are not compatible with the new major release.
why: Find out more
title: Flarum {version} Major Update Available
update: Update
@ -42,3 +48,6 @@ flarum-package-manager:
updater_help: Runs a check for new extension and Flarum updates.
update_successful: Flarum successfully updated.
why_not_modal:
title: Why Won't it Update

View File

@ -0,0 +1,47 @@
<?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\PackageManager\Api\Controller;
use Flarum\Bus\Dispatcher;
use Flarum\Http\RequestUtil;
use Flarum\PackageManager\Command\WhyNot;
use Illuminate\Support\Arr;
use Laminas\Diactoros\Response\JsonResponse;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Psr\Http\Message\ServerRequestInterface;
class WhyNotController implements RequestHandlerInterface
{
/**
* @var Dispatcher
*/
protected $bus;
public function __construct(Dispatcher $bus)
{
$this->bus = $bus;
}
public function handle(ServerRequestInterface $request): ResponseInterface
{
$actor = RequestUtil::getActor($request);
$package = Arr::get($request->getParsedBody(), 'data.package', '');
$version = Arr::get($request->getParsedBody(), 'data.version', '*');
$whyNot = $this->bus->dispatch(
new WhyNot($actor, $package, $version)
);
return new JsonResponse([
'data' => compact('whyNot')
]);
}
}

View File

@ -11,7 +11,7 @@ namespace Flarum\PackageManager\Command;
use Flarum\PackageManager\Composer\ComposerAdapter;
use Flarum\PackageManager\Exception\ComposerCommandFailedException;
use Flarum\PackageManager\LastUpdateCheck;
use Flarum\PackageManager\Settings\LastUpdateCheck;
use Symfony\Component\Console\Input\ArrayInput;
class CheckForUpdatesHandler
@ -22,7 +22,7 @@ class CheckForUpdatesHandler
protected $composer;
/**
* @var LastUpdateCheck
* @var \Flarum\PackageManager\Settings\LastUpdateCheck
*/
protected $lastUpdateCheck;
@ -95,7 +95,9 @@ class CheckForUpdatesHandler
}
}
return $this->lastUpdateCheck->save($firstOutput);
return $this->lastUpdateCheck
->with('installed', $firstOutput['installed'])
->save();
}
/**

View File

@ -15,7 +15,7 @@ use Flarum\PackageManager\Exception\MajorUpdateFailedException;
use Flarum\PackageManager\Exception\NoNewMajorVersionException;
use Illuminate\Contracts\Events\Dispatcher;
use Flarum\PackageManager\Event\FlarumUpdated;
use Flarum\PackageManager\LastUpdateCheck;
use Flarum\PackageManager\Settings\LastUpdateCheck;
use Symfony\Component\Console\Input\ArrayInput;
class MajorUpdateHandler
@ -68,6 +68,28 @@ class MajorUpdateHandler
{
$command->actor->assertAdmin();
// @todo remove testing code
throw new MajorUpdateFailedException(
'*',
'Loading composer repositories with package information
Updating dependencies
Your requirements could not be resolved to an installable set of packages.
Problem 1
- Root composer.json requires flarum/tags * -> satisfiable by flarum/tags[1.0.0].
- flarum/tags 1.0.0 requires flarum/core >=0.1.0-beta.15 <0.1.0-beta.16 -> found flarum/core[v0.1.0-beta.15] but it conflicts with your root composer.json require (^1.1.1).
Problem 2
- Root composer.json requires sycho/flarum-profile-cover * -> satisfiable by sycho/flarum-profile-cover[1.0.0].
- sycho/flarum-profile-cover 1.0.0 requires flarum/core >=0.1.0-beta.15 <=0.1.0-beta.16 -> found flarum/core[v0.1.0-beta.15, v0.1.0-beta.16] but it conflicts with your root composer.json require (^1.1.1).
Problem 3
- Root composer.json requires askvortsov/flarum-auto-moderator * -> satisfiable by askvortsov/flarum-auto-moderator[1.0.0].
- askvortsov/flarum-auto-moderator 1.0.0 requires flarum/core 0.1.0-beta.15 -> found flarum/core[v0.1.0-beta.15] but it conflicts with your root composer.json require (^1.1.1).
<warning>Running update with --no-dev does not mean require-dev is ignored, it just means the packages will not be installed. If dev requirements are blocking the update you have to resolve those problems.</warning>
',
'2.0',
);
$majorVersion = $this->lastUpdateCheck->getNewMajorVersion();
if (! $majorVersion) {
@ -91,6 +113,9 @@ class MajorUpdateHandler
return true;
}
/**
* @todo change minimum stability to 'stable' and any other similar params
*/
protected function updateComposerJson(string $majorVersion): void
{
$versionNumber = str_replace('v', '', $majorVersion);

View File

@ -14,7 +14,7 @@ use Flarum\PackageManager\Composer\ComposerJson;
use Illuminate\Contracts\Events\Dispatcher;
use Flarum\PackageManager\Event\FlarumUpdated;
use Flarum\PackageManager\Exception\ComposerUpdateFailedException;
use Flarum\PackageManager\LastUpdateCheck;
use Flarum\PackageManager\Settings\LastUpdateCheck;
use Symfony\Component\Console\Input\StringInput;
class MinorUpdateHandler
@ -25,7 +25,7 @@ class MinorUpdateHandler
protected $composer;
/**
* @var LastUpdateCheck
* @var \Flarum\PackageManager\Settings\LastUpdateCheck
*/
protected $lastUpdateCheck;

View File

@ -16,7 +16,7 @@ use Flarum\PackageManager\Exception\ComposerUpdateFailedException;
use Flarum\PackageManager\Exception\ExtensionNotInstalledException;
use Flarum\PackageManager\Extension\Event\Updated;
use Flarum\PackageManager\UpdateExtensionValidator;
use Flarum\PackageManager\LastUpdateCheck;
use Flarum\PackageManager\Settings\LastUpdateCheck;
use Symfony\Component\Console\Input\StringInput;
class UpdateExtensionHandler
@ -84,8 +84,6 @@ class UpdateExtensionHandler
throw new ComposerUpdateFailedException($extension->name, $output->getContents());
}
$this->lastUpdateCheck->forget($extension->name);
$this->events->dispatch(
new Updated($extension)
);

View File

@ -0,0 +1,37 @@
<?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\PackageManager\Command;
use Flarum\User\User;
class WhyNot
{
/**
* @var User
*/
public $actor;
/**
* @var string
*/
public $package;
/**
* @var string
*/
public $version;
public function __construct(User $actor, string $package, string $version)
{
$this->actor = $actor;
$this->package = $package;
$this->version = $version;
}
}

View File

@ -0,0 +1,65 @@
<?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\PackageManager\Command;
use Flarum\PackageManager\Composer\ComposerAdapter;
use Illuminate\Contracts\Events\Dispatcher;
use Flarum\PackageManager\Exception\ComposerRequireFailedException;
use Flarum\PackageManager\WhyNotValidator;
use Symfony\Component\Console\Input\StringInput;
class WhyNotHandler
{
/**
* @var ComposerAdapter
*/
protected $composer;
/**
* @var WhyNotValidator
*/
protected $validator;
/**
* @var Dispatcher
*/
protected $events;
public function __construct(ComposerAdapter $composer, WhyNotValidator $validator, Dispatcher $events)
{
$this->composer = $composer;
$this->validator = $validator;
$this->events = $events;
}
/**
* @throws \Flarum\User\Exception\PermissionDeniedException
* @throws \Exception
*/
public function handle(WhyNot $command)
{
$command->actor->assertAdmin();
$this->validator->assertValid([
'package' => $command->package,
'version' => $command->version
]);
$output = $this->composer->run(
new StringInput("why-not $command->package $command->version")
);
if ($output->getExitCode() !== 0) {
throw new ComposerRequireFailedException($command->package, $output->getContents());
}
return $output->getContents();
}
}

View File

@ -43,6 +43,8 @@ class ComposerAdapter
public function run(InputInterface $input): ComposerOutput
{
$this->application->resetComposer();
$exitCode = $this->application->run($input, $this->output);
$outputContents = $this->output->fetch();

View File

@ -14,8 +14,8 @@ use Flarum\User\User;
class FlarumUpdated
{
public const GLOBAL = 'global';
public const MAJOR = 'major';
public const MINOR = 'minor';
public const MAJOR = 'major';
/**
* @var User

View File

@ -1,8 +1,17 @@
<?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\PackageManager\Exception;
use Composer\Semver\Semver;
use Flarum\PackageManager\Event\FlarumUpdated;
use Flarum\PackageManager\Settings\LastUpdateRun;
class MajorUpdateFailedException extends ComposerCommandFailedException
{
@ -31,6 +40,12 @@ class MajorUpdateFailedException extends ComposerCommandFailedException
}
}
resolve(LastUpdateRun::class)
->for(FlarumUpdated::MAJOR)
->with('status', LastUpdateRun::FAILURE)
->with('incompatibleExtensions', $this->details['incompatible_extensions'])
->save();
return 'extensions_incompatible_with_new_major';
}

View File

@ -1,78 +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\PackageManager;
use Carbon\Carbon;
use Flarum\Settings\SettingsRepositoryInterface;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
class LastUpdateCheck
{
public const KEY = 'flarum-package-manager.last_update_check';
/**
* @var SettingsRepositoryInterface
*/
protected $settings;
public function __construct(SettingsRepositoryInterface $settings)
{
$this->settings = $settings;
}
public function save(array $updates): array
{
$lastUpdateCheck = [
'checkedAt' => Carbon::now(),
'updates' => $updates,
];
$this->settings->set(self::KEY, json_encode($lastUpdateCheck));
return $lastUpdateCheck;
}
public function get(): array
{
return json_decode($this->settings->get(self::KEY), true);
}
public function getNewMajorVersion(): ?string
{
$core = Arr::first(Arr::get($this->get(), 'updates.installed', []), function ($package) {
return $package['name'] === 'flarum/core';
});
return $core ? $core['latest-major'] : null;
}
public function forget(string $name): void
{
$lastUpdateCheck = $this->get();
if (isset($lastUpdateCheck['updates']) && ! empty($lastUpdateCheck['updates']['installed'])) {
$updatesListChanged = false;
foreach ($lastUpdateCheck['updates']['installed'] as $k => $package) {
if ($package['name'] === $name) {
unset($lastUpdateCheck['updates']['installed'][$k]);
$updatesListChanged = true;
break;
}
}
if ($updatesListChanged) {
$lastUpdateCheck['updates']['installed'] = array_values($lastUpdateCheck['updates']['installed']);
$this->settings->set(self::KEY, json_encode($lastUpdateCheck));
}
}
}
}

View File

@ -10,15 +10,13 @@
namespace Flarum\PackageManager\Listener;
use Composer\Command\ClearCacheCommand;
use Flarum\Bus\Dispatcher;
use Flarum\Database\Console\MigrateCommand;
use Flarum\Foundation\Console\AssetsPublishCommand;
use Flarum\PackageManager\Command\CheckForUpdates;
use Flarum\PackageManager\Event\FlarumUpdated;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\NullOutput;
class FlarumUpdateListener
class ClearCacheAfterUpdate
{
/**
* @var ClearCacheCommand
@ -35,36 +33,20 @@ class FlarumUpdateListener
*/
private $migrate;
/**
* @var Dispatcher
*/
private $bus;
/**
* @param ClearCacheCommand $clearCache
* @param AssetsPublishCommand $publishAssets
* @param MigrateCommand $migrate
* @param Dispatcher $bus
*/
public function __construct(ClearCacheCommand $clearCache, AssetsPublishCommand $publishAssets, MigrateCommand $migrate, Dispatcher $bus)
public function __construct(ClearCacheCommand $clearCache, AssetsPublishCommand $publishAssets, MigrateCommand $migrate)
{
$this->clearCache = $clearCache;
$this->publishAssets = $publishAssets;
$this->migrate = $migrate;
$this->bus = $bus;
}
/**
* @throws \Exception
*/
public function handle(FlarumUpdated $event)
public function handle(FlarumUpdated $event): void
{
$this->clearCache->run(new ArrayInput([]), new NullOutput());
$this->migrate->run(new ArrayInput([]), new NullOutput());
$this->publishAssets->run(new ArrayInput([]), new NullOutput());
$this->bus->dispatch(
new CheckForUpdates($event->actor)
);
}
}

View File

@ -0,0 +1,68 @@
<?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\PackageManager\Listener;
use Flarum\Bus\Dispatcher;
use Flarum\PackageManager\Command\CheckForUpdates;
use Flarum\PackageManager\Event\FlarumUpdated;
use Flarum\PackageManager\Extension\Event\Updated;
use Flarum\PackageManager\Settings\LastUpdateCheck;
use Flarum\PackageManager\Settings\LastUpdateRun;
class ReCheckForUpdates
{
/**
* @var LastUpdateRun
*/
private $lastUpdateRun;
/**
* @var LastUpdateCheck
*/
private $lastUpdateCheck;
/**
* @var Dispatcher
*/
private $bus;
public function __construct(LastUpdateRun $lastUpdateRun, LastUpdateCheck $lastUpdateCheck, Dispatcher $bus)
{
$this->lastUpdateRun = $lastUpdateRun;
$this->lastUpdateCheck = $lastUpdateCheck;
$this->bus = $bus;
}
/**
* @param FlarumUpdated|Updated $event
*/
public function handle($event): void
{
$previousUpdateCheck = $this->lastUpdateCheck->get();
$lastUpdateCheck = $this->bus->dispatch(
new CheckForUpdates($event->actor)
);
if ($event instanceof FlarumUpdated) {
$mapPackageName = function (array $package) {
return $package['name'];
};
$previousPackages = array_map($mapPackageName, $previousUpdateCheck['updates']['installed']);
$lastPackages = array_map($mapPackageName, $lastUpdateCheck['updates']['installed']);
$this->lastUpdateRun
->for($event->type)
->with('status', LastUpdateRun::SUCCESS)
->with('limitedPackages', array_intersect($previousPackages, $lastPackages))
->save();
}
}
}

View File

@ -17,6 +17,7 @@ use Flarum\Foundation\Paths;
use Flarum\Frontend\RecompileFrontendAssets;
use Flarum\Locale\LocaleManager;
use Flarum\PackageManager\Composer\ComposerAdapter;
use Flarum\PackageManager\Listener\ReCheckForUpdates;
use Illuminate\Contracts\Container\Container;
use Illuminate\Contracts\Events\Dispatcher;
use Monolog\Formatter\LineFormatter;
@ -24,7 +25,7 @@ use Monolog\Handler\RotatingFileHandler;
use Monolog\Logger;
use Flarum\PackageManager\Event\FlarumUpdated;
use Flarum\PackageManager\Extension\Event\Updated;
use Flarum\PackageManager\Listener\FlarumUpdateListener;
use Flarum\PackageManager\Listener\ClearCacheAfterUpdate;
class PackageManagerServiceProvider extends AbstractServiceProvider
{
@ -89,6 +90,7 @@ class PackageManagerServiceProvider extends AbstractServiceProvider
}
);
$events->listen(FlarumUpdated::class, FlarumUpdateListener::class);
$events->listen(FlarumUpdated::class, ClearCacheAfterUpdate::class);
$events->listen([FlarumUpdated::class, Updated::class], ReCheckForUpdates::class);
}
}

View File

@ -13,10 +13,12 @@ use Flarum\Foundation\AbstractValidator;
class RequirePackageValidator extends AbstractValidator
{
public const PACKAGE_NAME_REGEX = '/^[A-z0-9-_]+\/[A-z-0-9]+(?::[A-z-0-9.->=<_]+){0,1}$/i';
/**
* {@inheritdoc}
*/
protected $rules = [
'package' => ['required', 'string', 'regex:/^[A-z0-9-_]+\/[A-z-0-9]+(?::[A-z-0-9.->=<_]+){0,1}$/i']
'package' => ['required', 'string', 'regex:'.self::PACKAGE_NAME_REGEX]
];
}

View File

@ -0,0 +1,16 @@
<?php
namespace Flarum\PackageManager\Settings;
interface JsonSetting
{
public function with(string $key, $value): self;
public function save(): array;
public function get(): array;
public static function key(): string;
public static function default(): array;
}

View File

@ -0,0 +1,78 @@
<?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\PackageManager\Settings;
use Carbon\Carbon;
use Flarum\Settings\SettingsRepositoryInterface;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
class LastUpdateCheck implements JsonSetting
{
/**
* @var SettingsRepositoryInterface
*/
protected $settings;
protected $data = [];
public function __construct(SettingsRepositoryInterface $settings)
{
$this->settings = $settings;
}
public function with(string $key, $value): JsonSetting
{
$this->data[$key] = $value;
return $this;
}
public function save(): array
{
$lastUpdateCheck = [
'checkedAt' => Carbon::now(),
'updates' => $this->data,
];
$this->settings->set($this->key(), json_encode($lastUpdateCheck));
return $lastUpdateCheck;
}
public function get(): array
{
return json_decode($this->settings->get($this->key()), true);
}
public static function key(): string
{
return 'flarum-package-manager.last_update_check';
}
public static function default(): array
{
return [
'checkedAt' => null,
'updates' => [
'installed' => [],
],
];
}
public function getNewMajorVersion(): ?string
{
$core = Arr::first(Arr::get($this->get(), 'updates.installed', []), function ($package) {
return $package['name'] === 'flarum/core';
});
return $core ? $core['latest-major'] : null;
}
}

View File

@ -0,0 +1,91 @@
<?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\PackageManager\Settings;
use Carbon\Carbon;
use Flarum\PackageManager\Event\FlarumUpdated;
use Flarum\Settings\SettingsRepositoryInterface;
class LastUpdateRun implements JsonSetting
{
public const SUCCESS = 'success';
public const FAILURE = 'failure';
/**
* @var SettingsRepositoryInterface
*/
protected $settings;
protected $data;
/**
* @var {'major'|'minor'|'global'}
*/
protected $activeUpdate;
public function __construct(SettingsRepositoryInterface $settings)
{
$this->settings = $settings;
$this->data = self::default();
}
public function for(string $update): self
{
if (! in_array($update, [FlarumUpdated::MAJOR, FlarumUpdated::MINOR, FlarumUpdated::GLOBAL])) {
throw new \InvalidArgumentException("Last update runs can only be for one of: minor, major, global");
}
$this->activeUpdate = $update;
return $this;
}
public function with(string $key, $value): JsonSetting
{
$this->data[$this->activeUpdate][$key] = $value;
return $this;
}
public function save(): array
{
$this->data[$this->activeUpdate]['ranAt'] = Carbon::now();
$this->settings->set(self::key(), json_encode($this->data));
return $this->data;
}
public function get(): array
{
return json_decode($this->settings->get(self::key()), true);
}
public static function key(): string
{
return 'flarum-package-manager.last_update_run';
}
public static function default(): array
{
$defaultState = [
'ranAt' => null,
'status' => null,
'limitedPackages' => [],
'incompatibleExtensions' => [],
];
return [
FlarumUpdated::GLOBAL => $defaultState,
FlarumUpdated::MINOR => $defaultState,
FlarumUpdated::MAJOR => $defaultState,
];
}
}

View File

@ -0,0 +1,16 @@
<?php
namespace Flarum\PackageManager;
use Flarum\Foundation\AbstractValidator;
class WhyNotValidator extends AbstractValidator
{
/**
* {@inheritdoc}
*/
protected $rules = [
'package' => ['required', 'string', 'regex:'.RequirePackageValidator::PACKAGE_NAME_REGEX],
'version' => ['sometimes', 'string', 'regex:/(?:\*|[A-z0-9.-]+)/i']
];
}