prestashop 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +56 -0
  3. data/README.md +111 -0
  4. data/Rakefile +9 -0
  5. data/lib/prestashop.rb +21 -0
  6. data/lib/prestashop/api.rb +9 -0
  7. data/lib/prestashop/api/connection.rb +225 -0
  8. data/lib/prestashop/api/converter.rb +152 -0
  9. data/lib/prestashop/api/error.rb +18 -0
  10. data/lib/prestashop/api/refinement.rb +14 -0
  11. data/lib/prestashop/client.rb +19 -0
  12. data/lib/prestashop/client/cache.rb +53 -0
  13. data/lib/prestashop/client/error.rb +9 -0
  14. data/lib/prestashop/client/implementation.rb +33 -0
  15. data/lib/prestashop/mapper.rb +9 -0
  16. data/lib/prestashop/mapper/extension.rb +161 -0
  17. data/lib/prestashop/mapper/model.rb +38 -0
  18. data/lib/prestashop/mapper/models.rb +1 -0
  19. data/lib/prestashop/mapper/models/address.rb +9 -0
  20. data/lib/prestashop/mapper/models/carrier.rb +9 -0
  21. data/lib/prestashop/mapper/models/cart.rb +9 -0
  22. data/lib/prestashop/mapper/models/cart_rule.rb +9 -0
  23. data/lib/prestashop/mapper/models/category.rb +114 -0
  24. data/lib/prestashop/mapper/models/combination.rb +81 -0
  25. data/lib/prestashop/mapper/models/contact.rb +9 -0
  26. data/lib/prestashop/mapper/models/content_management_system.rb +9 -0
  27. data/lib/prestashop/mapper/models/country.rb +15 -0
  28. data/lib/prestashop/mapper/models/currency.rb +9 -0
  29. data/lib/prestashop/mapper/models/customer.rb +9 -0
  30. data/lib/prestashop/mapper/models/customer_message.rb +9 -0
  31. data/lib/prestashop/mapper/models/customer_thread.rb +9 -0
  32. data/lib/prestashop/mapper/models/delivery.rb +9 -0
  33. data/lib/prestashop/mapper/models/employee.rb +9 -0
  34. data/lib/prestashop/mapper/models/group.rb +9 -0
  35. data/lib/prestashop/mapper/models/guest.rb +9 -0
  36. data/lib/prestashop/mapper/models/image.rb +52 -0
  37. data/lib/prestashop/mapper/models/image_type.rb +9 -0
  38. data/lib/prestashop/mapper/models/language.rb +15 -0
  39. data/lib/prestashop/mapper/models/manufacturer.rb +79 -0
  40. data/lib/prestashop/mapper/models/order.rb +9 -0
  41. data/lib/prestashop/mapper/models/order_carrier.rb +9 -0
  42. data/lib/prestashop/mapper/models/order_detail.rb +9 -0
  43. data/lib/prestashop/mapper/models/order_discount.rb +9 -0
  44. data/lib/prestashop/mapper/models/order_history.rb +9 -0
  45. data/lib/prestashop/mapper/models/order_invoice.rb +9 -0
  46. data/lib/prestashop/mapper/models/order_payment.rb +9 -0
  47. data/lib/prestashop/mapper/models/order_state.rb +9 -0
  48. data/lib/prestashop/mapper/models/price_range.rb +9 -0
  49. data/lib/prestashop/mapper/models/product.rb +198 -0
  50. data/lib/prestashop/mapper/models/product_feature.rb +69 -0
  51. data/lib/prestashop/mapper/models/product_feature_value.rb +60 -0
  52. data/lib/prestashop/mapper/models/product_option.rb +72 -0
  53. data/lib/prestashop/mapper/models/product_option_value.rb +56 -0
  54. data/lib/prestashop/mapper/models/product_supplier.rb +31 -0
  55. data/lib/prestashop/mapper/models/search.rb +9 -0
  56. data/lib/prestashop/mapper/models/shop.rb +9 -0
  57. data/lib/prestashop/mapper/models/shop_group.rb +9 -0
  58. data/lib/prestashop/mapper/models/specific_price.rb +9 -0
  59. data/lib/prestashop/mapper/models/specific_price_rule.rb +9 -0
  60. data/lib/prestashop/mapper/models/state.rb +9 -0
  61. data/lib/prestashop/mapper/models/stock.rb +9 -0
  62. data/lib/prestashop/mapper/models/stock_available.rb +35 -0
  63. data/lib/prestashop/mapper/models/stock_movement.rb +9 -0
  64. data/lib/prestashop/mapper/models/stock_movement_reason.rb +9 -0
  65. data/lib/prestashop/mapper/models/store.rb +9 -0
  66. data/lib/prestashop/mapper/models/supplier.rb +45 -0
  67. data/lib/prestashop/mapper/models/supply_order.rb +9 -0
  68. data/lib/prestashop/mapper/models/supply_order_detail.rb +9 -0
  69. data/lib/prestashop/mapper/models/supply_order_history.rb +9 -0
  70. data/lib/prestashop/mapper/models/supply_order_receipt_history.rb +9 -0
  71. data/lib/prestashop/mapper/models/supply_order_state.rb +9 -0
  72. data/lib/prestashop/mapper/models/tag.rb +9 -0
  73. data/lib/prestashop/mapper/models/tax.rb +24 -0
  74. data/lib/prestashop/mapper/models/tax_rule.rb +15 -0
  75. data/lib/prestashop/mapper/models/tax_rule_group.rb +9 -0
  76. data/lib/prestashop/mapper/models/translated_configuration.rb +9 -0
  77. data/lib/prestashop/mapper/models/warehouse.rb +9 -0
  78. data/lib/prestashop/mapper/models/warehouse_product_location.rb +9 -0
  79. data/lib/prestashop/mapper/models/weight_range.rb +9 -0
  80. data/lib/prestashop/mapper/models/zone.rb +9 -0
  81. data/lib/prestashop/mapper/refinement.rb +43 -0
  82. data/lib/prestashop/version.rb +3 -0
  83. metadata +279 -0
@@ -0,0 +1,18 @@
1
+ module Prestashop
2
+ module Api
3
+ class InvalidCredentials < RuntimeError
4
+ def initialize
5
+ super "Your credentials are invalid"
6
+ end
7
+ end
8
+
9
+ class RequestFailed < RuntimeError
10
+ attr_reader :response
11
+ def initialize response
12
+ @response = response
13
+ end
14
+ end
15
+
16
+ class ParserError < RuntimeError; end
17
+ end
18
+ end
@@ -0,0 +1,14 @@
1
+ module Prestashop
2
+ module Api
3
+ module Refinement
4
+ refine String do
5
+ def parse
6
+ Converter.parse self
7
+ end
8
+ def parse_error
9
+ Converter.parse_error self
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,19 @@
1
+ require 'prestashop/client/error'
2
+ require 'prestashop/client/implementation'
3
+ require 'prestashop/client/cache'
4
+
5
+ module Prestashop
6
+ module Client
7
+ extend SingleForwardable
8
+ def_delegators :current, :connection, :cache
9
+ def_delegators :connection, :create, :read, :update, :delete, :check, :upload
10
+ def_delegators :cache, :manufacturers_cache, :clear_manufacturers_cache, :categories_cache, :clear_categories_cache, :features_cache, :clear_features_cache,
11
+ :feature_values_cache, :clear_feature_values_cache, :options_cache, :clear_options_cache, :option_values_cache, :clear_option_values_cache
12
+
13
+ # Delegate to current user implementation
14
+ #
15
+ def self.current
16
+ Implementation.current
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,53 @@
1
+ module Prestashop
2
+ module Client
3
+ class Cache
4
+ def manufacturers_cache
5
+ @manufacturers_cache ||= Mapper::Manufacturer.cache
6
+ end
7
+
8
+ def clear_manufacturers_cache
9
+ @manufacturers_cache = nil
10
+ end
11
+
12
+ def categories_cache
13
+ @categories_cache ||= Mapper::Category.cache
14
+ end
15
+
16
+ def clear_categories_cache
17
+ @categories_cache = nil
18
+ end
19
+
20
+ def features_cache
21
+ @features_cache ||= Mapper::ProductFeature.cache
22
+ end
23
+
24
+ def clear_features_cache
25
+ @features_cache = nil
26
+ end
27
+
28
+ def feature_values_cache
29
+ @feature_values_cache ||= Mapper::ProductFeatureValue.cache
30
+ end
31
+
32
+ def clear_feature_values_cache
33
+ @feature_values_cache = nil
34
+ end
35
+
36
+ def options_cache
37
+ @options_cache ||= Mapper::ProductOption.cache
38
+ end
39
+
40
+ def clear_options_cache
41
+ @options_cache = nil
42
+ end
43
+
44
+ def option_values_cache
45
+ @option_values_cache ||= Mapper::ProductOptionValue.cache
46
+ end
47
+
48
+ def clear_option_values_cache
49
+ @option_values_cache = nil
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,9 @@
1
+ module Prestashop
2
+ module Client
3
+ class UnitializedClient < RuntimeError
4
+ def initialize
5
+ super "Client isn't initialized"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,33 @@
1
+ require 'singleton'
2
+
3
+ module Prestashop
4
+ module Client
5
+ class Implementation
6
+ include Singleton
7
+ attr_reader :connection, :cache
8
+
9
+ # Initialize new client see +Api::Connection#new+
10
+ #
11
+ def initialize api_key, api_url
12
+ @connection = Api::Connection.new api_key, api_url
13
+ @cache = Cache.new
14
+ end
15
+
16
+ class << self
17
+
18
+ # Create new user implementation, keep it in current thread to allow multithearding, see +#new+
19
+ #
20
+ def create api_key, api_url
21
+ Thread.current[:prestashop_client] = new api_key, api_url
22
+ current
23
+ end
24
+
25
+ # Get current client or raise exception, when client isn't initialized
26
+ #
27
+ def current
28
+ Thread.current[:prestashop_client] ? Thread.current[:prestashop_client] : raise(UnitializedClient)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,9 @@
1
+ require 'prestashop/mapper/refinement'
2
+ require 'prestashop/mapper/extension'
3
+ require 'prestashop/mapper/model'
4
+ require 'prestashop/mapper/models'
5
+
6
+ module Prestashop
7
+ module Mapper
8
+ end
9
+ end
@@ -0,0 +1,161 @@
1
+ module Prestashop
2
+ module Mapper
3
+ module Extension
4
+ module ClassMethods
5
+
6
+ # Determinate if model with class resource exists with given id
7
+ #
8
+ # Car.exists?(1) # => true # if given car exist
9
+ # Car.exists?(2) # => false # if given car don't exist
10
+ #
11
+ def exists? id
12
+ Client.check self.resource, id
13
+ end
14
+
15
+ # Find model by class resource and given id, returns hash
16
+ # with all nodes, based on node name as key, node value as value
17
+ #
18
+ # Car.find(1) # => { id: 1, name: 'BMW' }
19
+ # Car.find(2) # => nil
20
+ #
21
+ def find id
22
+ result = Client.read self.resource, id
23
+ result ? result[self.model] : nil
24
+ end
25
+
26
+ # Find model by class resource and params in hash
27
+ # Returns first result, see #where for more informations
28
+ #
29
+ # Car.find_by(name: 'BMW') # => 1
30
+ #
31
+ def find_by options = {}
32
+ results = where(options)
33
+ results ? results.first : nil
34
+ end
35
+
36
+ # Get models all results by class resource, you can specifi what
37
+ # you should to see as result by specifiyng +:display+
38
+ #
39
+ # Car.all # => [1,2,3]
40
+ # Car.all(display: ['name']) # => [{ name: { language: { attr: { id: 2, href: 'http://localhost.com/api/languages/2'}, val: 'BMW 7'} }]
41
+ #
42
+ def all options = {}
43
+ result = if options[:display]
44
+ Client.read self.resource, nil, display: options[:display]
45
+ else
46
+ Client.read self.resource
47
+ end
48
+ handle_result result, options
49
+ end
50
+
51
+ # Get results by class resource and given conditionals
52
+ #
53
+ # Car.where('filter[id_supplier' => 1) # => [1, 2]
54
+ #
55
+ def where options = {}
56
+ result = Client.read self.resource, nil, options
57
+ handle_result result, options
58
+ end
59
+
60
+ # Destroy model by class resource and given id
61
+ #
62
+ # Car.destroy(1) # => true
63
+ #
64
+ def destroy id
65
+ Client.delete self.resource, id
66
+ end
67
+
68
+ # Create hash suitable for update, contains #fixed_hash as hash with deleted
69
+ # keys, which shouldn't be in payload, if exist
70
+ #
71
+ # Car.update_hash(1, name: 'BMW7') # => {name: 'BMW7', manufacturer: 'BMW'}
72
+ #
73
+ def update_hash id, options = {}
74
+ original = defined?(fixed_hash(nil)) ? fixed_hash(id) : find(id)
75
+ original.merge(options)
76
+ end
77
+
78
+ # Create payload for update, converts hash to XML
79
+ #
80
+ # Car.update_payload(1, name: 'BMW 7') # => <prestashop xmlns:xlink="http://www.w3.org/1999/xlink"><car><name><![CDATA[BMW 7]]></name></car></prestashop>
81
+ #
82
+ def update_payload id, options = {}
83
+ Api::Converter.build(self.resource, self.model, update_hash(id, options))
84
+ end
85
+
86
+ # Update model, with class resource by +id+ and given updates
87
+ #
88
+ # Car.update(1, name: 'BMW 7') # => {id: 1, name: 'BMW 7'}
89
+ #
90
+ def update id, options = {}
91
+ result = Client.update self.resource, id, update_payload(id, options)
92
+ result ? result[self.model] : nil
93
+ end
94
+
95
+ private
96
+ # Handle result to return +id+ or array with +ids+ of requested objects
97
+ #
98
+ # handle_result({ customers: { customer: [ 1,2 ] } }) # => [1, 2]
99
+ # handle_result({ customers: { customer: { attr: { id: 1 }} } }) # => [1]
100
+ #
101
+ def handle_result result, options = {}
102
+ if options[:display]
103
+ if result[self.resource].kind_of?(Hash) and result[self.resource][self.model]
104
+ objects = result[self.resource][self.model]
105
+ objects.kind_of?(Array) ? objects : [objects]
106
+ end
107
+ else
108
+ if result[self.resource].kind_of?(Hash) and result[self.resource][self.model]
109
+ [objects = result[self.resource][self.model]]
110
+ objects.kind_of?(Array) ? objects.map{ |o| o[:attr][:id] } : [ objects[:attr][:id] ]
111
+ else
112
+ nil
113
+ end
114
+ end
115
+ end
116
+ end
117
+
118
+ module InstanceMethods
119
+
120
+ # Generate hash with ID
121
+ #
122
+ # car.hash_id(1) # => {id: 1}
123
+ #
124
+ def hash_id id
125
+ { id: id } if id
126
+ end
127
+
128
+ # Make array of unique IDs in hash
129
+ #
130
+ # car.hash_ids(1,2,3) # => [{id: 1},{id: 2},{id: 3}]
131
+ #
132
+ def hash_ids ids
133
+ ids.flatten.uniq.map{|id| hash_id(id)} if ids
134
+ end
135
+
136
+ # Create payload for create new object, coverts hash to XML
137
+ #
138
+ # car.payload # => '<prestashop xmlns:xlink="http://www.w3.org/1999/xlink"><car><name><![CDATA[BMW 7]]></name><manufacturer><![CDATA[BMW]]></manufacturer></car></prestashop>'
139
+ #
140
+ def payload
141
+ Api::Converter.build(self.class.resource, self.class.model, hash)
142
+ end
143
+
144
+ # Create new model from instance, based on class resource a payload generated from
145
+ # hash method
146
+ #
147
+ # Car.new(name: 'BMW 7', manufacturer: 'BMW').create # => { id: 1, name: 'BMW 7', manufacturer: 'BMW' }
148
+ #
149
+ def create
150
+ result = Client.create self.class.resource, payload
151
+ result ? result[self.class.model] : nil
152
+ end
153
+ end
154
+
155
+ def self.included(receiver)
156
+ receiver.extend ClassMethods
157
+ receiver.send :include, InstanceMethods
158
+ end
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,38 @@
1
+ using Prestashop::Mapper::Refinement
2
+ module Prestashop
3
+ module Mapper
4
+ class Model
5
+ include Extension
6
+ extend Extension
7
+
8
+ # Meta title is same as name, when is not given
9
+ def meta_title
10
+ @meta_title ? @meta_title.plain.truncate(61) : name
11
+ end
12
+
13
+ # Meta description is same as description, when is not given
14
+ def meta_description
15
+ @meta_description ? @meta_description.restricted.truncate(252) : ( description_short.plain if description_short )
16
+ end
17
+
18
+ # Meta keywords are generated from name, when are not given
19
+ def meta_keywords
20
+ @meta_keywords ? @meta_keywords.plain.truncate(61) : name.split(' ').join(', ')
21
+ end
22
+
23
+ def hash_lang name, id_lang
24
+ { language: { val: name, attr: { id: id_lang }}} if name
25
+ end
26
+
27
+ class << self
28
+ def resource value = nil
29
+ value.nil? ? @resource : @resource = value
30
+ end
31
+
32
+ def model value = nil
33
+ value.nil? ? @model : @model = value
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1 @@
1
+ Dir[File.dirname(__FILE__) + '/models/*.rb'].each {|file| require file }
@@ -0,0 +1,9 @@
1
+ using Prestashop::Mapper::Refinement
2
+ module Prestashop
3
+ module Mapper
4
+ class Address < Model
5
+ resource :addresses
6
+ model :address
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ using Prestashop::Mapper::Refinement
2
+ module Prestashop
3
+ module Mapper
4
+ class Carrier < Model
5
+ resource :carriers
6
+ model :carrier
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ using Prestashop::Mapper::Refinement
2
+ module Prestashop
3
+ module Mapper
4
+ class Cart < Model
5
+ resource :carts
6
+ model :cart
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ using Prestashop::Mapper::Refinement
2
+ module Prestashop
3
+ module Mapper
4
+ class CartRule < Model
5
+ resource :cart_rules
6
+ model :cart_rule
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,114 @@
1
+ using Prestashop::Mapper::Refinement
2
+ module Prestashop
3
+ module Mapper
4
+ class Category < Model
5
+ resource :categories
6
+ model :category
7
+
8
+ attr_accessor :id_lang
9
+ attr_accessor :id, :id_parent, :level_depth, :active, :id_shop_default, :is_root_category, :position
10
+ attr_writer :name, :description, :link_rewrite
11
+
12
+ def initialize args = {}
13
+ @id = args[:id]
14
+ @id_parent = args.fetch(:id_parent, 2)
15
+ @level_depth = args[:level_depth]
16
+ # nb_products_recursive
17
+ @active = args.fetch(:active, 1)
18
+ @id_shop_default = args.fetch(:id_shop_default, 1)
19
+ @is_root_category = 0
20
+ @position = args[:position]
21
+ # date_add
22
+ # date_upd
23
+ @name = args.fetch(:name)
24
+ @link_rewrite = args[:link_rewrite]
25
+ @description = args[:description]
26
+ @meta_title = args[:meta_title]
27
+ @meta_description = args[:meta_description]
28
+ @meta_keywords = args[:meta_keywords]
29
+
30
+ @id_lang = args.fetch(:id_lang)
31
+ end
32
+
33
+ # Category name can't have some symbols and can't be longer than 63
34
+ def name
35
+ @name.plain.truncate(61)
36
+ end
37
+
38
+ # Description can have additional symbols and can't be longer than 255
39
+ def description
40
+ @description.restricted.truncate(252) if @description
41
+ end
42
+
43
+ # Link rewrite must be usable in uri
44
+ def link_rewrite
45
+ @link_rewrite ? @link_rewrite.parameterize : name.parameterize
46
+ end
47
+
48
+ # Category hash structure, which will be converted to XML
49
+ def hash
50
+ { id_parent: id_parent,
51
+ active: active ,
52
+ id_shop_default: id_shop_default,
53
+ is_root_category: is_root_category,
54
+ name: hash_lang(name, id_lang),
55
+ link_rewrite: hash_lang(link_rewrite, id_lang),
56
+ description: hash_lang(description, id_lang),
57
+ meta_title: hash_lang(name, id_lang),
58
+ meta_description: hash_lang(description, id_lang),
59
+ meta_keywords: hash_lang(meta_keywords, id_lang) }
60
+ end
61
+
62
+ # Find category by name and id parent, create new one from hash, when doesn't exist
63
+ def find_or_create
64
+ category = self.class.find_in_cache id_parent, name, id_lang
65
+ unless category
66
+ category = create
67
+ Client.clear_categories_cache
68
+ end
69
+ category[:id]
70
+ end
71
+
72
+ class << self
73
+
74
+ # Search for category based on args on cached categories, see #cache and #Client::Settings.categories_cache
75
+ # Returns founded category or nil
76
+ #
77
+ def find_in_cache id_parent, name, id_lang
78
+ Client.categories_cache.find{ |c| c[:id_parent] == id_parent and c[:name].find_lang(name, id_lang) }
79
+ end
80
+
81
+ # Requesting all on Prestashop API, displaying id, id_parent, name
82
+ def cache
83
+ all display: '[id, id_parent, name]'
84
+ end
85
+
86
+ # Create new category based on given param, delimited by delimiter in settings
87
+ #
88
+ # ==== Example:
89
+ # Category.create_from_name('Apple||iPhone', 2) # => [1, 2]
90
+ #
91
+ def create_from_name category_name, id_lang
92
+ if category_name and !category_name.empty?
93
+ names = [category_name.split('||')].flatten!
94
+ categories = []
95
+ id_parent = 2
96
+ names.each do |name|
97
+ id_parent = new(name: name, id_parent: id_parent, id_lang: id_lang).find_or_create
98
+ categories << id_parent
99
+ end
100
+ categories
101
+ end
102
+ end
103
+
104
+ def create_from_names category_names, id_lang
105
+ categories = []
106
+ category_names.each do |category_name|
107
+ categories << create_from_name(category_name, id_lang)
108
+ end
109
+ categories.flatten.uniq
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end