WWW-SFDC

 view release on metacpan or  search on metacpan

lib/WWW/SFDC.pm  view on Meta::CPAN

  # static C<use> statements.
  for my $module (qw'
    Apex Constants Metadata Partner Tooling
  '){
    has $module,
      is => 'ro',
      lazy => 1,
      default => sub {
        my $self = shift;
        require "WWW/SFDC/$module.pm"; ## no critic
        "WWW::SFDC::$module"->new(session => $self);
      };
  }
}

method _login {

  INFO "Logging in...\t";

  my $request = SOAP::Lite
    ->proxy(
      $self->url()."/services/Soap/u/".$self->apiVersion()
    )
    ->readable(1)
    ->ns("urn:partner.soap.sforce.com","urn")
    ->call(
      'login',
      SOAP::Data->name("username")->value($self->username),
      SOAP::Data->name("password")->value($self->password)
    );

  TRACE "Request: " . Dumper $request;
  WWW::SFDC::CallException->throw(
    message => "Login failed: " . $request->faultstring,
    request => $request
  ) if $request->fault;

  return $request->result();
}


method _doCall ($attempts, $URL, $NS, $method, @params) {

  # This is the utility method behind call(). It orchestrates the actual
  # SOAP::Lite call with the correct parameters and detects connection vs
  # SOAP errors.

  INFO "Starting $method request";
  if (
    my $result = eval {
      # SOAP::Lite dies when there's a connection error; if there's an API
      # error it lives but $result->fault is set. This allows us to detect
      # network errors and retry.
      SOAP::Lite
        ->proxy($URL)
        ->readable(1)
        ->default_ns($NS)
        ->call(
          $method,
          @params,
          SOAP::Header->name("SessionHeader" => {
            "sessionId" => $self->loginResult->{"sessionId"}
          })->uri($NS)
        );
    }
  ) {
    return $result;

  } elsif ($attempts) {
    # Looping by recursion makes it easier to write this bit.
    INFO "$method failed: $@";
    INFO "Retrying ($attempts attempts remaining)";
    return $self->_doCall($attempts-1, $URL, $NS, $method, @params);

  } else {
    WWW::SFDC::CallException->throw(
      message => "$method failed: " . $@
    );
  }
}

method call (@_) {
  my $result;

  until (
    # CallResult is falsy when the call failed
    $result = $self->_doCall($self->attempts, @_)
  ) {
    TRACE "Operation request " => Dumper $result;

    if ($result->faultstring =~ /INVALID_SESSION_ID/) {
      $self->loginResult($self->_login());
    } else {
      WWW::SFDC::CallException->throw(
        message => "$_[2] failed: " . $result->faultstring,
        request => $result
      );
    }
  }

  return WWW::SFDC::CallResult->new(request => $result);
};


method isSandbox {
  return $self->loginResult->{sandbox} eq  "true";
}

1;


package WWW::SFDC::CallException;
# CallException allows sensible handling of API errors;
# L<WWW::SFDC::Role::Exception> provides overloaded stringification so that
# when you C<die $exception;> there's a sensible error message, but you can
# still examine the request and response in a consumer library.

use strict;
use warnings;
use Moo;
with 'WWW::SFDC::Role::Exception';



( run in 0.643 second using v1.01-cache-2.11-cpan-39bf76dae61 )