Add initial HTML template for MojeGS1 application with Cookiebot and Google Analytics integration
This commit is contained in:
84
bin/cron.php
Normal file
84
bin/cron.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
use App\Core\Database\ConnectionFactory;
|
||||
use App\Core\Support\Env;
|
||||
use App\Modules\Cron\CronJobProcessor;
|
||||
use App\Modules\Cron\CronJobRepository;
|
||||
use App\Modules\Cron\CronJobType;
|
||||
use App\Modules\Cron\ProductLinksHealthCheckHandler;
|
||||
use App\Modules\ProductLinks\ChannelOffersRepository;
|
||||
use App\Modules\ProductLinks\OfferImportService;
|
||||
use App\Modules\ProductLinks\ProductLinksRepository;
|
||||
use App\Modules\Settings\IntegrationRepository;
|
||||
use App\Modules\Settings\ShopProClient;
|
||||
|
||||
$basePath = dirname(__DIR__);
|
||||
$vendorAutoload = $basePath . '/vendor/autoload.php';
|
||||
|
||||
if (is_file($vendorAutoload)) {
|
||||
require $vendorAutoload;
|
||||
} else {
|
||||
spl_autoload_register(static function (string $class) use ($basePath): void {
|
||||
$prefix = 'App\\';
|
||||
if (!str_starts_with($class, $prefix)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$relative = substr($class, strlen($prefix));
|
||||
$file = $basePath . '/src/' . str_replace('\\', '/', $relative) . '.php';
|
||||
if (is_file($file)) {
|
||||
require $file;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Env::load($basePath . '/.env');
|
||||
|
||||
/** @var array<string, mixed> $dbConfig */
|
||||
$dbConfig = require $basePath . '/config/database.php';
|
||||
/** @var array<string, mixed> $appConfig */
|
||||
$appConfig = require $basePath . '/config/app.php';
|
||||
|
||||
$limit = 20;
|
||||
foreach ($argv as $argument) {
|
||||
if (!str_starts_with((string) $argument, '--limit=')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$limitValue = (int) substr((string) $argument, strlen('--limit='));
|
||||
if ($limitValue > 0) {
|
||||
$limit = min(200, $limitValue);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$pdo = ConnectionFactory::make($dbConfig);
|
||||
|
||||
$cronJobs = new CronJobRepository($pdo);
|
||||
$processor = new CronJobProcessor($cronJobs);
|
||||
|
||||
$integrationRepository = new IntegrationRepository(
|
||||
$pdo,
|
||||
(string) (($appConfig['integrations']['secret'] ?? '') ?: '')
|
||||
);
|
||||
$offersRepository = new ChannelOffersRepository($pdo);
|
||||
$linksRepository = new ProductLinksRepository($pdo);
|
||||
$shopProClient = new ShopProClient();
|
||||
$offerImportService = new OfferImportService($shopProClient, $offersRepository, $pdo);
|
||||
$linksHealthCheckHandler = new ProductLinksHealthCheckHandler(
|
||||
$integrationRepository,
|
||||
$offerImportService,
|
||||
$linksRepository,
|
||||
$offersRepository
|
||||
);
|
||||
|
||||
$processor->registerHandler(CronJobType::PRODUCT_LINKS_HEALTH_CHECK, $linksHealthCheckHandler);
|
||||
|
||||
$result = $processor->run($limit);
|
||||
|
||||
echo json_encode($result, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES) . PHP_EOL;
|
||||
} catch (\Throwable $exception) {
|
||||
fwrite(STDERR, '[error] ' . $exception->getMessage() . PHP_EOL);
|
||||
exit(1);
|
||||
}
|
||||
231
bin/test_gs1_api.php
Normal file
231
bin/test_gs1_api.php
Normal file
@@ -0,0 +1,231 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* GS1 API diagnostic
|
||||
*
|
||||
* Usage:
|
||||
* php bin/test_gs1_api.php <login> <password> [gtin]
|
||||
*
|
||||
* If login/password are not provided, script tries to read them from DB app_settings.
|
||||
*/
|
||||
|
||||
$login = $argv[1] ?? '';
|
||||
$password = $argv[2] ?? '';
|
||||
$targetGtin = $argv[3] ?? '5905323904514';
|
||||
|
||||
if ($login === '' || $password === '') {
|
||||
$envFile = dirname(__DIR__) . '/.env';
|
||||
$env = [];
|
||||
if (is_file($envFile)) {
|
||||
foreach (file($envFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $line) {
|
||||
$line = trim($line);
|
||||
if ($line === '' || $line[0] === '#') {
|
||||
continue;
|
||||
}
|
||||
$pos = strpos($line, '=');
|
||||
if ($pos === false) {
|
||||
continue;
|
||||
}
|
||||
$env[trim(substr($line, 0, $pos))] = trim(trim(substr($line, $pos + 1)), "\"'");
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
$pdo = new PDO(
|
||||
sprintf(
|
||||
'mysql:host=%s;port=%s;dbname=%s;charset=utf8mb4',
|
||||
$env['DB_HOST'] ?? '127.0.0.1',
|
||||
$env['DB_PORT'] ?? '3306',
|
||||
$env['DB_DATABASE'] ?? 'orderpro'
|
||||
),
|
||||
$env['DB_USERNAME'] ?? 'root',
|
||||
$env['DB_PASSWORD'] ?? '',
|
||||
[PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
|
||||
);
|
||||
|
||||
$stmt = $pdo->prepare('SELECT setting_key, setting_value FROM app_settings WHERE setting_key IN (?, ?)');
|
||||
$stmt->execute(['gs1_api_login', 'gs1_api_password']);
|
||||
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $row) {
|
||||
if ($row['setting_key'] === 'gs1_api_login') {
|
||||
$login = (string) $row['setting_value'];
|
||||
}
|
||||
if ($row['setting_key'] === 'gs1_api_password') {
|
||||
$password = (string) $row['setting_value'];
|
||||
}
|
||||
}
|
||||
} catch (Throwable) {
|
||||
// Ignore and use CLI args fallback.
|
||||
}
|
||||
}
|
||||
|
||||
if ($login === '' || $password === '') {
|
||||
fwrite(STDERR, "Brak credentials. Uzyj: php bin/test_gs1_api.php <login> <password> [gtin]\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!preg_match('/^\d{13,14}$/', $targetGtin)) {
|
||||
fwrite(STDERR, "Nieprawidlowy GTIN: {$targetGtin}. Oczekiwane 13 lub 14 cyfr.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
const GS1_BASE = 'https://mojegs1.pl/api/v2';
|
||||
|
||||
/**
|
||||
* @return array{status:int, body:string, error:string}
|
||||
*/
|
||||
function gs1Request(
|
||||
string $method,
|
||||
string $url,
|
||||
string $login,
|
||||
string $password,
|
||||
?string $rawBody = null,
|
||||
string $contentType = 'application/json',
|
||||
string $accept = 'application/json'
|
||||
): array {
|
||||
$curl = curl_init($url);
|
||||
if ($curl === false) {
|
||||
return ['status' => 0, 'body' => '', 'error' => 'Nie mozna zainicjalizowac cURL'];
|
||||
}
|
||||
|
||||
$headers = ['Accept: ' . $accept];
|
||||
if ($rawBody !== null) {
|
||||
$headers[] = 'Content-Type: ' . $contentType;
|
||||
}
|
||||
|
||||
curl_setopt_array($curl, [
|
||||
CURLOPT_RETURNTRANSFER => true,
|
||||
CURLOPT_HTTPHEADER => $headers,
|
||||
CURLOPT_USERPWD => $login . ':' . $password,
|
||||
CURLOPT_HTTPAUTH => CURLAUTH_BASIC,
|
||||
CURLOPT_TIMEOUT => 30,
|
||||
CURLOPT_SSL_VERIFYPEER => true,
|
||||
CURLOPT_SSL_VERIFYHOST => 2,
|
||||
CURLOPT_CUSTOMREQUEST => $method,
|
||||
]);
|
||||
|
||||
if ($rawBody !== null) {
|
||||
curl_setopt($curl, CURLOPT_POSTFIELDS, $rawBody);
|
||||
}
|
||||
|
||||
$body = curl_exec($curl);
|
||||
$status = (int) curl_getinfo($curl, CURLINFO_RESPONSE_CODE);
|
||||
$error = curl_error($curl);
|
||||
curl_close($curl);
|
||||
|
||||
return [
|
||||
'status' => $status,
|
||||
'body' => is_string($body) ? $body : '',
|
||||
'error' => $error,
|
||||
];
|
||||
}
|
||||
|
||||
function toJson(mixed $value): string
|
||||
{
|
||||
$json = json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRETTY_PRINT);
|
||||
return $json === false ? '[json_encode error]' : $json;
|
||||
}
|
||||
|
||||
function printResponse(string $label, array $response): void
|
||||
{
|
||||
echo $label . PHP_EOL;
|
||||
echo 'HTTP: ' . $response['status'] . PHP_EOL;
|
||||
if ($response['error'] !== '') {
|
||||
echo 'cURL error: ' . $response['error'] . PHP_EOL;
|
||||
}
|
||||
if ($response['body'] === '') {
|
||||
echo "BODY: [empty]\n\n";
|
||||
return;
|
||||
}
|
||||
|
||||
$decoded = json_decode($response['body'], true);
|
||||
if (is_array($decoded)) {
|
||||
echo "BODY:\n" . toJson($decoded) . PHP_EOL;
|
||||
if (!empty($decoded['errors'])) {
|
||||
echo "ERRORS:\n" . toJson($decoded['errors']) . PHP_EOL;
|
||||
}
|
||||
} else {
|
||||
echo "BODY:\n" . $response['body'] . PHP_EOL;
|
||||
}
|
||||
echo PHP_EOL;
|
||||
}
|
||||
|
||||
function putProduct(string $gtin, array $attributes, string $login, string $password): array
|
||||
{
|
||||
$payload = [
|
||||
'data' => [
|
||||
'type' => 'products',
|
||||
'id' => $gtin,
|
||||
'attributes' => $attributes,
|
||||
],
|
||||
];
|
||||
|
||||
return gs1Request(
|
||||
'PUT',
|
||||
GS1_BASE . '/products/' . rawurlencode($gtin),
|
||||
$login,
|
||||
$password,
|
||||
json_encode($payload, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES)
|
||||
);
|
||||
}
|
||||
|
||||
echo "=== GS1 Diagnostic v5 ===\n";
|
||||
echo "Target GTIN: {$targetGtin}\n\n";
|
||||
|
||||
// 1) Check target GTIN
|
||||
$targetGet = gs1Request('GET', GS1_BASE . '/products/' . rawurlencode($targetGtin), $login, $password);
|
||||
printResponse('--- Step 1: GET target GTIN ---', $targetGet);
|
||||
|
||||
// 2) PUT with values aligned to external API swagger example (language as `pl`)
|
||||
$attrsSwaggerLike = [
|
||||
'brandName' => 'Test Marka',
|
||||
'subBrandName' => 'Test Podmarka',
|
||||
'commonName' => 'Test produkt',
|
||||
'name' => 'Test produkt API',
|
||||
'description' => 'Test opisu produktu',
|
||||
'gpcCode' => 10000002,
|
||||
'netContent' => 1.5,
|
||||
'netContentUnit' => 'kg',
|
||||
'status' => 'ACT',
|
||||
'targetMarket' => ['PL'],
|
||||
'descriptionLanguage' => 'pl',
|
||||
];
|
||||
$putTargetSwaggerLike = putProduct($targetGtin, $attrsSwaggerLike, $login, $password);
|
||||
printResponse('--- Step 2: PUT target GTIN (swagger-like payload) ---', $putTargetSwaggerLike);
|
||||
|
||||
// 3) PUT with original app defaults (for direct comparison with old script behavior)
|
||||
$attrsAppLike = [
|
||||
'brandName' => 'marianek.pl',
|
||||
'subBrandName' => 'marianek.pl',
|
||||
'commonName' => 'Produkt testowy',
|
||||
'name' => 'Produkt testowy API',
|
||||
'gpcCode' => 10008365,
|
||||
'netContent' => 1,
|
||||
'netContentUnit' => 'szt',
|
||||
'status' => 'ACT',
|
||||
'targetMarket' => ['PL'],
|
||||
'descriptionLanguage' => 'PL',
|
||||
];
|
||||
$putTargetAppLike = putProduct($targetGtin, $attrsAppLike, $login, $password);
|
||||
printResponse('--- Step 3: PUT target GTIN (app-like payload) ---', $putTargetAppLike);
|
||||
|
||||
// 4) Permission check: read an existing product and try no-op PUT.
|
||||
$list = gs1Request('GET', GS1_BASE . '/products?page[offset]=1&page[limit]=1&sort=name', $login, $password);
|
||||
printResponse('--- Step 4a: GET list (first product) ---', $list);
|
||||
|
||||
$existingGtin = null;
|
||||
$existingAttributes = null;
|
||||
$listDecoded = json_decode($list['body'], true);
|
||||
if (is_array($listDecoded) && isset($listDecoded['data'][0]['id'])) {
|
||||
$existingGtin = (string) $listDecoded['data'][0]['id'];
|
||||
$existingAttributes = $listDecoded['data'][0]['attributes'] ?? null;
|
||||
}
|
||||
|
||||
if ($existingGtin !== null && is_array($existingAttributes)) {
|
||||
$noOpPut = putProduct($existingGtin, $existingAttributes, $login, $password);
|
||||
printResponse('--- Step 4b: PUT existing product with attributes from GET (no-op) ---', $noOpPut);
|
||||
} else {
|
||||
echo "--- Step 4b: skipped (no product data from list) ---\n\n";
|
||||
}
|
||||
|
||||
echo "=== DONE ===\n";
|
||||
Reference in New Issue
Block a user