radiant-downloads-extension 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ module DownloadGroup
2
+ def self.included(base)
3
+ base.class_eval {
4
+ has_and_belongs_to_many :downloads
5
+ }
6
+ end
7
+ end
@@ -0,0 +1,165 @@
1
+ module DownloadTags
2
+ include Radiant::Taggable
3
+
4
+ class TagError < StandardError; end
5
+
6
+ # the root group tag is defined in reader_group and should only expand if there is a page group or message group
7
+
8
+ desc %{
9
+ Expands if this group has any downloads.
10
+
11
+ <pre><code><r:group:if_downloads>...</r:group:if_downloads /></code></pre>
12
+ }
13
+ tag "group:if_downloads" do |tag|
14
+ tag.expand if tag.locals.group.downloads.any?
15
+ end
16
+
17
+ desc %{
18
+ Expands if this group does not have any downloads.
19
+
20
+ <pre><code><r:group:unless_downloads>...</r:group:unless_downloads /></code></pre>
21
+ }
22
+ tag "group:unless_downloads" do |tag|
23
+ tag.expand unless tag.locals.group.downloads.any?
24
+ end
25
+
26
+ desc %{
27
+ Cycles through all downloads for the current group.
28
+ (which will only be defined if this is the home page for a group)
29
+
30
+ *Usage:*
31
+ <pre><code><r:group:downloads:each>...</r:group:downloads:each></code></pre>
32
+ }
33
+ tag 'group:downloads' do |tag|
34
+ tag.expand if tag.locals.group
35
+ end
36
+ tag 'group:downloads:each' do |tag|
37
+ result = []
38
+ tag.locals.group.downloads.each do |download|
39
+ tag.locals.download = download
40
+ result << tag.expand
41
+ end
42
+ result
43
+ end
44
+
45
+ desc %{
46
+ Expands if the current reader has any downloads.
47
+
48
+ <pre><code><r:reader:if_downloads>...</r:reader:if_downloads /></code></pre>
49
+ }
50
+ tag "reader:if_downloads" do |tag|
51
+ tag.expand if tag.locals.reader.downloads.any?
52
+ end
53
+
54
+ desc %{
55
+ Expands if the current reader does not have any downloads.
56
+
57
+ <pre><code><r:reader:unless_downloads>...</r:reader:unless_downloads /></code></pre>
58
+ }
59
+ tag "reader:unless_downloads" do |tag|
60
+ tag.expand unless tag.locals.reader.downloads.any?
61
+ end
62
+
63
+ desc %{
64
+ Cycles through all downloads for the current reader.
65
+
66
+ *Usage:*
67
+ <pre><code><r:reader:downloads:each>...</r:reader:downloads:each></code></pre>
68
+ }
69
+ tag 'reader:downloads' do |tag|
70
+ tag.locals.reader ||= current_reader
71
+ tag.expand if tag.locals.reader
72
+ end
73
+ tag 'reader:downloads:each' do |tag|
74
+ result = []
75
+ tag.locals.reader.downloads.each do |download|
76
+ tag.locals.download = download
77
+ result << tag.expand
78
+ end
79
+ result
80
+ end
81
+
82
+ desc %{
83
+ The root 'download' tag is not meant to be called directly.
84
+ All it does is summon a download object so that its fields can be displayed with eg.
85
+ <pre><code><r:download:url /></code></pre>
86
+ }
87
+
88
+ tag 'download' do |tag|
89
+ tag.expand
90
+ # tag.locals.download ||= _get_download(tag)
91
+ # if tag.locals.download
92
+ # tag.expand
93
+ # else
94
+ # %{No download found with id '#{tag.attr['id']}' or title '#{tag.attr['title']}'}
95
+ # end
96
+ end
97
+
98
+ desc %{
99
+ Returns title of current download.
100
+
101
+ *Usage:*
102
+ <pre><code><r:download:title /></code></pre>
103
+ }
104
+ tag 'download:title' do |tag|
105
+ if download = _get_download(tag)
106
+ download.name
107
+ end
108
+ end
109
+ tag 'download:name' do |tag|
110
+ if download = _get_download(tag)
111
+ download.name
112
+ end
113
+ end
114
+
115
+ desc %{
116
+ Returns description of current download.
117
+
118
+ *Usage:*
119
+ <pre><code><r:download:description /></code></pre>
120
+ }
121
+ tag 'download:description' do |tag|
122
+ if download = _get_download(tag)
123
+ download.description
124
+ end
125
+ end
126
+
127
+ desc %{
128
+ Returns the secure url of the current download.
129
+
130
+ *Usage:*
131
+ <pre><code><a href="<r:download:url id="4" />">...</a></code></pre>
132
+ }
133
+ tag 'download:url' do |tag|
134
+ if download = _get_download(tag)
135
+ download_path(download)
136
+ end
137
+ end
138
+
139
+ desc %{
140
+ Returns a link to the current download.
141
+ Attributes and enclosed link text are passed through in the usual way.
142
+
143
+ *Usage:*
144
+ <pre><code><r:download:link /></code></pre>
145
+ }
146
+ tag 'download:link' do |tag|
147
+ tag.locals.download = _get_download(tag)
148
+ options = tag.attr.dup
149
+ attributes = options.inject('') { |s, (k, v)| s << %{#{k.downcase}="#{v}" } }.strip
150
+ attributes = " #{attributes}" unless attributes.empty?
151
+ text = tag.double? ? tag.expand : tag.render('download:title')
152
+ %{<a href="#{tag.render('download:url')}"#{attributes}>#{text}</a>}
153
+ end
154
+
155
+
156
+ private
157
+
158
+ def _get_download(tag)
159
+ download = tag.locals.download
160
+ download ||= Download.find_by_id(tag.attr.delete('id')) if tag.attr['id']
161
+ download ||= Download.find_by_title(tag.attr.delete('title')) if tag.attr['title']
162
+ download
163
+ end
164
+
165
+ end
@@ -0,0 +1,38 @@
1
+ module DownloadUI
2
+
3
+ def self.included(base)
4
+ base.class_eval do
5
+
6
+ attr_accessor :download
7
+ alias_method :downloads, :download
8
+
9
+ def load_default_regions_with_download
10
+ load_default_regions_without_download
11
+ @download = load_default_download_regions
12
+ end
13
+
14
+ alias_method_chain :load_default_regions, :download
15
+
16
+ protected
17
+
18
+ def load_default_download_regions
19
+ returning OpenStruct.new do |download|
20
+ download.edit = Radiant::AdminUI::RegionSet.new do |edit|
21
+ edit.main.concat %w{edit_header edit_form}
22
+ edit.form.concat %w{edit_title edit_description edit_document edit_access}
23
+ edit.form_bottom.concat %w{edit_timestamp edit_buttons}
24
+ end
25
+ download.index = Radiant::AdminUI::RegionSet.new do |index|
26
+ index.thead.concat %w{name_header document_header access_header modify_header}
27
+ index.tbody.concat %w{name_cell document_cell access_cell modify_cell}
28
+ index.bottom.concat %w{new_button}
29
+ end
30
+ download.remove = download.index
31
+ download.new = download.edit
32
+ end
33
+ end
34
+
35
+ end
36
+ end
37
+ end
38
+
@@ -0,0 +1,28 @@
1
+ namespace :radiant do
2
+ namespace :extensions do
3
+ namespace :downloads do
4
+
5
+ desc "Runs the migration of the Downloads extension"
6
+ task :migrate => :environment do
7
+ require 'radiant/extension_migrator'
8
+ if ENV["VERSION"]
9
+ DownloadsExtension.migrator.migrate(ENV["VERSION"].to_i)
10
+ else
11
+ DownloadsExtension.migrator.migrate
12
+ end
13
+ end
14
+
15
+ desc "Copies public assets of the Downloads to the instance public/ directory."
16
+ task :update => :environment do
17
+ is_svn_or_dir = proc {|path| path =~ /\.svn/ || File.directory?(path) }
18
+ puts "Copying assets from DownloadsExtension"
19
+ Dir[DownloadsExtension.root + "/public/**/*"].reject(&is_svn_or_dir).each do |file|
20
+ path = file.sub(DownloadsExtension.root, '')
21
+ directory = File.dirname(path)
22
+ mkdir_p RAILS_ROOT + directory
23
+ cp file, RAILS_ROOT + path
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,25 @@
1
+ /* submenu admin */
2
+
3
+ #content table.index .node .download {
4
+ font-size:115%;
5
+ font-weight:bold;
6
+ }
7
+
8
+ #content table.index .node .download a {
9
+ color: black;
10
+ }
11
+
12
+ #content .form-area .user select {
13
+ font-family:Georgia,Palatino,"Times New Roman",Times,serif;
14
+ font-size:150%;
15
+ width:60%;
16
+ }
17
+
18
+ #content .form-area p.description {
19
+ margin-top: 10px;
20
+ }
21
+
22
+ #content .form-area span.formnote {
23
+ color: #7d796c;
24
+ font-size: 85%;
25
+ }
@@ -0,0 +1,73 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe DownloadsController do
4
+ dataset :download_groups
5
+
6
+ before do
7
+ controller.stub!(:request).and_return(request)
8
+ Page.current_site = sites(:test) if defined? Site
9
+ request.env["HTTP_REFERER"] = 'http://test.host/referer!'
10
+ end
11
+
12
+ describe "with a protected download" do
13
+ describe "and no reader" do
14
+ before do
15
+ logout_reader
16
+ get :show, :id => download_id(:grouped)
17
+ end
18
+
19
+ it "should redirect to login" do
20
+ response.should be_redirect
21
+ response.should redirect_to(reader_login_url)
22
+ end
23
+
24
+ it "should set the right return_to url" do
25
+ session[:return_to].should == request.request_uri
26
+ end
27
+ end
28
+
29
+ describe "and a logged-in reader" do
30
+ describe "who is not in a permitted group" do
31
+ before do
32
+ login_as_reader(:ungrouped)
33
+ get :show, :id => download_id(:grouped)
34
+ end
35
+
36
+ it "should redirect to the permission denied page" do
37
+ response.should be_success
38
+ response.should render_template('site/not_allowed')
39
+ end
40
+ end
41
+
42
+ describe "who is in a permitted group" do
43
+ before do
44
+ login_as_reader(:normal)
45
+ get :show, :id => download_id(:grouped)
46
+ end
47
+
48
+ it "should return an internal redirect" do
49
+ dl = downloads(:grouped)
50
+ response.should be_success
51
+ response.headers.should include('X-Accel-Redirect');
52
+ response.headers['X-Accel-Redirect'].should == dl.document.path
53
+ response.headers['Content-Disposition'].should =~ /^attachment/
54
+ end
55
+ end
56
+ end
57
+ end
58
+
59
+ describe "with an ungrouped download" do
60
+ describe "and no reader" do
61
+ before do
62
+ logout_reader
63
+ get :show, :id => download_id(:grouped)
64
+ end
65
+
66
+ it "should refuse access" do
67
+ response.should be_redirect
68
+ response.should redirect_to(reader_login_url)
69
+ end
70
+ end
71
+ end
72
+
73
+ end
@@ -0,0 +1,42 @@
1
+ require 'digest/sha1'
2
+ class DownloadGroupsDataset < Dataset::Base
3
+ datasets = [:downloads, :download_readers]
4
+ datasets << :download_sites if defined? Site
5
+ uses *datasets
6
+
7
+ def load
8
+ create_group "Normal"
9
+ create_group "Busy"
10
+ create_group "Idle"
11
+ add_downloads_to_group :normal, [:grouped]
12
+ add_downloads_to_group :busy, [:grouped, :alsogrouped]
13
+ add_readers_to_group :busy, [:normal, :another]
14
+ end
15
+
16
+ helpers do
17
+ def create_group(name, att={})
18
+ group = create_record Group, name.symbolize, group_attributes(att.update(:name => name))
19
+ end
20
+
21
+ def group_attributes(att={})
22
+ name = att[:name] || "A group"
23
+ attributes = {
24
+ :name => name,
25
+ :description => "Test group"
26
+ }.merge(att)
27
+ attributes[:site_id] ||= site_id(:test) if defined? Site
28
+ attributes
29
+ end
30
+ end
31
+
32
+ def add_readers_to_group(g, rr)
33
+ g = g.is_a?(Group) ? g : groups(g)
34
+ g.readers << rr.map{|r| readers(r)}
35
+ end
36
+
37
+ def add_downloads_to_group(g, dd)
38
+ g = g.is_a?(Group) ? g : groups(g)
39
+ g.downloads << dd.map{|d| downloads(d)}
40
+ end
41
+
42
+ end
@@ -0,0 +1,49 @@
1
+ require "authlogic/test_case"
2
+
3
+ class DownloadReadersDataset < Dataset::Base
4
+ uses :download_sites if defined? Site
5
+
6
+ def load
7
+ create_reader "Normal"
8
+ create_reader "Another"
9
+ create_reader "Ungrouped"
10
+ end
11
+
12
+ helpers do
13
+ def create_reader(name, attributes={})
14
+ attributes = reader_attributes(attributes.update(:name => name))
15
+ reader = create_model Reader, name.symbolize, attributes
16
+ end
17
+
18
+ def reader_attributes(attributes={})
19
+ name = attributes[:name] || "John Doe"
20
+ symbol = name.symbolize
21
+ attributes = {
22
+ :name => name,
23
+ :email => "#{symbol}@spanner.org",
24
+ :login => "#{symbol}@spanner.org",
25
+ :activated_at => Time.now - 1.week,
26
+ :password_salt => "golly",
27
+ :password => 'password',
28
+ :password_confirmation => 'password'
29
+ }.merge(attributes)
30
+ attributes[:site] = sites(:test) if defined? Site
31
+ attributes
32
+ end
33
+
34
+ def login_as_reader(reader)
35
+ activate_authlogic
36
+ login_reader = reader.is_a?(Reader) ? reader : readers(reader)
37
+ ReaderSession.create(login_reader)
38
+ login_reader
39
+ end
40
+
41
+ def logout_reader
42
+ activate_authlogic
43
+ if session = ReaderSession.find
44
+ session.destroy
45
+ end
46
+ end
47
+ end
48
+
49
+ end
@@ -0,0 +1,9 @@
1
+ class DownloadSitesDataset < Dataset::Base
2
+ uses :pages
3
+
4
+ def load
5
+ create_record Site, :test, :name => 'Test Site', :domain => 'test', :base_domain => 'test.host', :position => 1, :mail_from_name => 'test sender', :mail_from_address => 'sender@spanner.org', :homepage_id => page_id(:home)
6
+ Page.current_site = sites(:test)
7
+ end
8
+
9
+ end