matrei commented on code in PR #14875:
URL: https://github.com/apache/grails-core/pull/14875#discussion_r2183115856


##########
grails-gsp/grails-layout/src/main/groovy/org/grails/plugins/web/taglib/RenderGrailsLayoutTagLib.groovy:
##########
@@ -0,0 +1,337 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    https://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.grails.plugins.web.taglib
+
+import com.opensymphony.module.sitemesh.*
+import grails.artefact.TagLibrary
+import grails.core.GrailsApplication
+import grails.core.support.GrailsApplicationAware
+import grails.gsp.TagLib
+import grails.util.TypeConvertingMap
+import groovy.text.Template
+import groovy.transform.CompileStatic
+import org.apache.grails.web.layout.FactoryHolder
+import org.apache.grails.web.layout.GSPGrailsLayoutPage
+import org.apache.grails.web.layout.GrailsHTMLPageParser
+import org.apache.grails.web.layout.EmbeddedGrailsLayoutView
+import org.apache.grails.web.layout.GroovyPageLayoutFinder
+import org.apache.grails.web.layout.SpringMVCViewDecorator
+import org.grails.buffer.FastStringWriter
+import org.grails.buffer.StreamCharBuffer
+import org.grails.gsp.GroovyPageTemplate
+import org.grails.gsp.GroovyPagesTemplateEngine
+import org.grails.gsp.compiler.GroovyPageParser
+import org.grails.taglib.TagLibraryLookup
+import org.grails.taglib.TagOutput
+import org.grails.taglib.encoder.OutputContextLookupHelper
+import jakarta.servlet.http.HttpServletRequest
+
+/**
+ * Tags to help rendering of views and layouts.
+ *
+ * @author Graeme Rocher
+ */
+@CompileStatic
+@TagLib
+class RenderGrailsLayoutTagLib implements RequestConstants, TagLibrary, 
GrailsApplicationAware {
+    GroovyPagesTemplateEngine groovyPagesTemplateEngine
+    TagLibraryLookup gspTagLibraryLookup
+    GroovyPageLayoutFinder groovyPageLayoutFinder
+    protected boolean grailsLayoutPreprocessMode = true
+
+    protected HTMLPage getPage() {
+        return (HTMLPage) getRequest().getAttribute(PAGE)
+    }
+
+    @Override
+    void setGrailsApplication(GrailsApplication grailsApplication) {
+        grailsLayoutPreprocessMode = 
grailsApplication.config.getProperty(GroovyPageParser.CONFIG_PROPERTY_GSP_GRAILS_LAYOUT_PREPROCESS,
 Boolean, true)
+    }
+
+    protected boolean isGrailsLayoutPreprocessMode() {
+        return grailsLayoutPreprocessMode
+    }
+
+
+    /**
+     * Apply a layout to a particular block of text or to the given view or 
template.<br/>
+     *
+     * &lt;g:applyLayout name="myLayout"&gt;some 
text&lt;/g:applyLayout&gt;<br/>
+     * &lt;g:applyLayout name="myLayout" template="mytemplate" /&gt;<br/>
+     * &lt;g:applyLayout name="myLayout" url="http://www.google.com"; /&gt;<br/>
+     * &lt;g:applyLayout name="myLayout" action="myAction" 
controller="myController"&gt;<br/>
+     *
+     * @attr name The name of the layout
+     * @attr template Optional. The template to apply the layout to
+     * @attr url Optional. The URL to retrieve the content from and apply a 
layout to
+     * @attr action Optional. The action to be called to generate the content 
to apply the layout to
+     * @attr controller Optional. The controller that contains the action that 
will generate the content to apply the layout to
+     * @attr contentType Optional. The content type to use, default is 
"text/html"
+     * @attr encoding Optional. The encoding to use
+     * @attr params Optional. The params to pass onto the page object
+     * @attr parse Optional. If true, Grails Layout parser will always be used 
to parse the content.
+     */
+    Closure applyLayout = { Map attrs, body ->
+        if (!groovyPagesTemplateEngine) throw new 
IllegalStateException("Property [groovyPagesTemplateEngine] must be set!")
+        def oldPage = getPage()
+        String contentType = attrs.contentType ? attrs.contentType as String : 
"text/html"
+
+        Map pageParams = attrs.params instanceof Map ? (Map) attrs.params : [:]
+        Map viewModel = attrs.model instanceof Map ? (Map) attrs.model : [:]
+        Object content = null
+        GSPGrailsLayoutPage gspGrailsLayoutPage = null
+        if (attrs.url) {
+            content = new URL(attrs.url as String).getText("UTF-8")
+        } else if (attrs.action && attrs.controller) {
+            def includeAttrs = [action: attrs.action, controller: 
attrs.controller, params: pageParams, model: viewModel]
+            content = TagOutput.captureTagOutput(gspTagLibraryLookup, 'g', 
'include', includeAttrs, null, OutputContextLookupHelper.lookupOutputContext())
+        } else {
+            def oldGspGrailsLayoutPage = 
request.getAttribute(EmbeddedGrailsLayoutView.GSP_GRAILS_LAYOUT_PAGE)
+            try {
+                gspGrailsLayoutPage = new GSPGrailsLayoutPage()
+                
request.setAttribute(EmbeddedGrailsLayoutView.GSP_GRAILS_LAYOUT_PAGE, 
gspGrailsLayoutPage)
+                if (attrs.view || attrs.template) {
+                    content = TagOutput.captureTagOutput(gspTagLibraryLookup, 
'g', 'render', attrs, null, OutputContextLookupHelper.lookupOutputContext())
+                } else {
+                    def bodyClosure = 
TagOutput.createOutputCapturingClosure(this, body, 
OutputContextLookupHelper.lookupOutputContext())
+                    content = bodyClosure()
+                }
+                if (content instanceof StreamCharBuffer) {
+                    gspGrailsLayoutPage.setPageBuffer(content)
+                    gspGrailsLayoutPage.setUsed(isGrailsLayoutPreprocessMode())
+                } else if (content != null) {
+                    FastStringWriter stringWriter = new FastStringWriter()
+                    stringWriter.print((Object) content)
+                    gspGrailsLayoutPage.setPageBuffer(stringWriter.buffer)
+                    gspGrailsLayoutPage.setUsed(isGrailsLayoutPreprocessMode())
+                }
+            }
+            finally {
+                
request.setAttribute(EmbeddedGrailsLayoutView.GSP_GRAILS_LAYOUT_PAGE, 
oldGspGrailsLayoutPage)
+            }
+        }
+        if (content == null) {
+            content = ''
+        }
+
+        Page page = null
+        if (!((TypeConvertingMap) attrs).boolean('parse') && 
gspGrailsLayoutPage != null && gspGrailsLayoutPage.isUsed()) {
+            page = gspGrailsLayoutPage
+        } else {
+            def parser = createPageParser(contentType)
+            char[] charArray
+            if (content instanceof StreamCharBuffer) {
+                charArray = ((StreamCharBuffer) content).toCharArray()
+            } else {
+                charArray = content.toString().toCharArray()
+            }
+            page = parser.parse(charArray)
+        }
+
+        def decorator = findDecorator(request, attrs.name as String)
+        if (decorator && decorator.page) {
+            pageParams.each { k, v ->
+                page.addProperty(k as String, v as String)
+            }
+            try {
+                request.setAttribute(PAGE, page)
+                Template template = findTemplate(decorator)
+                template.make(viewModel).writeTo(out)
+            }
+            finally {
+                request.setAttribute(PAGE, oldPage)
+            }
+        } else {
+            out << content
+        }
+    }
+
+    protected Template findTemplate(Decorator decorator) {
+        Template template
+        if (decorator instanceof SpringMVCViewDecorator) {
+            template = ((SpringMVCViewDecorator) decorator).getTemplate()
+            if (template instanceof GroovyPageTemplate) {
+                GroovyPageTemplate gpt = (GroovyPageTemplate) template
+                gpt = (GroovyPageTemplate) gpt.clone()
+                gpt.setAllowSettingContentType(false)
+                template = gpt
+            }
+        } else {
+            template = 
groovyPagesTemplateEngine.createTemplate(decorator.getPage())
+        }
+        return template
+    }
+
+    protected Decorator findDecorator(HttpServletRequest req, String 
layoutName) {
+        DecoratorMapper decoratorMapper = sitemeshFactory?.getDecoratorMapper()
+        Decorator d
+        if (decoratorMapper) {
+            d = decoratorMapper.getNamedDecorator(req, layoutName)
+        } else {
+            d = groovyPageLayoutFinder.getNamedDecorator(req, layoutName)
+        }
+        d
+    }
+
+    protected PageParser createPageParser(String contentType) {
+        PageParser parser = sitemeshFactory?.getPageParser(contentType)
+        if (parser == null) {
+            parser = new GrailsHTMLPageParser()
+        }
+        return parser
+    }
+
+    protected Factory getSitemeshFactory() {
+        return FactoryHolder.getGrailsLayoutFactory()
+    }
+
+    /**
+     * Used to retrieve a property of the decorated page.<br/>
+     *
+     * &lt;g:pageProperty default="defaultValue" name="body.onload" /&gt;<br/>
+     *
+     * @emptyTag
+     *
+     * @attr REQUIRED name the property name
+     * @attr default the default value to use if the property is null
+     * @attr writeEntireProperty if true, writes the property in the form 'foo 
= "bar"', otherwise renders 'bar'
+     */
+    Closure pageProperty = { Map attrs ->
+        if (!attrs.name) {
+            throwTagError("Tag [pageProperty] is missing required attribute 
[name]")
+        }
+
+        String propertyName = attrs.name as String
+        def htmlPage = getPage()
+        def propertyValue

Review Comment:
   Assign `null` to `propertyValue`?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to