Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add page layouts repository class option #2410

Merged
merged 3 commits into from
Jan 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
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