Group
Extension

WWW-Shopify/lib/WWW/Shopify/URLHandler.pm

#!/usr/bin/perl

use strict;
use warnings;

package WWW::Shopify::URLHandler;
use JSON qw(from_json to_json encode_json decode_json);
use Data::Dumper;
use Scalar::Util qw(weaken);
use DateTime;
use Encode;

sub new {
	my ($package, $parent, $headers) = @_;
	my $self = bless {_parent => $parent, _default_headers => ($headers || {})}, $package;
	weaken($self->{_parent});
	return $self;
}
sub ua { return $_[0]->parent->ua; }

sub default_header {
	my ($self, $key, $value) = @_;
	$self->{_default_headers}->{$key} = $value if int(@_) >= 3;
	return $self->{_default_headers}->{$key};
}

sub parent { $_[0]->{_parent} = $_[1] if defined $_[1]; return $_[0]->{_parent}; }

sub get_url {
	my ($self, $url, $parameters, $type) = @_;
	$type = "application/json" unless $type;
	my $uri = URI->new($url);
	my %filtered = ();
	if ($parameters->{fields} && ref($parameters->{fields}) && ref($parameters->{fields}) eq "ARRAY") {
		$parameters->{fields} = join(",", @{$parameters->{fields}});
	}
	for (keys(%$parameters)) {
		if ($parameters->{$_} && ref($parameters->{$_}) eq "DateTime") {
			$filtered{$_} = $parameters->{$_}->strftime('%Y-%m-%d %H:%M:%S%z')
		}
		elsif ($_ ne "parent") {
			$filtered{$_} = $parameters->{$_};
		}
	}
	$uri->query_form(\%filtered);
	my $request = HTTP::Request->new("GET", $uri);
	$request->header("Accept" => $type);
	$request->header("Accept-Encoding" => "gzip") if !$ENV{"SHOPIFY_LOG"} || $ENV{"SHOPIFY_LOG"} != 2;
	$request->header($_ => $self->{_default_headers}->{$_}) for (keys(%{$self->{_default_headers}}));
	return $self->handle_response($self->request($request));
	
}

sub request {
	my ($self, $request) = @_;
	return $self->ua->request($request);
}

sub handle_response {
	my ($self, $response) = @_;
	if (!$response->is_success) {
		die WWW::Shopify::Exception::CallLimit->new($response) if $response->code() == 429;
		die WWW::Shopify::Exception::InvalidKey->new($response) if $response->code() == 401;
		die WWW::Shopify::Exception::NotFound->new($response) if $response->code() == 404;
		die WWW::Shopify::Exception->new($response);
	}
	my $limit = $response->header('x-shopify-shop-api-call-limit');
	if ($limit) {
		die new WWW::Shopify::Exception("Unrecognized limit.") unless $limit =~ m/(\d+)\/(\d+)/;
		$self->parent->api_calls($1);
		$self->parent->max_api_calls($2);
	}
	my $content = $response->decoded_content;
	# From JSON because decodec content is already a perl internal string.
	# Sigh. No. It's not. As per https://rt.cpan.org/Public/Bug/Display.html?id=82963; decoded_content doesn't actually do anything.
	$content = decode("UTF-8", $content) if ($response->header('Content-Type') =~ m/application\/json/);
	my $decoded = length($content) >= 2 && (!$response->header('Content-Type') || $response->header('Content-Type') =~ /json/) ? from_json($content) : $content;
	return ($decoded, $response);
}

use URI::Escape;
use JSON qw(encode_json);
use Scalar::Util qw(reftype);


sub flatten_object {
	my ($prefix, $object) = @_;
	return map {  
		my $key = $_;
		my @items;
		@items = $object->{$key}->iso8601 if (ref($object) || "") eq "DateTime";
		@items = flatten_object($prefix . $key, $object->{$key}) if reftype($object->{$key}) && reftype($object->{$key}) eq "HASH";
		@items = (map { flatten_object($prefix . "[" . $key . "][]", $_) } @{$object->{$key}}) if reftype($object->{$key}) && reftype($object->{$key}) eq "ARRAY";
		@items = ($prefix . "[" . $key . "]=" . uri_escape_utf8(defined $object->{$key} ? $object->{$key} : '')) if !reftype($object->{$key});
		
		@items;
	} grep { $_ ne "associated_parent" && $_ ne "associated_sa" } keys(%$object);
}

sub use_url{
	my ($self, $method, $url, $hash, $needs_login, $type, $accept) = @_;
	$type = "application/json" unless $type;
	$accept = "application/json" unless $accept;
	my $request = HTTP::Request->new($method, $url);
	$request->header("Accept" => $accept, "Content-Type" => $type);
	$request->header("Accept-Encoding" => "gzip") if !$ENV{"SHOPIFY_LOG"} || $ENV{"SHOPIFY_LOG"} != 2;
	$request->header($_ => $self->{_default_headers}->{$_}) for (keys(%{$self->{_default_headers}}));
	if ($type =~ m/json/) {
		$request->content($hash ? encode_json($hash) : undef);
	} else {
		if ($hash) {
			$request->content(join("&", map { 
				if (reftype($hash->{$_}) && reftype($hash->{$_}) eq "HASH") {
					flatten_object($_, $hash->{$_});
				} else {
					my $name = uri_escape_utf8($_); 
					map { $name . "=" . uri_escape_utf8($_) } ($hash->{$_} && ref($hash->{$_}) eq "ARRAY" ? @{$hash->{$_}} : ($hash->{$_})) 
				}
			} keys(%$hash) ));
		}
	}
	my $response = $self->request($request);
	if ($type =~ m/json/) {
		return $self->handle_response($response);
	} else {
		if ($response->is_redirect) {
			
		}
		return (undef, $response);
	}
}

sub upload_url {
	my ($self, $method, $url, $name, $filename, $mime, $contents) = @_;
	my $request = HTTP::Request->new($method, $url);
	my $boundary = '----WebKitFormBoundaryePkpFF7tjBAqx29L';
	$request->header('Content-Type' => 'multipart/form-data; boundary=' . $boundary);
	$request->header('Accept' => 'Accept:application/json, text/javascript, */*; q=0.01');
	$request->content("--" . $boundary . "\r\n" .
	"Content-Disposition: form-data; name=\"$name\"; filename=\"$filename\"\r\n" .
	"Content-Type: $mime\r\n\r\n$contents\r\n--$boundary--");
	return $self->ua->request($request);
}

sub put_url { return shift->use_url("PUT", @_); }
sub post_url { return shift->use_url("POST", @_); }
sub delete_url { return shift->use_url("DELETE", @_); }

1;


Powered by Groonga
Maintained by Kenichi Ishigaki <ishigaki@cpan.org>. If you find anything, submit it on GitHub.