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 String dialog;
80 private Boolean editable;
81
82 @Inject
83 public ComponentElement(ServerConfiguration server, RenderingContext renderingContext, RenderingEngine renderingEngine, TemplateDefinitionAssignment templateDefinitionAssignment ) {
84 super(server, renderingContext);
85 this.renderingEngine = renderingEngine;
86 this.templateDefinitionAssignment = templateDefinitionAssignment;
87 }
88
89 @Override
90 public void begin(Appendable out) throws IOException, RenderException {
91
92 content = getPassedContent();
93
94 if(content == null) {
95 throw new RenderException("The 'content' or 'workspace' and 'path' attribute have to be set to render a component.");
96 }
97
98 if(isAdmin() && hasPermission(content)){
99 MarkupHelper helper = new MarkupHelper(out);
100
101 helper.openComment("cms:component");
102
103
104 helper.attribute(AreaDirective.CONTENT_ATTRIBUTE, getNodePath(content));
105
106 if(content instanceof InheritanceNodeWrapper) {
107 if (((InheritanceNodeWrapper) content).isInherited()) {
108 helper.attribute("inherited", "true");
109 }
110 }
111 try {
112 this.componentDefinition = templateDefinitionAssignment.getAssignedTemplateDefinition(content);
113 } catch (RegistrationException e) {
114 throw new RenderException("No template definition found for the current content", e);
115 }
116
117 final Messages messages = MessagesManager.getMessages(componentDefinition.getI18nBasename());
118
119 this.editable = resolveEditable();
120 if (this.editable != null) {
121 helper.attribute("editable", String.valueOf(this.editable));
122 }
123
124 if(StringUtils.isEmpty(dialog)) {
125 dialog = resolveDialog();
126 }
127 helper.attribute("dialog", dialog);
128
129 String label = StringUtils.defaultIfEmpty(componentDefinition.getTitle(),componentDefinition.getName());
130 helper.attribute("label", messages.getWithDefault(label, label));
131
132 if(StringUtils.isNotEmpty(componentDefinition.getDescription())){
133 helper.attribute("description", componentDefinition.getDescription());
134 }
135 helper.append(" -->\n");
136 }
137
138
139
140 WebContext webContext = MgnlContext.getWebContext();
141 webContext.push(webContext.getRequest(), webContext.getResponse());
142 setAttributesInWebContext(contextAttributes, WebContext.LOCAL_SCOPE);
143
144
145 try {
146 if(componentDefinition != null) {
147 renderingEngine.render(content, componentDefinition, new HashMap<String, Object>(), new AppendableOnlyOutputProvider(out));
148 } else {
149 renderingEngine.render(content, new AppendableOnlyOutputProvider(out));
150 }
151 } finally {
152 webContext.pop();
153 webContext.setPageContext(null);
154 restoreAttributesInWebContext(contextAttributes, WebContext.LOCAL_SCOPE);
155 }
156 }
157
158 private boolean hasPermission(Node node) {
159 try {
160 return node.getSession().hasPermission(node.getPath(), Session.ACTION_SET_PROPERTY);
161 } catch (RepositoryException e) {
162 log.error("Could not determine permission for node {}", node);
163 }
164 return false;
165 }
166
167 private Boolean resolveEditable() {
168 return editable != null ? editable : componentDefinition != null && componentDefinition.getEditable() != null ? componentDefinition.getEditable() : null;
169 }
170
171 @Override
172 public void end(Appendable out) throws IOException, RenderException {
173 if(isAdmin()){
174 new MarkupHelper(out).closeComment("cms:component");
175 }
176 }
177
178 public Map<String, Object> getContextAttributes() {
179 return contextAttributes;
180 }
181
182 public void setContextAttributes(Map<String, Object> contextAttributes) {
183 this.contextAttributes = contextAttributes;
184 }
185
186 private String resolveDialog() {
187 if (StringUtils.isNotEmpty(this.dialog)) {
188 return this.dialog;
189 }
190 String dialog = componentDefinition.getDialog();
191 if (StringUtils.isNotEmpty(dialog)) {
192 return dialog;
193 }
194 return null;
195 }
196
197 public void setDialog(String dialog) {
198 this.dialog = dialog;
199 }
200
201 public void setEditable(Boolean editable) {
202 this.editable = editable;
203 }
204
205 public Boolean getEditable() {
206 return editable;
207 }
208 }