radiant-archive-extension 1.0.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.
data/README ADDED
@@ -0,0 +1,29 @@
1
+ = Archive
2
+
3
+ The Archive extension extracts the Archive pages from their original place
4
+ in the Radiant distribution.
5
+
6
+ == Archive page
7
+
8
+ An archive page provides behavior similar to a blog archive or a news
9
+ archive. Child page URLs are altered to be in %Y/%m/%d format
10
+ (2004/05/06).
11
+
12
+ An archive page can be used in conjunction with the "Archive Year Index",
13
+ "Archive Month Index", and "Archive Day Index" page types to create year,
14
+ month, and day indexes.
15
+
16
+ == Archive Index pages
17
+
18
+ To create a year/month/day index for an archive, create a child page for the
19
+ archive and assign the "Archive [Year/Month/Day] Index" page type to it.
20
+
21
+ An index page makes following tags available to you:
22
+
23
+ <r:archive:children>...</r:archive:children>
24
+ Grants access to a subset of the children of the archive page
25
+ that match the specific year/month/day which the index page is rendering.
26
+
27
+ The title and breadcrumb attributes of an index page are rendered using Ruby's
28
+ Time#strftime method. Please refer to documentation for Time#strftime to
29
+ format these attributes.
data/Rakefile ADDED
@@ -0,0 +1,109 @@
1
+ # Determine where the RSpec plugin is by loading the boot
2
+ unless defined? RADIANT_ROOT
3
+ ENV["RAILS_ENV"] = "test"
4
+ case
5
+ when ENV["RADIANT_ENV_FILE"]
6
+ require File.dirname(ENV["RADIANT_ENV_FILE"]) + "/boot"
7
+ when File.dirname(__FILE__) =~ %r{vendor/radiant/vendor/extensions}
8
+ require "#{File.expand_path(File.dirname(__FILE__) + "/../../../../../")}/config/boot"
9
+ else
10
+ require "#{File.expand_path(File.dirname(__FILE__) + "/../../../")}/config/boot"
11
+ end
12
+ end
13
+
14
+ require 'rake'
15
+ require 'rake/rdoctask'
16
+ require 'rake/testtask'
17
+
18
+ rspec_base = File.expand_path(RADIANT_ROOT + '/vendor/plugins/rspec/lib')
19
+ $LOAD_PATH.unshift(rspec_base) if File.exist?(rspec_base)
20
+ require 'spec/rake/spectask'
21
+ require 'cucumber'
22
+ require 'cucumber/rake/task'
23
+
24
+ # Cleanup the RADIANT_ROOT constant so specs will load the environment
25
+ Object.send(:remove_const, :RADIANT_ROOT)
26
+
27
+ extension_root = File.expand_path(File.dirname(__FILE__))
28
+
29
+ task :default => [:spec, :features]
30
+ task :stats => "spec:statsetup"
31
+
32
+ desc "Run all specs in spec directory"
33
+ Spec::Rake::SpecTask.new(:spec) do |t|
34
+ t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
35
+ t.spec_files = FileList['spec/**/*_spec.rb']
36
+ end
37
+
38
+ task :features => 'spec:integration'
39
+
40
+ namespace :spec do
41
+ desc "Run all specs in spec directory with RCov"
42
+ Spec::Rake::SpecTask.new(:rcov) do |t|
43
+ t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
44
+ t.spec_files = FileList['spec/**/*_spec.rb']
45
+ t.rcov = true
46
+ t.rcov_opts = ['--exclude', 'spec', '--rails']
47
+ end
48
+
49
+ desc "Print Specdoc for all specs"
50
+ Spec::Rake::SpecTask.new(:doc) do |t|
51
+ t.spec_opts = ["--format", "specdoc", "--dry-run"]
52
+ t.spec_files = FileList['spec/**/*_spec.rb']
53
+ end
54
+
55
+ [:models, :controllers, :views, :helpers].each do |sub|
56
+ desc "Run the specs under spec/#{sub}"
57
+ Spec::Rake::SpecTask.new(sub) do |t|
58
+ t.spec_opts = ['--options', "\"#{extension_root}/spec/spec.opts\""]
59
+ t.spec_files = FileList["spec/#{sub}/**/*_spec.rb"]
60
+ end
61
+ end
62
+
63
+ desc "Run the Cucumber features"
64
+ Cucumber::Rake::Task.new(:integration) do |t|
65
+ t.fork = true
66
+ t.cucumber_opts = ['--format', (ENV['CUCUMBER_FORMAT'] || 'pretty')]
67
+ # t.feature_pattern = "#{extension_root}/features/**/*.feature"
68
+ t.profile = "default"
69
+ end
70
+
71
+ # Setup specs for stats
72
+ task :statsetup do
73
+ require 'code_statistics'
74
+ ::STATS_DIRECTORIES << %w(Model\ specs spec/models)
75
+ ::STATS_DIRECTORIES << %w(View\ specs spec/views)
76
+ ::STATS_DIRECTORIES << %w(Controller\ specs spec/controllers)
77
+ ::STATS_DIRECTORIES << %w(Helper\ specs spec/views)
78
+ ::CodeStatistics::TEST_TYPES << "Model specs"
79
+ ::CodeStatistics::TEST_TYPES << "View specs"
80
+ ::CodeStatistics::TEST_TYPES << "Controller specs"
81
+ ::CodeStatistics::TEST_TYPES << "Helper specs"
82
+ ::STATS_DIRECTORIES.delete_if {|a| a[0] =~ /test/}
83
+ end
84
+
85
+ namespace :db do
86
+ namespace :fixtures do
87
+ desc "Load fixtures (from spec/fixtures) into the current environment's database. Load specific fixtures using FIXTURES=x,y"
88
+ task :load => :environment do
89
+ require 'active_record/fixtures'
90
+ ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym)
91
+ (ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/) : Dir.glob(File.join(RAILS_ROOT, 'spec', 'fixtures', '*.{yml,csv}'))).each do |fixture_file|
92
+ Fixtures.create_fixtures('spec/fixtures', File.basename(fixture_file, '.*'))
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+ desc 'Generate documentation for the archive extension.'
100
+ Rake::RDocTask.new(:rdoc) do |rdoc|
101
+ rdoc.rdoc_dir = 'rdoc'
102
+ rdoc.title = 'ArchiveExtension'
103
+ rdoc.options << '--line-numbers' << '--inline-source'
104
+ rdoc.rdoc_files.include('README')
105
+ rdoc.rdoc_files.include('lib/**/*.rb')
106
+ end
107
+
108
+ # Load any custom rakefiles for extension
109
+ Dir[File.dirname(__FILE__) + '/tasks/*.rake'].sort.each { |f| require f }
@@ -0,0 +1,32 @@
1
+ class ArchiveDayIndexPage < Page
2
+
3
+ def allowed_children
4
+ []
5
+ end
6
+
7
+ description %{
8
+ To create a day index for an archive, create a child page for the
9
+ archive and assign the "Archive Day Index" page type to it.
10
+
11
+ A day index page makes following tags available to you:
12
+
13
+ <r:archive:children>...</r:archive:children>
14
+ Grants access to a subset of the children of the archive page
15
+ that match the specific year which the index page is rendering.
16
+ }
17
+
18
+ include ArchiveIndexTagsAndMethods
19
+ desc %{
20
+ Grants access to a subset of the children of the archive page
21
+ that match the specific day which the index page is rendering.
22
+
23
+ *Usage*:
24
+ <pre><code><r:archive:children>...</r:archive:children></code></pre>
25
+ }
26
+ tag "archive:children" do |tag|
27
+ year, month, day = $1, $2, $3 if request_uri =~ %r{/(\d{4})/(\d{2})/(\d{2})/?$}
28
+ tag.locals.children = ArchiveFinder.day_finder(parent.children, year, month, day)
29
+ tag.expand
30
+ end
31
+
32
+ end
@@ -0,0 +1,60 @@
1
+ class ArchiveFinder
2
+
3
+ def initialize(&block)
4
+ @block = block
5
+ end
6
+
7
+ def find(method, options = {})
8
+ @block.call(method, options)
9
+ end
10
+
11
+ # stub for page tag finding
12
+ def all(options ={})
13
+ self.find(:all, options)
14
+ end
15
+
16
+ class << self
17
+ def year_finder(finder, year)
18
+ new do |method, options|
19
+ start = Time.local(year)
20
+ finish = start.next_year
21
+ add_condition(options, "published_at >= ? and published_at < ?", start, finish)
22
+ finder.find(method, options)
23
+ end
24
+ end
25
+
26
+ def month_finder(finder, year, month)
27
+ new do |method, options|
28
+ start = Time.local(year, month)
29
+ finish = start.next_month
30
+ add_condition(options, "published_at >= ? and published_at < ?", start, finish)
31
+ finder.find(method, options)
32
+ end
33
+ end
34
+
35
+ def day_finder(finder, year, month, day)
36
+ new do |method, options|
37
+ start = Time.local(year, month, day)
38
+ finish = start.tomorrow
39
+ add_condition(options, "published_at >= ? and published_at < ?", start, finish)
40
+ finder.find(method, options)
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def concat_conditions(a, b)
47
+ sql = "(#{ [a.shift, b.shift].compact.join(") AND (") })"
48
+ params = a + b
49
+ [sql, *params]
50
+ end
51
+
52
+ def add_condition(options, *condition)
53
+ old = options[:conditions] || []
54
+ conditions = concat_conditions(old, condition)
55
+ options[:conditions] = conditions
56
+ options
57
+ end
58
+
59
+ end
60
+ end
@@ -0,0 +1,32 @@
1
+ class ArchiveMonthIndexPage < Page
2
+
3
+ def allowed_children
4
+ []
5
+ end
6
+
7
+ description %{
8
+ To create a month index for an archive, create a child page for the
9
+ archive and assign the "Archive Month Index" page type to it.
10
+
11
+ A month index page makes following tags available to you:
12
+
13
+ <r:archive:children>...</r:archive:children>
14
+ Grants access to a subset of the children of the archive page
15
+ that match the specific year which the index page is rendering.
16
+ }
17
+
18
+ include ArchiveIndexTagsAndMethods
19
+ desc %{
20
+ Grants access to a subset of the children of the archive page
21
+ that match the specific month which the index page is rendering.
22
+
23
+ *Usage*:
24
+ <pre><code><r:archive:children>...</r:archive:children></code></pre>
25
+ }
26
+ tag "archive:children" do |tag|
27
+ year, month = $1, $2 if request_uri =~ %r{/(\d{4})/(\d{2})/?$}
28
+ tag.locals.children = ArchiveFinder.month_finder(parent.children, year, month)
29
+ tag.expand
30
+ end
31
+
32
+ end
@@ -0,0 +1,77 @@
1
+ class ArchivePage < Page
2
+ cattr_accessor :allowed_children
3
+ cattr_accessor :single_use_children
4
+ @@single_use_children = [ArchiveDayIndexPage, ArchiveMonthIndexPage, ArchiveYearIndexPage, FileNotFoundPage]
5
+ @@allowed_children = [self.default_child, *@@single_use_children]
6
+
7
+ def allowed_children
8
+ overlap = @@allowed_children & (existing_child_types - [default_child])
9
+
10
+ (@@allowed_children - overlap)
11
+ end
12
+
13
+ def existing_child_types
14
+ children(:select => 'DISTINCT class_name', :order => nil).collect{|p| p.class }.uniq
15
+ end
16
+
17
+ description %{
18
+ An archive page provides behavior similar to a blog archive or a news
19
+ archive. Child page URLs are altered to be in %Y/%m/%d format
20
+ (2004/05/06).
21
+
22
+ An archive page can be used in conjunction with the "Archive Year Index",
23
+ "Archive Month Index", and "Archive Day Index" page types to create year,
24
+ month, and day indexes.
25
+ }
26
+
27
+ def child_path(child)
28
+ year, month, day = $1, ($2 || 1).to_i, ($3 || 1).to_i if child.request and child.request.request_uri =~ %r{/(\d{4})(?:/(\d{2})(?:/(\d{2}))?)?/?$}
29
+
30
+ if year && %w{ ArchiveYearIndexPage ArchiveMonthIndexPage ArchiveDayIndexPage }.include?(child.class_name)
31
+ date = Date.new(year.to_i, month, day)
32
+ if ArchiveYearIndexPage === child
33
+ clean_path "#{ path }/#{ date.strftime '%Y' }/"
34
+ elsif ArchiveMonthIndexPage === child
35
+ clean_path "#{ path }/#{ date.strftime '%Y/%m' }/"
36
+ else ArchiveDayIndexPage === child
37
+ clean_path "#{ path }/#{ date.strftime '%Y/%m/%d/' }/"
38
+ end
39
+ else
40
+ if child.published_at?
41
+ clean_path "#{ path }/#{ child.published_at.strftime '%Y/%m/%d' }/#{ child.slug }"
42
+ else
43
+ clean_path "#{ path }/#{ Time.zone.now.strftime '%Y/%m/%d' }/#{ child.slug }"
44
+ end
45
+ end
46
+ end
47
+ def child_url(child)
48
+ ActiveSupport::Deprecation.warn("`child_url' has been deprecated; use `child_path' instead.", caller)
49
+ child_path(child)
50
+ end
51
+
52
+ def find_by_path(path, live = true, clean = false)
53
+ path = clean_path(path) if clean
54
+ if path =~ %r{^#{ self.path }(\d{4})(?:/(\d{2})(?:/(\d{2})(?:/([-_.A-Za-z0-9]*))?)?)?/?$}
55
+ year, month, day, slug = $1, $2, $3, $4
56
+ children.find_by_class_name(
57
+ case
58
+ when slug.present?
59
+ found = children.find_by_slug(slug)
60
+ return found if found
61
+ when day.present?
62
+ 'ArchiveDayIndexPage'
63
+ when month.present?
64
+ 'ArchiveMonthIndexPage'
65
+ else
66
+ 'ArchiveYearIndexPage'
67
+ end
68
+ )
69
+ else
70
+ super
71
+ end
72
+ end
73
+ def find_by_url(*args)
74
+ ActiveSupport::Deprecation.warn("`find_by_url' has been deprecated; use `find_by_path' instead.", caller)
75
+ find_by_path(*args)
76
+ end
77
+ end
@@ -0,0 +1,32 @@
1
+ class ArchiveYearIndexPage < Page
2
+
3
+ def allowed_children
4
+ []
5
+ end
6
+
7
+ description %{
8
+ To create a year index for an archive, create a child page for the
9
+ archive and assign the "Archive Year Index" page type to it.
10
+
11
+ A year index page makes following tags available to you:
12
+
13
+ <r:archive:children>...</r:archive:children>
14
+ Grants access to a subset of the children of the archive page
15
+ that match the specific year which the index page is rendering.
16
+ }
17
+
18
+ include ArchiveIndexTagsAndMethods
19
+ desc %{
20
+ Grants access to a subset of the children of the archive page
21
+ that match the specific year which the index page is rendering.
22
+
23
+ *Usage*:
24
+ <pre><code><r:archive:children>...</r:archive:children></code></pre>
25
+ }
26
+ tag "archive:children" do |tag|
27
+ year = $1 if request_uri =~ %r{/(\d{4})/?$}
28
+ tag.locals.children = ArchiveFinder.year_finder(parent.children, year)
29
+ tag.expand
30
+ end
31
+
32
+ end
@@ -0,0 +1,20 @@
1
+ # Uncomment this if you reference any of your controllers in activate
2
+ # require_dependency 'application_controller'
3
+ require 'radiant-archive-extension/version'
4
+ class ArchiveExtension < Radiant::Extension
5
+ version RadiantArchiveExtension::VERSION
6
+ description "Provides page types for news or blog archives."
7
+ url "http://radiantcms.org/"
8
+
9
+ def activate
10
+ # allow bootstrap
11
+ if Page.table_exists?
12
+ Page.class_eval do
13
+ def allowed_children_with_archive
14
+ allowed_children_without_archive.reject { |p| p.name =~ /Archive(Day|Month|Year)IndexPage/ }
15
+ end
16
+ alias_method_chain :allowed_children, :archive
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,3 @@
1
+ Radiant.config do |config|
2
+ # config.define "setting.name", :default => 'value', :select_from => ['foo', 'bar']
3
+ end
@@ -0,0 +1,3 @@
1
+ ---
2
+ en:
3
+ archive: Archive
data/config/routes.rb ADDED
@@ -0,0 +1,5 @@
1
+ ActionController::Routing::Routes.draw do |map|
2
+ # map.namespace :admin, :member => { :remove => :get } do |admin|
3
+ # admin.resources :archive
4
+ # end
5
+ end
data/cucumber.yml ADDED
@@ -0,0 +1 @@
1
+ default: --format progress features --tags ~@proposed,~@in_progress
@@ -0,0 +1,51 @@
1
+ Feature: Serving pages from front-end
2
+ In order to view the website content properly
3
+ a visitor
4
+ wants to see archive enhancements
5
+
6
+ Scenario: Archive page basic rendering
7
+ Given I am logged in as "existing"
8
+ When I edit the "archive" page
9
+ And I fill in the "body" content with the text
10
+ """
11
+ <h1>Articles</h1>
12
+ <r:children:each><p><r:link /></p>
13
+ </r:children:each><p>Thanks for reading!</p>
14
+ """
15
+ And I press "Save Changes"
16
+ And I visit the "archive" page
17
+ Then the page should render
18
+ """
19
+ <h1>Articles</h1>
20
+ <p><a href="/archive/2000/01/01/article-z/">Article Z</a></p>
21
+ <p><a href="/archive/2000/01/02/early-post/">Early Post</a></p>
22
+ <p><a href="/archive/2000/01/03/z-post/">Z Post</a></p>
23
+ <p><a href="/archive/2000/01/04/a-post/">A Post</a></p>
24
+ <p><a href="/archive/2001/02/02/article-y/">Article Y</a></p>
25
+ <p><a href="/archive/2002/03/03/article-x/">Article X</a></p>
26
+ <p><a href="/archive/2003/04/04/article-w/">Article W</a></p>
27
+ <p><a href="/archive/2004/05/05/article-v/">Article V</a></p>
28
+ <p>Thanks for reading!</p>
29
+ """
30
+
31
+
32
+ Scenario: Archive Monthly Index children rendering
33
+ Given I am logged in as "existing"
34
+ When I edit the "month_index" page
35
+ And I fill in the "body" content with the text
36
+ """
37
+ <h1>This Month's Articles</h1>
38
+ <r:archive:children:each><p><r:link /></p>
39
+ </r:archive:children:each><p>Thanks for reading the Monthly Archive!</p>
40
+ """
41
+ And I press "Save Changes"
42
+ And I visit "/archive/2000/01/"
43
+ Then the page should render
44
+ """
45
+ <h1>This Month's Articles</h1>
46
+ <p><a href="/archive/2000/01/01/article-z/">Article Z</a></p>
47
+ <p><a href="/archive/2000/01/02/early-post/">Early Post</a></p>
48
+ <p><a href="/archive/2000/01/03/z-post/">Z Post</a></p>
49
+ <p><a href="/archive/2000/01/04/a-post/">A Post</a></p>
50
+ <p>Thanks for reading the Monthly Archive!</p>
51
+ """
@@ -0,0 +1,7 @@
1
+ Given /^I visit the "([^"]*)" page$/ do |slug|
2
+ visit Page.find_by_slug(slug).path
3
+ end
4
+
5
+ Given /^I visit "([^"]*)"$/ do |path|
6
+ visit path
7
+ end
@@ -0,0 +1,3 @@
1
+ Cucumber::Rails::World.class_eval do
2
+ dataset :users, :archive
3
+ end
@@ -0,0 +1,11 @@
1
+ # Sets up the Rails environment for Cucumber
2
+ ENV["RAILS_ENV"] = "test"
3
+ # Extension root
4
+ extension_env = File.expand_path(File.dirname(__FILE__) + '/../../../../../config/environment')
5
+ require extension_env+'.rb'
6
+
7
+ Dir.glob(File.join(RADIANT_ROOT, "features", "**", "*.rb")).each {|step| require step unless step =~ /datasets_loader\.rb$/}
8
+
9
+ Cucumber::Rails::World.class_eval do
10
+ dataset :archive
11
+ end
@@ -0,0 +1,3 @@
1
+ Dir.glob("#{RADIANT_ROOT}/spec/matchers/*.rb").each do |matcher|
2
+ require matcher
3
+ end
@@ -0,0 +1,22 @@
1
+ module NavigationHelpers
2
+
3
+ # Extend the standard PathMatchers with your own paths
4
+ # to be used in your features.
5
+ #
6
+ # The keys and values here may be used in your standard web steps
7
+ # Using:
8
+ #
9
+ # When I go to the "archive" admin page
10
+ #
11
+ # would direct the request to the path you provide in the value:
12
+ #
13
+ # admin_archive_path
14
+ #
15
+ PathMatchers = {} unless defined?(PathMatchers)
16
+ PathMatchers.merge!({
17
+ # /archive/i => 'admin_archive_path'
18
+ })
19
+
20
+ end
21
+
22
+ World(NavigationHelpers)
@@ -0,0 +1,77 @@
1
+ module ArchiveIndexTagsAndMethods
2
+
3
+ include Radiant::Taggable
4
+
5
+ desc %{
6
+ Scope tags for an ArchivePage
7
+ }
8
+ tag "archive" do |tag|
9
+ tag.expand
10
+ end
11
+
12
+ [:title, :breadcrumb].each do |method|
13
+ tag method.to_s do |tag|
14
+ setup_date_parts
15
+ page = tag.locals.page
16
+ unless @year.nil?
17
+ Date.new((@year || 1).to_i, (@month || 1).to_i, (@day || 1).to_i).strftime(page.send(method))
18
+ else
19
+ page.send(method)
20
+ end
21
+ end
22
+ end
23
+
24
+ desc %{
25
+ Display the year for the current Archive
26
+ }
27
+ tag "archive:year" do |tag|
28
+ setup_date_parts
29
+ @year.to_i unless @year.nil?
30
+ end
31
+
32
+
33
+ desc %{
34
+ Display the month for the current Archive
35
+ }
36
+ tag "archive:month" do |tag|
37
+ setup_date_parts
38
+ Date.new(@year.to_i, @month.to_i, 1).strftime('%B') rescue ''
39
+ end
40
+
41
+
42
+ desc %{
43
+ Display the day for the current Archive
44
+ }
45
+ tag "archive:day" do |tag|
46
+ setup_date_parts
47
+ @day.to_i unless @day.nil?
48
+ end
49
+
50
+
51
+ desc %{
52
+ Display the day of the week for the current Archive
53
+ }
54
+ tag "archive:day_of_week" do |tag|
55
+ setup_date_parts
56
+ Date.new(@year.to_i, @month.to_i, @day.to_i).strftime('%A') rescue ''
57
+ end
58
+
59
+ tag("archive:children:first") { "unimplemented" }
60
+ tag("archive:children:last" ) { "unimplemented" }
61
+ tag("archive:children:count") { "unimplemented" }
62
+
63
+ def virtual?
64
+ true
65
+ end
66
+
67
+ private
68
+
69
+ def request_uri
70
+ request.request_uri unless request.nil?
71
+ end
72
+
73
+ def setup_date_parts
74
+ @year, @month, @day = $1, $2, $3 if request_uri =~ %r{/(\d{4})(?:/(\d{2})(?:/(\d{2}))?)?/?$}
75
+ end
76
+
77
+ end
@@ -0,0 +1,2 @@
1
+ module RadiantArchiveExtension
2
+ end
@@ -0,0 +1,3 @@
1
+ module RadiantArchiveExtension
2
+ VERSION = '1.0.0'
3
+ end
@@ -0,0 +1,55 @@
1
+ namespace :radiant do
2
+ namespace :extensions do
3
+ namespace :archive do
4
+
5
+ desc "Runs the migration of the Archive extension"
6
+ task :migrate => :environment do
7
+ require 'radiant/extension_migrator'
8
+ if ENV["VERSION"]
9
+ ArchiveExtension.migrator.migrate(ENV["VERSION"].to_i)
10
+ Rake::Task['db:schema:dump'].invoke
11
+ else
12
+ ArchiveExtension.migrator.migrate
13
+ Rake::Task['db:schema:dump'].invoke
14
+ end
15
+ end
16
+
17
+ desc "Copies public assets of the Archive to the instance public/ directory."
18
+ task :update => :environment do
19
+ is_svn_or_dir = proc {|path| path =~ /\.svn/ || File.directory?(path) }
20
+ puts "Copying assets from ArchiveExtension"
21
+ Dir[ArchiveExtension.root + "/public/**/*"].reject(&is_svn_or_dir).each do |file|
22
+ path = file.sub(ArchiveExtension.root, '')
23
+ directory = File.dirname(path)
24
+ mkdir_p RAILS_ROOT + directory, :verbose => false
25
+ cp file, RAILS_ROOT + path, :verbose => false
26
+ end
27
+ unless ArchiveExtension.root.starts_with? RAILS_ROOT # don't need to copy vendored tasks
28
+ puts "Copying rake tasks from ArchiveExtension"
29
+ local_tasks_path = File.join(RAILS_ROOT, %w(lib tasks))
30
+ mkdir_p local_tasks_path, :verbose => false
31
+ Dir[File.join ArchiveExtension.root, %w(lib tasks *.rake)].each do |file|
32
+ cp file, local_tasks_path, :verbose => false
33
+ end
34
+ end
35
+ end
36
+
37
+ desc "Syncs all available translations for this ext to the English ext master"
38
+ task :sync => :environment do
39
+ # The main translation root, basically where English is kept
40
+ language_root = ArchiveExtension.root + "/config/locales"
41
+ words = TranslationSupport.get_translation_keys(language_root)
42
+
43
+ Dir["#{language_root}/*.yml"].each do |filename|
44
+ next if filename.match('_available_tags')
45
+ basename = File.basename(filename, '.yml')
46
+ puts "Syncing #{basename}"
47
+ (comments, other) = TranslationSupport.read_file(filename, basename)
48
+ words.each { |k,v| other[k] ||= words[k] } # Initializing hash variable as empty if it does not exist
49
+ other.delete_if { |k,v| !words[k] } # Remove if not defined in en.yml
50
+ TranslationSupport.write_file(filename, basename, comments, other)
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "radiant-archive-extension/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "radiant-archive-extension"
7
+ s.version = RadiantArchiveExtension::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Radiant CMS Dev Team"]
10
+ s.email = ["radiant@radiantcms.org"]
11
+ s.homepage = "http://radiantcms.org"
12
+ s.summary = %q{Archive for Radiant CMS}
13
+ s.description = %q{Provides page types for news or blog archives.}
14
+
15
+ ignores = if File.exist?('.gitignore')
16
+ File.read('.gitignore').split("\n").inject([]) {|a,p| a + Dir[p] }
17
+ else
18
+ []
19
+ end
20
+ s.files = Dir['**/*'] - ignores
21
+ s.test_files = Dir['test/**/*','spec/**/*','features/**/*'] - ignores
22
+ # s.executables = Dir['bin/*'] - ignores
23
+ s.require_paths = ["lib"]
24
+
25
+ s.post_install_message = %{
26
+ Add this to your radiant project with:
27
+ config.gem 'radiant-archive-extension', :version => '~>#{RadiantArchiveExtension::VERSION}'
28
+ }
29
+ end
@@ -0,0 +1,55 @@
1
+ class ArchiveDataset < Dataset::Base
2
+ uses :home_page
3
+
4
+ def load
5
+ create_page "Archive", :class_name => "ArchivePage" do
6
+ create_page "Year Index", :class_name => "ArchiveYearIndexPage", :title => "%Y Archive", :virtual => true # dataset won't load this
7
+ create_page "Month Index", :class_name => "ArchiveMonthIndexPage", :title => "%B %Y Archive", :virtual => true # dataset won't load this
8
+ create_page "Day Index", :class_name => "ArchiveDayIndexPage", :title => "%B %d, %Y Archive", :virtual => true # dataset won't load this
9
+ %w{Z Y X W V}.each_with_index do |letter, index|
10
+ i = index + 1
11
+ create_page "Article #{letter}", :published_at => Time.local(1999+i, i, i).to_s(:db)
12
+ end
13
+ create_page "Early Post", :published_at => Time.local(2000, 01, 02).to_s(:db)
14
+ create_page "Z Post", :published_at => Time.local(2000, 01, 03).to_s(:db)
15
+ create_page "A Post", :published_at => Time.local(2000, 01, 04).to_s(:db)
16
+ create_page "Draft Article", :status_id => Status[:draft].id, :published_at => nil
17
+ end
18
+ end
19
+
20
+ helpers do
21
+ describe "Archive index page", :shared => true do
22
+ it "should be virtual" do
23
+ @page.should be_virtual
24
+ end
25
+
26
+ it "should render <r:archive:children:first /> as unimplemented" do
27
+ @page.should render('<r:archive:children:first><r:slug /></r:archive:children:first>').as('unimplemented')
28
+ end
29
+
30
+ it "should render <r:archive:children:last /> as unimplemented" do
31
+ @page.should render('<r:archive:children:last><r:slug /></r:archive:children:last>').as('unimplemented')
32
+ end
33
+
34
+ it "should <r:archive:children:count /> as unimplemented" do
35
+ @page.should render('<r:archive:children:count><r:slug /></r:archive:children:count>').as('unimplemented')
36
+ end
37
+
38
+ it "should render the <r:archive:year /> tag" do
39
+ @page.should render("<r:archive:year />").as("2000").on("/archive/2000/")
40
+ end
41
+
42
+ it "should render the <r:archive:month /> tag" do
43
+ @page.should render("<r:archive:month />").as("June").on("/archive/2000/06/")
44
+ end
45
+
46
+ it "should render the <r:archive:day /> tag" do
47
+ @page.should render('<r:archive:day />').as("9").on('/archive/2000/06/09/')
48
+ end
49
+
50
+ it "should render the <r:archive:day_of_week /> tag" do
51
+ @page.should render('<r:archive:day_of_week />').as('Friday').on("/archive/2000/06/09/")
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,30 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe ArchiveDayIndexPage do
4
+ dataset :archive
5
+
6
+ before :each do
7
+ @page = pages(:day_index)
8
+ end
9
+
10
+ its(:allowed_children){ should == [] }
11
+
12
+ it_should_behave_like "Archive index page"
13
+
14
+ it "should render the <r:archive:children:each /> tag" do
15
+ @page.should render('<r:archive:children:each><r:slug /> </r:archive:children:each>').as('article-y ').on('/archive/2001/02/02/')
16
+ @page.should render('<r:archive:children:each><r:slug /> </r:archive:children:each>').as('article-y ').on('/archive/2001/02/02')
17
+ end
18
+
19
+ it "should render the <r:title /> tag with interpolated date" do
20
+ @page.should render('<r:title />').as('June 09, 2000 Archive').on('/archive/2000/06/09/')
21
+ end
22
+
23
+ it "should render the <r:breadcrumb /> tag with interpolated date" do
24
+ @page.should render('<r:breadcrumb />').as('June 09, 2000 Archive').on('/archive/2000/06/09/')
25
+ end
26
+
27
+ it "should render the <r:url /> tag with interpolated date" do
28
+ @page.should render('<r:url />').as('/archive/2000/06/09/').on('/archive/2000/06/09')
29
+ end
30
+ end
@@ -0,0 +1,34 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe ArchiveMonthIndexPage do
4
+ dataset :archive
5
+
6
+ before :each do
7
+ @page = pages(:month_index)
8
+ end
9
+
10
+ its(:allowed_children){ should == [] }
11
+
12
+ it_should_behave_like "Archive index page"
13
+
14
+ it "should render the <r:archive:children:each /> tag" do
15
+ @page.should render('<r:archive:children:each><r:slug /> </r:archive:children:each>').as('article-y ').on('/archive/2001/02/')
16
+ @page.should render('<r:archive:children:each><r:slug /> </r:archive:children:each>').as('article-y ').on('/archive/2001/02')
17
+ end
18
+
19
+ it "should render the <r:title /> tag with interpolated date" do
20
+ @page.should render('<r:title />').as('June 2000 Archive').on('/archive/2000/06/')
21
+ end
22
+
23
+ it "should render the <r:breadcrumb /> tag with interpolated date" do
24
+ @page.should render('<r:breadcrumb />').as('June 2000 Archive').on('/archive/2000/06/')
25
+ end
26
+
27
+ it "should render the <r:path /> tag with interpolated date" do
28
+ @page.should render('<r:path />').as('/archive/2000/06/').on('/archive/2000/06')
29
+ end
30
+
31
+ it "should properly render the <r:path /> tag of an archive child with interpolated date" do
32
+ @page.should render('<r:archive:children:each><r:path /> </r:archive:children:each>').as('/archive/2000/01/01/article-z/ /archive/2000/01/02/early-post/ /archive/2000/01/03/z-post/ /archive/2000/01/04/a-post/ ').on('/archive/2000/01/')
33
+ end
34
+ end
@@ -0,0 +1,56 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe ArchivePage do
4
+ dataset :archive
5
+
6
+ let(:archive){ pages(:archive) }
7
+
8
+ it "should not render archive index pages" do
9
+ archive.should render('<r:children:each><r:slug /> </r:children:each>').as('article-z early-post z-post a-post article-y article-x article-w article-v ')
10
+ end
11
+
12
+ it "should scope child URLs by date" do
13
+ pages(:article_z).url.should == '/archive/2000/01/01/article-z/'
14
+ end
15
+
16
+ it "should scope unpublished children by the current date" do
17
+ pages(:draft_article).url.should == '/archive/' + Time.zone.now.strftime('%Y/%m/%d') + '/draft-article/'
18
+ end
19
+
20
+ it "should find the year index" do
21
+ archive.find_by_path('/archive/2000/').should == pages(:year_index)
22
+ end
23
+
24
+ it "should find the month index" do
25
+ archive.find_by_path('/archive/2000/06/').should == pages(:month_index)
26
+ end
27
+
28
+ it "should find the day index" do
29
+ archive.find_by_path('/archive/2000/06/09/').should == pages(:day_index)
30
+ end
31
+
32
+ it "should find child URLs from the homepage" do
33
+ pages(:home).find_by_path('/archive/2000/01/01/article-z/').should == pages(:article_z)
34
+ end
35
+
36
+ its(:single_use_children){ should == [ArchiveDayIndexPage, ArchiveMonthIndexPage, ArchiveYearIndexPage, FileNotFoundPage]}
37
+ its(:allowed_children){ should == [Page, *ArchivePage.single_use_children]}
38
+
39
+ describe '#existing_child_types' do
40
+ it 'should return a unique array of classes of the page children' do
41
+ archive.existing_child_types.should == archive.children.all(:select => 'DISTINCT class_name').collect{|p| p.class }.uniq
42
+ end
43
+ end
44
+
45
+ describe '#allowed_children' do
46
+ context 'when no children exist' do
47
+ subject{ ArchivePage.new }
48
+ its(:allowed_children){ should == ArchivePage.allowed_children }
49
+ end
50
+ it 'should remove any existing single_use_children from the allowed_children' do
51
+ existing_except_default = archive.existing_child_types - [archive.default_child]
52
+ used_allowed_children = ArchivePage.allowed_children & existing_except_default
53
+ archive.allowed_children.should == (ArchivePage.allowed_children - used_allowed_children)
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,31 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe ArchiveYearIndexPage do
4
+ dataset :archive
5
+
6
+ before :each do
7
+ @page = pages(:year_index)
8
+ end
9
+
10
+ its(:allowed_children){ should == [] }
11
+
12
+ it_should_behave_like "Archive index page"
13
+
14
+ it "should render the <r:archive:children:each /> tag" do
15
+ @page.should render('<r:archive:children:each><r:slug /> </r:archive:children:each>').as('article-y ').on('/archive/2001/')
16
+ @page.should render('<r:archive:children:each><r:slug /> </r:archive:children:each>').as('article-y ').on('/archive/2001')
17
+ end
18
+
19
+ it "should render the <r:title /> tag with interpolated date" do
20
+ @page.should render('<r:title />').as('2000 Archive').on('/archive/2000')
21
+ end
22
+
23
+ it "should render the <r:breadcrumb /> tag with interpolated date" do
24
+ @page.should render('<r:breadcrumb />').as('2000 Archive').on('/archive/2000')
25
+ end
26
+
27
+ it "should render the <r:url /> tag with interpolated date" do
28
+ @page.should render('<r:url />').as('/archive/2000/').on('/archive/2000')
29
+ end
30
+
31
+ end
@@ -0,0 +1,6 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper'
2
+
3
+ describe Page do
4
+ its(:default_child){ should == Page}
5
+ its(:allowed_children){ should == [Page, *Page.descendants.sort_by(&:name)].select(&:in_menu?).reject{|p| p.name =~ /Archive(Day|Month|Year)IndexPage/}}
6
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1,6 @@
1
+ --colour
2
+ --format
3
+ progress
4
+ --loadby
5
+ mtime
6
+ --reverse
@@ -0,0 +1,36 @@
1
+ unless defined? RADIANT_ROOT
2
+ ENV["RAILS_ENV"] = "test"
3
+ case
4
+ when ENV["RADIANT_ENV_FILE"]
5
+ require ENV["RADIANT_ENV_FILE"]
6
+ when File.dirname(__FILE__) =~ %r{vendor/radiant/vendor/extensions}
7
+ require "#{File.expand_path(File.dirname(__FILE__) + "/../../../../../../")}/config/environment"
8
+ else
9
+ require "#{File.expand_path(File.dirname(__FILE__) + "/../../../../")}/config/environment"
10
+ end
11
+ end
12
+ require "#{RADIANT_ROOT}/spec/spec_helper"
13
+
14
+ Dataset::Resolver.default << (File.dirname(__FILE__) + "/datasets")
15
+
16
+ if File.directory?(File.dirname(__FILE__) + "/matchers")
17
+ Dir[File.dirname(__FILE__) + "/matchers/*.rb"].each {|file| require file }
18
+ end
19
+
20
+ Spec::Runner.configure do |config|
21
+ # config.use_transactional_fixtures = true
22
+ # config.use_instantiated_fixtures = false
23
+ # config.fixture_path = RAILS_ROOT + '/spec/fixtures'
24
+
25
+ # You can declare fixtures for each behaviour like this:
26
+ # describe "...." do
27
+ # fixtures :table_a, :table_b
28
+ #
29
+ # Alternatively, if you prefer to declare them only once, you can
30
+ # do so here, like so ...
31
+ #
32
+ # config.global_fixtures = :table_a, :table_b
33
+ #
34
+ # If you declare global fixtures, be aware that they will be declared
35
+ # for all of your examples, even those that don't use them.
36
+ end
metadata ADDED
@@ -0,0 +1,111 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: radiant-archive-extension
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease:
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ version: 1.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Radiant CMS Dev Team
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-06-11 00:00:00 -04:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: Provides page types for news or blog archives.
23
+ email:
24
+ - radiant@radiantcms.org
25
+ executables: []
26
+
27
+ extensions: []
28
+
29
+ extra_rdoc_files: []
30
+
31
+ files:
32
+ - app/models/archive_day_index_page.rb
33
+ - app/models/archive_finder.rb
34
+ - app/models/archive_month_index_page.rb
35
+ - app/models/archive_page.rb
36
+ - app/models/archive_year_index_page.rb
37
+ - archive_extension.rb
38
+ - config/initializers/radiant_config.rb
39
+ - config/locales/en.yml
40
+ - config/routes.rb
41
+ - cucumber.yml
42
+ - features/archive_content.feature
43
+ - features/step_definitions/web_steps.rb
44
+ - features/support/datasets_loader.rb
45
+ - features/support/env.rb
46
+ - features/support/matchers.rb
47
+ - features/support/paths.rb
48
+ - lib/archive_index_tags_and_methods.rb
49
+ - lib/radiant-archive-extension/version.rb
50
+ - lib/radiant-archive-extension.rb
51
+ - lib/tasks/archive_extension_tasks.rake
52
+ - radiant-archive-extension.gemspec
53
+ - Rakefile
54
+ - README
55
+ - spec/datasets/archive_dataset.rb
56
+ - spec/models/archive_day_index_page_spec.rb
57
+ - spec/models/archive_month_index_page_spec.rb
58
+ - spec/models/archive_page_spec.rb
59
+ - spec/models/archive_year_index_page_spec.rb
60
+ - spec/models/page_spec.rb
61
+ - spec/spec.opts
62
+ - spec/spec_helper.rb
63
+ has_rdoc: true
64
+ homepage: http://radiantcms.org
65
+ licenses: []
66
+
67
+ post_install_message: "\n Add this to your radiant project with:\n config.gem 'radiant-archive-extension', :version => '~>1.0.0'\n "
68
+ rdoc_options: []
69
+
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ hash: 3
78
+ segments:
79
+ - 0
80
+ version: "0"
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ hash: 3
87
+ segments:
88
+ - 0
89
+ version: "0"
90
+ requirements: []
91
+
92
+ rubyforge_project:
93
+ rubygems_version: 1.6.2
94
+ signing_key:
95
+ specification_version: 3
96
+ summary: Archive for Radiant CMS
97
+ test_files:
98
+ - spec/datasets/archive_dataset.rb
99
+ - spec/models/archive_day_index_page_spec.rb
100
+ - spec/models/archive_month_index_page_spec.rb
101
+ - spec/models/archive_page_spec.rb
102
+ - spec/models/archive_year_index_page_spec.rb
103
+ - spec/models/page_spec.rb
104
+ - spec/spec.opts
105
+ - spec/spec_helper.rb
106
+ - features/archive_content.feature
107
+ - features/step_definitions/web_steps.rb
108
+ - features/support/datasets_loader.rb
109
+ - features/support/env.rb
110
+ - features/support/matchers.rb
111
+ - features/support/paths.rb