diff --git a/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/html/HtmlBuilder.java b/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/html/HtmlBuilder.java index 0205bfea367..8f4929bda63 100644 --- a/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/html/HtmlBuilder.java +++ b/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/html/HtmlBuilder.java @@ -69,9 +69,9 @@ public HtmlBuilder closeEmpty() public HtmlBuilder attribute( final String name, final String value ) { this.str.append( ' ' ); - this.str.append( name ); + this.str.append( escaper.escape( name ) ); this.str.append( "=\"" ); - this.str.append( value ); + this.str.append( escaper.escape( value ) ); this.str.append( '"' ); this.addedInner = false; this.closedEmptyTag = false; diff --git a/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/rendering/DescriptorBasedComponentRenderer.java b/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/rendering/DescriptorBasedComponentRenderer.java index e267c86ed22..e44a056ca60 100644 --- a/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/rendering/DescriptorBasedComponentRenderer.java +++ b/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/rendering/DescriptorBasedComponentRenderer.java @@ -1,8 +1,6 @@ package com.enonic.xp.portal.impl.rendering; -import java.text.MessageFormat; - -import com.google.common.html.HtmlEscapers; +import com.google.common.base.Function; import com.google.common.net.MediaType; import com.enonic.xp.app.ApplicationKey; @@ -12,6 +10,7 @@ import com.enonic.xp.portal.RenderMode; import com.enonic.xp.portal.controller.ControllerScript; import com.enonic.xp.portal.controller.ControllerScriptFactory; +import com.enonic.xp.portal.impl.html.HtmlBuilder; import com.enonic.xp.region.Component; import com.enonic.xp.region.ComponentDescriptor; import com.enonic.xp.region.DescriptorBasedComponent; @@ -19,26 +18,31 @@ import com.enonic.xp.web.HttpStatus; import static com.google.common.base.Strings.nullToEmpty; +import static java.util.Objects.requireNonNullElse; public abstract class DescriptorBasedComponentRenderer implements Renderer { - private static final String EMPTY_COMPONENT_EDIT_MODE_HTML = - "
"; - - private static final String EMPTY_COMPONENT_PREVIEW_MODE_HTML = - "
"; - - private static final String COMPONENT_PLACEHOLDER_ERROR_HTML = "
{1}
"; - private static final LiveEditAttributeInjection LIVE_EDIT_ATTRIBUTE_INJECTION = new LiveEditAttributeInjection(); private final ControllerScriptFactory controllerScriptFactory; - public DescriptorBasedComponentRenderer( final ControllerScriptFactory controllerScriptFactory ) + private final Class type; + + private final Function componentDescriptorGetter; + + public DescriptorBasedComponentRenderer( final ControllerScriptFactory controllerScriptFactory, final Class type, + final Function componentDescriptorGetter ) { this.controllerScriptFactory = controllerScriptFactory; + this.type = type; + this.componentDescriptorGetter = componentDescriptorGetter; + } + + @Override + public Class getType() + { + return type; } @Override @@ -64,7 +68,7 @@ private PortalResponse doRender( final R component, final PortalRequest portalRe final ComponentDescriptor descriptor = resolveDescriptor( component ); if ( descriptor == null ) { - return renderEmptyComponent( component, portalRequest ); + return renderEmptyComponent( component ); } final ResourceKey script = descriptor.getComponentPath().resolve( descriptor.getComponentPath().getName() + ".js" ); @@ -89,11 +93,10 @@ private PortalResponse doRender( final R component, final PortalRequest portalRe { if ( portalResponse.getStatus().equals( HttpStatus.METHOD_NOT_ALLOWED ) ) { - final String errorMessage = "No method provided to handle request"; - return renderErrorComponentPlaceHolder( component, errorMessage ); + return renderErrorComponentPlaceHolder( component, "No method provided to handle request" ); } - return renderEmptyComponent( component, portalRequest ); + return renderEmptyComponent( component ); } } @@ -108,32 +111,13 @@ private PortalResponse doRender( final R component, final PortalRequest portalRe } } - private PortalResponse renderEmptyComponent( final DescriptorBasedComponent component, final PortalRequest portalRequest ) + private PortalResponse renderEmptyComponent( final DescriptorBasedComponent component ) { - final RenderMode renderMode = portalRequest.getMode(); - if ( renderMode == RenderMode.EDIT ) - { - return renderEmptyComponentEditMode( component ); - } - else - { - return renderEmptyComponentPreviewMode( component ); - } - } - - private PortalResponse renderEmptyComponentEditMode( final DescriptorBasedComponent component ) - { - final String html = MessageFormat.format( EMPTY_COMPONENT_EDIT_MODE_HTML, component.getType().toString() ); - - return PortalResponse.create(). - contentType( MediaType.HTML_UTF_8 ). - body( html ). - build(); - } - - private PortalResponse renderEmptyComponentPreviewMode( final DescriptorBasedComponent component ) - { - final String html = MessageFormat.format( EMPTY_COMPONENT_PREVIEW_MODE_HTML, component.getType().toString() ); + final String html = new HtmlBuilder().open( "div" ) + .attribute( RenderingConstants.PORTAL_COMPONENT_ATTRIBUTE, component.getType().toString() ) + .text( "" ) + .close() + .toString(); return PortalResponse.create(). contentType( MediaType.HTML_UTF_8 ). @@ -143,9 +127,16 @@ private PortalResponse renderEmptyComponentPreviewMode( final DescriptorBasedCom private PortalResponse renderErrorComponentPlaceHolder( final DescriptorBasedComponent component, final String errorMessage ) { - final String escapedMessage = errorMessage == null ? "" : HtmlEscapers.htmlEscaper().escape( errorMessage ); - final String html = MessageFormat.format( COMPONENT_PLACEHOLDER_ERROR_HTML, component.getType().toString(), escapedMessage ); - + final String html = new HtmlBuilder().open( "div" ) + .attribute( RenderingConstants.PORTAL_COMPONENT_ATTRIBUTE, component.getType().toString() ) + .attribute( "data-portal-placeholder", "true" ) + .attribute( "data-portal-placeholder-error", "true" ) + .open( "span" ) + .attribute( "class", "data-portal-placeholder-error" ) + .escapedText( requireNonNullElse( errorMessage, "" ) ) + .close() + .close() + .toString(); return PortalResponse.create(). contentType( MediaType.HTML_UTF_8 ). body( html ). @@ -155,8 +146,6 @@ private PortalResponse renderErrorComponentPlaceHolder( final DescriptorBasedCom private ComponentDescriptor resolveDescriptor( final DescriptorBasedComponent component ) { final DescriptorKey descriptorKey = component.getDescriptor(); - return descriptorKey == null ? null : getComponentDescriptor( descriptorKey ); + return descriptorKey == null ? null : componentDescriptorGetter.apply( descriptorKey ); } - - protected abstract ComponentDescriptor getComponentDescriptor( DescriptorKey descriptorKey ); } diff --git a/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/rendering/FragmentRenderer.java b/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/rendering/FragmentRenderer.java index 6a1f71a8719..ea93d6f87a2 100644 --- a/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/rendering/FragmentRenderer.java +++ b/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/rendering/FragmentRenderer.java @@ -1,11 +1,8 @@ package com.enonic.xp.portal.impl.rendering; -import java.text.MessageFormat; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.html.HtmlEscapers; import com.google.common.net.MediaType; import com.enonic.xp.content.Content; @@ -15,6 +12,7 @@ import com.enonic.xp.portal.PortalRequest; import com.enonic.xp.portal.PortalResponse; import com.enonic.xp.portal.RenderMode; +import com.enonic.xp.portal.impl.html.HtmlBuilder; import com.enonic.xp.region.Component; import com.enonic.xp.region.FragmentComponent; import com.enonic.xp.region.LayoutComponent; @@ -22,17 +20,10 @@ import com.enonic.xp.region.LayoutDescriptorService; import com.enonic.xp.region.LayoutRegions; import com.enonic.xp.region.Region; +import com.enonic.xp.web.HttpStatus; public final class FragmentRenderer { - private static final String EMPTY_FRAGMENT_HTML = "
"; - - private static final String EDIT_MODE_FRAGMENT_WRAPPER_HTML = - "
{1}
"; - - private static final String COMPONENT_PLACEHOLDER_ERROR_HTML = "
{1}
"; - private static final Logger LOG = LoggerFactory.getLogger( FragmentRenderer.class ); private final ContentService contentService; @@ -58,22 +49,28 @@ public PortalResponse render( final FragmentComponent component, final PortalReq if ( component.getFragment() == null ) { - return renderEmptyFragment( renderMode, component ); + if ( renderMode == RenderMode.EDIT ) + { + return renderEmptyFragmentInEdit( component ); + } + else + { + return renderResponse( "", HttpStatus.NOT_FOUND ); + } } final Component fragmentComponent = getFragmentComponent( component ); if ( fragmentComponent == null ) { - LOG.warn( "Fragment content could not be found. ContentId: " + component.getFragment().toString() ); + LOG.warn( "Fragment content could not be found. ContentId: {}", component.getFragment() ); if ( renderMode == RenderMode.EDIT ) { - final String errorMessage = "Fragment content could not be found"; - return renderErrorComponentPlaceHolder( component, errorMessage ); + return renderErrorComponentPlaceHolderInEdit( component, "Fragment content could not be found" ); } else { - return renderEmptyFragment( renderMode, component ); + return renderResponse( "", HttpStatus.NOT_FOUND ); } } @@ -98,7 +95,7 @@ public PortalResponse render( final FragmentComponent component, final PortalReq if ( body.contains( noMethodErrorMessage ) ) { - return renderErrorComponentPlaceHolder( component, noMethodErrorMessage ); + return renderErrorComponentPlaceHolderInEdit( component, noMethodErrorMessage ); } return wrapFragmentForEditMode( fragmentResponse, type ); @@ -108,8 +105,11 @@ public PortalResponse render( final FragmentComponent component, final PortalReq private PortalResponse wrapFragmentForEditMode( final PortalResponse response, final String type ) { - final String body = (String) response.getBody(); - final String wrappedBody = MessageFormat.format( EDIT_MODE_FRAGMENT_WRAPPER_HTML, type, body ); + final String wrappedBody = new HtmlBuilder().open( "div" ) + .attribute( RenderingConstants.PORTAL_COMPONENT_ATTRIBUTE, type ) + .text( (String) response.getBody() ) + .close() + .toString(); return PortalResponse.create( response ).body( wrappedBody ).build(); } @@ -176,17 +176,34 @@ private LayoutComponent buildLayoutWithRegions( final LayoutComponent existingLa return layoutBuilder.regions( regionsBuilder.build() ).build(); } - private PortalResponse renderEmptyFragment( final RenderMode renderMode, final FragmentComponent component ) + private PortalResponse renderEmptyFragmentInEdit( final FragmentComponent component ) { - final String type = component.getType().toString(); - final String html = renderMode == RenderMode.EDIT ? MessageFormat.format( EMPTY_FRAGMENT_HTML, type ) : ""; - return PortalResponse.create().body( html ).contentType( MediaType.HTML_UTF_8 ).postProcess( false ).build(); + final String html = new HtmlBuilder().open( "div" ) + .attribute( RenderingConstants.PORTAL_COMPONENT_ATTRIBUTE, component.getType().toString() ) + .text( "" ) + .close() + .toString(); + return renderResponse( html, HttpStatus.OK ); + } + + private static PortalResponse renderResponse( final String html, HttpStatus status ) + { + return PortalResponse.create().body( html ).status( status ).contentType( MediaType.HTML_UTF_8 ).postProcess( false ).build(); } - private PortalResponse renderErrorComponentPlaceHolder( final FragmentComponent component, final String errorMessage ) + private PortalResponse renderErrorComponentPlaceHolderInEdit( final FragmentComponent component, final String errorMessage ) { - final String escapedMessage = HtmlEscapers.htmlEscaper().escape( errorMessage ); - final String html = MessageFormat.format( COMPONENT_PLACEHOLDER_ERROR_HTML, component.getType().toString(), escapedMessage ); - return PortalResponse.create().contentType( MediaType.HTML_UTF_8 ).postProcess( false ).body( html ).build(); + final String html = new HtmlBuilder().open( "div" ) + .attribute( RenderingConstants.PORTAL_COMPONENT_ATTRIBUTE, component.getType().toString() ) + .attribute( "data-portal-placeholder", "true" ) + .attribute( "data-portal-placeholder-error", "true" ) + .open( "span" ) + .attribute( "class", "data-portal-placeholder-error" ) + .escapedText( errorMessage ) + .close() + .close() + .toString(); + + return renderResponse( html, HttpStatus.OK ); } } diff --git a/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/rendering/ImageRenderer.java b/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/rendering/ImageRenderer.java index 5f78d9d0163..0426899b8b5 100644 --- a/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/rendering/ImageRenderer.java +++ b/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/rendering/ImageRenderer.java @@ -1,13 +1,11 @@ package com.enonic.xp.portal.impl.rendering; -import java.text.MessageFormat; - +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import com.google.common.html.HtmlEscapers; import com.google.common.net.MediaType; import com.enonic.xp.attachment.Attachment; @@ -18,24 +16,28 @@ import com.enonic.xp.portal.PortalRequest; import com.enonic.xp.portal.PortalResponse; import com.enonic.xp.portal.RenderMode; +import com.enonic.xp.portal.impl.html.HtmlBuilder; import com.enonic.xp.portal.url.ImageUrlParams; import com.enonic.xp.portal.url.PortalUrlService; import com.enonic.xp.region.ImageComponent; +import com.enonic.xp.web.HttpStatus; @Component(immediate = true, service = Renderer.class) public final class ImageRenderer implements Renderer { - private static final String EMPTY_IMAGE_HTML = "
"; - - private static final String COMPONENT_PLACEHOLDER_ERROR_HTML = "
{1}
"; - private static final Logger LOG = LoggerFactory.getLogger( ImageRenderer.class ); - private PortalUrlService urlService; + private final PortalUrlService urlService; - private ContentService contentService; + private final ContentService contentService; + + @Activate + public ImageRenderer( @Reference final PortalUrlService urlService, @Reference final ContentService contentService ) + { + this.urlService = urlService; + this.contentService = contentService; + } @Override public Class getType() @@ -55,8 +57,6 @@ private final class ImageComponentRenderer private final PortalRequest portalRequest; - private static final String ERROR_IMAGE_NOT_FOUND = "Image could not be found"; - private ImageComponentRenderer( final ImageComponent component, final PortalRequest portalRequest ) { this.component = component; @@ -69,7 +69,7 @@ private PortalResponse render() { if ( component.hasImage() ) { - return renderOkResponse( generateImageHtml() ); + return renderResponse( generateImageHtml(), HttpStatus.OK ); } return renderResponseNoImage(); } @@ -81,45 +81,30 @@ private PortalResponse render() private String generateImageHtml() { - final StringBuilder html = new StringBuilder(); - - appendFigureTag( html ); - - return html.toString(); - } - - private void appendFigureTag( final StringBuilder html ) - { - openFigureTag( html ); - appendImageTag( html ); - appendCaptionTag( html ); - closeFigureTag( html ); - } - - private void openFigureTag( final StringBuilder html ) - { - final String type = component.getType().toString(); - html.append( "
" ); - } - - private void appendImageTag( final StringBuilder html ) - { - html.append( "" ); - } - - private void appendAltAttribute( final StringBuilder html ) - { final String altText = getImageAlternativeText(); if ( altText != null ) { - html.append( "alt=\"" ).append( altText ).append( "\"" ); + htmlBuilder.attribute( "alt", altText ); } + htmlBuilder.closeEmpty(); + + if ( component.hasCaption() ) + { + htmlBuilder.open( "figcaption" ).escapedText( component.getCaption() ).close(); + } + + htmlBuilder.close(); + + return htmlBuilder.toString(); } private String buildUrl() @@ -161,27 +146,14 @@ private String getImageAttachmentName( final Content image ) return null; } - private void appendCaptionTag( final StringBuilder html ) + private PortalResponse renderResponse( final String html, final HttpStatus status ) { - if ( component.hasCaption() ) - { - html.append( "
" ).append( component.getCaption() ).append( "
" ); - } - } - - private void closeFigureTag( final StringBuilder html ) - { - html.append( "
" ); - } - - private PortalResponse renderOkResponse( final String html ) - { - return PortalResponse.create().body( html ).contentType( MediaType.HTML_UTF_8 ).postProcess( false ).build(); + return PortalResponse.create().body( html ).contentType( MediaType.HTML_UTF_8 ).status( status ).postProcess( false ).build(); } private PortalResponse renderResponseImageNotFound() { - LOG.warn( "Image content could not be found. ContentId: " + component.getImage().toString() ); + LOG.warn( "Image content could not be found. ContentId: {}", component.getImage() ); final RenderMode renderMode = portalRequest.getMode(); @@ -190,9 +162,7 @@ private PortalResponse renderResponseImageNotFound() return renderErrorResponse(); } - final String componentType = component.getType().toString(); - - return renderOkResponse( MessageFormat.format( EMPTY_IMAGE_HTML, componentType ) ); + return renderEmptyFigure( HttpStatus.NOT_FOUND ); } private PortalResponse renderResponseNoImage() @@ -201,32 +171,36 @@ private PortalResponse renderResponseNoImage() if ( renderMode == RenderMode.EDIT ) { - final String componentType = component.getType().toString(); - - return renderOkResponse( MessageFormat.format( EMPTY_IMAGE_HTML, componentType ) ); + return renderEmptyFigure( HttpStatus.OK ); } - return renderOkResponse( "" ); + return renderResponse( "", HttpStatus.NOT_FOUND ); + } + + private PortalResponse renderEmptyFigure( final HttpStatus status ) + { + final String html = new HtmlBuilder().open( "figure" ) + .attribute( RenderingConstants.PORTAL_COMPONENT_ATTRIBUTE, component.getType().toString() ) + .text( "" ) + .close() + .toString(); + return renderResponse( html, status ); } private PortalResponse renderErrorResponse() { - final String escapedMessage = HtmlEscapers.htmlEscaper().escape( ERROR_IMAGE_NOT_FOUND ); - final String html = MessageFormat.format( COMPONENT_PLACEHOLDER_ERROR_HTML, component.getType().toString(), escapedMessage ); + final String html = new HtmlBuilder().open( "div" ) + .attribute( RenderingConstants.PORTAL_COMPONENT_ATTRIBUTE, component.getType().toString() ) + .attribute( "data-portal-placeholder", "true" ) + .attribute( "data-portal-placeholder-error", "true" ) + .open( "span" ) + .attribute( "class", "data-portal-placeholder-error" ) + .text( "Image could not be found" ) + .close() + .close() + .toString(); return PortalResponse.create().contentType( MediaType.HTML_UTF_8 ).postProcess( false ).body( html ).build(); } } - - @Reference - public void setUrlService( final PortalUrlService urlService ) - { - this.urlService = urlService; - } - - @Reference - public void setContentService( final ContentService contentService ) - { - this.contentService = contentService; - } } diff --git a/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/rendering/LayoutRenderer.java b/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/rendering/LayoutRenderer.java index 60cf0c4a806..c1b271c0fb2 100644 --- a/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/rendering/LayoutRenderer.java +++ b/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/rendering/LayoutRenderer.java @@ -4,9 +4,7 @@ import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; -import com.enonic.xp.page.DescriptorKey; import com.enonic.xp.portal.controller.ControllerScriptFactory; -import com.enonic.xp.region.ComponentDescriptor; import com.enonic.xp.region.LayoutComponent; import com.enonic.xp.region.LayoutDescriptorService; @@ -14,25 +12,10 @@ public final class LayoutRenderer extends DescriptorBasedComponentRenderer { - private final LayoutDescriptorService layoutDescriptorService; - @Activate public LayoutRenderer( @Reference final ControllerScriptFactory controllerScriptFactory, @Reference final LayoutDescriptorService layoutDescriptorService ) { - super( controllerScriptFactory ); - this.layoutDescriptorService = layoutDescriptorService; - } - - @Override - public Class getType() - { - return LayoutComponent.class; - } - - @Override - protected ComponentDescriptor getComponentDescriptor( final DescriptorKey descriptorKey ) - { - return layoutDescriptorService.getByKey( descriptorKey ); + super( controllerScriptFactory, LayoutComponent.class, layoutDescriptorService::getByKey ); } } diff --git a/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/rendering/PartRenderer.java b/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/rendering/PartRenderer.java index bb12e26dc34..a0ab424cbfc 100644 --- a/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/rendering/PartRenderer.java +++ b/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/rendering/PartRenderer.java @@ -4,9 +4,7 @@ import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; -import com.enonic.xp.page.DescriptorKey; import com.enonic.xp.portal.controller.ControllerScriptFactory; -import com.enonic.xp.region.ComponentDescriptor; import com.enonic.xp.region.PartComponent; import com.enonic.xp.region.PartDescriptorService; @@ -14,24 +12,10 @@ public final class PartRenderer extends DescriptorBasedComponentRenderer { - private final PartDescriptorService partDescriptorService; - @Activate - public PartRenderer( @Reference final ControllerScriptFactory controllerScriptFactory, @Reference final PartDescriptorService partDescriptorService ) - { - super( controllerScriptFactory ); - this.partDescriptorService = partDescriptorService; - } - - @Override - public Class getType() - { - return PartComponent.class; - } - - @Override - protected ComponentDescriptor getComponentDescriptor( final DescriptorKey descriptorKey ) + public PartRenderer( @Reference final ControllerScriptFactory controllerScriptFactory, + @Reference final PartDescriptorService partDescriptorService ) { - return this.partDescriptorService.getByKey( descriptorKey ); + super( controllerScriptFactory, PartComponent.class, partDescriptorService::getByKey ); } } diff --git a/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/rendering/TextRenderer.java b/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/rendering/TextRenderer.java index 5f93b6a4397..cab479b1659 100644 --- a/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/rendering/TextRenderer.java +++ b/modules/portal/portal-impl/src/main/java/com/enonic/xp/portal/impl/rendering/TextRenderer.java @@ -1,7 +1,6 @@ package com.enonic.xp.portal.impl.rendering; -import java.text.MessageFormat; - +import org.osgi.service.component.annotations.Activate; import org.osgi.service.component.annotations.Component; import org.osgi.service.component.annotations.Reference; @@ -11,6 +10,7 @@ import com.enonic.xp.portal.PortalResponse; import com.enonic.xp.portal.RenderMode; import com.enonic.xp.portal.html.HtmlElement; +import com.enonic.xp.portal.impl.html.HtmlBuilder; import com.enonic.xp.portal.url.PortalUrlService; import com.enonic.xp.portal.url.ProcessHtmlParams; import com.enonic.xp.region.TextComponent; @@ -21,9 +21,13 @@ public final class TextRenderer implements Renderer { - PortalUrlService service; + private final PortalUrlService portalUrlService; - private static final String COMPONENT_HTML = "
{1}
"; + @Activate + public TextRenderer( @Reference final PortalUrlService portalUrlService ) + { + this.portalUrlService = portalUrlService; + } @Override public Class getType() @@ -42,7 +46,7 @@ public PortalResponse render( final TextComponent textComponent, final PortalReq final String text = textComponent.getText(); if ( renderMode == RenderMode.EDIT ) { - portalResponseBuilder.body( MessageFormat.format( COMPONENT_HTML, textComponent.getType().toString(), text ) ); + portalResponseBuilder.body( renderHtml( textComponent, text ) ); } else { @@ -52,26 +56,27 @@ public PortalResponse render( final TextComponent textComponent, final PortalReq } else { - ProcessHtmlParams params = new ProcessHtmlParams().portalRequest( portalRequest ). - value( text ). - customHtmlProcessor( processor -> { + ProcessHtmlParams params = + new ProcessHtmlParams().portalRequest( portalRequest ).value( text ).customHtmlProcessor( processor -> { processor.processDefault(); - processor.getDocument().select( "figcaption:empty" ). - forEach( HtmlElement::remove ); + processor.getDocument().select( "figcaption:empty" ).forEach( HtmlElement::remove ); return processor.getDocument().getInnerHtml(); } ); - final String processedHtml = service.processHtml( params ); - portalResponseBuilder.body( MessageFormat.format( COMPONENT_HTML, textComponent.getType().toString(), processedHtml ) ); + final String processedHtml = portalUrlService.processHtml( params ); + portalResponseBuilder.body( renderHtml( textComponent, processedHtml ) ); } } return portalResponseBuilder.build(); } - @Reference - public void setPortalUrlService( final PortalUrlService service ) + private static String renderHtml( final TextComponent textComponent, final String text ) { - this.service = service; + return new HtmlBuilder().open( "section" ) + .attribute( PORTAL_COMPONENT_ATTRIBUTE, textComponent.getType().toString() ) + .text( text ) + .close() + .toString(); } } diff --git a/modules/portal/portal-impl/src/test/java/com/enonic/xp/portal/impl/rendering/ImageRendererTest.java b/modules/portal/portal-impl/src/test/java/com/enonic/xp/portal/impl/rendering/ImageRendererTest.java index 25d05bb3224..29076dacb57 100644 --- a/modules/portal/portal-impl/src/test/java/com/enonic/xp/portal/impl/rendering/ImageRendererTest.java +++ b/modules/portal/portal-impl/src/test/java/com/enonic/xp/portal/impl/rendering/ImageRendererTest.java @@ -14,14 +14,13 @@ import com.enonic.xp.portal.impl.ContentFixtures; import com.enonic.xp.portal.impl.url.AbstractPortalUrlServiceImplTest; import com.enonic.xp.region.ImageComponent; +import com.enonic.xp.web.HttpStatus; import static org.junit.jupiter.api.Assertions.assertEquals; public class ImageRendererTest extends AbstractPortalUrlServiceImplTest { - private PortalResponse portalResponse; - private ImageComponent imageComponent; private ImageRenderer renderer; @@ -37,7 +36,6 @@ private Content createContent() @BeforeEach public void before() { - portalResponse = PortalResponse.create().build(); portalRequest.setMode( RenderMode.LIVE ); } @@ -46,13 +44,14 @@ public void imageComponentWithNoImage() { // setup imageComponent = ImageComponent.create().build(); - renderer = new ImageRenderer(); + renderer = new ImageRenderer( this.service, contentService ); // exercise - portalResponse = renderer.render( imageComponent, portalRequest ); + PortalResponse portalResponse = renderer.render( imageComponent, portalRequest ); // verify assertEquals( "", portalResponse.getAsString() ); + assertEquals( HttpStatus.NOT_FOUND, portalResponse.getStatus() ); } @Test @@ -83,12 +82,10 @@ private void testImageComponentWithImage( final Content content, final String ex final PropertyTree config = new PropertyTree(); config.addString( "caption", "Image Title" ); imageComponent = ImageComponent.create().image( ContentId.from( "123456" ) ).config( config ).build(); - renderer = new ImageRenderer(); - renderer.setUrlService( this.service ); - renderer.setContentService( contentService ); + renderer = new ImageRenderer( this.service, contentService ); // exercise - portalResponse = renderer.render( imageComponent, portalRequest ); + PortalResponse portalResponse = renderer.render( imageComponent, portalRequest ); // verify assertEquals( expected, portalResponse.getAsString() ); @@ -101,14 +98,15 @@ public void imageComponentRenderModeEdit() // setup portalRequest.setMode( RenderMode.EDIT ); imageComponent = ImageComponent.create().build(); - renderer = new ImageRenderer(); + renderer = new ImageRenderer( this.service, contentService ); // exercise - portalResponse = renderer.render( imageComponent, portalRequest ); + PortalResponse portalResponse = renderer.render( imageComponent, portalRequest ); // verify String result = "
"; assertEquals( result, portalResponse.getAsString() ); + assertEquals( HttpStatus.OK, portalResponse.getStatus() ); } @Test @@ -124,16 +122,15 @@ public void imageComponentMissingImageModeLive() final PropertyTree config = new PropertyTree(); config.addString( "caption", "Image Title" ); imageComponent = ImageComponent.create().image( ContentId.from( "123456" ) ).config( config ).build(); - renderer = new ImageRenderer(); - renderer.setUrlService( this.service ); - renderer.setContentService( contentService ); + renderer = new ImageRenderer( this.service, contentService ); // exercise - portalResponse = renderer.render( imageComponent, portalRequest ); + PortalResponse portalResponse = renderer.render( imageComponent, portalRequest ); // verify String result = "
"; assertEquals( result, portalResponse.getAsString() ); + assertEquals( HttpStatus.NOT_FOUND, portalResponse.getStatus() ); } @Test @@ -151,17 +148,16 @@ public void imageComponentMissingImageModeEdit() imageComponent = ImageComponent.create().image( ContentId.from( "123456" ) ).config( config ).build(); - renderer = new ImageRenderer(); - renderer.setUrlService( this.service ); - renderer.setContentService( contentService ); + renderer = new ImageRenderer( this.service, contentService ); // exercise - portalResponse = renderer.render( imageComponent, portalRequest ); + PortalResponse portalResponse = renderer.render( imageComponent, portalRequest ); // verify String result = "
Image could not be found
"; assertEquals( result, portalResponse.getAsString() ); + assertEquals( HttpStatus.OK, portalResponse.getStatus() ); } @Test @@ -174,11 +170,10 @@ public void testRenderImageComponentWithReadPermission() imageComponent = ImageComponent.create().image( ContentId.from( "id" ) ).build(); - renderer = new ImageRenderer(); - renderer.setUrlService( this.service ); - renderer.setContentService( contentService ); + renderer = new ImageRenderer(this.service, contentService ); PortalResponse response = renderer.render( imageComponent, portalRequest ); assertEquals( "
", response.getAsString() ); + assertEquals( HttpStatus.NOT_FOUND, response.getStatus() ); } } diff --git a/modules/portal/portal-impl/src/test/java/com/enonic/xp/portal/impl/rendering/TextRendererTest.java b/modules/portal/portal-impl/src/test/java/com/enonic/xp/portal/impl/rendering/TextRendererTest.java index 019f103c0c4..84a88074e81 100644 --- a/modules/portal/portal-impl/src/test/java/com/enonic/xp/portal/impl/rendering/TextRendererTest.java +++ b/modules/portal/portal-impl/src/test/java/com/enonic/xp/portal/impl/rendering/TextRendererTest.java @@ -50,8 +50,7 @@ public void textComponentWithNoText() { // setup textComponent = TextComponent.create().build(); - renderer = new TextRenderer(); - renderer.setPortalUrlService( service ); + renderer = new TextRenderer( service ); // exercise portalResponse = renderer.render( textComponent, portalRequest ); @@ -66,8 +65,7 @@ public void textComponentWithNoTextAndRenderModeEdit() // setup portalRequest.setMode( RenderMode.EDIT ); textComponent = TextComponent.create().build(); - renderer = new TextRenderer(); - renderer.setPortalUrlService( service ); + renderer = new TextRenderer( service ); // exercise portalResponse = renderer.render( textComponent, portalRequest ); @@ -81,8 +79,7 @@ public void textComponentWithNoTextAndRenderModePreview() // setup portalRequest.setMode( RenderMode.PREVIEW ); textComponent = TextComponent.create().build(); - renderer = new TextRenderer(); - renderer.setPortalUrlService( service ); + renderer = new TextRenderer( service ); // exercise portalResponse = renderer.render( textComponent, portalRequest ); @@ -97,8 +94,7 @@ public void textComponentWithNoTextAndRenderModeInline() // setup portalRequest.setMode( RenderMode.INLINE ); textComponent = TextComponent.create().build(); - renderer = new TextRenderer(); - renderer.setPortalUrlService( service ); + renderer = new TextRenderer( service ); // exercise portalResponse = renderer.render( textComponent, portalRequest ); @@ -114,8 +110,7 @@ public void textComponentWithSomeTextAndRenderModePreview() // setup String text = "

hello

How are you?

"; textComponent = TextComponent.create().text( text ).build(); - renderer = new TextRenderer(); - renderer.setPortalUrlService( service ); + renderer = new TextRenderer( service ); // exercise portalResponse = renderer.render( textComponent, portalRequest ); @@ -130,8 +125,7 @@ public void textComponentRendererRemovesEmptyFigCaptionTags() // setup String text = "
\n" + "
\n" + "
"; textComponent = TextComponent.create().text( text ).build(); - renderer = new TextRenderer(); - renderer.setPortalUrlService( service ); + renderer = new TextRenderer( service ); // exercise portalResponse = renderer.render( textComponent, portalRequest ); @@ -147,8 +141,7 @@ public void textComponentWithSomeTextAndRenderModeEdit() portalRequest.setMode( RenderMode.EDIT ); String text = "

hello

How are you?

"; textComponent = TextComponent.create().text( text ).build(); - renderer = new TextRenderer(); - renderer.setPortalUrlService( service ); + renderer = new TextRenderer( service ); // exercise portalResponse = renderer.render( textComponent, portalRequest );