radiant-clipped-extension-add-group 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (131) hide show
  1. data/LICENSE +22 -0
  2. data/README.md +184 -0
  3. data/Rakefile +109 -0
  4. data/app/controllers/admin/assets_controller.rb +66 -0
  5. data/app/controllers/admin/page_attachments_controller.rb +18 -0
  6. data/app/helpers/admin/assets_helper.rb +16 -0
  7. data/app/helpers/admin/page_attachments_helper.rb +2 -0
  8. data/app/models/asset.rb +237 -0
  9. data/app/models/asset_type.rb +241 -0
  10. data/app/models/old_page_attachment.rb +26 -0
  11. data/app/models/page_attachment.rb +20 -0
  12. data/app/views/admin/assets/_asset.html.haml +12 -0
  13. data/app/views/admin/assets/_asset_table.html.haml +33 -0
  14. data/app/views/admin/assets/_errors.html.haml +3 -0
  15. data/app/views/admin/assets/_form.html.haml +25 -0
  16. data/app/views/admin/assets/_page_assets.html.haml +12 -0
  17. data/app/views/admin/assets/_search.html.haml +17 -0
  18. data/app/views/admin/assets/_search_results.html.haml +17 -0
  19. data/app/views/admin/assets/edit.html.haml +41 -0
  20. data/app/views/admin/assets/index.html.haml +19 -0
  21. data/app/views/admin/assets/new.html.haml +24 -0
  22. data/app/views/admin/assets/refresh.html.haml +14 -0
  23. data/app/views/admin/assets/remove.html.haml +16 -0
  24. data/app/views/admin/configuration/_clipped_edit.html.haml +8 -0
  25. data/app/views/admin/configuration/_clipped_show.html.haml +12 -0
  26. data/app/views/admin/page_attachments/_attachment.html.haml +25 -0
  27. data/app/views/admin/page_parts/_page_part.html.haml +21 -0
  28. data/app/views/admin/pages/_asset_popups.html.haml +42 -0
  29. data/app/views/admin/pages/_assets.html.haml +11 -0
  30. data/app/views/admin/removed/_assets_bucket.html.haml +8 -0
  31. data/app/views/admin/removed/_assets_container.html.haml +58 -0
  32. data/app/views/admin/removed/_bucket.html.haml +11 -0
  33. data/app/views/admin/removed/_bucket_asset.html.haml +9 -0
  34. data/app/views/admin/removed/_show_bucket_link.html.haml +4 -0
  35. data/app/views/admin/removed/_upload_to_page.html.haml +12 -0
  36. data/app/views/admin/removed/bucket/_iframe.html.haml +1 -0
  37. data/artwork/icons.png +0 -0
  38. data/clipped_extension.rb +52 -0
  39. data/config/initializers/interpolation.rb +6 -0
  40. data/config/initializers/processors.rb +43 -0
  41. data/config/initializers/radiant_config.rb +65 -0
  42. data/config/locales/de.yml +109 -0
  43. data/config/locales/en.yml +110 -0
  44. data/config/locales/nl.yml +107 -0
  45. data/config/locales/ru.yml +110 -0
  46. data/config/routes.rb +8 -0
  47. data/cucumber.yml +1 -0
  48. data/db/migrate/001_create_assets.rb +12 -0
  49. data/db/migrate/002_create_paperclip_attributes.rb +13 -0
  50. data/db/migrate/003_create_user_observer.rb +13 -0
  51. data/db/migrate/004_create_page_attachments.rb +19 -0
  52. data/db/migrate/005_rename_users.rb +13 -0
  53. data/db/migrate/20110513205050_asset_uuid.rb +11 -0
  54. data/db/migrate/20110606111250_update_configuration.rb +34 -0
  55. data/db/migrate/20110609101438_dimensions.rb +13 -0
  56. data/db/migrate/20121024064452_add_group_to_assets.rb +9 -0
  57. data/features/support/env.rb +11 -0
  58. data/features/support/paths.rb +22 -0
  59. data/lib/asset_tags.rb +350 -0
  60. data/lib/clipped_admin_ui.rb +32 -0
  61. data/lib/cloud.rb +41 -0
  62. data/lib/generators/templates/clipped_config.rb +53 -0
  63. data/lib/page_asset_associations.rb +13 -0
  64. data/lib/paperclip/frame_grab.rb +73 -0
  65. data/lib/paperclip/geometry_transformation.rb +80 -0
  66. data/lib/radiant-clipped-extension.rb +8 -0
  67. data/lib/tasks/clipped_extension_tasks.rake +124 -0
  68. data/lib/tasks/paperclip_tasks.rake +79 -0
  69. data/public/flash/ZeroClipboard.swf +0 -0
  70. data/public/images/admin/assets/add.png +0 -0
  71. data/public/images/admin/assets/archive_icon.png +0 -0
  72. data/public/images/admin/assets/audio_icon.png +0 -0
  73. data/public/images/admin/assets/audio_thumbnail.png +0 -0
  74. data/public/images/admin/assets/c_icon.png +0 -0
  75. data/public/images/admin/assets/copy.png +0 -0
  76. data/public/images/admin/assets/css_icon.png +0 -0
  77. data/public/images/admin/assets/database_icon.png +0 -0
  78. data/public/images/admin/assets/delete.png +0 -0
  79. data/public/images/admin/assets/document_icon.png +0 -0
  80. data/public/images/admin/assets/document_thumbnail.png +0 -0
  81. data/public/images/admin/assets/flash_icon.png +0 -0
  82. data/public/images/admin/assets/flash_thumbnail.png +0 -0
  83. data/public/images/admin/assets/font_icon.png +0 -0
  84. data/public/images/admin/assets/gzip_icon.png +0 -0
  85. data/public/images/admin/assets/html_icon.png +0 -0
  86. data/public/images/admin/assets/image_icon.png +0 -0
  87. data/public/images/admin/assets/image_thumbnail.png +0 -0
  88. data/public/images/admin/assets/java_icon.png +0 -0
  89. data/public/images/admin/assets/page_edit.png +0 -0
  90. data/public/images/admin/assets/perl_icon.png +0 -0
  91. data/public/images/admin/assets/php_icon.png +0 -0
  92. data/public/images/admin/assets/presentation_icon.png +0 -0
  93. data/public/images/admin/assets/python_icon.png +0 -0
  94. data/public/images/admin/assets/reorder_assets.png +0 -0
  95. data/public/images/admin/assets/ruby_icon.png +0 -0
  96. data/public/images/admin/assets/script_icon.png +0 -0
  97. data/public/images/admin/assets/spreadsheet_icon.png +0 -0
  98. data/public/images/admin/assets/tar_icon.png +0 -0
  99. data/public/images/admin/assets/unknown_icon.png +0 -0
  100. data/public/images/admin/assets/unknown_thumbnail.png +0 -0
  101. data/public/images/admin/assets/video_icon.png +0 -0
  102. data/public/images/admin/assets/video_thumbnail.png +0 -0
  103. data/public/images/admin/assets/xml_icon.png +0 -0
  104. data/public/images/admin/assets/zip_icon.png +0 -0
  105. data/public/javascripts/admin/assets.js +297 -0
  106. data/public/stylesheets/sass/admin/assets.sass +224 -0
  107. data/radiant-clipped-extension.gemspec +29 -0
  108. data/spec/ci/before_script +23 -0
  109. data/spec/ci/script +2 -0
  110. data/spec/controllers/admin/assets_controller_spec.rb +50 -0
  111. data/spec/controllers/admin/page_attachments_controller_spec.rb +50 -0
  112. data/spec/datasets/assets_dataset.rb +36 -0
  113. data/spec/fixtures/5k.png +0 -0
  114. data/spec/fixtures/test.flv +0 -0
  115. data/spec/lib/asset_tags_spec.rb +107 -0
  116. data/spec/lib/frame_grab_spec.rb +17 -0
  117. data/spec/lib/geometry_transformation_spec.rb +63 -0
  118. data/spec/models/asset_spec.rb +72 -0
  119. data/spec/models/asset_type_spec.rb +70 -0
  120. data/spec/models/post_processing_spec.rb +62 -0
  121. data/spec/spec.opts +7 -0
  122. data/spec/spec_helper.rb +36 -0
  123. data/wireframes/edit-page-assets-2.bmml +453 -0
  124. data/wireframes/edit-page-assets-2.png +0 -0
  125. data/wireframes/edit-page-assets-3.bmml +454 -0
  126. data/wireframes/edit-page-assets-3.png +0 -0
  127. data/wireframes/edit-page-assets.bmml +433 -0
  128. data/wireframes/edit-page-assets.png +0 -0
  129. data/wireframes/edit-page.bmml +174 -0
  130. data/wireframes/edit-page.png +0 -0
  131. metadata +281 -0
@@ -0,0 +1,32 @@
1
+ module ClippedAdminUI
2
+
3
+ def self.included(base)
4
+ base.class_eval do
5
+
6
+ attr_accessor :asset
7
+ alias_method :assets, :asset
8
+
9
+ protected
10
+
11
+ def load_default_asset_regions
12
+ OpenStruct.new.tap do |asset|
13
+ asset.edit = Radiant::AdminUI::RegionSet.new do |edit|
14
+ edit.main.concat %w{edit_header edit_form edit_regenerate}
15
+ edit.form.concat %w{edit_title edit_metadata}
16
+ end
17
+ asset.new = asset.edit
18
+ asset.index = Radiant::AdminUI::RegionSet.new do |index|
19
+ index.top.concat %w{filters}
20
+ index.bottom.concat %w{}
21
+ index.thead.concat %w{thumbnail_header content_type_header actions_header}
22
+ index.tbody.concat %w{thumbnail_cell title_cell content_type_cell actions_cell}
23
+ index.paginate
24
+ end
25
+ asset.remove = asset.index
26
+ end
27
+ end
28
+ end
29
+
30
+ end
31
+ end
32
+
data/lib/cloud.rb ADDED
@@ -0,0 +1,41 @@
1
+ module RadiantClippedExtension
2
+
3
+ module Cloud
4
+
5
+ def self.credentials
6
+ case Radiant.config["paperclip.fog.provider"]
7
+ when "AWS"
8
+ {
9
+ :provider => "AWS",
10
+ :aws_access_key_id => Radiant.config["paperclip.s3.key"],
11
+ :aws_secret_access_key => Radiant.config["paperclip.s3.secret"],
12
+ :region => Radiant.config["paperclip.s3.region"],
13
+ }
14
+ when "Google"
15
+ {
16
+ :provider => "Google",
17
+ :rackspace_username => Radiant.config["paperclip.google_storage.access_key_id"],
18
+ :rackspace_api_key => Radiant.config["paperclip.google_storage.secret_access_key"]
19
+ }
20
+ when "Rackspace"
21
+ {
22
+ :provider => "Rackspace",
23
+ :rackspace_username => Radiant.config["paperclip.rackspace.username"],
24
+ :rackspace_api_key => Radiant.config["paperclip.rackspace.api_key"]
25
+ }
26
+ end
27
+ end
28
+
29
+ def self.host
30
+ return Radiant.config["paperclip.fog.host"] if Radiant.config["paperclip.fog.host"]
31
+ case Radiant.config["paperclip.fog.provider"]
32
+ when "AWS"
33
+ "http://#{Radiant.config['paperclip.fog.directory']}.s3.amazonaws.com"
34
+ else
35
+ nil
36
+ end
37
+ end
38
+
39
+ end
40
+
41
+ end
@@ -0,0 +1,53 @@
1
+ Radiant.config do |config|
2
+
3
+ # Uncomment and change the settings below to customize the Clipped extension
4
+
5
+ # The default settings
6
+ # config["paperclip.url"] = "/system/:attachment/:id/:style/:basename:no_original_style.:extension"
7
+ # config["paperclip.path"] = ":rails_root/public/system/:attachment/:id/:style/:basename:no_original_style.:extension"
8
+ # config["paperclip.storage"] = "filesystem"
9
+ # config["paperclip.skip_filetype_validation"] = true
10
+ # config["assets.max_asset_size"] = 5 # megabytes
11
+ # config["assets.display_size"] = "normal"
12
+ # config["assets.insertion_size"] = "normal"
13
+ # config["assets.create_image_thumbnails?"] = true
14
+ # config["assets.create_video_thumbnails?"] = true
15
+ # config["assets.create_pdf_thumbnails?"] = true
16
+ # Check http://www.imagemagick.org/script/command-line-processing.php#geometry
17
+ # for more details on ImageMagick settings for thumbnail generation
18
+ # config["assets.thumbnails.image"] = "normal:size=640x640>|small:size=320x320>"
19
+ # config["assets.thumbnails.video"] = "normal:size=640x640>,format=jpg|small:size=320x320>,format=jpg"
20
+ # config["assets.thumbnails.pdf"] = "normal:size=640x640>,format=jpg|small:size=320x320>,format=jpg"
21
+
22
+ # An example of using Amazon S3
23
+ # add `gem "fog", "~> 1.0"` to your Gemfile and run `bundle install`
24
+ # config["paperclip.storage"] = "fog"
25
+ # config["paperclip.path"] = ":attachment/:id/:style/:basename:no_original_style.:extension"
26
+ # config["paperclip.fog.provider"] = "AWS"
27
+ # config["paperclip.fog.directory"] = "bucket-name"
28
+ # config["paperclip.s3.key"] = "S3_KEY"
29
+ # config["paperclip.s3.secret"] = "S3_SECRET"
30
+ # optionally use a custom domain name; requires a CNAME DNS record
31
+ # config["paperclip.fog.host"] = "http://assets.example.com"
32
+ # optionally set the S3 region of your bucket; defaults to US East
33
+ # Asia North East => ap-northeast-1
34
+ # Asia South East => ap-southeast-1
35
+ # EU West => eu-west-1
36
+ # US East => us-east-1
37
+ # US West => us-west-1
38
+ # config["paperclip.s3.region"] = "us-east-1"
39
+
40
+ # An example of using Rackspace Cloud Files
41
+ # add `gem "fog", "~> 1.0"` to your Gemfile and run `bundle install`
42
+ # config["paperclip.storage"] = "fog"
43
+ # config["paperclip.path"] = ":attachment/:id/:style/:basename:no_original_style.:extension"
44
+ # config["paperclip.fog.provider"] = "Rackspace"
45
+ # config["paperclip.fog.directory"] = "container-name"
46
+ # config["paperclip.rackspace.username"] = "RACKSPACE_USERNAME"
47
+ # config["paperclip.rackspace.api_key"] = "RACKSPACE_API_KEY"
48
+ # paperclip.fog.host is your Cloud Files CDN URL
49
+ # config["paperclip.fog.host"] = "http://a.b.c.rackcdn.com"
50
+ # optionally use a custom domain name; requires a CNAME DNS record
51
+ # config["paperclip.fog.host"] = "http://assets.example.com"
52
+
53
+ end
@@ -0,0 +1,13 @@
1
+ module PageAssetAssociations
2
+
3
+ #TODO: Turn page_attachments into a generic, polymorphic asset-attachment mechanism
4
+
5
+ def self.included(base)
6
+ base.class_eval {
7
+ has_many :page_attachments, :order => "position ASC"
8
+ has_many :assets, :through => :page_attachments, :order => "page_attachments.position ASC"
9
+ accepts_nested_attributes_for :page_attachments, :allow_destroy => true
10
+ }
11
+ end
12
+
13
+ end
@@ -0,0 +1,73 @@
1
+ module Paperclip
2
+ class FrameGrab < Processor
3
+
4
+ attr_accessor :time_offset, :current_geometry, :target_geometry, :whiny, :current_format, :target_format
5
+
6
+ def initialize(file, options = {}, attachment = nil)
7
+ super
8
+ @file = file
9
+ @time_offset = options[:time_offset] || '-4'
10
+ geometry = options[:geometry]
11
+ unless geometry.blank?
12
+ @crop = geometry[-1,1] == '#'
13
+ @target_geometry = Geometry.parse(geometry)
14
+ @current_geometry = Geometry.parse(video_dimensions(file))
15
+ end
16
+ @current_format = File.extname(@file.path)
17
+ @target_format = options[:format] || 'jpg'
18
+ @basename = File.basename(@file.path, @current_format)
19
+ @whiny = options[:whiny].nil? ? true : options[:whiny]
20
+ end
21
+
22
+ def crop?
23
+ !!@crop
24
+ end
25
+
26
+ def make
27
+ src = @file
28
+ dst = Tempfile.new([ @basename, @target_format ].compact.join("."))
29
+ dst.binmode
30
+
31
+ begin
32
+ # grab frame at offset
33
+ cmd = %Q[-itsoffset #{time_offset} -i :source -y -vcodec mjpeg -vframes 1 -an -f rawvideo ]
34
+
35
+ # if scale-and-crop parameters can be calculated, we pipe to convert for resizing
36
+ if scale_and_crop = transformation_options
37
+ cmd << %{pipe: | convert #{scale_and_crop} - #{target_format}:- }
38
+
39
+ # otherwise we let ffmpeg resize the to the right size without preserving aspect ratio
40
+ else
41
+ cmd << %{-s #{target_geometry} pipe: }
42
+ end
43
+
44
+ # then pipe to composite to overlay video icon
45
+ cmd << %{| composite -gravity center :icon - :dest }
46
+
47
+ Paperclip.run('ffmpeg', cmd, :source => File.expand_path(src.path), :dest => File.expand_path(dst.path), :icon => AssetType.find(:video).icon_path, :swallow_stderr => false)
48
+ rescue PaperclipCommandLineError => e
49
+ raise PaperclipError, "There was an error processing the thumbnail for #{@basename}: #{e}" if whiny
50
+ end
51
+
52
+ dst
53
+ end
54
+
55
+ # get video dimensions in nasty hacky way
56
+ def video_dimensions(file)
57
+ dim = Paperclip.run('ffmpeg', '-i :source 2>&1', :source => File.expand_path(file.path), :expected_outcodes => [0,1], :swallow_stderr => false)
58
+ $1 if dim =~ /(\d+x\d+)/
59
+ end
60
+
61
+ # Duplicated from Thumbnail. We can't just subclass because of assumed compatibility with Geometry.from_file
62
+ def transformation_options
63
+ if current_geometry
64
+ scale, crop = current_geometry.transformation_to(target_geometry, crop?)
65
+ trans = []
66
+ trans << "-resize" << %["#{scale}"] unless scale.nil? || scale.empty?
67
+ trans << "-crop" << %["#{crop}"] << "+repage" if crop
68
+ trans.join(" ")
69
+ end
70
+ end
71
+
72
+ end
73
+ end
@@ -0,0 +1,80 @@
1
+ module Paperclip
2
+
3
+ class TransformationError < PaperclipError; end
4
+ class StyleError < PaperclipError; end
5
+
6
+ class Geometry
7
+
8
+ # Returns a new Geometry object with the the same dimensions as this but with no modifier.
9
+ def without_modifier
10
+ Geometry.new(self.width, self.height)
11
+ end
12
+
13
+ # Returns the dimensions that would result if a thumbnail was created by transforming this geometry into that geometry.
14
+ # Its purpose is to mimic imagemagick conversions. Used like so:
15
+ # file_geometry.transformed_by(style_geometry)
16
+ # it returns the size of the thumbnail image you would get by applying that rule.
17
+ # This saves us having to go back to the file, which is expensive with S3.
18
+ # We understand all the Imagemagick geometry arguments described at http://www.imagemagick.org/script/command-line-processing.php#geometry
19
+ # including both '^' and paperclip's own '#' modifier.
20
+ #
21
+ def transformed_by (other)
22
+ other = Geometry.parse(other) unless other.is_a? Geometry
23
+ # if the two geometries are similar, or the destination geometry is a fixed size, the resulting dimensions are fixed
24
+ return other.without_modifier if self =~ other || ['#', '!', '^'].include?(other.modifier)
25
+ # otherwise, we apply the transformation
26
+ raise TransformationError, "geometry is not transformable without both width and height" if self.height == 0 or self.width == 0
27
+ case other.modifier
28
+ when '>'
29
+ (other.width < self.width || other.height < self.height) ? scaled_to_fit(other) : self
30
+ when '<'
31
+ (other.width > self.width && other.height > self.height) ? scaled_to_fit(other) : self
32
+ when '%'
33
+ scaled_by(other)
34
+ when '@'
35
+ scaled_by(other.width * 100 / (self.width * self.height))
36
+ else
37
+ scaled_to_fit(other)
38
+ end
39
+ end
40
+ alias :* :transformed_by
41
+
42
+ # Tests whether two geometries are identical in dimensions and modifier.
43
+ def == (other)
44
+ self.to_s == other.to_s
45
+ end
46
+
47
+ # Tests whether two geometries have the same dimensions, ignoring modifier.
48
+ def =~ (other)
49
+ self.height.to_i == other.height.to_i && self.width.to_i == other.width.to_i
50
+ end
51
+
52
+ # Scales this geometry to fit within that geometry.
53
+ def scaled_to_fit(other)
54
+ if (other.width > 0 && other.height == 0)
55
+ Geometry.new(other.width, self.height * other.width / self.width)
56
+ elsif (other.width == 0 && other.height > 0)
57
+ Geometry.new(self.width * other.height / self.height, other.height)
58
+ else
59
+ ratio = Geometry.new( other.width / self.width, other.height / self.height )
60
+ if ratio.square?
61
+ other.without_modifier
62
+ elsif ratio.horizontal?
63
+ Geometry.new(ratio.height * self.width, other.height)
64
+ else
65
+ Geometry.new(other.width, ratio.width * self.height)
66
+ end
67
+ end
68
+ end
69
+
70
+ # Scales this geometry by the percentage(s) specified in that geometry.
71
+ def scaled_by(other)
72
+ other = Geometry.new("#{other}%") unless other.is_a? Geometry
73
+ if other.height > 0
74
+ Geometry.new(self.width * other.width / 100, self.height * other.height / 100)
75
+ else
76
+ Geometry.new(self.width * other.width / 100, self.height * other.width / 100)
77
+ end
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,8 @@
1
+ module RadiantClippedExtension
2
+ VERSION = "1.1.2"
3
+ SUMMARY = %q{Assets for Radiant CMS, add group}
4
+ DESCRIPTION = %q{Asset-management derived from Keith Bingman's Paperclipped extension.}
5
+ URL = "http://radiantcms.org"
6
+ AUTHORS = ["Keith Bingman", "Benny Degezelle", "William Ross", "John W. Long", "John Muhl", "Alvin Ye"]
7
+ EMAIL = ["radiant@radiantcms.org"]
8
+ end
@@ -0,0 +1,124 @@
1
+ namespace :radiant do
2
+ namespace :extensions do
3
+ namespace :clipped do
4
+
5
+ desc "Runs the migration of the Clipped extension"
6
+ task :migrate => :environment do
7
+ require 'radiant/extension_migrator'
8
+ if ActiveRecord::Base.connection.select_values("SELECT version FROM #{ActiveRecord::Migrator.schema_migrations_table_name} WHERE version = 'Assets-20110513205050'").any?
9
+ puts "Assimilating Assets extension migration 20110513205050"
10
+ ClippedExtension.migrator.new(:up, ClippedExtension.migrations_path).send(:assume_migrated_upto_version, '20110513205050')
11
+ end
12
+
13
+ if ENV["VERSION"]
14
+ ClippedExtension.migrator.migrate(ENV["VERSION"].to_i)
15
+ Rake::Task['db:schema:dump'].invoke
16
+ else
17
+ ClippedExtension.migrator.migrate
18
+ Rake::Task['db:schema:dump'].invoke
19
+ end
20
+ end
21
+
22
+ desc "Copies public assets of the Clipped extension to the instance public/ directory."
23
+ task :update => [:environment, :initialize] do
24
+ is_svn_or_dir = proc {|path| path =~ /\.svn/ || File.directory?(path) }
25
+ puts "Copying assets from ClippedExtension"
26
+ Dir[ClippedExtension.root + "/public/**/*"].reject(&is_svn_or_dir).each do |file|
27
+ path = file.sub(ClippedExtension.root, '')
28
+ directory = File.dirname(path)
29
+ mkdir_p RAILS_ROOT + directory, :verbose => false
30
+ cp_r file, RAILS_ROOT + path, :verbose => false
31
+ end
32
+
33
+ desc "Syncs all available translations for this ext to the English ext master"
34
+ task :sync => :environment do
35
+ # The main translation root, basically where English is kept
36
+ language_root = ClippedExtension.get_translation_keys(language_root)
37
+
38
+ Dir["#{language_root}/*.yml"].each do |filename|
39
+ next if filename.match('_available_tags')
40
+ basename = File.basename(filename, '.yml')
41
+ puts "Syncing #{basename}"
42
+ (comments, other) = TranslationSupport.read_file(filename, basename)
43
+ words.each { |k,v| other[k] ||= words[k] } # Initializing hash variable as empty if it does not exist
44
+ other.delete_if { |k,v| !words[k] } # Remove if not defined in en.yml
45
+ TranslationSupport.write_file(filename, basename, comments, other)
46
+ end
47
+ end
48
+ end
49
+
50
+ desc "Exports assets from database to assets directory"
51
+ task :export => :environment do
52
+ asset_path = File.join(RAILS_ROOT, "assets")
53
+ mkdir_p asset_path
54
+ Asset.find(:all).each do |asset|
55
+ puts "Exporting #{asset.asset_file_name}"
56
+ cp asset.asset.path, File.join(asset_path, asset.asset_file_name)
57
+ end
58
+ puts "Done."
59
+ end
60
+
61
+ desc "Imports assets to database from assets directory"
62
+ task :import => :environment do
63
+ asset_path = File.join(RAILS_ROOT, "assets")
64
+ if File.exist?(asset_path) && File.stat(asset_path).directory?
65
+ Dir.glob("#{asset_path}/*").each do |file_with_path|
66
+ if File.stat(file_with_path).file?
67
+ new_asset = File.new(file_with_path)
68
+ puts "Creating #{File.basename(file_with_path)}"
69
+ Asset.create :asset => new_asset
70
+ end
71
+ end
72
+ end
73
+ end
74
+
75
+ desc "Migrates page attachments from the original page attachments extension into new Assets"
76
+ task :migrate_from_page_attachments => :environment do
77
+ puts "This task can clean up traces of the page_attachments (think table records and files currently in /public/page_attachments).
78
+ If you would like to use this mode type \"yes\", type \"no\" or just hit enter to leave them untouched for now."
79
+ answer = STDIN.gets.chomp
80
+ erase_tracks = answer.eql?('yes') ? true : false
81
+ OldPageAttachment.find_all_by_parent_id(nil).each do |opa|
82
+ asset = opa.create_paperclipped_record
83
+ # move the actual file
84
+ old_dir = "#{RAILS_ROOT}/public/page_attachments/0000/#{opa.id.to_s.rjust(4,'0')}"
85
+ new_dir = "#{RAILS_ROOT}/public/assets/#{asset.id}"
86
+ puts "Copying #{old_dir.gsub(RAILS_ROOT, '')}/#{opa.filename} to #{new_dir.gsub(RAILS_ROOT, '')}/#{opa.filename}..."
87
+ mkdir_p new_dir
88
+ cp old_dir + "/#{opa.filename}", new_dir + "/#{opa.filename}"
89
+ # remove old record and remainings
90
+ if erase_tracks
91
+ rm_rf old_dir
92
+ end
93
+ end
94
+ # regenerate thumbnails
95
+ puts "Regenerating asset thumbnails"
96
+ ENV['CLASS'] = 'Asset'
97
+ Rake::Task['paperclip:refresh'].invoke
98
+ puts "Done."
99
+ end
100
+
101
+ desc "Migrates from old 'assets' extension."
102
+ task :migrate_from_assets => :environment do
103
+ Asset.delete_all("thumbnail IS NOT NULL OR parent_id IS NOT NULL")
104
+ ActiveRecord::Base.connection.tap do |c|
105
+ c.rename_column :assets, :filename, :asset_file_name
106
+ c.rename_column :assets, :content_type, :asset_content_type
107
+ c.rename_column :assets, :size, :asset_file_size
108
+ c.remove_column :assets, :parent_id
109
+ c.remove_column :assets, :thumbnail
110
+ end
111
+
112
+ ClippedExtension.migrator.new(:up, ClippedExtension.migrations_path).send(:assume_migrated_upto_version, 3)
113
+ ClippedExtension.migrator.migrate
114
+ end
115
+
116
+ desc "Generate an example initializer"
117
+ task :initialize do
118
+ puts "Copying initializer from ClippedExtension"
119
+ cp ClippedExtension.root + "/lib/generators/templates/clipped_config.rb", RAILS_ROOT + "/config/initializers/", :verbose => false
120
+ end
121
+
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,79 @@
1
+ def obtain_class
2
+ class_name = ENV['CLASS'] || ENV['class']
3
+ raise "Must specify CLASS" unless class_name
4
+ @klass = Object.const_get(class_name)
5
+ end
6
+
7
+ def obtain_attachments
8
+ name = ENV['ATTACHMENT'] || ENV['attachment']
9
+ raise "Class #{@klass.name} has no attachments specified" unless @klass.respond_to?(:attachment_definitions)
10
+ if !name.blank? && @klass.attachment_definitions.keys.include?(name)
11
+ [ name ]
12
+ else
13
+ @klass.attachment_definitions.keys
14
+ end
15
+ end
16
+
17
+ def for_all_attachments
18
+ klass = obtain_class
19
+ names = obtain_attachments
20
+ ids = klass.connection.select_values(klass.send(:construct_finder_sql, :select => 'id'))
21
+
22
+ ids.each do |id|
23
+ instance = klass.find(id)
24
+ names.each do |name|
25
+ result = if instance.send("#{ name }?")
26
+ yield(instance, name)
27
+ else
28
+ true
29
+ end
30
+ print result ? "." : "x"; $stdout.flush
31
+ end
32
+ end
33
+ puts " Done."
34
+ end
35
+
36
+ namespace :paperclip do
37
+ desc "Refreshes both metadata and thumbnails."
38
+ task :refresh => ["paperclip:refresh:metadata", "paperclip:refresh:thumbnails"]
39
+
40
+ namespace :refresh do
41
+ desc "Regenerates thumbnails for a given CLASS (and optional ATTACHMENT)."
42
+ task :thumbnails => :environment do
43
+ errors = []
44
+ for_all_attachments do |instance, name|
45
+ result = instance.send(name).reprocess!
46
+ errors << [instance.id, instance.errors] unless instance.errors.blank?
47
+ result
48
+ end
49
+ errors.each{|e| puts "#{e.first}: #{e.last.full_messages.inspect}" }
50
+ end
51
+
52
+ desc "Regenerates content_type/size metadata for a given CLASS (and optional ATTACHMENT)."
53
+ task :metadata => :environment do
54
+ for_all_attachments do |instance, name|
55
+ if file = instance.send(name).to_file
56
+ instance.send("#{name}_file_name=", instance.send("#{name}_file_name").strip)
57
+ instance.send("#{name}_content_type=", file.content_type.strip)
58
+ instance.send("#{name}_file_size=", file.size) if instance.respond_to?("#{name}_file_size")
59
+ instance.save(false)
60
+ else
61
+ true
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+ desc "Cleans out invalid attachments. Useful after you've added new validations."
68
+ task :clean => :environment do
69
+ for_all_attachments do |instance, name|
70
+ instance.send(name).send(:validate)
71
+ if instance.send(name).valid?
72
+ true
73
+ else
74
+ instance.send("#{name}=", nil)
75
+ instance.save
76
+ end
77
+ end
78
+ end
79
+ end