diff --git a/modules/lib/src/main/resources/assets/js/app/ContentFormContext.ts b/modules/lib/src/main/resources/assets/js/app/ContentFormContext.ts index 117f3d2172..c9f1a7a3ab 100644 --- a/modules/lib/src/main/resources/assets/js/app/ContentFormContext.ts +++ b/modules/lib/src/main/resources/assets/js/app/ContentFormContext.ts @@ -8,6 +8,7 @@ import {ContentTypeName} from '@enonic/lib-admin-ui/schema/content/ContentTypeNa import {ContentId} from './content/ContentId'; import {ContentPath} from './content/ContentPath'; import {Project} from './settings/data/project/Project'; +import {ApplicationKey} from '@enonic/lib-admin-ui/application/ApplicationKey'; export class ContentFormContext extends FormContext { @@ -16,9 +17,11 @@ export class ContentFormContext private persistedContent?: Content; - private contentTypeName?: ContentTypeName; + private readonly contentTypeName?: ContentTypeName; - private project?: Project; + private readonly project?: Project; + + private readonly applicationKey?: ApplicationKey; private contentUpdatedListeners: { (content: Content): void }[] = []; @@ -29,6 +32,7 @@ export class ContentFormContext this.persistedContent = builder.persistedContent; this.contentTypeName = builder.contentTypeName; this.project = builder.project; + this.applicationKey = builder.applicationKey; } getSite(): Site { @@ -66,6 +70,10 @@ export class ContentFormContext return this.project; } + getApplicationKey(): ApplicationKey { + return this.applicationKey; + } + createInputTypeViewContext(inputTypeConfig: any, parentPropertyPath: PropertyPath, input: Input): ContentInputTypeViewContext { const viewContext = { formContext: this, @@ -74,7 +82,8 @@ export class ContentFormContext parentDataPath: parentPropertyPath, site: this.getSite(), content: this.getPersistedContent(), - project: this.getProject() + project: this.getProject(), + applicationKey: this.applicationKey }; this.contentUpdatedListeners.push(content => { @@ -90,6 +99,7 @@ export class ContentFormContext .setPersistedContent(this.persistedContent) .setContentTypeName(this.contentTypeName) .setProject(this.project) + .setApplicationKey(this.applicationKey) .setFormState(this.getFormState()) .setShowEmptyFormItemSetOccurrences(this.getShowEmptyFormItemSetOccurrences()) .setValidationErrors(this.getValidationErrors()); @@ -111,26 +121,33 @@ export class ContentFormContextBuilder project: Project; - public setSite(value: Site): ContentFormContextBuilder { + applicationKey: ApplicationKey; + + public setSite(value: Site): this { this.site = value; return this; } - public setPersistedContent(value: Content): ContentFormContextBuilder { + public setPersistedContent(value: Content): this { this.persistedContent = value; return this; } - public setContentTypeName(value: ContentTypeName): ContentFormContextBuilder { + public setContentTypeName(value: ContentTypeName): this { this.contentTypeName = value; return this; } - public setProject(value: Project): ContentFormContextBuilder { + public setProject(value: Project): this { this.project = value; return this; } + public setApplicationKey(value: ApplicationKey): this { + this.applicationKey = value; + return this; + } + public build(): ContentFormContext { return new ContentFormContext(this); } diff --git a/modules/lib/src/main/resources/assets/js/app/inputtype/ContentInputTypeViewContext.ts b/modules/lib/src/main/resources/assets/js/app/inputtype/ContentInputTypeViewContext.ts index b23257f3ea..962fcf2888 100644 --- a/modules/lib/src/main/resources/assets/js/app/inputtype/ContentInputTypeViewContext.ts +++ b/modules/lib/src/main/resources/assets/js/app/inputtype/ContentInputTypeViewContext.ts @@ -2,8 +2,8 @@ import {InputTypeViewContext} from '@enonic/lib-admin-ui/form/inputtype/InputTyp import {ContentFormContext} from '../ContentFormContext'; import {Site} from '../content/Site'; import {ContentSummary} from '../content/ContentSummary'; -import {ContentPath} from '../content/ContentPath'; import {Project} from '../settings/data/project/Project'; +import {ApplicationKey} from '@enonic/lib-admin-ui/application/ApplicationKey'; export interface ContentInputTypeViewContext extends InputTypeViewContext { @@ -16,4 +16,6 @@ export interface ContentInputTypeViewContext project?: Project; + applicationKey?: ApplicationKey; + } diff --git a/modules/lib/src/main/resources/assets/js/app/inputtype/selector/ContentSelector.ts b/modules/lib/src/main/resources/assets/js/app/inputtype/selector/ContentSelector.ts index 697313be5e..bbeb5dc530 100644 --- a/modules/lib/src/main/resources/assets/js/app/inputtype/selector/ContentSelector.ts +++ b/modules/lib/src/main/resources/assets/js/app/inputtype/selector/ContentSelector.ts @@ -211,7 +211,8 @@ export class ContentSelector .setContentTypeNames(this.allowedContentTypes) .setRelationshipType(this.relationshipType) .setContent(this.context.content) - .setProject(this.context.project); + .setProject(this.context.project) + .setApplicationKey(this.context.applicationKey); } protected doCreateContentComboBoxBuilder(): ContentComboBoxBuilder { diff --git a/modules/lib/src/main/resources/assets/js/app/inputtype/siteconfigurator/SiteConfiguratorSelectedOptionView.ts b/modules/lib/src/main/resources/assets/js/app/inputtype/siteconfigurator/SiteConfiguratorSelectedOptionView.ts index fb76be4131..b5f76ae0cf 100644 --- a/modules/lib/src/main/resources/assets/js/app/inputtype/siteconfigurator/SiteConfiguratorSelectedOptionView.ts +++ b/modules/lib/src/main/resources/assets/js/app/inputtype/siteconfigurator/SiteConfiguratorSelectedOptionView.ts @@ -238,7 +238,10 @@ export class SiteConfiguratorSelectedOptionView private createFormView(siteConfig: ApplicationConfig): FormView { const context: ContentFormContext = - this.formContext.cloneBuilder().setFormState(new FormState(this.isNew)).build(); + this.formContext.cloneBuilder() + .setApplicationKey(this.application.getApplicationKey()) + .setFormState(new FormState(this.isNew)) + .build(); const formView: FormView = new FormView(context, this.application.getForm(), siteConfig.getConfig()).addClass('site-form'); diff --git a/modules/lib/src/main/resources/assets/js/app/inputtype/ui/selector/ContentSummaryOptionDataLoader.ts b/modules/lib/src/main/resources/assets/js/app/inputtype/ui/selector/ContentSummaryOptionDataLoader.ts index 7571048d90..813730c28f 100644 --- a/modules/lib/src/main/resources/assets/js/app/inputtype/ui/selector/ContentSummaryOptionDataLoader.ts +++ b/modules/lib/src/main/resources/assets/js/app/inputtype/ui/selector/ContentSummaryOptionDataLoader.ts @@ -18,12 +18,15 @@ import {ContentSummaryJson} from '../../../content/ContentSummaryJson'; import {ContentSelectorRequest} from '../../../resource/ContentSelectorRequest'; import {ListByIdSelectorRequest} from '../../../resource/ListByIdSelectorRequest'; import {Project} from '../../../settings/data/project/Project'; +import {ApplicationKey} from '@enonic/lib-admin-ui/application/ApplicationKey'; export class ContentSummaryOptionDataLoader extends OptionDataLoader { protected readonly project?: Project; + protected readonly applicationKey: ApplicationKey; + private readonly treeRequest: ContentTreeSelectorQueryRequest | ListByIdSelectorRequest; private readonly flatRequest: ContentSelectorQueryRequest; @@ -40,29 +43,30 @@ export class ContentSummaryOptionDataLoader().setRequestProject(this.project) : new ListByIdSelectorRequest().setRequestProject(this.project); + this.flatRequest.setApplicationKey(builder?.applicationKey); + this.treeRequest.setApplicationKey(builder?.applicationKey); + if (builder) { this.initRequests(builder); } - } load(postLoad: boolean = false): Q.Promise { - if (!this.isTreeLoadMode) { return this.sendAndParseFlatRequest(true, postLoad); } this.treeRequest.setContent(null); - this.notifyLoadingData(postLoad); - return this.loadItems().then(data => { + return this.loadItems().then((data: DATA[]) => { this.notifyLoadedData(data, postLoad); return data; }); @@ -248,6 +252,8 @@ export class ContentSummaryOptionDataLoaderBuilder { project: Project; + applicationKey: ApplicationKey; + public setContentTypeNames(contentTypeNames: string[]): ContentSummaryOptionDataLoaderBuilder { this.contentTypeNames = contentTypeNames; return this; @@ -278,6 +284,11 @@ export class ContentSummaryOptionDataLoaderBuilder { return this; } + public setApplicationKey(key: ApplicationKey): ContentSummaryOptionDataLoaderBuilder { + this.applicationKey = key; + return this; + } + build(): ContentSummaryOptionDataLoader { return new ContentSummaryOptionDataLoader(this); } diff --git a/modules/lib/src/main/resources/assets/js/app/resource/ContentSelectorRequest.ts b/modules/lib/src/main/resources/assets/js/app/resource/ContentSelectorRequest.ts index aff7ac9ce2..bbbadc1067 100644 --- a/modules/lib/src/main/resources/assets/js/app/resource/ContentSelectorRequest.ts +++ b/modules/lib/src/main/resources/assets/js/app/resource/ContentSelectorRequest.ts @@ -11,6 +11,7 @@ import {HttpMethod} from '@enonic/lib-admin-ui/rest/HttpMethod'; import {ContentSummary} from '../content/ContentSummary'; import {CmsContentResourceRequest} from './CmsContentResourceRequest'; import {ResultMetadata} from './ResultMetadata'; +import {ApplicationKey} from '@enonic/lib-admin-ui/application/ApplicationKey'; export abstract class ContentSelectorRequest extends CmsContentResourceRequest { @@ -39,11 +40,13 @@ export abstract class ContentSelectorRequest private relationshipType: string; + private applicationKey: ApplicationKey; + protected loaded: boolean; protected results: CONTENT[] = []; - constructor() { + protected constructor() { super(); this.setMethod(HttpMethod.POST); @@ -116,6 +119,10 @@ export abstract class ContentSelectorRequest this.queryExpr = queryExpr; } + setApplicationKey(key: ApplicationKey): void { + this.applicationKey = key; + } + protected createSearchExpression(searchString: string): Expression { return new PathMatchExpressionBuilder() .setSearchString(searchString) @@ -155,7 +162,8 @@ export abstract class ContentSelectorRequest inputName: this.getInputName(), contentTypeNames: this.contentTypeNames, allowedContentPaths: this.allowedContentPaths, - relationshipType: this.relationshipType + relationshipType: this.relationshipType, + applicationKey: this.applicationKey?.toString() || null }; } diff --git a/modules/lib/src/main/resources/assets/js/app/settings/wizard/panel/form/element/ProjectApplicationSelectedOptionView.ts b/modules/lib/src/main/resources/assets/js/app/settings/wizard/panel/form/element/ProjectApplicationSelectedOptionView.ts index cdb1a94395..8a5ec4f0d6 100644 --- a/modules/lib/src/main/resources/assets/js/app/settings/wizard/panel/form/element/ProjectApplicationSelectedOptionView.ts +++ b/modules/lib/src/main/resources/assets/js/app/settings/wizard/panel/form/element/ProjectApplicationSelectedOptionView.ts @@ -120,7 +120,11 @@ export class ProjectApplicationSelectedOptionView const app: Application = this.getOption().getDisplayValue(); const isNew: boolean = !this.currentConfigSet; const propSet: PropertySet = new PropertyTree(isNew ? new PropertySet() : this.currentConfigSet).getRoot(); - const context: FormContext = ContentFormContext.create().setProject(this.project).setFormState(new FormState(isNew)).build(); + const context: FormContext = ContentFormContext.create() + .setProject(this.project) + .setApplicationKey(app.getApplicationKey()) + .setFormState(new FormState(isNew)) + .build(); const formView: FormView = new FormViewWrapper(context, app.getForm(), propSet); formView.onLayoutFinished(() => { diff --git a/modules/rest/src/main/java/com/enonic/xp/app/contentstudio/rest/resource/content/ContentSelectorQueryJsonToContentQueryConverter.java b/modules/rest/src/main/java/com/enonic/xp/app/contentstudio/rest/resource/content/ContentSelectorQueryJsonToContentQueryConverter.java index 6544ceb1da..8d6d15c2e9 100644 --- a/modules/rest/src/main/java/com/enonic/xp/app/contentstudio/rest/resource/content/ContentSelectorQueryJsonToContentQueryConverter.java +++ b/modules/rest/src/main/java/com/enonic/xp/app/contentstudio/rest/resource/content/ContentSelectorQueryJsonToContentQueryConverter.java @@ -1,10 +1,26 @@ package com.enonic.xp.app.contentstudio.rest.resource.content; +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import com.google.common.base.Preconditions; + +import com.enonic.xp.app.ApplicationKey; import com.enonic.xp.app.ApplicationWildcardMatcher; import com.enonic.xp.app.contentstudio.rest.resource.content.json.ContentSelectorQueryJson; -import com.enonic.xp.content.*; +import com.enonic.xp.content.Content; +import com.enonic.xp.content.ContentConstants; +import com.enonic.xp.content.ContentQuery; +import com.enonic.xp.content.ContentRelativePathResolver; +import com.enonic.xp.content.ContentService; import com.enonic.xp.node.NodeIndexPath; -import com.enonic.xp.query.expr.*; +import com.enonic.xp.query.expr.CompareExpr; +import com.enonic.xp.query.expr.ConstraintExpr; +import com.enonic.xp.query.expr.FieldExpr; +import com.enonic.xp.query.expr.LogicalExpr; +import com.enonic.xp.query.expr.QueryExpr; +import com.enonic.xp.query.expr.ValueExpr; import com.enonic.xp.query.parser.QueryParser; import com.enonic.xp.schema.content.ContentType; import com.enonic.xp.schema.content.ContentTypeName; @@ -14,11 +30,6 @@ import com.enonic.xp.schema.relationship.RelationshipTypeName; import com.enonic.xp.schema.relationship.RelationshipTypeService; import com.enonic.xp.site.Site; -import com.google.common.base.Preconditions; - -import java.util.List; -import java.util.function.Predicate; -import java.util.stream.Collectors; import static com.google.common.base.Strings.isNullOrEmpty; @@ -63,27 +74,53 @@ public ContentQuery createQuery() private ContentTypeNames getContentTypeNamesFromJson() { - List contentTypeNames = this.contentQueryJson.getContentTypeNames(); + final List contentTypeNames = this.contentQueryJson.getContentTypeNames(); + if ( contentTypeNames.isEmpty() ) { return this.getContentTypeNamesFromRelationshipType(); } - if ( this.content != null ) + final ApplicationKey applicationKey = getApplicationKey(); + + if ( applicationKey != null ) { - final ApplicationWildcardMatcher wildcardMatcher = - new ApplicationWildcardMatcher<>( this.content.getType().getApplicationKey(), ContentTypeName::toString, - this.contentTypeParseMode ); - - final Predicate filter = - contentTypeNames.stream().map( wildcardMatcher::createPredicate ).reduce( Predicate::or ).orElse( s -> false ); - return ContentTypeNames.from( - contentTypeService.getAll().stream().map( ContentType::getName ).filter( filter ).collect( Collectors.toList() ) ); + return this.filterContentTypeNames( applicationKey ); } return ContentTypeNames.from( contentTypeNames ); } + private ApplicationKey getApplicationKey() + { + if ( this.contentQueryJson.getApplicationKey() != null ) + { + return this.contentQueryJson.getApplicationKey(); + } + + if ( this.content != null ) + { + return this.content.getType().getApplicationKey(); + } + + return null; + } + + private ContentTypeNames filterContentTypeNames( final ApplicationKey applicationKey ) + { + final ApplicationWildcardMatcher wildcardMatcher = + new ApplicationWildcardMatcher<>( applicationKey, ContentTypeName::toString, this.contentTypeParseMode ); + + final Predicate filter = this.contentQueryJson.getContentTypeNames() + .stream() + .map( wildcardMatcher::createPredicate ) + .reduce( Predicate::or ) + .orElse( s -> false ); + + return ContentTypeNames.from( + contentTypeService.getAll().stream().map( ContentType::getName ).filter( filter ).collect( Collectors.toList() ) ); + } + private ContentTypeNames getContentTypeNamesFromRelationshipType() { if ( this.contentQueryJson.getRelationshipType() == null ) diff --git a/modules/rest/src/main/java/com/enonic/xp/app/contentstudio/rest/resource/content/json/ContentSelectorQueryJson.java b/modules/rest/src/main/java/com/enonic/xp/app/contentstudio/rest/resource/content/json/ContentSelectorQueryJson.java index 6b429009a5..67703cb32a 100644 --- a/modules/rest/src/main/java/com/enonic/xp/app/contentstudio/rest/resource/content/json/ContentSelectorQueryJson.java +++ b/modules/rest/src/main/java/com/enonic/xp/app/contentstudio/rest/resource/content/json/ContentSelectorQueryJson.java @@ -6,6 +6,7 @@ import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; +import com.enonic.xp.app.ApplicationKey; import com.enonic.xp.content.ContentId; public class ContentSelectorQueryJson @@ -24,6 +25,8 @@ public class ContentSelectorQueryJson private final String relationshipType; + private final ApplicationKey applicationKey; + private Integer from; private Integer size; @@ -36,7 +39,8 @@ public ContentSelectorQueryJson( @JsonProperty("queryExpr") final String queryEx @JsonProperty("inputName") final String inputName, @JsonProperty("contentTypeNames") final List contentTypeNamesString, @JsonProperty("allowedContentPaths") final List allowedContentPaths, - @JsonProperty("relationshipType") final String relationshipType ) + @JsonProperty("relationshipType") final String relationshipType, + @JsonProperty("applicationKey") final String applicationKey ) { this.from = from; @@ -48,6 +52,7 @@ public ContentSelectorQueryJson( @JsonProperty("queryExpr") final String queryEx this.contentTypeNames = contentTypeNamesString; this.allowedContentPaths = allowedContentPaths; this.relationshipType = relationshipType; + this.applicationKey = applicationKey != null ? ApplicationKey.from( applicationKey ) : null; } @JsonIgnore @@ -104,6 +109,12 @@ public String getRelationshipType() return relationshipType; } + @JsonIgnore + public ApplicationKey getApplicationKey() + { + return applicationKey; + } + public void setFrom( final Integer from ) { this.from = from; diff --git a/modules/rest/src/main/java/com/enonic/xp/app/contentstudio/rest/resource/content/json/ContentTreeSelectorQueryJson.java b/modules/rest/src/main/java/com/enonic/xp/app/contentstudio/rest/resource/content/json/ContentTreeSelectorQueryJson.java index fa85e7918e..8b324de134 100644 --- a/modules/rest/src/main/java/com/enonic/xp/app/contentstudio/rest/resource/content/json/ContentTreeSelectorQueryJson.java +++ b/modules/rest/src/main/java/com/enonic/xp/app/contentstudio/rest/resource/content/json/ContentTreeSelectorQueryJson.java @@ -28,9 +28,11 @@ public ContentTreeSelectorQueryJson( @JsonProperty("queryExpr") final String que @JsonProperty("allowedContentPaths") final List allowedContentPaths, @JsonProperty("relationshipType") final String relationshipType, @JsonProperty("parentPath") final String parentPath, - @JsonProperty("childOrder") final String childOrder) + @JsonProperty("childOrder") final String childOrder, + @JsonProperty("applicationKey") final String applicationKey ) { - super( queryExprString, from, size, expand, contentId, inputName, contentTypeNamesString, allowedContentPaths, relationshipType ); + super( queryExprString, from, size, expand, contentId, inputName, contentTypeNamesString, allowedContentPaths, relationshipType, + applicationKey ); if ( parentPath != null ) { diff --git a/modules/rest/src/test/java/com/enonic/xp/app/contentstudio/rest/resource/content/ContentResourceTest.java b/modules/rest/src/test/java/com/enonic/xp/app/contentstudio/rest/resource/content/ContentResourceTest.java index eccb319323..b6c9830adc 100644 --- a/modules/rest/src/test/java/com/enonic/xp/app/contentstudio/rest/resource/content/ContentResourceTest.java +++ b/modules/rest/src/test/java/com/enonic/xp/app/contentstudio/rest/resource/content/ContentResourceTest.java @@ -2034,7 +2034,7 @@ public void selectorQuery() .thenReturn( Contents.from( content ) ); AbstractContentQueryResultJson result = contentResource.selectorQuery( - new ContentTreeSelectorQueryJson( "", 0, 10, null, null, null, new ArrayList<>(), new ArrayList<>(), null, null, null ) ); + new ContentTreeSelectorQueryJson( "", 0, 10, null, null, null, new ArrayList<>(), new ArrayList<>(), null, null, null, null ) ); assertEquals( 1, result.getContents().size() ); assertTrue( result.getContents().contains( new ContentIdJson( content.getId() ) ) ); diff --git a/modules/rest/src/test/java/com/enonic/xp/app/contentstudio/rest/resource/content/ContentSelectorQueryJsonToContentQueryConverterTest.java b/modules/rest/src/test/java/com/enonic/xp/app/contentstudio/rest/resource/content/ContentSelectorQueryJsonToContentQueryConverterTest.java index 1b9a1e3ee2..1f0a48c1c6 100644 --- a/modules/rest/src/test/java/com/enonic/xp/app/contentstudio/rest/resource/content/ContentSelectorQueryJsonToContentQueryConverterTest.java +++ b/modules/rest/src/test/java/com/enonic/xp/app/contentstudio/rest/resource/content/ContentSelectorQueryJsonToContentQueryConverterTest.java @@ -21,8 +21,6 @@ import com.enonic.xp.content.ExtraData; import com.enonic.xp.data.PropertyTree; import com.enonic.xp.icon.Icon; -import com.enonic.xp.inputtype.InputTypeConfig; -import com.enonic.xp.inputtype.InputTypeProperty; import com.enonic.xp.schema.content.ContentType; import com.enonic.xp.schema.content.ContentTypeName; import com.enonic.xp.schema.content.ContentTypeNames; @@ -63,8 +61,7 @@ public void testSelectorQueryWithFewAllowPaths() final Content content = createContent( "content-id", "my-content", ContentTypeName.folder() ); - Mockito.when( contentService.getById( Mockito.isA( ContentId.class ) ) ). - thenReturn( content ); + Mockito.when( contentService.getById( Mockito.isA( ContentId.class ) ) ).thenReturn( content ); final List contentTypeNames = new ArrayList(); contentTypeNames.add( "myApplication:comment" ); @@ -74,7 +71,7 @@ public void testSelectorQueryWithFewAllowPaths() allowPaths.add( "/path/to/parent" ); ContentSelectorQueryJson contentQueryJson = - new ContentSelectorQueryJson( "", 0, 100, "summary", "contentId", "inputName", contentTypeNames, allowPaths, null ); + new ContentSelectorQueryJson( "", 0, 100, "summary", "contentId", "inputName", contentTypeNames, allowPaths, null, "testapp" ); ContentSelectorQueryJsonToContentQueryConverter processor = ContentSelectorQueryJsonToContentQueryConverter.create() .contentQueryJson( contentQueryJson ) .contentService( contentService ) @@ -103,14 +100,13 @@ public void testPathsWithSiteResolved() allowPaths.add( "${site}/path2/path3" ); allowPaths.add( "parent-path/child-path" ); - Mockito.when( contentService.getById( Mockito.isA( ContentId.class ) ) ). - thenReturn( content ); + Mockito.when( contentService.getById( Mockito.isA( ContentId.class ) ) ).thenReturn( content ); - Mockito.when( contentService.getNearestSite( Mockito.isA( ContentId.class ) ) ). - thenReturn( site ); + Mockito.when( contentService.getNearestSite( Mockito.isA( ContentId.class ) ) ).thenReturn( site ); ContentSelectorQueryJson contentQueryJson = - new ContentSelectorQueryJson( "", 0, 100, "summary", "contentId", "inputName", Collections.emptyList(), allowPaths, null ); + new ContentSelectorQueryJson( "", 0, 100, "summary", "contentId", "inputName", Collections.emptyList(), allowPaths, null, + null ); ContentSelectorQueryJsonToContentQueryConverter processor = ContentSelectorQueryJsonToContentQueryConverter.create() .contentQueryJson( contentQueryJson ) .contentService( contentService ) @@ -144,7 +140,7 @@ public void testPathWithAllowTypePassedFromJson() final List allowTypesFromJson = Arrays.asList( "myApplication:type1", "myApplication:type2", "myApplication:type2" ); ContentSelectorQueryJson contentQueryJson = - new ContentSelectorQueryJson( "", 0, 100, "summary", "contentId", "inputName", allowTypesFromJson, allowPaths, null ); + new ContentSelectorQueryJson( "", 0, 100, "summary", "contentId", "inputName", allowTypesFromJson, allowPaths, null, null ); ContentSelectorQueryJsonToContentQueryConverter processor = ContentSelectorQueryJsonToContentQueryConverter.create() .contentQueryJson( contentQueryJson ) .contentService( contentService ) @@ -170,14 +166,13 @@ public void testNullSiteResolved() final List allowPaths = new ArrayList(); allowPaths.add( "${site}/*" ); - Mockito.when( contentService.getById( Mockito.isA( ContentId.class ) ) ). - thenReturn( content ); + Mockito.when( contentService.getById( Mockito.isA( ContentId.class ) ) ).thenReturn( content ); - Mockito.when( contentService.getNearestSite( Mockito.isA( ContentId.class ) ) ). - thenReturn( null ); + Mockito.when( contentService.getNearestSite( Mockito.isA( ContentId.class ) ) ).thenReturn( null ); ContentSelectorQueryJson contentQueryJson = - new ContentSelectorQueryJson( "", 0, 100, "summary", "contentId", "inputName", Collections.emptyList(), allowPaths, null ); + new ContentSelectorQueryJson( "", 0, 100, "summary", "contentId", "inputName", Collections.emptyList(), allowPaths, null, + "testapp" ); ContentSelectorQueryJsonToContentQueryConverter processor = ContentSelectorQueryJsonToContentQueryConverter.create() .contentQueryJson( contentQueryJson ) .contentService( contentService ) @@ -193,13 +188,12 @@ public void testQueryWithSearchAndNoPaths() { final Content content = createContent( "content-id", "my-content", ContentTypeName.media() ); - Mockito.when( contentService.getById( Mockito.isA( ContentId.class ) ) ). - thenReturn( content ); + Mockito.when( contentService.getById( Mockito.isA( ContentId.class ) ) ).thenReturn( content ); ContentSelectorQueryJson contentQueryJson = new ContentSelectorQueryJson( "(fulltext('displayName^5,_name^3,_alltext', 'check', 'AND') OR ngram('displayName^5,_name^3,_alltext', 'check', 'AND')) " + "ORDER BY _modifiedTime DESC", 0, 100, "summary", "contentId", "inputName", Collections.emptyList(), - Collections.emptyList(), null ); + Collections.emptyList(), null, null ); ContentSelectorQueryJsonToContentQueryConverter processor = getProcessor( contentQueryJson ); final ContentQuery contentQuery = processor.createQuery(); @@ -235,12 +229,11 @@ public void testQueryWithSearch() final List contentTypeNames = new ArrayList(); contentTypeNames.add( "myApplication:comment" ); - Mockito.when( contentService.getById( Mockito.isA( ContentId.class ) ) ). - thenReturn( content ); + Mockito.when( contentService.getById( Mockito.isA( ContentId.class ) ) ).thenReturn( content ); ContentSelectorQueryJson contentQueryJson = new ContentSelectorQueryJson( "(fulltext('displayName^5,_name^3,_alltext', 'check', 'AND') OR ngram('displayName^5,_name^3,_alltext', 'check', 'AND')) " + - "ORDER BY _modifiedTime DESC", 0, 100, "summary", "contentId", "inputName", contentTypeNames, allowPaths, null ); + "ORDER BY _modifiedTime DESC", 0, 100, "summary", "contentId", "inputName", contentTypeNames, allowPaths, null, null ); ContentSelectorQueryJsonToContentQueryConverter processor = getProcessor( contentQueryJson ); final ContentQuery contentQuery = processor.createQuery(); @@ -256,17 +249,11 @@ public void testQueryWithSearch() @Test public void testRelationshipTypesFetched() { - final InputTypeConfig config = InputTypeConfig.create(). - property( InputTypeProperty.create( "relationship", "system:reference" ).build() ). - property( InputTypeProperty.create( "allowContentType", "myApplication:comment" ).build() ). - property( InputTypeProperty.create( "allowPath", "/*" ).build() ). - build(); - - final RelationshipType relationshipType = RelationshipType.create(). - name( "myrelationshiptype" ). - addAllowedToType( ContentTypeName.media() ). - addAllowedToType( ContentTypeName.dataMedia() ). - build(); + final RelationshipType relationshipType = RelationshipType.create() + .name( "myrelationshiptype" ) + .addAllowedToType( ContentTypeName.media() ) + .addAllowedToType( ContentTypeName.dataMedia() ) + .build(); Mockito.when( this.relationshipTypeService.getByName( Mockito.any() ) ).thenReturn( relationshipType ); @@ -275,13 +262,12 @@ public void testRelationshipTypesFetched() final List allowPaths = new ArrayList<>(); allowPaths.add( "/*" ); - Mockito.when( contentService.getById( Mockito.isA( ContentId.class ) ) ). - thenReturn( content ); + Mockito.when( contentService.getById( Mockito.isA( ContentId.class ) ) ).thenReturn( content ); ContentSelectorQueryJson contentQueryJson = new ContentSelectorQueryJson( "(fulltext('displayName^5,_name^3,_alltext', 'check', 'AND') OR ngram('displayName^5,_name^3,_alltext', 'check', 'AND')) " + "ORDER BY _modifiedTime DESC", 0, 100, "summary", "contentId", "inputName", Collections.emptyList(), allowPaths, - "relationship-type" ); + "relationship-type", "testapp" ); ContentSelectorQueryJsonToContentQueryConverter processor = getProcessor( contentQueryJson ); final ContentQuery contentQuery = processor.createQuery(); @@ -294,70 +280,92 @@ public void testRelationshipTypesFetched() contentQuery.getQueryExpr().toString() ); } + @Test + public void testNoContentAndNoAppKey() + { + Mockito.when( contentTypeService.getAll() ).thenReturn( ContentTypes.from( createContentType( "myApplication:comment" ) ) ); + + final List allowPaths = new ArrayList(); + allowPaths.add( "${site}/path1" ); + + final List contentTypeNames = new ArrayList(); + contentTypeNames.add( "myApplication:comment" ); + + ContentSelectorQueryJson contentQueryJson = new ContentSelectorQueryJson( + "(fulltext('displayName^5,_name^3,_alltext', 'check', 'AND') OR ngram('displayName^5,_name^3,_alltext', 'check', 'AND')) " + + "ORDER BY _modifiedTime DESC", 0, 100, "summary", "contentId", "inputName", contentTypeNames, allowPaths, null, null ); + ContentSelectorQueryJsonToContentQueryConverter processor = getProcessor( contentQueryJson ); + + final ContentQuery contentQuery = processor.createQuery(); + + assertEquals( 0, contentQuery.getFrom() ); + assertEquals( 100, contentQuery.getSize() ); + assertEquals( ContentTypeNames.from( "myApplication:comment" ), contentQuery.getContentTypes() ); + assertEquals( "(fulltext('displayName^5,_name^3,_alltext', 'check', 'AND') " + + "OR ngram('displayName^5,_name^3,_alltext', 'check', 'AND')) ORDER BY _modifiedtime DESC", + contentQuery.getQueryExpr().toString() ); + } + private Content createContent( final String id, final String name, final ContentTypeName contentTypeName ) { final PropertyTree metadata = new PropertyTree(); - final Content parent1 = Content.create(). - id( ContentId.from( id ) ). - parentPath( ContentPath.ROOT ). - name( "parent-content-1" ). - valid( true ). - createdTime( Instant.parse( this.currentTime ) ). - creator( PrincipalKey.from( "user:system:admin" ) ). - owner( PrincipalKey.from( "user:myStore:me" ) ). - language( Locale.ENGLISH ). - displayName( "My Content" ). - modifiedTime( Instant.parse( this.currentTime ) ). - modifier( PrincipalKey.from( "user:system:admin" ) ). - type( contentTypeName ). - addExtraData( new ExtraData( XDataName.from( "myApplication:myField" ), metadata ) ). - build(); - - final Content parent2 = Content.create(). - id( ContentId.from( id ) ). - parentPath( parent1.getPath() ). - name( "parent-content-2" ). - valid( true ). - createdTime( Instant.parse( this.currentTime ) ). - creator( PrincipalKey.from( "user:system:admin" ) ). - owner( PrincipalKey.from( "user:myStore:me" ) ). - language( Locale.ENGLISH ). - displayName( "My Content" ). - modifiedTime( Instant.parse( this.currentTime ) ). - modifier( PrincipalKey.from( "user:system:admin" ) ). - type( contentTypeName ). - addExtraData( new ExtraData( XDataName.from( "myApplication:myField" ), metadata ) ). - build(); - - return Content.create(). - id( ContentId.from( id ) ). - parentPath( parent2.getPath() ). - name( name ). - valid( true ). - createdTime( Instant.parse( this.currentTime ) ). - creator( PrincipalKey.from( "user:system:admin" ) ). - owner( PrincipalKey.from( "user:myStore:me" ) ). - language( Locale.ENGLISH ). - displayName( "My Content" ). - modifiedTime( Instant.parse( this.currentTime ) ). - modifier( PrincipalKey.from( "user:system:admin" ) ). - type( contentTypeName ). - addExtraData( new ExtraData( XDataName.from( "myApplication:myField" ), metadata ) ). - build(); + final Content parent1 = Content.create() + .id( ContentId.from( id ) ) + .parentPath( ContentPath.ROOT ) + .name( "parent-content-1" ) + .valid( true ) + .createdTime( Instant.parse( this.currentTime ) ) + .creator( PrincipalKey.from( "user:system:admin" ) ) + .owner( PrincipalKey.from( "user:myStore:me" ) ) + .language( Locale.ENGLISH ) + .displayName( "My Content" ) + .modifiedTime( Instant.parse( this.currentTime ) ) + .modifier( PrincipalKey.from( "user:system:admin" ) ) + .type( contentTypeName ) + .addExtraData( new ExtraData( XDataName.from( "myApplication:myField" ), metadata ) ) + .build(); + + final Content parent2 = Content.create() + .id( ContentId.from( id ) ) + .parentPath( parent1.getPath() ) + .name( "parent-content-2" ) + .valid( true ) + .createdTime( Instant.parse( this.currentTime ) ) + .creator( PrincipalKey.from( "user:system:admin" ) ) + .owner( PrincipalKey.from( "user:myStore:me" ) ) + .language( Locale.ENGLISH ) + .displayName( "My Content" ) + .modifiedTime( Instant.parse( this.currentTime ) ) + .modifier( PrincipalKey.from( "user:system:admin" ) ) + .type( contentTypeName ) + .addExtraData( new ExtraData( XDataName.from( "myApplication:myField" ), metadata ) ) + .build(); + + return Content.create() + .id( ContentId.from( id ) ) + .parentPath( parent2.getPath() ) + .name( name ) + .valid( true ) + .createdTime( Instant.parse( this.currentTime ) ) + .creator( PrincipalKey.from( "user:system:admin" ) ) + .owner( PrincipalKey.from( "user:myStore:me" ) ) + .language( Locale.ENGLISH ) + .displayName( "My Content" ) + .modifiedTime( Instant.parse( this.currentTime ) ) + .modifier( PrincipalKey.from( "user:system:admin" ) ) + .type( contentTypeName ) + .addExtraData( new ExtraData( XDataName.from( "myApplication:myField" ), metadata ) ) + .build(); } private Site createSite( final String id, final String name ) { return Site.create() - . - id( ContentId.from( id ) ) - . - parentPath( ContentPath.ROOT ) - . - name( name ) - . - valid( true ) + .id( ContentId.from( id ) ) + .parentPath( ContentPath.ROOT ) + .name( name ) + .valid( true ) .createdTime( Instant.parse( this.currentTime ) ) .creator( PrincipalKey.from( "user:system:admin" ) ) .owner( PrincipalKey.from( "user:myStore:me" ) )