Skip to content

Commit

Permalink
#11713 fixes pp error updating content types (#11736)
Browse files Browse the repository at this point in the history
* #11713 fixes pp error updating content types

* #11713 improvements

* #11713 improvements

(cherry picked from commit b115de8)
  • Loading branch information
Oswaldo Gallango authored and jgambarios committed May 26, 2017
1 parent ff92ca2 commit 4eff30d
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import java.util.Set;

import com.dotcms.contenttype.model.field.Field;
import com.dotcms.contenttype.model.field.FieldVariable;
import com.dotcms.contenttype.model.type.BaseContentType;
import com.dotcms.contenttype.model.type.ContentType;
import com.dotcms.repackage.com.google.common.collect.ImmutableSet;
Expand Down Expand Up @@ -242,6 +243,30 @@ public interface ContentTypeAPI {
List<ContentType> search(String condition, BaseContentType base, String orderBy, int limit, int offset)
throws DotDataException;

/**
* Save or update a Content Type. If the Content Type already exist
* then it's going to update the fields with the values set on the fields
* parameter
*
* @param contentType Content Type that is going to be modified
* @param fields Content Type list of fields
* @return Content Type Object saved.
* @throws DotDataException Error occurred when performing the action.
* @throws DotSecurityException The user does not have permissions to perform this action.
*/
ContentType save(ContentType contentType, List<Field> fields) throws DotDataException, DotSecurityException;


/**
* Save or update a Content Type. If the Content Type already exist
* then it's going to update the fields and fields variables with the values set
* on the fields and fieldVariables parameters
*
* @param contentType Content Type that is going to be modified
* @param fields Content Type list of fields
* @param fieldVariables ContentType list of field variables
* @return Content Type Object saved.
* @throws DotDataException Error occurred when performing the action.
* @throws DotSecurityException The user does not have permissions to perform this action.
*/
ContentType save(ContentType contentType, List<Field> fields, List<FieldVariable> fieldVariables) throws DotDataException, DotSecurityException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import com.dotcms.contenttype.exception.NotFoundInDbException;
import com.dotcms.contenttype.model.field.Field;
import com.dotcms.contenttype.model.field.FieldBuilder;
import com.dotcms.contenttype.model.field.FieldVariable;
import com.dotcms.contenttype.model.type.BaseContentType;
import com.dotcms.contenttype.model.type.ContentType;
import com.dotcms.contenttype.model.type.ContentTypeBuilder;
Expand Down Expand Up @@ -55,24 +56,26 @@ public class ContentTypeAPIImpl implements ContentTypeAPI {
final PermissionAPI perms;
final User user;
final Boolean respectFrontendRoles;
final FieldAPI fAPI;



public ContentTypeAPIImpl(User user, boolean respectFrontendRoles, ContentTypeFactory fac, FieldFactory ffac,
PermissionAPI perms) {
PermissionAPI perms, FieldAPI fAPI) {
super();
this.fac = fac;
this.ffac = ffac;
this.perms = perms;
this.user = user;
this.respectFrontendRoles = respectFrontendRoles;
this.fAPI = fAPI;
}



public ContentTypeAPIImpl(User user, boolean respectFrontendRoles) {
this(user, respectFrontendRoles, FactoryLocator.getContentTypeFactory(), FactoryLocator.getFieldFactory(),
APILocator.getPermissionAPI());
APILocator.getPermissionAPI(), APILocator.getContentTypeFieldAPI());
}


Expand Down Expand Up @@ -201,55 +204,7 @@ public void validateFields(ContentType type) {

@Override
public ContentType save(ContentType type) throws DotDataException, DotSecurityException {


Permissionable parent = type.getParentPermissionable();


if (!perms.doesUserHavePermissions(parent,
"PARENT:" + PermissionAPI.PERMISSION_CAN_ADD_CHILDREN + ", STRUCTURES:" + PermissionAPI.PERMISSION_PUBLISH,
user)) {
throw new DotSecurityException(
"User-does-not-have-add-children-or-structure-permission-on-host-folder:" + parent);
}

// set to system folder if on system host or the host id of the folder it is on
List<Field> fields = type.fields();

//Checks if the folder has been set, if so checks the host where that folder lives and set it.
if(UtilMethods.isSet(type.folder()) && !type.folder().equals(Folder.SYSTEM_FOLDER)){
type = ContentTypeBuilder.builder(type)
.host(APILocator.getFolderAPI().find(type.folder(), user, false).getHostId()).build();
}else if(UtilMethods.isSet(type.host())){//If there is no folder set, check if the host has been set, if so set the folder to System Folder
type = ContentTypeBuilder.builder(type).folder(Folder.SYSTEM_FOLDER).build();
}

if (!fields.isEmpty())
type.constructWithFields(fields);

ContentType oldType = type;
try {
if (type.id() != null)
oldType = this.fac.find(type.id());
} catch (NotFoundInDbException notThere) {
// not logging, expected when inserting new from separate environment
}
type = this.fac.save(type);

if (oldType != null) {
if (fireUpdateIdentifiers(oldType.expireDateVar(), type.expireDateVar())) {
IdentifierDateJob.triggerJobImmediately(oldType, user);
} else if (fireUpdateIdentifiers(oldType.publishDateVar(), type.publishDateVar())) {
IdentifierDateJob.triggerJobImmediately(oldType, user);
}
perms.resetPermissionReferences(type);
}
ActivityLogger.logInfo(getClass(), "Save ContentType Action", "User " + user.getUserId() + "/" + user.getFullName()
+ " added ContentType " + type.name() + " to host id:" + type.host());
AdminLogger.log(getClass(), "ContentType", "ContentType saved : " + type.name(), user);

return type;

return save(type, null, null);
}

@Override
Expand Down Expand Up @@ -413,7 +368,112 @@ public List<ContentType> search(String condition, BaseContentType base, String o
public List<ContentType> findUrlMapped() throws DotDataException {
return fac.findUrlMapped();
}

@Override
public ContentType save(ContentType contentType, List<Field> fields) throws DotDataException, DotSecurityException {
return save(contentType, fields, null);
}

@Override
public ContentType save(ContentType contentType, List<Field> fields, List<FieldVariable> fieldVariables) throws DotDataException, DotSecurityException {

return LocalTransaction.wrapReturn(() -> {
Permissionable parent = contentType.getParentPermissionable();

ContentType newContentType = contentType;
if (!perms.doesUserHavePermissions(parent,
"PARENT:" + PermissionAPI.PERMISSION_CAN_ADD_CHILDREN + ", STRUCTURES:" + PermissionAPI.PERMISSION_PUBLISH,
user)) {
throw new DotSecurityException(
"User-does-not-have-add-children-or-structure-permission-on-host-folder:" + parent);
}

// set to system folder if on system host or the host id of the folder it is on
List<Field> localFields = newContentType.fields();

//Checks if the folder has been set, if so checks the host where that folder lives and set it.
if(UtilMethods.isSet(newContentType.folder()) && !newContentType.folder().equals(Folder.SYSTEM_FOLDER)){
newContentType = ContentTypeBuilder.builder(newContentType)
.host(APILocator.getFolderAPI().find(newContentType.folder(), user, false).getHostId()).build();
}else if(UtilMethods.isSet(newContentType.host())){//If there is no folder set, check if the host has been set, if so set the folder to System Folder
newContentType = ContentTypeBuilder.builder(newContentType).folder(Folder.SYSTEM_FOLDER).build();
}

if (!localFields.isEmpty())
newContentType.constructWithFields(localFields);

ContentType oldType = newContentType;
try {
if (newContentType.id() != null)
oldType = this.fac.find(newContentType.id());
} catch (NotFoundInDbException notThere) {
// not logging, expected when inserting new from separate environment
}
newContentType = this.fac.save(newContentType);

if (oldType != null) {
if (fireUpdateIdentifiers(oldType.expireDateVar(), newContentType.expireDateVar())) {
IdentifierDateJob.triggerJobImmediately(oldType, user);
} else if (fireUpdateIdentifiers(oldType.publishDateVar(), newContentType.publishDateVar())) {
IdentifierDateJob.triggerJobImmediately(oldType, user);
}
perms.resetPermissionReferences(newContentType);
}
ActivityLogger.logInfo(getClass(), "Save ContentType Action", "User " + user.getUserId() + "/" + user.getFullName()
+ " added ContentType " + newContentType.name() + " to host id:" + newContentType.host());
AdminLogger.log(getClass(), "ContentType", "ContentType saved : " + newContentType.name(), user);


//update the existing content type fields
if(fields != null){
//Fields on current content type version
localFields = newContentType.fields();
//Create a copy in order to avoid a possible concurrent modification error
List<String> localFieldsVarNames = new ArrayList<String>();

for (Field localField : localFields) {
localFieldsVarNames.add(localField.variable());
}


//for each field in the content type lets create it if doesn't exists and update its properties if it does
for( Field field : fields ) {
try {
Field localField = fAPI.byContentTypeIdAndVar(field.contentTypeId(), field.variable());
if ( localField == null || !UtilMethods.isSet( localField.inode() ) ) {
fAPI.save(field,APILocator.systemUser());
} else {
fAPI.delete(localField);
fAPI.save(field,APILocator.systemUser());
}
}catch(NotFoundInDbException e){
//add field, if doesn't exist
fAPI.save(field,APILocator.systemUser());
}

localFieldsVarNames.remove( field.variable() );
if(fieldVariables != null){
for(FieldVariable fieldVariable : fieldVariables) {
if(fieldVariable.fieldId().equals(field.inode())) {
fAPI.save(fieldVariable, APILocator.systemUser());
}
}
}
}

if ( localFieldsVarNames.size() > 0 ) {
// we have local fields that didn't came
// in the content type. lets remove them
for ( String localFieldVarName : localFieldsVarNames ) {
fAPI.delete(fAPI.byContentTypeIdAndVar(newContentType.inode(), localFieldVarName));
}
}
}


return newContentType;
});
}


}

0 comments on commit 4eff30d

Please sign in to comment.