You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
76 lines
2.2 KiB
76 lines
2.2 KiB
import {Relation, RelationNotLoadedError} from './Relation'
|
|
import {TreeModel} from '../TreeModel'
|
|
import {RelationBuilder} from './RelationBuilder'
|
|
import {raw} from '../../dialect/SQLDialect'
|
|
import {AbstractBuilder} from '../../builder/AbstractBuilder'
|
|
import {ModelBuilder} from '../ModelBuilder'
|
|
import {Collection, Maybe} from '../../../util'
|
|
|
|
export class HasTreeParent<T extends TreeModel<T>> extends Relation<T, T, Maybe<T>> {
|
|
|
|
protected parentInstance?: T
|
|
|
|
protected loaded = false
|
|
|
|
protected constructor(
|
|
protected model: T,
|
|
protected readonly leftTreeField: string,
|
|
protected readonly parentIdField: string,
|
|
) {
|
|
super(model, model)
|
|
}
|
|
|
|
protected get parentValue(): any {
|
|
return this.model.key()
|
|
}
|
|
|
|
public query(): RelationBuilder<T> {
|
|
return this.builder()
|
|
.tap(b => this.model.applyScopes(b))
|
|
.select(raw('*'))
|
|
.orderByAscending(this.leftTreeField)
|
|
}
|
|
|
|
public applyScope(where: AbstractBuilder<T>): void {
|
|
const parentId = this.model.parentId()
|
|
if ( !parentId ) {
|
|
where.whereMatchNone()
|
|
return
|
|
}
|
|
|
|
where.where(this.parentIdField, '=', parentId)
|
|
}
|
|
|
|
public buildEagerQuery(parentQuery: ModelBuilder<T>, result: Collection<T>): ModelBuilder<T> {
|
|
const parentIds = result.map(model => model.parentId()).whereDefined()
|
|
return this.model.query()
|
|
.without('subtree')
|
|
.whereIn(this.parentIdField, parentIds)
|
|
}
|
|
|
|
public matchResults(possiblyRelated: Collection<T>): Collection<T> {
|
|
return possiblyRelated.filter(related => related.key() === this.model.parentId())
|
|
}
|
|
|
|
public setValue(related: Maybe<T>): void {
|
|
this.loaded = true
|
|
this.parentInstance = related
|
|
}
|
|
|
|
public getValue(): Maybe<T> {
|
|
if ( !this.loaded && this.model.parentId() ) {
|
|
throw new RelationNotLoadedError()
|
|
}
|
|
|
|
return this.parentInstance
|
|
}
|
|
|
|
public isLoaded(): boolean {
|
|
return this.loaded || !this.model.parentId()
|
|
}
|
|
|
|
public async get(): Promise<Maybe<T>> {
|
|
return this.fetch().first()
|
|
}
|
|
}
|