magentor 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/MIT-LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2010 Preston Stuteville
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,45 @@
1
+ = Magentor
2
+ Simple wrapper for the Magento XMLRPC api
3
+
4
+ Magento api documentation: http://www.magentocommerce.com/support/magento_core_api
5
+
6
+
7
+ = Usage
8
+ Setup your connection to magento
9
+
10
+ Magento::Base.connection = Magento::Connection.new({
11
+ :username => 'username',
12
+ :api_key => 'api_key',
13
+ :host => 'magento.example.org',
14
+ :path => '/magento/api/xmlrpc',
15
+ :port => '80'
16
+ })
17
+
18
+ Then get down to business
19
+
20
+ Magento::Customer.list
21
+ Magento::Product.info(1).sku
22
+ customer = Magento::Customer.find(:first, {:email => 'example@magentor.ccc'})
23
+ customer.update_attributes({:firstname => 'duke', :lastname => 'magentor'})
24
+ customer.delete
25
+
26
+ = License
27
+ Copyright (c) 2010 Preston Stuteville
28
+
29
+ Permission is hereby granted, free of charge, to any person obtaining a copy
30
+ of this software and associated documentation files (the "Software"), to deal
31
+ in the Software without restriction, including without limitation the rights
32
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
33
+ copies of the Software, and to permit persons to whom the Software is
34
+ furnished to do so, subject to the following conditions:
35
+
36
+ The above copyright notice and this permission notice shall be included in
37
+ all copies or substantial portions of the Software.
38
+
39
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
40
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
41
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
42
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
43
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
44
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
45
+ THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ begin
2
+ require 'jeweler'
3
+ Jeweler::Tasks.new do |gemspec|
4
+ gemspec.name = "magentor"
5
+ gemspec.summary = "Ruby wrapper for the Magento xmlrpc api"
6
+ gemspec.email = "preston.stuteville@gmail.com"
7
+ gemspec.homepage = "http://github.com/pstuteville/magentor"
8
+ gemspec.authors = ["Preston Stuteville"]
9
+
10
+ gemspec.has_rdoc = true
11
+ gemspec.rdoc_options = ["--main", "README.rdoc", "--inline-source", "--line-numbers"]
12
+ gemspec.extra_rdoc_files = ["README.rdoc"]
13
+ end
14
+ rescue LoadError
15
+ puts "Jeweler not available. Install it with: gem install jeweler"
16
+ end
data/TODOS ADDED
@@ -0,0 +1,3 @@
1
+ - Implement correct method signatures instead of passing *args to most api calls
2
+ - Validation
3
+ - Add more convenience methods to objects
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'magento'
@@ -0,0 +1,55 @@
1
+ # Base Magento model handles basic crud operations and stores connection to magento instance.
2
+ # It has the following class attributes:
3
+ #
4
+ # * <tt>connection</tt>: the Magento::Connection to use
5
+ #
6
+ # And the following instance attributes:
7
+ # * <tt>attributes</tt>: the attributes of the magento object
8
+ #
9
+ module Magento
10
+ class Base
11
+ attr_accessor :attributes
12
+ class << self; attr_accessor :connection end
13
+
14
+ module ClassMethods
15
+ # Uses the classes name and method to make an rpc call through connection
16
+ def commit(method, *args)
17
+ # TODO: need to catch errors sent back from magento and bubble them up appropriately
18
+ method = "#{to_s.split('::').last.underscore.downcase}.#{method}"
19
+ Magento::Base.connection.call(method, *args)
20
+ end
21
+ end
22
+
23
+ module InstanceMethods
24
+ def initialize(attributes = {})
25
+ @attributes = attributes.dup
26
+ end
27
+
28
+ # TODO: find out if the id naming is consistent
29
+ def id
30
+ @attributes["#{self.class.to_s.split('::').last.underscore.downcase}_id"]
31
+ end
32
+
33
+ def id=(_id)
34
+ @attributes["#{self.class.to_s.split('::').last.underscore.downcase}_id"] = _id
35
+ end
36
+
37
+ def object_attributes=(new_attributes)
38
+ return if new_attributes.nil?
39
+ attributes = new_attributes.dup
40
+ attributes.stringify_keys!
41
+ attributes.each do |k, v|
42
+ send(k + "=", v)
43
+ end
44
+ end
45
+
46
+ def method_missing(method, *args)
47
+ return nil unless @attributes
48
+ @attributes[method.to_s]
49
+ end
50
+ end
51
+
52
+ include InstanceMethods
53
+ extend ClassMethods
54
+ end
55
+ end
@@ -0,0 +1,215 @@
1
+ module Magento
2
+ # http://www.magentocommerce.com/wiki/doc/webservices-api/api/catalog_category
3
+ # 100 Requested store view not found.
4
+ # 101 Requested website not found.
5
+ # 102 Category not exists.
6
+ # 103 Invalid data given. Details in error message.
7
+ # 104 Category not moved. Details in error message.
8
+ # 105 Category not deleted. Details in error message.
9
+ # 106 Requested product is not assigned to category.
10
+ class Category < Base
11
+ class << self
12
+ # catalog_category.create
13
+ # Create new category and return its id.
14
+ #
15
+ # Return: int
16
+ #
17
+ # Arguments:
18
+ #
19
+ # int $parentId - ID of parent category
20
+ # array $categoryData - category data ( array(’attribute_code’⇒‘attribute_value’ )
21
+ # mixed $storeView - store view ID or code (optional)
22
+ def create(attributes)
23
+ id = commit("create", attributes)
24
+ record = new(attributes)
25
+ record.id = id
26
+ record
27
+ end
28
+
29
+ # catalog_category.info
30
+ # Retrieve category data
31
+ #
32
+ # Return: array
33
+ #
34
+ # Arguments:
35
+ #
36
+ # int $categoryId - category ID
37
+ # mixed $storeView - store view id or code (optional)
38
+ # array $attributes - return only specified attributes (optional)
39
+ def info(*args)
40
+ new(commit("info", *args))
41
+ end
42
+
43
+ # catalog_category.update
44
+ # Update category
45
+ #
46
+ # Return: boolean
47
+ #
48
+ # Arguments:
49
+ #
50
+ # int $categoryId - ID of category for updating
51
+ # array $categoryData - category data ( array(’attribute_code’⇒‘attribute_value’ )
52
+ # mixed storeView - store view ID or code (optional)
53
+ def update(*args)
54
+ commit("update", *args)
55
+ end
56
+
57
+ # catalog_category.delete
58
+ # Delete category
59
+ #
60
+ # Return: boolean
61
+ #
62
+ # Arguments:
63
+ #
64
+ # int $categoryId - category ID
65
+ def delete(*args)
66
+ commit("delete", *args)
67
+ end
68
+
69
+ # catalog_category.currentStore
70
+ # Set/Get current store view
71
+ #
72
+ # Return: int
73
+ #
74
+ # Arguments:
75
+ #
76
+ # mixed storeView - Store view ID or code.
77
+ def current_store(*args)
78
+ commit("currentStore", *args)
79
+ end
80
+
81
+ # catalog_category.tree
82
+ # Retrieve hierarchical tree of categories.
83
+ #
84
+ # Return: array
85
+ #
86
+ # Arguments:
87
+ #
88
+ # int parentId - parent category id (optional)
89
+ # mixed storeView - store view (optional)
90
+ def tree(*args)
91
+ commit("tree", *args)
92
+ end
93
+
94
+ # catalog_category.level
95
+ # Retrieve one level of categories by website/store view/parent category
96
+ #
97
+ # Return: array
98
+ #
99
+ # Arguments:
100
+ #
101
+ # mixed website - website code or Id (optional)
102
+ # mixed storeView - store view code or Id (optional)
103
+ # mixed parentCategory - parent category Id (optional)
104
+ def level(*args)
105
+ commit("level", *args)
106
+ end
107
+
108
+ # catalog_category.move
109
+ # Move category in tree
110
+ #
111
+ # Return: boolean
112
+ #
113
+ # Arguments:
114
+ #
115
+ # int $categoryId - category ID for moving
116
+ # int $parentId - new category parent
117
+ # int $afterId - category ID after what position it will be moved (optional)
118
+ #
119
+ # NOTE Please make sure that you are not moving category to any of its own children.
120
+ # There are no extra checks to prevent doing it through webservices API, and you won’t
121
+ # be able to fix this from admin interface then
122
+ def move(*args)
123
+ commit("move", *args)
124
+ end
125
+
126
+ # catalog_category.assignedProducts
127
+ # Retrieve list of assigned products
128
+ #
129
+ # Return: array
130
+ #
131
+ # Arguments:
132
+ #
133
+ # int $categoryId - category ID
134
+ # mixed $store - store ID or code
135
+ def assigned_products(*args)
136
+ commit("assignedProducts", *args)
137
+ end
138
+
139
+ # catalog_category.assignProduct
140
+ # Assign product to category
141
+ #
142
+ # Return: boolean
143
+ #
144
+ # Arguments:
145
+ #
146
+ # int $categoryId - category ID
147
+ # mixed $product - product ID or sku
148
+ # int $position - position of product in category (optional)
149
+ def assign_product(*args)
150
+ commit("assignProduct", *args)
151
+ end
152
+
153
+ # catalog_category.updateProduct
154
+ # Update assigned product
155
+ #
156
+ # Return: boolean
157
+ #
158
+ # Arguments:
159
+ #
160
+ # int $categoryId - category ID
161
+ # mixed $product - product ID or sku
162
+ # int $position - position of product in category (optional)
163
+ def update_product(*args)
164
+ commit("updateProduct", *args)
165
+ end
166
+
167
+ # catalog_category.removeProduct
168
+ # Remove product assignment from category
169
+ #
170
+ # Return: boolean
171
+ #
172
+ # Arguments:
173
+ #
174
+ # int $categoryId - category ID
175
+ # mixed $product - product ID or sku
176
+ def remove_product(*args)
177
+ commit("removeProduct", *args)
178
+ end
179
+
180
+ def find_by_id(id)
181
+ info(id)
182
+ end
183
+ end
184
+
185
+ def delete
186
+ self.class.delete(self.id)
187
+ end
188
+
189
+ def update_attribute(name, value)
190
+ @attributes[name] = value
191
+ self.class.update(self.id, Hash[*[name.to_sym, value]])
192
+ end
193
+
194
+ def update_attributes(attrs)
195
+ attrs.each_pair { |k, v| @attributes[k] = v }
196
+ self.class.update(self.id, attrs)
197
+ end
198
+
199
+ def assigned_products(*args)
200
+ self.class.assigned_products(self.id, *args)
201
+ end
202
+
203
+ def assign_product(*args)
204
+ self.class.assign_product(self.id, *args)
205
+ end
206
+
207
+ def update_product(*args)
208
+ self.class.update_product(self.id, *args)
209
+ end
210
+
211
+ def remove_product(*args)
212
+ self.class.remove_product(self.id, *args)
213
+ end
214
+ end
215
+ end
@@ -0,0 +1,42 @@
1
+ module Magento
2
+ # http://www.magentocommerce.com/wiki/doc/webservices-api/api/catalog_category_attribute
3
+ # 100 Requested store view not found.
4
+ # 101 Requested attribute not found.
5
+ class CategoryAttribute < Base
6
+ class << self
7
+ # catalog_category_attribute.list
8
+ # Retrieve category attributes
9
+ #
10
+ # Return: array
11
+ def list
12
+ results = commit("list", nil)
13
+ results.collect do |result|
14
+ new(result)
15
+ end
16
+ end
17
+
18
+ # catalog_category_attribute.currentStore
19
+ # Set/Get current store view
20
+ #
21
+ # Return: int
22
+ #
23
+ # Arguments:
24
+ #
25
+ # mixed storeView - Store view ID or code. (optional)
26
+ def current_store(*args)
27
+ commit("currentStore", *args)
28
+ end
29
+
30
+ # catalog_category_attribute.options
31
+ # Retrieve attribute options
32
+ #
33
+ # Arguments:
34
+ #
35
+ # attributeId - attribute id or code
36
+ # storeView - store view id or code
37
+ def options(*args)
38
+ commit("options", *args)
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,23 @@
1
+ module Magento
2
+ class Connection
3
+ attr_accessor :client, :config, :logger
4
+ def initialize(config = {})
5
+ @logger ||= Logger.new(STDOUT)
6
+ @config = config
7
+ self
8
+ end
9
+
10
+ def connect
11
+ @client = XMLRPC::Client.new(config[:host], config[:path], config[:port])
12
+ @session = @client.call("login", config[:username], config[:api_key])
13
+ end
14
+
15
+ def call(method = nil, *args)
16
+ @logger.debug "call: #{method}, #{args.inspect}"
17
+ connect
18
+ @client.call("call", @session, method, args)
19
+ rescue XMLRPC::FaultException => e
20
+ @logger.debug "exception: #{e.faultCode} -> #{e.faultString}"
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,21 @@
1
+ module Magento
2
+ # http://www.magentocommerce.com/wiki/doc/webservices-api/api/directory_country
3
+ class Country < Base
4
+ class << self
5
+ # directory_country.list
6
+ # Retrieve list of countries.
7
+ #
8
+ # Return: array.
9
+ def list
10
+ results = commit("list", nil)
11
+ results.collect do |result|
12
+ new(result)
13
+ end
14
+ end
15
+
16
+ def all
17
+ list
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,122 @@
1
+ module Magento
2
+ # http://www.magentocommerce.com/wiki/doc/webservices-api/api/customer
3
+ # 100 Invalid customer data. Details in error message.
4
+ # 101 Invalid filters specified. Details in error message.
5
+ # 102 Customer does not exist.
6
+ # 103 Customer not deleted. Details in error message.
7
+ class Customer < Base
8
+ class << self
9
+ # customer.list
10
+ # Retrieve customers
11
+ #
12
+ # Return: array
13
+ #
14
+ # Arguments:
15
+ #
16
+ # array filters - filters by customer attributes (optional)
17
+ # filter list - “updated_at”, “website_id”, “increment_id”, “lastname”, “group_id”,
18
+ # “firstname”, “created_in”, “customer_id”, “password_hash”, “store_id”, “email”, “created_at”
19
+ #
20
+ # Note: password_hash will only match exactly with the same MD5 and salt as was used when
21
+ # Magento stored the value. If you try to match with an unsalted MD5 hash, or any salt other
22
+ # than what Magento used, it will not match. This is just a straight string comparison.
23
+ def list(*args)
24
+ results = commit("list", *args)
25
+ results.collect do |result|
26
+ new(result)
27
+ end
28
+ end
29
+
30
+ # customer.create
31
+ # Create customer
32
+ #
33
+ # Return: int
34
+ #
35
+ # Arguments:
36
+ #
37
+ # array customerData - cutomer data (email, firstname, lastname, etc...)
38
+ def create(attributes)
39
+ id = commit("create", attributes)
40
+ record = new(attributes)
41
+ record.id = id
42
+ record
43
+ end
44
+
45
+
46
+ # customer.info
47
+ # Retrieve customer data
48
+ #
49
+ # Return: array
50
+ #
51
+ # Arguments:
52
+ #
53
+ # int customerId - Customer ID.
54
+ # array attributes | string attribute (optional depending on version) -
55
+ # return only these attributes. Possible attributes are updated_at, increment_id,
56
+ # customer_id, created_at. The value, customer_id, is always returned.
57
+ def info(*args)
58
+ new(commit("info", *args))
59
+ end
60
+
61
+ # customer.update
62
+ # Update customer data
63
+ #
64
+ # Return: boolean
65
+ #
66
+ # Arguments:
67
+ #
68
+ # int customerId - customer ID
69
+ # array customerData - customer data (email, firstname, etc...)
70
+ def update(*args)
71
+ commit("update", *args)
72
+ end
73
+
74
+
75
+ # customer.delete
76
+ # Delete customer
77
+ #
78
+ # Return: boolean
79
+ #
80
+ # Arguments:
81
+ #
82
+ # int customerId - customer ID.
83
+ def delete(*args)
84
+ commit("delete", *args)
85
+ end
86
+
87
+ def find_by_id(id)
88
+ info(id)
89
+ end
90
+
91
+ def find(find_type, options = {})
92
+ filters = {}
93
+ options.each_pair { |k, v| filters[k] = {:eq => v} }
94
+ results = list(filters)
95
+ if find_type == :first
96
+ results.first
97
+ else
98
+ results
99
+ end
100
+ end
101
+
102
+ def all
103
+ list
104
+ end
105
+
106
+ end
107
+
108
+ def delete
109
+ self.class.delete(self.id)
110
+ end
111
+
112
+ def update_attribute(name, value)
113
+ @attributes[name] = value
114
+ self.class.update(self.id, Hash[*[name.to_sym, value]])
115
+ end
116
+
117
+ def update_attributes(attrs)
118
+ attrs.each_pair { |k, v| @attributes[k] = v }
119
+ self.class.update(self.id, attrs)
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,101 @@
1
+ module Magento
2
+ # http://www.magentocommerce.com/wiki/doc/webservices-api/api/customer_address
3
+ # 100 Invalid address data. Details in error message.
4
+ # 101 Customer not exists.
5
+ # 102 Address not exists.
6
+ # 103 Address not deleted. Details in error message.
7
+ class CustomerAddress < Base
8
+ class << self
9
+ # customer_address.list
10
+ # Retrieve customer addresses
11
+ #
12
+ # Return: array
13
+ #
14
+ # Arguments:
15
+ #
16
+ # int customerId - Customer Id
17
+ def list(*args)
18
+ results = commit("list", *args)
19
+ results.collect do |result|
20
+ new(result)
21
+ end
22
+ end
23
+
24
+ # customer_address.create
25
+ # Create customer address
26
+ #
27
+ # Return: int
28
+ #
29
+ # Arguments:
30
+ #
31
+ # int customerId - customer ID
32
+ # array addressData - adress data (country, zip, city, etc...)
33
+ def create(attributes)
34
+ id = commit("create", attributes)
35
+ record = new(attributes)
36
+ record.id = id
37
+ record
38
+ end
39
+
40
+ # customer_address.info
41
+ # Retrieve customer address data
42
+ #
43
+ # Return: array
44
+ #
45
+ # Arguments:
46
+ #
47
+ # int addressId - customer address ID
48
+ def info(*args)
49
+ new(commit("info", *args))
50
+ end
51
+
52
+ # customer_address.update
53
+ # Update customer address data
54
+ #
55
+ # Return: boolean
56
+ #
57
+ # Arguments:
58
+ #
59
+ # int addressId - customer address ID
60
+ # array addressData - adress data (country, zip, city, etc...)
61
+ def update(*args)
62
+ commit("update", *args)
63
+ end
64
+
65
+ # customer_address.delete
66
+ # Delete customer address
67
+ #
68
+ # Return: boolean
69
+ #
70
+ # Arguments:
71
+ #
72
+ # int addressId - customer address ID
73
+ def delete(*args)
74
+ commit("delete", *args)
75
+ end
76
+
77
+ def find_by_id(id)
78
+ info(id)
79
+ end
80
+
81
+ def find_by_customer_id(id)
82
+ list(id)
83
+ end
84
+
85
+ end
86
+
87
+ def delete
88
+ self.class.delete(self.id)
89
+ end
90
+
91
+ def update_attribute(name, value)
92
+ @attributes[name] = value
93
+ self.class.update(self.id, Hash[*[name.to_sym, value]])
94
+ end
95
+
96
+ def update_attributes(attrs)
97
+ attrs.each_pair { |k, v| @attributes[k] = v }
98
+ self.class.update(self.id, attrs)
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,17 @@
1
+ module Magento
2
+ # http://www.magentocommerce.com/wiki/doc/webservices-api/api/customer_group
3
+ class CustomerGroup < Base
4
+ class << self
5
+ # customer_group.list
6
+ # Retrieve customer groups
7
+ #
8
+ # Return: array
9
+ def list
10
+ results = commit("list", nil)
11
+ results.collect do |result|
12
+ new(result)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,4 @@
1
+ module Magento
2
+ class Inventory < Base
3
+ end
4
+ end