2018-06-15 21:34:33 +00:00
|
|
|
# Representa los distintos tipos de campos que pueden venir de una
|
|
|
|
# plantilla compleja
|
|
|
|
class Post
|
|
|
|
class TemplateField
|
|
|
|
attr_reader :post, :contents, :key
|
|
|
|
|
2018-06-21 17:32:54 +00:00
|
|
|
STRING_VALUES = %w[string text url number email].freeze
|
|
|
|
|
2018-06-15 21:34:33 +00:00
|
|
|
def initialize(post, key, contents)
|
|
|
|
@post = post
|
|
|
|
@key = key
|
|
|
|
@contents = contents
|
|
|
|
end
|
|
|
|
|
2018-06-15 22:13:18 +00:00
|
|
|
# Obtiene el valor
|
|
|
|
def value
|
|
|
|
complex? ? contents.dig('value') : contents
|
|
|
|
end
|
|
|
|
|
2018-06-20 18:00:32 +00:00
|
|
|
def max
|
|
|
|
return 0 if simple?
|
|
|
|
contents.fetch('max', 0)
|
|
|
|
end
|
|
|
|
|
|
|
|
def min
|
|
|
|
return 0 if simple?
|
|
|
|
contents.fetch('min', 0)
|
|
|
|
end
|
|
|
|
|
2018-06-15 21:34:33 +00:00
|
|
|
def type
|
|
|
|
return @type if @type
|
|
|
|
|
|
|
|
case
|
2018-06-15 21:40:22 +00:00
|
|
|
when text_area?
|
2018-06-15 21:34:33 +00:00
|
|
|
@type = 'text_area'
|
2018-06-15 21:40:22 +00:00
|
|
|
when string?
|
|
|
|
@type = 'text'
|
|
|
|
when string? && contents.split('/', 2).count == 2
|
2018-06-15 21:34:33 +00:00
|
|
|
@type = 'select'
|
2018-06-19 20:38:43 +00:00
|
|
|
when nested?
|
|
|
|
@type = 'table'
|
2018-06-15 21:40:22 +00:00
|
|
|
when array?
|
2018-06-15 21:34:33 +00:00
|
|
|
@type = 'select'
|
2018-06-15 21:40:22 +00:00
|
|
|
when boolean?
|
2018-06-15 21:34:33 +00:00
|
|
|
@type = 'check_box'
|
|
|
|
end
|
|
|
|
|
|
|
|
@type
|
|
|
|
end
|
|
|
|
|
2018-06-21 17:33:45 +00:00
|
|
|
# Devuelve los valores vacíos según el tipo
|
|
|
|
def empty_value
|
|
|
|
case
|
|
|
|
when string?
|
|
|
|
''
|
|
|
|
when nested?
|
|
|
|
# TODO devolver las keys también
|
|
|
|
{}
|
|
|
|
when array?
|
|
|
|
[]
|
|
|
|
when boolean?
|
|
|
|
false
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-06-15 21:44:35 +00:00
|
|
|
# El campo es requerido si es complejo y se especifica que lo sea
|
|
|
|
def required?
|
|
|
|
complex? && contents.dig('required')
|
|
|
|
end
|
|
|
|
|
2018-06-15 21:40:22 +00:00
|
|
|
def boolean?
|
2018-06-15 21:44:35 +00:00
|
|
|
value.is_a?(FalseClass) || value.is_a?(TrueClass)
|
2018-06-15 21:40:22 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def string?
|
2018-06-15 21:44:35 +00:00
|
|
|
value.is_a? String
|
2018-06-15 21:40:22 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def text_area?
|
2018-06-15 21:44:35 +00:00
|
|
|
value == 'text'
|
2018-06-15 21:40:22 +00:00
|
|
|
end
|
|
|
|
|
2018-06-15 21:34:33 +00:00
|
|
|
# Si la plantilla es simple no está admitiendo Hashes como valores
|
|
|
|
def simple?
|
|
|
|
!complex?
|
|
|
|
end
|
|
|
|
|
|
|
|
def complex?
|
|
|
|
contents.is_a? Hash
|
|
|
|
end
|
|
|
|
|
|
|
|
# XXX Retrocompatibilidad
|
|
|
|
def to_s
|
|
|
|
key
|
|
|
|
end
|
|
|
|
|
2018-06-15 21:40:22 +00:00
|
|
|
# Convierte el campo en un parámetro
|
2018-06-15 21:34:33 +00:00
|
|
|
def to_param
|
2018-06-21 17:32:54 +00:00
|
|
|
if nested?
|
|
|
|
{ key.to_sym => {} }
|
|
|
|
elsif array?
|
2018-06-15 21:34:33 +00:00
|
|
|
{ key.to_sym => [] }
|
|
|
|
else
|
|
|
|
key.to_sym
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-06-21 17:33:45 +00:00
|
|
|
# Convierte la plantilla en el formato de front_matter
|
|
|
|
def to_front_matter
|
|
|
|
{ key => empty_value }
|
|
|
|
end
|
|
|
|
|
2018-06-15 21:34:33 +00:00
|
|
|
def array?
|
2018-06-15 21:44:35 +00:00
|
|
|
value.is_a? Array
|
2018-06-15 21:34:33 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
# TODO detectar cuando es complejo y tomar el valor de :multiple
|
|
|
|
def multiple?
|
2018-06-18 21:05:05 +00:00
|
|
|
# si la plantilla es simple, es multiple cuando tenemos un array
|
|
|
|
return array? if simple?
|
|
|
|
|
2018-06-18 21:06:10 +00:00
|
|
|
array? && contents.fetch('multiple', true)
|
2018-06-15 21:34:33 +00:00
|
|
|
end
|
|
|
|
|
2018-06-18 20:58:44 +00:00
|
|
|
# Detecta si el valor es una tabla de campos
|
|
|
|
def nested?
|
2018-06-19 20:38:43 +00:00
|
|
|
value.is_a?(Hash) || (array? && value.first.is_a?(Hash))
|
2018-06-18 20:58:44 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
# Un campo acepta valores abiertos si no es un array con múltiples
|
|
|
|
# elementos
|
|
|
|
def open?
|
|
|
|
# Todos los valores simples son abiertos
|
|
|
|
return true unless complex?
|
|
|
|
return false unless array?
|
|
|
|
# La cosa se complejiza cuando tenemos valores complejos
|
|
|
|
#
|
|
|
|
# Si tenemos una lista cerrada de valores, necesitamos saber si el
|
|
|
|
# campo es abierto o cerrado. Si la lista tiene varios elementos,
|
|
|
|
# es una lista cerrada, opcionalmente abierta. Si la lista tiene
|
|
|
|
# un elemento, quiere decir que estamos autocompletando desde otro
|
|
|
|
# lado.
|
|
|
|
contents.fetch('open', value.count < 2)
|
|
|
|
end
|
|
|
|
|
2018-06-19 17:45:04 +00:00
|
|
|
# Determina si los valores del campo serán públicos después
|
|
|
|
#
|
|
|
|
# XXX Esto es solo una indicación, el theme Jekyll tiene que
|
|
|
|
# respetarlos por su lado luego
|
|
|
|
def public?
|
|
|
|
# Todos los campos son públicos a menos que se indique lo
|
|
|
|
# contrario
|
|
|
|
simple? || contents.fetch('public', true)
|
|
|
|
end
|
|
|
|
|
|
|
|
def private?
|
|
|
|
!public?
|
|
|
|
end
|
|
|
|
|
2018-06-19 16:50:39 +00:00
|
|
|
def human
|
|
|
|
h = key.humanize
|
|
|
|
h = h + ' *' if required?
|
|
|
|
|
|
|
|
h
|
|
|
|
end
|
|
|
|
|
2018-06-19 17:37:45 +00:00
|
|
|
def help
|
2018-06-19 20:38:43 +00:00
|
|
|
(complex? && contents.dig('help')) || human
|
|
|
|
end
|
|
|
|
|
|
|
|
def nested_fields
|
|
|
|
return unless nested?
|
|
|
|
|
|
|
|
v = value
|
|
|
|
v = value.first if array?
|
|
|
|
|
|
|
|
@nested_fields ||= v.map do |k,sv|
|
|
|
|
Post::TemplateField.new post, k, sv
|
|
|
|
end
|
2018-06-19 17:37:45 +00:00
|
|
|
end
|
|
|
|
|
2018-06-15 21:34:33 +00:00
|
|
|
# Obtiene los valores posibles para el campo de la plantilla
|
|
|
|
def values
|
2018-06-21 17:32:54 +00:00
|
|
|
return '' if STRING_VALUES.include? value
|
2018-06-15 21:34:33 +00:00
|
|
|
|
|
|
|
# Para obtener los valores posibles, hay que procesar la string y
|
|
|
|
# convertirla a parametros
|
|
|
|
#
|
|
|
|
# XXX Prestar atención a no enviar metodos privados
|
|
|
|
|
|
|
|
# Si es una array de un solo elemento, es un indicador de que
|
|
|
|
# tenemos que rellenarla con los valores que indica
|
2018-06-18 20:00:27 +00:00
|
|
|
if array? && value.count == 1
|
2018-06-15 21:34:33 +00:00
|
|
|
values = value.first
|
|
|
|
else
|
|
|
|
values = value
|
|
|
|
end
|
|
|
|
|
|
|
|
# Procesar el valor
|
|
|
|
if values.is_a?(String)
|
|
|
|
value = values.split(':', 2).map do |v|
|
2018-06-21 17:32:54 +00:00
|
|
|
collection, attr, subattr = v.split('/', 3)
|
2018-06-15 21:34:33 +00:00
|
|
|
|
|
|
|
if collection == 'site'
|
|
|
|
# TODO puede ser peligroso permitir acceder a cualquier
|
|
|
|
# atributo de site? No estamos trayendo nada fuera de
|
|
|
|
# lo normal
|
|
|
|
post.site.send(attr.to_sym)
|
2018-06-21 17:32:54 +00:00
|
|
|
# Si hay un subatributo, tenemos que averiguar todos los
|
|
|
|
# valores dentro de el
|
|
|
|
# TODO volver elegante!
|
|
|
|
elsif subattr
|
|
|
|
post.site.everything_of(attr, lang: collection).compact.map do |v|
|
|
|
|
tv = v.dig('value')
|
|
|
|
if tv.is_a? Array
|
|
|
|
tv.map do |sv|
|
|
|
|
sv[subattr]
|
|
|
|
end
|
|
|
|
else
|
|
|
|
tv[subattr]
|
|
|
|
end
|
|
|
|
end
|
2018-06-15 21:34:33 +00:00
|
|
|
else
|
2018-06-21 17:32:54 +00:00
|
|
|
post.site.everything_of(attr, lang: collection).compact
|
2018-06-15 21:34:33 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-06-18 20:00:27 +00:00
|
|
|
values = value.last.zip value.first
|
2018-06-15 21:34:33 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
# En última instancia, traer el valor por defecto
|
2018-06-18 20:00:27 +00:00
|
|
|
values
|
2018-06-15 21:34:33 +00:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|