our
$VERSION
=
'1.6.2'
;
sub
new
{
my
(
$class
,
$exact_target
,
%args
) =
@_
;
confess
'Pass an Email::ExactTarget object to create an Email::ExactTarget::SubscriberOperations object'
unless
defined
(
$exact_target
) &&
$exact_target
->isa(
'Email::ExactTarget'
);
my
$self
=
bless
(
{
'exact_target'
=>
$exact_target
,
},
$class
,
);
return
$self
;
}
sub
exact_target
{
my
(
$self
) =
@_
;
return
$self
->{
'exact_target'
};
}
sub
create
{
my
(
$self
,
$subscribers
) =
@_
;
return
$self
->_update_create(
'subscribers'
=>
$subscribers
,
'soap_action'
=>
'Create'
,
'soap_method'
=>
'CreateRequest'
,
'options'
=>
undef
,
);
}
sub
update_or_create
{
my
(
$self
,
$subscribers
) =
@_
;
return
$self
->_update_create(
'subscribers'
=>
$subscribers
,
'soap_action'
=>
'Create'
,
'soap_method'
=>
'CreateRequest'
,
'options'
=> SOAP::Data->name(
'Options'
=> \SOAP::Data->value(
SOAP::Data->name(
'SaveOptions'
=> \SOAP::Data->value(
SOAP::Data->name(
'SaveOption'
=> \SOAP::Data->value(
SOAP::Data->name(
'PropertyName'
=>
'*'
,
),
SOAP::Data->name(
'SaveAction'
=>
'UpdateAdd'
,
),
),
),
),
),
),
),
);
}
sub
update
{
my
(
$self
,
$subscribers
) =
@_
;
return
$self
->_update_create(
'subscribers'
=>
$subscribers
,
'soap_action'
=>
'Update'
,
'soap_method'
=>
'UpdateRequest'
,
'options'
=> SOAP::Data->name(
'Options'
=> \SOAP::Data->value(),
),
);
}
sub
retrieve
{
my
(
$self
,
%args
) =
@_
;
my
$email
=
delete
(
$args
{
'email'
} );
confess
'Emails identifying the subscribers to retrieve were not passed.'
if
!
defined
(
$email
);
confess
"The 'email' parameter must be an arrayref"
if
!Data::Validate::Type::is_arrayref(
$email
);
confess
'Emails identifying the subscribers to retrieve were not passed.'
if
scalar
(
@$email
) == 0;
$email
= [
$email
->[0],
$email
->[0] ]
if
scalar
(
@$email
) == 1;
my
$exact_target
=
$self
->exact_target() || confess
'Email::ExactTarget object is not defined'
;
my
$verbose
=
$exact_target
->verbose();
my
$soap_args
=
[
SOAP::Data->name(
RetrieveRequest
=> \SOAP::Data->value(
SOAP::Data->name(
ObjectType
=>
'Subscriber'
,
),
SOAP::Data->name(
Properties
=> (
'ID'
,
'EmailTypePreference'
,
'EmailAddress'
),
),
SOAP::Data->name(
'Filter'
=> \SOAP::Data->value(
SOAP::Data->name(
Property
=>
'EmailAddress'
,
),
SOAP::Data->name(
SimpleOperator
=>
'IN'
,
),
SOAP::Data->name(
Value
=>
@$email
,
),
),
)->attr( {
'xsi:type'
=>
'SimpleFilterPart'
} ),
),
),
];
my
$soap_response
=
$exact_target
->soap_call(
'action'
=>
'Retrieve'
,
'method'
=>
'RetrieveRequestMsg'
,
'arguments'
=>
$soap_args
,
);
my
(
$soap_success
,
$soap_request_id
,
@soap_object
) =
$soap_response
->paramsall();
confess Dumper(
$soap_response
->fault() )
if
defined
(
$soap_response
->fault() );
confess
"The SOAP reply status is '$soap_success', not 'OK'"
unless
defined
(
$soap_success
) && (
$soap_success
eq
'OK'
);
my
@subscriber
= ();
foreach
my
$soap_object
(
@soap_object
)
{
confess
"No attributes found."
unless
defined
(
$soap_object
->{
'Attributes'
} );
confess
'No subscriber ID found.'
unless
defined
(
$soap_object
->{
'ID'
} );
my
$subscriber
= Email::ExactTarget::Subscriber->new();
$subscriber
->id(
$soap_object
->{
'ID'
} );
$subscriber
->set_properties(
{
map
{
$_
=>
$soap_object
->{
$_
} }
qw( EmailTypePreference EmailAddress )
},
'is_live'
=> 1,
);
$subscriber
->set_attributes(
{
map
{
$_
->{
'Name'
} =>
$_
->{
'Value'
}
} @{
$soap_object
->{
'Attributes'
} }
},
'is_live'
=> 1,
);
push
(
@subscriber
,
$subscriber
);
}
return
\
@subscriber
;
}
sub
pull_list_subscriptions
{
my
(
$self
,
$subscribers
,
%args
) =
@_
;
my
$list_ids
=
delete
(
$args
{
'list_ids'
} );
croak
'Unrecognized arguments: '
.
join
(
', '
,
keys
%args
)
if
scalar
(
keys
%args
) != 0;
confess
'An arrayref of subscribers to pull list subscriptions for is required.'
if
!Data::Validate::Type::is_arrayref(
$subscribers
);
confess
'A non-empty arrayref of subscribers to pull list subscriptions for is required.'
if
scalar
(
@$subscribers
) == 0;
if
(
defined
(
$list_ids
) )
{
confess
'When defined, the argument "list_ids" must be an arrayref'
if
!Data::Validate::Type::is_arrayref(
$list_ids
);
confess
'When defined, the argument "list_ids" must contain at least one list ID to restrict the query to'
if
scalar
(
@$list_ids
) == 0;
}
my
$exact_target
=
$self
->exact_target() || confess
'Email::ExactTarget object is not defined'
;
my
$verbose
=
$exact_target
->verbose();
my
@emails
=
map
{
$_
->get_attribute(
'Email Address'
) }
@$subscribers
;
my
$email_filter
= \SOAP::Data->value(
SOAP::Data->name(
Property
=>
'SubscriberKey'
,
),
SOAP::Data->name(
SimpleOperator
=>
scalar
(
@emails
) == 1
?
'equals'
:
'IN'
,
),
SOAP::Data->name(
Value
=>
scalar
(
@emails
) == 1
?
$emails
[0]
:
@emails
,
),
);
my
$list_id_filter
;
if
(
defined
(
$list_ids
) )
{
$list_id_filter
= \SOAP::Data->value(
SOAP::Data->name(
Property
=>
'ListID'
,
),
SOAP::Data->name(
SimpleOperator
=>
scalar
(
@$list_ids
) == 1
?
'equals'
:
'IN'
,
),
SOAP::Data->name(
Value
=>
scalar
(
@$list_ids
) == 1
?
$list_ids
->[0]
:
@$list_ids
,
),
);
}
my
$filter
;
if
(
defined
(
$list_id_filter
) )
{
$filter
= SOAP::Data->name(
'Filter'
=> \SOAP::Data->value(
SOAP::Data->name(
'LeftOperand'
=>
$email_filter
,
)->attr( {
'xsi:type'
=>
'SimpleFilterPart'
} ),
SOAP::Data->name(
LogicalOperator
=>
'AND'
,
),
SOAP::Data->name(
'RightOperand'
=>
$list_id_filter
,
)->attr( {
'xsi:type'
=>
'SimpleFilterPart'
} ),
),
)->attr( {
'xsi:type'
=>
'ComplexFilterPart'
} );
}
else
{
$filter
= SOAP::Data->name(
'Filter'
=>
$email_filter
,
)->attr( {
'xsi:type'
=>
'SimpleFilterPart'
} );
}
my
$soap_args
=
[
SOAP::Data->name(
RetrieveRequest
=> \SOAP::Data->value(
SOAP::Data->name(
ObjectType
=>
'ListSubscriber'
,
),
SOAP::Data->name(
Properties
=>
qw( ListID SubscriberKey Status )
,
),
$filter
,
),
),
];
my
$soap_response
=
$exact_target
->soap_call(
'action'
=>
'Retrieve'
,
'method'
=>
'RetrieveRequestMsg'
,
'arguments'
=>
$soap_args
,
);
my
(
$soap_success
,
$soap_request_id
,
@soap_params_out
) =
$soap_response
->paramsall();
confess Dumper(
$soap_response
->fault() )
if
defined
(
$soap_response
->fault() );
confess
"The SOAP reply status is '$soap_success', not 'OK'"
unless
defined
(
$soap_success
) && (
$soap_success
eq
'OK'
);
my
$subscribers_by_email
=
{
map
{
$_
->get_attribute(
'Email Address'
) =>
$_
}
@$subscribers
};
foreach
my
$soap_param_out
(
@soap_params_out
)
{
$subscribers_by_email
->{
$soap_param_out
->{
'SubscriberKey'
} }->set_lists_status(
{
$soap_param_out
->{
'ListID'
} =>
$soap_param_out
->{
'Status'
},
},
'is_live'
=> 1,
);
}
return
1;
}
sub
delete_permanently
{
my
(
$self
,
$subscribers
) =
@_
;
confess
'The "subscribers" parameter need to be set.'
if
!
defined
(
$subscribers
);
confess
'The "subscribers" parameter must be an arrayref'
if
!Data::Validate::Type::is_arrayref(
$subscribers
);
confess
'The "subscribers" parameter must have at least one subscriber in the arrayref'
if
scalar
(
@$subscribers
) == 0;
my
$exact_target
=
$self
->exact_target() || confess
'Email::ExactTarget object is not defined'
;
my
$verbose
=
$exact_target
->verbose();
my
@soap_data
= ();
foreach
my
$subscriber
(
@$subscribers
)
{
my
@object
=
(
SOAP::Data->name(
'EmailAddress'
=>
$subscriber
->get_attribute(
'Email Address'
,
'is_live'
=> 1 ),
),
SOAP::Data->name(
'ID'
=>
$subscriber
->id(),
),
);
push
(
@soap_data
,
SOAP::Data->name(
'Objects'
=> \SOAP::Data->value(
@object
),
)->attr( {
'xsi:type'
=>
'Subscriber'
} ),
)
}
my
$soap_response
=
$exact_target
->soap_call(
'action'
=>
'Delete'
,
'method'
=>
'DeleteRequest'
,
'arguments'
=>
[
SOAP::Data->value(
@soap_data
)
],
);
my
@soap_params_out
=
$soap_response
->paramsall();
my
$soap_success
=
pop
(
@soap_params_out
);
my
$soap_request_id
=
pop
(
@soap_params_out
);
confess Dumper(
$soap_response
->fault() )
if
defined
(
$soap_response
->fault() );
confess
"The SOAP reply status is '$soap_success', not 'OK'"
unless
defined
(
$soap_success
) && (
$soap_success
eq
'OK'
);
my
$deletion_results
= {};
foreach
my
$param_out
(
@soap_params_out
)
{
$deletion_results
->{
$param_out
->{
'OrdinalID'
} } =
{
'StatusCode'
=>
$param_out
->{
'StatusCode'
},
'StatusMessage'
=>
$param_out
->{
'StatusMessage'
},
};
}
my
$errors_found
= 0;
for
(
my
$count
= 0;
$count
<
scalar
(
@$subscribers
);
$count
++ )
{
my
$subscriber
=
$subscribers
->[
$count
];
my
$deletion_result
=
$deletion_results
->{
$count
};
if
(
$deletion_result
->{
'StatusCode'
} ne
'OK'
)
{
$errors_found
= 1;
$subscriber
->add_error(
$deletion_result
->{
'StatusMessage'
} );
next
;
}
unless
(
$subscriber
->flag_as_deleted_permanently() )
{
$errors_found
= 1;
$subscriber
->add_error(
"Deleted in ExactTarget's database, but failed to flag locally the object as deleted."
);
next
;
}
}
return
!
$errors_found
;
}
sub
_update_create
{
my
(
$self
,
%args
) =
@_
;
my
$subscribers
=
delete
(
$args
{
'subscribers'
} );
confess
'The "subscribers" parameter need to be set.'
if
!
defined
(
$subscribers
);
confess
'The "subscribers" parameter must be an arrayref'
if
!Data::Validate::Type::is_arrayref(
$subscribers
);
confess
'The "subscribers" parameter must have at least one subscriber in the arrayref'
if
scalar
(
@$subscribers
) == 0;
my
$exact_target
=
$self
->exact_target() || confess
'Email::ExactTarget object is not defined'
;
my
$verbose
=
$exact_target
->verbose();
foreach
my
$subscriber
(
@$subscribers
)
{
next
unless
$subscriber
->is_deleted_permanently();
confess
'Cannot perform operations on an object flagged as permanently deleted'
. (
$verbose
?
': '
. Dumper(
$subscriber
) :
'.'
);
}
my
@soap_data
= ();
if
(
defined
(
$args
{
'options'
} ) )
{
push
(
@soap_data
,
$args
{
'options'
} );
}
foreach
my
$subscriber
(
@$subscribers
)
{
my
@object
= ();
if
(
$args
{
'soap_action'
} eq
'Create'
)
{
push
(
@object
,
SOAP::Data->name(
'EmailAddress'
=>
$subscriber
->get_attribute(
'Email Address'
,
'is_live'
=> 0 ),
),
);
}
else
{
push
(
@object
,
SOAP::Data->name(
'EmailAddress'
=>
$subscriber
->get_attribute(
'Email Address'
,
'is_live'
=> 1 ),
),
SOAP::Data->name(
'ID'
=>
$subscriber
->id(),
),
);
}
my
$properties
=
$subscriber
->get_properties(
is_live
=> 0 );
foreach
my
$name
(
keys
%$properties
)
{
push
(
@object
,
SOAP::Data->name(
$name
=>
$properties
->{
$name
}
)
);
}
push
(
@object
,
$self
->_soap_format_attributes(
$subscriber
->get_attributes(
'is_live'
=> 0 ) ),
$self
->_soap_format_lists(
'current'
=>
$subscriber
->get_lists_status(
'is_live'
=> 1 ),
'staged'
=>
$subscriber
->get_lists_status(
'is_live'
=> 0 ),
),
);
push
(
@soap_data
,
SOAP::Data->name(
'Objects'
=> \SOAP::Data->value(
@object
),
)->attr( {
'xsi:type'
=>
'Subscriber'
} ),
);
}
my
$soap_response
=
$exact_target
->soap_call(
'action'
=>
$args
{
'soap_action'
},
'method'
=>
$args
{
'soap_method'
},
'arguments'
=>
[
SOAP::Data->value(
@soap_data
)
],
);
my
@soap_params_out
=
$soap_response
->paramsall();
my
$soap_success
=
pop
(
@soap_params_out
);
my
$soap_request_id
=
pop
(
@soap_params_out
);
confess Dumper(
$soap_response
->fault() )
if
defined
(
$soap_response
->fault() );
my
$batch_success
=
defined
(
$soap_success
) && (
$soap_success
eq
'OK'
)
? 1
: 0;
my
%update_details
= ();
foreach
my
$param_out
(
@soap_params_out
)
{
$update_details
{
$param_out
->{
'Object'
}->{
'EmailAddress'
} } =
$param_out
;
}
foreach
my
$subscriber
(
@$subscribers
)
{
my
$email
=
$args
{
'soap_action'
} eq
'Create'
?
$subscriber
->get_attribute(
'Email Address'
,
is_live
=> 0 )
:
$subscriber
->get_attribute(
'Email Address'
);
my
$update_details
=
$update_details
{
$email
};
if
(
$update_details
->{
'StatusCode'
} ne
'OK'
)
{
$subscriber
->add_error(
$update_details
->{
'StatusMessage'
} );
next
;
}
if
(
defined
(
$update_details
->{
'Object'
}->{
'ID'
} ) )
{
if
(
defined
(
$subscriber
->id() ) )
{
confess
'The subscriber object ID was '
.
$subscriber
->id() .
' locally, '
.
'but ExactTarget now claims it is '
.
$update_details
->{
'Object'
}->{
'ID'
}
if
$subscriber
->id() !=
$update_details
->{
'Object'
}->{
'ID'
};
}
else
{
$subscriber
->id(
$update_details
->{
'Object'
}->{
'ID'
} );
}
}
if
(
defined
(
$update_details
->{
'Object'
}->{
'Attributes'
} ) )
{
my
$attributes
= Data::Validate::Type::is_arrayref(
$update_details
->{
'Object'
}->{
'Attributes'
} )
?
$update_details
->{
'Object'
}->{
'Attributes'
}
: [
$update_details
->{
'Object'
}->{
'Attributes'
} ];
$subscriber
->apply_staged_attributes(
[
map
{
$_
->{
'Name'
} }
@$attributes
]
);
}
if
(
defined
(
$update_details
->{
'Object'
}->{
'Lists'
} ) )
{
my
$lists
= Data::Validate::Type::is_arrayref(
$update_details
->{
'Object'
}->{
'Lists'
} )
?
$update_details
->{
'Object'
}->{
'Lists'
}
: [
$update_details
->{
'Object'
}->{
'Lists'
} ];
$subscriber
->apply_staged_lists_status(
{
map
{
$_
->{
'ID'
} =>
$_
->{
'Status'
} }
@$lists
}
);
}
my
$attributes_remaining
=
$subscriber
->get_attributes(
'is_live'
=> 0 );
if
(
scalar
(
keys
%$attributes_remaining
) != 0 )
{
$subscriber
->add_error(
'The following staged changes were not applied: '
.
join
(
', '
,
keys
%$attributes_remaining
) .
'.'
);
}
my
$lists_remaining
=
$subscriber
->get_lists_status(
'is_live'
=> 0 );
if
(
scalar
(
keys
%$lists_remaining
) != 0 )
{
$subscriber
->add_error(
"The following staged lists status changes were not applied:\n"
.
join
(
"\n"
,
map
{
" $_ => $lists_remaining->{$_}"
}
keys
%$lists_remaining
)
);
}
}
return
$batch_success
;
}
sub
_soap_format_lists
{
my
(
$self
,
%args
) =
@_
;
my
$status_current
=
$args
{
'current'
};
my
$status_staged
=
$args
{
'staged'
};
confess
'Current lists status not defined'
unless
defined
(
$status_current
);
confess
'Staged lists status not defined'
unless
defined
(
$status_staged
);
my
@lists
= ();
foreach
my
$list_id
(
keys
%$status_staged
)
{
push
(
@lists
,
SOAP::Data->name(
'Lists'
=> \SOAP::Data->value(
SOAP::Data->name(
'ID'
=>
$list_id
,
),
SOAP::Data->name(
'Status'
=>
$status_staged
->{
$list_id
},
),
SOAP::Data->name(
'Action'
=>
defined
(
$status_current
->{
$list_id
} )
?
'update'
:
'create'
,
),
),
),
);
}
return
@lists
;
}
sub
_soap_format_attributes
{
my
(
$self
,
$attributes
) =
@_
;
confess
'Attributes not defined'
unless
defined
(
$attributes
);
if
(
$self
->exact_target()->unaccent() )
{
foreach
my
$attribute
(
keys
%$attributes
)
{
next
if
!
defined
(
$attributes
->{
$attribute
} );
$attributes
->{
$attribute
} = Text::Unaccent::unac_string(
'latin1'
,
$attributes
->{
$attribute
},
);
}
}
my
@attribute
= ();
foreach
my
$name
(
keys
%{
$attributes
} )
{
push
(
@attribute
,
SOAP::Data->name(
'Attributes'
=> \SOAP::Data->value(
SOAP::Data->name(
'Name'
=>
$name
,
),
SOAP::Data->name(
'Value'
=>
$attributes
->{
$name
},
),
),
),
);
}
return
@attribute
;
}
1;