1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.templating.elements;
35
36 import info.magnolia.cms.beans.config.ServerConfiguration;
37 import info.magnolia.cms.i18n.Messages;
38 import info.magnolia.cms.i18n.MessagesManager;
39 import info.magnolia.context.MgnlContext;
40 import info.magnolia.context.WebContext;
41 import info.magnolia.jcr.inheritance.InheritanceNodeWrapper;
42 import info.magnolia.registry.RegistrationException;
43 import info.magnolia.rendering.context.RenderingContext;
44 import info.magnolia.rendering.engine.AppendableOnlyOutputProvider;
45 import info.magnolia.rendering.engine.RenderException;
46 import info.magnolia.rendering.engine.RenderingEngine;
47 import info.magnolia.rendering.template.TemplateDefinition;
48 import info.magnolia.rendering.template.assignment.TemplateDefinitionAssignment;
49 import info.magnolia.templating.freemarker.AreaDirective;
50
51 import java.io.IOException;
52 import java.util.HashMap;
53 import java.util.Map;
54
55 import javax.inject.Inject;
56 import javax.jcr.Node;
57 import javax.jcr.RepositoryException;
58 import javax.jcr.Session;
59
60 import org.apache.commons.lang.StringUtils;
61 import org.slf4j.Logger;
62 import org.slf4j.LoggerFactory;
63
64
65
66
67
68
69 public class ComponentElement extends AbstractContentTemplatingElement {
70
71 private static final Logger log = LoggerFactory.getLogger(ComponentElement.class);
72
73 private Map<String, Object> contextAttributes = new HashMap<String, Object>();
74 private final RenderingEngine renderingEngine;
75 private Node content;
76 private final TemplateDefinitionAssignment templateDefinitionAssignment;
77 private TemplateDefinition componentDefinition;
78
79 private boolean renderEditbar = true;
80 private String dialog;
81 private Boolean editable;
82
83 @Inject
84 public ComponentElement(ServerConfiguration server, RenderingContext renderingContext, RenderingEngine renderingEngine, TemplateDefinitionAssignment templateDefinitionAssignment ) {
85 super(server, renderingContext);
86 this.renderingEngine = renderingEngine;
87 this.templateDefinitionAssignment = templateDefinitionAssignment;
88 }
89
90 @Override
91 public void begin(Appendable out) throws IOException, RenderException {
92
93 content = getPassedContent();
94
95 if(content == null) {
96 throw new RenderException("The 'content' or 'workspace' and 'path' attribute have to be set to render a component.");
97 }
98
99 if(isAdmin() && hasPermission(content)){
100
101 try {
102 this.componentDefinition = templateDefinitionAssignment.getAssignedTemplateDefinition(content);
103 } catch (RegistrationException e) {
104 throw new RenderException("No template definition found for the current content", e);
105 }
106
107 final Messages messages = MessagesManager.getMessages(componentDefinition.getI18nBasename());
108
109 if (isRenderEditbar()) {
110 MarkupHelper helper = new MarkupHelper(out);
111
112 helper.openComment("cms:component");
113
114 helper.attribute(AreaDirective.CONTENT_ATTRIBUTE, getNodePath(content));
115
116 if(content instanceof InheritanceNodeWrapper) {
117 if (((InheritanceNodeWrapper) content).isInherited()) {
118 helper.attribute("inherited", "true");
119 }
120 }
121
122 this.editable = resolveEditable();
123 if (this.editable != null) {
124 helper.attribute("editable", String.valueOf(this.editable));
125 }
126
127 if(StringUtils.isEmpty(dialog)) {
128 dialog = resolveDialog();
129 }
130 helper.attribute("dialog", dialog);
131
132 String label = StringUtils.defaultIfEmpty(componentDefinition.getTitle(),componentDefinition.getName());
133 helper.attribute("label", messages.getWithDefault(label, label));
134
135 if(StringUtils.isNotEmpty(componentDefinition.getDescription())){
136 helper.attribute("description", componentDefinition.getDescription());
137 }
138 helper.append(" -->\n");
139 }
140 }
141
142
143
144 WebContext webContext = MgnlContext.getWebContext();
145 webContext.push(webContext.getRequest(), webContext.getResponse());
146 setAttributesInWebContext(contextAttributes, WebContext.LOCAL_SCOPE);
147
148
149 try {
150 if(componentDefinition != null) {
151 renderingEngine.render(content, componentDefinition, new HashMap<String, Object>(), new AppendableOnlyOutputProvider(out));
152 } else {
153 renderingEngine.render(content, new AppendableOnlyOutputProvider(out));
154 }
155 } finally {
156 webContext.pop();
157 webContext.setPageContext(null);
158 restoreAttributesInWebContext(contextAttributes, WebContext.LOCAL_SCOPE);
159 }
160 }
161
162 private boolean hasPermission(Node node) {
163 try {
164 return node.getSession().hasPermission(node.getPath(), Session.ACTION_SET_PROPERTY);
165 } catch (RepositoryException e) {
166 log.error("Could not determine permission for node {}", node);
167 }
168 return false;
169 }
170
171 private Boolean resolveEditable() {
172 return editable != null ? editable : componentDefinition != null && componentDefinition.getEditable() != null ? componentDefinition.getEditable() : null;
173 }
174
175 @Override
176 public void end(Appendable out) throws IOException, RenderException {
177 if(isAdmin()){
178 if (renderEditbar) {
179 new MarkupHelper(out).closeComment("cms:component");
180 }
181 }
182 }
183
184 public Map<String, Object> getContextAttributes() {
185 return contextAttributes;
186 }
187
188 public void setContextAttributes(Map<String, Object> contextAttributes) {
189 this.contextAttributes = contextAttributes;
190 }
191
192 private String resolveDialog() {
193 if (StringUtils.isNotEmpty(this.dialog)) {
194 return this.dialog;
195 }
196 String dialog = componentDefinition.getDialog();
197 if (StringUtils.isNotEmpty(dialog)) {
198 return dialog;
199 }
200 return null;
201 }
202
203 public void setDialog(String dialog) {
204 this.dialog = dialog;
205 }
206
207 public void setEditable(Boolean editable) {
208 this.editable = editable;
209 }
210
211 public Boolean getEditable() {
212 return editable;
213 }
214
215 public boolean isRenderEditbar() {
216 return renderEditbar;
217 }
218
219 public void setRenderEditbar(boolean renderEditbar) {
220 this.renderEditbar = renderEditbar;
221 }
222 }