Skip to content

Commit 9a2e2ef

Browse files
committed
IT (ALMOST) WORKS!
1 parent 4ac6d6b commit 9a2e2ef

25 files changed

+485
-70
lines changed

.env

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# In all environments, the following files are loaded if they exist,
2+
# the latter taking precedence over the former:
3+
#
4+
# * .env contains default values for the environment variables needed by the app
5+
# * .env.local uncommitted file with local overrides
6+
# * .env.$APP_ENV committed environment-specific defaults
7+
# * .env.$APP_ENV.local uncommitted environment-specific overrides
8+
#
9+
# Real environment variables win over .env files.
10+
#
11+
# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES.
12+
# https://symfony.com/doc/current/configuration/secrets.html
13+
#
14+
# Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2).
15+
# https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration
16+
17+
###> symfony/framework-bundle ###
18+
APP_ENV=dev
19+
APP_SECRET=bbcdf66688281e1a04ffe7399c404c85
20+
###< symfony/framework-bundle ###

.env.test

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# define your env variables for the test env here
2+
KERNEL_CLASS='TurboLabIt\ShopifySdk\tests\Kernel'
3+
APP_SECRET='$ecretf0rt3st'
4+
SYMFONY_DEPRECATIONS_HELPER=999999
5+
PANTHER_APP_ENV=panther
6+
PANTHER_ERROR_SCREENSHOT_DIR=./var/error-screenshots

composer.json

+4-3
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,16 @@
1919
],
2020
"require": {
2121
"php": "^8.2",
22-
"sammyjo20/saloon": "^2.0"
22+
"sammyjo20/saloon": "^2.0",
23+
"symfony/twig-pack": "^1.0"
2324
},
2425
"require-dev": {
25-
"symfony/framework-bundle": "^6.3",
2626
"symfony/yaml": "^6.3",
2727
"symfony/dotenv": "^6.3",
2828
"symfony/config": "^6.3",
2929
"symfony/dependency-injection": "^6.3",
30-
"symfony/http-kernel": "^6.3"
30+
"symfony/http-kernel": "^6.3",
31+
"symfony/test-pack": "^1.1"
3132
},
3233
"config": {
3334
"allow-plugins": {

config/bundles.php

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
return [
4+
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
5+
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
6+
Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
7+
TurboLabIt\ShopifySdk\ShopifySdkBundle::class => ['all' => true],
8+
];

config/packages/framework.yaml

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# see https://symfony.com/doc/current/reference/configuration/framework.html
2+
framework:
3+
secret: '%env(APP_SECRET)%'
4+
http_method_override: false
5+
6+
when@test:
7+
framework:
8+
test: true
9+
session:
10+
storage_factory_id: session.storage.factory.mock_file

config/packages/twig.yaml

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
twig:
2+
default_path: '%kernel.project_dir%/templates'
3+
4+
when@test:
5+
twig:
6+
strict_variables: true

config/services.yaml

+19-11
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,24 @@ parameters:
33
default_results_per_page: 250
44

55
services:
6-
TurboLabIt\ShopifySdk\Service\ShopifyAdminConnector:
7-
autowire: true
8-
public: true
9-
arguments:
10-
$arrConfig:
11-
shop_name: '%env(APP_SHOPIFY_SHOP_NAME)%'
12-
access_token: '%env(APP_SHOPIFY_ACCESS_TOKEN)%'
13-
api_version: '%env(default:default_shopify_api_version:APP_SHOPIFY_API_VERSION)%'
14-
results_per_page: '%env(default:default_results_per_page:APP_SHOPIFY_API_RESULTS_PER_PAGE)%'
6+
TurboLabIt\ShopifySdk\Connector\ShopifyAdminConnector:
7+
autowire: true
8+
public: true
9+
arguments:
10+
$arrConfig:
11+
shop_name: '%env(APP_SHOPIFY_SHOP_NAME)%'
12+
access_token: '%env(APP_SHOPIFY_ACCESS_TOKEN)%'
13+
api_version: '%env(default:default_shopify_api_version:APP_SHOPIFY_API_VERSION)%'
14+
results_per_page: '%env(default:default_results_per_page:APP_SHOPIFY_API_RESULTS_PER_PAGE)%'
1515

1616
shopifysdk.admin_connector:
17-
alias: TurboLabIt\ShopifySdk\Service\ShopifyAdminConnector
18-
public: true
17+
alias: TurboLabIt\ShopifySdk\Connector\ShopifyAdminConnector
18+
public: true
19+
20+
TurboLabIt\ShopifySdk\Request\ShopifyOrderListRequest:
21+
autowire: true
22+
public: true
23+
24+
shopifysdk.order_list_request:
25+
alias: TurboLabIt\ShopifySdk\Request\ShopifyOrderListRequest
26+
public: true

phpunit.xml.dist

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<!-- https://phpunit.readthedocs.io/en/latest/configuration.html -->
4+
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
6+
backupGlobals="false"
7+
colors="true"
8+
bootstrap="tests/bootstrap.php"
9+
convertDeprecationsToExceptions="false"
10+
>
11+
<php>
12+
<ini name="display_errors" value="1" />
13+
<ini name="error_reporting" value="-1" />
14+
<server name="APP_ENV" value="test" force="true" />
15+
<server name="SHELL_VERBOSITY" value="-1" />
16+
<server name="SYMFONY_PHPUNIT_REMOVE" value="" />
17+
<server name="SYMFONY_PHPUNIT_VERSION" value="9.5" />
18+
</php>
19+
20+
<testsuites>
21+
<testsuite name="Project Test Suite">
22+
<directory>tests</directory>
23+
</testsuite>
24+
</testsuites>
25+
26+
<coverage processUncoveredFiles="true">
27+
<include>
28+
<directory suffix=".php">src</directory>
29+
</include>
30+
</coverage>
31+
32+
<listeners>
33+
<listener class="Symfony\Bridge\PhpUnit\SymfonyTestsListener" />
34+
</listeners>
35+
36+
<!-- Run `composer require symfony/panther` before enabling this extension -->
37+
<!--
38+
<extensions>
39+
<extension class="Symfony\Component\Panther\ServerExtension" />
40+
</extensions>
41+
-->
42+
</phpunit>
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
namespace TurboLabIt\ShopifySdk\Connector;
3+
4+
5+
class ShopifyAdminConnector extends ShopifyBaseConnector
6+
{
7+
protected string $endpoint = 'https://##shop-name##.myshopify.com/admin/api/##api-version##/graphql.json';
8+
}
+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
namespace TurboLabIt\ShopifySdk\Connector;
3+
4+
use Saloon\Http\Connector;
5+
6+
7+
abstract class ShopifyBaseConnector extends Connector
8+
{
9+
protected string $endpoint = '';
10+
11+
12+
public function __construct(protected array $arrConfig)
13+
{ }
14+
15+
16+
public function defaultConfig(): array
17+
{
18+
return [
19+
'timeout' => 15,
20+
];
21+
}
22+
23+
24+
public function resolveBaseUrl() : string
25+
{
26+
$arrData = [
27+
"##shop-name##" => $this->arrConfig["shop_name"],
28+
"##api-version##" => $this->arrConfig["api_version"],
29+
];
30+
31+
$endpoint = str_ireplace(array_keys($arrData), array_values($arrData), $this->endpoint);
32+
return $endpoint;
33+
}
34+
35+
36+
protected function defaultHeaders(): array
37+
{
38+
return [
39+
'Content-Type' => 'application/graphql',
40+
'X-Shopify-Access-Token' => $this->arrConfig["access_token"]
41+
];
42+
}
43+
}
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
namespace TurboLabIt\ShopifySdk\Connector;
3+
4+
5+
class ShopifyFrontConnector extends ShopifyBaseConnector
6+
{
7+
protected string $endpoint = 'TBD';
8+
}

src/DependencyInjection/ShopifySdkExtension.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
class ShopifySdkExtension extends Extension
1111
{
12-
public function load(array $configs, ContainerBuilder $container)
12+
public function load(array $configs, ContainerBuilder $container) : void
1313
{
1414
$loader = new YamlFileLoader($container, new FileLocator(dirname(__DIR__).'/../config'));
1515
$loader->load('services.yaml');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?php
2+
namespace TurboLabIt\ShopifySdk\Exception;
3+
4+
class ShopifyConfigurationException extends \Exception
5+
{
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?php
2+
3+
namespace TurboLabIt\ShopifySdk\Exception;
4+
5+
class ShopifyResponseException extends \Exception
6+
{
7+
}
+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
namespace TurboLabIt\ShopifySdk\Request;
3+
4+
use Twig\Environment;
5+
use TurboLabIt\ShopifySdk\Connector\ShopifyAdminConnector;
6+
7+
8+
9+
abstract class ShopifyBaseAdminRequest extends ShopifyBaseRequest
10+
{
11+
public function __construct(protected Environment $twig, protected ShopifyAdminConnector $connector)
12+
{ }
13+
}
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
namespace TurboLabIt\ShopifySdk\Request;
3+
4+
use Twig\Environment;
5+
use TurboLabIt\ShopifySdk\Connector\ShopifyFrontConnector;
6+
7+
8+
abstract class ShopifyBaseFrontRequest extends BaseRequest
9+
{
10+
public function __construct(protected Environment $twig, protected ShopifyFrontConnector $connector)
11+
{ }
12+
}

src/Request/ShopifyBaseRequest.php

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<?php
2+
namespace TurboLabIt\ShopifySdk\Request;
3+
4+
use Saloon\Http\Request;
5+
use Saloon\Traits\Body\HasBody;
6+
use Saloon\Enums\Method;
7+
use Saloon\Contracts\Body\HasBody as HasBodyContract;
8+
use TurboLabIt\ShopifySdk\Exception\ShopifyConfigurationException;
9+
use Saloon\Http\Response;
10+
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
11+
use TurboLabIt\ShopifySdk\Exception\ShopifyResponseException;
12+
13+
14+
abstract class ShopifyBaseRequest extends Request implements HasBodyContract
15+
{
16+
protected Method $method = Method::POST;
17+
18+
protected string $templateDir = 'request/shopify/graphql/';
19+
protected string $templateFile = '';
20+
21+
use HasBody;
22+
23+
24+
public function setQueryFromTemplateBuilt(array $arrData = []) : static
25+
{
26+
if( empty($this->templateFile) ) {
27+
throw new ShopifyConfigurationException("$this->templateFile not set!");
28+
}
29+
30+
$template = $this->templateDir . $this->templateFile . ".graphql.twig";
31+
$graphQlQuery = $this->twig->render($template, $arrData);
32+
33+
return $this->setQuery($graphQlQuery);
34+
}
35+
36+
37+
public function setQuery(string $graphQl) : static
38+
{
39+
$this->body()->set($graphQl);
40+
return $this;
41+
}
42+
43+
44+
public function resolveEndpoint(): string
45+
{
46+
return '';
47+
}
48+
49+
50+
public function buildFromResponse(Response $response)
51+
{
52+
$errorMessages = [];
53+
54+
$httpStatusCode = $response->status() ?? null;
55+
56+
if(
57+
empty($httpStatusCode) ||
58+
$httpStatusCode < SymfonyResponse::HTTP_OK ||
59+
$httpStatusCode >= SymfonyResponse::HTTP_MULTIPLE_CHOICES
60+
) {
61+
$errorMessages[] = "HTTP response error: ##$httpStatusCode##";
62+
}
63+
64+
try {
65+
$json = $response->json();
66+
} catch (\JsonException $ex) {
67+
$errorMessages[] = "JSON decode error: ##" . $response->body() . "##";
68+
}
69+
70+
if( !empty($json) && is_array($json) && !empty($json["errors"]) ) {
71+
72+
$arrErrorFromJson = array_column($json["errors"], 'message') ?? null;
73+
$errorMessages = array_merge($errorMessages, $arrErrorFromJson);
74+
}
75+
76+
if( !empty($errorMessages) ) {
77+
78+
$message = implode(PHP_EOL, $errorMessages);
79+
throw new ShopifyResponseException($message, $httpStatusCode);
80+
}
81+
82+
return $json;
83+
}
84+
}
+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
namespace TurboLabIt\ShopifySdk\Request;
3+
4+
5+
class ShopifyOrderListRequest extends ShopifyBaseAdminRequest
6+
{
7+
protected string $templateFile = 'orders-bulk';
8+
9+
10+
public function getRecent(int $lastDays = 7) : array
11+
{
12+
$date =
13+
(new \DateTime())
14+
->modify('-' . $lastDays . ' days')
15+
->format('Y-m-d');
16+
17+
$request =
18+
$this
19+
->setQueryFromTemplateBuilt([
20+
"selectOrderAfterDate" => $date
21+
]);
22+
23+
$response = $this->connector->send($request);
24+
25+
$arrOrders = $this->buildFromResponse($response);
26+
27+
return $arrOrders;
28+
}
29+
}

0 commit comments

Comments
 (0)