bsm-openx 1.9.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.
@@ -0,0 +1,125 @@
1
+ module OpenX
2
+ module Services
3
+
4
+ class TargetingRule < Hash
5
+ TYPES = {
6
+ 'Client' => %w(Browser Domain Ip Language Os Useragent),
7
+ 'Geo' => %w(Areacode City Continent Country Dma Latlong Netspeed Organisation Postalcode Region),
8
+ 'Site' => %w(Channel Pageurl Referingpage Source Variable),
9
+ 'Time' => %w(Date Day Hour)
10
+ }.freeze
11
+
12
+ DATA_KEYS = ['comparison', 'data', 'logical'].freeze
13
+ ALL_KEYS = (DATA_KEYS + ['type']).freeze
14
+
15
+ attr_reader :type
16
+
17
+ def self.instantiate(hash)
18
+ rule = new(hash['type'])
19
+ DATA_KEYS.each {|k| rule.update k => hash[k] }
20
+ rule
21
+ end
22
+
23
+ def initialize(type)
24
+ super().update('type' => verify_type(type), 'logical' => 'and')
25
+ end
26
+
27
+ def equal?(value)
28
+ update 'comparison' => '==', 'data' => convert(value)
29
+ end
30
+ alias_method :eq?, :equal?
31
+ alias_method :is?, :equal?
32
+ alias_method :==, :equal?
33
+
34
+ def not_equal?(value)
35
+ update 'comparison' => '!=', 'data' => convert(value)
36
+ end
37
+ alias_method :ne?, :not_equal?
38
+ alias_method :not?, :not_equal?
39
+
40
+ def lt?(value)
41
+ update 'comparison' => '<', 'data' => convert(value)
42
+ end
43
+ alias_method :<, :lt?
44
+
45
+ def gt?(value)
46
+ update 'comparison' => '>', 'data' => convert(value)
47
+ end
48
+ alias_method :>, :gt?
49
+
50
+ def lte?(value)
51
+ update 'comparison' => '<=', 'data' => convert(value)
52
+ end
53
+ alias_method :<=, :lte?
54
+
55
+ def gte?(value)
56
+ update 'comparison' => '>=', 'data' => convert(value)
57
+ end
58
+ alias_method :>=, :gte?
59
+
60
+ def match?(value)
61
+ update 'comparison' => '=x', 'data' => convert(value)
62
+ end
63
+ alias_method :=~, :match?
64
+
65
+ def &(other)
66
+ other.logical('and')
67
+ end
68
+
69
+ def |(other)
70
+ other.logical('or')
71
+ end
72
+
73
+ def no_match?(value)
74
+ update 'comparison' => '!x', 'data' => convert(value)
75
+ end
76
+
77
+ def include?(*value)
78
+ update 'comparison' => '=~', 'data' => convert(value)
79
+ end
80
+ alias_method :contains?, :include?
81
+
82
+ def exclude?(*value)
83
+ update 'comparison' => '!~', 'data' => convert(value)
84
+ end
85
+ alias_method :does_not_contain?, :exclude?
86
+
87
+ def with(value)
88
+ update 'data' => convert(value)
89
+ end
90
+
91
+ def compare(value)
92
+ update 'comparison' => value
93
+ end
94
+
95
+ def logical(value)
96
+ value = value.to_s
97
+ update 'logical' => (value == 'or' ? value : 'and')
98
+ end
99
+
100
+ def complete?
101
+ values_at(*ALL_KEYS).all? {|v| !v.nil? }
102
+ end
103
+
104
+ private
105
+
106
+ def verify_type(type)
107
+ group, component = type.to_s.split(':').last(2)
108
+ raise "Invalid type '#{self['type']}'" unless TYPES.key?(group) && TYPES[group].include?(component)
109
+ "#{group}:#{component}"
110
+ end
111
+
112
+ def convert(value)
113
+ case value
114
+ when Array
115
+ value.map {|v| convert(v) }.join(',')
116
+ when Regexp
117
+ value.source
118
+ else
119
+ value.to_s
120
+ end
121
+ end
122
+
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,26 @@
1
+ module OpenX
2
+ module Services
3
+
4
+ # Create targeting rule sets. Example:
5
+ #
6
+ # rules = OpenX::Services::TargetingRules.new do |t|
7
+ # t['Site:Pageurl'].include?('test') &
8
+ # t['Client:Ip'].match?(/^127\./) |
9
+ # t['Geo:Country'].include?('GB', 'US')
10
+ # end
11
+ class TargetingRules < Array
12
+
13
+ def initialize(&block)
14
+ super([])
15
+ block.call(self)
16
+ end
17
+
18
+ def [](key)
19
+ rule = TargetingRule.new(key)
20
+ push(rule)
21
+ rule
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,82 @@
1
+ module OpenX
2
+ module Services
3
+ class Zone < Base
4
+ # Delivery types
5
+ BANNER = 'delivery-b'
6
+ INTERSTITIAL = 'delivery-i'
7
+ TEXT = 'delivery-t'
8
+ EMAIL = 'delivery-e'
9
+
10
+ # Tag Types
11
+ JAVASCRIPT = 'adjs'
12
+ LOCAL = 'local'
13
+ IFRAME = 'adframe'
14
+ XMLRPC_TAG = 'xmlrpc'
15
+
16
+ openx_accessor :name => :zoneName,
17
+ :id => :zoneId,
18
+ :width => :width,
19
+ :height => :height,
20
+ :type => :type,
21
+ :publisher_id => :publisherId
22
+
23
+ has_one :publisher
24
+
25
+ self.create = 'ox.addZone'
26
+ self.update = 'ox.modifyZone'
27
+ self.delete = 'ox.deleteZone'
28
+ self.find_one = 'ox.getZone'
29
+ self.find_all = 'ox.getZoneListByPublisherId'
30
+
31
+ class << self
32
+
33
+ # Deliver +zone_id+ to +ip_address+ with +cookies+,
34
+ def deliver(zone_id, options = {})
35
+ options = { 'ip_address' => '192.168.1.1', 'cookies' => [] }.update(options)
36
+ server = XmlrpcClient.new("#{connection.host}/delivery/axmlrpc.php")
37
+ server.call('openads.view', options, "zone:#{zone_id}", 0, '', '', true, [])
38
+ end
39
+
40
+ end
41
+
42
+ def initialize(params = {})
43
+ raise "need publisher" unless params[:publisher_id] || params[:publisher]
44
+ params[:publisher_id] ||= params[:publisher].id
45
+ super(params)
46
+ end
47
+
48
+ # Link this zone to +campaign+
49
+ def link_campaign(campaign)
50
+ raise "Zone must be saved" if new_record?
51
+ raise ArgumentError.new("Campaign must be saved")if campaign.new_record?
52
+ remote.call("ox.linkCampaign", self.id, campaign.id)
53
+ end
54
+
55
+ # Unlink this zone from +campaign+
56
+ def unlink_campaign(campaign)
57
+ raise "Zone must be saved" if new_record?
58
+ raise ArgumentError.new("Campaign must be saved")if campaign.new_record?
59
+ remote.call("ox.unlinkCampaign", self.id, campaign.id)
60
+ end
61
+
62
+ # Link this zone to +banner+
63
+ def link_banner(banner)
64
+ raise "Zone must be saved" if new_record?
65
+ raise ArgumentError.new("Banner must be saved")if banner.new_record?
66
+ remote.call("ox.linkBanner", self.id, banner.id)
67
+ end
68
+
69
+ # Unlink this zone from +banner+
70
+ def unlink_banner(banner)
71
+ raise "Zone must be saved" if new_record?
72
+ raise ArgumentError.new("Banner must be saved")if banner.new_record?
73
+ remote.call("ox.unlinkBanner", self.id, banner.id)
74
+ end
75
+
76
+ # Generate tags for displaying this zone using +tag_type+
77
+ def generate_tags(tag_type = IFRAME)
78
+ remote.call("ox.generateTags", self.id, tag_type, [])
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,72 @@
1
+ require 'xmlrpc/client'
2
+
3
+ module OpenX
4
+
5
+ unless defined? HTTPBroken
6
+ # A module that captures all the possible Net::HTTP exceptions
7
+ # from http://pastie.org/pastes/145154
8
+ module HTTPBroken; end
9
+ [
10
+ Timeout::Error, Errno::EINVAL, Errno::EPIPE,
11
+ Errno::ECONNRESET, EOFError, Net::HTTPBadResponse,
12
+ Net::HTTPHeaderSyntaxError, Net::ProtocolError
13
+ ].each {|m| m.send(:include, HTTPBroken) }
14
+ end
15
+
16
+ class XmlrpcClient
17
+ attr_reader :client, :url
18
+
19
+ def initialize(url)
20
+ @url = url
21
+ init_client!
22
+ end
23
+
24
+ def call(method, *args)
25
+ @client.call(method, *convert(args))
26
+ rescue HTTPBroken
27
+ raise unless OpenX.configuration['retry']
28
+ init_client!
29
+ retry
30
+ end
31
+
32
+ protected
33
+
34
+ def convert(args)
35
+ args
36
+ end
37
+
38
+ private
39
+
40
+ def init_client!
41
+ @client = XMLRPC::Client.new2(url)
42
+ @client.timeout = OpenX.configuration['timeout']
43
+ end
44
+
45
+ end
46
+
47
+
48
+ class XmlrpcSessionClient < XmlrpcClient
49
+
50
+ attr_reader :session
51
+
52
+ def initialize(session)
53
+ @session = session
54
+ super(session.url)
55
+ end
56
+
57
+ def call(method, *args)
58
+ super
59
+ rescue XMLRPC::FaultException => error
60
+ raise unless error.message =~ /Session ID.*invalid/i
61
+ session.recreate!
62
+ retry
63
+ end
64
+
65
+ protected
66
+
67
+ def convert(args)
68
+ [session.id] + args
69
+ end
70
+
71
+ end
72
+ end
Binary file
Binary file
data/test/helper.rb ADDED
@@ -0,0 +1,131 @@
1
+ $LOAD_PATH.unshift(File.expand_path(File.join(File.dirname(__FILE__), '../lib')))
2
+
3
+ ENV['OPENX_ENV'] = 'test'
4
+
5
+ require 'rubygems'
6
+ require 'bundler'
7
+
8
+ Bundler.setup
9
+ Bundler.require :test
10
+
11
+ require 'test/unit'
12
+ require 'openx'
13
+
14
+ module OpenX
15
+ class TestCase < ActiveSupport::TestCase
16
+ TEST_SWF = File.expand_path(File.join(File.dirname(__FILE__), 'assets', 'cat.swf'))
17
+ TEST_JPG = File.expand_path(File.join(File.dirname(__FILE__), 'assets', '300x250.jpg'))
18
+
19
+ Base = OpenX::Services::Base
20
+ Banner = OpenX::Services::Banner
21
+ Zone = OpenX::Services::Zone
22
+ Publisher = OpenX::Services::Publisher
23
+ Campaign = OpenX::Services::Campaign
24
+ Agency = OpenX::Services::Agency
25
+ Advertiser = OpenX::Services::Advertiser
26
+ Session = OpenX::Services::Session
27
+ Channel = OpenX::Services::Channel
28
+ TargetingRule = OpenX::Services::TargetingRule
29
+ TargetingRules = OpenX::Services::TargetingRules
30
+
31
+ undef :default_test
32
+
33
+ def setup
34
+ raise 'Please create the credentials file' unless File.exists?(OpenX.config_file)
35
+ end
36
+
37
+ def agency
38
+ @agency ||= Agency.create!({
39
+ :name => "Testing! - #{Time.now}",
40
+ :contact_name => 'Contact Name!',
41
+ :email => 'foo@bar.com'
42
+ })
43
+ end
44
+
45
+ def advertiser
46
+ @advertiser ||= Advertiser.create!(
47
+ {
48
+ :name => "adv-#{Time.now}",
49
+ :contact_name => 'Contact Name!',
50
+ :email => 'foo@bar.com'
51
+ }.merge(:agency => agency)
52
+ )
53
+ end
54
+
55
+ def campaign
56
+ @campaign ||= Campaign.create!(
57
+ {
58
+ :advertiser => advertiser,
59
+ :name => "Campaign-#{Time.now}",
60
+ :impressions => 2000
61
+ }
62
+ )
63
+ end
64
+
65
+ def publisher
66
+ @publisher ||= Publisher.create!(
67
+ {
68
+ :agency => agency,
69
+ :name => "Publisher! - #{Time.now}",
70
+ :contact_name => 'Aaron Patterson',
71
+ :email => 'aaron@tenderlovemaking.com',
72
+ :username => 'one',
73
+ :password => 'two',
74
+ }
75
+ )
76
+ end
77
+
78
+ def zone
79
+ @zone ||= Zone.create!(
80
+ {
81
+ :publisher => publisher,
82
+ :name => "Zone - #{Time.now}",
83
+ :type => Zone::BANNER,
84
+ :width => 300,
85
+ :height => 250,
86
+ }
87
+ )
88
+ end
89
+
90
+ def channel
91
+ @channel ||= Channel.create!(
92
+ {
93
+ :publisher => publisher,
94
+ :name => "Channel - #{Time.now}",
95
+ :comments => 'Random Comments',
96
+ :description => 'Random Description'
97
+ }
98
+ )
99
+ end
100
+
101
+ def banner
102
+ @banner ||= Banner.create!({
103
+ :name => "Banner-#{Time.now}",
104
+ :storage_type => Banner::LOCAL_SQL,
105
+ :campaign => campaign,
106
+ :url => 'http://tenderlovemaking.com/',
107
+ :file_name => 'oogabooga',
108
+ :image => OpenX::Image.new(File.open(TEST_SWF, 'rb'))
109
+ })
110
+ end
111
+
112
+ def targeting_rules
113
+ @targeting_rules ||= OpenX::Services::TargetingRules.new do |t|
114
+ t['Site:Pageurl'].include?('test') &
115
+ t['Client:Ip'].match?(/^127\./) |
116
+ t['Geo:Country'].include?('GB', 'US')
117
+ end
118
+ end
119
+
120
+ def destroy
121
+ @banner.destroy if defined? @banner
122
+ @zone.destroy if defined? @zone
123
+ @publisher.destroy if defined? @publisher
124
+ @campaign.destroy if defined? @campaign
125
+ @advertiser.destroy if defined? @advertiser
126
+ @agency.destroy if defined? @agency
127
+ @channel.destroy if defined? @channel
128
+ end
129
+
130
+ end
131
+ end
@@ -0,0 +1,82 @@
1
+ require File.dirname(__FILE__) + '/helper'
2
+
3
+ class AdvertiserTest < OpenX::TestCase
4
+ def test_create_advertiser
5
+ advertiser = nil
6
+ assert_nothing_raised {
7
+ advertiser = Advertiser.create!(init_params.merge({
8
+ :agency => agency,
9
+ }))
10
+ }
11
+ assert_not_nil advertiser
12
+ init_params.each do |k,v|
13
+ assert_equal(v, advertiser.send(:"#{k}"))
14
+ end
15
+ end
16
+
17
+ def test_destroy
18
+ a = nil
19
+ assert_nothing_raised {
20
+ a = Advertiser.create!(init_params.merge({:agency => agency}))
21
+ }
22
+ id = a.id
23
+ assert_nothing_raised {
24
+ a.destroy
25
+ }
26
+ assert_raises(XMLRPC::FaultException) {
27
+ Advertiser.find(id)
28
+ }
29
+ end
30
+
31
+ def test_create_advertiser_with_agency
32
+ advertiser = nil
33
+ assert_nothing_raised {
34
+ advertiser = agency.create_advertiser!(init_params)
35
+ }
36
+ assert_not_nil advertiser
37
+ init_params.each do |k,v|
38
+ assert_equal(v, advertiser.send(:"#{k}"))
39
+ end
40
+ end
41
+
42
+ def test_find_advertiser
43
+ advertiser = nil
44
+ assert_nothing_raised {
45
+ advertiser = agency.create_advertiser!(init_params)
46
+ }
47
+ assert_not_nil advertiser
48
+
49
+ original = advertiser
50
+ advertiser = Advertiser.find(advertiser.id)
51
+ assert_equal(original, advertiser)
52
+ assert_not_nil advertiser
53
+ assert_not_nil advertiser.agency
54
+ init_params.each do |k,v|
55
+ assert_equal(v, advertiser.send(:"#{k}"))
56
+ end
57
+ end
58
+
59
+ def test_find_all_advertisers
60
+ advertiser = nil
61
+ assert_nothing_raised {
62
+ advertiser = agency.create_advertiser!(init_params)
63
+ }
64
+ assert_not_nil advertiser
65
+
66
+ advertisers = Advertiser.find(:all, agency.id)
67
+
68
+ advertiser = advertisers.find { |a| a.id == advertiser.id }
69
+ assert_not_nil advertiser
70
+ init_params.each do |k,v|
71
+ assert_equal(v, advertiser.send(:"#{k}"))
72
+ end
73
+ end
74
+
75
+ def init_params
76
+ {
77
+ :name => 'Test advertiser',
78
+ :contact_name => 'Contact name',
79
+ :email => 'email@example.com',
80
+ }
81
+ end
82
+ end