| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. 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 |
| * |
| * http://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. For additional information regarding |
| * copyright in this work, please see the NOTICE file in the top level |
| * directory of this distribution. |
| */ |
| |
| package org.apache.roller.weblogger.pojos; |
| |
| import java.io.Serializable; |
| import java.io.UnsupportedEncodingException; |
| import java.net.URLEncoder; |
| import java.sql.Timestamp; |
| import java.text.SimpleDateFormat; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Calendar; |
| import java.util.Collections; |
| import java.util.Date; |
| import java.util.HashSet; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.StringTokenizer; |
| import java.util.TreeSet; |
| |
| import org.apache.commons.lang3.StringEscapeUtils; |
| import org.apache.commons.lang3.StringUtils; |
| import org.apache.commons.lang3.builder.EqualsBuilder; |
| import org.apache.commons.lang3.builder.HashCodeBuilder; |
| import org.apache.commons.logging.Log; |
| import org.apache.commons.logging.LogFactory; |
| import org.apache.roller.util.DateUtil; |
| import org.apache.roller.util.RollerConstants; |
| import org.apache.roller.util.UUIDGenerator; |
| import org.apache.roller.weblogger.WebloggerException; |
| import org.apache.roller.weblogger.business.UserManager; |
| import org.apache.roller.weblogger.business.WeblogEntryManager; |
| import org.apache.roller.weblogger.business.WebloggerFactory; |
| import org.apache.roller.weblogger.business.plugins.entry.WeblogEntryPlugin; |
| import org.apache.roller.weblogger.config.WebloggerConfig; |
| import org.apache.roller.weblogger.config.WebloggerRuntimeConfig; |
| import org.apache.roller.weblogger.util.HTMLSanitizer; |
| import org.apache.roller.weblogger.util.I18nMessages; |
| import org.apache.roller.weblogger.util.Utilities; |
| |
| /** |
| * Represents a Weblog Entry. |
| */ |
| public class WeblogEntry implements Serializable { |
| private static Log mLogger = |
| LogFactory.getFactory().getInstance(WeblogEntry.class); |
| |
| public static final long serialVersionUID = 2341505386843044125L; |
| |
| public enum PubStatus {DRAFT, PUBLISHED, PENDING, SCHEDULED} |
| |
| private static final char TITLE_SEPARATOR = |
| WebloggerConfig.getBooleanProperty("weblogentry.title.useUnderscoreSeparator") ? '_' : '-'; |
| |
| // Simple properies |
| private String id = UUIDGenerator.generateUUID(); |
| private String title = null; |
| private String link = null; |
| private String summary = null; |
| private String text = null; |
| private String contentType = null; |
| private String contentSrc = null; |
| private String anchor = null; |
| private Timestamp pubTime = null; |
| private Timestamp updateTime = null; |
| private String plugins = null; |
| private Boolean allowComments = Boolean.TRUE; |
| private Integer commentDays = 7; |
| private Boolean rightToLeft = Boolean.FALSE; |
| private Boolean pinnedToMain = Boolean.FALSE; |
| private PubStatus status = PubStatus.DRAFT; |
| private String locale = null; |
| private String creatorUserName = null; |
| private String searchDescription = null; |
| |
| // set to true when switching between pending/draft/scheduled and published |
| // either the aggregate table needs the entry's tags added (for published) |
| // or subtracted (anything else) |
| private Boolean refreshAggregates = Boolean.FALSE; |
| |
| // Associated objects |
| private Weblog website = null; |
| private WeblogCategory category = null; |
| |
| // Collection of name/value entry attributes |
| private Set<WeblogEntryAttribute> attSet = new TreeSet<WeblogEntryAttribute>(); |
| |
| private Set<WeblogEntryTag> tagSet = new HashSet<WeblogEntryTag>(); |
| private Set<WeblogEntryTag> removedTags = new HashSet<WeblogEntryTag>(); |
| private Set<WeblogEntryTag> addedTags = new HashSet<WeblogEntryTag>(); |
| |
| //----------------------------------------------------------- Construction |
| |
| public WeblogEntry() { |
| } |
| |
| public WeblogEntry( |
| String id, |
| WeblogCategory category, |
| Weblog website, |
| User creator, |
| String title, |
| String link, |
| String text, |
| String anchor, |
| Timestamp pubTime, |
| Timestamp updateTime, |
| PubStatus status) { |
| //this.id = id; |
| this.category = category; |
| this.website = website; |
| this.creatorUserName = creator.getUserName(); |
| this.title = title; |
| this.link = link; |
| this.text = text; |
| this.anchor = anchor; |
| this.pubTime = pubTime; |
| this.updateTime = updateTime; |
| this.status = status; |
| } |
| |
| public WeblogEntry(WeblogEntry otherData) { |
| this.setData(otherData); |
| } |
| |
| //---------------------------------------------------------- Initializaion |
| |
| /** |
| * Set bean properties based on other bean. |
| */ |
| public void setData(WeblogEntry other) { |
| |
| this.setId(other.getId()); |
| this.setCategory(other.getCategory()); |
| this.setWebsite(other.getWebsite()); |
| this.setCreatorUserName(other.getCreatorUserName()); |
| this.setTitle(other.getTitle()); |
| this.setLink(other.getLink()); |
| this.setText(other.getText()); |
| this.setSummary(other.getSummary()); |
| this.setSearchDescription(other.getSearchDescription()); |
| this.setAnchor(other.getAnchor()); |
| this.setPubTime(other.getPubTime()); |
| this.setUpdateTime(other.getUpdateTime()); |
| this.setStatus(other.getStatus()); |
| this.setPlugins(other.getPlugins()); |
| this.setAllowComments(other.getAllowComments()); |
| this.setCommentDays(other.getCommentDays()); |
| this.setRightToLeft(other.getRightToLeft()); |
| this.setPinnedToMain(other.getPinnedToMain()); |
| this.setLocale(other.getLocale()); |
| } |
| |
| //------------------------------------------------------- Good citizenship |
| |
| public String toString() { |
| StringBuilder buf = new StringBuilder(); |
| buf.append("{"); |
| buf.append(getId()); |
| buf.append(", ").append(this.getAnchor()); |
| buf.append(", ").append(this.getTitle()); |
| buf.append(", ").append(this.getPubTime()); |
| buf.append("}"); |
| return buf.toString(); |
| } |
| |
| public boolean equals(Object other) { |
| if (other == this) { |
| return true; |
| } |
| if (!(other instanceof WeblogEntry)) { |
| return false; |
| } |
| WeblogEntry o = (WeblogEntry)other; |
| return new EqualsBuilder() |
| .append(getAnchor(), o.getAnchor()) |
| .append(getWebsite(), o.getWebsite()) |
| .isEquals(); |
| } |
| |
| public int hashCode() { |
| return new HashCodeBuilder() |
| .append(getAnchor()) |
| .append(getWebsite()) |
| .toHashCode(); |
| } |
| |
| //------------------------------------------------------ Simple properties |
| |
| public String getId() { |
| return this.id; |
| } |
| |
| public void setId(String id) { |
| // Form bean workaround: empty string is never a valid id |
| if (id != null && id.trim().length() == 0) { |
| return; |
| } |
| this.id = id; |
| } |
| |
| public WeblogCategory getCategory() { |
| return this.category; |
| } |
| |
| public void setCategory(WeblogCategory category) { |
| this.category = category; |
| } |
| |
| /** |
| * Return collection of WeblogCategory objects of this entry. |
| * Added for symmetry with PlanetEntryData object. |
| */ |
| public List<WeblogCategory> getCategories() { |
| List<WeblogCategory> cats = new ArrayList<WeblogCategory>(); |
| cats.add(getCategory()); |
| return cats; |
| } |
| |
| public Weblog getWebsite() { |
| return this.website; |
| } |
| |
| public void setWebsite(Weblog website) { |
| this.website = website; |
| } |
| |
| public User getCreator() { |
| try { |
| return WebloggerFactory.getWeblogger().getUserManager().getUserByUserName(getCreatorUserName()); |
| } catch (Exception e) { |
| mLogger.error("ERROR fetching user object for username: " + getCreatorUserName(), e); |
| } |
| return null; |
| } |
| |
| public String getCreatorUserName() { |
| return creatorUserName; |
| } |
| |
| public void setCreatorUserName(String creatorUserName) { |
| this.creatorUserName = creatorUserName; |
| } |
| |
| public String getTitle() { |
| return this.title; |
| } |
| |
| public void setTitle(String title) { |
| this.title = title; |
| } |
| |
| /** |
| * Get summary for weblog entry (maps to RSS description and Atom summary). |
| */ |
| public String getSummary() { |
| return summary; |
| } |
| |
| /** |
| * Set summary for weblog entry (maps to RSS description and Atom summary). |
| */ |
| public void setSummary(String summary) { |
| this.summary = summary; |
| } |
| |
| /** |
| * Get search description for weblog entry. |
| */ |
| public String getSearchDescription() { |
| return searchDescription; |
| } |
| |
| /** |
| * Set search description for weblog entry |
| */ |
| public void setSearchDescription(String searchDescription) { |
| this.searchDescription = searchDescription; |
| } |
| |
| /** |
| * Get content text for weblog entry (maps to RSS content:encoded and Atom content). |
| */ |
| public String getText() { |
| return this.text; |
| } |
| |
| /** |
| * Set content text for weblog entry (maps to RSS content:encoded and Atom content). |
| */ |
| public void setText(String text) { |
| this.text = text; |
| } |
| |
| /** |
| * Get content type (text, html, xhtml or a MIME content type) |
| */ |
| public String getContentType() { |
| return contentType; |
| } |
| |
| /** |
| * Set content type (text, html, xhtml or a MIME content type) |
| */ |
| public void setContentType(String contentType) { |
| this.contentType = contentType; |
| } |
| |
| /** |
| * Get URL for out-of-line content. |
| */ |
| public String getContentSrc() { |
| return contentSrc; |
| } |
| |
| /** |
| * Set URL for out-of-line content. |
| */ |
| public void setContentSrc(String contentSrc) { |
| this.contentSrc = contentSrc; |
| } |
| |
| public String getAnchor() { |
| return this.anchor; |
| } |
| |
| public void setAnchor(String anchor) { |
| this.anchor = anchor; |
| } |
| |
| //------------------------------------------------------------------------- |
| |
| public Set<WeblogEntryAttribute> getEntryAttributes() { |
| return attSet; |
| } |
| |
| public void setEntryAttributes(Set atts) { |
| this.attSet = atts; |
| } |
| |
| public String findEntryAttribute(String name) { |
| if (getEntryAttributes() != null) { |
| for (WeblogEntryAttribute att : getEntryAttributes()) { |
| if (name.equals(att.getName())) { |
| return att.getValue(); |
| } |
| } |
| } |
| return null; |
| } |
| |
| public void putEntryAttribute(String name, String value) throws Exception { |
| WeblogEntryAttribute att = null; |
| for (WeblogEntryAttribute o : getEntryAttributes()) { |
| if (name.equals(o.getName())) { |
| att = o; |
| break; |
| } |
| } |
| if (att == null) { |
| att = new WeblogEntryAttribute(); |
| att.setEntry(this); |
| att.setName(name); |
| att.setValue(value); |
| getEntryAttributes().add(att); |
| } else { |
| att.setValue(value); |
| } |
| } |
| |
| //------------------------------------------------------------------------- |
| |
| /** |
| * <p>Publish time is the time that an entry is to be (or was) made available |
| * for viewing by newsfeed readers and visitors to the Roller site.</p> |
| * |
| * <p>Roller stores time using the timeZone of the server itself. When |
| * times are displayed in a user's weblog they must be translated |
| * to the user's timeZone.</p> |
| * |
| * <p>NOTE: Times are stored using the SQL TIMESTAMP datatype, which on |
| * MySQL has only a one-second resolution.</p> |
| */ |
| public Timestamp getPubTime() { |
| return this.pubTime; |
| } |
| |
| public void setPubTime(Timestamp pubTime) { |
| this.pubTime = pubTime; |
| } |
| |
| /** |
| * <p>Update time is the last time that an weblog entry was saved in the |
| * Roller weblog editor or via web services API (XML-RPC or Atom).</p> |
| * |
| * <p>Roller stores time using the timeZone of the server itself. When |
| * times are displayed in a user's weblog they must be translated |
| * to the user's timeZone.</p> |
| * |
| * <p>NOTE: Times are stored using the SQL TIMESTAMP datatype, which on |
| * MySQL has only a one-second resolution.</p> |
| */ |
| public Timestamp getUpdateTime() { |
| return this.updateTime; |
| } |
| |
| public void setUpdateTime(Timestamp updateTime) { |
| this.updateTime = updateTime; |
| } |
| |
| public PubStatus getStatus() { |
| return this.status; |
| } |
| |
| public void setStatus(PubStatus status) { |
| this.status = status; |
| } |
| |
| /** |
| * Some weblog entries are about one specific link. |
| * @return Returns the link. |
| */ |
| public String getLink() { |
| return link; |
| } |
| |
| /** |
| * @param link The link to set. |
| */ |
| public void setLink(String link) { |
| this.link = link; |
| } |
| |
| /** |
| * Comma-delimited list of this entry's Plugins. |
| */ |
| public String getPlugins() { |
| return plugins; |
| } |
| |
| public void setPlugins(String string) { |
| plugins = string; |
| } |
| |
| /** |
| * True if comments are allowed on this weblog entry. |
| */ |
| public Boolean getAllowComments() { |
| return allowComments; |
| } |
| /** |
| * True if comments are allowed on this weblog entry. |
| */ |
| public void setAllowComments(Boolean allowComments) { |
| this.allowComments = allowComments; |
| } |
| |
| /** |
| * Number of days after pubTime that comments should be allowed, or 0 for no limit. |
| */ |
| public Integer getCommentDays() { |
| return commentDays; |
| } |
| /** |
| * Number of days after pubTime that comments should be allowed, or 0 for no limit. |
| */ |
| public void setCommentDays(Integer commentDays) { |
| this.commentDays = commentDays; |
| } |
| |
| /** |
| * True if this entry should be rendered right to left. |
| */ |
| public Boolean getRightToLeft() { |
| return rightToLeft; |
| } |
| /** |
| * True if this entry should be rendered right to left. |
| */ |
| public void setRightToLeft(Boolean rightToLeft) { |
| this.rightToLeft = rightToLeft; |
| } |
| |
| /** |
| * True if story should be pinned to the top of the Roller site main blog. |
| * @return Returns the pinned. |
| */ |
| public Boolean getPinnedToMain() { |
| return pinnedToMain; |
| } |
| /** |
| * True if story should be pinned to the top of the Roller site main blog. |
| * @param pinnedToMain The pinned to set. |
| */ |
| public void setPinnedToMain(Boolean pinnedToMain) { |
| this.pinnedToMain = pinnedToMain; |
| } |
| |
| /** |
| * The locale string that defines the i18n approach for this entry. |
| */ |
| public String getLocale() { |
| return locale; |
| } |
| |
| public void setLocale(String locale) { |
| this.locale = locale; |
| } |
| |
| public Set<WeblogEntryTag> getTags() { |
| return tagSet; |
| } |
| |
| @SuppressWarnings("unused") |
| private void setTags(Set<WeblogEntryTag> tagSet) throws WebloggerException { |
| this.tagSet = tagSet; |
| this.removedTags = new HashSet<WeblogEntryTag>(); |
| this.addedTags = new HashSet<WeblogEntryTag>(); |
| } |
| |
| /** |
| * Roller lowercases all tags based on locale because there's not a 1:1 mapping |
| * between uppercase/lowercase characters across all languages. |
| * @param name |
| * @throws WebloggerException |
| */ |
| public void addTag(String name) throws WebloggerException { |
| Locale localeObject = getWebsite() != null ? getWebsite().getLocaleInstance() : Locale.getDefault(); |
| name = Utilities.normalizeTag(name, localeObject); |
| if (name.length() == 0) { |
| return; |
| } |
| |
| for (WeblogEntryTag tag : getTags()) { |
| if (tag.getName().equals(name)) { |
| return; |
| } |
| } |
| |
| WeblogEntryTag tag = new WeblogEntryTag(); |
| tag.setName(name); |
| tag.setCreatorUserName(getCreatorUserName()); |
| tag.setWeblog(getWebsite()); |
| tag.setWeblogEntry(this); |
| tag.setTime(getUpdateTime()); |
| tagSet.add(tag); |
| |
| addedTags.add(tag); |
| } |
| |
| public Set<WeblogEntryTag> getAddedTags() { |
| return addedTags; |
| } |
| |
| public Set<WeblogEntryTag> getRemovedTags() { |
| return removedTags; |
| } |
| |
| public String getTagsAsString() { |
| StringBuilder sb = new StringBuilder(); |
| // Sort by name |
| Set<WeblogEntryTag> tmp = new TreeSet<WeblogEntryTag>(new WeblogEntryTagComparator()); |
| tmp.addAll(getTags()); |
| for (WeblogEntryTag entryTag : tmp) { |
| sb.append(entryTag.getName()).append(" "); |
| } |
| if (sb.length() > 0) { |
| sb.deleteCharAt(sb.length() - 1); |
| } |
| |
| return sb.toString(); |
| } |
| |
| public void setTagsAsString(String tags) throws WebloggerException { |
| if (StringUtils.isEmpty(tags)) { |
| removedTags.addAll(tagSet); |
| tagSet.clear(); |
| return; |
| } |
| |
| List<String> updatedTags = Utilities.splitStringAsTags(tags); |
| Set<String> newTags = new HashSet<String>(updatedTags.size()); |
| Locale localeObject = getWebsite() != null ? getWebsite().getLocaleInstance() : Locale.getDefault(); |
| |
| for (String name : updatedTags) { |
| newTags.add(Utilities.normalizeTag(name, localeObject)); |
| } |
| |
| // remove old ones no longer passed. |
| for (Iterator it = tagSet.iterator(); it.hasNext();) { |
| WeblogEntryTag tag = (WeblogEntryTag) it.next(); |
| if (!newTags.contains(tag.getName())) { |
| // tag no longer listed in UI, needs removal from DB |
| removedTags.add(tag); |
| it.remove(); |
| } else { |
| // already in persisted set, therefore isn't new |
| newTags.remove(tag.getName()); |
| } |
| } |
| |
| for (String newTag : newTags) { |
| addTag(newTag); |
| } |
| } |
| |
| // ------------------------------------------------------------------------ |
| |
| /** |
| * True if comments are still allowed on this entry considering the |
| * allowComments and commentDays fields as well as the website and |
| * site-wide configs. |
| */ |
| public boolean getCommentsStillAllowed() { |
| if (!WebloggerRuntimeConfig.getBooleanProperty("users.comments.enabled")) { |
| return false; |
| } |
| if (getWebsite().getAllowComments() != null && !getWebsite().getAllowComments()) { |
| return false; |
| } |
| if (getAllowComments() != null && !getAllowComments()) { |
| return false; |
| } |
| boolean ret = false; |
| if (getCommentDays() == null || getCommentDays() == 0) { |
| ret = true; |
| } else { |
| // we want to use pubtime for calculating when comments expire, but |
| // if pubtime isn't set (like for drafts) then just use updatetime |
| Date inPubTime = getPubTime(); |
| if (inPubTime == null) { |
| inPubTime = getUpdateTime(); |
| } |
| |
| Calendar expireCal = Calendar.getInstance( |
| getWebsite().getLocaleInstance()); |
| expireCal.setTime(inPubTime); |
| expireCal.add(Calendar.DATE, getCommentDays()); |
| Date expireDay = expireCal.getTime(); |
| Date today = new Date(); |
| if (today.before(expireDay)) { |
| ret = true; |
| } |
| } |
| return ret; |
| } |
| public void setCommentsStillAllowed(boolean ignored) { |
| // no-op |
| } |
| |
| |
| //------------------------------------------------------------------------ |
| |
| /** |
| * Format the publish time of this weblog entry using the specified pattern. |
| * See java.text.SimpleDateFormat for more information on this format. |
| * |
| * @see java.text.SimpleDateFormat |
| * @return Publish time formatted according to pattern. |
| */ |
| public String formatPubTime(String pattern) { |
| try { |
| SimpleDateFormat format = new SimpleDateFormat(pattern, |
| this.getWebsite().getLocaleInstance()); |
| |
| return format.format(getPubTime()); |
| } catch (RuntimeException e) { |
| mLogger.error("Unexpected exception", e); |
| } |
| |
| return "ERROR: formatting date"; |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| /** |
| * Format the update time of this weblog entry using the specified pattern. |
| * See java.text.SimpleDateFormat for more information on this format. |
| * |
| * @see java.text.SimpleDateFormat |
| * @return Update time formatted according to pattern. |
| */ |
| public String formatUpdateTime(String pattern) { |
| try { |
| SimpleDateFormat format = new SimpleDateFormat(pattern); |
| |
| return format.format(getUpdateTime()); |
| } catch (RuntimeException e) { |
| mLogger.error("Unexpected exception", e); |
| } |
| |
| return "ERROR: formatting date"; |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| public List<WeblogEntryComment> getComments() { |
| return getComments(true, true); |
| } |
| |
| /** |
| * TODO: why is this method exposed to users with ability to get spam/non-approved comments? |
| */ |
| public List<WeblogEntryComment> getComments(boolean ignoreSpam, boolean approvedOnly) { |
| List<WeblogEntryComment> list = new ArrayList<WeblogEntryComment>(); |
| try { |
| WeblogEntryManager wmgr = WebloggerFactory.getWeblogger().getWeblogEntryManager(); |
| |
| CommentSearchCriteria csc = new CommentSearchCriteria(); |
| csc.setWeblog(getWebsite()); |
| csc.setEntry(this); |
| csc.setStatus(approvedOnly ? WeblogEntryComment.ApprovalStatus.APPROVED : null); |
| return wmgr.getComments(csc); |
| } catch (WebloggerException alreadyLogged) {} |
| return list; |
| } |
| |
| public int getCommentCount() { |
| List comments = getComments(true, true); |
| return comments.size(); |
| } |
| |
| //------------------------------------------------------------------------ |
| |
| /** |
| * Returns absolute entry permalink. |
| */ |
| public String getPermalink() { |
| return WebloggerFactory.getWeblogger().getUrlStrategy().getWeblogEntryURL(getWebsite(), null, getAnchor(), true); |
| } |
| |
| /** |
| * Returns entry permalink, relative to Roller context. |
| * @deprecated Use getPermalink() instead. |
| */ |
| public String getPermaLink() { |
| String lAnchor = this.getAnchor(); |
| try { |
| lAnchor = URLEncoder.encode(getAnchor(), "UTF-8"); |
| } catch (UnsupportedEncodingException e) { |
| // go with the "no encoding" version |
| } |
| return "/" + getWebsite().getHandle() + "/entry/" + lAnchor; |
| } |
| |
| /** |
| * Get relative URL to comments page. |
| * @deprecated Use commentLink() instead |
| */ |
| public String getCommentsLink() { |
| return getPermaLink() + "#comments"; |
| } |
| |
| /** |
| * Return the Title of this post, or the first 255 characters of the |
| * entry's text. |
| * |
| * @return String |
| */ |
| public String getDisplayTitle() { |
| if ( getTitle()==null || getTitle().trim().equals("") ) { |
| return StringUtils.left(Utilities.removeHTML(getText()), RollerConstants.TEXTWIDTH_255); |
| } |
| return Utilities.removeHTML(getTitle()); |
| } |
| |
| /** |
| * Return RSS 09x style description (escaped HTML version of entry text) |
| */ |
| public String getRss09xDescription() { |
| return getRss09xDescription(-1); |
| } |
| |
| /** |
| * Return RSS 09x style description (escaped HTML version of entry text) |
| */ |
| public String getRss09xDescription(int maxLength) { |
| String ret = StringEscapeUtils.escapeHtml3(getText()); |
| if (maxLength != -1 && ret.length() > maxLength) { |
| ret = ret.substring(0,maxLength-3)+"..."; |
| } |
| return ret; |
| } |
| |
| /** Create anchor for weblog entry, based on title or text */ |
| protected String createAnchor() throws WebloggerException { |
| return WebloggerFactory.getWeblogger().getWeblogEntryManager().createAnchor(this); |
| } |
| |
| /** Create anchor for weblog entry, based on title or text */ |
| public String createAnchorBase() { |
| |
| // Use title (minus non-alphanumeric characters) |
| String base = null; |
| if (!StringUtils.isEmpty(getTitle())) { |
| base = Utilities.replaceNonAlphanumeric(getTitle(), ' ').trim(); |
| } |
| // If we still have no base, then try text (minus non-alphanumerics) |
| if (StringUtils.isEmpty(base) && !StringUtils.isEmpty(getText())) { |
| base = Utilities.replaceNonAlphanumeric(getText(), ' ').trim(); |
| } |
| |
| if (!StringUtils.isEmpty(base)) { |
| |
| // Use only the first 4 words |
| StringTokenizer toker = new StringTokenizer(base); |
| String tmp = null; |
| int count = 0; |
| while (toker.hasMoreTokens() && count < 5) { |
| String s = toker.nextToken(); |
| s = s.toLowerCase(); |
| tmp = (tmp == null) ? s : tmp + TITLE_SEPARATOR + s; |
| count++; |
| } |
| base = tmp; |
| } |
| // No title or text, so instead we will use the items date |
| // in YYYYMMDD format as the base anchor |
| else { |
| base = DateUtil.format8chars(getPubTime()); |
| } |
| |
| return base; |
| } |
| |
| /** |
| * A no-op. TODO: fix formbean generation so this is not needed. |
| */ |
| public void setPermalink(String string) {} |
| |
| /** |
| * A no-op. TODO: fix formbean generation so this is not needed. |
| */ |
| public void setPermaLink(String string) {} |
| |
| /** |
| * A no-op. |
| * TODO: fix formbean generation so this is not needed. |
| * @param string |
| */ |
| public void setDisplayTitle(String string) { |
| } |
| |
| /** |
| * A no-op. |
| * TODO: fix formbean generation so this is not needed. |
| * @param string |
| */ |
| public void setRss09xDescription(String string) { |
| } |
| |
| |
| /** |
| * Convenience method to transform mPlugins to a List |
| * @return |
| */ |
| public List<String> getPluginsList() { |
| if (getPlugins() != null) { |
| return Arrays.asList( StringUtils.split(getPlugins(), ",") ); |
| } |
| return new ArrayList<String>(); |
| } |
| |
| /** Convenience method for checking status */ |
| public boolean isDraft() { |
| return getStatus().equals(PubStatus.DRAFT); |
| } |
| |
| /** Convenience method for checking status */ |
| public boolean isPending() { |
| return getStatus().equals(PubStatus.PENDING); |
| } |
| |
| /** Convenience method for checking status */ |
| public boolean isPublished() { |
| return getStatus().equals(PubStatus.PUBLISHED); |
| } |
| |
| /** |
| * Get entry text, transformed by plugins enabled for entry. |
| */ |
| public String getTransformedText() { |
| return render(getText()); |
| } |
| |
| /** |
| * Get entry summary, transformed by plugins enabled for entry. |
| */ |
| public String getTransformedSummary() { |
| return render(getSummary()); |
| } |
| |
| /** |
| * Determine if the specified user has permissions to edit this entry. |
| */ |
| public boolean hasWritePermissions(User user) throws WebloggerException { |
| |
| // global admins can hack whatever they want |
| GlobalPermission adminPerm = |
| new GlobalPermission(Collections.singletonList(GlobalPermission.ADMIN)); |
| boolean hasAdmin = WebloggerFactory.getWeblogger().getUserManager() |
| .checkPermission(adminPerm, user); |
| if (hasAdmin) { |
| return true; |
| } |
| |
| WeblogPermission perm = null; |
| try { |
| // if user is an author then post status defaults to PUBLISHED, otherwise PENDING |
| UserManager umgr = WebloggerFactory.getWeblogger().getUserManager(); |
| perm = umgr.getWeblogPermission(getWebsite(), user); |
| |
| } catch (WebloggerException ex) { |
| // security interceptor should ensure this never happens |
| mLogger.error("ERROR retrieving user's permission", ex); |
| return false; |
| } |
| |
| boolean author = perm.hasAction(WeblogPermission.POST) || perm.hasAction(WeblogPermission.ADMIN); |
| boolean limited = !author && perm.hasAction(WeblogPermission.EDIT_DRAFT); |
| |
| return author || (limited && (status == PubStatus.DRAFT || status == PubStatus.PENDING)); |
| } |
| |
| /** |
| * Transform string based on plugins enabled for this weblog entry. |
| */ |
| private String render(String str) { |
| String ret = str; |
| mLogger.debug("Applying page plugins to string"); |
| Map<String, WeblogEntryPlugin> inPlugins = getWebsite().getInitializedPlugins(); |
| if (str != null && inPlugins != null) { |
| List entryPlugins = getPluginsList(); |
| |
| // if no Entry plugins, don't bother looping. |
| if (entryPlugins != null && !entryPlugins.isEmpty()) { |
| |
| // now loop over mPagePlugins, matching |
| // against Entry plugins (by name): |
| // where a match is found render Plugin. |
| for (Map.Entry<String, WeblogEntryPlugin> entry : inPlugins.entrySet()) { |
| if (entryPlugins.contains(entry.getKey())) { |
| WeblogEntryPlugin pagePlugin = entry.getValue(); |
| try { |
| ret = pagePlugin.render(this, ret); |
| } catch (Exception e) { |
| mLogger.error("ERROR from plugin: " + pagePlugin.getName(), e); |
| } |
| } |
| } |
| } |
| } |
| return HTMLSanitizer.conditionallySanitize(ret); |
| } |
| |
| |
| /** |
| * Get the right transformed display content depending on the situation. |
| * |
| * If the readMoreLink is specified then we assume the caller wants to |
| * prefer summary over content and we include a "Read More" link at the |
| * end of the summary if it exists. Otherwise, if the readMoreLink is |
| * empty or null then we assume the caller prefers content over summary. |
| */ |
| public String displayContent(String readMoreLink) { |
| |
| String displayContent = null; |
| |
| if(readMoreLink == null || readMoreLink.trim().length() < 1 || |
| "nil".equals(readMoreLink)) { |
| |
| // no readMore link means permalink, so prefer text over summary |
| if(StringUtils.isNotEmpty(this.getText())) { |
| displayContent = this.getTransformedText(); |
| } else { |
| displayContent = this.getTransformedSummary(); |
| } |
| } else { |
| // not a permalink, so prefer summary over text |
| // include a "read more" link if needed |
| if(StringUtils.isNotEmpty(this.getSummary())) { |
| displayContent = this.getTransformedSummary(); |
| if(StringUtils.isNotEmpty(this.getText())) { |
| // add read more |
| List<String> args = new ArrayList<String>(); |
| args.add(readMoreLink); |
| |
| // TODO: we need a more appropriate way to get the view locale here |
| String readMore = I18nMessages.getMessages(getWebsite().getLocaleInstance()).getString("macro.weblog.readMoreLink", args); |
| |
| displayContent += readMore; |
| } |
| } else { |
| displayContent = this.getTransformedText(); |
| } |
| } |
| |
| return HTMLSanitizer.conditionallySanitize(displayContent); |
| } |
| |
| |
| /** |
| * Get the right transformed display content. |
| */ |
| public String getDisplayContent() { |
| return displayContent(null); |
| } |
| |
| public Boolean getRefreshAggregates() { |
| return refreshAggregates; |
| } |
| |
| public void setRefreshAggregates(Boolean refreshAggregates) { |
| this.refreshAggregates = refreshAggregates; |
| } |
| |
| } |