org.fenixedu.cms.ui.AdminPostsService.java Source code

Java tutorial

Introduction

Here is the source code for org.fenixedu.cms.ui.AdminPostsService.java

Source

/**
 * Copyright  2014 Instituto Superior Tcnico
 *
 * This file is part of FenixEdu CMS.
 *
 * FenixEdu CMS is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * FenixEdu CMS is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with FenixEdu CMS.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.fenixedu.cms.ui;

import static java.util.Optional.ofNullable;
import static org.fenixedu.cms.domain.PermissionEvaluation.canDoThis;
import static org.fenixedu.cms.domain.PermissionEvaluation.ensureCanDoThis;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;

import org.fenixedu.bennu.core.domain.User;
import org.fenixedu.bennu.core.groups.Group;
import org.fenixedu.bennu.core.rest.UserResource;
import org.fenixedu.bennu.io.domain.GroupBasedFile;
import org.fenixedu.bennu.io.servlets.FileDownloadServlet;
import org.fenixedu.bennu.signals.DomainObjectEvent;
import org.fenixedu.bennu.signals.Signal;
import org.fenixedu.cms.domain.Category;
import org.fenixedu.cms.domain.PermissionEvaluation;
import org.fenixedu.cms.domain.PermissionsArray.Permission;
import org.fenixedu.cms.domain.Post;
import org.fenixedu.cms.domain.PostFile;
import org.fenixedu.cms.domain.PostMetadata;
import org.fenixedu.cms.domain.Site;
import org.fenixedu.commons.i18n.LocalizedString;
import org.joda.time.DateTime;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonNull;
import com.google.gson.JsonObject;

import pt.ist.fenixframework.Atomic;
import pt.ist.fenixframework.FenixFramework;

/**
 * Created by borgez on 30-07-2015.
 */
@Service
public class AdminPostsService {

    @Atomic(mode = Atomic.TxMode.WRITE)
    public Post createPost(Site site, LocalizedString name) {
        Post post = new Post(site);
        post.setName(Post.sanitize(name));
        post.setBodyAndExcerpt(new LocalizedString(), new LocalizedString());
        post.setCanViewGroup(site.getCanViewGroup());
        post.setPublicationBegin(new DateTime());
        post.setActive(false);
        return post;
    }

    @Atomic(mode = Atomic.TxMode.WRITE)
    public PostFile createFile(Post post, String name, Boolean embedded, Group canViewGroup, MultipartFile file) {
        try {
            GroupBasedFile groupBasedFile = new GroupBasedFile(name, name, file.getBytes(), canViewGroup);
            return new PostFile(post, groupBasedFile, embedded, post.getFilesSet().size());
        } catch (IOException e) {
            throw new RuntimeException("Error creating Post File for post " + post, e);
        }
    }

    @Atomic(mode = Atomic.TxMode.WRITE)
    public void processPostChanges(Site site, Post post, JsonObject postJson) {
        LocalizedString name = Post.sanitize(LocalizedString.fromJson(postJson.get("name")));
        LocalizedString body = Post.sanitize(LocalizedString.fromJson(postJson.get("body")));
        LocalizedString excerpt = Post.sanitize(LocalizedString.fromJson(postJson.get("excerpt")));

        String slug = ofNullable(postJson.get("slug")).map(JsonElement::getAsString).orElse(post.getSlug());

        if (!post.getName().equals(name)) {
            post.setName(name);
        }
        if (!post.getBody().equals(body) || (post.getExcerpt() == null && excerpt != null)
                || !post.getExcerpt().equals(excerpt)) {
            post.setBodyAndExcerpt(body, excerpt);
        }
        if (!post.getSlug().equals(slug)) {
            post.setSlug(slug);
        }

        processCategoryChanges(site, post, postJson);
        processFileChanges(site, post, postJson);
        processPublicationChanges(site, post, postJson);
        post.fixOrder(post.getFilesSorted());
        Signal.emit(Post.SIGNAL_EDITED, new DomainObjectEvent<>(post));
    }

    private boolean equalDates(DateTime time1, DateTime time2) {
        return ofNullable(time1).map(DateTime::toString).orElse("")
                .equals(ofNullable(time2).map(DateTime::toString).orElse(""));
    }

    public JsonObject serializePost(Post post) {
        JsonObject postJson = new JsonObject();
        JsonArray categoriesJson = new JsonArray();
        JsonArray filesJson = new JsonArray();
        if (canDoThis(post.getSite(), Permission.LIST_CATEGORIES, Permission.EDIT_CATEGORY)) {
            boolean canUsePrivileged = canDoThis(post.getSite(), Permission.USE_PRIVILEGED_CATEGORY);
            post.getSite().getCategoriesSet().stream().filter(cat -> canUsePrivileged || !cat.getPrivileged())
                    .sorted(Category.CATEGORY_NAME_COMPARATOR).map(category -> serializeCategory(category, post))
                    .forEach(categoriesJson::add);
        }
        post.getFilesSorted().stream().map(this::serializePostFile).forEach(filesJson::add);
        postJson.addProperty("slug", post.getSlug());
        postJson.add("name", ofNullable(post.getName()).map(LocalizedString::json).orElseGet(JsonObject::new));
        postJson.add("body", ofNullable(post.getBody()).map(LocalizedString::json).orElseGet(JsonObject::new));
        postJson.add("excerpt",
                ofNullable(post.getExcerpt()).map(LocalizedString::json).orElseGet(JsonObject::new));

        if (PermissionEvaluation.canDoThis(post.getSite(), Permission.SEE_METADATA)) {
            postJson.add("metadata",
                    ofNullable(post.getMetadata()).map(PostMetadata::json).orElseGet(JsonObject::new));
        } else {
            postJson.add("metadata", JsonNull.INSTANCE);
        }
        postJson.add("categories", categoriesJson);
        postJson.add("files", filesJson);
        postJson.addProperty("address", post.getAddress());

        if (canPublish(post)) {
            postJson.addProperty("active", post.getActive());
            postJson.addProperty("canViewGroup", post.getCanViewGroup().getExpression());
            postJson.add("createdBy", UserResource.getBuilder().view(post.getCreatedBy()));
            postJson.addProperty("publicationBegin",
                    ofNullable(post.getPublicationBegin()).map(DateTime::toString).orElse(null));
            postJson.addProperty("publicationEnd",
                    ofNullable(post.getPublicationEnd()).map(DateTime::toString).orElse(null));
        }

        return postJson;
    }

    private JsonObject serializeCategory(Category category, Post post) {
        JsonObject categoryJson = new JsonObject();
        categoryJson.add("name", category.getName().json());
        categoryJson.addProperty("slug", category.getSlug());
        categoryJson.addProperty("use", post.getCategoriesSet().contains(category));
        return categoryJson;
    }

    public JsonObject serializePostFile(PostFile postFile) {
        JsonObject fileJson = new JsonObject();
        fileJson.addProperty("id", postFile.getExternalId());
        fileJson.addProperty("displayName", postFile.getFiles().getDisplayName());
        fileJson.addProperty("fileName", postFile.getFiles().getFilename());
        fileJson.addProperty("contentType", postFile.getFiles().getContentType());
        fileJson.addProperty("editUrl", postFile.getEditUrl());
        fileJson.addProperty("isEmbedded", postFile.getIsEmbedded());
        fileJson.addProperty("index", postFile.getIndex());
        fileJson.addProperty("canViewGroup", postFile.getFiles().getAccessGroup().getExpression());
        fileJson.addProperty("url", FileDownloadServlet.getDownloadUrl(postFile.getFiles()));
        return fileJson;
    }

    private void processPublicationChanges(Site site, Post post, JsonObject postJson) {
        if (canPublish(post)) {

            boolean active = ofNullable(postJson.get("active")).map(JsonElement::getAsBoolean).orElse(false);

            DateTime publicationBegin = ofNullable(postJson.get("publicationBegin"))
                    .filter(JsonElement::isJsonPrimitive).map(JsonElement::getAsString).filter(x -> !x.isEmpty())
                    .map(DateTime::parse).orElse(null);

            DateTime publicationEnds = ofNullable(postJson.get("publicationEnd"))
                    .filter(JsonElement::isJsonPrimitive).map(JsonElement::getAsString).filter(x -> !x.isEmpty())
                    .map(DateTime::parse).orElse(null);

            Group canViewGroup = ofNullable(postJson.get("canViewGroup")).map(JsonElement::getAsString)
                    .map(Group::parse).orElse(post.getCanViewGroup());

            if (PermissionEvaluation.canDoThis(site, Permission.CHANGE_OWNERSHIP_POST)) {
                User createdBy = ofNullable(postJson.get("createdBy")).map(JsonElement::getAsJsonObject)
                        .map(json -> json.get("username").getAsString()).map(User::findByUsername)
                        .orElse(post.getCreatedBy());
                if (!post.getCreatedBy().equals(createdBy)) {
                    post.setCreatedBy(createdBy);
                }
            }

            if (!equalDates(post.getPublicationBegin(), publicationBegin)) {
                post.setPublicationBegin(publicationBegin);
            }
            if (!equalDates(post.getPublicationEnd(), publicationEnds)) {
                post.setPublicationEnd(publicationEnds);
            }
            if (!post.getCanViewGroup().equals(canViewGroup)) {
                post.setCanViewGroup(canViewGroup);
            }
            if (post.getActive() != active) {
                post.setActive(active);
            }

        }
    }

    private void processCategoryChanges(Site site, Post post, JsonObject postJson) {
        if (canDoThis(post.getSite(), Permission.LIST_CATEGORIES, Permission.EDIT_CATEGORY)) {
            if (postJson.get("categories") != null && postJson.get("categories").isJsonArray()) {
                Set<Category> newCategories = new HashSet<>();
                for (JsonElement categoryJsonEl : postJson.get("categories").getAsJsonArray()) {
                    JsonObject categoryJson = categoryJsonEl.getAsJsonObject();
                    if (ofNullable(categoryJson.get("use")).map(JsonElement::getAsBoolean).orElse(false)) {
                        String categorySlug = categoryJson.get("slug").getAsString();
                        LocalizedString categoryName = Post
                                .sanitize(LocalizedString.fromJson(categoryJson.get("name")));
                        Category category = site.categoryForSlug(categorySlug);
                        if (category == null) {
                            PermissionEvaluation.ensureCanDoThis(site, Permission.CREATE_CATEGORY);
                            category = new Category(site, categoryName);
                        } else if (category.getPrivileged()) {
                            ensureCanDoThis(site, Permission.USE_PRIVILEGED_CATEGORY);
                        }
                        newCategories.add(category);
                    }
                }

                if (!canDoThis(site, Permission.USE_PRIVILEGED_CATEGORY)) {
                    //If the user has no access to remove previleged categories, then we add them back
                    HashSet<Category> removed = new HashSet<>(post.getCategoriesSet());
                    removed.removeAll(newCategories);
                    removed.stream().filter(Category::getPrivileged).forEach(newCategories::add);
                }

                if (!newCategories.containsAll(post.getCategoriesSet())
                        || !post.getCategoriesSet().containsAll(newCategories)) {
                    post.getCategoriesSet().clear();
                    newCategories.stream().forEach(post::addCategories);
                }
            }
        }
    }

    private void processFileChanges(Site site, Post post, JsonObject postJson) {
        if (postJson.get("files") != null && postJson.get("files").isJsonArray()) {
            for (JsonElement fileJsonEl : postJson.get("files").getAsJsonArray()) {
                JsonObject fileJson = fileJsonEl.getAsJsonObject();
                PostFile postFile = FenixFramework.getDomainObject(fileJson.get("id").getAsString());
                if (postFile.getPost() == post) {
                    int index = fileJson.get("index").getAsInt();
                    boolean isEmbedded = fileJson.get("isEmbedded").getAsBoolean();
                    if (postFile.getIndex() != index) {
                        postFile.setIndex(index);
                    }
                    if (postFile.getIsEmbedded() != isEmbedded) {
                        postFile.setIsEmbedded(isEmbedded);
                    }
                    Signal.emit(PostFile.SIGNAL_EDITED, new DomainObjectEvent<>(postFile));
                }
            }
        }

    }

    private boolean canPublish(Post post) {
        return (post.isStaticPost() && canDoThis(post.getSite(), Permission.PUBLISH_PAGES))
                || (!post.isStaticPost() && canDoThis(post.getSite(), Permission.PUBLISH_POSTS));
    }
}