2018-01-29 22:19:10 +00:00
|
|
|
# Un sitio es un directorio dentro del directorio de sitios de cada
|
|
|
|
# Usuaria
|
|
|
|
class Site
|
|
|
|
|
2018-02-23 19:20:51 +00:00
|
|
|
attr_accessor :jekyll, :collections
|
2018-02-02 22:20:31 +00:00
|
|
|
attr_reader :path
|
2018-01-29 22:19:10 +00:00
|
|
|
|
2018-02-02 22:20:31 +00:00
|
|
|
def initialize(jekyll:, path: nil)
|
2018-01-29 22:19:10 +00:00
|
|
|
@jekyll = jekyll
|
2018-02-02 22:20:31 +00:00
|
|
|
@path = path || @jekyll.config['source']
|
2018-02-23 19:20:51 +00:00
|
|
|
@collections = {}
|
2018-01-29 22:19:10 +00:00
|
|
|
end
|
|
|
|
|
2018-02-22 19:01:11 +00:00
|
|
|
# Determina si el sitio está en varios idiomas
|
|
|
|
def i18n?
|
|
|
|
@jekyll.config.dig('i18n').present?
|
|
|
|
end
|
|
|
|
|
2018-01-29 22:19:10 +00:00
|
|
|
# Obtener el nombre del sitio
|
|
|
|
def name
|
|
|
|
@name ||= @jekyll.config['source'].split('/').last
|
|
|
|
end
|
|
|
|
|
2018-02-22 19:01:11 +00:00
|
|
|
def name_with_i18n(lang)
|
|
|
|
[name, lang].join('/')
|
|
|
|
end
|
|
|
|
|
2018-01-29 22:19:10 +00:00
|
|
|
# El id es el sitio sin puntos, para no confundir al routeador de
|
|
|
|
# rails
|
|
|
|
def id
|
|
|
|
@id ||= name.tr('.', '-')
|
|
|
|
end
|
|
|
|
alias :to_s :id
|
|
|
|
|
2018-02-19 19:33:28 +00:00
|
|
|
def read
|
|
|
|
@jekyll.read
|
|
|
|
end
|
|
|
|
|
|
|
|
# Fuerza relectura del sitio, eliminando el sitio actual en favor de
|
|
|
|
# un sitio nuevo, leído desde cero
|
|
|
|
def read!
|
|
|
|
@jekyll = Site.load_jekyll(@jekyll.path)
|
|
|
|
|
|
|
|
@jekyll.read
|
|
|
|
end
|
|
|
|
|
2018-02-09 21:28:27 +00:00
|
|
|
def data
|
|
|
|
if @jekyll.data.empty?
|
2018-02-19 19:33:28 +00:00
|
|
|
read
|
2018-02-09 21:28:27 +00:00
|
|
|
Rails.logger.info 'Leyendo data'
|
|
|
|
end
|
|
|
|
|
|
|
|
@jekyll.data
|
|
|
|
end
|
|
|
|
|
|
|
|
def config
|
|
|
|
if @jekyll.config.empty?
|
2018-02-19 19:33:28 +00:00
|
|
|
read
|
2018-02-09 21:28:27 +00:00
|
|
|
Rails.logger.info 'Leyendo config'
|
|
|
|
end
|
|
|
|
|
|
|
|
@jekyll.config
|
|
|
|
end
|
|
|
|
|
2018-02-23 19:20:51 +00:00
|
|
|
def collections
|
|
|
|
@collections
|
|
|
|
end
|
|
|
|
|
2018-02-22 19:01:11 +00:00
|
|
|
# Los posts de este sitio, si el sitio está traducido, trae los posts
|
|
|
|
# del idioma actual, porque _posts va a estar vacío
|
2018-01-29 22:19:10 +00:00
|
|
|
def posts
|
2018-02-22 19:01:11 +00:00
|
|
|
@posts ||= if i18n?
|
|
|
|
posts_for(I18n.locale.to_s)
|
|
|
|
else
|
|
|
|
posts_for('posts')
|
|
|
|
end
|
|
|
|
end
|
2018-01-29 22:19:10 +00:00
|
|
|
|
2018-02-22 19:01:11 +00:00
|
|
|
# Obtiene todos los posts de una colección determinada
|
|
|
|
#
|
|
|
|
# Devuelve nil si la colección no existe
|
|
|
|
def posts_for(collection)
|
|
|
|
return unless @jekyll.config['collections'].key? collection
|
|
|
|
|
2018-02-23 19:20:51 +00:00
|
|
|
_collection = @collections[collection]
|
|
|
|
return _collection if _collection
|
2018-02-03 22:37:09 +00:00
|
|
|
|
2018-02-22 19:01:11 +00:00
|
|
|
Rails.logger.info "Procesando #{collection}"
|
|
|
|
|
|
|
|
col = @jekyll.collections[collection].docs
|
|
|
|
if col.empty?
|
2018-02-02 22:20:31 +00:00
|
|
|
@jekyll.read
|
|
|
|
# Queremos saber cuantas veces releemos los articulos
|
|
|
|
Rails.logger.info 'Leyendo articulos'
|
|
|
|
end
|
2018-01-29 22:19:10 +00:00
|
|
|
|
|
|
|
# Los convertimos a una clase intermedia capaz de acceder a sus
|
|
|
|
# datos y modificarlos
|
2018-02-23 19:20:51 +00:00
|
|
|
@collections[collection] = col.map do |post|
|
2018-02-22 19:01:11 +00:00
|
|
|
Post.new(site: self, post: post, lang: collection)
|
2018-02-23 19:20:51 +00:00
|
|
|
end
|
2018-01-29 22:19:10 +00:00
|
|
|
end
|
|
|
|
|
2018-02-03 23:41:02 +00:00
|
|
|
def categories
|
2018-02-08 14:05:05 +00:00
|
|
|
everything_of :categories
|
2018-02-03 23:41:02 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def tags
|
2018-02-08 14:05:05 +00:00
|
|
|
everything_of :tags
|
|
|
|
end
|
|
|
|
|
|
|
|
def everything_of(attr)
|
|
|
|
posts.map do |p|
|
|
|
|
p.get_front_matter attr
|
|
|
|
end.flatten.uniq
|
2018-02-03 23:41:02 +00:00
|
|
|
end
|
|
|
|
|
2018-02-20 17:47:11 +00:00
|
|
|
# Las usuarias que tienen acceso a este sitio se guardan en un archivo
|
|
|
|
# `.usuarias` que tiene la dirección de correo de cada una
|
|
|
|
def usuarias_file
|
|
|
|
File.join(path, '.usuarias')
|
|
|
|
end
|
|
|
|
|
|
|
|
# Obtiene las usuarias que gestionan este sitio
|
|
|
|
def usuarias
|
|
|
|
@usuarias ||= File.read(usuarias_file).split("\n").map do |u|
|
|
|
|
Usuaria.find(u)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def failed_file
|
|
|
|
File.join(path, '.failed')
|
|
|
|
end
|
|
|
|
|
|
|
|
def failed?
|
|
|
|
File.exist? failed_file
|
|
|
|
end
|
|
|
|
|
|
|
|
def defail
|
|
|
|
FileUtils.rm failed_file if failed?
|
|
|
|
end
|
|
|
|
alias :defail! :defail
|
|
|
|
|
|
|
|
def build_log
|
|
|
|
File.join(path, 'build.log')
|
|
|
|
end
|
|
|
|
|
|
|
|
def build_log?
|
|
|
|
File.exist? build_log
|
|
|
|
end
|
|
|
|
|
|
|
|
def queue_file
|
|
|
|
File.join(path, '.generate')
|
|
|
|
end
|
|
|
|
|
|
|
|
def enqueued?
|
|
|
|
File.exist? queue_file
|
|
|
|
end
|
|
|
|
alias :queued? :enqueued?
|
|
|
|
|
|
|
|
# El sitio se genera cuando se coloca en una cola de generación, para
|
|
|
|
# que luego lo construya un cronjob
|
|
|
|
def enqueue
|
|
|
|
defail!
|
|
|
|
# TODO ya van tres métodos donde usamos esta idea, convertir en un
|
|
|
|
# helper o algo
|
|
|
|
r = File.open(queue_file, File::RDWR | File::CREAT, 0o640) do |f|
|
|
|
|
# Bloquear el archivo para que no sea accedido por otro
|
|
|
|
# proceso u otra editora
|
|
|
|
f.flock(File::LOCK_EX)
|
|
|
|
|
|
|
|
# Empezar por el principio
|
|
|
|
f.rewind
|
|
|
|
|
|
|
|
# Escribir la fecha de creación
|
|
|
|
f.write(Time.now.to_i.to_s)
|
|
|
|
|
|
|
|
# Eliminar el resto
|
|
|
|
f.flush
|
|
|
|
f.truncate(f.pos)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
alias :enqueue! :enqueue
|
|
|
|
|
|
|
|
# Eliminar de la cola
|
|
|
|
def dequeue
|
|
|
|
FileUtils.rm(queue_file) if enqueued?
|
|
|
|
end
|
|
|
|
alias :dequeue! :dequeue
|
|
|
|
|
2018-01-29 22:19:10 +00:00
|
|
|
# El directorio donde se almacenan los sitios
|
|
|
|
def self.site_path
|
|
|
|
File.join(Rails.root, '_sites')
|
|
|
|
end
|
|
|
|
|
|
|
|
# El directorio de los sitios de una usuaria
|
|
|
|
#
|
|
|
|
# Los sitios se organizan por usuaria, entonces los sitios que
|
|
|
|
# administra pueden encontrarse directamente en su directorio.
|
|
|
|
#
|
|
|
|
# Si comparten gestión con otras usuarias, se hacen links simbólicos
|
|
|
|
# entre sí.
|
|
|
|
def self.site_path_for(usuaria)
|
|
|
|
File.join(Site.site_path, usuaria.username)
|
|
|
|
end
|
|
|
|
|
|
|
|
# Comprueba que el directorio parezca ser de jekyll
|
|
|
|
def self.jekyll?(dir)
|
|
|
|
File.directory?(dir) && File.exist?(File.join(dir, '_config.yml'))
|
|
|
|
end
|
|
|
|
|
2018-02-19 19:33:28 +00:00
|
|
|
def self.load_jekyll(path)
|
|
|
|
config = ::Jekyll.configuration('source' => path)
|
|
|
|
|
|
|
|
# No necesitamos cargar plugins en este momento
|
|
|
|
%w[plugins gems].each do |unneeded|
|
|
|
|
config[unneeded] = [] if config.key? unneeded
|
|
|
|
end
|
|
|
|
|
2018-02-22 19:01:11 +00:00
|
|
|
# Si estamos usando nuestro propio plugin de i18n, los posts están
|
|
|
|
# en "colecciones"
|
|
|
|
i18n = config.dig('i18n')
|
|
|
|
if i18n
|
|
|
|
i18n.each do |i|
|
|
|
|
config['collections'][i] = {}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-02-19 19:33:28 +00:00
|
|
|
Jekyll::Site.new(config)
|
|
|
|
end
|
|
|
|
|
2018-01-29 22:19:10 +00:00
|
|
|
# Obtener todos los directorios de sitios asociados a esta usuaria
|
|
|
|
def self.all_for(usuaria)
|
|
|
|
@sites ||= Pathname.new(Site.site_path_for(usuaria))
|
|
|
|
.children.map(&:expand_path).map(&:to_s).map do |j|
|
|
|
|
|
|
|
|
next unless Site.jekyll? j
|
|
|
|
|
|
|
|
Dir.chdir(j) do
|
2018-02-19 19:33:28 +00:00
|
|
|
jekyll = Site.load_jekyll(Dir.pwd)
|
|
|
|
Site.new(jekyll: jekyll, path: j)
|
2018-01-29 22:19:10 +00:00
|
|
|
end
|
|
|
|
end.compact
|
|
|
|
end
|
|
|
|
end
|