beef-has_assets 0.5.0 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -4,14 +4,14 @@ require 'rake'
4
4
  begin
5
5
  require 'jeweler'
6
6
  Jeweler::Tasks.new do |gem|
7
- gem.name = "has_assets"
7
+ gem.name = "beef-has_assets"
8
8
  gem.summary = %Q{Rails Engine. Adds uploadable assets to a model and admin area for files}
9
9
  gem.email = "steve@wearebeef.co.uk"
10
10
  gem.homepage = "http://github.com/beef/assets"
11
11
  gem.authors = ["Steve England"]
12
12
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
13
13
  end
14
-
14
+ Jeweler::GemcutterTasks.new
15
15
  rescue LoadError
16
16
  puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
17
17
  end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.0
1
+ 0.6.1
@@ -39,6 +39,16 @@ class Admin::AssetsController < Admin::BaseController
39
39
  format.js { render :action => 'index'}
40
40
  end
41
41
  end
42
+
43
+ def category
44
+ @assets = Asset.all(:conditions => ["category = ?",params[:category]])
45
+
46
+ respond_to do |format|
47
+ format.html { render :layout => false}
48
+ format.xml { @assets.to_xml }
49
+ format.js { render :layout => false}
50
+ end
51
+ end
42
52
 
43
53
  def descriptions
44
54
  @descriptions = Asset.not_thumbnails.find(:all, :select => 'description', :group => 'description', :order => 'description', :conditions => 'description IS NOT NULL')
@@ -14,13 +14,15 @@ class Admin::FlickrsController < Admin::BaseController
14
14
  end
15
15
 
16
16
  def index
17
- @flickr_result = {}
18
- if defined?(Flickr) and File.exists?("#{RAILS_ROOT}/config/flickr.yml")
19
- flickr = Flickr.new("#{RAILS_ROOT}/config/flickr.yml")
20
- flickr_params = { :per_page => '12', :page => params[:page], :user_id => Settings.flickr_user_id, :sort => 'date-taken-desc', :tag_mode => 'all' }
21
- flickr_params[:tags] = params[:tags] unless params[:tags].blank?
22
- @flickr_result = flickr.photos.search(flickr_params)
17
+ respond_to do |format|
18
+ format.js do
19
+ if defined?(Flickr) and File.exists?("#{RAILS_ROOT}/config/flickr.yml")
20
+ flickr = Flickr.new("#{RAILS_ROOT}/config/flickr.yml")
21
+ flickr_params = { :per_page => '12', :page => params[:page], :user_id => Settings.flickr_user_id, :sort => 'date-taken-desc', :tag_mode => 'all' }
22
+ flickr_params[:tags] = params[:tags] unless params[:tags].blank?
23
+ @flickr_result = flickr.photos.search(flickr_params)
24
+ end
25
+ end
23
26
  end
24
- render :layout => false
25
27
  end
26
28
  end
@@ -10,7 +10,8 @@ module Admin::AssetsHelper
10
10
  def asset_browser(for_content = false)
11
11
  render :partial => '/admin/assets/browser',
12
12
  :locals => { :asset_types => Asset.grouped_by_category,
13
- :for_content => for_content }
13
+ :for_content => for_content,
14
+ :ajaxify => true }
14
15
  end
15
16
 
16
17
  def asset_upload_form
@@ -34,21 +35,20 @@ module Admin::AssetsHelper
34
35
 
35
36
 
36
37
  def lastest_flickr
37
- return unless defined?(Flickr) and File.exists?("#{RAILS_ROOT}/config/flickr.yml")
38
+ return unless defined?(Flickr) and File.exists?("#{RAILS_ROOT}/config/flickr.yml") and !Settings.flickr_user_id.blank?
38
39
  flickr = Flickr.new("#{RAILS_ROOT}/config/flickr.yml")
39
40
  flickr_params = { :per_page => '5', :page => params[:page], :user_id => Settings.flickr_user_id, :sort => 'date-taken-desc', :tag_mode => 'all' }
40
41
  flickr_params[:tags] = params[:tags] unless params[:tags].blank?
41
42
  flickr_result = flickr.photos.search(flickr_params)
42
43
  render :partial => 'admin/shared/flickr_latest.html.erb', :locals => { :flickr_images => flickr_result }
44
+ rescue RuntimeError => e
45
+ logger.warn "Flickr error: #{e}"
46
+ return
43
47
  end
44
48
 
45
49
 
46
50
  def flickr_select
47
- return unless defined?(Flickr) and File.exists?("#{RAILS_ROOT}/config/flickr.yml")
48
- flickr = Flickr.new("#{RAILS_ROOT}/config/flickr.yml")
49
- flickr_params = { :per_page => '12', :page => params[:page], :user_id => Settings.flickr_user_id, :sort => 'date-taken-desc', :tag_mode => 'all' }
50
- flickr_params[:tags] = params[:tags] unless params[:tags].blank?
51
- flickr_result = flickr.photos.search(flickr_params)
52
- render :partial => 'admin/shared/flickr.html.erb', :locals => { :flickr_images => flickr_result }
51
+ return unless defined?(Flickr) and File.exists?("#{RAILS_ROOT}/config/flickr.yml") and !Settings.flickr_user_id.blank?
52
+ render :partial => 'admin/flickrs/selector'
53
53
  end
54
54
  end
@@ -8,18 +8,10 @@
8
8
  <dd id="<%= asset_type.parameterize %>-description">
9
9
  <h3 class="type-heading"><%= asset_type %></h3>
10
10
  <ul id="<%= asset_type.parameterize %>-list" class="asset-list">
11
- <% for asset in assets -%>
12
- <li class="<%= asset.content_type.gsub('/', ' ') %>" id="browser-asset-<%= asset.id %>">
13
- <% if asset.content_type =~ /image/ -%>
14
- <%= render :partial => "admin/assets/image", :locals => { :asset => asset, :for_content => for_content } %>
15
- <% else -%>
16
- <%= render :partial => "admin/assets/document", :locals => { :asset => asset, :for_content => for_content } %>
17
- <% end -%>
18
- </li>
19
- <% end -%>
11
+ <%= render :partial => "admin/assets/category_contents", :locals => { :assets => assets, :for_content => for_content } unless ajaxify %>
20
12
  </ul>
21
13
  </dd>
22
14
  <% end -%>
23
15
  </dl>
24
- <%= javascript_tag "new AssetBrowser('#{@grouping}', '#{params[:folder]}');" %>
16
+ <%= javascript_tag "new AssetBrowser('#{@grouping}', '#{params[:folder]}', #{for_content.to_s}, #{ajaxify.to_s});" %>
25
17
 
@@ -0,0 +1,9 @@
1
+ <% for asset in assets -%>
2
+ <li class="<%= asset.content_type.gsub('/', ' ') %>" id="browser-asset-<%= asset.id %>">
3
+ <% if asset.content_type =~ /image/ -%>
4
+ <%= render :partial => "admin/assets/image", :locals => { :asset => asset, :for_content => for_content } %>
5
+ <% else -%>
6
+ <%= render :partial => "admin/assets/document", :locals => { :asset => asset, :for_content => for_content } %>
7
+ <% end -%>
8
+ </li>
9
+ <% end -%>
@@ -0,0 +1 @@
1
+ <%= render :partial => "admin/assets/category_contents", :locals => { :ajaxify => true, :assets => @assets, :for_content => (params[:for_content] == "true" || false) } %>
@@ -1,7 +1,7 @@
1
1
  <h1>Browse for Files</h1>
2
2
  <%= toggle_grouping_links %>
3
3
  <div id="main-browser">
4
- <%= render :partial => 'browser', :locals => { :asset_types => @asset_types, :for_content => false } %>
4
+ <%= render :partial => 'browser', :locals => { :ajaxify => true, :asset_types => @asset_types, :for_content => false } %>
5
5
  </div>
6
6
 
7
7
  <% content_for :sub_content do %>
@@ -1 +1 @@
1
- page.replace 'asset-browser', :partial => '/admin/assets/browser', :locals => { :asset_types => @asset_types, :for_content => (params[:for_content] == 'true' )}
1
+ page.replace 'asset-browser', :partial => '/admin/assets/browser', :locals => { :ajaxify => true, :asset_types => @asset_types, :for_content => (params[:for_content] == 'true' )}
@@ -0,0 +1 @@
1
+ <%= link_to "#{image_tag photo.url(:square), :alt => photo.description}", "#{photo.url(:large)}", :title => "#{photo.title}", :onclick => "addLinkedImage('#{photo.url(:medium)}',this.title); return false;" %>
@@ -3,8 +3,7 @@
3
3
  <% form_remote_tag( :url => admin_flickr_path, :method => :get ) do -%>
4
4
  <p><label for="tags">Search by tag:</label>
5
5
  <%= text_field_tag :tags, params[:tags] %> &nbsp; <%= submit_tag "go" %></p>
6
- <% for photo in flickr_images %>
7
- <%= link_to "#{image_tag photo.url(:square)}", "#{photo.url(:large)}", :title => "#{photo.title}", :onclick => "addLinkedImage('#{photo.url(:medium)}',this.title); return false;" %>
8
- <% end -%>
6
+
7
+ <div id="flickr-image-container">Loading Flickr images</div>
9
8
  <% end -%>
10
9
  </div>
@@ -0,0 +1,3 @@
1
+ page.replace_html 'flickr-image-container', :partial => 'admin/flickrs/photo', :collection => @flickr_result
2
+ page.insert_html :bottom, 'flickr-image-container', link_to_remote( '< Previous', :url => admin_flickrs_path(:page => @flickr_result.page - 1), :method => :get) unless @flickr_result.page == 1
3
+ page.insert_html :bottom, 'flickr-image-container', link_to_remote( 'Next >', :url => admin_flickrs_path(:page => @flickr_result.page + 1), :method => :get) unless @flickr_result.page == @flickr_result.pages
@@ -4,12 +4,12 @@
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
- s.name = %q{has_assets}
8
- s.version = "0.5.0"
7
+ s.name = %q{beef-has_assets}
8
+ s.version = "0.6.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Steve England"]
12
- s.date = %q{2009-09-25}
12
+ s.date = %q{2009-10-27}
13
13
  s.email = %q{steve@wearebeef.co.uk}
14
14
  s.extra_rdoc_files = [
15
15
  "LICENSE",
@@ -29,24 +29,26 @@ Gem::Specification.new do |s|
29
29
  "app/models/asset.rb",
30
30
  "app/models/asseting.rb",
31
31
  "app/views/admin/assets/_browser.html.erb",
32
+ "app/views/admin/assets/_category_contents.html.erb",
32
33
  "app/views/admin/assets/_document.html.erb",
33
34
  "app/views/admin/assets/_file_info.html.erb",
34
35
  "app/views/admin/assets/_form.html.erb",
35
36
  "app/views/admin/assets/_image.html.erb",
36
37
  "app/views/admin/assets/_list.html.erb",
37
38
  "app/views/admin/assets/_toggle.html.erb",
39
+ "app/views/admin/assets/category.html.erb",
38
40
  "app/views/admin/assets/index.html.erb",
39
41
  "app/views/admin/assets/index.js.rjs",
40
42
  "app/views/admin/assets/rename_category.js.rjs",
41
43
  "app/views/admin/assets/show.html.erb",
42
44
  "app/views/admin/assets/show.js.rjs",
45
+ "app/views/admin/flickrs/_flickr_latest.html.erb",
46
+ "app/views/admin/flickrs/_photo.html.erb",
43
47
  "app/views/admin/flickrs/_selector.html.erb",
44
- "app/views/admin/flickrs/index.html.erb",
48
+ "app/views/admin/flickrs/index.js.rjs",
45
49
  "app/views/admin/flickrs/show.html.erb",
46
50
  "app/views/admin/flickrs/show.js.rjs",
47
- "app/views/admin/shared/_flickr.html.erb",
48
- "app/views/admin/shared/_flickr_image.html.erb",
49
- "app/views/admin/shared/_flickr_latest.html.erb",
51
+ "beef-has_assets.gemspec",
50
52
  "config/routes.rb",
51
53
  "generators/asset_migration/asset_migration_generator.rb",
52
54
  "generators/asset_migration/templates/migration.rb",
@@ -56,8 +58,6 @@ Gem::Specification.new do |s|
56
58
  "generators/assets_admin_files/templates/public/javascripts/admin/assets.js",
57
59
  "generators/assets_admin_files/templates/public/javascripts/swfupload.js",
58
60
  "generators/assets_admin_files/templates/public/javascripts/upload_progress.js",
59
- "has_assets.gemspec",
60
- "lib/flickr.rb",
61
61
  "lib/has_assets.rb",
62
62
  "lib/has_assets/custom_redcloth_tags.rb",
63
63
  "lib/has_assets/flash_sesion_cookie_middleware.rb",
@@ -74,8 +74,8 @@ Gem::Specification.new do |s|
74
74
  s.rubygems_version = %q{1.3.5}
75
75
  s.summary = %q{Rails Engine. Adds uploadable assets to a model and admin area for files}
76
76
  s.test_files = [
77
- "test/test_helper.rb",
78
- "test/has_assets_test.rb"
77
+ "test/has_assets_test.rb",
78
+ "test/test_helper.rb"
79
79
  ]
80
80
 
81
81
  if s.respond_to? :specification_version then
data/config/routes.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  ActionController::Routing::Routes.draw do |map|
2
2
  map.namespace(:admin) do |admin|
3
3
  admin.resources :flickrs
4
- admin.resources :assets, :collection => { :by_content_type => :get, :descriptions => :get, :by_category => :get, :categories => :get }, :member => { :set_lead => :put, :rename_category => :post }
4
+ admin.resources :assets, :collection => { :by_content_type => :get, :descriptions => :get, :by_category => :get, :categories => :get, :category => :get }, :member => { :set_lead => :put, :rename_category => :post }
5
5
  end
6
6
  end
@@ -12,6 +12,10 @@ var AssetBrowser = Class.create({
12
12
  dt.dd.hide();
13
13
  dt.onclick = function() {
14
14
  AssetBrowser.closeInfo();
15
+
16
+ if(AssetBrowser.ajax && !this.dd.visible() && !dt.dd.down('ul li'))
17
+ AssetBrowser.loadFilesByFolder(dt.innerHTML, dt.dd.down('ul').id);
18
+
15
19
  this.dd.toggle();
16
20
  if (AssetBrowser.current_content != this.dd) {
17
21
  if (AssetBrowser.current_content != null && AssetBrowser.current_content.visible()) {
@@ -74,7 +78,15 @@ Object.extend(AssetBrowser, {
74
78
  this.destroyAsset(asset);
75
79
  }
76
80
  },
77
-
81
+
82
+ loadFilesByFolder: function(folder_name, folder_id){
83
+ new Ajax.Request('/admin/assets/category', { method: 'get',
84
+ asynchronous:true,
85
+ parameters: { for_content: AssetBrowser.for_content, format: 'html', category: folder_name, authenticity_token: AJ.authenticity_token() },
86
+ onSuccess: function(response){ $(folder_id).update(response.responseText); } } );
87
+
88
+ },
89
+
78
90
  destroyAsset: function(asset) {
79
91
  if (confirm('Are you sure you wish to delete the asset \'' + asset.filename + ' \'?')) {
80
92
  new Ajax.Request('/admin/assets/'+ asset.id, { method: 'delete',
@@ -134,6 +146,8 @@ Object.extend(AssetBrowser, {
134
146
  this.contentNodeForm = $(id);
135
147
  if (this.contentNodeForm) {
136
148
  this.contentNodeForm.model_name = this.contentNodeForm.className.split('_').slice(1,this.contentNodeForm.className.split('_').length).join('_');
149
+ this.contentNodeForm.model_title = '';
150
+ this.contentNodeForm.className.split('_').slice(1,this.contentNodeForm.className.split('_').length).each(function(e){ this.contentNodeForm.model_title = this.contentNodeForm.model_title + e.charAt(0).toUpperCase() + e.slice(1).toLowerCase(); });
137
151
  this.setUpAssetList();
138
152
  this.contentNodeForm.addAssetIDs = function() {
139
153
  $$('input.asset_id').invoke('remove');
@@ -391,22 +405,64 @@ var Renameable = Class.create(Holdable, {
391
405
  }
392
406
  });
393
407
 
408
+ /**
409
+ * Ajax.Request.abort
410
+ * extend the prototype.js Ajax.Request object so that it supports an abort method
411
+ */
412
+ Ajax.Request.prototype.abort = function() {
413
+ // prevent and state change callbacks from being issued
414
+ this.transport.onreadystatechange = Prototype.emptyFunction;
415
+ // abort the XHR
416
+ this.transport.abort();
417
+ // update the request counter
418
+ Ajax.activeRequestCount--;
419
+ };
420
+
421
+
422
+
423
+
394
424
  var flickr_comms_ref = false;
395
425
  var flickr_before_handler = function(){
396
426
  if(false != flickr_comms_ref)
397
- flickr_comms_ref;
427
+ flickr_comms_ref.abort();
398
428
  $('flickr_loading').show();
429
+ };
430
+
431
+ var current_page = 1;
432
+ var flickr_get_next_page = function(button){
433
+ flickr_get_page(current_page+=1);
434
+ }
435
+ var flickr_get_prev_page = function(button){
436
+ current_page = Math.max(1,current_page-1)
437
+ flickr_get_page(current_page);
438
+ }
439
+
440
+ var flickr_get_page = function(num){
441
+ flickr_before_handler();
442
+
443
+ //if we have this page already
444
+ if(page_div = $('flickr-page-' + num)){
445
+ $$('.flickr-page').invoke('hide');
446
+ page_div.show();
447
+ $('flickr_loading').hide();
448
+ }
449
+ //get it
450
+ else{
451
+ flickr_comms_ref = new Ajax.Request('/admin/flickrs', {
452
+ method: 'get',
453
+ parameters: { page: num, format: 'html' },
454
+ onSuccess: function(response){ $$('.flickr-page').invoke('hide');flickr_display_images(response, num); }
455
+ });
456
+ }
457
+
399
458
  };
400
- var flickr_display_images = function(response){
459
+ var flickr_display_images = function(response, page){
401
460
  $('flickr_loading').hide();
402
- $('flickr-image-container').update(response.responseText)
403
- }
461
+ $('flickr-image-container').insert('<div class="flickr-page" id="flickr-page-' + page + '">' +response.responseText+ '</div>')
462
+ };
404
463
  var flickr_load_select = function(){
405
- flickr_before_handler();
406
- flickr_comms_ref = new Ajax.Request('/admin/flickrs', {
407
- method: 'get',
408
- parameters: { format: 'html', authenticity_token: AJ.authenticity_token() },
409
- onSuccess: flickr_display_images
410
- });
411
- }
464
+ if($('flickr-image-container')) {
465
+ new Ajax.Request('/admin/flickrs', {method: 'get'});
466
+ }
467
+ };
412
468
  document.observe('dom:loaded', flickr_load_select);
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: beef-has_assets
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steve England
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-09-25 00:00:00 -07:00
12
+ date: 2009-10-27 00:00:00 +00:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -36,24 +36,26 @@ files:
36
36
  - app/models/asset.rb
37
37
  - app/models/asseting.rb
38
38
  - app/views/admin/assets/_browser.html.erb
39
+ - app/views/admin/assets/_category_contents.html.erb
39
40
  - app/views/admin/assets/_document.html.erb
40
41
  - app/views/admin/assets/_file_info.html.erb
41
42
  - app/views/admin/assets/_form.html.erb
42
43
  - app/views/admin/assets/_image.html.erb
43
44
  - app/views/admin/assets/_list.html.erb
44
45
  - app/views/admin/assets/_toggle.html.erb
46
+ - app/views/admin/assets/category.html.erb
45
47
  - app/views/admin/assets/index.html.erb
46
48
  - app/views/admin/assets/index.js.rjs
47
49
  - app/views/admin/assets/rename_category.js.rjs
48
50
  - app/views/admin/assets/show.html.erb
49
51
  - app/views/admin/assets/show.js.rjs
52
+ - app/views/admin/flickrs/_flickr_latest.html.erb
53
+ - app/views/admin/flickrs/_photo.html.erb
50
54
  - app/views/admin/flickrs/_selector.html.erb
51
- - app/views/admin/flickrs/index.html.erb
55
+ - app/views/admin/flickrs/index.js.rjs
52
56
  - app/views/admin/flickrs/show.html.erb
53
57
  - app/views/admin/flickrs/show.js.rjs
54
- - app/views/admin/shared/_flickr.html.erb
55
- - app/views/admin/shared/_flickr_image.html.erb
56
- - app/views/admin/shared/_flickr_latest.html.erb
58
+ - beef-has_assets.gemspec
57
59
  - config/routes.rb
58
60
  - generators/asset_migration/asset_migration_generator.rb
59
61
  - generators/asset_migration/templates/migration.rb
@@ -63,8 +65,6 @@ files:
63
65
  - generators/assets_admin_files/templates/public/javascripts/admin/assets.js
64
66
  - generators/assets_admin_files/templates/public/javascripts/swfupload.js
65
67
  - generators/assets_admin_files/templates/public/javascripts/upload_progress.js
66
- - has_assets.gemspec
67
- - lib/flickr.rb
68
68
  - lib/has_assets.rb
69
69
  - lib/has_assets/custom_redcloth_tags.rb
70
70
  - lib/has_assets/flash_sesion_cookie_middleware.rb
@@ -74,9 +74,10 @@ files:
74
74
  - rails/init.rb
75
75
  - test/has_assets_test.rb
76
76
  - test/test_helper.rb
77
- has_rdoc: false
77
+ has_rdoc: true
78
78
  homepage: http://github.com/beef/assets
79
- licenses:
79
+ licenses: []
80
+
80
81
  post_install_message:
81
82
  rdoc_options:
82
83
  - --charset=UTF-8
@@ -102,5 +103,5 @@ signing_key:
102
103
  specification_version: 3
103
104
  summary: Rails Engine. Adds uploadable assets to a model and admin area for files
104
105
  test_files:
105
- - test/test_helper.rb
106
106
  - test/has_assets_test.rb
107
+ - test/test_helper.rb
@@ -1 +0,0 @@
1
- <%= render :partial => 'admin/shared/flickr_image.html.erb', :collection => @flickr_result -%>
@@ -1,17 +0,0 @@
1
-
2
- <div id="flickr-select">
3
- <% form_remote_tag( :method => :get, :url => admin_flickrs_path, :before => "flickr_before_handler()", :success => "flickr_display_images(request);" ) do -%>
4
- <p><label for="tags">Search by tag:</label>
5
- <%= text_field_tag :tags, params[:tags] %> &nbsp; <%= submit_tag "go" %> <span id="flickr_loading">Loading Flickr images</span></p>
6
-
7
- <% end -%>
8
-
9
- <div id="flickr-image-container">
10
- <% #= render :partial => 'admin/shared/flickr_image.html.erb', :collection => flickr_images -%>
11
- </div>
12
-
13
- <ul id="flickr_nav">
14
- <li class="first"><a href="#" onclick="flickr_get_prev_page();return false;">previous</a></li>&nbsp;|&nbsp;
15
- <li class="last"><a href="#" onclick="flickr_get_next_page();return false;">next</a></li>
16
- </ul>
17
- </div>
@@ -1 +0,0 @@
1
- <img src="<%= flickr_image.url(:square) %>" alt="<%= flickr_image.description || flickr_image.title %>" title="<%= flickr_image.title %>" onclick="addLinkedImage('<%= flickr_image.url(:medium) %>',this.alt)"/>
data/lib/flickr.rb DELETED
@@ -1,386 +0,0 @@
1
- # = Flickr
2
- # An insanely easy interface to the Flickr photo-sharing service. By Scott Raymond.
3
- # Modified by Steve England www.wearebeef.co.uk
4
-
5
- # Now using ObjectiveFlickr gem as it makes auth easy
6
- # gem 'objectiveflickr'
7
- require 'objectiveflickr'
8
-
9
- class Flickr
10
-
11
- def self.connect(api_key, secret, auth_token = nil)
12
- API.connect(api_key, secret, auth_token)
13
- self
14
- end
15
-
16
- class Error < StandardError ; end
17
-
18
- # Essentially a standard RuntimeError that can include the response as an
19
- # REXML object reference.
20
- class APIError < Error
21
- attr_reader :response
22
-
23
- # Creates a new exception.
24
- def initialize(response)
25
- super
26
- @response = response
27
- end
28
-
29
- # The error string returned by the API call.
30
- def to_s
31
- response['message']
32
- end
33
- end
34
-
35
- # Flickr client class. Requires an API key, and optionally takes an email and password for authentication
36
- class API
37
- class << self
38
-
39
- # Replace this API key with your own (see http://www.flickr.com/services/api/misc.api_keys.html)
40
- def connect(api_key, secret, auth_token = nil)
41
- @api_key = api_key
42
- @auth_token = auth_token
43
- @fi = FlickrInvocation.new(api_key,secret)
44
- self
45
- end
46
-
47
- def fi
48
- raise Error.new('API not connected') if @fi.nil?
49
- @fi
50
- end
51
-
52
- def login_url(permission='read')
53
- fi.login_url(permission)
54
- end
55
-
56
- def unauthorised?
57
- params = { :api_key => @api_key, :auth_token => @auth_token }
58
- logger.debug params
59
- data = fi.call('flickr.auth.checkToken',params).data
60
- logger.debug data
61
- return data['message'] if data['stat'] != 'ok'
62
- false
63
- end
64
-
65
- def authorise(frob)
66
- @auth_token = request('flickr.auth.getToken', { :api_key => @api_key, :frob => frob } )['auth']['token']['_content']
67
- end
68
-
69
- # Implements flickr.urls.lookupGroup and flickr.urls.lookupUser
70
- def find_by_url(url)
71
- response = urls_lookupUser('url'=>url) rescue urls_lookupGroup('url'=>url) rescue nil
72
- (response['user']) ? User.new(response['user']['id']) : Group.new(response['group']['id']) unless response.nil?
73
- end
74
-
75
- # Implements flickr.photos.getRecent and flickr.photos.search, returns PhotoList object so
76
- # that page_count, total etc. are avaiable for pagination.
77
- def photos(params = {})
78
- photos = (params.empty?) ? photos_getRecent['photos'] : photos_search(params)['photos']
79
- PhotoList.new(photos, self)
80
- end
81
-
82
- # Implements flickr.people.getOnlineList, flickr.people.findByEmail, and flickr.people.findByUsername
83
- def users(lookup=nil)
84
- if(lookup)
85
- user = people_findByEmail('find_email'=>lookup)['user'] rescue people_findByUsername('username'=>lookup)['user']
86
- return User.find(user['nsid'])
87
- else
88
- return people_getOnlineList['online']['user'].collect { |person| User.new(person['nsid']) }
89
- end
90
- end
91
-
92
- # Implements flickr.groups.getActiveList
93
- def groups
94
- groups_getActiveList['activegroups']['group'].collect { |group| Group.new(group['nsid']) }
95
- end
96
-
97
- # Implements flickr.tags.getRelated
98
- def related_tags(tag)
99
- tags_getRelated('tag_id'=>tag)['tags']['tag']
100
- end
101
-
102
- # Implements flickr.photos.licenses.getInfo
103
- def licenses
104
- photos_licenses_getInfo['licenses']['license']
105
- end
106
-
107
- # Todo:
108
- # logged_in?
109
- # if logged in:
110
- # flickr.blogs.getList
111
- # flickr.favorites.add
112
- # flickr.favorites.remove
113
- # flickr.groups.browse
114
- # flickr.photos.getCounts
115
- # flickr.photos.getNotInSet
116
- # flickr.photos.getUntagged
117
- # flickr.photosets.create
118
- # flickr.photosets.orderSets
119
- # flickr.tags.getListUserPopular
120
- # flickr.test.login
121
- # uploading
122
-
123
- private
124
-
125
- def logger
126
- RAILS_DEFAULT_LOGGER
127
- end
128
-
129
- # Takes a Flickr API method name and set of parameters
130
- def request(method, params = {}, auth = true)
131
- params[:auth] = auth
132
- params[:auth_token] = @auth_token unless @auth_token.nil?
133
- logger.debug params.inspect
134
-
135
-
136
- data = fi.call(method,params).data
137
- logger.debug data.inspect
138
- raise APIError.new(data) if data['stat'] != 'ok'
139
- data
140
- end
141
-
142
- # Implements everything else.
143
- # Any method not defined explicitly will be passed on to the Flickr API,
144
- # and return an XmlSimple document. For example, Flickr#test_echo is not defined,
145
- # so it will pass the call to the flickr.test.echo method.
146
- # e.g., Flickr#test_echo['stat'] should == 'ok'
147
- def method_missing(method_id, *params)
148
- request('flickr.' + method_id.id2name.gsub(/_/, '.'), params[0])
149
- end
150
-
151
- end
152
-
153
- end
154
-
155
- class ApiObject
156
-
157
- protected
158
-
159
- def initialize(hash)
160
- hash.each do |key, value|
161
- instance_variable_set '@' + key, value
162
- end
163
- end
164
-
165
- def self.find(*args)
166
- case args.first
167
- when :first then find_initial(args[1])
168
- when :all then find_every(args[1])
169
- else find_by_id(args)
170
- end
171
- end
172
-
173
- end
174
-
175
- class Person < ApiObject
176
-
177
- attr_reader :nsid, :username, :name, :location, :count, :firstdate, :firstdatetaken
178
-
179
- def self.find_by_id(id)
180
- self.new(API.people_getInfo('user_id'=>id)['person'])
181
- end
182
-
183
- def self.find_by_email(email)
184
- id = API.people_findByEmail('find_email'=>email)['user']['nsid']
185
- find(id)
186
- end
187
-
188
- # Implements flickr.people.getPublicGroups
189
- def groups
190
- API.people_getPublicGroups('user_id'=>@nsid)['groups']['group'].collect { |group| Group.new(group['nsid']) }
191
- end
192
-
193
- def photos(params = {})
194
- @photolist ||= API.photos(params.merge('user_id'=>@nsid, 'sort'=>'date-taken-desc'))
195
- end
196
-
197
- # Implements flickr.photosets.getList
198
- def photosets
199
- if @photosets.nil?
200
- photosets = API.photosets_getList('user_id'=>@nsid)['photosets']
201
- if photosets.empty?
202
- @photosets = []
203
- else
204
- @photosets = photosets['photoset'].collect { |photoset| Photoset.new(photoset) }
205
- end
206
- else
207
- @photosets
208
- end
209
- end
210
-
211
- # Implements flickr.contacts.getPublicList and flickr.contacts.getList
212
- def contacts
213
- API.contacts_getPublicList('user_id'=>@nsid)['contacts']['contact'].collect { |contact| User.new(contact['nsid']) }
214
- end
215
-
216
- # Implements flickr.favorites.getPublicList and flickr.favorites.getList
217
- def favorites
218
- API.favorites_getPublicList('user_id'=>@nsid)['photos']['photo'].collect { |photo| Photo.new(photo) }
219
- #or
220
- end
221
-
222
- # Implements flickr.tags.getListUser
223
- def tags
224
- API.tags_getListUser('user_id'=>@nsid)['who']['tags']['tag'].collect { |tag| tag }
225
- end
226
-
227
- # Implements flickr.photos.getContactsPublicPhotos and flickr.photos.getContactsPhotos
228
- def contactsPhotos
229
- API.photos_getContactsPublicPhotos('user_id'=>@nsid)['photos']['photo'].collect { |photo| Photo.new(photo) }
230
- # or
231
- #API.photos_getContactsPhotos['photos']['photo'].collect { |photo| Photo.new(photo['id']) }
232
- end
233
-
234
- def to_s
235
- @name
236
- end
237
-
238
- end
239
-
240
- class Photoset < ApiObject
241
- attr_reader :id, :title, :description
242
-
243
- def find_by_id(id)
244
- self.new(photosets_getInfo('photoset_id'=>id)['photoset'])
245
- end
246
-
247
- def total
248
- @photos
249
- end
250
-
251
- def photos
252
- photo = API.photosets_getPhotos('photoset_id'=>id)['photoset']['photo']
253
- return [] if photo.nil?
254
- return [Photo.new(photo, self)] if photo.is_a? Hash
255
- photo.collect { |photo| Photo.new(photo) }
256
- end
257
- end
258
-
259
- class Photo < ApiObject
260
-
261
- attr_reader :id, :title, :owner_id, :server, :isfavourite, :license, :rotation, :description, :notes
262
- attr_writer :owner
263
-
264
- def self.find_by_id(id)
265
- self.new(API.photos_getInfo('photo_id'=>id)['photo'])
266
- end
267
-
268
- # Implements flickr.photos.getRecent and flickr.photos.search, returns PhotoList object so
269
- # that page_count, total etc. are avaiable for pagination.
270
- def self.find_every(params = {})
271
- photos = (params.empty?) ? API.photos_getRecent['photos'] : API.photos_search(params)['photos']
272
- PhotoList.new(photos)
273
- end
274
-
275
- def self.find_initial(params = {})
276
- params[:per_page] = 1
277
- find_every(params = {})
278
- end
279
-
280
- # Returns the URL for the photo page (default or any specified size)
281
- def url(size='Medium')
282
- if size=='Medium'
283
- "http://flickr.com/photos/#{owner.username}/#{@id}"
284
- else
285
- sizes(size)['url']
286
- end
287
- end
288
-
289
- # Returns the URL for the image (default or any specified size)
290
- def source(size=nil)
291
- url = "http://static.flickr.com/#{@server}/#{@id}_#{@secret}"
292
- url << "_#{size}" unless size.nil?
293
- url + ".jpg"
294
- end
295
-
296
- # Returns the photo file data itself, in any specified size. Example: File.open(photo.title, 'w') { |f| f.puts photo.file }
297
- def file(size=nil)
298
- Net::HTTP.get_response(URI.parse(source(size))).body
299
- end
300
-
301
- # Unique filename for the image, based on the Flickr NSID
302
- def filename
303
- "#{@id}.jpg"
304
- end
305
-
306
- # Implements flickr.photos.getContext
307
- def context
308
- context = API.photos_getContext('photo_id'=>@id)
309
- @previousPhoto = Photo.new(context['prevphoto']['id'])
310
- @nextPhoto = Photo.new(context['nextphoto']['id'])
311
- return [@previousPhoto, @nextPhoto]
312
- end
313
-
314
- # Implements flickr.photos.getExif
315
- def exif
316
- API.photos_getExif('photo_id'=>@id)['photo']
317
- end
318
-
319
- # Implements flickr.photos.getPerms
320
- def permissions
321
- API.photos_getPerms('photo_id'=>@id)['perms']
322
- end
323
-
324
- # Implements flickr.photos.getSizes
325
- def sizes(size=nil)
326
- sizes = API.photos_getSizes('photo_id'=>@id)['sizes']['size']
327
- sizes = sizes.find{|asize| asize['label']==size} if size
328
- return sizes
329
- end
330
-
331
- # flickr.tags.getListPhoto
332
- def tags
333
- API.tags_getListPhoto('photo_id'=>@id)['photo']['tags']
334
- end
335
-
336
- # Implements flickr.blogs.postPhoto
337
- def postToBlog(blog_id, title='', description='')
338
- API.blogs_postPhoto('photo_id'=>@id, 'title'=>title, 'description'=>description)
339
- end
340
-
341
- # Converts the Photo to a string by returning its title
342
- def to_s
343
- @title
344
- end
345
-
346
- end
347
-
348
- # Todo:
349
- # flickr.groups.pools.add
350
- # flickr.groups.pools.getContext
351
- # flickr.groups.pools.getGroups
352
- # flickr.groups.pools.getPhotos
353
- # flickr.groups.pools.remove
354
- class Group < ApiObject
355
- attr_reader :id, :client, :name, :members, :online, :privacy, :chatid, :chatcount, :url
356
-
357
- def self.find_by_id(id)
358
- self.new(API.groups_getInfo('user_id'=>id)['person'])
359
- end
360
-
361
- def self.photos(id, params = {})
362
- params['group_id'] = id
363
- PhotoList.new(API.groups_pools_getPhotos(params)['photos'])
364
- end
365
-
366
-
367
- end
368
-
369
- # Extended from array to allow perpage etc.
370
- class PhotoList < Array
371
- attr_reader :page, :pages, :perpage, :total
372
-
373
- def initialize(flickr_response)
374
- @page = flickr_response['page'].to_i
375
- @perpage = flickr_response['perpage'].to_i
376
- @total = flickr_response['total'].to_i
377
- @pages = flickr_response['pages'].to_i
378
-
379
- @photo = flickr_response['photo']
380
-
381
- super Photo.new(@photo, self) if @photo.is_a? Hash
382
- super @photo.collect { |photo| Photo.new(photo) }
383
- end
384
- end
385
-
386
- end