mirror of
https://0xacab.org/sutty/sutty
synced 2024-11-25 23:06:22 +00:00
160 lines
4.3 KiB
Ruby
160 lines
4.3 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
# Este servicio se encarga de crear artículos y guardarlos en git,
|
|
# asignándoselos a une usuarie
|
|
PostService = Struct.new(:site, :usuarie, :post, :params, keyword_init: true) do
|
|
# Crea un artículo nuevo
|
|
#
|
|
# @return Post
|
|
def create
|
|
self.post = site.posts(lang: locale)
|
|
.build(layout: layout)
|
|
post.usuaries << usuarie
|
|
params[:post][:draft] = true if site.invitade? usuarie
|
|
|
|
params.require(:post).permit(:slug).tap do |p|
|
|
post.slug.value = p[:slug] if p[:slug].present?
|
|
end
|
|
|
|
commit(action: :created, add: update_related_posts) if post.update(post_params)
|
|
|
|
update_site_license!
|
|
|
|
# Devolver el post aunque no se haya salvado para poder rescatar los
|
|
# errores
|
|
post
|
|
end
|
|
|
|
# Crear un post anónimo, con opciones más limitadas. No usamos post.
|
|
def create_anonymous
|
|
# XXX: Confiamos en el parámetro de idioma porque estamos
|
|
# verificándolos en Site#posts
|
|
self.post = site.posts(lang: locale)
|
|
.build(layout: layout)
|
|
# Los artículos anónimos siempre son borradores
|
|
params[:draft] = true
|
|
|
|
commit(action: :created, add: [post.path.absolute]) if post.update(anon_post_params)
|
|
post
|
|
end
|
|
|
|
def update
|
|
post.usuaries << usuarie
|
|
params[:post][:draft] = true if site.invitade? usuarie
|
|
|
|
# Eliminar ("mover") el archivo si cambió de ubicación.
|
|
if post.update(post_params)
|
|
rm = []
|
|
rm << post.path.value_was if post.path.changed?
|
|
|
|
# Es importante que el artículo se guarde primero y luego los
|
|
# relacionados.
|
|
commit(action: :updated, add: update_related_posts, rm: rm)
|
|
|
|
update_site_license!
|
|
end
|
|
|
|
# Devolver el post aunque no se haya salvado para poder rescatar los
|
|
# errores
|
|
post
|
|
end
|
|
|
|
def destroy
|
|
post.destroy!
|
|
|
|
commit(action: :destroyed, rm: [post.path.absolute]) if post.destroyed?
|
|
|
|
post
|
|
end
|
|
|
|
# Reordena todos los posts que soporten orden de acuerdo a un hash de
|
|
# uuids y nuevas posiciones. La posición actual la da la posición en
|
|
# el array.
|
|
#
|
|
# { uuid => 2, uuid => 1, uuid => 0 }
|
|
def reorder
|
|
reorder = params.require(:post).permit(reorder: {})&.dig(:reorder)&.transform_values(&:to_i)
|
|
posts = site.posts(lang: locale).where(uuid: reorder.keys)
|
|
|
|
files = posts.map do |post|
|
|
next unless post.attribute? :order
|
|
|
|
order = reorder[post.uuid.value]
|
|
|
|
next if post.order.value == order
|
|
|
|
post.order.value = order
|
|
post.path.absolute
|
|
end.compact
|
|
|
|
return if files.empty?
|
|
|
|
# TODO: Implementar transacciones!
|
|
posts.save_all(validate: false) &&
|
|
commit(action: :reorder, add: files)
|
|
end
|
|
|
|
private
|
|
|
|
def commit(action:, add: [], rm: [])
|
|
site.repository.commit(add: add,
|
|
rm: rm,
|
|
usuarie: usuarie,
|
|
message: I18n.t("post_service.#{action}",
|
|
title: post&.title&.value))
|
|
|
|
GitPushJob.perform_later(site)
|
|
end
|
|
|
|
# Solo permitir cambiar estos atributos de cada articulo
|
|
def post_params
|
|
params.require(:post).permit(post.params)
|
|
end
|
|
|
|
# Eliminar metadatos internos
|
|
def anon_post_params
|
|
params.permit(post.params).delete_if do |k, _|
|
|
%w[date slug order uuid].include? k.to_s
|
|
end
|
|
end
|
|
|
|
def locale
|
|
params.dig(:post, :lang)&.to_sym || I18n.locale
|
|
end
|
|
|
|
def layout
|
|
params.dig(:post, :layout) || params[:layout]
|
|
end
|
|
|
|
# Actualiza los artículos relacionados según los métodos que los
|
|
# metadatos declaren.
|
|
#
|
|
# Este método se asegura que todos los artículos se guardan una sola
|
|
# vez.
|
|
#
|
|
# @return [Array] Lista de archivos modificados
|
|
def update_related_posts
|
|
posts = Set.new
|
|
|
|
post.attributes.each do |a|
|
|
post[a].related_methods.each do |m|
|
|
next unless post[a].respond_to? m
|
|
|
|
# La respuesta puede ser una PostRelation también
|
|
posts.merge [post[a].public_send(m)].flatten.compact
|
|
end
|
|
end
|
|
|
|
posts.map do |p|
|
|
p.path.absolute if p.save(validate: false)
|
|
end.compact << post.path.absolute
|
|
end
|
|
|
|
# Si les usuaries modifican o crean una licencia, considerarla
|
|
# personalizada en el panel.
|
|
def update_site_license!
|
|
if site.usuarie?(usuarie) && post.layout.name == :license && !site.licencia.custom?
|
|
site.update licencia: Licencia.find_by_icons('custom')
|
|
end
|
|
end
|
|
end
|