import { Injectable , Post } from '@nestjs/common' ; import { InjectConnection } from '@nestjs/typeorm' ; import * as _ from 'lodash' ; import { Connection , In } from 'typeorm' ; import { CacheService } from '../../cache/cache.service' ; import * as CACHE_KEY from '../../common/constants/cache.constant' ; import { ID } from '../../common/shared-types' ; import { PostMeta , Term , TermMeta , TermRelationships , TermTaxonomy } from '../../entity' ; @ Injectable ( ) export class TermService { constructor ( @ InjectConnection ( ) private connection , private readonly cacheService ) { } param slug async findTermBySlug ( taxonomy , slug ) { const data = await this . connection . manager . createQueryBuilder ( ) . select ( ) . from ( TermTaxonomy , 'tt' ) . innerJoin ( query => { return query . from ( Term , 't' ) ; } , 't' , 'tt.termId = t.id' ) . where ( 'tt.taxonomy = :taxonomy' , { taxonomy } ) . andWhere ( 't.slug = :slug' , { slug } ) . getRawOne ( ) ; return data ; } param categorySlug param status param page param pageSize async getFromCategory ( categorySlug , status ? , querys ? ) { const pageSize = querys . pageSize ? querys . pageSize : 10 ; const page = querys . page ? querys . page * pageSize : 1 ; let where ; if ( _ . isEmpty ( status ) ) { where = `obj.status NOT IN ('trash')` ; } else { where = `obj.status = '${ status }'` ; } let data ; data = await this . connection . manager . createQueryBuilder ( ) . select ( 'obj.*, tt.description as category' ) . from ( Term , 't' ) . innerJoin ( query => { return query . from ( TermTaxonomy , 'tt' ) ; } , 'tt' , 'tt.id = t.id' ) . innerJoin ( query => { return query . from ( TermRelationships , 'tr' ) ; } , 'tr' , 'tr.taxonomyId = tt.id' ) . innerJoin ( query => { return query . from ( Post , 'obj' ) ; } , 'obj' , 'obj.id = tr.objectId' ) . where ( 'obj.type = :type' , { type : 'page' } ) . andWhere ( where ) . andWhere ( 't.slug = :categorySlug' , { categorySlug } ) . orderBy ( 'obj.updatedAt' , 'DESC' ) . offset ( page ) . limit ( pageSize ) . getRawMany ( ) ; const objIds = [ ] ; data . forEach ( item => { objIds . push ( item . id ) ; } ) ; if ( ! _ . isEmpty ( objIds ) ) { const metaData = await this . connection . getRepository ( PostMeta ) . find ( { post : In ( objIds ) , } ) ; data . forEach ( item => { item . metas = _ . filter ( metaData , { id : item . id } ) ; } ) ; } return data ; } param isRandom param limit async getPopular ( isRandom = false , limit = 10 ) { let data ; const orderBy = ! isRandom ? { viewCount : 'DESC' } : 'rand()' ; data = await this . connection . manager . createQueryBuilder ( ) . select ( 'p.*, JSON_LENGTH(value) as viewCount' ) . from ( Post , 'p' ) . innerJoin ( query => { return query . from ( PostMeta , 'meta' ) ; } , 'meta' , 'meta.postId = p.id' ) . where ( 'meta.key = :key' , { key : '_post_views' } ) . orderBy ( orderBy ) . limit ( limit ) . getRawMany ( ) ; return data ; } param limit async getNews ( limit ) { let data ; data = await this . connection . manager . createQueryBuilder ( ) . select ( 'obj.*, tt.description as category' ) . from ( Term , 't' ) . innerJoin ( query => { return query . from ( TermTaxonomy , 'tt' ) ; } , 'tt' , 'tt.id = t.id' ) . innerJoin ( query => { return query . from ( TermRelationships , 'tr' ) ; } , 'tr' , 'tr.taxonomyId = tt.id' ) . innerJoin ( query => { return query . from ( Post , 'obj' ) ; } , 'obj' , 'obj.id = tr.objectId' ) . where ( 'obj.type = :type' , { type : 'page' } ) . andWhere ( 'obj.status IN (:status)' , { status : 'publish' } ) . andWhere ( 'tt.taxonomy = :category' , { category : 'category' } ) . orderBy ( 'obj.updatedAt' , 'DESC' ) . limit ( limit ) . getRawMany ( ) ; const objIds = [ ] ; data . forEach ( item => { objIds . push ( item . id ) ; } ) ; if ( ! _ . isEmpty ( objIds ) ) { const metaData = await this . connection . getRepository ( PostMeta ) . find ( { post : In ( objIds ) , } ) ; data . forEach ( item => { item . metas = _ . filter ( metaData , { id : item . id } ) ; } ) ; } return data ; } param stickys async getStickys ( stickys ) { const data = await this . connection . manager . createQueryBuilder ( ) . select ( ) . from ( Post , 'p' ) . where ( 'p.id IN (:stickys)' , { stickys } ) . orderBy ( `INSTR (',${ stickys },', CONCAT(',',id,','))` ) . getRawMany ( ) ; return data ; } param taxonomy async getTermsByTaxonomy ( taxonomy ) { const allTerms = await this . loadAllTerms ( ) ; return allTerms . filter ( ( term ) => { return term . taxonomy === taxonomy ; } ) . map ( ( t ) => Object . assign ( { } , t ) ) ; } param flag async loadAllTerms ( flag ? ) { if ( flag ) { await this . cacheService . set ( CACHE_KEY . TERMS , null ) ; } let ret = await this . cacheService . get ( CACHE_KEY . TERMS ) ; if ( _ . isEmpty ( ret ) ) { const data = await this . connection . manager . createQueryBuilder ( ) . select ( ) . from ( Term , 't' ) . innerJoin ( query => { return query . from ( TermTaxonomy , 'tt' ) ; } , 'tt' , 't.id = tt.termId' ) . orderBy ( 'tt.id' , 'ASC' ) . getRawMany ( ) ; const ids = [ ] ; for ( const item of data ) { ids . push ( item . termId ) ; } const metaList = await this . connection . manager . createQueryBuilder ( ) . select ( 'tm.*' ) . from ( TermMeta , 'tm' ) . where ( 'termId IN (:ids)' , { ids } ) . getRawMany ( ) ; const metaGroup = _ . groupBy ( metaList , 'termId' ) ; for ( const key of Object . keys ( metaGroup ) ) { for ( const item of data ) { if ( item . termId . toString ( ) === key . toString ( ) ) { item . metas = metaGroup [ key ] ; } } } this . formatMeta ( data ) ; await this . cacheService . set ( CACHE_KEY . TERMS , data ) ; ret = await this . cacheService . get ( CACHE_KEY . TERMS ) ; } return ret ; } private formatMeta ( list ) { const items = [ ] ; for ( const item of list ) { item . meta = { } ; if ( _ . has ( item , 'metas' ) && item . metas . length > 0 ) { for ( const meta of item . metas ) { item . meta [ meta . key ] = meta . value ; } } Reflect . deleteProperty ( item , 'metas' ) ; items . push ( item ) ; } return items ; } }