diff --git a/core-web/libs/edit-content/src/lib/components/dot-edit-content-field/dot-edit-content-field.component.html b/core-web/libs/edit-content/src/lib/components/dot-edit-content-field/dot-edit-content-field.component.html index 9e0265812f12..f5d356765301 100644 --- a/core-web/libs/edit-content/src/lib/components/dot-edit-content-field/dot-edit-content-field.component.html +++ b/core-web/libs/edit-content/src/lib/components/dot-edit-content-field/dot-edit-content-field.component.html @@ -6,94 +6,58 @@ {{ field.name }} -@switch (field.fieldType) { - @case (fieldTypes.SELECT) { - - } - @case (fieldTypes.RADIO) { - - } - @case (fieldTypes.TEXT) { - - } - @case (fieldTypes.TEXTAREA) { - - } - @case (fieldTypes.CHECKBOX) { - - } - @case (fieldTypes.MULTI_SELECT) { - - } - @case (calendarTypes.includes(field.fieldType) ? field.fieldType : '') { - - } - @case (fieldTypes.TAG) { - - } - @case (fieldTypes.JSON) { - - } - @case (fieldTypes.BINARY) { - - } - @case (fieldTypes.CUSTOM_FIELD) { - - } - @case (fieldTypes.BLOCK_EDITOR) { - - } - @case (fieldTypes.KEY_VALUE) { - - } - @case (fieldTypes.WYSIWYG) { - - } - @case (fieldTypes.HOST_FOLDER) { - - } - @case (fieldTypes.CATEGORY) { - - } -} -@if (field.hint) { - {{ field.hint }} +@switch (field.fieldType) { @case (fieldTypes.SELECT) { + +} @case (fieldTypes.RADIO) { + +} @case (fieldTypes.TEXT) { + +} @case (fieldTypes.TEXTAREA) { + +} @case (fieldTypes.CHECKBOX) { + +} @case (fieldTypes.MULTI_SELECT) { + +} @case (calendarTypes.includes(field.fieldType) ? field.fieldType : '') { + +} @case (fieldTypes.TAG) { + +} @case (fieldTypes.JSON) { + +} @case (fieldTypes.BINARY) { + +} @case (fieldTypes.CUSTOM_FIELD) { + +} @case (fieldTypes.BLOCK_EDITOR) { + +} @case (fieldTypes.KEY_VALUE) { + +} @case (fieldTypes.WYSIWYG) { + +} @case (fieldTypes.HOST_FOLDER) { + +} @case (fieldTypes.CATEGORY) { + +} } @if (field.hint) { +{{ field.hint }} } diff --git a/core-web/libs/portlets/dot-locales/portlet/src/lib/dot-locales-list/components/dot-locale-create-edit/DotLocaleCreateEdit.component.html b/core-web/libs/portlets/dot-locales/portlet/src/lib/dot-locales-list/components/dot-locale-create-edit/DotLocaleCreateEdit.component.html index 1966ba72f2f1..ce0af06f47ee 100644 --- a/core-web/libs/portlets/dot-locales/portlet/src/lib/dot-locales-list/components/dot-locale-create-edit/DotLocaleCreateEdit.component.html +++ b/core-web/libs/portlets/dot-locales/portlet/src/lib/dot-locales-list/components/dot-locale-create-edit/DotLocaleCreateEdit.component.html @@ -4,156 +4,152 @@ [formGroup]="form" class="p-fluid"> @if (languageId?.value) { - -
- + +
+ + +
+ +
+ + + -
- -
- - - - - -
-
- - - - - -
+ +
+
+ + + + + +
} @else { - -
- - - -
+ +
+ + + +
- @if (localeTypeDropdown.value == 1) { - -
- - - - {{ language.name }} - {{ language.code }} - - - {{ language.name }} - {{ language.code }} - - - {{ 'locales.language.hint' | dm }} -
-
- - - - {{ country.name }} - {{ country.code }} - - - {{ country.name }} - {{ country.code }} - - - {{ 'locales.country.hint' | dm }} -
-
- - - - - - {{ 'locale.id.standard.hint' | dm }} -
- } @else { - -
- - - {{ 'locale.display.name.hint' | dm }} -
-
- - - {{ 'locale.id.hint' | dm }} -
- } - } - @if (showError | async) { - {{ - 'locale.error.message' | dm - }} + @if (localeTypeDropdown.value == 1) { + +
+ + + + {{ language.name }} - {{ language.code }} + + + {{ language.name }} - {{ language.code }} + + + {{ 'locales.language.hint' | dm }} +
+
+ + + + {{ country.name }} - {{ country.code }} + + + {{ country.name }} - {{ country.code }} + + + {{ 'locales.country.hint' | dm }} +
+
+ + + + + + {{ 'locale.id.standard.hint' | dm }} +
+ } @else { + +
+ + + {{ 'locale.display.name.hint' | dm }} +
+
+ + + {{ 'locale.id.hint' | dm }} +
+ } } @if (showError | async) { + {{ + 'locale.error.message' | dm + }} }
diff --git a/core-web/libs/ui/src/lib/components/dot-action-menu-button/dot-action-menu-button.component.html b/core-web/libs/ui/src/lib/components/dot-action-menu-button/dot-action-menu-button.component.html index 85149e769bf9..1b063dba6c86 100644 --- a/core-web/libs/ui/src/lib/components/dot-action-menu-button/dot-action-menu-button.component.html +++ b/core-web/libs/ui/src/lib/components/dot-action-menu-button/dot-action-menu-button.component.html @@ -1,12 +1,11 @@ @if (actions.length > 1 && filteredActions.length) { - -} -@if (actions.length === 1 && filteredActions.length === 1) { - - + +} @if (actions.length === 1 && filteredActions.length === 1) { + + } diff --git a/core-web/libs/ui/src/lib/components/dot-ai-image-prompt/ai-image-prompt.component.html b/core-web/libs/ui/src/lib/components/dot-ai-image-prompt/ai-image-prompt.component.html index f1b284d05cdd..034d223e5300 100644 --- a/core-web/libs/ui/src/lib/components/dot-ai-image-prompt/ai-image-prompt.component.html +++ b/core-web/libs/ui/src/lib/components/dot-ai-image-prompt/ai-image-prompt.component.html @@ -1,57 +1,57 @@ @if (vm$ | async; as vm) { - -
- @if (vm.showDialog) { - - } -
- - @if (vm.images.length || vm.isLoading) { -
- - -
- } + +
+ @if (vm.showDialog) { + + } +
+ + @if (vm.images.length || vm.isLoading) { +
+ +
- - + }
- + + +
+
} diff --git a/core-web/libs/ui/src/lib/components/dot-ai-image-prompt/components/ai-image-prompt-form/ai-image-prompt-form.component.html b/core-web/libs/ui/src/lib/components/dot-ai-image-prompt/components/ai-image-prompt-form/ai-image-prompt-form.component.html index dd71d03b7898..8098c5b7711b 100644 --- a/core-web/libs/ui/src/lib/components/dot-ai-image-prompt/components/ai-image-prompt-form/ai-image-prompt-form.component.html +++ b/core-web/libs/ui/src/lib/components/dot-ai-image-prompt/components/ai-image-prompt-form/ai-image-prompt-form.component.html @@ -47,13 +47,13 @@ class="ai-image-prompt__text">
@if (requiredPrompt) { - + } @else { - + } - -
+
+ +
+ +
+
}
@@ -96,24 +96,24 @@ pButton type="submit"> @if (!isLoading) { - - - - - + + + + + } @else { - + } diff --git a/core-web/libs/ui/src/lib/components/dot-ai-image-prompt/components/ai-image-prompt-form/ai-image-prompt-form.component.ts b/core-web/libs/ui/src/lib/components/dot-ai-image-prompt/components/ai-image-prompt-form/ai-image-prompt-form.component.ts index 095f6a3900e1..2e88e2bc2816 100644 --- a/core-web/libs/ui/src/lib/components/dot-ai-image-prompt/components/ai-image-prompt-form/ai-image-prompt-form.component.ts +++ b/core-web/libs/ui/src/lib/components/dot-ai-image-prompt/components/ai-image-prompt-form/ai-image-prompt-form.component.ts @@ -195,7 +195,7 @@ export class AiImagePromptFormComponent implements OnChanges, OnInit { this.submitButtonLabel = isLoading ? 'block-editor.extension.ai-image.generating' : this.aiProcessedPrompt || this.value?.error - ? 'block-editor.extension.ai-image.regenerate' - : 'block-editor.extension.ai-image.generate'; + ? 'block-editor.extension.ai-image.regenerate' + : 'block-editor.extension.ai-image.generate'; } } diff --git a/core-web/libs/ui/src/lib/components/dot-ai-image-prompt/components/ai-image-prompt-gallery/ai-image-prompt-gallery.component.html b/core-web/libs/ui/src/lib/components/dot-ai-image-prompt/components/ai-image-prompt-gallery/ai-image-prompt-gallery.component.html index 5877fb666a5a..61b9cdf89edb 100644 --- a/core-web/libs/ui/src/lib/components/dot-ai-image-prompt/components/ai-image-prompt-gallery/ai-image-prompt-gallery.component.html +++ b/core-web/libs/ui/src/lib/components/dot-ai-image-prompt/components/ai-image-prompt-gallery/ai-image-prompt-gallery.component.html @@ -1,76 +1,68 @@ @if (!isLoading && !images?.length) { -
- - - - - - -
-} -@if (isLoading) { - +
+ + + + + + +
+} @if (isLoading) { + - -} -@if (!isLoading && images?.length) { - - - @if (item.response) { - - - - - - } @else { - - } - - -} -@if (!isLoading && images?.length) { - - {{ activeImageIndex + 1 }} {{ 'of' | dm }} {{ images.length }} - + +} @if (!isLoading && images?.length) { + + + @if (item.response) { + + + + + + } @else { + + } + + +} @if (!isLoading && images?.length) { + + {{ activeImageIndex + 1 }} {{ 'of' | dm }} {{ images.length }} + } diff --git a/core-web/libs/ui/src/lib/components/dot-asset-search/components/dot-asset-card-list/dot-asset-card-list.component.html b/core-web/libs/ui/src/lib/components/dot-asset-search/components/dot-asset-card-list/dot-asset-card-list.component.html index b8e97ff43bfe..43a44a557379 100644 --- a/core-web/libs/ui/src/lib/components/dot-asset-search/components/dot-asset-card-list/dot-asset-card-list.component.html +++ b/core-web/libs/ui/src/lib/components/dot-asset-search/components/dot-asset-card-list/dot-asset-card-list.component.html @@ -1,36 +1,35 @@ @if (rows?.length && !loading) { - - -
- @if (contentlet[0]) { - - } - @if (contentlet[1]) { - - } -
-
-
+ + +
+ @if (contentlet[0]) { + + } @if (contentlet[1]) { + + } +
+
+
} @else { - + }
@for (loadingItem of loadingItems; track loadingItem) { -
- - -
+
+ + +
}
diff --git a/core-web/libs/ui/src/lib/components/dot-asset-search/dot-asset-search.component.html b/core-web/libs/ui/src/lib/components/dot-asset-search/dot-asset-search.component.html index 41a5f479f1fa..79c59022588f 100644 --- a/core-web/libs/ui/src/lib/components/dot-asset-search/dot-asset-search.component.html +++ b/core-web/libs/ui/src/lib/components/dot-asset-search/dot-asset-search.component.html @@ -14,10 +14,10 @@
@if (vm$ | async; as vm) { - + } diff --git a/core-web/libs/ui/src/lib/components/dot-drop-zone/directive/dot-drop-zone-value-accesor/dot-drop-zone-value-accessor.directive.stories.ts b/core-web/libs/ui/src/lib/components/dot-drop-zone/directive/dot-drop-zone-value-accesor/dot-drop-zone-value-accessor.directive.stories.ts index 9052a332bab4..37acf9bc62a6 100644 --- a/core-web/libs/ui/src/lib/components/dot-drop-zone/directive/dot-drop-zone-value-accesor/dot-drop-zone-value-accessor.directive.stories.ts +++ b/core-web/libs/ui/src/lib/components/dot-drop-zone/directive/dot-drop-zone-value-accesor/dot-drop-zone-value-accessor.directive.stories.ts @@ -41,12 +41,10 @@ import { DotDropZoneComponent } from '../../dot-drop-zone.component'; formControlName="file" dotDropZoneValueAccessor>
- Drop files here. - @if (accept.length) { -
Allowed Type: {{ accept }}
- } - @if (maxFileSize) { -
Max File Size: {{ maxFileSize }}
+ Drop files here. @if (accept.length) { +
Allowed Type: {{ accept }}
+ } @if (maxFileSize) { +
Max File Size: {{ maxFileSize }}
}
diff --git a/core-web/libs/ui/src/lib/components/dot-empty-container/dot-empty-container.component.html b/core-web/libs/ui/src/lib/components/dot-empty-container/dot-empty-container.component.html index e86676a25d10..d8f4dc625578 100644 --- a/core-web/libs/ui/src/lib/components/dot-empty-container/dot-empty-container.component.html +++ b/core-web/libs/ui/src/lib/components/dot-empty-container/dot-empty-container.component.html @@ -3,43 +3,38 @@ class="message__principal-wrapper flex align-items-center flex-column gap-2" data-Testid="message-principal"> @if (configuration?.icon) { - + }

{{ configuration?.title }}

@if (configuration?.subtitle) { -

- {{ configuration?.subtitle }} -

+

+ {{ configuration?.subtitle }} +

}
@if (!hideContactUsLink || buttonLabel) { -
- @if (buttonLabel) { - - } - @if (!hideContactUsLink) { - @if (!hideContactUsLink && buttonLabel) { - {{ 'dot.common.or.text' | dm }} - } - {{ 'Contact-Us-for-more-Information' | dm }} - } -
+
+ @if (buttonLabel) { + + } @if (!hideContactUsLink) { @if (!hideContactUsLink && buttonLabel) { + {{ 'dot.common.or.text' | dm }} + } + {{ 'Contact-Us-for-more-Information' | dm }} + } +
} diff --git a/core-web/libs/ui/src/lib/components/dot-field-validation-message/dot-field-validation-message.component.html b/core-web/libs/ui/src/lib/components/dot-field-validation-message/dot-field-validation-message.component.html index c87d2a0b9b12..72acf1209d4c 100644 --- a/core-web/libs/ui/src/lib/components/dot-field-validation-message/dot-field-validation-message.component.html +++ b/core-web/libs/ui/src/lib/components/dot-field-validation-message/dot-field-validation-message.component.html @@ -1,5 +1,5 @@ @if (_field && _field.enabled && _field.dirty && !_field.valid) { - - {{ errorMsg | dm }} - + + {{ errorMsg | dm }} + } diff --git a/core-web/libs/ui/src/lib/components/dot-form-dialog/dot-form-dialog.component.ts b/core-web/libs/ui/src/lib/components/dot-form-dialog/dot-form-dialog.component.ts index b720689b2e20..5b912f98a021 100644 --- a/core-web/libs/ui/src/lib/components/dot-form-dialog/dot-form-dialog.component.ts +++ b/core-web/libs/ui/src/lib/components/dot-form-dialog/dot-form-dialog.component.ts @@ -41,10 +41,7 @@ export class DotFormDialogComponent implements OnInit, OnDestroy { @Output() cancel: EventEmitter = new EventEmitter(null); - constructor( - private dynamicDialog: DynamicDialogRef, - private el: ElementRef - ) {} + constructor(private dynamicDialog: DynamicDialogRef, private el: ElementRef) {} ngOnInit(): void { const content = document.querySelector('p-dynamicdialog .p-dialog-content'); diff --git a/core-web/libs/ui/src/lib/components/dot-key-value-ng/dot-key-value-ng.component.html b/core-web/libs/ui/src/lib/components/dot-key-value-ng/dot-key-value-ng.component.html index ae19b98fcabc..aef0b17789de 100644 --- a/core-web/libs/ui/src/lib/components/dot-key-value-ng/dot-key-value-ng.component.html +++ b/core-web/libs/ui/src/lib/components/dot-key-value-ng/dot-key-value-ng.component.html @@ -14,9 +14,9 @@ {{ 'keyValue.value_header.label' | dm }} @if (showHiddenField) { - - {{ 'keyValue.hidden_header.label' | dm }} - + + {{ 'keyValue.hidden_header.label' | dm }} + } {{ 'keyValue.actions_header.label' | dm }} diff --git a/core-web/libs/ui/src/lib/components/dot-key-value-ng/dot-key-value-table-row/dot-key-value-table-row.component.html b/core-web/libs/ui/src/lib/components/dot-key-value-ng/dot-key-value-table-row/dot-key-value-table-row.component.html index a4173f585837..2b548ed1b2e9 100644 --- a/core-web/libs/ui/src/lib/components/dot-key-value-ng/dot-key-value-table-row/dot-key-value-table-row.component.html +++ b/core-web/libs/ui/src/lib/components/dot-key-value-ng/dot-key-value-table-row/dot-key-value-table-row.component.html @@ -2,78 +2,77 @@ {{ variable.key }} @if (isHiddenField) { - {{ passwordPlaceholder }} + {{ passwordPlaceholder }} } @else { - - - - - - - @if (isHiddenField || currentHiddenValue) { - - {{ passwordPlaceholder }} - - } @else { - - {{ currentValue }} - - } - - - - } - @if (showHiddenField) { - - - + + + + + + + @if (isHiddenField || currentHiddenValue) { + + {{ passwordPlaceholder }} + + } @else { + + {{ currentValue }} + + } + + + + } @if (showHiddenField) { + + + } @if (showEditMenu()) { - - + + } @else { - - + + } diff --git a/core-web/libs/ui/src/lib/components/dot-link/dot-link.component.html b/core-web/libs/ui/src/lib/components/dot-link/dot-link.component.html index 20805665ef61..21ef12881668 100644 --- a/core-web/libs/ui/src/lib/components/dot-link/dot-link.component.html +++ b/core-web/libs/ui/src/lib/components/dot-link/dot-link.component.html @@ -1,6 +1,6 @@ @if (link) { - - - {{ this.label | dm }} - + + + {{ this.label | dm }} + } diff --git a/core-web/libs/ui/src/lib/components/dot-menu/dot-menu.component.html b/core-web/libs/ui/src/lib/components/dot-menu/dot-menu.component.html index 2e1e6b889daa..b904e9e14e64 100644 --- a/core-web/libs/ui/src/lib/components/dot-menu/dot-menu.component.html +++ b/core-web/libs/ui/src/lib/components/dot-menu/dot-menu.component.html @@ -1,17 +1,17 @@ @if (float) { - + } @else { - + } diff --git a/core-web/libs/ui/src/lib/components/dot-sidebar-header/dot-sidebar-header.component.html b/core-web/libs/ui/src/lib/components/dot-sidebar-header/dot-sidebar-header.component.html index d4cc1ef2771b..52d14dada349 100644 --- a/core-web/libs/ui/src/lib/components/dot-sidebar-header/dot-sidebar-header.component.html +++ b/core-web/libs/ui/src/lib/components/dot-sidebar-header/dot-sidebar-header.component.html @@ -11,9 +11,9 @@

@if (actionButtonTpl) { -
- -
+
+ +
} diff --git a/core-web/libs/ui/src/lib/components/dot-temp-file-thumbnail/dot-temp-file-thumbnail.component.html b/core-web/libs/ui/src/lib/components/dot-temp-file-thumbnail/dot-temp-file-thumbnail.component.html index a6b8c00014d1..f3ff179cbfb7 100644 --- a/core-web/libs/ui/src/lib/components/dot-temp-file-thumbnail/dot-temp-file-thumbnail.component.html +++ b/core-web/libs/ui/src/lib/components/dot-temp-file-thumbnail/dot-temp-file-thumbnail.component.html @@ -1,31 +1,19 @@ -@if (type) { - @switch (type) { - @case (CONTENT_THUMBNAIL_TYPE.image) { - - } - @case (CONTENT_THUMBNAIL_TYPE.video) { - - } - @case (CONTENT_THUMBNAIL_TYPE.pdf) { - - } - @default { - - } - } -} +@if (type) { @switch (type) { @case (CONTENT_THUMBNAIL_TYPE.image) { + +} @case (CONTENT_THUMBNAIL_TYPE.video) { + +} @case (CONTENT_THUMBNAIL_TYPE.pdf) { + +} @default { + +} } } diff --git a/core-web/libs/ui/src/lib/directives/dot-autofocus/dot-autofocus.directive.spec.ts b/core-web/libs/ui/src/lib/directives/dot-autofocus/dot-autofocus.directive.spec.ts index 92c873f80991..093f1e1f488f 100644 --- a/core-web/libs/ui/src/lib/directives/dot-autofocus/dot-autofocus.directive.spec.ts +++ b/core-web/libs/ui/src/lib/directives/dot-autofocus/dot-autofocus.directive.spec.ts @@ -9,9 +9,9 @@ import { DotAutofocusDirective } from '@dotcms/ui'; @Component({ template: ` @if (disabled) { - + } @else { - + } ` }) diff --git a/core-web/libs/ui/src/lib/dot-tab-buttons/dot-tab-buttons.component.html b/core-web/libs/ui/src/lib/dot-tab-buttons/dot-tab-buttons.component.html index f86ed077a5e6..2193f4cdc2a0 100644 --- a/core-web/libs/ui/src/lib/dot-tab-buttons/dot-tab-buttons.component.html +++ b/core-web/libs/ui/src/lib/dot-tab-buttons/dot-tab-buttons.component.html @@ -1,42 +1,40 @@
@for (item of _options; track $index) { -
-
- - @if (item.value.showDropdownButton) { - - } -
- @if (activeId === item.value.id) { -
+
+
+ + @if (item.value.showDropdownButton) { + }
+ @if (activeId === item.value.id) { +
+ } +
}
diff --git a/core-web/libs/ui/src/lib/modules/dot-dialog/dot-dialog.component.html b/core-web/libs/ui/src/lib/modules/dot-dialog/dot-dialog.component.html index 2b8e31d563d4..bcdb4ce5bfc8 100644 --- a/core-web/libs/ui/src/lib/modules/dot-dialog/dot-dialog.component.html +++ b/core-web/libs/ui/src/lib/modules/dot-dialog/dot-dialog.component.html @@ -1,51 +1,50 @@ @if (visible) { -
-
-

- @if (closeable) { - - } -
-
- -
- @if (actions) { -
- @if (actions.cancel) { - - } - @if (actions.accept) { - - } -
+
+
+

+ @if (closeable) { + } +
+
+
+ @if (actions) { +
+ @if (actions.cancel) { + + } @if (actions.accept) { + + } +
+ } +
} diff --git a/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryAPI.java b/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryAPI.java index 1e286448a066..2989f3835799 100644 --- a/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryAPI.java +++ b/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryAPI.java @@ -484,4 +484,17 @@ Category findByVariable(final String variable, final User user, final boolean respectFrontendRoles) throws DotDataException, DotSecurityException; List getCategoriesFromContent(final Contentlet contentlet, final User user, boolean respectFrontendRoles ) throws DotDataException, DotSecurityException; + + /** + * Return a list of Categories regardless of their levels. + * + * @param searchCriteria Searching criteria + * @param user User to check Permission + * @param respectFrontendRoles true if you must respect Frontend Roles + * + * @return List of Category filtered + */ + PaginatedCategories findAll(final CategoryFactory.CategorySearchCriteria searchCriteria, + final User user, boolean respectFrontendRoles) + throws DotDataException, DotSecurityException; } diff --git a/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryAPIImpl.java b/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryAPIImpl.java index 34d7ab311fde..2206c4a9ec1a 100644 --- a/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryAPIImpl.java +++ b/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryAPIImpl.java @@ -22,6 +22,7 @@ import com.dotmarketing.util.InodeUtils; import com.dotmarketing.util.Logger; import com.dotmarketing.util.UtilMethods; +import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; import com.liferay.portal.model.User; import java.util.ArrayList; @@ -48,8 +49,13 @@ public class CategoryAPIImpl implements CategoryAPI { private final PermissionAPI permissionAPI; public CategoryAPIImpl () { - categoryFactory = FactoryLocator.getCategoryFactory(); - permissionAPI = APILocator.getPermissionAPI(); + this(FactoryLocator.getCategoryFactory(), APILocator.getPermissionAPI()); + } + + @VisibleForTesting + public CategoryAPIImpl (final CategoryFactory categoryFactory, final PermissionAPI permissionAPI) { + this.categoryFactory = categoryFactory; + this.permissionAPI = permissionAPI; } /** @@ -943,4 +949,31 @@ private boolean hasCategoryFields(final ContentType contentType) { } + /** + * Default implementation. + * + * @param searchCriteria Searching criteria + * @param user User to check Permission + * @param respectFrontendRoles true if you must respect Frontend Roles + * + * @return + * @throws DotDataException + * @throws DotSecurityException + */ + @CloseDBIfOpened + @Override + public PaginatedCategories findAll(final CategoryFactory.CategorySearchCriteria searchCriteria, + final User user, boolean respectFrontendRoles) + throws DotDataException, DotSecurityException { + + if (searchCriteria.limit < 1) { + throw new IllegalArgumentException("Limit must be greater than 0"); + } + + final List categories = permissionAPI.filterCollection(categoryFactory.findAll(searchCriteria), + PermissionAPI.PERMISSION_READ, respectFrontendRoles, user); + + return getCategoriesSubList(searchCriteria.offset, searchCriteria.limit, categories, null); + } + } diff --git a/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryFactory.java b/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryFactory.java index 01d1e34a71af..9c1c76807ea9 100644 --- a/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryFactory.java +++ b/dotCMS/src/main/java/com/dotmarketing/portlets/categories/business/CategoryFactory.java @@ -289,7 +289,8 @@ public abstract class CategoryFactory { * * @return List of Category filtered */ - public abstract Collection findAll(final CategorySearchCriteria searchCriteria) throws DotDataException; + public abstract List findAll(final CategorySearchCriteria searchCriteria) throws DotDataException; + /** * Represents Search Criteria for {@link Category} searching, you cans set the follow: @@ -304,12 +305,22 @@ public static class CategorySearchCriteria { final String filter; final String orderBy; final OrderDirection direction; +<<<<<<< HEAD + final int limit; + final int offset; +======= +>>>>>>> origin/master private CategorySearchCriteria (final Builder builder) { this.rootInode = builder.rootInode; this.filter = builder.filter; this.orderBy = builder.orderBy; this.direction = builder.direction; +<<<<<<< HEAD + this.limit = builder.limit; + this.offset = builder.offset; +======= +>>>>>>> origin/master } public static class Builder { @@ -317,6 +328,11 @@ public static class Builder { private String filter; private String orderBy = "category_name"; private OrderDirection direction = OrderDirection.ASC; +<<<<<<< HEAD + private int limit = -1; + private int offset = 0; +======= +>>>>>>> origin/master public Builder rootInode(String rootInode) { this.rootInode = rootInode; @@ -338,6 +354,20 @@ public Builder direction(OrderDirection direction) { return this; } +<<<<<<< HEAD + public Builder limit(int limit) { + this.limit = limit; + return this; + } + + public Builder offset(int offset) { + this.offset = offset; + return this; + } + + +======= +>>>>>>> origin/master public CategorySearchCriteria build() { return new CategorySearchCriteria(this); } diff --git a/dotcms-integration/src/test/java/com/dotmarketing/portlets/categories/business/CategoryAPITest.java b/dotcms-integration/src/test/java/com/dotmarketing/portlets/categories/business/CategoryAPITest.java index 5a4d03115ca6..f0c0f39a90bb 100644 --- a/dotcms-integration/src/test/java/com/dotmarketing/portlets/categories/business/CategoryAPITest.java +++ b/dotcms-integration/src/test/java/com/dotmarketing/portlets/categories/business/CategoryAPITest.java @@ -1,5 +1,6 @@ package com.dotmarketing.portlets.categories.business; +import static com.dotcms.util.CollectionsUtils.list; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotEquals; @@ -7,6 +8,8 @@ import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import com.dotcms.IntegrationTestBase; import com.dotcms.contenttype.business.ContentTypeAPIImpl; @@ -21,10 +24,12 @@ import com.dotcms.datagen.SiteDataGen; import com.dotcms.datagen.UserDataGen; import com.dotcms.util.IntegrationTestInitService; +import com.dotcms.util.pagination.OrderDirection; import com.dotmarketing.beans.Host; import com.dotmarketing.beans.Permission; import com.dotmarketing.business.APILocator; import com.dotmarketing.business.CacheLocator; +import com.dotmarketing.business.FactoryLocator; import com.dotmarketing.business.PermissionAPI; import com.dotmarketing.business.PermissionAPI.PermissionableType; import com.dotmarketing.exception.DotDataException; @@ -45,6 +50,10 @@ import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Random; +import java.util.stream.Collectors; + +import net.bytebuddy.utility.RandomString; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; @@ -1537,4 +1546,123 @@ public void test_save_createTopLevelCategory_asLimitedUser_fail() categoryAPI.save(null, newCategory, limitedUser, false); } + + /** + * Method to test: {@link CategoryAPIImpl#findAll(CategoryFactory.CategorySearchCriteria, User, boolean)} + * When: Call the API method + * Should: it should + * - Use the {@link CategoryFactoryImpl#findAll(CategoryFactory.CategorySearchCriteria)} to search the {@link Category} + * - Use the {@link PermissionAPI#filterCollection(List, int, boolean, User)} method to check permission + */ + @Test + public void getAllCategoriesFiltered() throws DotDataException, DotSecurityException { + final String inode = new RandomString().nextString(); + final String filter = new RandomString().nextString(); + final String orderBy = "category_key"; + + final CategoryFactory.CategorySearchCriteria searchingCriteria = + new CategoryFactory.CategorySearchCriteria.Builder() + .inode(inode) + .direction(OrderDirection.DESC) + .orderBy(orderBy) + .filter(filter) + .limit(10) + .build(); + + final User user = mock(); + + final Category category1 = mock(Category.class); + final Category category2 = mock(Category.class); + final Category category3 = mock(Category.class); + + final List categoriesAfterSearch = list(category1, category2, category3); + final List categoriesAfterPermission = list(category1, category2); + + final CategoryFactory categoryFactory = mock(); + when(categoryFactory.findAll(searchingCriteria)).thenReturn(categoriesAfterSearch); + + final PermissionAPI permissionAPI = mock(); + when(permissionAPI.filterCollection(categoriesAfterSearch, PermissionAPI.PERMISSION_READ, false, user)) + .thenReturn(categoriesAfterPermission); + + final CategoryAPI categoryAPI = new CategoryAPIImpl(categoryFactory, permissionAPI); + PaginatedCategories paginatedCategories = categoryAPI.findAll(searchingCriteria, user, false); + + assertEquals(categoriesAfterPermission.size(), (int) paginatedCategories.getTotalCount()); + assertTrue(categoriesAfterPermission.containsAll(paginatedCategories.getCategories())); + } + + /** + * Method to test: {@link CategoryAPIImpl#findAll(CategoryFactory.CategorySearchCriteria, User, boolean)} + * When: Create 9 Category, call the two times: + * first: limit =5, offset =0 + * second: limit =5, offset =5 + * + * Should: Return All the Categories with the 2 called + */ + @Test + public void getAllCategoriesFilteredWithPagination() throws DotDataException, DotSecurityException { + final String inode = new RandomString().nextString(); + final String filter = new RandomString().nextString(); + final String orderBy = "category_key"; + + final CategoryFactory.CategorySearchCriteria searchingCriteria_1 = + new CategoryFactory.CategorySearchCriteria.Builder() + .inode(inode) + .direction(OrderDirection.DESC) + .orderBy(orderBy) + .filter(filter) + .limit(5) + .offset(0) + .build(); + + final CategoryFactory.CategorySearchCriteria searchingCriteria_2 = + new CategoryFactory.CategorySearchCriteria.Builder() + .inode(inode) + .direction(OrderDirection.DESC) + .orderBy(orderBy) + .filter(filter) + .limit(5) + .offset(5) + .build(); + + final Category category1 = mock(Category.class); + final Category category2 = mock(Category.class); + final Category category3 = mock(Category.class); + final Category category4 = mock(Category.class); + final Category category5 = mock(Category.class); + final Category category6 = mock(Category.class); + final Category category7 = mock(Category.class); + final Category category8 = mock(Category.class); + final Category category9 = mock(Category.class); + + final User user = mock(); + + final List categories = list(category1, category2, category3, category4, category5, category6, + category7, category8, category9); + + final CategoryFactory categoryFactory = mock(); + when(categoryFactory.findAll(searchingCriteria_1)).thenReturn(categories); + when(categoryFactory.findAll(searchingCriteria_2)).thenReturn(categories); + + final PermissionAPI permissionAPI = mock(); + when(permissionAPI.filterCollection(categories, PermissionAPI.PERMISSION_READ, false, user)) + .thenReturn(categories); + + + + final CategoryAPI categoryAPI = new CategoryAPIImpl(categoryFactory, permissionAPI); + PaginatedCategories firstPage = categoryAPI.findAll(searchingCriteria_1, user, false); + + assertEquals(9, (int) firstPage.getTotalCount()); + assertEquals(5, firstPage.getCategories().size()); + assertTrue(list(category1, category2, category3, category4, category5).containsAll(firstPage.getCategories())); + + + PaginatedCategories secondPage = categoryAPI.findAll(searchingCriteria_2, user, false); + + assertEquals(9, (int) secondPage.getTotalCount()); + assertEquals(4, secondPage.getCategories().size()); + assertTrue(list(category6, category7, category8, category9).containsAll(secondPage.getCategories())); + } }