radiant-tags-extension 1.5.1
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/HELP.md +50 -0
- data/HELP_admin.md +30 -0
- data/README +38 -0
- data/Rakefile +25 -0
- data/app/models/meta_tag.rb +53 -0
- data/app/models/radius_tags.rb +328 -0
- data/app/models/tag_search_page.rb +87 -0
- data/app/models/tagging.rb +10 -0
- data/app/views/admin/help/_using_tags.html.haml +4 -0
- data/app/views/admin/pages/_tag_field.html.haml +8 -0
- data/db/migrate/001_add_tag_support.rb +20 -0
- data/lib/tagging_methods.rb +128 -0
- data/lib/tasks/tags_extension_tasks.rake +32 -0
- data/public/stylesheets/tags.css +11 -0
- data/tags_extension.rb +57 -0
- data/test/fixtures/meta_tags.yml +12 -0
- data/test/fixtures/page_parts.yml +17 -0
- data/test/fixtures/pages.yml +43 -0
- data/test/fixtures/taggings.yml +20 -0
- data/test/functional/tag_search_page_test.rb +44 -0
- data/test/functional/tags_extension_test.rb +19 -0
- data/test/helpers/render_test_helper.rb +60 -0
- data/test/test_helper.rb +20 -0
- data/test/unit/page_taggability_test.rb +20 -0
- data/vendor/plugins/has_many_polymorphs/.gitignore +1 -0
- data/vendor/plugins/has_many_polymorphs/CHANGELOG +86 -0
- data/vendor/plugins/has_many_polymorphs/LICENSE +184 -0
- data/vendor/plugins/has_many_polymorphs/Manifest +173 -0
- data/vendor/plugins/has_many_polymorphs/README +205 -0
- data/vendor/plugins/has_many_polymorphs/Rakefile +28 -0
- data/vendor/plugins/has_many_polymorphs/TODO +2 -0
- data/vendor/plugins/has_many_polymorphs/examples/hmph.rb +69 -0
- data/vendor/plugins/has_many_polymorphs/generators/tagging/tagging_generator.rb +97 -0
- data/vendor/plugins/has_many_polymorphs/generators/tagging/templates/migration.rb +28 -0
- data/vendor/plugins/has_many_polymorphs/generators/tagging/templates/tag.rb +39 -0
- data/vendor/plugins/has_many_polymorphs/generators/tagging/templates/tag_test.rb +15 -0
- data/vendor/plugins/has_many_polymorphs/generators/tagging/templates/tagging.rb +16 -0
- data/vendor/plugins/has_many_polymorphs/generators/tagging/templates/tagging_extensions.rb +203 -0
- data/vendor/plugins/has_many_polymorphs/generators/tagging/templates/tagging_test.rb +85 -0
- data/vendor/plugins/has_many_polymorphs/generators/tagging/templates/taggings.yml +23 -0
- data/vendor/plugins/has_many_polymorphs/generators/tagging/templates/tags.yml +7 -0
- data/vendor/plugins/has_many_polymorphs/init.rb +2 -0
- data/vendor/plugins/has_many_polymorphs/lib/has_many_polymorphs/association.rb +160 -0
- data/vendor/plugins/has_many_polymorphs/lib/has_many_polymorphs/autoload.rb +69 -0
- data/vendor/plugins/has_many_polymorphs/lib/has_many_polymorphs/base.rb +60 -0
- data/vendor/plugins/has_many_polymorphs/lib/has_many_polymorphs/class_methods.rb +600 -0
- data/vendor/plugins/has_many_polymorphs/lib/has_many_polymorphs/configuration.rb +19 -0
- data/vendor/plugins/has_many_polymorphs/lib/has_many_polymorphs/debugging_tools.rb +103 -0
- data/vendor/plugins/has_many_polymorphs/lib/has_many_polymorphs/rake_task_redefine_task.rb +35 -0
- data/vendor/plugins/has_many_polymorphs/lib/has_many_polymorphs/reflection.rb +58 -0
- data/vendor/plugins/has_many_polymorphs/lib/has_many_polymorphs/support_methods.rb +88 -0
- data/vendor/plugins/has_many_polymorphs/lib/has_many_polymorphs.rb +27 -0
- data/vendor/plugins/has_many_polymorphs/test/fixtures/bow_wows.yml +10 -0
- data/vendor/plugins/has_many_polymorphs/test/fixtures/cats.yml +18 -0
- data/vendor/plugins/has_many_polymorphs/test/fixtures/eaters_foodstuffs.yml +0 -0
- data/vendor/plugins/has_many_polymorphs/test/fixtures/fish.yml +12 -0
- data/vendor/plugins/has_many_polymorphs/test/fixtures/frogs.yml +5 -0
- data/vendor/plugins/has_many_polymorphs/test/fixtures/keep_your_enemies_close.yml +0 -0
- data/vendor/plugins/has_many_polymorphs/test/fixtures/little_whale_pupils.yml +0 -0
- data/vendor/plugins/has_many_polymorphs/test/fixtures/people.yml +7 -0
- data/vendor/plugins/has_many_polymorphs/test/fixtures/petfoods.yml +11 -0
- data/vendor/plugins/has_many_polymorphs/test/fixtures/whales.yml +5 -0
- data/vendor/plugins/has_many_polymorphs/test/fixtures/wild_boars.yml +10 -0
- data/vendor/plugins/has_many_polymorphs/test/generator/tagging_generator_test.rb +42 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/README +182 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/Rakefile +19 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/controllers/application.rb +7 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/controllers/bones_controller.rb +5 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/helpers/addresses_helper.rb +2 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/helpers/application_helper.rb +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/helpers/bones_helper.rb +2 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/helpers/sellers_helper.rb +28 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/helpers/states_helper.rb +2 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/helpers/users_helper.rb +2 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/models/bone.rb +2 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/models/double_sti_parent.rb +2 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/models/double_sti_parent_relationship.rb +2 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/models/organic_substance.rb +2 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/models/single_sti_parent.rb +4 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/models/single_sti_parent_relationship.rb +4 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/models/stick.rb +2 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/models/stone.rb +2 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/addresses/edit.html.erb +12 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/addresses/index.html.erb +18 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/addresses/new.html.erb +11 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/addresses/show.html.erb +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/bones/index.rhtml +5 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/layouts/addresses.html.erb +17 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/layouts/sellers.html.erb +17 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/layouts/states.html.erb +17 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/layouts/users.html.erb +17 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/sellers/edit.html.erb +12 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/sellers/index.html.erb +20 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/sellers/new.html.erb +11 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/sellers/show.html.erb +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/states/edit.html.erb +12 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/states/index.html.erb +19 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/states/new.html.erb +11 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/states/show.html.erb +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/users/edit.html.erb +12 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/users/index.html.erb +22 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/users/new.html.erb +11 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/app/views/users/show.html.erb +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/config/boot.rb +110 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/config/database.yml +17 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/config/environment.rb +19 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/config/environment.rb.canonical +19 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/config/environments/development.rb +9 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/config/environments/production.rb +18 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/config/environments/test.rb +19 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/config/locomotive.yml +6 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/config/routes.rb +33 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/config/ultrasphinx/default.base +56 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/config/ultrasphinx/development.conf.canonical +155 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/db/migrate/001_create_sticks.rb +11 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/db/migrate/002_create_stones.rb +11 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/db/migrate/003_create_organic_substances.rb +11 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/db/migrate/004_create_bones.rb +8 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/db/migrate/005_create_single_sti_parents.rb +11 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/db/migrate/006_create_double_sti_parents.rb +11 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/db/migrate/007_create_single_sti_parent_relationships.rb +13 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/db/migrate/008_create_double_sti_parent_relationships.rb +14 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/db/migrate/009_create_library_model.rb +11 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/doc/README_FOR_APP +2 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/generators/commenting_generator_test.rb +83 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/lib/library_model.rb +2 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/public/.htaccess +40 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/public/404.html +30 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/public/500.html +30 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/public/dispatch.cgi +10 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/public/dispatch.fcgi +24 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/public/dispatch.rb +10 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/public/favicon.ico +0 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/public/images/rails.png +0 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/public/index.html +277 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/public/javascripts/application.js +2 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/public/javascripts/controls.js +833 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/public/javascripts/dragdrop.js +942 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/public/javascripts/effects.js +1088 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/public/javascripts/prototype.js +2515 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/public/robots.txt +1 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/public/stylesheets/scaffold.css +74 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/script/about +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/script/breakpointer +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/script/console +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/script/destroy +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/script/generate +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/script/performance/benchmarker +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/script/performance/profiler +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/script/plugin +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/script/process/inspector +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/script/process/reaper +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/script/process/spawner +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/script/runner +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/script/server +3 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/fixtures/double_sti_parent_relationships.yml +7 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/fixtures/double_sti_parents.yml +7 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/fixtures/organic_substances.yml +5 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/fixtures/single_sti_parent_relationships.yml +7 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/fixtures/single_sti_parents.yml +7 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/fixtures/sticks.yml +7 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/fixtures/stones.yml +7 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/functional/addresses_controller_test.rb +57 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/functional/bones_controller_test.rb +8 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/functional/sellers_controller_test.rb +57 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/functional/states_controller_test.rb +57 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/functional/users_controller_test.rb +57 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/test_helper.rb +8 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/unit/bone_test.rb +8 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/unit/double_sti_parent_relationship_test.rb +8 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/unit/double_sti_parent_test.rb +8 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/unit/organic_substance_test.rb +8 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/unit/single_sti_parent_relationship_test.rb +8 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/unit/single_sti_parent_test.rb +8 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/unit/stick_test.rb +8 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/app/test/unit/stone_test.rb +8 -0
- data/vendor/plugins/has_many_polymorphs/test/integration/server_test.rb +43 -0
- data/vendor/plugins/has_many_polymorphs/test/models/aquatic/fish.rb +5 -0
- data/vendor/plugins/has_many_polymorphs/test/models/aquatic/pupils_whale.rb +7 -0
- data/vendor/plugins/has_many_polymorphs/test/models/aquatic/whale.rb +15 -0
- data/vendor/plugins/has_many_polymorphs/test/models/beautiful_fight_relationship.rb +26 -0
- data/vendor/plugins/has_many_polymorphs/test/models/canine.rb +9 -0
- data/vendor/plugins/has_many_polymorphs/test/models/cat.rb +5 -0
- data/vendor/plugins/has_many_polymorphs/test/models/dog.rb +18 -0
- data/vendor/plugins/has_many_polymorphs/test/models/eaters_foodstuff.rb +8 -0
- data/vendor/plugins/has_many_polymorphs/test/models/frog.rb +4 -0
- data/vendor/plugins/has_many_polymorphs/test/models/kitten.rb +3 -0
- data/vendor/plugins/has_many_polymorphs/test/models/parentship.rb +4 -0
- data/vendor/plugins/has_many_polymorphs/test/models/person.rb +9 -0
- data/vendor/plugins/has_many_polymorphs/test/models/petfood.rb +39 -0
- data/vendor/plugins/has_many_polymorphs/test/models/tabby.rb +2 -0
- data/vendor/plugins/has_many_polymorphs/test/models/wild_boar.rb +3 -0
- data/vendor/plugins/has_many_polymorphs/test/modules/extension_module.rb +9 -0
- data/vendor/plugins/has_many_polymorphs/test/modules/other_extension_module.rb +9 -0
- data/vendor/plugins/has_many_polymorphs/test/patches/symlinked_plugins_1.2.6.diff +46 -0
- data/vendor/plugins/has_many_polymorphs/test/schema.rb +87 -0
- data/vendor/plugins/has_many_polymorphs/test/setup.rb +14 -0
- data/vendor/plugins/has_many_polymorphs/test/test_helper.rb +52 -0
- data/vendor/plugins/has_many_polymorphs/test/unit/has_many_polymorphs_test.rb +713 -0
- metadata +421 -0
data/HELP.md
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
The Tags extension provides a way for you to easily categorize your pages.
|
|
2
|
+
|
|
3
|
+
== Results page
|
|
4
|
+
|
|
5
|
+
<r:search:empty>
|
|
6
|
+
<h2>I couldn't find anything tagged with "<r:search:query/>".</h2>
|
|
7
|
+
</r:search:empty>
|
|
8
|
+
|
|
9
|
+
<r:search:results>
|
|
10
|
+
<h2>Found the following pages that are tagged with "<em><r:search:query/></em>".</h2>
|
|
11
|
+
|
|
12
|
+
<ul>
|
|
13
|
+
<r:search:results:each>
|
|
14
|
+
<li><r:link/> - <r:author/> - <r:date/></li>
|
|
15
|
+
</r:search:results:each>
|
|
16
|
+
</ul>
|
|
17
|
+
</r:search:results>
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
== Tag cloud
|
|
21
|
+
|
|
22
|
+
Use `<r:tag_cloud />` anywhere you like.
|
|
23
|
+
I made a stab at building the 'perfect' tag cloud markup, as inspired by a post on 24ways.org; http://24ways.org/2006/marking-up-a-tag-cloud
|
|
24
|
+
|
|
25
|
+
== Tag list
|
|
26
|
+
|
|
27
|
+
Use `<r:tag_list />` to get a list of tags for the current page.
|
|
28
|
+
Also works through children:each.
|
|
29
|
+
|
|
30
|
+
== All tags
|
|
31
|
+
|
|
32
|
+
Use `<r:all_tags />` to get a list of all tags. You may iterate through them with
|
|
33
|
+
`<r:all_tags:each>` and access their associated pages with `<r:all_tags:each:pages:each>`
|
|
34
|
+
|
|
35
|
+
== Collections
|
|
36
|
+
|
|
37
|
+
You can grab a collection of pages with a certain tag like so;
|
|
38
|
+
|
|
39
|
+
<r:tagged with="sometag" [scope="/some/page"] [with_any="true"]>
|
|
40
|
+
<r:link />
|
|
41
|
+
</r:tagged>
|
|
42
|
+
|
|
43
|
+
Which would iterate over all the resulting pages, like you do with children:each.
|
|
44
|
+
When you define scope, only this page and any of it's (grand)children will be used.
|
|
45
|
+
Using scope="current_page" will use the page that is currently being rendered as scope.
|
|
46
|
+
You can also set limit, offset etc like with children:each.
|
|
47
|
+
|
|
48
|
+
Using r:tagged in it's default setting searches for pages that have all of the given tags.
|
|
49
|
+
Using r:tagged with the attribute 'with_any' set to 'true' will find pages that have any of
|
|
50
|
+
the given tags.
|
data/HELP_admin.md
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
The Tags extension allows you to configure the style of tagging between 2 options:
|
|
2
|
+
simple or complex strings.
|
|
3
|
+
|
|
4
|
+
== Simple Tagging
|
|
5
|
+
|
|
6
|
+
By default you may add tags to a page in a string such as "this that other". That string
|
|
7
|
+
will be parsed and turned into 3 separate tags.
|
|
8
|
+
|
|
9
|
+
== Complex Tagging
|
|
10
|
+
|
|
11
|
+
You may set `Radiant::Config['tags.complex_strings'] = true` to allow you to enter more
|
|
12
|
+
complex tags for your pages.
|
|
13
|
+
|
|
14
|
+
When this setting is `true` the tags are delimited by a semi-colon, allowing you to enter
|
|
15
|
+
a string of tags such as "My Summer Vacation (2008); Entertainment/Nonsense; Miscellaneous 2.0".
|
|
16
|
+
The result of that string will return 3 tags: `My Summer Vacation (2008)`,
|
|
17
|
+
`Entertainment/Nonsense` and 'Miscellaneous 2.0'
|
|
18
|
+
|
|
19
|
+
== Making the choice
|
|
20
|
+
|
|
21
|
+
You'll need to restart the application server after changing this setting. Please keep in
|
|
22
|
+
mind that any changes to this setting may affect any tags you currently have in the database.
|
|
23
|
+
It is recommended that you choose either Simple or Complex, but that you do not switch
|
|
24
|
+
after creating your tags.
|
|
25
|
+
|
|
26
|
+
== Tag Clouds
|
|
27
|
+
|
|
28
|
+
Some styles are provided in tags.css for the <r:tag_cloud>. To use it, add this to your layout:
|
|
29
|
+
|
|
30
|
+
<link rel="stylesheet" type="text/css" href="/stylesheets/tags.css" />
|
data/README
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
= Tags extension
|
|
2
|
+
|
|
3
|
+
Created by: Keith Bingman - keithbingman.com
|
|
4
|
+
Revived by: Benny Degezelle - gorilla-webdesign.be
|
|
5
|
+
New features by: Jim Gay - saturnflyer.com
|
|
6
|
+
Version: 1.5
|
|
7
|
+
|
|
8
|
+
This extension enhances the page model with tagging capabilities, tagging as in "2.0" and tagclouds.
|
|
9
|
+
|
|
10
|
+
== Requirements
|
|
11
|
+
|
|
12
|
+
This extension depends on the has_many_polymorphs plugin (included in vendor/plugins)
|
|
13
|
+
If you're still on Radiant pre-0.6.7, then the shards_extension should be installed and loaded first.
|
|
14
|
+
You can change the load order of extensions in config/environment.rb (see http://wiki.radiantcms.org/Using_the_Shards_Extension).
|
|
15
|
+
|
|
16
|
+
== Installation
|
|
17
|
+
|
|
18
|
+
1. Copy the extension to your vendor/extensions directory as you would any other extension.
|
|
19
|
+
2. Run 'rake radiant:extensions:tags:install'
|
|
20
|
+
3. Make a page to sit in /search/by-tag, and give it the "Tag Search" pagetype.
|
|
21
|
+
If you want to change this location, it's in Radiant::Config['tags.results_page_url'].
|
|
22
|
+
|
|
23
|
+
Done!
|
|
24
|
+
Here's a sample results page to get you started;
|
|
25
|
+
|
|
26
|
+
<r:search:empty>
|
|
27
|
+
<h2>I couldn't find anything tagged with "<r:search:query/>".</h2>
|
|
28
|
+
</r:search:empty>
|
|
29
|
+
|
|
30
|
+
<r:search:results>
|
|
31
|
+
<h2>Found the following pages that are tagged with "<em><r:search:query/></em>".</h2>
|
|
32
|
+
|
|
33
|
+
<ul>
|
|
34
|
+
<r:search:results:each>
|
|
35
|
+
<li><r:link/> - <r:author/> - <r:date/></li>
|
|
36
|
+
</r:search:results:each>
|
|
37
|
+
</ul>
|
|
38
|
+
</r:search:results>
|
data/Rakefile
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require 'rake'
|
|
2
|
+
require 'rake/testtask'
|
|
3
|
+
require 'rake/rdoctask'
|
|
4
|
+
|
|
5
|
+
desc 'Default: run unit tests.'
|
|
6
|
+
task :default => :test
|
|
7
|
+
|
|
8
|
+
desc 'Test the tags extension.'
|
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
|
10
|
+
t.libs << 'lib'
|
|
11
|
+
t.pattern = 'test/**/*_test.rb'
|
|
12
|
+
t.verbose = true
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
desc 'Generate documentation for the tags extension.'
|
|
16
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
|
17
|
+
rdoc.rdoc_dir = 'rdoc'
|
|
18
|
+
rdoc.title = 'TagsExtension'
|
|
19
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
|
20
|
+
rdoc.rdoc_files.include('README')
|
|
21
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
# Load any custom rakefiles for extension
|
|
25
|
+
Dir[File.dirname(__FILE__) + '/tasks/*.rake'].sort.each { |f| require f }
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
class MetaTag < ActiveRecord::Base
|
|
2
|
+
|
|
3
|
+
if Radiant::Config['tags.complex_strings'] == 'true'
|
|
4
|
+
delim = ";"
|
|
5
|
+
re_format = /^[a-zA-Z0-9,\_\-\s\/()'.&]+$/
|
|
6
|
+
else
|
|
7
|
+
delim = " "
|
|
8
|
+
re_format = /^[a-zA-Z0-9\_\-]+$/
|
|
9
|
+
end
|
|
10
|
+
DELIMITER = delim
|
|
11
|
+
# how to separate tags in strings (you may
|
|
12
|
+
# also need to change the validates_format_of parameters
|
|
13
|
+
# if you update this)
|
|
14
|
+
|
|
15
|
+
# if speed becomes an issue, you could remove these validations
|
|
16
|
+
# and rescue the AR index errors instead
|
|
17
|
+
validates_presence_of :name
|
|
18
|
+
validates_uniqueness_of :name, :case_sensitive => false
|
|
19
|
+
validates_format_of :name, :with => re_format,
|
|
20
|
+
:message => "can not contain special characters"
|
|
21
|
+
|
|
22
|
+
has_many_polymorphs :taggables,
|
|
23
|
+
:from => [:pages],
|
|
24
|
+
:through => :taggings,
|
|
25
|
+
:dependent => :destroy,
|
|
26
|
+
:skip_duplicates => false
|
|
27
|
+
|
|
28
|
+
def after_save
|
|
29
|
+
# if you allow editable tag names, you might want before_save instead
|
|
30
|
+
self.name = name.downcase.strip.squeeze(" ")
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
class << self
|
|
34
|
+
def find_or_create_by_name!(name)
|
|
35
|
+
find_by_name(name) || create!(:name => name)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def cloud(args = {})
|
|
39
|
+
find(:all, :select => 'meta_tags.*, count(*) as popularity',
|
|
40
|
+
:limit => args[:limit] || 5,
|
|
41
|
+
:joins => "JOIN taggings ON taggings.meta_tag_id = meta_tags.id",
|
|
42
|
+
:conditions => args[:conditions],
|
|
43
|
+
:group => "meta_tags.id, meta_tags.name",
|
|
44
|
+
:order => "popularity DESC" )
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def <=>(other)
|
|
49
|
+
# To be able to sort an array of tags
|
|
50
|
+
name <=> other.name
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
end
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
module RadiusTags
|
|
2
|
+
include Radiant::Taggable
|
|
3
|
+
include ActionView::Helpers::TextHelper
|
|
4
|
+
|
|
5
|
+
class TagError < StandardError; end
|
|
6
|
+
|
|
7
|
+
desc %{
|
|
8
|
+
Expands if a <pre><r:tagged with="" /></pre> call would return items. Takes the same options as the 'tagged' tag.
|
|
9
|
+
The <pre><r:unless_tagged with="" /></pre> is also available.
|
|
10
|
+
}
|
|
11
|
+
tag "if_tagged" do |tag|
|
|
12
|
+
if tag.attr["with"]
|
|
13
|
+
tag.locals.tagged_results = find_with_tag_options(tag)
|
|
14
|
+
tag.expand unless tag.locals.tagged_results.empty?
|
|
15
|
+
else
|
|
16
|
+
tag.expand unless tag.locals.page.tag_list.empty?
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
tag "unless_tagged" do |tag|
|
|
20
|
+
if tag.attr["with"]
|
|
21
|
+
tag.expand if find_with_tag_options(tag).empty?
|
|
22
|
+
else
|
|
23
|
+
tag.expand if tag.locals.page.tag_list.empty?
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
desc %{
|
|
28
|
+
Find all pages with certain tags, within in an optional scope. Additionally, you may set with_any to true to select pages that have any of the listed tags (opposed to all listed tags which is the provided default).
|
|
29
|
+
|
|
30
|
+
*Usage:*
|
|
31
|
+
<pre><code><r:tagged with="shoes diesel" [scope="/fashion/cult-update"] [with_any="true"] [offset="number"] [limit="number"] [by="attribute"] [order="asc|desc"]>...</r:tagged></code></pre>
|
|
32
|
+
}
|
|
33
|
+
tag "tagged" do |tag|
|
|
34
|
+
unless tag.locals.tagged_results.nil? # We're inside an r:if_tagged, so results are already available;
|
|
35
|
+
results = tag.locals.tagged_results
|
|
36
|
+
else
|
|
37
|
+
results = find_with_tag_options(tag)
|
|
38
|
+
end
|
|
39
|
+
output = []
|
|
40
|
+
results.each do |page|
|
|
41
|
+
tag.locals.page = page
|
|
42
|
+
output << tag.expand
|
|
43
|
+
end
|
|
44
|
+
output
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
desc %{
|
|
48
|
+
Find all pages related to the current page, based on all or any of the current page's tags. A scope attribute may be given to limit results to a certain site area.
|
|
49
|
+
|
|
50
|
+
*Usage:*
|
|
51
|
+
<pre><code><r:related_by_tags [scope="/fashion/cult-update"] [offset="number"] [limit="number"] [by="attribute"] [order="asc|desc"]>...</r:related_by_tags></code></pre>
|
|
52
|
+
}
|
|
53
|
+
tag "related_by_tags" do |tag|
|
|
54
|
+
tag.attr["with"] = tag.locals.page.tag_list.split(MetaTag::DELIMITER)
|
|
55
|
+
tag.attr["with_any"] = true
|
|
56
|
+
tag.attr["exclude_id"] = tag.locals.page.id
|
|
57
|
+
results = find_with_tag_options(tag)
|
|
58
|
+
return false if results.size < 1
|
|
59
|
+
output = []
|
|
60
|
+
first = true
|
|
61
|
+
results.each do |page|
|
|
62
|
+
tag.locals.page = page
|
|
63
|
+
tag.locals.first = first
|
|
64
|
+
output << tag.expand
|
|
65
|
+
first = false
|
|
66
|
+
end
|
|
67
|
+
output
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
tag "if_has_related_by_tags" do |tag|
|
|
71
|
+
tag.attr["with"] = tag.locals.page.tag_list.split(MetaTag::DELIMITER)
|
|
72
|
+
tag.attr["with_any"] = true
|
|
73
|
+
tag.attr["exclude_id"] = tag.locals.page.id
|
|
74
|
+
results = find_with_tag_options(tag)
|
|
75
|
+
results -= [tag.locals.page]
|
|
76
|
+
tag.expand if results.size > 0
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
tag "related_by_tags:if_first" do |tag|
|
|
80
|
+
tag.expand if tag.locals.first
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
desc %{
|
|
84
|
+
Render a Tag cloud
|
|
85
|
+
The results_page attribute will default to #{Radiant::Config['tags.results_page_url']}
|
|
86
|
+
|
|
87
|
+
*Usage:*
|
|
88
|
+
<pre><code><r:tag_cloud_list [limit="number"] [results_page="/some/url"] [scope="/some/url"]/></code></pre>
|
|
89
|
+
}
|
|
90
|
+
tag "tag_cloud" do |tag|
|
|
91
|
+
tag_cloud = MetaTag.cloud(:limit => tag.attr['limit'] || 5).sort
|
|
92
|
+
tag_cloud = filter_tags_to_url_scope(tag_cloud, tag.attr['scope']) unless tag.attr['scope'].nil?
|
|
93
|
+
|
|
94
|
+
results_page = tag.attr['results_page'] || Radiant::Config['tags.results_page_url']
|
|
95
|
+
output = "<ol class=\"tag_cloud\">"
|
|
96
|
+
if tag_cloud.length > 0
|
|
97
|
+
build_tag_cloud(tag_cloud, %w(size1 size2 size3 size4 size5 size6 size7 size8 size9)) do |tag, cloud_class, amount|
|
|
98
|
+
output += "<li class=\"#{cloud_class}\"><span>#{pluralize(amount, 'page is', 'pages are')} tagged with </span><a href=\"#{results_page}/#{tag}\" class=\"tag\">#{tag}</a></li>"
|
|
99
|
+
end
|
|
100
|
+
else
|
|
101
|
+
return "<p>No tags found.</p>"
|
|
102
|
+
end
|
|
103
|
+
output += "</ol>"
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
desc %{
|
|
107
|
+
Render a Tag list, more for 'categories'-ish usage, i.e.: Cats (2) Logs (1) ...
|
|
108
|
+
The results_page attribute will default to #{Radiant::Config['tags.results_page_url']}
|
|
109
|
+
|
|
110
|
+
*Usage:*
|
|
111
|
+
<pre><code><r:tag_cloud_list [results_page="/some/url"] [scope="/some/url"]/></code></pre>
|
|
112
|
+
}
|
|
113
|
+
tag "tag_cloud_list" do |tag|
|
|
114
|
+
tag_cloud = MetaTag.cloud({:limit => 100}).sort
|
|
115
|
+
tag_cloud = filter_tags_to_url_scope(tag_cloud, tag.attr['scope']) unless tag.attr['scope'].nil?
|
|
116
|
+
|
|
117
|
+
results_page = tag.attr['results_page'] || Radiant::Config['tags.results_page_url']
|
|
118
|
+
output = "<ul class=\"tag_list\">"
|
|
119
|
+
if tag_cloud.length > 0
|
|
120
|
+
build_tag_cloud(tag_cloud, %w(size1 size2 size3 size4 size5 size6 size7 size8 size9)) do |tag, cloud_class, amount|
|
|
121
|
+
output += "<li class=\"#{cloud_class}\"><a href=\"#{results_page}/#{tag}\" class=\"tag\">#{tag} (#{amount})</a></li>"
|
|
122
|
+
end
|
|
123
|
+
else
|
|
124
|
+
return "<p>No tags found.</p>"
|
|
125
|
+
end
|
|
126
|
+
output += "</ul>"
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
desc "List the current page's tags"
|
|
130
|
+
tag "tag_list" do |tag|
|
|
131
|
+
results_page = tag.attr['results_page'] || Radiant::Config['tags.results_page_url']
|
|
132
|
+
output = []
|
|
133
|
+
tag.locals.page.tag_list.split(MetaTag::DELIMITER).each {|t| output << "<a href=\"#{results_page}/#{t}\" class=\"tag\">#{t}</a>"}
|
|
134
|
+
output.join ", "
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
desc "List the current page's tagsi as technorati tags. this should be included in the body of a post or in your rss feed"
|
|
138
|
+
tag "tag_list_technorati" do |tag|
|
|
139
|
+
output = []
|
|
140
|
+
tag.locals.page.tag_list.split(MetaTag::DELIMITER).each {|t| output << "<a href=\"http://technorati.com/tag/#{ t.split(" ").join("+")}\" rel=\"tag\">#{t}</a>"}
|
|
141
|
+
output.join ", "
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
tag "tags" do |tag|
|
|
145
|
+
tag.expand
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
desc "Iterates over the tags of the current page"
|
|
149
|
+
tag "tags:each" do |tag|
|
|
150
|
+
result = []
|
|
151
|
+
tag.locals.page.meta_tags.each do |meta_tag|
|
|
152
|
+
tag.locals.meta_tag = meta_tag
|
|
153
|
+
result << tag.expand
|
|
154
|
+
end
|
|
155
|
+
result
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
tag "tags:each:name" do |tag|
|
|
159
|
+
tag.locals.meta_tag.name
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
tag "tags:each:link" do |tag|
|
|
163
|
+
results_page = tag.attr['results_page'] || Radiant::Config['tags.results_page_url']
|
|
164
|
+
name = tag.locals.meta_tag.name
|
|
165
|
+
return "<a href=\"#{results_page}/#{name}\" class=\"tag\">#{name}</a>"
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
desc "Set the scope for all tags in the database"
|
|
169
|
+
tag "all_tags" do |tag|
|
|
170
|
+
tag.expand
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
desc %{
|
|
174
|
+
Iterates through each tag and allows you to specify the order: by popularity or by name.
|
|
175
|
+
The default is by name. You may also limit the search; the default is 5 results.
|
|
176
|
+
|
|
177
|
+
Usage: <pre><code><r:all_tags:each order="popularity" limit="5">...</r:all_tags:each></code></pre>
|
|
178
|
+
}
|
|
179
|
+
tag "all_tags:each" do |tag|
|
|
180
|
+
order = tag.attr['order'] || 'name'
|
|
181
|
+
limit = tag.attr['limit'] || '5'
|
|
182
|
+
result = []
|
|
183
|
+
case order
|
|
184
|
+
when 'name'
|
|
185
|
+
all_tags = MetaTag.find(:all, :limit => limit)
|
|
186
|
+
else
|
|
187
|
+
all_tags = MetaTag.cloud(:limit => limit)
|
|
188
|
+
end
|
|
189
|
+
all_tags.each do |t|
|
|
190
|
+
next if t.pages.empty? # skip unused tags
|
|
191
|
+
tag.locals.meta_tag = t
|
|
192
|
+
result << tag.expand
|
|
193
|
+
end
|
|
194
|
+
result
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
desc "Renders the tag's name"
|
|
198
|
+
tag "all_tags:each:name" do |tag|
|
|
199
|
+
tag.locals.meta_tag.name
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
tag "all_tags:each:link" do |tag|
|
|
203
|
+
results_page = tag.attr['results_page'] || Radiant::Config['tags.results_page_url']
|
|
204
|
+
name = tag.locals.meta_tag.name
|
|
205
|
+
return "<a href=\"#{results_page}/#{name}\" class=\"tag\">#{name}</a>"
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
desc "Set the scope for the tag's pages"
|
|
210
|
+
tag "all_tags:each:pages" do |tag|
|
|
211
|
+
tag.expand
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
desc "Iterates through each page"
|
|
215
|
+
tag "all_tags:each:pages:each" do |tag|
|
|
216
|
+
result = []
|
|
217
|
+
tag.locals.meta_tag.taggables.each do |taggable|
|
|
218
|
+
if taggable.is_a?(Page)
|
|
219
|
+
tag.locals.page = taggable
|
|
220
|
+
result << tag.expand
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
result
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
private
|
|
227
|
+
|
|
228
|
+
def build_tag_cloud(tag_cloud, style_list)
|
|
229
|
+
max, min = 0, 0
|
|
230
|
+
tag_cloud.each do |tag|
|
|
231
|
+
max = tag.popularity.to_i if tag.popularity.to_i > max
|
|
232
|
+
min = tag.popularity.to_i if tag.popularity.to_i < min
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
divisor = ((max - min) / style_list.size) + 1
|
|
236
|
+
|
|
237
|
+
tag_cloud.each do |tag|
|
|
238
|
+
yield tag.name, style_list[(tag.popularity.to_i - min) / divisor], tag.popularity.to_i
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def tag_item_url(name)
|
|
243
|
+
"#{Radiant::Config['tags.results_page_url']}/#{name}"
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
def find_with_tag_options(tag)
|
|
247
|
+
options = tagged_with_options(tag)
|
|
248
|
+
with_any = tag.attr['with_any'] || false
|
|
249
|
+
scope_attr = tag.attr['scope'] || '/'
|
|
250
|
+
results = []
|
|
251
|
+
raise TagError, "`tagged' tag must contain a `with' attribute." unless (tag.attr['with'] || tag.locals.page.class_name = TagSearchPage)
|
|
252
|
+
ttag = tag.attr['with'] || @request.parameters[:tag]
|
|
253
|
+
|
|
254
|
+
scope = scope_attr == 'current_page' ? Page.find_by_url(@request.request_uri) : Page.find_by_url(scope_attr)
|
|
255
|
+
return "The scope attribute must be a valid url to an existing page." if scope.nil? || scope.class_name.eql?('FileNotFoundPage')
|
|
256
|
+
|
|
257
|
+
if with_any
|
|
258
|
+
Page.tagged_with_any(ttag, options).each do |page|
|
|
259
|
+
next unless (page.ancestors.include?(scope) or page == scope)
|
|
260
|
+
results << page
|
|
261
|
+
end
|
|
262
|
+
else
|
|
263
|
+
Page.tagged_with(ttag, options).each do |page|
|
|
264
|
+
next unless (page.ancestors.include?(scope) or page == scope)
|
|
265
|
+
results << page
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
results
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def tagged_with_options(tag)
|
|
272
|
+
attr = tag.attr.symbolize_keys
|
|
273
|
+
|
|
274
|
+
options = {}
|
|
275
|
+
|
|
276
|
+
[:limit, :offset].each do |symbol|
|
|
277
|
+
if number = attr[symbol]
|
|
278
|
+
if number =~ /^\d{1,4}$/
|
|
279
|
+
options[symbol] = number.to_i
|
|
280
|
+
else
|
|
281
|
+
raise TagError.new("`#{symbol}' attribute of `each' tag must be a positive number between 1 and 4 digits")
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
by = (attr[:by] || 'published_at').strip
|
|
287
|
+
order = (attr[:order] || 'asc').strip
|
|
288
|
+
order_string = ''
|
|
289
|
+
if self.attributes.keys.include?(by)
|
|
290
|
+
order_string << by
|
|
291
|
+
else
|
|
292
|
+
raise TagError.new("`by' attribute of `each' tag must be set to a valid field name")
|
|
293
|
+
end
|
|
294
|
+
if order =~ /^(asc|desc)$/i
|
|
295
|
+
order_string << " #{$1.upcase}"
|
|
296
|
+
else
|
|
297
|
+
raise TagError.new(%{`order' attribute of `each' tag must be set to either "asc" or "desc"})
|
|
298
|
+
end
|
|
299
|
+
options[:order] = order_string
|
|
300
|
+
|
|
301
|
+
status = (attr[:status] || 'published').downcase
|
|
302
|
+
exclude = attr[:exclude_id] ? "AND pages.id != #{attr[:exclude_id]}" : ""
|
|
303
|
+
|
|
304
|
+
unless status == 'all'
|
|
305
|
+
stat = Status[status]
|
|
306
|
+
unless stat.nil?
|
|
307
|
+
options[:conditions] = ["(virtual = ?) and (status_id = ?) #{exclude} and (published_at <= ?)", false, stat.id, Time.current]
|
|
308
|
+
else
|
|
309
|
+
raise TagError.new(%{`status' attribute of `each' tag must be set to a valid status})
|
|
310
|
+
end
|
|
311
|
+
else
|
|
312
|
+
options[:conditions] = ["virtual = ? #{exclude}", false]
|
|
313
|
+
end
|
|
314
|
+
options
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
def filter_tags_to_url_scope(tags, scope)
|
|
318
|
+
new_tags = []
|
|
319
|
+
tags.each do |t|
|
|
320
|
+
catch :record_found do # using fancy ballsports stuff to avoid unnecessary db calls (by calling each page, ànd by calling page.url)
|
|
321
|
+
t.pages.each do |p|
|
|
322
|
+
(new_tags << t; throw :record_found) if p.url.include?(scope)
|
|
323
|
+
end
|
|
324
|
+
end
|
|
325
|
+
end
|
|
326
|
+
new_tags
|
|
327
|
+
end
|
|
328
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
class TagSearchPage < Page
|
|
2
|
+
|
|
3
|
+
attr_accessor :requested_tag
|
|
4
|
+
#### Tags ####
|
|
5
|
+
desc %{ The namespace for all search tags.}
|
|
6
|
+
tag 'search' do |tag|
|
|
7
|
+
tag.expand
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
desc %{ Renders the passed query.}
|
|
11
|
+
tag 'search:query' do |tag|
|
|
12
|
+
CGI.escapeHTML(requested_tag)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
desc %{ Renders the contained block if no results were returned.}
|
|
16
|
+
tag 'search:empty' do |tag|
|
|
17
|
+
if found_tags.blank?
|
|
18
|
+
tag.expand
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
desc %{ Renders the contained block if results were returned.}
|
|
23
|
+
tag 'search:results' do |tag|
|
|
24
|
+
unless found_tags.blank?
|
|
25
|
+
tag.expand
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
desc %{ <r:search:results:each [sort_by="id"] [order="asc"]/>
|
|
30
|
+
Renders the contained block for each result page. The context
|
|
31
|
+
inside the tag refers to the found page. The optional sort_by and order attributes
|
|
32
|
+
specify how the results are sorted}
|
|
33
|
+
tag 'search:results:each' do |tag|
|
|
34
|
+
# Ordering in Ruby because we already fetched our resultset before
|
|
35
|
+
tags = found_tags
|
|
36
|
+
tags = tags.sort_by(&tag.attr['sort_by'].to_sym) if tag.attr['sort_by']
|
|
37
|
+
tags = tags.reverse if tag.attr['order'].to_s =~ /desc/i
|
|
38
|
+
|
|
39
|
+
returning String.new do |content|
|
|
40
|
+
tags.each do |page|
|
|
41
|
+
tag.locals.page = page
|
|
42
|
+
content << tag.expand
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
desc %{ <r:truncate_and_strip [length="100"] />
|
|
48
|
+
Truncates and strips all HTML tags from the content of the contained block.
|
|
49
|
+
Useful for displaying a snippet of a found page. The optional `length' attribute
|
|
50
|
+
specifies how many characters to truncate to.}
|
|
51
|
+
tag 'truncate_and_strip' do |tag|
|
|
52
|
+
tag.attr['length'] ||= 100
|
|
53
|
+
length = tag.attr['length'].to_i
|
|
54
|
+
helper = ActionView::Base.new
|
|
55
|
+
helper.truncate(helper.strip_tags(tag.expand).gsub(/\s+/," "), length)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
#### "Behavior" methods ####
|
|
59
|
+
def cache?
|
|
60
|
+
true
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def found_tags
|
|
64
|
+
return @found_tags if @found_tags
|
|
65
|
+
return [] if requested_tag.blank?
|
|
66
|
+
|
|
67
|
+
@found_tags = Page.tagged_with(requested_tag).delete_if { |p| !p.published? }
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def render
|
|
71
|
+
self.requested_tag = @request.parameters[:tag] unless requested_tag
|
|
72
|
+
self.title = "Tagged with #{requested_tag}" if requested_tag
|
|
73
|
+
|
|
74
|
+
super
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def find_by_url(url, live = true, clean = false)
|
|
78
|
+
url = clean_url(url).chop # chop off trailing slash added by clean_url
|
|
79
|
+
if url =~ /^#{self.url}([a-zA-Z0-9,\_\-\s\/()'.&]*)\/?$/
|
|
80
|
+
self.requested_tag = $1
|
|
81
|
+
self
|
|
82
|
+
else
|
|
83
|
+
super
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
class Tagging < ActiveRecord::Base
|
|
2
|
+
belongs_to :meta_tag
|
|
3
|
+
belongs_to :taggable, :polymorphic => true
|
|
4
|
+
|
|
5
|
+
def before_destroy
|
|
6
|
+
# if all the taggings for a particular <%= parent_association_name -%> are deleted, we want to
|
|
7
|
+
# delete the <%= parent_association_name -%> too
|
|
8
|
+
meta_tag.destroy_without_callbacks if meta_tag.taggings.count < 2
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
%h4 Tags
|
|
2
|
+
%p Tags that you list on your pages are ad-hoc categories and tags that you apply to your pages are as flexible as you want them to be. Rather than selecting a category for your page from a pre-defined list of categories, you can create whatever you need.
|
|
3
|
+
%p Tags are delimited (separated) by a space, so if you want to tag a page with Totally Awesome as one tag, be sure to put it in quotes such as 'Totally Awesome', otherwise you'll create two tags: one called Totally and one called Awesome.
|
|
4
|
+
%p These tags may be used by the site developers to provide a list of links (for example) to a group of pages with the same tag.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
class AddTagSupport < ActiveRecord::Migration
|
|
2
|
+
def self.up
|
|
3
|
+
create_table :meta_tags do |t|
|
|
4
|
+
t.column :name, :string, :null => false
|
|
5
|
+
end
|
|
6
|
+
add_index :meta_tags, :name, :unique => true
|
|
7
|
+
|
|
8
|
+
create_table :taggings do |t|
|
|
9
|
+
t.column :meta_tag_id, :integer, :null => false
|
|
10
|
+
t.column :taggable_id, :integer, :null => false
|
|
11
|
+
t.column :taggable_type, :string, :null => false
|
|
12
|
+
end
|
|
13
|
+
add_index :taggings, [:meta_tag_id, :taggable_id, :taggable_type], :unique => true
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def self.down
|
|
17
|
+
drop_table :meta_tags
|
|
18
|
+
drop_table :taggings
|
|
19
|
+
end
|
|
20
|
+
end
|