Skip to content

Commit

Permalink
Merge pull request #2410 from tvdeyen/page-definition-repository
Browse files Browse the repository at this point in the history
Add page layouts repository class option
  • Loading branch information
tvdeyen authored Jan 18, 2023
2 parents 13820ae + b532408 commit fb069af
Show file tree
Hide file tree
Showing 10 changed files with 252 additions and 205 deletions.
6 changes: 3 additions & 3 deletions app/controllers/alchemy/admin/pages_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,9 @@ def info

def new
@page ||= Page.new(layoutpage: params[:layoutpage] == "true", parent_id: params[:parent_id])
@page_layouts = PageLayout.layouts_for_select(@current_language.id, @page.layoutpage?)
@page_layouts = Page.layouts_for_select(@current_language.id, layoutpages: @page.layoutpage?)
@clipboard = get_clipboard("pages")
@clipboard_items = Page.all_from_clipboard_for_select(@clipboard, @current_language.id, @page.layoutpage?)
@clipboard_items = Page.all_from_clipboard_for_select(@clipboard, @current_language.id, layoutpages: @page.layoutpage?)
end

def create
Expand Down Expand Up @@ -398,7 +398,7 @@ def serialized_page_tree
def load_languages_and_layouts
@language = @current_language
@languages_with_page_tree = Language.on_current_site.with_root_page
@page_layouts = PageLayout.layouts_for_select(@language.id)
@page_layouts = Page.layouts_for_select(@language.id)
end

def set_preview_mode
Expand Down
6 changes: 4 additions & 2 deletions app/models/alchemy/page.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#

require_dependency "alchemy/page/fixed_attributes"
require_dependency "alchemy/page/page_layouts"
require_dependency "alchemy/page/page_scopes"
require_dependency "alchemy/page/page_natures"
require_dependency "alchemy/page/page_naming"
Expand Down Expand Up @@ -152,6 +153,7 @@ class Page < BaseRecord
after_update :touch_nodes

# Concerns
include PageLayouts
include PageScopes
include PageNatures
include PageNaming
Expand Down Expand Up @@ -267,11 +269,11 @@ def all_from_clipboard(clipboard)
where(id: clipboard.collect { |p| p["id"] })
end

def all_from_clipboard_for_select(clipboard, language_id, layoutpage = false)
def all_from_clipboard_for_select(clipboard, language_id, layoutpages: false)
return [] if clipboard.blank?

clipboard_pages = all_from_clipboard(clipboard)
allowed_page_layouts = Alchemy::PageLayout.selectable_layouts(language_id, layoutpage)
allowed_page_layouts = Alchemy::Page.selectable_layouts(language_id, layoutpages: layoutpages)
allowed_page_layout_names = allowed_page_layouts.collect { |p| p["name"] }
clipboard_pages.select { |cp| allowed_page_layout_names.include?(cp.page_layout) }
end
Expand Down
128 changes: 128 additions & 0 deletions app/models/alchemy/page/page_layouts.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# frozen_string_literal: true

module Alchemy
class Page < BaseRecord
# Module concerning page layouts
#
module PageLayouts
extend ActiveSupport::Concern

module ClassMethods
# Register a custom page layouts repository
#
# The default repository is Alchemy::PageLayout
#
def layouts_repository=(klass)
@_layouts_repository = klass
end

# Returns page layouts ready for Rails' select form helper.
#
def layouts_for_select(language_id, layoutpages: false)
@map_array = []
mapped_layouts_for_select(selectable_layouts(language_id, layoutpages: layoutpages))
end

# Returns page layouts including given layout ready for Rails' select form helper.
#
def layouts_with_own_for_select(page_layout_name, language_id, layoutpages: false)
layouts = selectable_layouts(language_id, layoutpages: layoutpages)
if layouts.detect { |l| l["name"] == page_layout_name }.nil?
@map_array = [[human_layout_name(page_layout_name), page_layout_name]]
else
@map_array = []
end
mapped_layouts_for_select(layouts)
end

deprecate :layouts_with_own_for_select, deprecator: Alchemy::Deprecation

# Returns all layouts that can be used for creating a new page.
#
# It removes all layouts from available layouts that are unique and already taken and that are marked as hide.
#
# @param [Fixnum]
# language_id of current used Language.
# @param [Boolean] (false)
# Pass true to only select layouts for global/layout pages.
#
def selectable_layouts(language_id, layoutpages: false)
@language_id = language_id
layouts_repository.all.select do |layout|
if layoutpages
layout["layoutpage"] && layout_available?(layout)
else
!layout["layoutpage"] && layout_available?(layout)
end
end
end

# Translates name for given layout
#
# === Translation example
#
# en:
# alchemy:
# page_layout_names:
# products_overview: Products Overview
#
# @param [String]
# The layout name
#
def human_layout_name(layout)
Alchemy.t(layout, scope: "page_layout_names", default: layout.to_s.humanize)
end

private

def layouts_repository
@_layouts_repository ||= PageLayout
end

# Maps given layouts for Rails select form helper.
#
def mapped_layouts_for_select(layouts)
layouts.each do |layout|
@map_array << [human_layout_name(layout["name"]), layout["name"]]
end
@map_array
end

# Returns true if the given layout is unique and not already taken or it should be hidden.
#
def layout_available?(layout)
!layout["hide"] && !already_taken?(layout) && available_on_site?(layout)
end

# Returns true if this layout is unique and already taken by another page.
#
def already_taken?(layout)
layout["unique"] && page_with_layout_existing?(layout["name"])
end

# Returns true if one page already has the given layout
#
def page_with_layout_existing?(layout)
Alchemy::Page.where(page_layout: layout, language_id: @language_id).pluck(:id).any?
end

# Returns true if given layout is available for current site.
#
# If no site layouts are defined it always returns true.
#
# == Example
#
# # config/alchemy/site_layouts.yml
# - name: default_site
# page_layouts: [default_intro]
#
def available_on_site?(layout)
return false unless Alchemy::Site.current

Alchemy::Site.current.definition.blank? ||
Alchemy::Site.current.definition.fetch("page_layouts", []).include?(layout["name"])
end
end
end
end
end
2 changes: 1 addition & 1 deletion app/views/alchemy/admin/languages/_form.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
<%= f.input :frontpage_name %>
<%= f.input :page_layout,
collection: Alchemy::PageLayout.all,
label_method: ->(p) { Alchemy::PageLayout.human_layout_name(p['name']) },
label_method: ->(p) { Alchemy::Page.human_layout_name(p['name']) },
value_method: ->(p) { p['name'] },
input_html: {class: 'alchemy_selectbox'} %>
<%= f.input :public %>
Expand Down
2 changes: 1 addition & 1 deletion app/views/alchemy/admin/languages/_language.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
<%= language.frontpage_name %>
</td>
<td>
<%= Alchemy::PageLayout.human_layout_name(language.page_layout) %>
<%= Alchemy::Page.human_layout_name(language.page_layout) %>
</td>
<td class="center">
<%= language.public? ? render_icon(:check) : nil %>
Expand Down
2 changes: 1 addition & 1 deletion app/views/alchemy/admin/pages/_page_layout_filter.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
options_for_select(
@current_language.site.page_layout_names.map do |layout|
[
Alchemy::PageLayout.human_layout_name(layout),
Alchemy::Page.human_layout_name(layout),
layout
]
end,
Expand Down
113 changes: 0 additions & 113 deletions lib/alchemy/page_layout.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,112 +41,8 @@ def get(name)
all.detect { |a| a["name"].casecmp(name).zero? }
end

def get_all_by_attributes(attributes)
return [] if attributes.blank?

if attributes.is_a? Hash
layouts = []
attributes.stringify_keys.each do |key, value|
result = all.select { |l| l.key?(key) && l[key].to_s.casecmp(value.to_s).zero? }
layouts += result unless result.empty?
end
layouts
else
[]
end
end

# Returns page layouts ready for Rails' select form helper.
#
def layouts_for_select(language_id, only_layoutpages = false)
@map_array = []
mapped_layouts_for_select(selectable_layouts(language_id, only_layoutpages))
end

# Returns all layouts that can be used for creating a new page.
#
# It removes all layouts from available layouts that are unique and already taken and that are marked as hide.
#
# @param [Fixnum]
# language_id of current used Language.
# @param [Boolean] (false)
# Pass true to only select layouts for global/layout pages.
#
def selectable_layouts(language_id, only_layoutpages = false)
@language_id = language_id
all.select do |layout|
if only_layoutpages
layout["layoutpage"] && layout_available?(layout)
else
!layout["layoutpage"] && layout_available?(layout)
end
end
end

# Returns all names of elements defined in given page layout.
#
def element_names_for(page_layout)
if definition = get(page_layout)
definition.fetch("elements", [])
else
Rails.logger.warn "\n+++ Warning: No layout definition for #{page_layout} found! in page_layouts.yml\n"
[]
end
end

# Translates name for given layout
#
# === Translation example
#
# en:
# alchemy:
# page_layout_names:
# products_overview: Products Overview
#
# @param [String]
# The layout name
#
def human_layout_name(layout)
Alchemy.t(layout, scope: "page_layout_names", default: layout.to_s.humanize)
end

private

# Returns true if the given layout is unique and not already taken or it should be hidden.
#
def layout_available?(layout)
!layout["hide"] && !already_taken?(layout) && available_on_site?(layout)
end

# Returns true if this layout is unique and already taken by another page.
#
def already_taken?(layout)
layout["unique"] && page_with_layout_existing?(layout["name"])
end

# Returns true if one page already has the given layout
#
def page_with_layout_existing?(layout)
Alchemy::Page.where(page_layout: layout, language_id: @language_id).pluck(:id).any?
end

# Returns true if given layout is available for current site.
#
# If no site layouts are defined it always returns true.
#
# == Example
#
# # config/alchemy/site_layouts.yml
# - name: default_site
# page_layouts: [default_intro]
#
def available_on_site?(layout)
return false unless Alchemy::Site.current

Alchemy::Site.current.definition.blank? ||
Alchemy::Site.current.definition.fetch("page_layouts", []).include?(layout["name"])
end

# Reads the layout definitions from +config/alchemy/page_layouts.yml+.
#
def read_definitions_file
Expand All @@ -168,15 +64,6 @@ def read_definitions_file
def layouts_file_path
Rails.root.join "config/alchemy/page_layouts.yml"
end

# Maps given layouts for Rails select form helper.
#
def mapped_layouts_for_select(layouts)
layouts.each do |layout|
@map_array << [human_layout_name(layout["name"]), layout["name"]]
end
@map_array
end
end
end
end
Loading

0 comments on commit fb069af

Please sign in to comment.