locomotivecms_mounter_pull_19 1.5.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (84) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +12 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +4 -0
  5. data/Gemfile +7 -0
  6. data/Gemfile.lock +131 -0
  7. data/MIT-LICENSE +20 -0
  8. data/NOTES +4 -0
  9. data/README.md +26 -0
  10. data/Rakefile +37 -0
  11. data/TODO +82 -0
  12. data/init.rb +2 -0
  13. data/lib/locomotive/mounter.rb +106 -0
  14. data/lib/locomotive/mounter/config.rb +21 -0
  15. data/lib/locomotive/mounter/engine_api.rb +205 -0
  16. data/lib/locomotive/mounter/exceptions.rb +44 -0
  17. data/lib/locomotive/mounter/extensions/compass.rb +38 -0
  18. data/lib/locomotive/mounter/extensions/httmultiparty.rb +22 -0
  19. data/lib/locomotive/mounter/extensions/sprockets.rb +46 -0
  20. data/lib/locomotive/mounter/extensions/tilt/css.rb +31 -0
  21. data/lib/locomotive/mounter/fields.rb +254 -0
  22. data/lib/locomotive/mounter/models/base.rb +42 -0
  23. data/lib/locomotive/mounter/models/content_asset.rb +84 -0
  24. data/lib/locomotive/mounter/models/content_entry.rb +372 -0
  25. data/lib/locomotive/mounter/models/content_field.rb +190 -0
  26. data/lib/locomotive/mounter/models/content_select_option.rb +29 -0
  27. data/lib/locomotive/mounter/models/content_type.rb +274 -0
  28. data/lib/locomotive/mounter/models/editable_element.rb +27 -0
  29. data/lib/locomotive/mounter/models/page.rb +442 -0
  30. data/lib/locomotive/mounter/models/site.rb +28 -0
  31. data/lib/locomotive/mounter/models/snippet.rb +55 -0
  32. data/lib/locomotive/mounter/models/theme_asset.rb +148 -0
  33. data/lib/locomotive/mounter/models/translation.rb +28 -0
  34. data/lib/locomotive/mounter/mounting_point.rb +65 -0
  35. data/lib/locomotive/mounter/reader/api.rb +64 -0
  36. data/lib/locomotive/mounter/reader/api/base.rb +67 -0
  37. data/lib/locomotive/mounter/reader/api/content_assets_reader.rb +39 -0
  38. data/lib/locomotive/mounter/reader/api/content_entries_reader.rb +142 -0
  39. data/lib/locomotive/mounter/reader/api/content_types_reader.rb +76 -0
  40. data/lib/locomotive/mounter/reader/api/pages_reader.rb +192 -0
  41. data/lib/locomotive/mounter/reader/api/site_reader.rb +42 -0
  42. data/lib/locomotive/mounter/reader/api/snippets_reader.rb +61 -0
  43. data/lib/locomotive/mounter/reader/api/theme_assets_reader.rb +42 -0
  44. data/lib/locomotive/mounter/reader/api/translations_reader.rb +30 -0
  45. data/lib/locomotive/mounter/reader/file_system.rb +43 -0
  46. data/lib/locomotive/mounter/reader/file_system/base.rb +65 -0
  47. data/lib/locomotive/mounter/reader/file_system/content_assets_reader.rb +90 -0
  48. data/lib/locomotive/mounter/reader/file_system/content_entries_reader.rb +97 -0
  49. data/lib/locomotive/mounter/reader/file_system/content_types_reader.rb +88 -0
  50. data/lib/locomotive/mounter/reader/file_system/pages_reader.rb +211 -0
  51. data/lib/locomotive/mounter/reader/file_system/site_reader.rb +27 -0
  52. data/lib/locomotive/mounter/reader/file_system/snippets_reader.rb +115 -0
  53. data/lib/locomotive/mounter/reader/file_system/theme_assets_reader.rb +83 -0
  54. data/lib/locomotive/mounter/reader/file_system/translations_reader.rb +36 -0
  55. data/lib/locomotive/mounter/reader/runner.rb +89 -0
  56. data/lib/locomotive/mounter/utils/hash.rb +31 -0
  57. data/lib/locomotive/mounter/utils/output.rb +124 -0
  58. data/lib/locomotive/mounter/utils/string.rb +40 -0
  59. data/lib/locomotive/mounter/utils/yaml.rb +125 -0
  60. data/lib/locomotive/mounter/utils/yaml_front_matters_template.rb +45 -0
  61. data/lib/locomotive/mounter/version.rb +8 -0
  62. data/lib/locomotive/mounter/writer/api.rb +74 -0
  63. data/lib/locomotive/mounter/writer/api/base.rb +172 -0
  64. data/lib/locomotive/mounter/writer/api/content_assets_writer.rb +74 -0
  65. data/lib/locomotive/mounter/writer/api/content_entries_writer.rb +227 -0
  66. data/lib/locomotive/mounter/writer/api/content_types_writer.rb +151 -0
  67. data/lib/locomotive/mounter/writer/api/pages_writer.rb +250 -0
  68. data/lib/locomotive/mounter/writer/api/site_writer.rb +125 -0
  69. data/lib/locomotive/mounter/writer/api/snippets_writer.rb +111 -0
  70. data/lib/locomotive/mounter/writer/api/theme_assets_writer.rb +201 -0
  71. data/lib/locomotive/mounter/writer/api/translations_writer.rb +85 -0
  72. data/lib/locomotive/mounter/writer/file_system.rb +44 -0
  73. data/lib/locomotive/mounter/writer/file_system/base.rb +70 -0
  74. data/lib/locomotive/mounter/writer/file_system/content_assets_writer.rb +38 -0
  75. data/lib/locomotive/mounter/writer/file_system/content_entries_writer.rb +33 -0
  76. data/lib/locomotive/mounter/writer/file_system/content_types_writer.rb +32 -0
  77. data/lib/locomotive/mounter/writer/file_system/pages_writer.rb +93 -0
  78. data/lib/locomotive/mounter/writer/file_system/site_writer.rb +30 -0
  79. data/lib/locomotive/mounter/writer/file_system/snippets_writer.rb +59 -0
  80. data/lib/locomotive/mounter/writer/file_system/theme_assets_writer.rb +72 -0
  81. data/lib/locomotive/mounter/writer/file_system/translations_writer.rb +29 -0
  82. data/lib/locomotive/mounter/writer/runner.rb +73 -0
  83. data/locomotivecms_mounter.gemspec +64 -0
  84. metadata +539 -0
@@ -0,0 +1,42 @@
1
+ module Locomotive
2
+ module Mounter
3
+ module Reader
4
+ module Api
5
+
6
+ class SiteReader < Base
7
+
8
+ def read
9
+ super
10
+
11
+ # get the site from the API
12
+ site = self.get(:current_site)
13
+
14
+ # set the default locale first
15
+ Locomotive::Mounter.locale = site['locales'].first.to_sym
16
+
17
+ Locomotive::Mounter::Models::Site.new(site).tap do |site|
18
+ # fetch the information in other locales
19
+ site.locales[1..-1].each do |locale|
20
+ Locomotive::Mounter.with_locale(locale) do
21
+ self.get(:current_site, locale).each do |name, value|
22
+ next unless %w(seo_title meta_keywords meta_description).include?(name)
23
+ site.send(:"#{name}=", value)
24
+ end
25
+ end
26
+ end
27
+
28
+ # set the time zone for the next Time operations (UTC by default)
29
+ Time.zone = ActiveSupport::TimeZone.new(site.timezone || 'UTC')
30
+ end
31
+ end
32
+
33
+ def safe_attributes
34
+ %w(name locales seo_title meta_keywords meta_description domains subdomain timezone created_at updated_at)
35
+ end
36
+
37
+ end
38
+
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,61 @@
1
+ module Locomotive
2
+ module Mounter
3
+ module Reader
4
+ module Api
5
+
6
+ class SnippetsReader < Base
7
+
8
+ # Build the list of snippets from the folder on the file system.
9
+ #
10
+ # @return [ Array ] The un-ordered list of snippets
11
+ #
12
+ def read
13
+ super
14
+
15
+ self.fetch
16
+
17
+ self.items
18
+ end
19
+
20
+ protected
21
+
22
+ # Record snippets found in file system
23
+ def fetch
24
+ self.get(:snippets).each do |attributes|
25
+ snippet = self.add(attributes.delete('slug'), attributes)
26
+
27
+ self.mounting_point.locales[1..-1].each do |locale|
28
+ Locomotive::Mounter.with_locale(locale) do
29
+ localized_attributes = self.get("snippets/#{snippet._id}", locale)
30
+ snippet.attributes = localized_attributes
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ # Add a new snippet in the global hash of snippets.
37
+ # If the snippet exists, it returns it.
38
+
39
+ # @param [ String ] slug The slug of the snippet
40
+ # @param [ Hash ] attributes The attributes of the snippet
41
+ #
42
+ # @return [ Object ] A newly created snippet or the existing one
43
+ #
44
+ def add(slug, attributes)
45
+ unless self.items.key?(slug)
46
+ self.items[slug] = Locomotive::Mounter::Models::Snippet.new(attributes)
47
+ end
48
+
49
+ self.items[slug]
50
+ end
51
+
52
+ def safe_attributes
53
+ %w(_id name slug template created_at updated_at)
54
+ end
55
+
56
+ end
57
+
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,42 @@
1
+ module Locomotive
2
+ module Mounter
3
+ module Reader
4
+ module Api
5
+
6
+ class ThemeAssetsReader < Base
7
+
8
+ def initialize(runner)
9
+ super
10
+ self.items = []
11
+ end
12
+
13
+ # Build the list of theme assets from the public folder with eager loading.
14
+ #
15
+ # @return [ Array ] The cached list of theme assets
16
+ #
17
+ def read
18
+ super
19
+
20
+ self.items = self.get(:theme_assets).map do |attributes|
21
+ url = attributes.delete('url')
22
+ url.gsub!(/^\/\//, "https://")
23
+
24
+ attributes['uri'] = URI(url =~ /^https?:\/\// ? url : "#{self.base_uri_with_scheme}#{url}")
25
+
26
+ Locomotive::Mounter::Models::ThemeAsset.new(attributes)
27
+ end
28
+ end
29
+
30
+ protected
31
+
32
+ def safe_attributes
33
+ %w(_id folder url created_at updated_at)
34
+ end
35
+
36
+ end
37
+
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,30 @@
1
+ module Locomotive
2
+ module Mounter
3
+ module Reader
4
+ module Api
5
+
6
+ class TranslationsReader < Base
7
+
8
+ # Build the list of translations
9
+ #
10
+ # @return [ Array ] The cached list of theme assets
11
+ #
12
+ def read
13
+ super
14
+
15
+ self.items = get(:translations).each_with_object({}) do |attributes,hash|
16
+ hash[attributes['key']] = Locomotive::Mounter::Models::Translation.new(attributes)
17
+ end
18
+ end
19
+
20
+ protected
21
+ def safe_attributes
22
+ %w[_id key values created_at updated_at]
23
+ end
24
+ end
25
+
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,43 @@
1
+ module Locomotive
2
+ module Mounter
3
+ module Reader
4
+ module FileSystem
5
+
6
+ # Build a singleton instance of the Runner class.
7
+ #
8
+ # @return [ Object ] A singleton instance of the Runner class
9
+ #
10
+ def self.instance
11
+ @@instance ||= Runner.new(:file_system)
12
+ end
13
+
14
+ class Runner < Locomotive::Mounter::Reader::Runner
15
+
16
+ attr_accessor :path
17
+
18
+ # Compass is required
19
+ def prepare
20
+ self.path = parameters.delete(:path)
21
+
22
+ if self.path.blank? || !File.exists?(self.path)
23
+ raise Locomotive::Mounter::ReaderException.new('path is required and must exist')
24
+ end
25
+
26
+ # TODO: Steam should deal with that
27
+ Locomotive::Mounter::Extensions::Compass.configure(self.path)
28
+ end
29
+
30
+ # Ordered list of atomic readers
31
+ #
32
+ # @return [ Array ] List of classes
33
+ #
34
+ def readers
35
+ [SiteReader, ContentTypesReader, PagesReader, SnippetsReader, ContentEntriesReader, ContentAssetsReader, ThemeAssetsReader, TranslationsReader]
36
+ end
37
+
38
+ end
39
+
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,65 @@
1
+ module Locomotive
2
+ module Mounter
3
+ module Reader
4
+ module FileSystem
5
+
6
+ class Base
7
+
8
+ attr_accessor :runner, :items
9
+
10
+ delegate :default_locale, :locales, to: :mounting_point
11
+
12
+ def initialize(runner)
13
+ self.runner = runner
14
+ self.items = {}
15
+ end
16
+
17
+ def mounting_point
18
+ self.runner.mounting_point
19
+ end
20
+
21
+ protected
22
+
23
+ # Return the locale of a file based on its extension.
24
+ #
25
+ # Ex:
26
+ # about_us/john_doe.fr.liquid.haml => 'fr'
27
+ # about_us/john_doe.liquid.haml => 'en' (default locale)
28
+ #
29
+ # @param [ String ] filepath The path to the file
30
+ #
31
+ # @return [ String ] The locale (ex: fr, en, ...etc) or nil if it has no information about the locale
32
+ #
33
+ def filepath_locale(filepath)
34
+ locale = File.basename(filepath).split('.')[1]
35
+
36
+ if locale.nil?
37
+ # no locale, use the default one
38
+ self.default_locale
39
+ elsif self.locales.include?(locale)
40
+ # the locale is registered
41
+ locale
42
+ elsif locale.size == 2
43
+ # unregistered locale
44
+ nil
45
+ else
46
+ self.default_locale
47
+ end
48
+ end
49
+
50
+ # Open a YAML file and returns the content of the file
51
+ #
52
+ # @param [ String ] filepath The path to the file
53
+ #
54
+ # @return [ Object ] The content of the file
55
+ #
56
+ def read_yaml(filepath)
57
+ YAML::load(File.open(filepath).read.force_encoding('utf-8'))
58
+ end
59
+
60
+ end
61
+
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,90 @@
1
+ module Locomotive
2
+ module Mounter
3
+ module Reader
4
+ module FileSystem
5
+
6
+ class ContentAssetsReader < Base
7
+
8
+ # Build the list of contents assets
9
+ #
10
+ # @return [ Array ] The list of content assets
11
+ #
12
+ def read
13
+ self.items = {} # prefer an array over a hash
14
+
15
+ self.fetch_from_pages
16
+
17
+ self.fetch_from_content_entries
18
+
19
+ self.items
20
+ end
21
+
22
+ protected
23
+
24
+ # Fetch the files from the template of all the pages
25
+ #
26
+ def fetch_from_pages
27
+ self.mounting_point.pages.values.each do |page|
28
+ page.translated_in.each do |locale|
29
+ Locomotive::Mounter.with_locale(locale) do
30
+ unless page.template.blank?
31
+ self.add_assets_from_string(page.template.raw_source)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+ # Fetch the files from the content entries
39
+ #
40
+ def fetch_from_content_entries
41
+ self.mounting_point.content_entries.values.each do |content_entry|
42
+ content_entry.translated_in.each do |locale|
43
+ Locomotive::Mounter.with_locale(locale) do
44
+ # get the string, text, file fields...
45
+ content_entry.content_type.fields.each do |field|
46
+ value = content_entry.dynamic_getter(field.name)
47
+
48
+ case field.type.to_sym
49
+ when :string, :text
50
+ self.add_assets_from_string(value)
51
+ when :file
52
+ self.add_assets_from_string(value['url']) if value
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+
60
+ # Parse the string passed in parameter in order to
61
+ # look for content assets. If found, then add them.
62
+ #
63
+ # @param [ String ] source The string to parse
64
+ #
65
+ def add_assets_from_string(source)
66
+ return if source.blank?
67
+
68
+ source.to_s.match(/\/samples\/.*\.[a-zA-Z0-9]+/) do |match|
69
+ filepath = File.join(self.root_dir, match.to_s)
70
+ folder = File.dirname(match.to_s)
71
+ self.items[source] = Locomotive::Mounter::Models::ContentAsset.new(filepath: filepath, folder: folder)
72
+ end
73
+ end
74
+
75
+ # Return the directory where all the theme assets
76
+ # are stored in the filesystem.
77
+ #
78
+ # @return [ String ] The theme assets directory
79
+ #
80
+ def root_dir
81
+ File.join(self.runner.path, 'public')
82
+ end
83
+
84
+ end
85
+
86
+ end
87
+
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,97 @@
1
+ module Locomotive
2
+ module Mounter
3
+ module Reader
4
+ module FileSystem
5
+
6
+ class ContentEntriesReader < Base
7
+
8
+ # Build the list of content types from the folder on the file system.
9
+ #
10
+ # @return [ Array ] The un-ordered list of content types
11
+ #
12
+ def read
13
+ self.fetch_from_filesystem
14
+
15
+ self.items
16
+ end
17
+
18
+ protected
19
+
20
+ def fetch_from_filesystem
21
+ Dir.glob(File.join(self.root_dir, '*.yml')).each do |filepath|
22
+ attributes = self.read_yaml(filepath)
23
+
24
+ content_type = self.get_content_type(File.basename(filepath, '.yml'))
25
+
26
+ content_type.entries.try(:clear)
27
+
28
+ attributes.each_with_index do |_attributes, index|
29
+ self.add(content_type, _attributes, index)
30
+ end unless attributes == false
31
+ end
32
+ end
33
+
34
+ # Get the content type identified by the slug from the mounting point.
35
+ # Raise an UnknownContentTypeException exception if such a content type
36
+ # does not exist.
37
+ #
38
+ # @param [ String ] slug The slug of the content type
39
+ #
40
+ # @return [ Object ] The instance of the content type
41
+ #
42
+ def get_content_type(slug)
43
+ self.mounting_point.content_types[slug.to_s].tap do |content_type|
44
+ if content_type.nil?
45
+ raise UnknownContentTypeException.new("unknow content type #{slug.inspect}")
46
+ end
47
+ end
48
+ end
49
+
50
+ # Add a content entry for a content type.
51
+ #
52
+ # @param [ Object ] content_type The content type
53
+ # @param [ Hash ] attributes The attributes of the content entry
54
+ # @param [ Integer ] position The position of the entry in the list
55
+ #
56
+ def add(content_type, attributes, position)
57
+ if attributes.is_a?(String)
58
+ label, _attributes = attributes, {}
59
+ else
60
+ label, _attributes = attributes.keys.first, attributes.values.first || {}
61
+ end
62
+
63
+ # check if the label_field is localized or not
64
+ label_field_name = content_type.label_field_name
65
+
66
+ if content_type.label_field.localized && _attributes.key?(label_field_name) && _attributes[label_field_name].is_a?(Hash)
67
+ _attributes[label_field_name].merge!(Locomotive::Mounter.locale => label).symbolize_keys!
68
+ else
69
+ _attributes[label_field_name] = label
70
+ end
71
+
72
+ _attributes[:_position] = position
73
+
74
+ # build the content entry
75
+ entry = content_type.build_entry(_attributes)
76
+
77
+ # and store it
78
+ key = File.join(content_type.slug, entry._slug)
79
+
80
+ self.items[key] = entry
81
+ end
82
+
83
+ # Return the directory where all the entries
84
+ # of the content types are stored.
85
+ #
86
+ # @return [ String ] The content entries root directory
87
+ #
88
+ def root_dir
89
+ File.join(self.runner.path, 'data')
90
+ end
91
+
92
+ end
93
+
94
+ end
95
+ end
96
+ end
97
+ end