line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Yahoo::Marketing; |
2
|
|
|
|
|
|
|
# Copyright (c) 2009 Yahoo! Inc. All rights reserved. |
3
|
|
|
|
|
|
|
# The copyrights to the contents of this file are licensed under the Perl Artistic License (ver. 15 Aug 1997) |
4
|
|
|
|
|
|
|
|
5
|
168
|
|
|
168
|
|
921384
|
use warnings; |
|
168
|
|
|
|
|
1279
|
|
|
168
|
|
|
|
|
6664
|
|
6
|
168
|
|
|
168
|
|
985
|
use strict; |
|
168
|
|
|
|
|
1364
|
|
|
168
|
|
|
|
|
7007
|
|
7
|
168
|
|
|
168
|
|
1030
|
use Carp; |
|
168
|
|
|
|
|
1580
|
|
|
168
|
|
|
|
|
44303
|
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
=head1 NAME |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
Yahoo::Marketing - an interface for Yahoo! Search Marketing's Web Services. |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
=head1 VERSION |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
Version 7.03 |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
=cut |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
# not using 3 part version #s, |
20
|
|
|
|
|
|
|
# see http://www.perlmonks.org/?node_id=520850 |
21
|
|
|
|
|
|
|
our $VERSION = '7.03'; |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
=head1 SYNOPSIS |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
This collection of modules makes interacting with Yahoo! Search Marketing's Web Services as easy as possible. |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
B |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
Sample Usage: |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
use Yahoo::Marketing::Keyword; |
33
|
|
|
|
|
|
|
use Yahoo::Marketing::KeywordService; |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
my $service = Yahoo::Marketing::KeywordService->new; |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
# setup your credentials |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
$service->username( 'your username' ) |
40
|
|
|
|
|
|
|
->password( 'your password' ) |
41
|
|
|
|
|
|
|
->license( 'your license' ) |
42
|
|
|
|
|
|
|
->master_account( 'your master account ID' ) |
43
|
|
|
|
|
|
|
->account( 'your account ID' ) |
44
|
|
|
|
|
|
|
->endpoint( 'https://sandbox.marketing.ews.yahooapis.com/services' ); |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
# OR |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
$service->parse_config( section => 'sandbox' ); |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
51
|
|
|
|
|
|
|
# create a keyword object, and add it |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
my $keyword = Yahoo::Marketing::Keyword->new |
54
|
|
|
|
|
|
|
->adGroupID( $ad_group_id ) |
55
|
|
|
|
|
|
|
->text( 'some text' ) |
56
|
|
|
|
|
|
|
->alternateText( 'some alternate text' ) |
57
|
|
|
|
|
|
|
->sponsoredSearchMaxBid( 1.00 ) |
58
|
|
|
|
|
|
|
->status( 'On' ) |
59
|
|
|
|
|
|
|
->advancedMatchON( 'true' ) |
60
|
|
|
|
|
|
|
->url( 'http://www.someurl.com' ) |
61
|
|
|
|
|
|
|
; |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
my $keyword_response = $service->addKeyword( keyword => $keyword ); |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
# added keyword will have ID set |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
my $added_keyword = $keyword_response->keyword; |
68
|
|
|
|
|
|
|
... |
69
|
|
|
|
|
|
|
|
70
|
|
|
|
|
|
|
=head1 VERSIONING |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
This version of Yahoo::Marketing is intended to be used with V7 of Yahoo's Marketing API. If you need to access both V4 and V6 simultaneously, you'll need to install 2 versions of Yahoo::Marketing. In order to have 2 versions of the same perl module installed, you'll need to put one in a non-standard location, for example ~/perl/. See perldoc CPAN for more information. |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
=head1 OVERVIEW |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
Yahoo's Marketing API allows you to manage your search marketing account in an automated fashion rather than manually. The API is exposed as a standard SOAP service that you can make calls to. This set of modules is designed to make using the SOAP service easier than using SOAP::Lite (for example) directly. There are 2 main types of modules available. The service modules (CampaignService, AdGroupService, BidInformationService, etc) are used to make the actual calls to each of the SOAP services in the API. The other type of module provided are the complex type modules, each of which represents one of the complex types defined in one of the WSDLs of the SOAP service. Examples include Campaign, AdGroup, Ad, PendingAd, CreditCardInfo, etc. |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
Yahoo::Marketing will call LocationService for you, and cache the results. This should be completely transparent. See the documtation for cache, cache_expire_time, purge_cache and clear_cache in Yahoo::Marketing::Service for more details. |
79
|
|
|
|
|
|
|
|
80
|
|
|
|
|
|
|
The calls you can make to the various services are documented on YSM's Technology Solutions Portal. See |
81
|
|
|
|
|
|
|
|
82
|
|
|
|
|
|
|
L |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
Where the documentation indicates that a complex type must be passed in to a particular service call, you must pass in the appropriate |
85
|
|
|
|
|
|
|
Yahoo::Marketing::ComplexType object. For example, CampaignService->addCampaign requires that a Campaign be passed in: |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
use Yahoo::Marketing::Campaign; |
88
|
|
|
|
|
|
|
use Yahoo::Marketing::CampaignService; |
89
|
|
|
|
|
|
|
|
90
|
|
|
|
|
|
|
my $campaign = Yahoo::Marketing::Campaign->new |
91
|
|
|
|
|
|
|
->startDate( '2006-07-16T09:20:30-05:00' ) |
92
|
|
|
|
|
|
|
->endDate( '2007-07-16T09:20:30-05:00' ) |
93
|
|
|
|
|
|
|
->name( 'test campaign' ) |
94
|
|
|
|
|
|
|
->status( 'On' ) |
95
|
|
|
|
|
|
|
->accountID( 123456789 ) |
96
|
|
|
|
|
|
|
; |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
my $campaign_service = Yahoo::Marketing::CampaignService->new; |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
my $campaign_response = $campaign_service->addCampaign( campaign => $campaign ); |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
my $added_campaign = $campaign_response->campaign; |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
Note that Yahoo::Marketing is smart enough to upgrade status from a simple string to the CampaignStatus simpleType for you. All simpleTypes referenced in the WSDLs are automatically handled for you - just pass in an appropriate string, and let Yahoo::Marketing do the rest. |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
When a method expects that multiple values will be set for a parameter, you must pass an anonymous array. An example would be AdGroupService->deleteAdGroups: |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
my $ad_group_service = Yahoo::Marketing::AdGroupService->new; |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
$ad_group_service->deleteAdGroups( adGroupIDs => [ '9167298', '2932719', '1827349' ] ); # existing Ad Group IDs |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
If a call returns data, you will receive an array if you make the call in an array context: |
114
|
|
|
|
|
|
|
|
115
|
|
|
|
|
|
|
my @ad_groups = $ad_group_service->getAdGroups( |
116
|
|
|
|
|
|
|
adGroupIDs => [ '9167298', '2932719', '1827349'], |
117
|
|
|
|
|
|
|
); |
118
|
|
|
|
|
|
|
|
119
|
|
|
|
|
|
|
Or just the first (or only element, if only one returned object is expected) if you make the call in a scalar context: |
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
my $ad_group = $ad_group_service->getAdGroups( |
122
|
|
|
|
|
|
|
adGroupIDs => [ '9167298', '2932719', '1827349'], |
123
|
|
|
|
|
|
|
); |
124
|
|
|
|
|
|
|
# $ad_group is just the first ad group returned (likely Ad Group ID 9167298) |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
Suggestions for improving how multiple return values should be handled in a scalar context are welcome. |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
If a SOAP Fault is encountered (whenever a call fails), the Yahoo::Marketing service will croak with the fault by default. If you set the immortal option, Yahoo::Marketing will not die, $service->fault will be set to the SOAP fault. The "immortal mode" is similar to how SOAP::Lite behaves by default. |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
Note that all get/set methods (and many other methods) are "chainable". That is, they return $self when used to set, so you can chain them together. See examples of this above and below in this documentation. |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
=head1 EXPORT |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
No exported functions |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
=head1 METHODS |
138
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
There are no methods available in Yahoo::Marketing directly. All functionality is exposed by the various Service modules and complex types. |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
See perldoc Yahoo::Marketing::Service for service use |
142
|
|
|
|
|
|
|
|
143
|
|
|
|
|
|
|
And perldoc Yahoo::Marketing::ComplexTypes for Complex Type documentation |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
=head1 EXAMPLES |
146
|
|
|
|
|
|
|
|
147
|
|
|
|
|
|
|
=head2 Example Code |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
See t/example.t for an example that parallels the perl example code at |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
L |
152
|
|
|
|
|
|
|
|
153
|
|
|
|
|
|
|
and |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
L |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
=head2 Example 1 - creating a campaign |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
my $campaign_service = Yahoo::Marketing::CampaignService->new |
160
|
|
|
|
|
|
|
->parse_config( section => 'sandbox' ); |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
# Create a Campaign |
163
|
|
|
|
|
|
|
my $campaign_response = $campaign_service->addCampaign( campaign => |
164
|
|
|
|
|
|
|
Yahoo::Marketing::Campaign->new |
165
|
|
|
|
|
|
|
->name( 'MP3' ) |
166
|
|
|
|
|
|
|
->description( 'MP3 Player' ) |
167
|
|
|
|
|
|
|
->accountID( $campaign_service->account ) |
168
|
|
|
|
|
|
|
->status( 'On' ) |
169
|
|
|
|
|
|
|
->sponsoredSearchON( 'true' ) |
170
|
|
|
|
|
|
|
->advancedMatchON( 'true' ) |
171
|
|
|
|
|
|
|
->contentMatchON( 'true' ) |
172
|
|
|
|
|
|
|
->campaignOptimizationON( 'false' ) |
173
|
|
|
|
|
|
|
->startDate( '2006-06-07T19:32:37-05:00' ) |
174
|
|
|
|
|
|
|
->endDate( '2007-07-08T07:32:37-05:00' ) |
175
|
|
|
|
|
|
|
); |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
my $campaign = $campaign_response->campaign; |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
# $campaign now contains the newly created campaign. |
180
|
|
|
|
|
|
|
# $campaign->ID will be set to the ID assigned to the new campaign. |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
=head2 Example 2 - updating Ads |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
my $ad_service = Yahoo::Marketing::AdService->new |
185
|
|
|
|
|
|
|
->parse_config; |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
$ad_service->updateAds( ads => [ Yahoo::Marketing::Ad->new |
188
|
|
|
|
|
|
|
->ID( '12427153' ) # id of existing ad |
189
|
|
|
|
|
|
|
->name( 'better than the old name' ) |
190
|
|
|
|
|
|
|
->status( 'Off' ) |
191
|
|
|
|
|
|
|
, |
192
|
|
|
|
|
|
|
Yahoo::Marketing::Ad->new |
193
|
|
|
|
|
|
|
->ID( '32482170' ) # id of existing ad |
194
|
|
|
|
|
|
|
->displayUrl( 'http://new.display.url/' ) |
195
|
|
|
|
|
|
|
->url( 'http://new.url' ) |
196
|
|
|
|
|
|
|
->description( 'a fancy new description' ) |
197
|
|
|
|
|
|
|
, |
198
|
|
|
|
|
|
|
], # end of our array of ads |
199
|
|
|
|
|
|
|
updateAll => 'false', |
200
|
|
|
|
|
|
|
); |
201
|
|
|
|
|
|
|
|
202
|
|
|
|
|
|
|
# Note that we passed an anonymous array for the ads parameter. |
203
|
|
|
|
|
|
|
# Also note that only the fields that were being updated needed to be |
204
|
|
|
|
|
|
|
# set, in addition to the ID field. |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
=head2 Example 3 - getting forecast information |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
my $forecast_service = Yahoo::Marketing::ForecastService->new->parse_config; |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
my $forecast_request_data |
211
|
|
|
|
|
|
|
= Yahoo::Marketing::ForecastRequestData->new |
212
|
|
|
|
|
|
|
->accountID( $forecast_service->account ) # default_account from config file, set in parse_config call |
213
|
|
|
|
|
|
|
->contentMatchMaxBid( '0.88' ) |
214
|
|
|
|
|
|
|
->marketID( 'US' ) |
215
|
|
|
|
|
|
|
->matchTypes( [qw(advanced_match content_match sponsored_search )] ) |
216
|
|
|
|
|
|
|
->sponsoredSearchMaxBid( '0.99' ); |
217
|
|
|
|
|
|
|
|
218
|
|
|
|
|
|
|
my $result = $forecast_service->getForecastForKeyword( |
219
|
|
|
|
|
|
|
keyword => 'porsche', |
220
|
|
|
|
|
|
|
adGroupID => 116439261, # some existing Ad Group ID |
221
|
|
|
|
|
|
|
forecastRequestData => $forecast_request_data, |
222
|
|
|
|
|
|
|
); |
223
|
|
|
|
|
|
|
|
224
|
|
|
|
|
|
|
my $forecast_response_detail = $result->forecastResponseDetail; |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
print "Number of forecast impressions: " |
227
|
|
|
|
|
|
|
.$forecast_response_detail->impressions |
228
|
|
|
|
|
|
|
."\n" |
229
|
|
|
|
|
|
|
; |
230
|
|
|
|
|
|
|
print "Number of forecast average position: " |
231
|
|
|
|
|
|
|
.$forecast_response_detail->averagePosition |
232
|
|
|
|
|
|
|
."\n" |
233
|
|
|
|
|
|
|
; |
234
|
|
|
|
|
|
|
my $forecast_landscapes = $result->forecastLandscape; |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
foreach my $forecast ( @$forecast_landscapes ){ |
237
|
|
|
|
|
|
|
print "cost per click: " |
238
|
|
|
|
|
|
|
.$forecast->costPerClick |
239
|
|
|
|
|
|
|
."\n" |
240
|
|
|
|
|
|
|
; |
241
|
|
|
|
|
|
|
} |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
=head2 Example 4 - using BidInformationService |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
my $bid_info_service = Yahoo::Marketing::BidInformationService->new->parse_config; |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
my $bid_information = $bid_info_service->getBidsForBestRank( |
248
|
|
|
|
|
|
|
adGroupID => '90171822', # existing Ad Group ID |
249
|
|
|
|
|
|
|
keyword => 'porsche', |
250
|
|
|
|
|
|
|
); |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
print "Bid: " |
253
|
|
|
|
|
|
|
.$bid_information->bid |
254
|
|
|
|
|
|
|
."\n" |
255
|
|
|
|
|
|
|
; |
256
|
|
|
|
|
|
|
print "Cut Off Bid: " |
257
|
|
|
|
|
|
|
.$bid_information->cutOffBid |
258
|
|
|
|
|
|
|
."\n" |
259
|
|
|
|
|
|
|
; |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
=head2 Example 5 - clearing the location cache from the command line |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
The following code will clear the location cache from the command line on a *nix machine. |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
perl -MYahoo::Marketing::Service -e 'my $ysm_ws = Yahoo::Marketing::Service->new->clear_cache;' |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
On windows, using double quotes instead of single quotes should work. |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
=head2 Example Config File |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
Config files are expected to be in YAML format. See perldoc YAML. |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
default_account is optional. If present, it will be set when a config file |
274
|
|
|
|
|
|
|
is loaded B |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
--- |
277
|
|
|
|
|
|
|
default: |
278
|
|
|
|
|
|
|
default_account: 12345678 |
279
|
|
|
|
|
|
|
endpoint: https://endpoint.host/services |
280
|
|
|
|
|
|
|
vault_endpoint: https://vault.endpoint.host/services |
281
|
|
|
|
|
|
|
license: your-ews-license |
282
|
|
|
|
|
|
|
master_account: 98765432 |
283
|
|
|
|
|
|
|
password: secretpassword |
284
|
|
|
|
|
|
|
uri: http://marketing.ews.yahooapis.com/V7 |
285
|
|
|
|
|
|
|
username: defaultusername |
286
|
|
|
|
|
|
|
version: V7 |
287
|
|
|
|
|
|
|
sandbox: |
288
|
|
|
|
|
|
|
default_account: 21921327 |
289
|
|
|
|
|
|
|
endpoint: https://sandbox.marketing.ews.yahooapis.com/services |
290
|
|
|
|
|
|
|
vault_endpoint: https://sandboxvault.marketing.ews.yahooapis.com/services |
291
|
|
|
|
|
|
|
license: 90837ada-3b26-c2e5-6d59-61d7f2fb578e |
292
|
|
|
|
|
|
|
master_account: 21921326 |
293
|
|
|
|
|
|
|
password: mypassword |
294
|
|
|
|
|
|
|
uri: http://marketing.ews.yahooapis.com/V7 |
295
|
|
|
|
|
|
|
username: mytestusername |
296
|
|
|
|
|
|
|
version: V7 |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
=head1 DEBUGGING |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
If you'd like to see the SOAP requests and responses, or other debugging information available from SOAP::Lite, you can turn it on just as you would for SOAP::Lite. See perldoc SOAP::Trace. As an example, if you wanted to see all trace information available, you could add the following to whatever module or script you use Yahoo::Marketing in: |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
use SOAP::Lite +trace; |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
=head1 AUTHOR |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
Jeff Lavallee, C<< >> |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
=head1 BUGS |
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
Please report any bugs or feature requests to |
315
|
|
|
|
|
|
|
C, or through the web interface at |
316
|
|
|
|
|
|
|
L. |
317
|
|
|
|
|
|
|
I will be notified, and then you'll automatically be notified of progress on |
318
|
|
|
|
|
|
|
your bug as I make changes. |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
=head1 SUPPORT |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
You can find documentation for this module with the perldoc command. |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
perldoc Yahoo::Marketing |
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
You can also look for information at: |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
=over 4 |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
=item * AnnoCPAN: Annotated CPAN documentation |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
L |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
=item * CPAN Ratings |
335
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
L |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
=item * RT: CPAN's request tracker |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
L |
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
=item * Search CPAN |
343
|
|
|
|
|
|
|
|
344
|
|
|
|
|
|
|
L |
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
=back |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
=head1 ACKNOWLEDGEMENTS |
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
co-author Johnny Shen, C<< >> without whom this wouldn't have been possible. |
351
|
|
|
|
|
|
|
Also Gerard Paulke C<< >>. |
352
|
|
|
|
|
|
|
|
353
|
|
|
|
|
|
|
=head1 COPYRIGHT & LICENSE |
354
|
|
|
|
|
|
|
|
355
|
|
|
|
|
|
|
Copyright (c) 2009 Yahoo! Inc. All rights reserved. |
356
|
|
|
|
|
|
|
The copyrights to the contents of this file are licensed under the Perl Artistic License (ver. 15 Aug 1997) |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
=head1 TODO |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
The TODO list is empty - if you have suggestions, please file a wishlist entry in RT (link above) |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
=cut |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
sub new { |
365
|
0
|
|
|
0
|
0
|
|
my ( $class, %args ) = @_; |
366
|
0
|
0
|
|
|
|
|
croak "cannot instantiate @{[ __PACKAGE__ ]} directly" |
|
0
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
unless $class ne __PACKAGE__; |
368
|
|
|
|
|
|
|
|
369
|
0
|
|
|
|
|
|
my $self = bless %args, $class; |
370
|
0
|
|
|
|
|
|
return $self; |
371
|
|
|
|
|
|
|
} |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
1; # End of Yahoo::Marketing |
376
|
|
|
|
|
|
|
|