alchemy_cms 2.4.1 → 2.5.0.b2
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +1 -1
- data/README.md +18 -17
- data/alchemy_cms.gemspec +5 -10
- data/app/assets/images/alchemy/icons.png +0 -0
- data/app/assets/stylesheets/alchemy/archive.scss +27 -0
- data/app/assets/stylesheets/alchemy/base.scss +0 -51
- data/app/assets/stylesheets/alchemy/elements.scss +37 -2
- data/app/assets/stylesheets/alchemy/icons.scss +4 -0
- data/app/assets/stylesheets/alchemy/modules.scss +4 -0
- data/app/assets/stylesheets/alchemy/sitemap.scss +1 -1
- data/app/assets/stylesheets/alchemy/tables.scss +1 -1
- data/app/assets/stylesheets/alchemy/variables.scss +1 -0
- data/app/controllers/alchemy/admin/pages_controller.rb +1 -0
- data/app/controllers/alchemy/admin/pictures_controller.rb +22 -8
- data/app/controllers/alchemy/admin/resources_controller.rb +1 -1
- data/app/controllers/alchemy/admin/sites_controller.rb +6 -0
- data/app/controllers/alchemy/base_controller.rb +8 -0
- data/app/controllers/alchemy/elements_controller.rb +33 -3
- data/app/controllers/alchemy/messages_controller.rb +47 -40
- data/app/controllers/alchemy/pages_controller.rb +8 -31
- data/app/controllers/alchemy/pictures_controller.rb +64 -30
- data/app/helpers/alchemy/admin/base_helper.rb +7 -0
- data/app/helpers/alchemy/admin/pages_helper.rb +12 -0
- data/app/helpers/alchemy/elements_helper.rb +2 -0
- data/app/helpers/alchemy/pages_helper.rb +30 -10
- data/app/helpers/alchemy/url_helper.rb +1 -0
- data/app/models/alchemy/content.rb +1 -2
- data/app/models/alchemy/element.rb +47 -2
- data/app/models/alchemy/language.rb +27 -14
- data/app/models/alchemy/page.rb +1 -1
- data/app/models/alchemy/picture.rb +46 -41
- data/app/models/alchemy/site.rb +44 -0
- data/app/views/alchemy/admin/elements/_element_head.html.erb +1 -0
- data/app/views/alchemy/admin/languages/index.html.erb +23 -0
- data/app/views/alchemy/admin/pages/edit.html.erb +27 -1
- data/app/views/alchemy/admin/pages/fold.js.erb +1 -0
- data/app/views/alchemy/admin/partials/_upload_form.html.erb +2 -0
- data/app/views/alchemy/admin/pictures/_picture.html.erb +24 -2
- data/app/views/alchemy/admin/pictures/_tag_list.html.erb +5 -4
- data/app/views/alchemy/admin/pictures/create.js.erb +1 -9
- data/app/views/alchemy/admin/pictures/info.html.erb +42 -0
- data/app/views/alchemy/admin/resources/_form.html.erb +0 -2
- data/app/views/alchemy/admin/resources/_resource.html.erb +2 -1
- data/app/views/alchemy/admin/resources/index.html.erb +2 -1
- data/app/views/alchemy/elements/show.html.erb +1 -6
- data/app/views/alchemy/elements/show.js.erb +4 -10
- data/app/views/alchemy/essences/_essence_link_view.html.erb +1 -0
- data/app/views/alchemy/search/_form.html.erb +9 -6
- data/app/views/alchemy/search/_result.html.erb +1 -1
- data/bin/alchemy +13 -120
- data/config/alchemy/config.yml +7 -11
- data/config/alchemy/modules.yml +24 -12
- data/config/authorization_rules.rb +6 -2
- data/config/initializers/dragonfly.rb +20 -0
- data/config/locales/alchemy.de.yml +57 -28
- data/config/locales/alchemy.en.yml +18 -4
- data/config/routes.rb +4 -2
- data/db/migrate/20121121162313_switch_from_fleximage_to_dragonfly.rb +21 -0
- data/db/migrate/20121205155004_create_alchemy_sites.rb +14 -0
- data/db/migrate/20121211163003_add_public_to_alchemy_sites.rb +6 -0
- data/lib/alchemy/capistrano.rb +7 -2
- data/lib/alchemy/ferret_search.rb +84 -0
- data/lib/alchemy/picture_attributes.rb +29 -0
- data/lib/alchemy/seeder.rb +10 -16
- data/lib/alchemy/upgrader.rb +59 -8
- data/lib/alchemy/version.rb +1 -1
- data/lib/alchemy_cms.rb +7 -4
- data/lib/rails/generators/alchemy/deploy_script/templates/deploy.rb.tt +3 -0
- data/lib/rails/generators/alchemy/elements/elements_generator.rb +5 -1
- data/lib/rails/generators/alchemy/page_layouts/page_layouts_generator.rb +1 -0
- data/lib/rails/generators/alchemy/scaffold/files/{pages.html.erb → application.html.erb} +0 -0
- data/lib/rails/generators/alchemy/scaffold/scaffold_generator.rb +11 -20
- data/lib/rails/templates/alchemy.rb +1 -7
- data/lib/tasks/{database.rake → alchemy/db.rake} +1 -1
- data/lib/tasks/{install.rake → alchemy/install.rake} +9 -14
- data/lib/tasks/{upgrade.rake → alchemy/upgrade.rake} +1 -1
- data/spec/controllers/elements_controller_spec.rb +24 -9
- data/spec/controllers/pictures_controller_spec.rb +11 -8
- data/{app → spec/dummy/app}/views/alchemy/elements/_article_editor.html.erb +0 -0
- data/{app → spec/dummy/app}/views/alchemy/elements/_article_view.html.erb +0 -0
- data/{app → spec/dummy/app}/views/alchemy/elements/_headline_view.html.erb +0 -0
- data/{app → spec/dummy/app}/views/alchemy/elements/_news_view.html.erb +0 -0
- data/{app → spec/dummy/app}/views/alchemy/elements/_searchresult_view.html.erb +0 -0
- data/{app → spec/dummy/app}/views/alchemy/page_layouts/_standard.html.erb +0 -0
- data/spec/dummy/config/alchemy/elements.yml +86 -0
- data/spec/dummy/config/alchemy/page_layouts.yml +26 -0
- data/spec/dummy/config/application.rb +1 -1
- data/spec/dummy/db/migrate/20121121162313_switch_from_fleximage_to_dragonfly.rb +21 -0
- data/spec/dummy/db/migrate/20121205155004_create_alchemy_sites.rb +14 -0
- data/spec/dummy/db/migrate/20121211163003_add_public_to_alchemy_sites.rb +6 -0
- data/spec/dummy/db/schema.rb +21 -6
- data/spec/factories.rb +6 -2
- data/spec/integration/translation_integration_spec.rb +4 -18
- data/spec/models/element_spec.rb +4 -4
- data/spec/models/picture_spec.rb +37 -20
- data/spec/models/site_spec.rb +69 -0
- data/spec/routing_spec.rb +115 -115
- data/spec/spec_helper.rb +1 -3
- data/spec/support/alchemy/specs_helpers.rb +4 -4
- data/vendor/assets/javascripts/jquery_plugins/jquery.html5uploader.js +1 -1
- metadata +72 -96
- data/app/assets/stylesheets/alchemy/standard_set.css +0 -440
- data/app/views/alchemy/elements/_bild_editor.html.erb +0 -1
- data/app/views/alchemy/elements/_bild_text_editor.html.erb +0 -7
- data/app/views/alchemy/elements/_bild_text_view.html.erb +0 -9
- data/app/views/alchemy/elements/_bild_view.html.erb +0 -9
- data/app/views/alchemy/elements/_claim_editor.html.erb +0 -1
- data/app/views/alchemy/elements/_claim_view.html.erb +0 -1
- data/app/views/alchemy/elements/_contactform_editor.html.erb +0 -4
- data/app/views/alchemy/elements/_contactform_view.html.erb +0 -78
- data/app/views/alchemy/elements/_download_editor.html.erb +0 -4
- data/app/views/alchemy/elements/_download_view.html.erb +0 -7
- data/app/views/alchemy/elements/_footnote_editor.html.erb +0 -1
- data/app/views/alchemy/elements/_footnote_view.html.erb +0 -5
- data/app/views/alchemy/elements/_header_editor.html.erb +0 -1
- data/app/views/alchemy/elements/_header_view.html.erb +0 -1
- data/app/views/alchemy/elements/_headline_editor.html.erb +0 -1
- data/app/views/alchemy/elements/_image_mosaic_editor.html.erb +0 -3
- data/app/views/alchemy/elements/_image_mosaic_view.html.erb +0 -14
- data/app/views/alchemy/elements/_intro_editor.html.erb +0 -1
- data/app/views/alchemy/elements/_intro_image_text_editor.html.erb +0 -3
- data/app/views/alchemy/elements/_intro_image_text_view.html.erb +0 -16
- data/app/views/alchemy/elements/_intro_view.html.erb +0 -3
- data/app/views/alchemy/elements/_news_editor.html.erb +0 -3
- data/app/views/alchemy/elements/_searchresult_editor.html.erb +0 -4
- data/app/views/alchemy/elements/_sitemap_editor.html.erb +0 -3
- data/app/views/alchemy/elements/_sitemap_view.html.erb +0 -38
- data/app/views/alchemy/elements/_sitename_editor.html.erb +0 -1
- data/app/views/alchemy/elements/_sitename_view.html.erb +0 -1
- data/app/views/alchemy/elements/_subheadline_editor.html.erb +0 -1
- data/app/views/alchemy/elements/_subheadline_view.html.erb +0 -5
- data/app/views/alchemy/elements/_text_editor.html.erb +0 -1
- data/app/views/alchemy/elements/_text_view.html.erb +0 -3
- data/app/views/alchemy/page_layouts/_contact.html.erb +0 -14
- data/app/views/alchemy/page_layouts/_external.html.erb +0 -0
- data/app/views/alchemy/page_layouts/_intro.html.erb +0 -14
- data/app/views/alchemy/page_layouts/_layout_footer.html.erb +0 -14
- data/app/views/alchemy/page_layouts/_layout_header.html.erb +0 -14
- data/app/views/alchemy/page_layouts/_news.html.erb +0 -14
- data/app/views/alchemy/page_layouts/_newsletter_layout.html.erb +0 -1
- data/app/views/alchemy/page_layouts/_search.html.erb +0 -14
- data/app/views/alchemy/pictures/show.gif.flexi +0 -19
- data/app/views/alchemy/pictures/show.jpg.flexi +0 -19
- data/app/views/alchemy/pictures/show.png.flexi +0 -19
- data/app/views/alchemy/pictures/thumbnail.png.flexi +0 -13
- data/app/views/alchemy/pictures/zoom.jpg.flexi +0 -3
- data/app/views/alchemy/pictures/zoom.png.flexi +0 -3
- data/app/views/layouts/alchemy/pages.html.erb +0 -51
- data/config/alchemy/elements.yml +0 -274
- data/config/alchemy/page_layouts.yml +0 -75
- data/config/asset_packages.yml +0 -30
- data/config/initializers/localeapp.rb +0 -9
- data/lib/rails/generators/alchemy/plugin/files/translation.pot +0 -3
- data/lib/rails/generators/alchemy/plugin/files/translation_de.po +0 -3
- data/lib/rails/generators/alchemy/plugin/files/translation_en.po +0 -3
- data/lib/rails/generators/alchemy/plugin/plugin_generator.rb +0 -37
- data/lib/rails/generators/alchemy/plugin/templates/authorization_rules.rb +0 -34
- data/lib/rails/generators/alchemy/plugin/templates/config.yml +0 -30
- data/lib/rails/generators/alchemy/plugin/templates/init.rb +0 -1
- data/lib/rails/generators/alchemy/plugin/templates/plugin.rb +0 -0
- data/lib/rails/generators/alchemy/plugin/templates/routes.rb +0 -10
- data/lib/tasks/fleximage.rake +0 -154
- data/spec/dummy/app/views/layouts/.gitkeep +0 -0
@@ -3,8 +3,6 @@ module Alchemy
|
|
3
3
|
|
4
4
|
include Alchemy::BaseHelper
|
5
5
|
include Alchemy::ElementsHelper
|
6
|
-
include Alchemy::ElementsBlockHelper
|
7
|
-
include Alchemy::UrlHelper
|
8
6
|
|
9
7
|
def render_classes(classes=[])
|
10
8
|
s = classes.uniq.delete_if { |x| x.blank? }.join(" ")
|
@@ -445,19 +443,41 @@ module Alchemy
|
|
445
443
|
javascript_include_tag("alchemy/preview") if @preview_mode
|
446
444
|
end
|
447
445
|
|
448
|
-
# Renders
|
446
|
+
# Renders a search form
|
447
|
+
#
|
448
|
+
# It queries the controller and then redirects to the search result page.
|
449
|
+
#
|
450
|
+
# === Example search results page layout
|
451
|
+
#
|
452
|
+
# Only performs the search if ferret is enabled in your +config/alchemy/config.yml+ and
|
453
|
+
# a page is present that is flagged with +searchresults+ true.
|
454
|
+
#
|
455
|
+
# # config/alchemy/page_layouts.yml
|
456
|
+
# - name: search
|
457
|
+
# searchresults: true # Flag as search result page
|
458
|
+
#
|
459
|
+
# === Note
|
460
|
+
#
|
461
|
+
# The search result page will not be cached.
|
462
|
+
#
|
463
|
+
# @option options html5 [Boolean] (true) Should the search form be of type search or not?
|
464
|
+
# @option options class [String] (fulltext_search) The default css class of the form
|
465
|
+
# @option options id [String] (search) The default css id of the form
|
466
|
+
#
|
449
467
|
def render_search_form(options={})
|
450
468
|
default_options = {
|
451
|
-
:html5 => false
|
469
|
+
:html5 => false,
|
470
|
+
:class => 'fulltext_search',
|
471
|
+
:id => 'search'
|
452
472
|
}
|
453
|
-
|
454
|
-
warning("No search result page found")
|
455
|
-
return
|
456
|
-
end
|
457
|
-
render :partial => 'alchemy/search/form', :locals => {:options => default_options.merge(options)}
|
473
|
+
render :partial => 'alchemy/search/form', :locals => {:options => default_options.merge(options), :search_result_page => find_search_result_page}
|
458
474
|
end
|
459
475
|
|
460
|
-
# Renders the search
|
476
|
+
# Renders the search results partial within +app/views/alchemy/search/_results.html+
|
477
|
+
#
|
478
|
+
# @option options show_result_count [Boolean] (true) Should the count of results be displayed or not?
|
479
|
+
# @option options show_heading [Boolean] (true) Should the heading be displayed or not?
|
480
|
+
#
|
461
481
|
def render_search_results(options={})
|
462
482
|
default_options = {
|
463
483
|
:show_result_count => true,
|
@@ -76,6 +76,7 @@ module Alchemy
|
|
76
76
|
|
77
77
|
# Returns the correct params-hash for passing to show_page_path
|
78
78
|
def show_page_path_params(page, optional_params={})
|
79
|
+
raise ArgumentError, 'Page is nil' if page.nil?
|
79
80
|
url_params = {:level1 => nil, :level2 => nil, :level3 => nil, :urlname => page.urlname}
|
80
81
|
url_params.update(optional_params)
|
81
82
|
url_params.update(params_for_nested_url(page)) if configuration(:url_nesting)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Alchemy
|
2
2
|
class Element < ActiveRecord::Base
|
3
3
|
|
4
|
-
FORBIDDEN_DEFINITION_ATTRIBUTES = %w(contents available_contents amount picture_gallery taggable)
|
4
|
+
FORBIDDEN_DEFINITION_ATTRIBUTES = %w(contents available_contents amount picture_gallery taggable hint)
|
5
5
|
SKIPPED_ATTRIBUTES_ON_COPY = %w(id position folded created_at updated_at creator_id updater_id cached_tag_list)
|
6
6
|
|
7
7
|
acts_as_taggable
|
@@ -12,7 +12,6 @@ module Alchemy
|
|
12
12
|
:folded,
|
13
13
|
:name,
|
14
14
|
:page_id,
|
15
|
-
:position,
|
16
15
|
:public,
|
17
16
|
:tag_list,
|
18
17
|
:unique
|
@@ -29,6 +28,7 @@ module Alchemy
|
|
29
28
|
|
30
29
|
validates_uniqueness_of :position, :scope => [:page_id, :cell_id], :if => lambda { |e| e.position != nil }
|
31
30
|
validates_presence_of :name, :on => :create
|
31
|
+
validates_format_of :name, :on => :create, :with => /\A[a-z0-9_-]+\z/
|
32
32
|
|
33
33
|
attr_accessor :create_contents_after_create
|
34
34
|
|
@@ -37,6 +37,7 @@ module Alchemy
|
|
37
37
|
scope :trashed, where(:position => nil).order('updated_at DESC')
|
38
38
|
scope :not_trashed, where(Element.arel_table[:position].not_eq(nil))
|
39
39
|
scope :published, where(:public => true)
|
40
|
+
scope :not_restricted, joins(:page).where("alchemy_pages" => {:restricted => false})
|
40
41
|
scope :available, published.not_trashed
|
41
42
|
scope :named, lambda { |names| where(:name => names) }
|
42
43
|
scope :excluded, lambda { |names| where(arel_table[:name].not_in(names)) }
|
@@ -510,6 +511,50 @@ module Alchemy
|
|
510
511
|
description['taggable'] == true
|
511
512
|
end
|
512
513
|
|
514
|
+
def to_partial_path
|
515
|
+
"alchemy/elements/#{name}_view"
|
516
|
+
end
|
517
|
+
|
518
|
+
# Returns the hint for this element
|
519
|
+
#
|
520
|
+
# To add a hint to an element either pass +hint: true+ to the element definition in its element.yml
|
521
|
+
#
|
522
|
+
# Then the hint itself is placed in the locale yml files.
|
523
|
+
#
|
524
|
+
# Alternativly you can pass the hint itself to the hint key.
|
525
|
+
#
|
526
|
+
# == Locale Example:
|
527
|
+
#
|
528
|
+
# # elements.yml
|
529
|
+
# - name: headline
|
530
|
+
# hint: true
|
531
|
+
#
|
532
|
+
# # config/locales/de.yml
|
533
|
+
# de:
|
534
|
+
# element_hints:
|
535
|
+
# headline: Lorem ipsum
|
536
|
+
#
|
537
|
+
# == Hint Key Example:
|
538
|
+
#
|
539
|
+
# - name: headline
|
540
|
+
# hint: "Lorem ipsum"
|
541
|
+
#
|
542
|
+
# @return String
|
543
|
+
#
|
544
|
+
def hint
|
545
|
+
hint = definition['hint']
|
546
|
+
if hint == true
|
547
|
+
I18n.t(name, scope: :element_hints)
|
548
|
+
else
|
549
|
+
hint
|
550
|
+
end
|
551
|
+
end
|
552
|
+
|
553
|
+
# Returns true if the element has a hint
|
554
|
+
def has_hint?
|
555
|
+
hint.present?
|
556
|
+
end
|
557
|
+
|
513
558
|
private
|
514
559
|
|
515
560
|
# creates the contents for this element as described in the elements.yml
|
@@ -9,17 +9,19 @@ module Alchemy
|
|
9
9
|
:public,
|
10
10
|
:default,
|
11
11
|
:country_code,
|
12
|
-
:code
|
12
|
+
:code,
|
13
|
+
:site
|
13
14
|
)
|
14
15
|
|
15
16
|
validates_presence_of :name
|
16
17
|
validates_presence_of :language_code
|
17
18
|
validates_presence_of :page_layout
|
18
19
|
validates_presence_of :frontpage_name
|
19
|
-
validates_uniqueness_of :language_code, :scope => :country_code
|
20
|
+
validates_uniqueness_of :language_code, :scope => [:site_id, :country_code]
|
20
21
|
validate :presence_of_default_language
|
21
22
|
validate :publicity_of_default_language
|
22
23
|
has_many :pages
|
24
|
+
belongs_to :site
|
23
25
|
after_destroy :delete_language_root_page
|
24
26
|
validates_format_of :language_code, :with => /^[a-z]{2}$/, :if => proc { language_code.present? }
|
25
27
|
validates_format_of :country_code, :with => /^[a-z]{2}$/, :if => proc { country_code.present? }
|
@@ -30,18 +32,29 @@ module Alchemy
|
|
30
32
|
|
31
33
|
scope :published, where(:public => true)
|
32
34
|
|
33
|
-
|
34
|
-
|
35
|
-
|
35
|
+
# multi-site support
|
36
|
+
scope :on_site, lambda { |s| s.present? ? where(site_id: s) : scoped }
|
37
|
+
default_scope { on_site(Site.current) }
|
36
38
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
39
|
+
class << self
|
40
|
+
|
41
|
+
# Returns all languages for which a language root page exists.
|
42
|
+
def all_for_created_language_trees
|
43
|
+
# don't use 'find' here as it would clash with our default_scopes
|
44
|
+
# in various unholy ways you don't want to find out about.
|
45
|
+
where(id: Page.language_roots.collect(&:language_id))
|
46
|
+
end
|
47
|
+
|
48
|
+
def all_codes_for_published
|
49
|
+
published.collect(&:code)
|
50
|
+
rescue
|
51
|
+
[]
|
52
|
+
end
|
53
|
+
|
54
|
+
def get_default
|
55
|
+
where(default: true).first
|
56
|
+
end
|
42
57
|
|
43
|
-
def self.get_default
|
44
|
-
self.find_by_default(true)
|
45
58
|
end
|
46
59
|
|
47
60
|
def label(attrib)
|
@@ -54,7 +67,7 @@ module Alchemy
|
|
54
67
|
|
55
68
|
include Code
|
56
69
|
|
57
|
-
|
70
|
+
private
|
58
71
|
|
59
72
|
def publicity_of_default_language
|
60
73
|
if self.default? && !self.public?
|
@@ -75,7 +88,7 @@ module Alchemy
|
|
75
88
|
end
|
76
89
|
|
77
90
|
def remove_old_default
|
78
|
-
lang = Language.get_default
|
91
|
+
lang = Language.on_site(site).get_default
|
79
92
|
return true if lang.nil?
|
80
93
|
lang.default = false
|
81
94
|
lang.save(:validate => false)
|
data/app/models/alchemy/page.rb
CHANGED
@@ -28,7 +28,6 @@ module Alchemy
|
|
28
28
|
:name,
|
29
29
|
:page_layout,
|
30
30
|
:parent_id,
|
31
|
-
:position,
|
32
31
|
:public,
|
33
32
|
:restricted,
|
34
33
|
:robot_index,
|
@@ -52,6 +51,7 @@ module Alchemy
|
|
52
51
|
has_and_belongs_to_many :to_be_sweeped_elements, :class_name => 'Alchemy::Element', :uniq => true, :join_table => 'alchemy_elements_alchemy_pages'
|
53
52
|
belongs_to :language
|
54
53
|
|
54
|
+
validates_presence_of :language, :on => :create, :unless => :root
|
55
55
|
validates_presence_of :name
|
56
56
|
validates_presence_of :page_layout, :unless => :systempage?
|
57
57
|
validates_presence_of :parent_id, :if => proc { Page.count > 1 }
|
@@ -6,27 +6,28 @@ module Alchemy
|
|
6
6
|
has_many :elements, :through => :contents
|
7
7
|
has_many :pages, :through => :elements
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
9
|
+
# Raise error, if picture is in use (aka. assigned to an EssencePicture)
|
10
|
+
#
|
11
|
+
# === CAUTION:
|
12
|
+
# This HAS to be placed for Dragonfly's class methods, to ensure this runs before Dragonfly's before_destroy callback.
|
13
|
+
#
|
14
|
+
before_destroy :unless => :deletable? do
|
15
|
+
raise PictureInUseError, I18n.t(:cannot_delete_picture_notice) % { :name => name }
|
16
|
+
end
|
17
|
+
|
18
|
+
image_accessor :image_file do
|
19
|
+
if Config.get(:preprocess_image_resize).present?
|
20
|
+
after_assign { |a| a.process!(:resize, Config.get(:preprocess_image_resize)) }
|
20
21
|
end
|
21
22
|
end
|
22
23
|
|
24
|
+
validates_presence_of :image_file
|
25
|
+
validates_property :format, :of => :image_file, :in => Config.get('uploader')['allowed_filetypes']['pictures'].map(&:to_sym), :message => I18n.t("not a valid image")
|
26
|
+
|
23
27
|
acts_as_taggable
|
24
28
|
|
25
29
|
attr_accessible(
|
26
30
|
:image_file,
|
27
|
-
:image_filename,
|
28
|
-
:image_height,
|
29
|
-
:image_width,
|
30
31
|
:name,
|
31
32
|
:tag_list,
|
32
33
|
:upload_hash
|
@@ -35,6 +36,7 @@ module Alchemy
|
|
35
36
|
stampable(:stamper_class_name => 'Alchemy::User')
|
36
37
|
|
37
38
|
scope :recent, where("#{self.table_name}.created_at > ?", Time.now-24.hours).order(:created_at)
|
39
|
+
scope :deletable, where("alchemy_pictures.id NOT IN (SELECT picture_id FROM alchemy_essence_pictures)")
|
38
40
|
|
39
41
|
def self.find_paginated(params, per_page)
|
40
42
|
Picture.where("name LIKE ?", "%#{params[:query]}%").page(params[:page] || 1).per(per_page).order(:name)
|
@@ -60,32 +62,31 @@ module Alchemy
|
|
60
62
|
end
|
61
63
|
|
62
64
|
def suffix
|
63
|
-
|
64
|
-
image_filename.split('.').last.downcase
|
65
|
-
else
|
66
|
-
""
|
67
|
-
end
|
65
|
+
image_file.ext
|
68
66
|
end
|
69
67
|
|
70
68
|
def humanized_name
|
71
|
-
return "" if
|
72
|
-
(
|
69
|
+
return "" if image_file_name.blank?
|
70
|
+
(image_file_name.downcase.gsub(/\.#{::Regexp.quote(suffix)}$/, '')).humanize
|
73
71
|
end
|
74
72
|
|
75
73
|
# Returning true if picture's width is greater than it's height
|
76
74
|
def landscape_format?
|
77
|
-
|
75
|
+
image_file.landscape?
|
78
76
|
end
|
77
|
+
alias_method :landscape?, :landscape_format?
|
79
78
|
|
80
79
|
# Returning true if picture's width is smaller than it's height
|
81
80
|
def portrait_format?
|
82
|
-
|
81
|
+
image_file.portrait?
|
83
82
|
end
|
83
|
+
alias_method :portrait?, :portrait_format?
|
84
84
|
|
85
85
|
# Returning true if picture's width and height is equal
|
86
86
|
def square_format?
|
87
|
-
|
87
|
+
image_file.aspect_ratio == 1.0
|
88
88
|
end
|
89
|
+
alias_method :square?, :square_format?
|
89
90
|
|
90
91
|
# Returns the default centered image mask for a given size
|
91
92
|
def default_mask(size)
|
@@ -93,24 +94,24 @@ module Alchemy
|
|
93
94
|
width = size.split('x')[0].to_i
|
94
95
|
height = size.split('x')[1].to_i
|
95
96
|
if (width > height)
|
96
|
-
zoom_factor =
|
97
|
+
zoom_factor = image_file_width.to_f / width
|
97
98
|
mask_height = (height * zoom_factor).round
|
98
99
|
x1 = 0
|
99
|
-
x2 =
|
100
|
-
y1 = (
|
100
|
+
x2 = image_file_width
|
101
|
+
y1 = (image_file_height - mask_height) / 2
|
101
102
|
y2 = y1 + mask_height
|
102
103
|
elsif (width == 0 && height == 0)
|
103
104
|
x1 = 0
|
104
|
-
x2 =
|
105
|
+
x2 = image_file_width
|
105
106
|
y1 = 0
|
106
|
-
y2 =
|
107
|
+
y2 = image_file_height
|
107
108
|
else
|
108
|
-
zoom_factor =
|
109
|
+
zoom_factor = image_file_height.to_f / height
|
109
110
|
mask_width = (width * zoom_factor).round
|
110
|
-
x1 = (
|
111
|
+
x1 = (image_file_width - mask_width) / 2
|
111
112
|
x2 = x1 + mask_width
|
112
113
|
y1 = 0
|
113
|
-
y2 =
|
114
|
+
y2 = image_file_height
|
114
115
|
end
|
115
116
|
{
|
116
117
|
:x1 => x1,
|
@@ -141,6 +142,14 @@ module Alchemy
|
|
141
142
|
pages.any? && pages.not_restricted.blank?
|
142
143
|
end
|
143
144
|
|
145
|
+
def deletable?
|
146
|
+
!essence_pictures.any?
|
147
|
+
end
|
148
|
+
|
149
|
+
def image_file_dimensions
|
150
|
+
"#{image_file_width} x #{image_file_height}"
|
151
|
+
end
|
152
|
+
|
144
153
|
# Returns a security token for signed picture rendering requests.
|
145
154
|
#
|
146
155
|
# Pass a params hash containing:
|
@@ -149,21 +158,17 @@ module Alchemy
|
|
149
158
|
# crop [Boolean] (Optional)
|
150
159
|
# crop_from [String] (Optional)
|
151
160
|
# crop_size [String] (Optional)
|
161
|
+
# quality [Integer] (Optional)
|
152
162
|
#
|
153
163
|
# to sign them.
|
154
164
|
#
|
155
165
|
def security_token(params = {})
|
156
166
|
@params = params.stringify_keys
|
157
|
-
@params.update({'crop' => @params['crop'] ? 'crop' : nil})
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
private
|
162
|
-
|
163
|
-
def secured_params
|
164
|
-
secret = Rails.configuration.secret_token
|
165
|
-
[id, @params['size'], @params['crop'], @params['crop_from'], @params['crop_size'], secret].join('-')
|
167
|
+
@params.update({'crop' => @params['crop'] ? 'crop' : nil, 'id' => self.id})
|
168
|
+
@params.delete_if { |k,v| v.nil? }
|
169
|
+
PictureAttributes.secure(@params)
|
166
170
|
end
|
167
171
|
|
168
172
|
end
|
173
|
+
class PictureInUseError < StandardError; end
|
169
174
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Alchemy
|
2
|
+
class Site < ActiveRecord::Base
|
3
|
+
cattr_accessor :current
|
4
|
+
|
5
|
+
attr_accessible :host, :name, :public
|
6
|
+
|
7
|
+
# validations
|
8
|
+
validates_presence_of :host
|
9
|
+
validates_uniqueness_of :host
|
10
|
+
|
11
|
+
# associations
|
12
|
+
has_many :languages
|
13
|
+
|
14
|
+
scope :published, where(public: true)
|
15
|
+
|
16
|
+
# Returns true if this site is the current site
|
17
|
+
def current?
|
18
|
+
self.class.current == self
|
19
|
+
end
|
20
|
+
|
21
|
+
class << self
|
22
|
+
def default
|
23
|
+
Site.first
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
before_create do
|
28
|
+
# If no languages are present, create a default language based
|
29
|
+
# on the host app's Alchemy configuration.
|
30
|
+
|
31
|
+
if languages.empty?
|
32
|
+
default_language = Alchemy::Config.get(:default_language)
|
33
|
+
languages.build(
|
34
|
+
name: default_language['name'],
|
35
|
+
language_code: default_language['code'],
|
36
|
+
frontpage_name: default_language['frontpage_name'],
|
37
|
+
page_layout: default_language['page_layout'],
|
38
|
+
public: true,
|
39
|
+
default: true
|
40
|
+
)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|