Commit c770f8a428b74680b54f3c71d7b440e35307b901

Authored by Evandro Jr
2 parents 711552ab 7826abb9

Merge branch 'virtuoso_integration' of gitlab.com:participa/noosfero into virtuoso_integration

Gemfile
... ... @@ -13,7 +13,7 @@ gem 'ruby-feedparser', '~> 0.7'
13 13 gem 'daemons', '~> 1.1.5'
14 14 gem 'thin', '~> 1.3.1'
15 15 gem 'hpricot', '~> 0.8.6'
16   -gem 'nokogiri', '~> 1.5.5'
  16 +gem 'nokogiri', '~> 1.6.0'
17 17 gem 'rake', :require => false
18 18 gem 'rest-client', '~> 1.6.7'
19 19 gem 'exception_notification', '~> 4.0.1'
... ...
plugins/virtuoso/Gemfile
... ... @@ -2,3 +2,5 @@ gem 'rdf'
2 2 gem 'rdf-virtuoso'
3 3 gem 'oai'
4 4 gem 'liquid'
  5 +gem 'roadie'
  6 +gem 'roadie-rails'
... ...
plugins/virtuoso/db/migrate/20141113131439_create_custom_queries.rb
... ... @@ -6,6 +6,7 @@ class CreateCustomQueries < ActiveRecord::Migration
6 6 t.string :name
7 7 t.text :query
8 8 t.text :template
  9 + t.text :stylesheet
9 10 t.boolean :enabled, :default => true
10 11 t.timestamps
11 12 end
... ...
plugins/virtuoso/features/edit_template.feature 0 → 100644
... ... @@ -0,0 +1,25 @@
  1 +Feature: edit template
  2 + As a noosfero user
  3 + I want to create and edit templates
  4 +
  5 + Background:
  6 + Given I am on the homepage
  7 + And plugin Virtuoso is enabled on environment
  8 + And the following users
  9 + | login | name |
  10 + | joaosilva | Joao Silva |
  11 + And I am logged in as "joaosilva"
  12 + And the following custom queries
  13 + | name | query | template |
  14 + | Default | query-1 | template-1 |
  15 +
  16 + @selenium
  17 + Scenario:
  18 + Given I am on joaosilva's control panel
  19 + And I follow "Manage Content"
  20 + And I should see "New content"
  21 + And I follow "New content"
  22 + And I should see "Triples template" within ".article-types"
  23 + When I follow "Triples template" within ".article-types"
  24 + And I follow "Copy" within ".custom-query"
  25 + Then the "SPARQL Query" field should contain "query-1"
... ...
plugins/virtuoso/features/step_definitions/virtuoso_plugin_steps.rb 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +Given /^the following custom queries$/ do |table|
  2 + table.hashes.map{|item| item.dup}.each do |item|
  3 + VirtuosoPlugin::CustomQuery.create!(item.merge(:environment => Environment.default))
  4 + end
  5 +end
... ...
plugins/virtuoso/lib/ext/literal.rb
1 1 class RDF::Literal
2 2  
  3 + include ActionView::Helpers::SanitizeHelper
  4 +
3 5 def to_liquid
4   - value
  6 + strip_tags(value)
5 7 end
6 8  
7 9 end
... ...
plugins/virtuoso/lib/virtuoso_plugin/custom_query.rb
... ... @@ -2,7 +2,7 @@ class VirtuosoPlugin::CustomQuery < Noosfero::Plugin::ActiveRecord
2 2  
3 3 belongs_to :environment
4 4  
5   - attr_accessible :enabled, :environment, :query, :template, :name
  5 + attr_accessible :enabled, :environment, :query, :template, :name, :stylesheet
6 6  
7 7 validates_presence_of :name
8 8  
... ...
plugins/virtuoso/lib/virtuoso_plugin/triples_management.rb
... ... @@ -18,15 +18,21 @@ class VirtuosoPlugin::TriplesManagement
18 18 def update_triple(graph_uri, from_triple, to_triple)
19 19 from_subject = from_triple[:subject]
20 20 from_predicate = from_triple[:predicate]
21   - from_object = from_triple[:object]
  21 + from_object = format_triple_term(from_triple[:object])
22 22  
23 23 to_subject = to_triple[:subject]
24 24 to_predicate = to_triple[:predicate]
25   - to_object = to_triple[:object]
  25 + to_object = format_triple_term(to_triple[:object])
26 26  
27   - query = "WITH <#{graph_uri}> DELETE { <#{from_subject}> <#{from_predicate}> '#{from_object}' } INSERT { <#{to_subject}> <#{to_predicate}> '#{to_object}' }"
  27 + query = "WITH <#{graph_uri}> DELETE { <#{from_subject}> <#{from_predicate}> #{from_object} } INSERT { <#{to_subject}> <#{to_predicate}> #{to_object} }"
28 28  
29 29 plugin.virtuoso_client.query(query)
30 30 end
31 31  
  32 + protected
  33 +
  34 + def format_triple_term(term)
  35 + term =~ /^(http|https):\/\// ? "<#{term}>" : "'#{term}'"
  36 + end
  37 +
32 38 end
... ...
plugins/virtuoso/lib/virtuoso_plugin/triples_template.rb
... ... @@ -8,10 +8,21 @@ class VirtuosoPlugin::TriplesTemplate &lt; Article
8 8 _('Triples template')
9 9 end
10 10  
  11 + def self.initial_template
  12 + '
  13 + {% for row in results %}
  14 + <div>
  15 + {{row}}
  16 + </div>
  17 + {% endfor %}
  18 + '
  19 + end
  20 +
11 21 settings_items :query, :type => :string
12   - settings_items :template, :type => :string
  22 + settings_items :template, :type => :string, :default => initial_template
  23 + settings_items :stylesheet, :type => :string
13 24  
14   - attr_accessible :query, :template
  25 + attr_accessible :query, :template, :stylesheet
15 26  
16 27 def to_html(options = {})
17 28 article = self
... ... @@ -27,12 +38,21 @@ class VirtuosoPlugin::TriplesTemplate &lt; Article
27 38 def template_content
28 39 begin
29 40 results = plugin.virtuoso_client.query(query)
30   - liquid_template = Liquid::Template.parse("{% for row in results %}#{template}{% endfor %}")
31   - liquid_template.render('results' => results)
  41 + liquid_template = Liquid::Template.parse(template)
  42 + page = liquid_template.render('results' => results)
  43 + transform_html(page)
32 44 rescue => ex
33 45 logger.info ex.to_s
34 46 "Failed to process the template"
35 47 end
36 48 end
37 49  
  50 + protected
  51 +
  52 + def transform_html(html)
  53 + document = Roadie::Document.new(html)
  54 + document.add_css(stylesheet) if stylesheet.present?
  55 + document.transform
  56 + end
  57 +
38 58 end
... ...
plugins/virtuoso/public/custom_query.js
... ... @@ -2,6 +2,7 @@ jQuery(document).ready(function($) {
2 2 $('#copy_custom_query').on('click', function() {
3 3 $.getJSON("/plugin/virtuoso/public/custom_query", {id: $('#select_custom_query').val()}, function(data) {
4 4 $('#article_query').val(data.custom_query.query);
  5 + $('#article_stylesheet').val(data.custom_query.stylesheet);
5 6 tinymce.get('article_template').setContent(data.custom_query.template);
6 7 });
7 8 });
... ...
plugins/virtuoso/test/functional/virtuoso_plugin_custom_queries_controller_test.rb
... ... @@ -2,7 +2,7 @@ require &#39;test_helper&#39;
2 2  
3 3 class VirtuosoPluginCustomQueriesControllerTest < ActionController::TestCase
4 4 setup do
5   - @custom_query = VirtuosoPlugin::CustomQuery.create!(:name => 'name', :query => 'query', :template => 'template', :environment => Environment.default)
  5 + @custom_query = VirtuosoPlugin::CustomQuery.create!(:name => 'name', :query => 'query', :template => 'template', :stylesheet => 'stylesheet', :environment => Environment.default)
6 6 login_as(create_admin_user(Environment.default))
7 7 end
8 8  
... ... @@ -19,7 +19,7 @@ class VirtuosoPluginCustomQueriesControllerTest &lt; ActionController::TestCase
19 19  
20 20 should "create custom_query" do
21 21 assert_difference('VirtuosoPlugin::CustomQuery.count') do
22   - post :create, custom_query: { name: @custom_query.name, enabled: @custom_query.enabled, query: @custom_query.query, template: @custom_query.template }
  22 + post :create, custom_query: { name: @custom_query.name, enabled: @custom_query.enabled, query: @custom_query.query, template: @custom_query.template, stylesheet: @custom_query.stylesheet }
23 23 end
24 24  
25 25 assert_redirected_to :action => :index
... ... @@ -31,7 +31,7 @@ class VirtuosoPluginCustomQueriesControllerTest &lt; ActionController::TestCase
31 31 end
32 32  
33 33 should "update custom_query" do
34   - put :update, id: @custom_query, custom_query: { name: @custom_query.name, enabled: @custom_query.enabled, query: @custom_query.query, template: @custom_query.template }
  34 + put :update, id: @custom_query, custom_query: { name: @custom_query.name, enabled: @custom_query.enabled, query: @custom_query.query, template: @custom_query.template, stylesheet: @custom_query.stylesheet }
35 35 assert_redirected_to :action => :index
36 36 end
37 37  
... ...
plugins/virtuoso/test/unit/triples_template_test.rb
... ... @@ -12,18 +12,39 @@ class TriplesTemplateTest &lt; ActiveSupport::TestCase
12 12 article.stubs(:plugin).returns(mock)
13 13 article.plugin.expects(:virtuoso_client).at_least_once.returns(mock)
14 14 article.plugin.virtuoso_client.expects(:query).returns([{'var' => 'Hello '}, {'var' => 'World'}])
15   - article.template = "{{row.var}}"
  15 + article.template = "{% for row in results %}{{row.var}}{% endfor %}"
16 16  
17   - assert_equal 'Hello World', article.template_content
  17 + assert_match /Hello World/, article.template_content
18 18 end
19 19  
20 20 should 'display error message when failed to execute the query' do
21 21 article.stubs(:plugin).returns(mock)
22 22 article.plugin.expects(:virtuoso_client).at_least_once.returns(mock)
23 23 article.plugin.virtuoso_client.expects(:query).raises(RuntimeError.new)
24   - article.template = "{{row.var}}"
  24 + article.template = "{% for row in results %}{{row.var}}{% endfor %}"
25 25  
26 26 assert_equal "Failed to process the template", article.template_content
27 27 end
28 28  
  29 + should 'transform css into inline stylesheet' do
  30 + article.stubs(:plugin).returns(mock)
  31 + article.plugin.expects(:virtuoso_client).at_least_once.returns(mock)
  32 + article.plugin.virtuoso_client.expects(:query).returns([{'var' => 'Hello '}, {'var' => 'World'}])
  33 + article.template = "{% for row in results %}<p>{{row.var}}</p>{% endfor %}"
  34 + article.stylesheet = "p {color: red}"
  35 +
  36 + content = article.template_content
  37 + assert_match /<p style="color:red">Hello <\/p>/, content
  38 + assert_match /<p style="color:red">World<\/p>/, content
  39 + end
  40 +
  41 + should 'do not allow js injection' do
  42 + article.stubs(:plugin).returns(mock)
  43 + article.plugin.expects(:virtuoso_client).at_least_once.returns(mock)
  44 + article.plugin.virtuoso_client.expects(:query).returns([{'var' => RDF::Literal.new('<script>alert("hello");</script>')}])
  45 + article.template = "{% for row in results %}{{row.var}}{% endfor %}"
  46 +
  47 + assert_no_match /<script>/, article.template_content
  48 + end
  49 +
29 50 end
... ...
plugins/virtuoso/views/cms/virtuoso_plugin/_tinymce_template_editor.html.erb 0 → 100644
... ... @@ -0,0 +1,11 @@
  1 +<% extend TinymceHelper %>
  2 +
  3 +<%= tinymce_js %>
  4 +
  5 +<script>
  6 + function tinymce_macros_setup(editor) {}
  7 +
  8 + jQuery(document).ready(function($) {
  9 + <%= tinymce_init_js(:valid_children => "+body[style]", :convert_urls => false) %>
  10 + });
  11 +</script>
... ...
plugins/virtuoso/views/cms/virtuoso_plugin/_triples_template.html.erb
1 1 <div class="virtuoso-triples-template">
2 2 <%= required_fields_message %>
3 3  
4   - <%= render :file => 'shared/tiny_mce' %>
  4 + <%= render :partial => 'cms/virtuoso_plugin/tinymce_template_editor' %>
5 5  
6 6 <%= required labelled_form_field(_('Title'), text_field(:article, 'name', :size => '64', :maxlength => 150)) %>
7 7  
... ... @@ -20,6 +20,13 @@
20 20 </span>
21 21 </div>
22 22  
  23 + <div class="stylesheet">
  24 + <span class="label"><%= _('Stylesheet') %></span>
  25 + <span>
  26 + <%= text_area(:article, :stylesheet, :style => 'width: 98%; height: 100px;') %>
  27 + </span>
  28 + </div>
  29 +
23 30 <%= render :partial => 'shared/lead_and_body', :locals => {:tiny_mce => true} %>
24 31 <%= render :partial => 'general_fields' %>
25 32 </div>
... ...
plugins/virtuoso/views/virtuoso_plugin_custom_queries/_form.html.erb
... ... @@ -24,6 +24,10 @@
24 24 <%= f.text_area :template %>
25 25 </div>
26 26 <div class="field">
  27 + <%= f.label :stylesheet %><br />
  28 + <%= f.text_area :stylesheet %>
  29 + </div>
  30 + <div class="field">
27 31 <%= f.label :enabled %><br />
28 32 <%= f.check_box :enabled %>
29 33 </div>
... ...