113 lines
3.0 KiB
Ruby
113 lines
3.0 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require 'hamster'
|
|
require 'middleman-core/util/data'
|
|
require 'middleman-core/core_extensions/data/stores/local_file'
|
|
require 'middleman-core/core_extensions/data/stores/in_memory'
|
|
require 'middleman-core/core_extensions/data/proxies/array'
|
|
require 'middleman-core/core_extensions/data/proxies/hash'
|
|
|
|
module Middleman
|
|
module CoreExtensions
|
|
module Data
|
|
# The core logic behind the data extension.
|
|
class DataStoreController
|
|
extend Forwardable
|
|
|
|
def_delegator :@local_file_data_store, :update_files
|
|
def_delegators :@in_memory_data_store, :store, :callbacks
|
|
|
|
def initialize(app, track_data_access)
|
|
@data_collection_depth = app.config[:data_collection_depth]
|
|
@track_data_access = track_data_access
|
|
|
|
@local_file_data_store = Data::Stores::LocalFileDataStore.new(app)
|
|
@in_memory_data_store = Data::Stores::InMemoryDataStore.new
|
|
|
|
# Sorted in order of access precedence.
|
|
@data_stores = [
|
|
@local_file_data_store,
|
|
@in_memory_data_store
|
|
]
|
|
|
|
@enhanced_cache = {}
|
|
end
|
|
|
|
def key?(k)
|
|
@data_stores.any? { |s| s.key?(k) }
|
|
end
|
|
alias has_key? key?
|
|
|
|
def key(k)
|
|
source = @data_stores.find { |s| s.key?(k) }
|
|
source[k] unless source.nil?
|
|
end
|
|
alias [] key
|
|
|
|
def vertices
|
|
@data_stores.reduce(::Hamster::Set.empty) do |sum, s|
|
|
sum | s.vertices
|
|
end
|
|
end
|
|
|
|
def enhanced_data(k)
|
|
value = key(k)
|
|
|
|
if @enhanced_cache.key?(k)
|
|
cached_id, cached_value = @enhanced_cache[k]
|
|
|
|
return cached_value if cached_id == value.object_id
|
|
|
|
@enhanced_cache.delete(k)
|
|
end
|
|
|
|
enhanced = ::Middleman::Util.recursively_enhance(value)
|
|
|
|
@enhanced_cache[k] = [value.object_id, enhanced]
|
|
|
|
enhanced
|
|
end
|
|
|
|
def proxied_data(k, parent = nil)
|
|
data = enhanced_data(k)
|
|
|
|
return data unless @track_data_access
|
|
|
|
case data
|
|
when ::Middleman::Util::EnhancedHash
|
|
Data::Proxies::HashProxy.new(k, data, @data_collection_depth, parent)
|
|
when ::Array
|
|
Data::Proxies::ArrayProxy.new(k, data, @data_collection_depth, parent)
|
|
else
|
|
raise 'Invalid data to wrap'
|
|
end
|
|
end
|
|
|
|
# "Magically" find namespaces of data if they exist
|
|
#
|
|
# @param [String] path The namespace to search for
|
|
# @return [Hash, nil]
|
|
def method_missing(method)
|
|
return proxied_data(method) if key?(method)
|
|
|
|
super
|
|
end
|
|
|
|
# Needed so that method_missing makes sense
|
|
def respond_to_missing?(method, include_private = false)
|
|
key?(method) || super
|
|
end
|
|
|
|
# Convert all the data into a static hash
|
|
#
|
|
# @return [Hash]
|
|
def to_h
|
|
@data_stores.reduce({}) do |sum, store|
|
|
sum.merge(store.to_h)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|