From e2281a21230b23a635f742766ac3487b1d441f0a Mon Sep 17 00:00:00 2001 From: Sami Mazouz Date: Fri, 10 Nov 2023 22:20:18 +0100 Subject: [PATCH] chore: handle deprecations from 1.x (#3909) * chore: drop deprecated `post_number_index` column * chore: remove deprecated `FlagsWillBeDeleted` event * chore: `Migration::addSettings` can still be needed * chore: `settings->get` default can still be needed * chore: deprecated `$default` in `Settings::serializeToForum` extender * chore: deprecated request `actor` attribute * chore: already handled * chore: remove `RecompileFrontendAssets::whenSettingsSaved` * chore: remove `getReadIds` * chore: `Model::dateAttribute` extender * chore: `evented` js util * chore: `WelcomeHero` js hidden prop * chore: attributes pushData with relations * chore: app request options `extract` * chore: itemlist deprecations * chore: `search` state * chore: `getMentionText` * chore: deprecated non-registered store type * chore: `Button` title * chore: `Modal` deprecations * chore * chore: deprecated `less` mixins * Apply fixes from StyleCI * fix * fix: phpstan * fix * fix --------- Co-authored-by: StyleCI Bot --- extensions/embed/less/forum.less | 2 +- .../flags/js/src/forum/addFlagsToPosts.js | 2 +- .../flags/src/Command/DeleteFlagsHandler.php | 4 - .../flags/src/Event/FlagsWillBeDeleted.php | 27 --- extensions/mentions/js/src/forum/forum.js | 1 - .../js/src/forum/utils/getMentionText.js | 21 --- extensions/nicknames/extend.php | 3 +- .../js/src/admin/components/LoadingModal.tsx | 7 +- framework/core/js/src/common/Application.tsx | 21 +-- framework/core/js/src/common/Model.ts | 5 - framework/core/js/src/common/Store.ts | 14 +- .../core/js/src/common/components/Button.tsx | 17 +- .../core/js/src/common/components/Modal.tsx | 48 ------ .../core/js/src/common/utils/ItemList.ts | 63 +------ framework/core/js/src/common/utils/evented.js | 109 ------------ .../core/js/src/forum/components/Search.tsx | 19 --- .../js/src/forum/components/WelcomeHero.tsx | 6 - framework/core/less/common/Button.less | 2 +- .../less/common/mixins/vendor-prefixes.less | 160 ------------------ ...er_index_column_from_discussions_table.php | 12 ++ .../core/src/Admin/AdminServiceProvider.php | 12 -- framework/core/src/Database/Migration.php | 2 +- framework/core/src/Discussion/Discussion.php | 1 - .../src/Discussion/DiscussionRepository.php | 13 -- framework/core/src/Extend/Frontend.php | 12 -- framework/core/src/Extend/Model.php | 14 -- framework/core/src/Extend/Settings.php | 8 +- .../core/src/Forum/ForumServiceProvider.php | 6 - .../src/Frontend/RecompileFrontendAssets.php | 9 - framework/core/src/Http/RequestUtil.php | 3 - .../Settings/DefaultSettingsRepository.php | 2 - .../Settings/SettingsRepositoryInterface.php | 6 +- framework/core/src/helpers.php | 2 +- .../integration/extenders/SettingsTest.php | 46 ----- .../policy/DiscussionPolicyTest.php | 2 +- 35 files changed, 48 insertions(+), 633 deletions(-) delete mode 100644 extensions/flags/src/Event/FlagsWillBeDeleted.php delete mode 100644 extensions/mentions/js/src/forum/utils/getMentionText.js delete mode 100644 framework/core/js/src/common/utils/evented.js create mode 100644 framework/core/migrations/2023_10_23_000000_drop_post_number_index_column_from_discussions_table.php diff --git a/extensions/embed/less/forum.less b/extensions/embed/less/forum.less index d195646aa3..4b0959f862 100644 --- a/extensions/embed/less/forum.less +++ b/extensions/embed/less/forum.less @@ -50,7 +50,7 @@ padding: 15px 15px; .scrolled & { - .box-shadow(0 2px 6px var(--shadow-color)); + box-shadow: 0 2px 6px var(--shadow-color); } } diff --git a/extensions/flags/js/src/forum/addFlagsToPosts.js b/extensions/flags/js/src/forum/addFlagsToPosts.js index 018d6307f8..9002002c5a 100644 --- a/extensions/flags/js/src/forum/addFlagsToPosts.js +++ b/extensions/flags/js/src/forum/addFlagsToPosts.js @@ -54,7 +54,7 @@ export default function () { const controls = PostControls.destructiveControls(this.attrs.post); - Object.keys(controls.items).forEach((k) => { + Object.keys(controls.toObject()).forEach((k) => { const attrs = controls.get(k).attrs; attrs.className = 'Button'; diff --git a/extensions/flags/src/Command/DeleteFlagsHandler.php b/extensions/flags/src/Command/DeleteFlagsHandler.php index ffb4e008e0..be90e591ab 100644 --- a/extensions/flags/src/Command/DeleteFlagsHandler.php +++ b/extensions/flags/src/Command/DeleteFlagsHandler.php @@ -10,7 +10,6 @@ namespace Flarum\Flags\Command; use Flarum\Flags\Event\Deleting; -use Flarum\Flags\Event\FlagsWillBeDeleted; use Flarum\Post\Post; use Flarum\Post\PostRepository; use Illuminate\Events\Dispatcher; @@ -31,9 +30,6 @@ public function handle(DeleteFlags $command): Post $actor->assertCan('viewFlags', $post->discussion); - // Deprecated, removed v2.0 - $this->events->dispatch(new FlagsWillBeDeleted($post, $actor, $command->data)); - foreach ($post->flags as $flag) { $this->events->dispatch(new Deleting($flag, $actor, $command->data)); } diff --git a/extensions/flags/src/Event/FlagsWillBeDeleted.php b/extensions/flags/src/Event/FlagsWillBeDeleted.php deleted file mode 100644 index d2f4265917..0000000000 --- a/extensions/flags/src/Event/FlagsWillBeDeleted.php +++ /dev/null @@ -1,27 +0,0 @@ -default('flarum-nicknames.set_on_registration', true) ->default('flarum-nicknames.min', 1) ->default('flarum-nicknames.max', 150) - ->serializeToForum('displayNameDriver', 'display_name_driver', null, 'username') + ->default('display_name_driver', 'username') + ->serializeToForum('displayNameDriver', 'display_name_driver') ->serializeToForum('setNicknameOnRegistration', 'flarum-nicknames.set_on_registration', 'boolval') ->serializeToForum('randomizeUsernameOnRegistration', 'flarum-nicknames.random_username', 'boolval'), diff --git a/framework/core/js/src/admin/components/LoadingModal.tsx b/framework/core/js/src/admin/components/LoadingModal.tsx index 36f223ff33..f0bd33508c 100644 --- a/framework/core/js/src/admin/components/LoadingModal.tsx +++ b/framework/core/js/src/admin/components/LoadingModal.tsx @@ -4,10 +4,9 @@ import Modal, { IInternalModalAttrs } from '../../common/components/Modal'; export interface ILoadingModalAttrs extends IInternalModalAttrs {} export default class LoadingModal extends Modal { - /** - * @inheritdoc - */ - static readonly isDismissible: boolean = false; + protected static readonly isDismissibleViaCloseButton: boolean = false; + protected static readonly isDismissibleViaEscKey: boolean = false; + protected static readonly isDismissibleViaBackdropClick: boolean = false; className() { return 'LoadingModal Modal--small'; diff --git a/framework/core/js/src/common/Application.tsx b/framework/core/js/src/common/Application.tsx index cb086cfd80..bccc69b183 100644 --- a/framework/core/js/src/common/Application.tsx +++ b/framework/core/js/src/common/Application.tsx @@ -45,13 +45,6 @@ export type FlarumGenericRoute = RouteItem; export interface FlarumRequestOptions extends Omit, 'extract'> { errorHandler?: (error: RequestError) => void; url: string; - // TODO: [Flarum 2.0] Remove deprecated option - /** - * Manipulate the response text before it is parsed into JSON. - * - * @deprecated Please use `modifyText` instead. - */ - extract?: (responseText: string) => string; /** * Manipulate the response text before it is parsed into JSON. * @@ -434,7 +427,7 @@ export default class Application { } protected transformRequestOptions(flarumOptions: FlarumRequestOptions): InternalFlarumRequestOptions { - const { background, deserialize, extract, modifyText, ...tmpOptions } = { ...flarumOptions }; + const { background, deserialize, modifyText, ...tmpOptions } = { ...flarumOptions }; // Unless specified otherwise, requests should run asynchronously in the // background, so that they don't prevent redraws from occurring. @@ -446,11 +439,6 @@ export default class Application { const defaultDeserialize = (response: string) => response as ResponseType; - // When extracting the data from the response, we can check the server - // response code and show an error message to the user if something's gone - // awry. - const originalExtract = modifyText || extract; - const options: InternalFlarumRequestOptions = { background: background ?? defaultBackground, deserialize: deserialize ?? defaultDeserialize, @@ -474,11 +462,14 @@ export default class Application { options.method = 'POST'; } + // When extracting the data from the response, we can check the server + // response code and show an error message to the user if something's gone + // awry. options.extract = (xhr: XMLHttpRequest) => { let responseText; - if (originalExtract) { - responseText = originalExtract(xhr.responseText); + if (modifyText) { + responseText = modifyText(xhr.responseText); } else { responseText = xhr.responseText; } diff --git a/framework/core/js/src/common/Model.ts b/framework/core/js/src/common/Model.ts index 2a6e5b6978..ae769edd30 100644 --- a/framework/core/js/src/common/Model.ts +++ b/framework/core/js/src/common/Model.ts @@ -1,6 +1,5 @@ import app from '../common/app'; import { FlarumRequestOptions } from './Application'; -import { fireDeprecationWarning } from './helpers/fireDebugWarning'; import Store, { ApiPayloadSingle, ApiResponseSingle, MetaInformation } from './Store'; export interface ModelIdentifier { @@ -113,15 +112,11 @@ export default abstract class Model { if ('attributes' in data) { this.data.attributes ||= {}; - // @deprecated // Filter out relationships that got in by accident. for (const key in data.attributes) { const val = data.attributes[key]; if (val && val instanceof Model) { - fireDeprecationWarning('Providing models as attributes to `Model.pushData()` or `Model.pushAttributes()` is deprecated.', '3249'); delete data.attributes[key]; - data.relationships ||= {}; - data.relationships[key] = { data: Model.getIdentifier(val) }; } } diff --git a/framework/core/js/src/common/Store.ts b/framework/core/js/src/common/Store.ts index 0293a2f795..a6489c797b 100644 --- a/framework/core/js/src/common/Store.ts +++ b/framework/core/js/src/common/Store.ts @@ -1,6 +1,5 @@ import app from '../common/app'; import { FlarumRequestOptions } from './Application'; -import { fireDeprecationWarning } from './helpers/fireDebugWarning'; import Model, { ModelData, SavedModelData } from './Model'; export interface MetaInformation { @@ -100,7 +99,7 @@ export default class Store { pushPayload(payload: ApiPayload): ApiResponse> { if (payload.included) payload.included.map(this.pushObject.bind(this)); - const models = payload.data instanceof Array ? payload.data.map((o) => this.pushObject(o, false)) : this.pushObject(payload.data, false); + const models = payload.data instanceof Array ? payload.data.map((o) => this.pushObject(o)) : this.pushObject(payload.data); const result = models as ApiResponse>; // Attach the original payload to the model that we give back. This is @@ -120,14 +119,11 @@ export default class Store { * registered for this resource type. */ pushObject(data: SavedModelData): M | null; - pushObject(data: SavedModelData, allowUnregistered: false): M; - pushObject(data: SavedModelData, allowUnregistered = true): M | null { + pushObject(data: SavedModelData): M | null { if (!this.models[data.type]) { - if (!allowUnregistered) { - setTimeout(() => - fireDeprecationWarning(`Pushing object of type \`${data.type}\` not allowed, as type not yet registered in the store.`, '3206') - ); - } + setTimeout(() => { + throw new Error(`Pushing object of type \`${data.type}\` not allowed, as type not yet registered in the store.`); + }); return null; } diff --git a/framework/core/js/src/common/components/Button.tsx b/framework/core/js/src/common/components/Button.tsx index 009e67ef5d..641c46f7ed 100644 --- a/framework/core/js/src/common/components/Button.tsx +++ b/framework/core/js/src/common/components/Button.tsx @@ -27,18 +27,6 @@ export interface IButtonAttrs extends ComponentAttrs { * Default: `false` */ loading?: boolean; - /** - * **DEPRECATED:** Please use the `aria-label` attribute instead. For tooltips, use - * the `` component. - * - * Accessible text for the button. This should always be present if the button only - * contains an icon. - * - * The textual content of this attribute is passed to the DOM element as `aria-label`. - * - * @deprecated - */ - title?: string | Mithril.ChildArray; /** * Accessible text for the button. This should always be present if the button only * contains an icon. @@ -68,14 +56,11 @@ export interface IButtonAttrs extends ComponentAttrs { */ export default class Button extends Component { view(vnode: Mithril.VnodeDOM) { - let { type, title, 'aria-label': ariaLabel, icon: iconName, disabled, loading, className, class: _class, ...attrs } = this.attrs; + let { type, 'aria-label': ariaLabel, icon: iconName, disabled, loading, className, class: _class, ...attrs } = this.attrs; // If no `type` attr provided, set to "button" type ||= 'button'; - // Use `title` attribute as `aria-label` if none provided - ariaLabel ||= title; - // If given a translation object, extract the text. if (typeof ariaLabel === 'object') { ariaLabel = extractText(ariaLabel); diff --git a/framework/core/js/src/common/components/Modal.tsx b/framework/core/js/src/common/components/Modal.tsx index 376dc9dd3b..3e6e0275cf 100644 --- a/framework/core/js/src/common/components/Modal.tsx +++ b/framework/core/js/src/common/components/Modal.tsx @@ -17,10 +17,6 @@ export interface IInternalModalAttrs { } export interface IDismissibleOptions { - /** - * @deprecated Check specific individual attributes instead. Will be removed in Flarum 2.0. - */ - isDismissible: boolean; viaCloseButton: boolean; viaEscKey: boolean; viaBackdropClick: boolean; @@ -34,14 +30,6 @@ export default abstract class Modal { - // TODO: [Flarum 2.0] remove `isDismissible` static attribute - /** - * Determine whether or not the modal should be dismissible via an 'x' button. - * - * @deprecated Use the individual `isDismissibleVia...` attributes instead and remove references to this. - */ - static readonly isDismissible: boolean = true; - /** * Can the model be dismissed with a close button (X)? * @@ -58,18 +46,7 @@ export default abstract class Modal) { - super.oninit(vnode); - - // TODO: [Flarum 2.0] Remove the code below. - // This code prevents extensions which do not implement all abstract methods of this class from breaking - // the forum frontend. Without it, function calls would would error rather than returning `undefined.` - - const missingMethods: string[] = []; - - ['className', 'title', 'content', 'onsubmit'].forEach((method) => { - if (!(this as any)[method]) { - (this as any)[method] = function (): void {}; - missingMethods.push(method); - } - }); - - if (missingMethods.length > 0) { - fireDebugWarning( - `Modal \`${this.constructor.name}\` does not implement all abstract methods of the Modal super class. Missing methods: ${missingMethods.join( - ', ' - )}.` - ); - } - } - oncreate(vnode: Mithril.VnodeDOM) { super.oncreate(vnode); diff --git a/framework/core/js/src/common/utils/ItemList.ts b/framework/core/js/src/common/utils/ItemList.ts index a18819d219..c39ba1d6e4 100644 --- a/framework/core/js/src/common/utils/ItemList.ts +++ b/framework/core/js/src/common/utils/ItemList.ts @@ -26,24 +26,6 @@ export default class ItemList { */ protected _items: Record> = {}; - // TODO: [Flarum 2.0] Remove `.items` getter. - /** - * A **read-only copy** of items in the list. - * - * We don't allow adding new items to the ItemList via setting new properties, - * nor do we allow modifying existing items directly. - * - * @deprecated Use {@link ItemList.toObject} instead. - */ - get items(): DeepReadonly>> { - return new Proxy(this._items, { - set() { - console.warn('Modifying `ItemList.items` is not allowed.'); - return false; - }, - }); - } - /** * Check whether the list is empty. */ @@ -86,44 +68,6 @@ export default class ItemList { return this; } - // TODO: [Flarum 2.0] Remove deprecated `.replace()` method. - /** - * Replace an item and/or priority in the list, only if it is already present. - * - * If `content` or `priority` are `null`, these values will not be replaced. - * - * If the provided `key` is not present, nothing will happen. - * - * @deprecated Please use the {@link ItemList.setContent} and {@link ItemList.setPriority} - * methods to replace items and their priorities. This method will be removed in Flarum 2.0. - * - * @param key The key of the item in the list - * @param content The item's new content - * @param priority The item's new priority - * - * @example Replace priority and not content. - * items.replace('myItem', null, 10); - * - * @example Replace content and not priority. - * items.replace('myItem',

My new value.

); - * - * @example Replace content and priority. - * items.replace('myItem',

My new value.

, 10); - */ - replace(key: string, content: T | null = null, priority: number | null = null): this { - if (!this.has(key)) return this; - - if (content !== null) { - this._items[key].content = content; - } - - if (priority !== null) { - this._items[key].priority = priority; - } - - return this; - } - /** * Replaces an item's content, if the provided item key exists. * @@ -147,8 +91,11 @@ export default class ItemList { throw new Error(`[ItemList] Cannot set content of Item. Key \`${key}\` is not present.`); } - // Saves on bundle size to call the deprecated method internally - return this.replace(key, content); + if (content !== null) { + this._items[key].content = content; + } + + return this; } /** diff --git a/framework/core/js/src/common/utils/evented.js b/framework/core/js/src/common/utils/evented.js deleted file mode 100644 index 1aa9e359cc..0000000000 --- a/framework/core/js/src/common/utils/evented.js +++ /dev/null @@ -1,109 +0,0 @@ -import { fireDeprecationWarning } from '../helpers/fireDebugWarning'; - -const deprecatedNotice = 'The `evented` util is deprecated and no longer supported.'; -const deprecationIssueId = '2547'; - -/** - * The `evented` mixin provides methods allowing an object to trigger events, - * running externally registered event handlers. - * - * @deprecated v1.2, to be removed in v2.0 - */ -export default { - /** - * Arrays of registered event handlers, grouped by the event name. - * - * @type {Record} - * @protected - * - * @deprecated - */ - handlers: null, - - /** - * Get all of the registered handlers for an event. - * - * @param {string} event The name of the event. - * @return {Function[]} - * @protected - * - * @deprecated - */ - getHandlers(event) { - fireDeprecationWarning(deprecatedNotice, deprecationIssueId); - - this.handlers = this.handlers || {}; - - this.handlers[event] = this.handlers[event] || []; - - return this.handlers[event]; - }, - - /** - * Trigger an event. - * - * @param {string} event The name of the event. - * @param {any[]} args Arguments to pass to event handlers. - * - * @deprecated - */ - trigger(event, ...args) { - fireDeprecationWarning(deprecatedNotice, deprecationIssueId); - - this.getHandlers(event).forEach((handler) => handler.apply(this, args)); - }, - - /** - * Register an event handler. - * - * @param {string} event The name of the event. - * @param {Function} handler The function to handle the event. - * - * @deprecated - */ - on(event, handler) { - fireDeprecationWarning(deprecatedNotice, deprecationIssueId); - - this.getHandlers(event).push(handler); - }, - - /** - * Register an event handler so that it will run only once, and then - * unregister itself. - * - * @param {string} event The name of the event. - * @param {Function} handler The function to handle the event. - * - * @deprecated - */ - one(event, handler) { - fireDeprecationWarning(deprecatedNotice, deprecationIssueId); - - const wrapper = function () { - handler.apply(this, arguments); - - this.off(event, wrapper); - }; - - this.getHandlers(event).push(wrapper); - }, - - /** - * Unregister an event handler. - * - * @param {string} event The name of the event. - * @param {Function} handler The function that handles the event. - * - * @deprecated - */ - off(event, handler) { - fireDeprecationWarning(deprecatedNotice, deprecationIssueId); - - const handlers = this.getHandlers(event); - const index = handlers.indexOf(handler); - - if (index !== -1) { - handlers.splice(index, 1); - } - }, -}; diff --git a/framework/core/js/src/forum/components/Search.tsx b/framework/core/js/src/forum/components/Search.tsx index ac892cb186..c77744f0d3 100644 --- a/framework/core/js/src/forum/components/Search.tsx +++ b/framework/core/js/src/forum/components/Search.tsx @@ -8,7 +8,6 @@ import KeyboardNavigatable from '../../common/utils/KeyboardNavigatable'; import SearchState from '../states/SearchState'; import DiscussionsSearchSource from './DiscussionsSearchSource'; import UsersSearchSource from './UsersSearchSource'; -import { fireDeprecationWarning } from '../../common/helpers/fireDebugWarning'; import type Mithril from 'mithril'; import Icon from '../../common/components/Icon'; @@ -64,24 +63,6 @@ export default class Search extends Compone */ protected searchState!: SearchState; - /** - * The instance of `SearchState` for this component. - * - * @deprecated Replace with`this.searchState` instead. - */ - // TODO: [Flarum 2.0] Remove this. - // @ts-expect-error This is a get accessor, while superclass defines this as a property. This is needed to prevent breaking changes, however. - get state() { - fireDeprecationWarning('`state` property of the Search component is deprecated', '3212'); - return this.searchState; - } - set state(state: SearchState) { - // Workaround to prevent triggering deprecation warnings due to Mithril - // setting state to undefined when creating components - state !== undefined && fireDeprecationWarning('`state` property of the Search component is deprecated', '3212'); - this.searchState = state; - } - /** * Whether or not the search input has focus. */ diff --git a/framework/core/js/src/forum/components/WelcomeHero.tsx b/framework/core/js/src/forum/components/WelcomeHero.tsx index e93bd4e9e4..48213dbe99 100644 --- a/framework/core/js/src/forum/components/WelcomeHero.tsx +++ b/framework/core/js/src/forum/components/WelcomeHero.tsx @@ -13,11 +13,6 @@ const LOCAL_STORAGE_KEY = 'welcomeHidden'; * forum. */ export default class WelcomeHero extends Component { - /** - * @deprecated Extend the `isHidden` method instead. - */ - hidden: boolean = false; - oninit(vnode: Mithril.Vnode) { super.oninit(vnode); } @@ -60,7 +55,6 @@ export default class WelcomeHero extends Component { isHidden(): boolean { if (!app.forum.attribute('welcomeTitle')?.trim()) return true; if (localStorage.getItem(LOCAL_STORAGE_KEY)) return true; - if (this.hidden) return true; return false; } diff --git a/framework/core/less/common/Button.less b/framework/core/less/common/Button.less index f6b829d9a0..2c8d5555b2 100644 --- a/framework/core/less/common/Button.less +++ b/framework/core/less/common/Button.less @@ -68,7 +68,7 @@ &:active, &.active, .open > &.Dropdown-toggle { - .box-shadow(inset 0 3px 5px rgba(0, 0, 0, .125)); + box-shadow: inset 0 3px 5px rgba(0, 0, 0, .125); } &.disabled, diff --git a/framework/core/less/common/mixins/vendor-prefixes.less b/framework/core/less/common/mixins/vendor-prefixes.less index 6286204d51..13a4a40dd5 100644 --- a/framework/core/less/common/mixins/vendor-prefixes.less +++ b/framework/core/less/common/mixins/vendor-prefixes.less @@ -4,84 +4,6 @@ // The vendor presets below are to try to remain compatible with iOS 9+ and other // major browsers (Chrome/Firefox/new Edge/Safari desktop). -// Animations -// These remain for backwards compatibility with existing styles. -/** @deprecated */ -.animation(@animation) { - animation: @animation; -} -/** @deprecated */ -.animation-name(@name) { - animation-name: @name; -} -.animation-duration(@duration) { - animation-duration: @duration; -} -/** @deprecated */ -.animation-timing-function(@timing-function) { - animation-timing-function: @timing-function; -} -/** @deprecated */ -.animation-delay(@delay) { - animation-delay: @delay; -} -/** @deprecated */ -.animation-iteration-count(@iteration-count) { - animation-iteration-count: @iteration-count; -} -/** @deprecated */ -.animation-direction(@direction) { - animation-direction: @direction; -} -/** @deprecated */ -.animation-fill-mode(@fill-mode) { - animation-fill-mode: @fill-mode; -} - -// Backface visibility -// Prevent browsers from flickering when using CSS 3D transforms. -// Default value is `visible`, but can be changed to `hidden` -/** @deprecated */ -.backface-visibility(@visibility) { - // Safari - -webkit-backface-visibility: @visibility; - backface-visibility: @visibility; -} - -// Drop shadows -// These remain for backwards compatibility with existing styles. -/** @deprecated */ -.box-shadow(@shadow) { - box-shadow: @shadow; -} - -// Box sizing -// These remain for backwards compatibility with existing styles. -/** @deprecated */ -.box-sizing(@boxmodel) { - box-sizing: @boxmodel; -} - -// CSS3 Content Columns -/** @deprecated */ -.content-columns(@column-count; @column-gap: @grid-gutter-width) { - // Safari - -webkit-column-count: @column-count; - column-count: @column-count; - // Safari - -webkit-column-gap: @column-gap; - column-gap: @column-gap; -} - -// Optional hyphenation -/** @deprecated */ -.hyphens(@mode: auto) { - word-wrap: break-word; - // Safari - -webkit-hyphens: @mode; - hyphens: @mode; -} - // Placeholder text .placeholder(@color) { // Safari @@ -91,88 +13,6 @@ } } -// Transformations -// These remain for backwards compatibility with existing styles. -/** @deprecated */ -.scale(@ratio) { - transform: scale(@ratio); -} -/** @deprecated */ -.scale(@ratioX; @ratioY) { - transform: scale(@ratioX, @ratioY); -} -/** @deprecated */ -.scaleX(@ratio) { - transform: scaleX(@ratio); -} -/** @deprecated */ -.scaleY(@ratio) { - transform: scaleY(@ratio); -} -/** @deprecated */ -.skew(@x; @y) { - transform: skewX(@x) skewY(@y); -} -/** @deprecated */ -.translate(@x; @y) { - transform: translate(@x, @y); -} -/** @deprecated */ -.translate3d(@x; @y; @z) { - transform: translate3d(@x, @y, @z); -} -/** @deprecated */ -.rotate(@degrees) { - transform: rotate(@degrees); -} -/** @deprecated */ -.rotateX(@degrees) { - transform: rotateX(@degrees); -} -/** @deprecated */ -.rotateY(@degrees) { - transform: rotateY(@degrees); -} -/** @deprecated */ -.perspective(@perspective) { - perspective: @perspective; -} -/** @deprecated */ -.perspective-origin(@perspective) { - perspective-origin: @perspective; -} -/** @deprecated */ -.transform-origin(@origin) { - transform-origin: @origin; -} - -// Transitions -// These remain for backwards compatibility with existing styles. -/** @deprecated */ -.transition(@transition) { - transition: @transition; -} -/** @deprecated */ -.transition-property(@transition-property) { - transition-property: @transition-property; -} -/** @deprecated */ -.transition-delay(@transition-delay) { - transition-delay: @transition-delay; -} -/** @deprecated */ -.transition-duration(@transition-duration) { - transition-duration: @transition-duration; -} -/** @deprecated */ -.transition-timing-function(@timing-function) { - transition-timing-function: @timing-function; -} -/** @deprecated */ -.transition-transform(@transition) { - transition: transform @transition; -} - // User select // For selecting text on the page .user-select(@select) { diff --git a/framework/core/migrations/2023_10_23_000000_drop_post_number_index_column_from_discussions_table.php b/framework/core/migrations/2023_10_23_000000_drop_post_number_index_column_from_discussions_table.php new file mode 100644 index 0000000000..caa611250f --- /dev/null +++ b/framework/core/migrations/2023_10_23_000000_drop_post_number_index_column_from_discussions_table.php @@ -0,0 +1,12 @@ + '']); diff --git a/framework/core/src/Admin/AdminServiceProvider.php b/framework/core/src/Admin/AdminServiceProvider.php index 384c02c870..a19871b466 100644 --- a/framework/core/src/Admin/AdminServiceProvider.php +++ b/framework/core/src/Admin/AdminServiceProvider.php @@ -26,7 +26,6 @@ use Flarum\Http\RouteHandlerFactory; use Flarum\Http\UrlGenerator; use Flarum\Locale\LocaleManager; -use Flarum\Settings\Event\Saved; use Illuminate\Contracts\Container\Container; use Laminas\Stratigility\MiddlewarePipe; @@ -131,17 +130,6 @@ function () { $recompile->flush(); } ); - - $events->listen( - Saved::class, - function (Saved $event) { - $recompile = new RecompileFrontendAssets( - $this->container->make('flarum.assets.admin'), - $this->container->make(LocaleManager::class) - ); - $recompile->whenSettingsSaved($event); - } - ); } protected function populateRoutes(RouteCollection $routes): void diff --git a/framework/core/src/Database/Migration.php b/framework/core/src/Database/Migration.php index c926378cf3..3ef10cbfbb 100644 --- a/framework/core/src/Database/Migration.php +++ b/framework/core/src/Database/Migration.php @@ -120,7 +120,7 @@ public static function renameColumns(string $tableName, array $columnNames): arr /** * Add default values for config values. * - * @deprecated Use the Settings extender's `default` method instead to register settings. + * You generally should use the Settings extender's `default` method instead to register settings. * @see Settings::default() */ public static function addSettings(array $defaults): array diff --git a/framework/core/src/Discussion/Discussion.php b/framework/core/src/Discussion/Discussion.php index 7cd4a1feb9..8082d8a3c2 100644 --- a/framework/core/src/Discussion/Discussion.php +++ b/framework/core/src/Discussion/Discussion.php @@ -36,7 +36,6 @@ * @property string $slug * @property int $comment_count * @property int $participant_count - * @property int $post_number_index !!DEPRECATED!! * @property \Carbon\Carbon $created_at * @property int|null $user_id * @property int|null $first_post_id diff --git a/framework/core/src/Discussion/DiscussionRepository.php b/framework/core/src/Discussion/DiscussionRepository.php index ace69e7439..61cec343eb 100644 --- a/framework/core/src/Discussion/DiscussionRepository.php +++ b/framework/core/src/Discussion/DiscussionRepository.php @@ -11,7 +11,6 @@ use Flarum\User\User; use Illuminate\Database\Eloquent\Builder; -use Illuminate\Database\Eloquent\Collection; class DiscussionRepository { @@ -34,18 +33,6 @@ public function findOrFail(int|string $id, ?User $user = null): Discussion return $this->scopeVisibleTo($query, $user)->firstOrFail(); } - /** - * Get the IDs of discussions which a user has read completely. - * - * @param User $user - * @return Collection - * @deprecated 1.3 Use `getReadIdsQuery` instead - */ - public function getReadIds(User $user): Collection - { - return $this->getReadIdsQuery($user)->get(); - } - /** * Get a query containing the IDs of discussions which a user has read completely. * diff --git a/framework/core/src/Extend/Frontend.php b/framework/core/src/Extend/Frontend.php index 22ea6c0569..331f63a024 100644 --- a/framework/core/src/Extend/Frontend.php +++ b/framework/core/src/Extend/Frontend.php @@ -23,7 +23,6 @@ use Flarum\Http\RouteCollection; use Flarum\Http\RouteHandlerFactory; use Flarum\Locale\LocaleManager; -use Flarum\Settings\Event\Saved; use Illuminate\Contracts\Container\Container; use Psr\Http\Message\ServerRequestInterface; @@ -253,17 +252,6 @@ function () use ($container, $abstract) { $recompile->flush(); } ); - - $events->listen( - Saved::class, - function (Saved $event) use ($container, $abstract) { - $recompile = new RecompileFrontendAssets( - $container->make($abstract), - $container->make(LocaleManager::class) - ); - $recompile->whenSettingsSaved($event); - } - ); } } diff --git a/framework/core/src/Extend/Model.php b/framework/core/src/Extend/Model.php index 363973be52..c6763ae846 100644 --- a/framework/core/src/Extend/Model.php +++ b/framework/core/src/Extend/Model.php @@ -30,20 +30,6 @@ public function __construct( ) { } - /** - * Add an attribute to be treated as a date. - * - * @param string $attribute - * @return self - * @deprecated use `cast` instead. Will be removed in v2. - */ - public function dateAttribute(string $attribute): self - { - $this->cast($attribute, 'datetime'); - - return $this; - } - /** * Add a custom attribute type cast. Should not be applied to non-extension attributes. * diff --git a/framework/core/src/Extend/Settings.php b/framework/core/src/Extend/Settings.php index 18c83306d6..905b7f96a3 100644 --- a/framework/core/src/Extend/Settings.php +++ b/framework/core/src/Extend/Settings.php @@ -36,13 +36,11 @@ class Settings implements ExtenderInterface * The callable should return: * - mixed $value: The modified value. * - * @todo remove $default in 2.0 - * @param mixed $default: Deprecated optional default serialized value. Will be run through the optional callback. * @return self */ - public function serializeToForum(string $attributeName, string $key, callable|string $callback = null, mixed $default = null): self + public function serializeToForum(string $attributeName, string $key, callable|string $callback = null): self { - $this->settings[$key] = compact('attributeName', 'callback', 'default'); + $this->settings[$key] = compact('attributeName', 'callback'); return $this; } @@ -108,7 +106,7 @@ function () use ($container) { $attributes = []; foreach ($this->settings as $key => $setting) { - $value = $settings->get($key, $setting['default']); + $value = $settings->get($key); if (isset($setting['callback'])) { $callback = ContainerUtil::wrapCallback($setting['callback'], $container); diff --git a/framework/core/src/Forum/ForumServiceProvider.php b/framework/core/src/Forum/ForumServiceProvider.php index 66203febdd..a09b9f4d20 100644 --- a/framework/core/src/Forum/ForumServiceProvider.php +++ b/framework/core/src/Forum/ForumServiceProvider.php @@ -173,12 +173,6 @@ function () use ($container) { $events->listen( Saved::class, function (Saved $event) use ($container) { - $recompile = new RecompileFrontendAssets( - $container->make('flarum.assets.forum'), - $container->make(LocaleManager::class) - ); - $recompile->whenSettingsSaved($event); - $validator = new ValidateCustomLess( $container->make('flarum.assets.forum'), $container->make('flarum.locales'), diff --git a/framework/core/src/Frontend/RecompileFrontendAssets.php b/framework/core/src/Frontend/RecompileFrontendAssets.php index 49c85bbb17..a93f5f0c4f 100644 --- a/framework/core/src/Frontend/RecompileFrontendAssets.php +++ b/framework/core/src/Frontend/RecompileFrontendAssets.php @@ -10,7 +10,6 @@ namespace Flarum\Frontend; use Flarum\Locale\LocaleManager; -use Flarum\Settings\Event\Saved; /** * @internal @@ -23,14 +22,6 @@ public function __construct( ) { } - public function whenSettingsSaved(Saved $event): void - { - // @deprecated 'theme_' check, to be removed in 2.0 - if (preg_grep('/^theme_/i', array_keys($event->settings))) { - $this->flushCss(); - } - } - public function flush(): void { $this->flushCss(); diff --git a/framework/core/src/Http/RequestUtil.php b/framework/core/src/Http/RequestUtil.php index 47f9308687..5029fcedb1 100644 --- a/framework/core/src/Http/RequestUtil.php +++ b/framework/core/src/Http/RequestUtil.php @@ -30,9 +30,6 @@ public static function withActor(Request $request, User $actor): Request $actorReference->setActor($actor); - // @deprecated in 1.0 - $request = $request->withAttribute('actor', $actor); - return $request; } } diff --git a/framework/core/src/Settings/DefaultSettingsRepository.php b/framework/core/src/Settings/DefaultSettingsRepository.php index e1b93bbbd3..da7a9f06db 100644 --- a/framework/core/src/Settings/DefaultSettingsRepository.php +++ b/framework/core/src/Settings/DefaultSettingsRepository.php @@ -21,8 +21,6 @@ public function __construct( public function get(string $key, mixed $default = null): mixed { - // Global default overrules local default because local default is deprecated, - // and will be removed in 2.0 return $this->inner->get($key, $this->defaults->get($key, $default)); } diff --git a/framework/core/src/Settings/SettingsRepositoryInterface.php b/framework/core/src/Settings/SettingsRepositoryInterface.php index 88926c8d63..69469511ab 100644 --- a/framework/core/src/Settings/SettingsRepositoryInterface.php +++ b/framework/core/src/Settings/SettingsRepositoryInterface.php @@ -14,7 +14,11 @@ interface SettingsRepositoryInterface public function all(): array; /** - * @todo remove deprecated $default in 2.0 + * You generally should use the Settings extender's `default` method instead to register default values. + * You may still need to use the `$default` parameters here in cases where you need to + * access the default value of a dynamic setting. + * + * @see Settings::default() */ public function get(string $key, mixed $default = null): mixed; diff --git a/framework/core/src/helpers.php b/framework/core/src/helpers.php index b45ae2d869..4fcef6e84a 100644 --- a/framework/core/src/helpers.php +++ b/framework/core/src/helpers.php @@ -112,7 +112,7 @@ function event($event, $payload = [], $halt = false) if (! function_exists('config')) { /** - * @deprecated do not use, will be transferred to flarum/laravel-helpers. + * @deprecated */ function config(string $key, mixed $default = null): mixed { diff --git a/framework/core/tests/integration/extenders/SettingsTest.php b/framework/core/tests/integration/extenders/SettingsTest.php index 797c59559a..42af179fe9 100644 --- a/framework/core/tests/integration/extenders/SettingsTest.php +++ b/framework/core/tests/integration/extenders/SettingsTest.php @@ -118,52 +118,6 @@ public function custom_setting_callback_works_with_invokable_class() $this->assertEquals('customValueModifiedByInvokable', $payload['data']['attributes']['customPrefix.customSetting2']); } - /** - * @test - */ - public function custom_setting_falls_back_to_default() - { - $this->extend( - (new Extend\Settings()) - ->serializeToForum('customPrefix.noCustomSetting', 'custom-prefix.no_custom_setting', null, 'customDefault') - ); - - $response = $this->send( - $this->request('GET', '/api', [ - 'authenticatedAs' => 1, - ]) - ); - - $payload = json_decode($response->getBody()->getContents(), true); - - $this->assertArrayHasKey('customPrefix.noCustomSetting', $payload['data']['attributes']); - $this->assertEquals('customDefault', $payload['data']['attributes']['customPrefix.noCustomSetting']); - } - - /** - * @test - */ - public function custom_setting_default_passed_to_callback() - { - $this->extend( - (new Extend\Settings()) - ->serializeToForum('customPrefix.noCustomSetting', 'custom-prefix.no_custom_setting', function ($value) { - return $value.'Modified2'; - }, 'customDefault') - ); - - $response = $this->send( - $this->request('GET', '/api', [ - 'authenticatedAs' => 1, - ]) - ); - - $payload = json_decode($response->getBody()->getContents(), true); - - $this->assertArrayHasKey('customPrefix.noCustomSetting', $payload['data']['attributes']); - $this->assertEquals('customDefaultModified2', $payload['data']['attributes']['customPrefix.noCustomSetting']); - } - /** * @test */ diff --git a/framework/core/tests/integration/policy/DiscussionPolicyTest.php b/framework/core/tests/integration/policy/DiscussionPolicyTest.php index f71ee45bb7..b01a68087f 100644 --- a/framework/core/tests/integration/policy/DiscussionPolicyTest.php +++ b/framework/core/tests/integration/policy/DiscussionPolicyTest.php @@ -32,7 +32,7 @@ protected function setUp(): void $this->prepareDatabase([ 'discussions' => [ - ['id' => 1, 'title' => 'Editable discussion', 'created_at' => Carbon::parse('2021-11-01 13:00:00')->toDateTimeString(), 'user_id' => 2, 'first_post_id' => 1, 'comment_count' => 2, 'is_private' => 0, 'last_post_number' => 1, 'post_number_index' => 1, 'participant_count' => 1], + ['id' => 1, 'title' => 'Editable discussion', 'created_at' => Carbon::parse('2021-11-01 13:00:00')->toDateTimeString(), 'user_id' => 2, 'first_post_id' => 1, 'comment_count' => 2, 'is_private' => 0, 'last_post_number' => 1, 'participant_count' => 1], ['id' => 2, 'title' => 'Editable discussion', 'created_at' => Carbon::parse('2021-11-01 13:00:00')->toDateTimeString(), 'user_id' => 2, 'first_post_id' => 2, 'comment_count' => 2, 'is_private' => 0, 'last_post_number' => 2, 'participant_count' => 2], ], 'posts' => [