DocPublishService.java
package sk.iway.iwcm.doc;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import sk.iway.iwcm.Constants;
import sk.iway.iwcm.InitServlet;
import sk.iway.iwcm.Logger;
import sk.iway.iwcm.RequestBean;
import sk.iway.iwcm.SendMail;
import sk.iway.iwcm.Tools;
import sk.iway.iwcm.editor.DocNoteBean;
import sk.iway.iwcm.editor.DocNoteDB;
import sk.iway.iwcm.editor.rest.DocDetailsToDocHistoryMapper;
import sk.iway.iwcm.i18n.Prop;
import sk.iway.iwcm.users.UserDetails;
import sk.iway.iwcm.users.UsersDB;
/**
* Handles the datetime publication/depublication of webpages
*/
public class DocPublishService {
private long lastPublishCheck = 0;
//holds list of pages that are ready to be published{DocHistory} or disabled/unpublished{DocDetails}
private List<DocBasic> publicableDocs;
private DocHistoryRepository dhr = null;
private DocDetailsRepository ddr = null;
public DocPublishService() {
//empty constructor
}
/**
* check if there are any webpages in publicableDocs to publish/unpublish
*/
public void checkWebpagesToPublish(DocDB docDB) {
//check only once in 5 seconds
if (lastPublishCheck + 5000 > System.currentTimeMillis()) return;
lastPublishCheck = System.currentTimeMillis();
//Webjet MUST be initialized - otherwise DocDB/GroupsDB is not initialized correctly
if(InitServlet.isWebjetInitialized() == true) {
prepareRepositories();
//If publicableDocs is null, read pages to public -> could happen if Service was crated before Webjet was initialized
if(publicableDocs == null) refreshPagesToPublish();
long now = Tools.getNow();
ArrayList<DocHistory> copyDHtoD = new ArrayList<>(); // specify which pForm-s to copy from documents_history to documents
ArrayList<DocDetails> removeAfterEndList = new ArrayList<>();
if (publicableDocs != null && publicableDocs.size() > 0) {
//use good old for loop to avoid ConcurrentModificationException
for (DocBasic pdoc : publicableDocs) {
if (pdoc instanceof DocHistory) {
DocHistory doc = (DocHistory) pdoc;
//Is ready to by published
if(Tools.isTrue(doc.getPublicable()) && (doc.getPublishStart() > 0) && (now >= doc.getPublishStart())) {
copyDHtoD.add(doc);
continue;
}
}
if (pdoc instanceof DocDetails) {
DocDetails doc = (DocDetails) pdoc;
//Is ready to be disabled
if (doc.isPublicable()==false && doc.isDisableAfterEnd() && (doc.getPublishEnd()>0) && (now >= doc.getPublishEnd())) {
removeAfterEndList.add(doc);
continue;
}
}
}
//execute changes
for (DocHistory doc : copyDHtoD) {
copyDHistory(doc, docDB);
}
for (DocDetails doc : removeAfterEndList) {
disableAfterEnd(doc);
}
//publicableDocs is refreshed in DocDB.updateInternalCache call
}
}
}
/**
* copy data from table documents_history to table documents
* @param docHistory
* @param docDB
*/
private synchronized void copyDHistory(DocHistory docHistory, DocDB docDB) {
GroupsDB groupsDB = GroupsDB.getInstance();
DocDetails docDetails = DocDetailsToDocHistoryMapper.INSTANCE.docHistoryToDocDetails(docHistory);
Logger.debug(this,"Publishing from historyId: " + docDetails.getHistoryId() + " docId: " + docDetails.getDocId());
boolean publicable = dhr.getPublicableByDocIdIn(docDetails.getDocId()).contains(Boolean.TRUE) ? true : false;
Optional<List<Integer>> historyIdsOpt = dhr.getHisotryIdsByDocIdIn(docDetails.getDocId());
String historyIds = historyIdsOpt.isPresent() == true ? historyIdsOpt.get().stream().map(String::valueOf).collect(Collectors.joining(",")) : null;
if (historyIds == null || publicable == false) {
//asi sme cluster a uz to niekto aktualizoval
return;
}
dhr.updateActualAndSyncStatus(false, Tools.getTokensInt(sk.iway.iwcm.DB.getOnlyNumbersIn(historyIds), ","));
//updatni zaznam v history, zrus publicable a nastav actual
dhr.updatePublicableAndActual(false, true, docDetails.getAuthorId(), true, docDetails.getHistoryId());
Logger.println(this,"pForm.getPublishStart()=" + docDetails.getPublishStart());
///Now is available
docDetails.setAvailable(true);
docDetails.setPerexGroupString( docDetails.getPerexGroupIdsString(true) );
GroupDetails group = groupsDB.getGroup(docDetails.getGroupId());
if (group != null && group.isInternal() == false)
docDetails.setFileName( groupsDB.getGroupNamePath(docDetails.getGroupId()) );
else docDetails.setFileName(null);
//Set root groups
int[] rootGroups = DocDB.getRootGroupL(docDetails.getGroupId(), null, -1);
docDetails.setRootGroupL1(rootGroups[0]);
docDetails.setRootGroupL2(rootGroups[1]);
docDetails.setRootGroupL3(rootGroups[2]);
///Set publish after start to false
docDetails.setPublishAfterStart(false);
//Before save add audit param that signalize that webpage was published
RequestBean.addAuditValue("publishStatus", "Webpage was published");
//Perform update
ddr.save(docDetails);
// vypublikovanie slave clankov z historie (multikategorie)
DocDetails masterDocDetails = null;
for(Integer docId : MultigroupMappingDB.getSlaveDocIds(docDetails.getDocId()))
{
if (masterDocDetails == null) masterDocDetails = docDB.getDoc(docDetails.getDocId(), -1, false);
DocDetails slaveDoc = docDB.getBasicDocDetails(docId, false);
if (slaveDoc != null) {
//teraz zmenme hodnoty pre master doc a ulozme do DB
masterDocDetails.setVirtualPath(slaveDoc.getVirtualPath());
masterDocDetails.setExternalLink(slaveDoc.getExternalLink());
masterDocDetails.setDocId(docId);
masterDocDetails.setGroupId(slaveDoc.getGroupId());
DocDB.saveDoc(masterDocDetails);
}
}
//prekopirovanie poznamky pre redaktorov k stranke
DocNoteBean historyNote = DocNoteDB.getInstance().getDocNote(-1, docDetails.getHistoryId());
if(historyNote != null) {
DocNoteBean publishedNote = DocNoteDB.getInstance().getDocNote(docDetails.getDocId(), -1);
if(publishedNote == null)
publishedNote = new DocNoteBean();
publishedNote.setDocId(docDetails.getDocId());
publishedNote.setHistoryId(-1);
publishedNote.setNote(historyNote.getNote());
publishedNote.setUserId(historyNote.getUserId());
publishedNote.setCreated(historyNote.getCreated());
publishedNote.save();
}
if( Constants.getBoolean("webpagesNotifyAutorOnPublish") == true ) sendMailToPageAuthor(docHistory, docDB);
DocDB.getInstance().updateInternalCaches(docDetails.getDocId());
//refresh sablony sa vykona iba ak je stranka v System adresari
if(docDetails.getFullPath().startsWith("/System") || docDetails.getGroupId() == Constants.getInt("tempGroupId") || docDetails.getGroupId() == Constants.getInt("menuGroupId") || docDetails.getGroupId() == Constants.getInt("headerFooterGroupId"))
{
TemplatesDB.getInstance(true);
}
}
/**
* Disable page after unpublish/end time
* @param doc
*/
private synchronized void disableAfterEnd(DocDetails doc) {
ddr.updateAvailableAndDisabledAfterEnd(false, false, doc.getDocId());
DocDB.getInstance().updateInternalCaches(doc.getDocId());
}
/**
* Send email to page author about page publication
* @param docHistory
* @param docDB
*/
private void sendMailToPageAuthor(DocHistory docHistory, DocDB docDB) {
UserDetails user = UsersDB.getUser(docHistory.getAuthorId());
Prop prop = Prop.getInstance();
String subject = prop.getText("webpage.publishable.email.subject");
String publishableDateTime = Tools.formatDateTime(docHistory.getPublishStart());
String webpageLink = "<a href=\"" + docDB.getDocLink(docHistory.getDocId(), null, true, null) + "\">" + docHistory.getTitle() + "</a>";
String body = prop.getText("webpage.publishable.email.body", docHistory.getTitle(), ""+docHistory.getDocId(), publishableDateTime, webpageLink, ""+docHistory.getHistoryId());
SendMail.send(user.getFullName(), user.getEmail(), user.getEmail(), subject, body);
}
/**
* Read pages waiting for publishing or to be disabled
*/
public void refreshPagesToPublish() {
if(InitServlet.isWebjetInitialized() == true) {
DebugTimer dt = new DebugTimer("readPagesToPublic");
prepareRepositories();
if (dhr != null && ddr != null) {
//Clear list
List<DocBasic> publicableDocsLocal = new ArrayList<>();
//Get all pages that are publicable (publicable = true) and are not awaiting to approve (awaitingApprove = null or awaitingApprove = "")
List<DocHistory> publicableHistoryDocs = dhr.getPublicableThatAreNotAwaitingToApprove().orElse(new ArrayList<>());
publicableDocsLocal.addAll( publicableHistoryDocs );
//Add pages where disable_after_end = true
publicableDocsLocal.addAll( ddr.findAllByDisableAfterEndTrue() );
//filter pages in trash - boolean isInTrash = groupsDB.isInTrash(docDetails.getGroupId());
GroupsDB groupsDB = GroupsDB.getInstance();
publicableDocsLocal = publicableDocsLocal.stream().filter(doc -> groupsDB.isInTrash(doc.getGroupId())==false).collect(Collectors.toList());
publicableDocs = publicableDocsLocal;
dt.diff("done, size="+publicableDocs.size());
}
}
}
protected List<DocBasic> getPublicableDocs() {
return publicableDocs;
}
/**
* Setup Spring DATA repositories
*/
private void prepareRepositories() {
if(dhr == null) dhr = Tools.getSpringBean("docHistoryRepository", DocHistoryRepository.class);
if(ddr == null) ddr = Tools.getSpringBean("docDetailsRepository", DocDetailsRepository.class);
}
}