mirror of
https://github.com/flarum/core.git
synced 2025-08-04 15:37:51 +02:00
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 <bot@styleci.io>
This commit is contained in:
@@ -50,7 +50,7 @@
|
||||
padding: 15px 15px;
|
||||
|
||||
.scrolled & {
|
||||
.box-shadow(0 2px 6px var(--shadow-color));
|
||||
box-shadow: 0 2px 6px var(--shadow-color);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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';
|
||||
|
@@ -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 @@ class DeleteFlagsHandler
|
||||
|
||||
$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));
|
||||
}
|
||||
|
@@ -1,27 +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\Flags\Event;
|
||||
|
||||
use Flarum\Post\Post;
|
||||
use Flarum\User\User;
|
||||
|
||||
/**
|
||||
* @deprecated v2.0
|
||||
* Listen for Flarum\Flags\Event\Deleting instead
|
||||
*/
|
||||
class FlagsWillBeDeleted
|
||||
{
|
||||
public function __construct(
|
||||
public Post $post,
|
||||
public User $actor,
|
||||
public array $data = []
|
||||
) {
|
||||
}
|
||||
}
|
@@ -5,7 +5,6 @@ import './components/UserMentionedNotification';
|
||||
import './fragments/AutocompleteDropdown';
|
||||
import './fragments/PostQuoteButton';
|
||||
import './utils/getCleanDisplayName';
|
||||
import './utils/getMentionText';
|
||||
import './utils/reply';
|
||||
import './utils/selectedText';
|
||||
import './utils/textFormatter';
|
||||
|
@@ -1,21 +0,0 @@
|
||||
import app from 'flarum/forum/app';
|
||||
|
||||
/**
|
||||
* Fetches the mention text for a specified user (and optionally a post ID for replies or group).
|
||||
*
|
||||
* Automatically determines which mention syntax to be used based on the option in the
|
||||
* admin dashboard. Also performs display name clean-up automatically.
|
||||
*
|
||||
* @deprecated Use `app.mentionables.get('user').replacement(user)` instead. Will be removed in 2.0.
|
||||
*/
|
||||
export default function getMentionText(user, postId, group) {
|
||||
if (user !== undefined && postId === undefined) {
|
||||
return app.mentionables.get('user').replacement(user);
|
||||
} else if (user !== undefined && postId !== undefined) {
|
||||
return app.mentionables.get('post').replacement(app.store.getById('posts', postId));
|
||||
} else if (group !== undefined) {
|
||||
return app.mentionables.get('group').replacement(group);
|
||||
}
|
||||
|
||||
throw 'No parameters were passed';
|
||||
}
|
@@ -44,7 +44,8 @@ return [
|
||||
->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'),
|
||||
|
||||
|
@@ -4,10 +4,9 @@ import Modal, { IInternalModalAttrs } from '../../common/components/Modal';
|
||||
export interface ILoadingModalAttrs extends IInternalModalAttrs {}
|
||||
|
||||
export default class LoadingModal<ModalAttrs extends ILoadingModalAttrs = ILoadingModalAttrs> extends Modal<ModalAttrs> {
|
||||
/**
|
||||
* @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';
|
||||
|
@@ -45,13 +45,6 @@ export type FlarumGenericRoute = RouteItem<any, any, any>;
|
||||
export interface FlarumRequestOptions<ResponseType> extends Omit<Mithril.RequestOptions<ResponseType>, '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<ResponseType>(flarumOptions: FlarumRequestOptions<ResponseType>): InternalFlarumRequestOptions<ResponseType> {
|
||||
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<ResponseType> = {
|
||||
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;
|
||||
}
|
||||
|
@@ -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) };
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -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<M extends Model | Model[]>(payload: ApiPayload): ApiResponse<FlatArray<M, 1>> {
|
||||
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<FlatArray<M, 1>>;
|
||||
|
||||
// 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<M extends Model>(data: SavedModelData): M | null;
|
||||
pushObject<M extends Model>(data: SavedModelData, allowUnregistered: false): M;
|
||||
pushObject<M extends Model>(data: SavedModelData, allowUnregistered = true): M | null {
|
||||
pushObject<M extends Model>(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;
|
||||
}
|
||||
|
@@ -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 `<Tooltip>` 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<CustomAttrs extends IButtonAttrs = IButtonAttrs> extends Component<CustomAttrs> {
|
||||
view(vnode: Mithril.VnodeDOM<CustomAttrs, this>) {
|
||||
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);
|
||||
|
@@ -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<ModalAttrs extends IInternalModalAttrs = IIn
|
||||
ModalAttrs,
|
||||
CustomState
|
||||
> {
|
||||
// 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<ModalAttrs extends IInternalModalAttrs = IIn
|
||||
protected static readonly isDismissibleViaBackdropClick: boolean = true;
|
||||
|
||||
static get dismissibleOptions(): IDismissibleOptions {
|
||||
// If someone sets this to `false`, provide the same behaviour as previous versions of Flarum.
|
||||
if (!this.isDismissible) {
|
||||
return {
|
||||
isDismissible: false,
|
||||
viaCloseButton: false,
|
||||
viaEscKey: false,
|
||||
viaBackdropClick: false,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
isDismissible: true,
|
||||
viaCloseButton: this.isDismissibleViaCloseButton,
|
||||
viaEscKey: this.isDismissibleViaEscKey,
|
||||
viaBackdropClick: this.isDismissibleViaBackdropClick,
|
||||
@@ -83,31 +60,6 @@ export default abstract class Modal<ModalAttrs extends IInternalModalAttrs = IIn
|
||||
*/
|
||||
alertAttrs: AlertAttrs | null = null;
|
||||
|
||||
oninit(vnode: Mithril.Vnode<ModalAttrs, this>) {
|
||||
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<ModalAttrs, this>) {
|
||||
super.oncreate(vnode);
|
||||
|
||||
|
@@ -26,24 +26,6 @@ export default class ItemList<T> {
|
||||
*/
|
||||
protected _items: Record<string, Item<T>> = {};
|
||||
|
||||
// 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<Record<string, Item<T>>> {
|
||||
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<T> {
|
||||
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 <caption>Replace priority and not content.</caption>
|
||||
* items.replace('myItem', null, 10);
|
||||
*
|
||||
* @example <caption>Replace content and not priority.</caption>
|
||||
* items.replace('myItem', <p>My new value.</p>);
|
||||
*
|
||||
* @example <caption>Replace content and priority.</caption>
|
||||
* items.replace('myItem', <p>My new value.</p>, 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<T> {
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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<string, unknown>}
|
||||
* @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);
|
||||
}
|
||||
},
|
||||
};
|
@@ -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<T extends SearchAttrs = SearchAttrs> 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.
|
||||
*/
|
||||
|
@@ -13,11 +13,6 @@ const LOCAL_STORAGE_KEY = 'welcomeHidden';
|
||||
* forum.
|
||||
*/
|
||||
export default class WelcomeHero extends Component<IWelcomeHeroAttrs> {
|
||||
/**
|
||||
* @deprecated Extend the `isHidden` method instead.
|
||||
*/
|
||||
hidden: boolean = false;
|
||||
|
||||
oninit(vnode: Mithril.Vnode<IWelcomeHeroAttrs, this>) {
|
||||
super.oninit(vnode);
|
||||
}
|
||||
@@ -60,7 +55,6 @@ export default class WelcomeHero extends Component<IWelcomeHeroAttrs> {
|
||||
isHidden(): boolean {
|
||||
if (!app.forum.attribute<string>('welcomeTitle')?.trim()) return true;
|
||||
if (localStorage.getItem(LOCAL_STORAGE_KEY)) return true;
|
||||
if (this.hidden) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@@ -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,
|
||||
|
@@ -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) {
|
||||
|
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of Flarum.
|
||||
*
|
||||
* For detailed copyright and license information, please view the
|
||||
* LICENSE file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
use Flarum\Database\Migration;
|
||||
|
||||
return Migration::dropColumns('discussions', ['post_number_index' => '']);
|
@@ -26,7 +26,6 @@ use Flarum\Http\RouteCollection;
|
||||
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 @@ class AdminServiceProvider extends AbstractServiceProvider
|
||||
$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
|
||||
|
@@ -120,7 +120,7 @@ abstract class Migration
|
||||
/**
|
||||
* 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
|
||||
|
@@ -36,7 +36,6 @@ use Illuminate\Support\Str;
|
||||
* @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
|
||||
|
@@ -11,7 +11,6 @@ namespace Flarum\Discussion;
|
||||
|
||||
use Flarum\User\User;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
|
||||
class DiscussionRepository
|
||||
{
|
||||
@@ -34,18 +33,6 @@ class DiscussionRepository
|
||||
return $this->scopeVisibleTo($query, $user)->firstOrFail();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the IDs of discussions which a user has read completely.
|
||||
*
|
||||
* @param User $user
|
||||
* @return Collection<int, Discussion>
|
||||
* @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.
|
||||
*
|
||||
|
@@ -23,7 +23,6 @@ use Flarum\Frontend\RecompileFrontendAssets;
|
||||
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 @@ class Frontend implements ExtenderInterface
|
||||
$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);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -30,20 +30,6 @@ class Model implements ExtenderInterface
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
|
@@ -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 @@ class Settings implements ExtenderInterface
|
||||
$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);
|
||||
|
@@ -173,12 +173,6 @@ class ForumServiceProvider extends AbstractServiceProvider
|
||||
$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'),
|
||||
|
@@ -10,7 +10,6 @@
|
||||
namespace Flarum\Frontend;
|
||||
|
||||
use Flarum\Locale\LocaleManager;
|
||||
use Flarum\Settings\Event\Saved;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
@@ -23,14 +22,6 @@ class RecompileFrontendAssets
|
||||
) {
|
||||
}
|
||||
|
||||
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();
|
||||
|
@@ -30,9 +30,6 @@ class RequestUtil
|
||||
|
||||
$actorReference->setActor($actor);
|
||||
|
||||
// @deprecated in 1.0
|
||||
$request = $request->withAttribute('actor', $actor);
|
||||
|
||||
return $request;
|
||||
}
|
||||
}
|
||||
|
@@ -21,8 +21,6 @@ class DefaultSettingsRepository implements SettingsRepositoryInterface
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -112,7 +112,7 @@ if (! function_exists('event')) {
|
||||
|
||||
if (! function_exists('config')) {
|
||||
/**
|
||||
* @deprecated do not use, will be transferred to flarum/laravel-helpers.
|
||||
* @deprecated
|
||||
*/
|
||||
function config(string $key, mixed $default = null): mixed
|
||||
{
|
||||
|
@@ -118,52 +118,6 @@ class SettingsTest extends TestCase
|
||||
$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
|
||||
*/
|
||||
|
@@ -32,7 +32,7 @@ class DiscussionPolicyTest extends TestCase
|
||||
|
||||
$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' => [
|
||||
|
Reference in New Issue
Block a user