locomotive_cms 2.5.6 → 2.5.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +7 -3
  3. data/app/assets/javascripts/locomotive/utils/tinymce_settings.js.coffee +4 -3
  4. data/app/assets/javascripts/locomotive/views/pages/_form_view.js.coffee +2 -2
  5. data/app/assets/stylesheets/locomotive/backoffice/application.css.scss +34 -1
  6. data/app/controllers/locomotive/api/base_controller.rb +8 -0
  7. data/app/controllers/locomotive/api/content_entries_controller.rb +15 -2
  8. data/app/controllers/locomotive/api/my_account_controller.rb +15 -0
  9. data/app/controllers/locomotive/api/version_controller.rb +17 -0
  10. data/app/controllers/locomotive/base_controller.rb +1 -1
  11. data/app/controllers/locomotive/content_entries_controller.rb +9 -10
  12. data/app/helpers/locomotive/content_types_helper.rb +16 -1
  13. data/app/helpers/locomotive/pages_helper.rb +13 -1
  14. data/app/models/locomotive/content_type.rb +15 -8
  15. data/app/models/locomotive/extensions/page/layout.rb +42 -0
  16. data/app/models/locomotive/extensions/page/templatized.rb +1 -1
  17. data/app/models/locomotive/page.rb +1 -0
  18. data/app/presenters/locomotive/content_entry_presenter.rb +5 -1
  19. data/app/presenters/locomotive/page_presenter.rb +1 -1
  20. data/app/services/locomotive/content_entry_service.rb +81 -0
  21. data/app/uploaders/locomotive/theme_asset_uploader.rb +1 -1
  22. data/app/views/locomotive/content_entries/index.html.haml +8 -0
  23. data/app/views/locomotive/content_types/_form.html.haml +2 -0
  24. data/app/views/locomotive/notifications/new_content_entry.html.haml +2 -2
  25. data/app/views/locomotive/pages/_form.html.haml +8 -1
  26. data/config/locales/admin_ui.en.yml +2 -0
  27. data/config/locales/admin_ui.fr.yml +1 -0
  28. data/config/locales/formtastic.en.yml +3 -0
  29. data/config/routes.rb +6 -2
  30. data/features/api/content_entries.feature +22 -9
  31. data/features/backoffice/site.feature +1 -1
  32. data/features/public/content_entries.feature +20 -5
  33. data/features/step_definitions/content_types_steps.rb +6 -0
  34. data/lib/generators/locomotive/install/templates/devise.rb +0 -2
  35. data/lib/locomotive/action_controller/responder.rb +1 -1
  36. data/lib/locomotive/carrierwave.rb +1 -0
  37. data/lib/locomotive/carrierwave/asset.rb +1 -1
  38. data/lib/locomotive/httparty/webservice.rb +17 -11
  39. data/lib/locomotive/liquid/drops/content_types.rb +7 -1
  40. data/lib/locomotive/liquid/drops/page.rb +51 -3
  41. data/lib/locomotive/liquid/tags/consume.rb +15 -10
  42. data/lib/locomotive/liquid/tags/editable/base.rb +1 -1
  43. data/lib/locomotive/liquid/tags/with_scope.rb +6 -1
  44. data/lib/locomotive/presentable.rb +1 -1
  45. data/lib/locomotive/regexps.rb +1 -1
  46. data/lib/locomotive/version.rb +1 -1
  47. data/lib/tasks/locomotive.rake +1 -1
  48. data/spec/dummy/config/application.rb +1 -1
  49. data/spec/dummy/config/mongoid.yml +2 -2
  50. data/spec/lib/locomotive/httparty/webservice_spec.rb +8 -3
  51. data/spec/lib/locomotive/liquid/drops/page_spec.rb +20 -5
  52. data/spec/lib/locomotive/liquid/tags/consume_spec.rb +66 -48
  53. data/spec/lib/locomotive/liquid/tags/with_scope_spec.rb +6 -0
  54. data/spec/mailers/locomotive/notifications_spec.rb +15 -8
  55. data/spec/models/locomotive/content_entry_spec.rb +1 -1
  56. data/spec/models/locomotive/editable_control_spec.rb +2 -2
  57. data/spec/models/locomotive/extensions/page/layout_spec.rb +50 -0
  58. data/spec/models/locomotive/site_spec.rb +1 -1
  59. metadata +26 -7
@@ -117,7 +117,7 @@ module Locomotive
117
117
  #
118
118
  def fetch_target_entries(conditions = {})
119
119
  if self.content_type
120
- self.content_type.ordered_entries(conditions)
120
+ self.content_type.ordered_entries(where: conditions)
121
121
  else
122
122
  []
123
123
  end
@@ -8,6 +8,7 @@ module Locomotive
8
8
  ## Extensions ##
9
9
  include Extensions::Page::Tree
10
10
  include Extensions::Page::EditableElements
11
+ include Extensions::Page::Layout
11
12
  include Extensions::Page::Parse
12
13
  include Extensions::Page::Render
13
14
  include Extensions::Page::Templatized
@@ -94,7 +94,11 @@ module Locomotive
94
94
  {}.tap do |hash|
95
95
  (self.__source.has_many_custom_fields + self.__source.many_to_many_custom_fields).each do |name, _|
96
96
  if self.__depth == 0
97
- list = self.__source.send(name.to_sym).ordered
97
+ field = self.__source.content_type.find_entries_custom_field(name.to_s)
98
+
99
+ next if self.html_view? && !field.ui_enabled?
100
+
101
+ list = self.__source.send(name.to_sym).ordered
98
102
  hash[name.to_s] = list.map do |entry|
99
103
  if self.html_view?
100
104
  entry.to_presenter(depth: self.__depth + 1, html_view: true).as_json
@@ -16,7 +16,7 @@ module Locomotive
16
16
  property :redirect, type: 'Boolean'
17
17
  properties :redirect_url, :redirect_type
18
18
 
19
- properties :listed, :published, :templatized, type: 'Boolean'
19
+ properties :listed, :published, :templatized, :is_layout, :allow_layout, type: 'Boolean'
20
20
 
21
21
  property :templatized_from_parent, type: 'Boolean', only_getter: true
22
22
  property :target_klass_slug, alias: [:target_klass_name, :target_entry_name]
@@ -0,0 +1,81 @@
1
+ module Locomotive
2
+ class ContentEntryService < Struct.new(:content_type)
3
+
4
+ # List all the entries of a content type.
5
+ #
6
+ # If the content type allows the pagination, in other words, if the entries are not
7
+ # ordered by the position column), then this method will return
8
+ # a paginated list of entries.
9
+ #
10
+ # This list can also be filtered by the _label attribute, by setting the "q" key in the options.
11
+ #
12
+ # For a more powerful search, you can use the "where" key which accepts a JSON string or a Hash.
13
+ #
14
+ # @param [ Hash ] options The options for the pagination and the filtering
15
+ #
16
+ # @return [ Object ] a paginated list of content entries
17
+ #
18
+ def all(options = {})
19
+ _options = prepare_options_for_all(options)
20
+
21
+ if _options[:grouping]
22
+ content_type.list_or_group_entries(_options)
23
+ else
24
+ content_type.ordered_entries(_options)
25
+ end
26
+ end
27
+
28
+ # Destroy all the entries of a content type.
29
+ # Runs each entry's destroy callbacks.
30
+ #
31
+ def destroy_all
32
+ content_type.entries.destroy_all
33
+ end
34
+
35
+ protected
36
+
37
+ def prepare_options_for_all(options)
38
+ where = prepare_where_statement(options)
39
+
40
+ {
41
+ page: options[:page] || 1,
42
+ per_page: options[:per_page] || Locomotive.config.ui[:per_page],
43
+ grouping: options[:grouping] || options[:q].blank?,
44
+ where: where
45
+ }.tap do |_options|
46
+ _options[:order_by] = options[:order_by] if options[:order_by]
47
+ end
48
+ end
49
+
50
+ def prepare_where_statement(options)
51
+ where = (case options[:where]
52
+ when String then options[:where].blank? ? {} : JSON.parse(options[:where])
53
+ when Hash then options[:where]
54
+ else {}
55
+ end).with_indifferent_access
56
+
57
+ if options[:q]
58
+ where.merge!(prepare_query_statement(options[:q]))
59
+ end
60
+
61
+ where
62
+ end
63
+
64
+ def prepare_query_statement(query)
65
+ regexp = /.*#{query.split.map { |q| Regexp.escape(q) }.join('.*')}.*/i
66
+
67
+ {}.tap do |where|
68
+ if self.content_type.filter_fields.blank?
69
+ where[content_type.label_field_name.to_sym] = regexp
70
+ else
71
+ where['$or'] = []
72
+ self.content_type.filter_fields.each do |field_id|
73
+ field = self.content_type.entries_custom_fields.find(field_id)
74
+ where['$or'] << { field.name => regexp }
75
+ end
76
+ end
77
+ end
78
+ end
79
+
80
+ end
81
+ end
@@ -10,7 +10,7 @@ module Locomotive
10
10
  end
11
11
 
12
12
  def extension_white_list
13
- %w(jpg jpeg gif png css js swf flv eot svg ttf woff otf ico htc)
13
+ %w(jpg jpeg gif png css js swf flv eot svg ttf woff woff2 otf ico htc)
14
14
  end
15
15
 
16
16
  def self.url_for(site, path)
@@ -11,9 +11,17 @@
11
11
 
12
12
  = local_action_button :new, new_content_entry_path(@content_type.slug), icon: 'icon-plus'
13
13
 
14
+ - if @content_type.filter_fields.present?
15
+ .search-box
16
+ = form_tag content_entries_path(@content_type.slug), method: :get do
17
+ %i.icon-search
18
+ = text_field_tag :q, params[:q], placeholder: t('.search_placeholder')
19
+
14
20
  - if @content_type.description.present?
15
21
  %p= @content_type.description
16
22
 
23
+ .clear
24
+
17
25
  - if @content_type.groupable?
18
26
  - @content_entries.each do |group|
19
27
  .box
@@ -34,6 +34,8 @@
34
34
 
35
35
  = f.input :order_direction, as: :select, collection: options_for_order_direction, include_blank: false, wrapper_html: { style: "#{'display: none' if @content_type.order_manually?}" }
36
36
 
37
+ = f.input :filter_fields, as: :select, collection: options_for_filter_fields(@content_type), include_blank: false, multiple: true, wrapper_html: { class: 'multiple' }
38
+
37
39
  = f.input :public_submission_enabled, as: :'Locomotive::Toggle'
38
40
 
39
41
  = f.input :public_submission_accounts, as: :select, collection: options_for_account, include_blank: false, multiple: true, wrapper_html: { class: 'multiple', style: (@content_type.public_submission_enabled? ? '' : 'display: none') }
@@ -1,4 +1,4 @@
1
- %p= t('.title', name: @account.name, domain: @domain, date: I18n.l(Time.zone.now), locale: @account.locale).html_safe
1
+ %p= t('.title', name: @account.name, domain: @domain, date: I18n.l(Time.now.in_time_zone), locale: @account.locale).html_safe
2
2
 
3
3
  %p
4
4
  %b= t('.type', type: @type.name, locale: @account.locale)
@@ -28,4 +28,4 @@
28
28
  - when 'tags'
29
29
  = value.join(', ')
30
30
  - else
31
- = value
31
+ = value
@@ -16,6 +16,9 @@
16
16
 
17
17
  = f.input :slug, required: false, hint: @page.slug.blank? ? t('.empty_slug') : public_page_url(@page, locale: current_content_locale), input_html: { :'data-url' => get_path_pages_path, disabled: @page.index? || @page.not_found? }, wrapper_html: { style: "#{'display: none' if @page.templatized? && !@page.templatized_from_parent?};", class: 'em-inline-hints' }
18
18
 
19
+ - if display_page_layouts?
20
+ = f.input :layout, as: :select, collection: options_for_page_layouts, include_blank: false
21
+
19
22
  = f.inputs name: :seo, class: "inputs foldable #{'folded' if inputs_folded?(@page)}" do
20
23
 
21
24
  = f.input :seo_title
@@ -29,6 +32,10 @@
29
32
  - if can?(:customize, @page)
30
33
  = f.input :handle
31
34
 
35
+ = f.input :is_layout, as: :'Locomotive::Toggle', input_html: { class: 'simple-toggle' }
36
+
37
+ = f.input :allow_layout, as: :'Locomotive::Toggle', input_html: { class: 'simple-toggle' }
38
+
32
39
  = f.input :response_type, as: :select, collection: options_for_page_response_type, include_blank: false
33
40
 
34
41
  = f.input :templatized, as: :'Locomotive::Toggle', style: "#{'display: none' if @page.redirect? || @page.templatized_from_parent?}"
@@ -51,7 +58,7 @@
51
58
 
52
59
  = f.input :cache_strategy, as: :select, collection: options_for_page_cache_strategy, include_blank: false, wrapper_html: { style: "#{'display: none' if @page.redirect?}" }
53
60
 
54
- - if can?(:customize, @page)
61
+ - if can?(:customize, @page) && @page.layout.nil?
55
62
  = f.inputs name: :raw_template, class: "inputs foldable #{'folded' if inputs_folded?(@page)}" do
56
63
 
57
64
  = f.input :raw_template, as: :'Locomotive::Code', main_locale_template_url: page_main_template_path(@page)
@@ -155,6 +155,7 @@ en:
155
155
  delete_file: delete
156
156
  cancel: cancel
157
157
  default_block: Default
158
+ no_layout: Do not use a layout
158
159
  cache_strategy:
159
160
  none: None
160
161
  simple: Simple
@@ -303,6 +304,7 @@ en:
303
304
  category_noname: "No name"
304
305
  latest_entries: "Latest entries"
305
306
  updated_at: "Updated at"
307
+ search_placeholder: "Enter your search keywords here"
306
308
  list:
307
309
  no_items: "There are no entries for now. Just click <a href=\"%{url}\">here</a> to create the first one."
308
310
  new:
@@ -304,6 +304,7 @@ fr:
304
304
  category_noname: "Pas de nom"
305
305
  latest_entries: "Eléments récents"
306
306
  updated_at: "Mis à jour le"
307
+ search_placeholder: "Tapez votre recherche ici"
307
308
  list:
308
309
  no_entries: "Il n'existe pas d'éléments. Vous pouvez commencer par créer un <a href='%{url}'>ici</a>"
309
310
  new:
@@ -68,6 +68,8 @@ en:
68
68
  seo_title: "Define a page title which should be used as the value for the title tag in the head section. Leave it empty if you want to use the default value from the site settings."
69
69
  meta_keywords: "Overrides the site's meta keywords used within the head tag of the page. They are separated by a comma."
70
70
  meta_description: "Overrides the site's meta description used within the head tag of the page."
71
+ is_layout: "If true, this page can used as a layout for other pages."
72
+ allow_layout: "Let authors change or not the layout of that page."
71
73
  snippet:
72
74
  slug: "You need to know it in order to insert the snippet inside a page"
73
75
  site:
@@ -105,6 +107,7 @@ en:
105
107
  name: "We suggest you to type the plural form of the model. Ex: Projects, Recipes, Posts, Articles, ...etc"
106
108
  slug: "It will be used as the name of the collection in the liquid templates. Ex: <span class='code'>{{ contents.my_projects }}</span>"
107
109
  raw_item_template: "You can customize the text displayed for each item in the list. Simply use Liquid. Ex: <span class='code'>{{ entry.name }})</span>"
110
+ filter_fields: "If not empty, a filter bar will be displayed on the page listing the entries. The entries will be then filtered by the field(s) selected in the select box above."
108
111
  public_submission_enabled: "It is used to let people from outside to create new entries (example: messages in a contact form)"
109
112
  public_submission_accounts: "If the public submission option is enabled and for each entry created, sends a notification email to the accounts listed above."
110
113
  "custom_fields/field":
@@ -67,13 +67,15 @@ Rails.application.routes.draw do
67
67
 
68
68
  match 'documentation' => 'documentation#show'
69
69
 
70
+ match 'version' => 'version#show'
71
+
70
72
  resources :tokens, only: [:create, :destroy]
71
73
 
72
74
  resource :current_site, controller: 'current_site', only: [:show, :update, :destroy]
73
75
 
74
76
  resources :memberships, only: [:index, :show, :create, :update, :destroy]
75
77
 
76
- resource :my_account, controller: 'my_account', only: :show
78
+ resource :my_account, controller: 'my_account', only: [:show, :create, :update]
77
79
 
78
80
  with_options only: [:index, :show, :create, :update, :destroy] do |api|
79
81
 
@@ -87,7 +89,9 @@ Rails.application.routes.draw do
87
89
 
88
90
  api.resources :content_types
89
91
 
90
- api.resources :content_entries, path: 'content_types/:slug/entries'
92
+ api.resources :content_entries, path: 'content_types/:slug/entries' do
93
+ delete :index, on: :collection, action: :destroy_all
94
+ end
91
95
 
92
96
  api.resources :theme_assets
93
97
 
@@ -19,6 +19,7 @@ Feature: Content Entries
19
19
  | Logo | file | false | |
20
20
  | Client | belongs_to | false | Clients |
21
21
  And I have "code, design" as "Type" values of the "Projects" model
22
+ And I have the "Projects" entries ordered by the "Name" field
22
23
  And I have a custom model named "Workers" with
23
24
  | label | type | required |
24
25
  | Name | string | true |
@@ -48,6 +49,18 @@ Feature: Content Entries
48
49
  | 4f832c2cb0d86d3f42fffff0 | p1 | first | code | false | 2012-07-01 | logo1.jpg |
49
50
  | 4f832c2cb0d86d3f42fffff1 | p2 | 2nd | design | true | 2012-11-30 | logo1.jpg |
50
51
 
52
+ # paginating the content entries
53
+ Scenario: Paginating content entries
54
+ When I do an API GET request to content_types/projects/entries.json with:
55
+ """
56
+ {
57
+ "page": 1,
58
+ "per_page": 1
59
+ }
60
+ """
61
+ Then the JSON response should be an array
62
+ And the JSON response should have 1 entries
63
+
51
64
  # create content entry
52
65
 
53
66
  Scenario: Creating new project
@@ -71,15 +84,15 @@ Feature: Content Entries
71
84
  Then the JSON response should be an array
72
85
  And the JSON response should have 3 entries
73
86
  And the JSON should have the following:
74
- | 2/name | "Project 3" |
75
- | 2/desc | "The third" |
76
- | 2/type | "code" |
77
- | 2/started | false |
78
- | 2/due | "06/01/2012" |
79
- | 2/workers/0 | "w1" |
80
- | 2/workers/1 | "w3" |
81
- | 2/client | "c1" |
82
- And the JSON at "2/logo" should match /logo2.jpg$/
87
+ | 0/name | "Project 3" |
88
+ | 0/desc | "The third" |
89
+ | 0/type | "code" |
90
+ | 0/started | false |
91
+ | 0/due | "06/01/2012" |
92
+ | 0/workers/0 | "w1" |
93
+ | 0/workers/1 | "w3" |
94
+ | 0/client | "c1" |
95
+ And the JSON at "0/logo" should match /logo2.jpg$/
83
96
  And the response content type should match /application\/json/
84
97
 
85
98
  Scenario: Updating existing project
@@ -35,7 +35,7 @@ Scenario: Add a new site with chosen locale
35
35
  Scenario: Change timezone of site
36
36
  Given I am an authenticated user
37
37
  When I go to the site settings
38
- And I select "(GMT+04:00) Moscow" from "Timezone"
38
+ And I select "(GMT+03:00) Moscow" from "Timezone"
39
39
  Then I press "Save"
40
40
  Then I should see "My site was successfully updated." in the html code
41
41
 
@@ -12,11 +12,13 @@ Background:
12
12
  | Body | string | false |
13
13
  | Hidden | boolean | false |
14
14
  | Published at | date | false |
15
+ | Category | select | false |
16
+ And I have "Design, Development" as "Category" values of the "Articles" model
15
17
  And I have entries for "Articles" with
16
- | title | body | published_at | hidden |
17
- | Hello world | Lorem ipsum | 2015-01-01 | false |
18
- | Lorem ipsum | Lorem ipsum... | 2013-03-23 | false |
19
- | Yadi Yada | Lorem ipsum... | 2013-03-23 | true |
18
+ | title | body | published_at | category | hidden |
19
+ | Hello world | Lorem ipsum | 2015-01-01 | Development | false |
20
+ | Lorem ipsum | Lorem ipsum... | 2013-03-23 | Development | false |
21
+ | Yadi Yada | Lorem ipsum... | 2013-03-23 | Design | true |
20
22
 
21
23
  Scenario: List all of them
22
24
  Given a page named "my-articles" with the template:
@@ -29,6 +31,19 @@ Scenario: List all of them
29
31
  Hello world, Lorem ipsum, Yadi Yada
30
32
  """
31
33
 
34
+ Scenario: Filter by a select field
35
+ Given a page named "my-articles" with the template:
36
+ """
37
+ {% with_scope category: 'Development' %}
38
+ {% for article in contents.articles %}{{ article.title }}, {% endfor %}
39
+ {% endwith_scope %}
40
+ """
41
+ When I view the rendered page at "/my-articles"
42
+ Then the rendered output should look like:
43
+ """
44
+ Hello world, Lorem ipsum
45
+ """
46
+
32
47
  Scenario: Filter by a boolean
33
48
  Given a page named "my-articles" with the template:
34
49
  """
@@ -66,4 +81,4 @@ Scenario: Filter with regexp
66
81
  Then the rendered output should look like:
67
82
  """
68
83
  Hello world, Yadi Yada
69
- """
84
+ """
@@ -126,4 +126,10 @@ end
126
126
  Given(/^I click on the (\d+)[a-z]+ required flag$/) do |nth|
127
127
  find(".custom-field:nth-child(#{nth}) .required-input .switchHandle").click
128
128
  sleep(0.1)
129
+ end
130
+
131
+ Given(/^I have the "(.*?)" entries ordered by the "(.*?)" field$/) do |name, field|
132
+ content_type = Locomotive::ContentType.where(name: name).first
133
+ field = content_type.entries_custom_fields.detect { |f| f.label == field }
134
+ content_type.update_attribute :order_by, field.name
129
135
  end
@@ -1,8 +1,6 @@
1
1
  # Use this hook to configure devise mailer, warden hooks and so forth. The first
2
2
  # four configuration values can also be set straight in your models.
3
3
  Devise.setup do |config|
4
- config.secret_key = "d9eb5171c59a4c817f68b0de27b8c1e340c2341b52cdbc60d3083d4e8958532" \
5
- "18dcc5f589cafde048faec956b61f864b9b5513ff9ce29bf9e5d58b0f234f8e3b"
6
4
 
7
5
  # ==> Mailer Configuration
8
6
  # Configure the e-mail address which will be shown in Devise::Mailer,
@@ -81,4 +81,4 @@ module Locomotive
81
81
 
82
82
  end
83
83
  end
84
- end
84
+ end
@@ -7,6 +7,7 @@ require 'locomotive/carrierwave/patches'
7
7
  # register missing mime types
8
8
  EXTENSIONS[:eot] = 'application/vnd.ms-fontobject'
9
9
  EXTENSIONS[:woff] = 'application/x-woff'
10
+ EXTENSIONS[:woff2] = 'application/x-woff2'
10
11
  EXTENSIONS[:otf] = 'application/octet-stream'
11
12
 
12
13
  # Allow retina images
@@ -25,7 +25,7 @@ module Locomotive
25
25
  pdf: ['application/pdf', 'application/x-pdf'],
26
26
  stylesheet: ['text/css'],
27
27
  javascript: ['text/javascript', 'text/js', 'application/x-javascript', 'application/javascript', 'text/x-component'],
28
- font: [/^application\/.*font/, 'application/x-font-ttf', 'application/vnd.ms-fontobject', 'image/svg+xml', 'application/x-woff', 'application/x-font-truetype', 'application/x-font-woff']
28
+ font: [/^application\/.*font/, 'application/x-font-ttf', 'application/vnd.ms-fontobject', 'image/svg+xml', 'application/x-woff', 'application/x-woff2', 'application/x-font-truetype', 'application/x-font-woff', 'application/x-font-woff2']
29
29
  }
30
30
  end
31
31
 
@@ -7,10 +7,12 @@ module Locomotive
7
7
  include ::HTTParty
8
8
 
9
9
  def self.consume(url, options = {})
10
- options[:base_uri], path = self.extract_base_uri_and_path(url)
10
+ options[:method] = :get if options[:method].nil?
11
11
 
12
12
  options.delete(:format) if options[:format] == 'default'
13
13
 
14
+ path = extract_path(url, options)
15
+
14
16
  # auth ?
15
17
  username, password = options.delete(:username), options.delete(:password)
16
18
  options[:basic_auth] = { username: username, password: password } if username
@@ -18,25 +20,29 @@ module Locomotive
18
20
  self.perform_request_to(path, options)
19
21
  end
20
22
 
21
- def self.extract_base_uri_and_path(url)
22
- url = HTTParty.normalize_base_uri(url)
23
+ def self.extract_path(url, options)
24
+ url = HTTParty.normalize_base_uri(url)
25
+ uri = URI.parse(url)
26
+ params = Rack::Utils.parse_nested_query(uri.query)
23
27
 
24
- uri = URI.parse(url)
25
- path = uri.request_uri || '/'
26
- base_uri = "#{uri.scheme}://#{uri.host}"
27
- base_uri += ":#{uri.port}" if uri.port != 80
28
+ key = options[:method].to_sym == :post ? :body : :query
29
+ options[key] = params unless params.blank?
28
30
 
29
- [base_uri, path]
31
+ (uri.path.blank? ? '/' : uri.path).tap do
32
+ uri.query = nil; uri.path = ''
33
+ options[:base_uri] = uri.to_s
34
+ end
30
35
  end
31
36
 
32
37
  def self.perform_request_to(path, options)
33
- # [DEBUG] puts "[WebService] consuming #{path}, #{options.inspect}"
38
+ # [DEBUG]
39
+ # puts "[WebService] consuming #{path}, #{options.inspect}"
34
40
 
35
41
  # sanitize the options
36
42
  options[:format] = options[:format].gsub(/[\'\"]/, '').to_sym if options.has_key?(:format)
37
43
  options[:headers] = { 'User-Agent' => 'LocomotiveCMS' } if options[:with_user_agent]
38
44
 
39
- response = self.get(path, options)
45
+ response = self.send(options.delete(:method), path, options)
40
46
  parsed_response = response.parsed_response
41
47
 
42
48
  if response.code == 200
@@ -52,4 +58,4 @@ module Locomotive
52
58
 
53
59
  end
54
60
  end
55
- end
61
+ end