use of org.craftercms.studio.api.v1.to.ContentItemTO in project studio by craftercms.
the class PublishingManagerImpl method processItem.
@Override
public DeploymentItemTO processItem(PublishRequest item) throws DeploymentException, SiteNotFoundException {
if (item == null) {
throw new DeploymentException("Cannot process item, item is null.");
}
DeploymentItemTO deploymentItem = new DeploymentItemTO();
deploymentItem.setSite(item.getSite());
deploymentItem.setPath(item.getPath());
deploymentItem.setCommitId(item.getCommitId());
deploymentItem.setPackageId(item.getPackageId());
String site = item.getSite();
String path = item.getPath();
String oldPath = item.getOldPath();
String environment = item.getEnvironment();
String action = item.getAction();
String user = item.getUser();
String liveEnvironment = LIVE_ENVIRONMENT;
if (servicesConfig.isStagingEnvironmentEnabled(site)) {
liveEnvironment = servicesConfig.getLiveEnvironment(site);
}
boolean isLive = false;
if (StringUtils.isNotEmpty(liveEnvironment)) {
if (liveEnvironment.equals(environment)) {
isLive = true;
}
} else if (StringUtils.equalsIgnoreCase(LIVE_ENVIRONMENT, item.getEnvironment()) || StringUtils.equalsIgnoreCase(PRODUCTION_ENVIRONMENT, environment)) {
isLive = true;
}
if (StringUtils.equals(action, PublishRequest.Action.DELETE)) {
if (oldPath != null && oldPath.length() > 0) {
contentService.deleteContent(site, oldPath, user);
boolean hasRenamedChildren = false;
if (oldPath.endsWith(FILE_SEPARATOR + DmConstants.INDEX_FILE)) {
if (contentService.contentExists(site, oldPath.replace(FILE_SEPARATOR + DmConstants.INDEX_FILE, ""))) {
// TODO: SJ: This bypasses the Content Service, fix
RepositoryItem[] children = contentRepository.getContentChildren(site, oldPath.replace(FILE_SEPARATOR + DmConstants.INDEX_FILE, ""));
if (children.length > 1) {
hasRenamedChildren = true;
}
}
if (!hasRenamedChildren) {
deleteFolder(site, oldPath.replace(FILE_SEPARATOR + DmConstants.INDEX_FILE, ""), user);
}
}
deploymentItem.setMove(true);
deploymentItem.setOldPath(oldPath);
objectMetadataManager.clearRenamed(site, path);
}
boolean haschildren = false;
if (item.getPath().endsWith(FILE_SEPARATOR + DmConstants.INDEX_FILE)) {
if (contentService.contentExists(site, path.replace(FILE_SEPARATOR + DmConstants.INDEX_FILE, ""))) {
// TODO: SJ: This bypasses the Content Service, fix
RepositoryItem[] children = contentRepository.getContentChildren(site, path.replace(FILE_SEPARATOR + DmConstants.INDEX_FILE, ""));
if (children.length > 1) {
haschildren = true;
}
}
}
if (contentService.contentExists(site, path)) {
contentService.deleteContent(site, path, user);
if (!haschildren) {
deleteFolder(site, path.replace(FILE_SEPARATOR + DmConstants.INDEX_FILE, ""), user);
}
}
deploymentItem.setDelete(true);
} else {
if (StringUtils.equals(action, PublishRequest.Action.MOVE)) {
deploymentItem.setMove(true);
deploymentItem.setOldPath(oldPath);
if (oldPath != null && oldPath.length() > 0) {
if (isLive) {
objectMetadataManager.clearRenamed(site, path);
}
}
}
ItemMetadata itemMetadata = objectMetadataManager.getProperties(site, path);
if (itemMetadata == null) {
if (contentService.contentExists(site, path)) {
LOGGER.warn("Content item: '" + site + "':'" + path + "' doesn't exists in " + "the database, but does exist in git. This may cause problems " + "in the environment: '" + environment + "'");
} else {
LOGGER.warn("Content item: '" + site + "':'" + path + "' cannot be published. " + "Content does not exist in git nor in the database. Skipping...");
return null;
}
} else {
ContentItemTO contentItem = contentService.getContentItem(site, path);
if (isLive) {
// should consider what should be done if this does not work.
// Currently the method will bail and the item is stuck in processing.
LOGGER.debug("Environment is live, transition item to LIVE state {0}:{1}", site, path);
// check if commit id from workflow and from object state match
if (Objects.isNull(itemMetadata.getCommitId()) || itemMetadata.getCommitId().equals(item.getCommitId())) {
objectStateService.transition(site, contentItem, TransitionEvent.DEPLOYMENT);
}
} else {
objectStateService.transition(site, contentItem, TransitionEvent.SAVE);
}
itemMetadata.setSubmittedBy(StringUtils.EMPTY);
itemMetadata.setSendEmail(0);
itemMetadata.setSubmittedForDeletion(0);
itemMetadata.setSubmissionComment(StringUtils.EMPTY);
itemMetadata.setSubmittedToEnvironment(StringUtils.EMPTY);
itemMetadata.setLaunchDate(null);
objectMetadataManager.updateObjectMetadata(itemMetadata);
}
String blacklistConfig = studioConfiguration.getProperty(CONFIGURATION_PUBLISHING_BLACKLIST_REGEX);
if (StringUtils.isNotEmpty(blacklistConfig) && ContentUtils.matchesPatterns(item.getPath(), Arrays.asList(StringUtils.split(blacklistConfig, ",")))) {
LOGGER.debug("File " + item.getPath() + " of the site " + site + " will not be published because it " + "matches the configured publishing blacklist regex patterns.");
markItemsCompleted(site, item.getEnvironment(), Arrays.asList(item));
deploymentItem = null;
}
}
return deploymentItem;
}
use of org.craftercms.studio.api.v1.to.ContentItemTO in project studio by craftercms.
the class ContentServiceImpl method getContentItemTree.
@Override
@ValidateParams
public ContentItemTO getContentItemTree(@ValidateStringParam(name = "site") String site, @ValidateSecurePathParam(name = "path") String path, @ValidateIntegerParam(name = "depth") int depth) {
logger.debug("Getting content item tree for '{}':'{}' depth '{}'", site, path, depth);
DebugUtils.addDebugStack(logger);
long startTime = System.currentTimeMillis();
boolean isPages = (path.contains(FILE_SEPARATOR + "site" + FILE_SEPARATOR + "website"));
ContentItemTO root = null;
if (isPages && contentExists(site, path + FILE_SEPARATOR + DmConstants.INDEX_FILE)) {
if (depth > 1) {
root = getContentItem(site, path + FILE_SEPARATOR + DmConstants.INDEX_FILE, depth);
} else {
root = getContentItem(site, path + FILE_SEPARATOR + DmConstants.INDEX_FILE);
}
} else {
if (depth > 1) {
root = getContentItem(site, path, depth);
} else {
root = getContentItem(site, path);
}
}
long executionTime = System.currentTimeMillis() - startTime;
logger.debug("Content item tree ['{}':'{}' depth '{}'] retrieved in '{}' milli-seconds", site, path, depth, executionTime);
return root;
}
use of org.craftercms.studio.api.v1.to.ContentItemTO in project studio by craftercms.
the class ContentServiceImpl method updateChildrenOnMove.
protected void updateChildrenOnMove(String site, String fromPath, String movePath) throws SiteNotFoundException {
logger.debug("updateChildrenOnMove from {0} to {1}", fromPath, movePath);
// get the list of children
ContentItemTO movedTO = getContentItem(site, movePath, 2);
List<ContentItemTO> childrenTOs = movedTO.getChildren();
for (ContentItemTO childTO : childrenTOs) {
// calculate the child's from path by looking at it's parent's from path and the child new path
// (parent move operation has already happened)
String childToPath = childTO.getUri();
String oldParentFolderPath = fromPath.replace("/index.xml", "");
String parentFolderPath = movePath.replace("/index.xml", "");
String childFromPath = childToPath.replace(parentFolderPath, oldParentFolderPath);
logger.debug("updateChildrenOnMove handling child from: {0} to: {1} ", childFromPath, childToPath);
// update database, preview, cache etc
updateDatabaseOnMove(site, childFromPath, childToPath);
// handle this child's children
updateChildrenOnMove(site, childFromPath, childToPath);
}
}
use of org.craftercms.studio.api.v1.to.ContentItemTO in project studio by craftercms.
the class ContentServiceImpl method writeContent.
@Override
@ValidateParams
public void writeContent(@ValidateStringParam(name = "site") String site, @ValidateSecurePathParam(name = "path") String path, @ValidateStringParam(name = "fileName") String fileName, @ValidateStringParam(name = "contentType") String contentType, InputStream input, @ValidateStringParam(name = "createFolders") String createFolders, @ValidateStringParam(name = "edit") String edit, @ValidateStringParam(name = "unlock") String unlock, boolean skipAuditLogInsert) throws ServiceLayerException {
try {
entitlementValidator.validateEntitlement(EntitlementType.ITEM, 1);
} catch (EntitlementException e) {
throw new ServiceLayerException("Unable to complete request due to entitlement limits. Please contact your " + "system administrator.");
}
Map<String, String> params = new HashMap<String, String>();
params.put(DmConstants.KEY_SITE, site);
params.put(DmConstants.KEY_PATH, path);
params.put(DmConstants.KEY_FILE_NAME, fileName);
params.put(DmConstants.KEY_CONTENT_TYPE, contentType);
params.put(DmConstants.KEY_CREATE_FOLDERS, createFolders);
params.put(DmConstants.KEY_EDIT, edit);
params.put(DmConstants.KEY_UNLOCK, unlock);
params.put(DmConstants.KEY_SKIP_AUDIT_LOG_INSERT, String.valueOf(skipAuditLogInsert));
String id = site + ":" + path + ":" + fileName + ":" + contentType;
String relativePath = path;
boolean contentExists = contentExists(site, path);
String lockKey = id;
if (contentExists) {
lockKey = site + ":" + path;
}
try {
// Check if the user is saving and closing (releasing the lock) or just saving and will continue to edit
// If "unlock" is empty, it means it's a save and close operation
// if "unlock" is set to "false", it also means it's a save and continue operation
boolean isSaveAndClose = (StringUtils.isNotEmpty(unlock) && !unlock.equalsIgnoreCase("false"));
if (contentExists) {
ItemState itemState = objectStateService.getObjectState(site, path);
if (itemState == null) {
// This file is either new or someone created it outside of our system, we must create a state
// for it
ContentItemTO item = getContentItem(site, path, 0);
objectStateService.insertNewEntry(site, item);
itemState = objectStateService.getObjectState(site, path);
}
if (itemState != null) {
if (itemState.getSystemProcessing() != 0) {
// TODO: SJ: Review and refactor/redo
logger.error("Error Content {0} is being processed (Object State is system " + "processing);", path);
throw new ServiceLayerException("Content " + path + " is in system processing, we can't write " + "it");
}
objectStateService.setSystemProcessing(site, path, true);
} else {
logger.error("the object state is still null even after attempting to create it for site {0} " + "path {1} fileName {2} contentType {3}" + ".", site, path, fileName, contentType);
}
} else {
// Content does not exist; check for moved content and deleted content
if (objectStateService.deletedPathExists(site, path) || objectMetadataManager.movedPathExists(site, path)) {
throw new ServiceLayerException("Content " + path + " for site " + site + ", cannot be created " + "because this name/URL was in use by another content item that has been moved or" + " deleted by not yet published.");
}
}
// TODO: SJ: Item processing pipeline needs to be configurable without hardcoded paths
// TODO: SJ: We need to consider various mechanics for pipeline choice other than path
// TODO: SJ: Furthermore, we already have similar machinery in Crafter Core that might be a fit for some
// TODO: SJ: of this work
// default chain is asset type
String chainID = DmConstants.CONTENT_CHAIN_ASSET;
if (path.startsWith("/site")) {
// anything inside site is a form based XML
// example /site/website
// /site/components
// /site/books
chainID = DmConstants.CONTENT_CHAIN_FORM;
}
// TODO: SJ: Content is being written here via the pipeline, this is not the best design and will be
// TODO: SJ: refactored in 2.7.x
processContent(id, input, true, params, chainID);
// Item has been processed and persisted, set system processing state to off
objectStateService.setSystemProcessing(site, path, false);
// TODO: SJ: The path sent from the UI is inconsistent, hence the acrobatics below. Fix in 2.7.x
String savedFileName = params.get(DmConstants.KEY_FILE_NAME);
String savedPath = params.get(DmConstants.KEY_PATH);
relativePath = savedPath;
if (!savedPath.endsWith(savedFileName)) {
relativePath = savedPath + FILE_SEPARATOR + savedFileName;
}
// TODO: SJ: Why is the item being loaded again? Why is the state being set to system not processing
// TODO: SJ: again? Why would we insert the item into objectStateService again?
// TODO: SJ: Refactor for 2.7.x
ContentItemTO itemTo = getContentItem(site, relativePath, 0);
if (itemTo != null) {
if (isSaveAndClose) {
objectStateService.transition(site, itemTo, SAVE);
} else {
objectStateService.transition(site, itemTo, SAVE_FOR_PREVIEW);
}
objectStateService.setSystemProcessing(site, itemTo.getUri(), false);
} else {
// TODO: SJ: the line below doesn't make any sense, itemTo == null => insert? Investigate and fix in
// TODO: SJ: 2.7.x
objectStateService.insertNewEntry(site, itemTo);
}
// Sync preview
PreviewEventContext context = new PreviewEventContext();
context.setSite(site);
eventService.publish(EVENT_PREVIEW_SYNC, context);
} catch (RuntimeException e) {
logger.error("error writing content", e);
// TODO: SJ: Why setting two things? Are we guessing? Fix in 2.7.x
objectStateService.setSystemProcessing(site, relativePath, false);
objectStateService.setSystemProcessing(site, path, false);
throw e;
}
}
use of org.craftercms.studio.api.v1.to.ContentItemTO in project studio by craftercms.
the class ContentServiceImpl method getCopyDependencies.
private Map<String, String> getCopyDependencies(@ValidateStringParam(name = "site") String site, @ValidateSecurePathParam(name = "sourceContentPath") String sourceContentPath, @ValidateSecurePathParam(name = "dependencyPath") String dependencyPath) throws ServiceLayerException {
Map<String, String> copyDependency = new HashMap<String, String>();
if (sourceContentPath.endsWith(DmConstants.XML_PATTERN) && dependencyPath.endsWith(DmConstants.XML_PATTERN)) {
ContentItemTO dependencyItem = getContentItem(site, sourceContentPath);
if (dependencyItem != null) {
String contentType = dependencyItem.getContentType();
List<CopyDependencyConfigTO> copyDependencyPatterns = servicesConfig.getCopyDependencyPatterns(site, contentType);
if (copyDependencyPatterns != null && copyDependencyPatterns.size() > 0) {
logger.debug("Copy Pattern provided for contentType" + contentType);
Set<String> dependencies = dependencyService.getItemDependencies(site, dependencyPath, 1);
if (CollectionUtils.isNotEmpty(dependencies)) {
for (String dependency : dependencies) {
for (CopyDependencyConfigTO copyConfig : copyDependencyPatterns) {
if (contentExists(site, dependency) && StringUtils.isNotEmpty(copyConfig.getPattern()) && StringUtils.isNotEmpty(copyConfig.getTarget()) && dependency.matches(copyConfig.getPattern())) {
copyDependency.put(dependency, copyConfig.getTarget());
}
}
}
}
} else {
logger.debug("Copy Pattern is not provided for contentType" + contentType);
}
} else {
logger.debug("Not found dependency item at site {0} path {!}", site, sourceContentPath);
}
}
return copyDependency;
}
Aggregations