first commit

This commit is contained in:
2024-11-05 12:22:50 +01:00
commit e5682a3912
19641 changed files with 2948548 additions and 0 deletions

View File

@@ -0,0 +1,5 @@
{
"require": {
"br33f/php-ga4-mp": "^0.1.3"
}
}

View File

@@ -0,0 +1,573 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "744b19aba243b0d00c890005533a131f",
"packages": [
{
"name": "br33f/php-ga4-mp",
"version": "v0.1.3",
"source": {
"type": "git",
"url": "https://github.com/br33f/php-GA4-Measurement-Protocol.git",
"reference": "7fd3d60213e5955886e05a628c972b3291c0be31"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/br33f/php-GA4-Measurement-Protocol/zipball/7fd3d60213e5955886e05a628c972b3291c0be31",
"reference": "7fd3d60213e5955886e05a628c972b3291c0be31",
"shasum": ""
},
"require": {
"ext-json": "*",
"guzzlehttp/guzzle": "^6.5.5 || ^7.0.0",
"php": ">=7.1"
},
"require-dev": {
"fakerphp/faker": "^1.14",
"php-coveralls/php-coveralls": "^2.4",
"phpunit/phpunit": "^9.5"
},
"type": "library",
"autoload": {
"psr-4": {
"Br33f\\Ga4\\MeasurementProtocol\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Damian Zamojski",
"email": "damian.zamojski1@gmail.com"
}
],
"description": "PHP GoogleAnalytics4 Measurement Protocol Library",
"time": "2023-03-20T20:12:12+00:00"
},
{
"name": "guzzlehttp/guzzle",
"version": "7.7.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "fb7566caccf22d74d1ab270de3551f72a58399f5"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/fb7566caccf22d74d1ab270de3551f72a58399f5",
"reference": "fb7566caccf22d74d1ab270de3551f72a58399f5",
"shasum": ""
},
"require": {
"ext-json": "*",
"guzzlehttp/promises": "^1.5.3 || ^2.0",
"guzzlehttp/psr7": "^1.9.1 || ^2.4.5",
"php": "^7.2.5 || ^8.0",
"psr/http-client": "^1.0",
"symfony/deprecation-contracts": "^2.2 || ^3.0"
},
"provide": {
"psr/http-client-implementation": "1.0"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.8.1",
"ext-curl": "*",
"php-http/client-integration-tests": "dev-master#2c025848417c1135031fdf9c728ee53d0a7ceaee as 3.0.999",
"php-http/message-factory": "^1.1",
"phpunit/phpunit": "^8.5.29 || ^9.5.23",
"psr/log": "^1.1 || ^2.0 || ^3.0"
},
"suggest": {
"ext-curl": "Required for CURL handler support",
"ext-intl": "Required for Internationalized Domain Name (IDN) support",
"psr/log": "Required for using the Log middleware"
},
"type": "library",
"extra": {
"bamarni-bin": {
"bin-links": true,
"forward-command": false
}
},
"autoload": {
"files": [
"src/functions_include.php"
],
"psr-4": {
"GuzzleHttp\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Graham Campbell",
"email": "hello@gjcampbell.co.uk",
"homepage": "https://github.com/GrahamCampbell"
},
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "Jeremy Lindblom",
"email": "jeremeamia@gmail.com",
"homepage": "https://github.com/jeremeamia"
},
{
"name": "George Mponos",
"email": "gmponos@gmail.com",
"homepage": "https://github.com/gmponos"
},
{
"name": "Tobias Nyholm",
"email": "tobias.nyholm@gmail.com",
"homepage": "https://github.com/Nyholm"
},
{
"name": "Márk Sági-Kazár",
"email": "mark.sagikazar@gmail.com",
"homepage": "https://github.com/sagikazarmark"
},
{
"name": "Tobias Schultze",
"email": "webmaster@tubo-world.de",
"homepage": "https://github.com/Tobion"
}
],
"description": "Guzzle is a PHP HTTP client library",
"keywords": [
"client",
"curl",
"framework",
"http",
"http client",
"psr-18",
"psr-7",
"rest",
"web service"
],
"time": "2023-05-21T14:04:53+00:00"
},
{
"name": "guzzlehttp/promises",
"version": "2.0.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/promises.git",
"reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/promises/zipball/3a494dc7dc1d7d12e511890177ae2d0e6c107da6",
"reference": "3a494dc7dc1d7d12e511890177ae2d0e6c107da6",
"shasum": ""
},
"require": {
"php": "^7.2.5 || ^8.0"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.8.1",
"phpunit/phpunit": "^8.5.29 || ^9.5.23"
},
"type": "library",
"extra": {
"bamarni-bin": {
"bin-links": true,
"forward-command": false
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Promise\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Graham Campbell",
"email": "hello@gjcampbell.co.uk",
"homepage": "https://github.com/GrahamCampbell"
},
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "Tobias Nyholm",
"email": "tobias.nyholm@gmail.com",
"homepage": "https://github.com/Nyholm"
},
{
"name": "Tobias Schultze",
"email": "webmaster@tubo-world.de",
"homepage": "https://github.com/Tobion"
}
],
"description": "Guzzle promises library",
"keywords": [
"promise"
],
"time": "2023-05-21T13:50:22+00:00"
},
{
"name": "guzzlehttp/psr7",
"version": "2.5.0",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "b635f279edd83fc275f822a1188157ffea568ff6"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/b635f279edd83fc275f822a1188157ffea568ff6",
"reference": "b635f279edd83fc275f822a1188157ffea568ff6",
"shasum": ""
},
"require": {
"php": "^7.2.5 || ^8.0",
"psr/http-factory": "^1.0",
"psr/http-message": "^1.1 || ^2.0",
"ralouphie/getallheaders": "^3.0"
},
"provide": {
"psr/http-factory-implementation": "1.0",
"psr/http-message-implementation": "1.0"
},
"require-dev": {
"bamarni/composer-bin-plugin": "^1.8.1",
"http-interop/http-factory-tests": "^0.9",
"phpunit/phpunit": "^8.5.29 || ^9.5.23"
},
"suggest": {
"laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
},
"type": "library",
"extra": {
"bamarni-bin": {
"bin-links": true,
"forward-command": false
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Psr7\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Graham Campbell",
"email": "hello@gjcampbell.co.uk",
"homepage": "https://github.com/GrahamCampbell"
},
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "George Mponos",
"email": "gmponos@gmail.com",
"homepage": "https://github.com/gmponos"
},
{
"name": "Tobias Nyholm",
"email": "tobias.nyholm@gmail.com",
"homepage": "https://github.com/Nyholm"
},
{
"name": "Márk Sági-Kazár",
"email": "mark.sagikazar@gmail.com",
"homepage": "https://github.com/sagikazarmark"
},
{
"name": "Tobias Schultze",
"email": "webmaster@tubo-world.de",
"homepage": "https://github.com/Tobion"
},
{
"name": "Márk Sági-Kazár",
"email": "mark.sagikazar@gmail.com",
"homepage": "https://sagikazarmark.hu"
}
],
"description": "PSR-7 message implementation that also provides common utility methods",
"keywords": [
"http",
"message",
"psr-7",
"request",
"response",
"stream",
"uri",
"url"
],
"time": "2023-04-17T16:11:26+00:00"
},
{
"name": "psr/http-client",
"version": "1.0.2",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-client.git",
"reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-client/zipball/0955afe48220520692d2d09f7ab7e0f93ffd6a31",
"reference": "0955afe48220520692d2d09f7ab7e0f93ffd6a31",
"shasum": ""
},
"require": {
"php": "^7.0 || ^8.0",
"psr/http-message": "^1.0 || ^2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Client\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for HTTP clients",
"homepage": "https://github.com/php-fig/http-client",
"keywords": [
"http",
"http-client",
"psr",
"psr-18"
],
"time": "2023-04-10T20:12:12+00:00"
},
{
"name": "psr/http-factory",
"version": "1.0.2",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-factory.git",
"reference": "e616d01114759c4c489f93b099585439f795fe35"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-factory/zipball/e616d01114759c4c489f93b099585439f795fe35",
"reference": "e616d01114759c4c489f93b099585439f795fe35",
"shasum": ""
},
"require": {
"php": ">=7.0.0",
"psr/http-message": "^1.0 || ^2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common interfaces for PSR-7 HTTP message factories",
"keywords": [
"factory",
"http",
"message",
"psr",
"psr-17",
"psr-7",
"request",
"response"
],
"time": "2023-04-10T20:10:41+00:00"
},
{
"name": "psr/http-message",
"version": "2.0",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-message.git",
"reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71",
"reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "https://www.php-fig.org/"
}
],
"description": "Common interface for HTTP messages",
"homepage": "https://github.com/php-fig/http-message",
"keywords": [
"http",
"http-message",
"psr",
"psr-7",
"request",
"response"
],
"time": "2023-04-04T09:54:51+00:00"
},
{
"name": "ralouphie/getallheaders",
"version": "3.0.3",
"source": {
"type": "git",
"url": "https://github.com/ralouphie/getallheaders.git",
"reference": "120b605dfeb996808c31b6477290a714d356e822"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822",
"reference": "120b605dfeb996808c31b6477290a714d356e822",
"shasum": ""
},
"require": {
"php": ">=5.6"
},
"require-dev": {
"php-coveralls/php-coveralls": "^2.1",
"phpunit/phpunit": "^5 || ^6.5"
},
"type": "library",
"autoload": {
"files": [
"src/getallheaders.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ralph Khattar",
"email": "ralph.khattar@gmail.com"
}
],
"description": "A polyfill for getallheaders.",
"time": "2019-03-08T08:55:37+00:00"
},
{
"name": "symfony/deprecation-contracts",
"version": "v2.5.2",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/e8b495ea28c1d97b5e0c121748d6f9b53d075c66",
"reference": "e8b495ea28c1d97b5e0c121748d6f9b53d075c66",
"shasum": ""
},
"require": {
"php": ">=7.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "2.5-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
"files": [
"function.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"time": "2022-01-02T09:53:40+00:00"
}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": [],
"platform-dev": []
}

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<module>
<name>pdgoogleanalytycs4pro</name>
<displayName><![CDATA[Google Analytycs 4 Pro]]></displayName>
<version><![CDATA[1.1.9]]></version>
<description><![CDATA[Moduł kt&oacute;ry dodaje kod Google Analytycs 4.0 wraz z obsługą zdarzeń do Twojego sklepu internetowego.]]></description>
<author><![CDATA[PrestaDev.pl]]></author>
<tab><![CDATA[advertising_marketing]]></tab>
<is_configurable>1</is_configurable>
<need_instance>0</need_instance>
<limited_countries></limited_countries>
</module>

View File

@@ -0,0 +1,414 @@
<?php
/**
* 2012-2022 Patryk Marek PrestaDev.pl
*
* Patryk Marek PrestaDev.pl - PD Google Analytycs 4.0 Pro 1.6.x and 1.7.x Module © All rights reserved.
*
* DISCLAIMER
*
* Do not edit, modify or copy this file.
* If you wish to customize it, contact us at info@prestadev.pl.
*
* @author Patryk Marek <info@prestadev.pl>
* @copyright 2012-2022 Patryk Marek @ PrestaDev.pl
* @license Do not edit, modify or copy this file, if you wish to customize it, contact us at info@prestadev.pl.
* @link http://prestadev.pl
* @package PD Google Analytycs 4.0 Pro 1.6.x and 1.7.x Module
* @version 1.0.1
* @date 01-05-2021
*/
class PdGoogleAnalytycs4ProAjaxModuleFrontController extends ModuleFrontController
{
private $name = '';
public function initContent()
{
$this->ajax = true;
parent::initContent();
$this->name = 'pdgoogleanalytycs4pro';
}
public function displayAjax()
{
$module = new PdGoogleAnalytycs4Pro();
if (Tools::getValue('secure_key') == $module->secure_key) {
$id_product = (int)Tools::getValue('product_id');
$id_lang = (int)Configuration::get('PS_LANG_DEFAULT');
$id_shop = (int)Context::getContext()->shop->id;
$currency_iso = (string)$this->context->currency->iso_code;
$action = (string)Tools::getValue('action');
$cart_rules = $module->getCartRuleWithCoupon();
$cn = $module::getControlerName();
if ($action == 'updateCart') {
$id_product_attribute = Tools::getValue('product_id_product_attribute');
$product = new Product((int)$id_product, false, $id_lang);
$variant = '';
$attribute_combination_resume = false;
if ($id_product_attribute) {
$attribute_combination_resume = $product->getAttributeCombinationsById($id_product_attribute, $id_lang, true);
if ($attribute_combination_resume) {
foreach ($attribute_combination_resume as $acr) {
$variant .= $acr['group_name'].': '.$acr['attribute_name'].' - ';
}
$variant = mb_substr($variant, 0, -3);
}
}
if (!empty($variant)) {
$product_name = addslashes($product->name.' ('.$variant.')');
} else {
$product_name = addslashes($product->name);
}
$price = Product::getPriceStatic($id_product, true, $id_product_attribute, 6, null, false, true);
$price_old = Product::getPriceStatic($id_product, true, $id_product_attribute, 6, null, false, false);
$discount = 0;
if ($price_old > $price) {
$discount = $price_old - $price;
}
$content_ids = $module->getProductIdStringByType($product, $id_product_attribute);
$content_category = explode('/', $module->getCategoryPath($product->id_category_default));
$content_category = array_map('trim', $content_category);
$data = array(
'item_list_id' => $cn,
'item_list_name' => $cn,
'content_ids' => $content_ids,
'content_category' => isset($content_category[0]) ? addslashes($content_category[0]) : '',
'content_category2' => isset($content_category[1]) ? addslashes($content_category[1]) : '',
'content_category3' => isset($content_category[2]) ? addslashes($content_category[2]) : '',
'content_category4' => isset($content_category[3]) ? addslashes($content_category[3]) : '',
'content_category5' => isset($content_category[4]) ? addslashes($content_category[4]) : '',
'content_name' => $product_name,
'content_value' => Tools::ps_round($price, 2),
'content_value_old' => Tools::ps_round($price_old, 2),
'content_discount' => Tools::ps_round($discount, 2),
'content_variant' => $variant,
'content_manufacturer' => Manufacturer::getNameById($product->id_manufacturer) ? Manufacturer::getNameById($product->id_manufacturer) : '',
'content_coupon' => sizeof($cart_rules) ? $cart_rules['name'].' - '.$cart_rules['code'] : '',
'currency' => $currency_iso,
'http_referer' => addslashes($module->http_referer),
);
die(json_encode($data));
} elseif ($action == 'productClick') {
$id_product_attribute = Tools::getValue('product_id_product_attribute');
$product = new Product((int)$id_product, false, $id_lang);
$variant = '';
$attribute_combination_resume = false;
if ($id_product_attribute) {
$attribute_combination_resume = $product->getAttributeCombinationsById($id_product_attribute, $id_lang, true);
if ($attribute_combination_resume) {
foreach ($attribute_combination_resume as $acr) {
$variant .= $acr['group_name'].': '.$acr['attribute_name'].' - ';
}
$variant = mb_substr($variant, 0, -3);
}
}
if (!empty($variant)) {
$product_name = addslashes($product->name.' ('.$variant.')');
} else {
$product_name = addslashes($product->name);
}
$price = Product::getPriceStatic($id_product, true, $id_product_attribute, 6, null, false, true);
$price_old = Product::getPriceStatic($id_product, true, $id_product_attribute, 6, null, false, false);
$discount = 0;
if ($price_old > $price) {
$discount = $price_old - $price;
}
$content_category = explode('/', $module->getCategoryPath($product->id_category_default));
$content_category = array_map('trim', $content_category);
$content_ids = $module->getProductIdStringByType($product, $id_product_attribute);
$data = array(
'item_list_id' => $cn,
'item_list_name' => $cn,
'content_ids' => $content_ids,
'content_category' => isset($content_category[0]) ? addslashes($content_category[0]) : '',
'content_category2' => isset($content_category[1]) ? addslashes($content_category[1]) : '',
'content_category3' => isset($content_category[2]) ? addslashes($content_category[2]) : '',
'content_category4' => isset($content_category[3]) ? addslashes($content_category[3]) : '',
'content_category5' => isset($content_category[4]) ? addslashes($content_category[4]) : '',
'content_name' => $product_name,
'content_value' => Tools::ps_round($price, 2),
'content_value_old' => Tools::ps_round($price_old, 2),
'content_discount' => Tools::ps_round($discount, 2),
'content_variant' => $variant,
'content_manufacturer' => Manufacturer::getNameById($product->id_manufacturer) ? Manufacturer::getNameById($product->id_manufacturer) : '',
'content_coupon' => sizeof($cart_rules) ? $cart_rules['name'].' - '.$cart_rules['code'] : '',
'currency' => $currency_iso,
'http_referer' => addslashes($module->http_referer),
);
die(json_encode($data));
} elseif ($action == 'updateProduct') {
$groups = Tools::getValue('attributes_groups');
$id_product_attribute = (int)self::getIdProductAttributeByIdAttributes((int)$id_product, $groups);
$product = new Product((int)$id_product, false, $id_lang);
$price = Product::getPriceStatic($id_product, true, $id_product_attribute, 2);
$content_category = explode('/', $module->getCategoryPath($product->id_category_default));
$content_category = array_map('trim', $content_category);
$content_ids = $module->getProductIdStringByType($product, $id_product_attribute);
$variant = '';
$attribute_combination_resume = false;
if ($id_product_attribute) {
$attribute_combination_resume = $product->getAttributeCombinationsById($id_product_attribute, $id_lang, true);
if ($attribute_combination_resume) {
foreach ($attribute_combination_resume as $acr) {
$variant .= $acr['group_name'].': '.$acr['attribute_name'].' - ';
}
$variant = mb_substr($variant, 0, -3);
}
}
if (!empty($variant)) {
$product_name = addslashes($product->name.' ('.$variant.')');
} else {
$product_name = addslashes($product->name);
}
$price = Product::getPriceStatic($id_product, true, $id_product_attribute, 6, null, false, true);
$price_old = Product::getPriceStatic($id_product, true, $id_product_attribute, 6, null, false, false);
$discount = 0;
if ($price_old > $price) {
$discount = $price_old - $price;
}
$data = array(
'item_list_id' => $cn,
'item_list_name' => $cn,
'content_ids' => $content_ids,
'content_category' => isset($content_category[0]) ? addslashes($content_category[0]) : '',
'content_category2' => isset($content_category[1]) ? addslashes($content_category[1]) : '',
'content_category3' => isset($content_category[2]) ? addslashes($content_category[2]) : '',
'content_category4' => isset($content_category[3]) ? addslashes($content_category[3]) : '',
'content_category5' => isset($content_category[4]) ? addslashes($content_category[4]) : '',
'content_name' => $product_name,
'content_value' => Tools::ps_round($price, 2),
'content_value_old' => Tools::ps_round($price_old, 2),
'content_discount' => Tools::ps_round($discount, 2),
'content_variant' => $variant,
'content_manufacturer' => Manufacturer::getNameById($product->id_manufacturer) ? Manufacturer::getNameById($product->id_manufacturer) : '',
'content_coupon' => sizeof($cart_rules) ? $cart_rules['name'].' - '.$cart_rules['code'] : '',
'http_referer' => addslashes($module->http_referer),
);
die(json_encode($data));
} elseif ($action == 'addDeliveryInfo') {
$cart = Context::getContext()->cart;
if (!($cart instanceof Cart)) {
return;
}
if (isset($cart->id)) {
$id_carrier = (int)Tools::getValue('id_carrier');
$value = $cart->getOrderTotal(true, Cart::BOTH, null, $id_carrier, false, false);
$cart_products = $cart->getProducts();
foreach ($cart_products as &$cp) {
$content_category = explode('/', $module->getCategoryPath($cp['id_category_default']));
$content_category = array_map('trim', $content_category);
$cp['content_category'] = isset($content_category[0]) ? addslashes($content_category[0]) : '';
$cp['content_category2'] = isset($content_category[1]) ? addslashes($content_category[1]) : '';
$cp['content_category3'] = isset($content_category[2]) ? addslashes($content_category[2]) : '';
$cp['content_category4'] = isset($content_category[3]) ? addslashes($content_category[3]) : '';
$cp['content_category5'] = isset($content_category[4]) ? addslashes($content_category[4]) : '';
$cp['content_ids'] = $module->getProductIdStringByType($cp);
$cp['discount'] = 0;
$cp['content_coupon'] = ($cart_rules & is_array($cart_rules)) ? $cart_rules['name'].' - '.$cart_rules['code'] : '';
$cp['discount'] = Tools::ps_round($cp['price_without_reduction'] - $cp['price_wt'], 2);
$cp['price_old'] = Tools::ps_round($cp['price_without_reduction'], 2);
$product = new Product($cp['id_product'], false, $id_lang);
$attribute_combination_resume = $product->getAttributeCombinationsById($cp['id_product_attribute'], $id_lang, true);
if ($attribute_combination_resume) {
$cp['variant'] = '';
foreach ($attribute_combination_resume as $acr) {
$cp['variant'] .= $acr['group_name'].': '.$acr['attribute_name'].' - ';
}
$cp['variant'] = mb_substr($cp['variant'], 0, -3);
}
if (!empty($cp['variant'])) {
$cp['name'] = addslashes($product->name.' ('.$cp['variant'].')');
} else {
$cp['name'] = addslashes($product->name);
}
$cp['item_list_id'] = $cn;
$cp['item_list_name'] = $cn;
}
$carrier_name = '';
if ($id_carrier = Tools::getValue('id_carrier')) {
$carriers = $module->getCarriersArray();
$carrier_name = $carriers[$id_carrier];
}
$this->context->smarty->assign(array(
'content_value' => $value,
'content_products' => $cart_products,
'content_coupon' => sizeof($cart_rules) ? $cart_rules['name'].' - '.$cart_rules['code'] : '',
'currency' => $currency_iso,
'carrier_name' => addslashes($carrier_name),
'http_referer' => addslashes($module->http_referer),
));
$html = $this->context->smarty->fetch(_PS_MODULE_DIR_.$this->name.'/views/templates/hook/addDeliveryInfo.tpl');
die(json_encode($html));
}
} elseif ($action == 'addPaymentInfo') {
$cart = Context::getContext()->cart;
if (!($cart instanceof Cart)) {
return;
}
if (isset($cart->id)) {
$id_carrier = (int)Tools::getValue('id_carrier');
$value = $cart->getOrderTotal(true, Cart::BOTH, null, $id_carrier, false, false);
$cart_products = $cart->getProducts();
foreach ($cart_products as &$cp) {
$content_category = explode('/', $module->getCategoryPath($cp['id_category_default']));
$content_category = array_map('trim', $content_category);
$cp['content_category'] = isset($content_category[0]) ? addslashes($content_category[0]) : '';
$cp['content_category2'] = isset($content_category[1]) ? addslashes($content_category[1]) : '';
$cp['content_category3'] = isset($content_category[2]) ? addslashes($content_category[2]) : '';
$cp['content_category4'] = isset($content_category[3]) ? addslashes($content_category[3]) : '';
$cp['content_category5'] = isset($content_category[4]) ? addslashes($content_category[4]) : '';
$cp['content_ids'] = $module->getProductIdStringByType($cp);
$cp['content_coupon'] = ($cart_rules & is_array($cart_rules)) ? $cart_rules['name'].' - '.$cart_rules['code'] : '';
$cp['discount'] = 0;
$cp['discount'] = Tools::ps_round($cp['price_without_reduction'] - $cp['price_wt'], 2);
$cp['price_old'] = Tools::ps_round($cp['price_without_reduction'], 2);
$product = new Product($cp['id_product'], false, $id_lang);
$attribute_combination_resume = $product->getAttributeCombinationsById($cp['id_product_attribute'], $id_lang, true);
if ($attribute_combination_resume) {
$cp['variant'] = '';
foreach ($attribute_combination_resume as $acr) {
$cp['variant'] .= $acr['group_name'].': '.$acr['attribute_name'].' - ';
}
$cp['variant'] = mb_substr($cp['variant'], 0, -3);
}
if (!empty($cp['variant'])) {
$cp['name'] = addslashes($product->name.' ('.$cp['variant'].')');
} else {
$cp['name'] = addslashes($product->name);
}
$cp['item_list_id'] = $cn;
$cp['item_list_name'] = $cn;
}
$payment_name = '';
if ($payment_module = Tools::getValue('payment_module')) {
if (($payment_module_instance = Module::getInstanceByName($payment_module))) {
$payment_name = $payment_module_instance->displayName;
}
}
$this->context->smarty->assign(array(
'content_value' => $value,
'content_products' => $cart_products,
'content_coupon' => sizeof($cart_rules) ? $cart_rules['name'].' - '.$cart_rules['code'] : '',
'currency' => $currency_iso,
'payment_name' => addslashes($payment_name),
'http_referer' => addslashes($module->http_referer),
));
$html = $this->context->smarty->fetch(_PS_MODULE_DIR_.$this->name.'/views/templates/hook/addPaymentInfo.tpl');
die(json_encode($html));
}
}
}
}
public static function getIdProductAttributeByIdAttributes($idProduct, $idAttributes, $findBest = false)
{
$idProduct = (int) $idProduct;
if (!is_array($idAttributes) && is_numeric($idAttributes)) {
$idAttributes = [(int) $idAttributes];
}
if (!is_array($idAttributes) || empty($idAttributes)) {
throw new PrestaShopException(sprintf('Invalid parameter $idAttributes with value: "%s"', print_r($idAttributes, true)));
}
$idAttributesImploded = implode(',', array_map('intval', $idAttributes));
$idProductAttribute = Db::getInstance()->getValue(
'
SELECT
pac.`id_product_attribute`
FROM
`' . _DB_PREFIX_ . 'product_attribute_combination` pac
INNER JOIN `' . _DB_PREFIX_ . 'product_attribute` pa ON pa.id_product_attribute = pac.id_product_attribute
WHERE
pa.id_product = ' . $idProduct . '
AND pac.id_attribute IN (' . $idAttributesImploded . ')
GROUP BY
pac.`id_product_attribute`
HAVING
COUNT(pa.id_product) = ' . count($idAttributes)
);
if ($idProductAttribute === false && $findBest) {
//find the best possible combination
//first we order $idAttributes by the group position
$orderred = [];
$result = Db::getInstance()->executeS(
'
SELECT
a.`id_attribute`
FROM
`' . _DB_PREFIX_ . 'attribute` a
INNER JOIN `' . _DB_PREFIX_ . 'attribute_group` g ON a.`id_attribute_group` = g.`id_attribute_group`
WHERE
a.`id_attribute` IN (' . $idAttributesImploded . ')
ORDER BY
g.`position` ASC'
);
foreach ($result as $row) {
$orderred[] = $row['id_attribute'];
}
while ($idProductAttribute === false && count($orderred) > 1) {
array_pop($orderred);
$idProductAttribute = Db::getInstance()->getValue(
'
SELECT
pac.`id_product_attribute`
FROM
`' . _DB_PREFIX_ . 'product_attribute_combination` pac
INNER JOIN `' . _DB_PREFIX_ . 'product_attribute` pa ON pa.id_product_attribute = pac.id_product_attribute
WHERE
pa.id_product = ' . (int) $idProduct . '
AND pac.id_attribute IN (' . implode(',', array_map('intval', $orderred)) . ')
GROUP BY
pac.id_product_attribute
HAVING
COUNT(pa.id_product) = ' . count($orderred)
);
}
}
return $idProductAttribute;
}
}

View File

@@ -0,0 +1,35 @@
<?php
/*
* 2007-2011 PrestaShop
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to http://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2011 PrestaShop SA
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
header("Location: ../");
exit;

View File

@@ -0,0 +1,35 @@
<?php
/*
* 2007-2011 PrestaShop
*
* NOTICE OF LICENSE
*
* This source file is subject to the Open Software License (OSL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/osl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to http://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2011 PrestaShop SA
* @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
header("Location: ../");
exit;

View File

@@ -0,0 +1,10 @@
<?php
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
header("Location: ../");
exit;

Binary file not shown.

After

Width:  |  Height:  |  Size: 555 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 902 B

View File

@@ -0,0 +1,160 @@
<?php
/**
* 2012-2022 Patryk Marek PrestaDev.pl
*
* Patryk Marek PrestaDev.pl - PD Google Analytycs 4 Pro 1.6.x and 1.7.x Module © All rights reserved.
*
* DISCLAIMER
*
* Do not edit, modify or copy this file.
* If you wish to customize it, contact us at info@prestadev.pl.
*
* @author Patryk Marek <info@prestadev.pl>
* @copyright 2012-2022 Patryk Marek @ PrestaDev.pl
* @license Do not edit, modify or copy this file, if you wish to customize it, contact us at info@prestadev.pl.
* @link http://prestadev.pl
* @package PD Google Analytycs 4 Pro 1.6.x and 1.7.x Module
* @version 1.0.2
* @date 01-05-2021
*/
class PdGA4PModel extends ObjectModel
{
public $id_order;
public $client_id;
public $order_send;
public $refund_send;
public $to_refund;
public $date_add = '0000-00-00 00:00:00';
public $date_upd = '0000-00-00 00:00:00';
public static $definition = array(
'table' => 'pdgoogleanalytycs4pro',
'primary' => 'id_order',
'multilang' => false,
'fields' => array(
'id_order' => array('type' => self::TYPE_INT, 'validate' => 'isunsignedInt', 'required' => false),
'client_id' => array('type' => self::TYPE_STRING, 'validate' => 'isString', 'required' => false),
'order_send' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => false),
'refund_send' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => false),
'to_refund' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => false),
'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDateFormat', 'required' => false),
'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDateFormat', 'required' => false)
)
);
public function __construct($id_order = false)
{
parent::__construct($id_order);
}
public function add($autodate = true, $null_values = false)
{
return parent::add($autodate, $null_values);
}
public function delete()
{
if ((int)$this->id_order === 0) {
return false;
}
return parent::delete();
}
public function update($null_values = false)
{
if ((int)$this->id_order === 0) {
return false;
}
return parent::update($null_values);
}
public static function getGAClientIdByIdOrder($id_order)
{
return Db::getInstance()->getValue(
'
SELECT `client_id`
FROM `'._DB_PREFIX_.'pdgoogleanalytycs4pro`
WHERE `id_order` = '.(int)$id_order
);
}
public static function getOrdersToSendByIdOrder($id_order)
{
$res = Db::getInstance()->getRow(
'
SELECT `order_send`
FROM `'._DB_PREFIX_.'pdgoogleanalytycs4pro`
WHERE `id_order` = '.(int)$id_order
);
if (isset($res['order_send'])) {
return $res['order_send'];
} else {
return 2;
}
}
public static function getOrderIdToSendByIdCustomer($id_customer)
{
return (int)Db::getInstance()->getValue('
SELECT MAX(pd.`id_order`)
FROM `'._DB_PREFIX_.'orders` o
LEFT JOIN `'._DB_PREFIX_.'pdgoogleanalytycs4pro` pd
ON pd.`id_order` = o.`id_order`
WHERE o.`id_customer` = '.(int)$id_customer.'
AND pd.`order_send` = 0
');
}
public static function getLastOrderIdByIdCustomer($id_customer)
{
return (int)Db::getInstance()->getValue('
SELECT MAX(pd.`id_order`)
FROM `'._DB_PREFIX_.'orders` o
LEFT JOIN `'._DB_PREFIX_.'pdgoogleanalytycs4pro` pd
ON pd.`id_order` = o.`id_order`
WHERE o.`id_customer` = '.(int)$id_customer
);
}
public static function getOrdersToSendRefundByIdOrder($id_order)
{
$res = Db::getInstance()->getRow(
'
SELECT `refund_send`
FROM `'._DB_PREFIX_.'pdgoogleanalytycs4pro`
WHERE `id_order` = '.(int)$id_order
);
if (isset($res['refund_send'])) {
return $res['refund_send'];
} else {
return 2;
}
}
public static function installDB()
{
return Db::getInstance()->execute('
CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.'pdgoogleanalytycs4pro` (
`id_order` int(11) unsigned NOT NULL,
`client_id` varchar(64) NOT NULL,
`order_send` tinyint(1) NOT NULL DEFAULT \'0\',
`refund_send` tinyint(1) NOT NULL DEFAULT \'0\',
`to_refund` tinyint(1) NOT NULL DEFAULT \'0\',
`date_add` datetime,
`date_upd` datetime,
PRIMARY KEY (`id_order`)
) ENGINE='._MYSQL_ENGINE_.' DEFAULT CHARSET=utf8;
');
}
public static function uninstallDB()
{
return Db::getInstance()->execute('DROP TABLE IF EXISTS `'._DB_PREFIX_.'pdgoogleanalytycs4pro`');
}
}

View File

@@ -0,0 +1,95 @@
<?php
/**
* 2012-2015 Patryk Marek PrestaDev.pl
*
* Patryk Marek PrestaDev.pl - PD Facebook Pixel Tracking © All rights reserved.
*
* DISCLAIMER
*
* Do not edit, modify or copy this file.
* If you wish to customize it, contact us at info@prestadev.pl.
*
* @author Patryk Marek PrestaDev.pl <info@prestadev.pl>
* @copyright 2012-2015 Patryk Marek - PrestaDev.pl
* @link http://prestadev.pl
* @package PD Facebook Pixel Tracking PrestaShop 1.5.x and 1.6.x Module
* @version 1.1.1
* @license License is for use in domain / or one multistore enviroment (do not modify or reuse this code or part of it) if you want any changes please contact with me at info@prestadev.pl
* @date 24-05-2016
*/
class PdGA4PRegistrationModel extends ObjectModel
{
public $id_customer;
public $registered;
public $registered_send;
public $date_add = '0000-00-00 00:00:00';
public $date_upd = '0000-00-00 00:00:00';
public static $definition = array(
'table' => 'pdgoogleanalytycs4pro_registration',
'primary' => 'id_customer',
'multilang' => false,
'fields' => array(
'id_customer' => array('type' => self::TYPE_INT, 'validate' => 'isunsignedInt', 'required' => false),
'registered' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => false),
'registered_send' => array('type' => self::TYPE_BOOL, 'validate' => 'isBool', 'required' => false),
'date_add' => array('type' => self::TYPE_DATE, 'validate' => 'isDateFormat', 'required' => false),
'date_upd' => array('type' => self::TYPE_DATE, 'validate' => 'isDateFormat', 'required' => false)
)
);
public function __construct($id_customer)
{
parent::__construct($id_customer);
}
public function add($autodate = true, $null_values = false)
{
return parent::add($autodate, $null_values);
}
public function delete()
{
if ((int)$this->id_customer === 0) {
return false;
}
return parent::delete();
}
public function update($null_values = false)
{
if ((int)$this->id_customer === 0) {
return false;
}
return parent::update($null_values);
}
public static function getRegisteredValueByIdCustomer($id_customer)
{
return Db::getInstance()->getValue('
SELECT `registered` FROM `'._DB_PREFIX_.'pdgoogleanalytycs4pro_registration`
WHERE `id_customer` = '.(int)$id_customer.'
AND `registered_send` = 0
');
}
public static function installDB()
{
return Db::getInstance()->execute('
CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.'pdgoogleanalytycs4pro_registration` (
`id_customer` int(11) unsigned NOT NULL,
`registered` tinyint(1) NOT NULL DEFAULT \'0\',
`registered_send` tinyint(1) NOT NULL DEFAULT \'0\',
`date_add` datetime,
`date_upd` datetime,
PRIMARY KEY (`id_customer`)
) ENGINE='._MYSQL_ENGINE_.' DEFAULT CHARSET=utf8;
');
}
public static function uninstallDB()
{
return Db::getInstance()->execute('DROP TABLE IF EXISTS `'._DB_PREFIX_.'pdgoogleanalytycs4pro_registration`');
}
}

View File

@@ -0,0 +1,29 @@
<?php
/**
* 2012-2020 Patryk Marek PrestaDev
*
* Patryk Marek PrestaDev - PD Ceneo Zaufane Opinie Pro PrestaShop 1.6.x and 1.7.x Module © All rights reserved.
*
* DISCLAIMER
*
* Do not edit, modify or copy this file.
* If you wish to customize it, contact us at PrestaShop Addons.
*
* @author Patryk Marek PrestaDev
* @copyright 2012-2020 Patryk Marek - PrestaDev
* @license License is for use in domain / or one multistore enviroment (do not modify or reuse this code or part of it)
* @link http://prestadev.pl
* @package PD Ceneo Zaufane Opinie Pro PrestaShop 1.6.x and 1.7.x Module
* @version 2.0.0
* @date 24-12-2020
*/
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
header("Location: ../");
exit;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
<?php
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header('Last-Modified: ' . gmdate('D, d M Y H:i:s') . ' GMT');
header('Cache-Control: no-store, no-cache, must-revalidate');
header('Cache-Control: post-check=0, pre-check=0', false);
header('Pragma: no-cache');
header('Location: ../');
exit;

View File

@@ -0,0 +1,46 @@
<?php
global $_MODULE;
$_MODULE = array();
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_310a8b8f327ecb8718da0bd984e27d05'] = 'Google Analytycs 4 Pro';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_1c881f09b830bc74ead7559810f34ae3'] = 'Moduł który dodaje kod Google Analytycs 4.0 wraz z obsługą zdarzeń do Twojego sklepu internetowego.';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_221f06bbdab8b6141a0abe23b334cd7f'] = 'Musisz podać Twoje ID Google Analytycs 4.0 (identyfikator pomiaru)';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_2e8516350cba2d9049c31c2f28b9d71f'] = 'Musisz podać swój tajny klucz Google Analytics API, jeśli chcesz wysyłać transakcje po zmianie statusu zamówienia.';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_c888438d14855d7d96a2724ee9c306bd'] = 'Zapisano ustawienia';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_b04f2c8a90cfc485fc990dc8dc4ba293'] = 'Konfiguracja modułu';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_287944d00092b1014de3ec670ae8d4f2'] = 'Google Analytics 4 konfiguracja';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_57186f4322f21b8c5dc883f79fe1f5ab'] = 'Google Ads konwersja sprzedaży';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_2d3514c95b0aeea99bb4524888b5e044'] = 'Ustawienia transakcji zakupowych';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_35bd1e8cfa88ae6c94617636a81e7e26'] = 'Ustawienia zwrotów zamówień';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_b3424032d63e1f3b3dd647cd8d666fcc'] = 'Identyfikator pomiaru 1';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_3a17e9c1f323c37e7ec64162ec7c5308'] = 'Proszę wpisać identyfikator GA4 1, przykład: G-LS3XNT1111, znajdziesz je w interfejsie Google Analytics 4 w sekcji: Administracja > Strumienie danych > wybierz strumień > Identyfikator pomiaru';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_6ec0e11f9b28feb6a719eb1d19c9b996'] = 'Identyfikator pomiaru 2';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_30a364a305c823c5881401052bc7cfd2'] = 'Wpisz identyfikator GA4 2, w celu agencji lub innej potrzeby śledzenia 2 kont, np.: G-LS3XNT2222, znajdziesz je w interfejsie Google Analytics 4 w sekcji: Administracja > Strumienie danych > Wybierz strumień > Identyfikator pomiaru';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_6751922766e5430784cf141ced1efe59'] = 'Wyślij odwiedzenie strony';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_8f7f330c9e7a93adfa8bdb563f1931ef'] = 'Wysłać wyświetlenie strony do Google Analytics? jeśli nie chcesz, aby fragment wysyłał informację o odsłonie strony do Google Analytics, wyłącz tę opcję';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_93cba07454f06a4a960172bbd6e2a435'] = 'Tak';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_bafd7322c6e97d25b6299b5d6fe8920b'] = 'Nie';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_fbe7293c25867c05c1c78d6ff7f4a329'] = 'Id śledzenia konwersji Gogole Ads / Adwords';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_7df7c6c0ca5c563ad98e8bc771d5f904'] = 'Opcjonalnie, proszę podać identyfikator konwersji Google Ads / Adwords ID Chcesz śledzić konwersje Ads / Adwords, to pole jest opcjonalne, jeśli jest to konieczne, na przykład: AW-LS3XNT2222';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_c76ffc322ff254ff6302ddcc310ff136'] = 'Etykieta konwersji Gogole Ads / Adwords';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_aa802b4030d65c6e65a39897e26665df'] = 'Wprowadź etykietę dla tej konwersji jeśli śledzić konwersje Ads / Adwords, etykieta to kod alfanumeryczny wygenerowany przez Google we fragmencie kodu zdarzenia, np. AW-123456789/1A234C56789, gdzie ciąg po znaku „/”, czyli 1A234C56789, to etykieta konwersji)';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_58756ac4a56abc2ce6819ad610ab234b'] = 'Identyfikator produktu';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_7ddde2ab33a6f0de7544ab7ba63d2a78'] = 'Możesz wybrać, który identyfikator produktu chcemy przekazać jako item_id (identyfikator produktu w zdarzeniu) do Google Analitycs, jeśli musi być zgodny z identyfikatorami produktów w fedzie produktowym.';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_4bacd7eee0c76aa2b36699cc9706bbec'] = 'Id produktu (domyślne)';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_b563fabd188a59a9418aa3cc2d8672ed'] = 'id produktu - id atrybutu produktu (123-123)';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_770c4233b6e15b72434a0000e81355a2'] = 'id produktu _ id atrybutu produktu (123_123)';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_75ed578ac3cb02b0ba40002a25bc0403'] = 'Kod referencyjny / index produktu';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_cadc9536d156fbdef84b16dec722a7d5'] = 'Kod EAN';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_6f0b1a4c017d8b1fedd36ed7a9d05025'] = 'Jak wysłać szczegóły transakcji / zamówienia do GA4';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_014d2e21f3d3201a59c207aa7a94b43f'] = 'Wybierz, czy moduł ma wysyłać transakcję do Google Analytics 4 na stronie potwierdzenia zamówienia, gdy klient wróci z bramki płatności lub w przypadku zmiany statusu wybranego zamówienia';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_dcfe3e49062276a0366db71aef988138'] = 'Wyślij na stronie potwierdzenia zamówienia';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_73ec7f4aa1ddb9f616eb66fcdace940e'] = 'Wyślij po zmianie statusu zamówienia';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_38e72015c9065380053dde63862c3b42'] = 'Google Analytics 4 Klucz API Secret';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_be3336669c31c11ff9107ee31e5df62d'] = 'Proszę wprowadzić tajny klucz API Analytics 4, sklucz API znajdziesz w interfejsie Google Analytics 4 w sekcji: Administracja > Strumienie danych > wybierz strumień > Protokół pomiarowy > Utwórz, opcja służy do śledzenia transakcji php przy zmianie statusu zamówienia';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_eb98fcc6563c3e210ad0c709c8924c07'] = 'Statusy zamówień, aby wysłać zamówienie';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_bbdd92e0bdcee7529a7bbbf10db9e3dd'] = 'Statusy zamówień, aby wysłać zamówienie do Google Analytics w przypadku zmiany statusu zamówienia (zamówienia są wysyłane przez PHP)';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_3a1df2f681b30a7f3775164bb59effd5'] = 'Zezwalaj na konwersje rozszerzone';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_d692d52119acbd8493630540294c52ce'] = 'Zezwalaj na konwersje rozszerzone, dodając dane użytkownika do zdarzeń takich jak np.: telefon, adres e-mail, adres klienta';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_4652a52040c46b76301373f8dcfc0510'] = 'Status zamówienia do zwrotów';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_9a8d53e1fd8f6bb0c77c7aa939d8e1de'] = 'Po przypisaniu tego statusu na zamówieniu spowoduje wysłanie zwrotu transakcji zakupu w GA4';
$_MODULE['<{pdgoogleanalytycs4pro}prestashop>pdgoogleanalytycs4pro_d4dccb8ca2dac4e53c01bd9954755332'] = 'Zapisz ustawienia';

View File

@@ -0,0 +1,35 @@
<?php
/*
* 2007-2015 PrestaShop
*
* NOTICE OF LICENSE
*
* This source file is subject to the Academic Free License (AFL 3.0)
* that is bundled with this package in the file LICENSE.txt.
* It is also available through the world-wide-web at this URL:
* http://opensource.org/licenses/afl-3.0.php
* If you did not receive a copy of the license and are unable to
* obtain it through the world-wide-web, please send an email
* to license@prestashop.com so we can send you a copy immediately.
*
* DISCLAIMER
*
* Do not edit or add to this file if you wish to upgrade PrestaShop to newer
* versions in the future. If you wish to customize PrestaShop for your
* needs please refer to http://www.prestashop.com for more information.
*
* @author PrestaShop SA <contact@prestashop.com>
* @copyright 2007-2015 PrestaShop SA
* @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
* International Registered Trademark & Property of PrestaShop SA
*/
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header("Last-Modified: ".gmdate("D, d M Y H:i:s")." GMT");
header("Cache-Control: no-store, no-cache, must-revalidate");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
header("Location: ../");
exit;

View File

@@ -0,0 +1,38 @@
<?php
/**
* 2012-2022 Patryk Marek PrestaDev.pl
*
* Patryk Marek PrestaDev.pl - PD Google Analytycs 4 Pro 1.6.x and 1.7.x Module © All rights reserved.
*
* DISCLAIMER
*
* Do not edit, modify or copy this file.
* If you wish to customize it, contact us at info@prestadev.pl.
*
* @author Patryk Marek <info@prestadev.pl>
* @copyright 2012-2022 Patryk Marek @ PrestaDev.pl
* @license Do not edit, modify or copy this file, if you wish to customize it, contact us at info@prestadev.pl.
* @link http://prestadev.pl
* @package PD Google Analytycs 4 Pro 1.6.x and 1.7.x Module
* @version 1.0.2
* @date 01-05-2021
*/
if (!defined('_PS_VERSION_')) {
exit;
}
require_once(dirname(__FILE__).'../../models/PdGA4PModel.php');
require_once(dirname(__FILE__).'../../models/PdGA4PRegistrationModel.php');
function upgrade_module_1_1_0($module)
{
$module->registerHook('actionProductSearchAfter');
$module->registerHook('actionOrderStatusPostUpdate');
$module->registerHook('actionObjectOrderAddAfter');
$module->registerHook('actionCustomerAccountAdd');
PdGA4PModel::installDB();
PdGA4PRegistrationModel::installDB();
return true;
}

View File

@@ -0,0 +1,29 @@
<?php
/**
* 2012-2022 Patryk Marek PrestaDev.pl
*
* Patryk Marek PrestaDev.pl - PD Google Analytycs 4 Pro 1.6.x and 1.7.x Module © All rights reserved.
*
* DISCLAIMER
*
* Do not edit, modify or copy this file.
* If you wish to customize it, contact us at info@prestadev.pl.
*
* @author Patryk Marek <info@prestadev.pl>
* @copyright 2012-2022 Patryk Marek @ PrestaDev.pl
* @license Do not edit, modify or copy this file, if you wish to customize it, contact us at info@prestadev.pl.
* @link http://prestadev.pl
* @package PD Google Analytycs 4 Pro 1.6.x and 1.7.x Module
* @version 1.0.2
* @date 01-05-2021
*/
if (!defined('_PS_VERSION_')) {
exit;
}
function upgrade_module_1_1_1($module)
{
$module->registerHook('displayAfterBodyOpeningTag');
return true;
}

View File

@@ -0,0 +1,29 @@
<?php
/**
* 2012-2022 Patryk Marek PrestaDev.pl
*
* Patryk Marek PrestaDev.pl - PD Google Analytycs 4 Pro 1.6.x and 1.7.x Module © All rights reserved.
*
* DISCLAIMER
*
* Do not edit, modify or copy this file.
* If you wish to customize it, contact us at info@prestadev.pl.
*
* @author Patryk Marek <info@prestadev.pl>
* @copyright 2012-2022 Patryk Marek @ PrestaDev.pl
* @license Do not edit, modify or copy this file, if you wish to customize it, contact us at info@prestadev.pl.
* @link http://prestadev.pl
* @package PD Google Analytycs 4 Pro 1.6.x and 1.7.x Module
* @version 1.0.2
* @date 01-05-2021
*/
if (!defined('_PS_VERSION_')) {
exit;
}
function upgrade_module_1_1_4($module)
{
Configuration::updateValue('PD_GA4P_GOOGLE_ANAL_NO_DELIVERY', 0);
return true;
}

View File

@@ -0,0 +1,35 @@
<?php
/**
* 2012-2022 Patryk Marek PrestaDev.pl
*
* Patryk Marek PrestaDev.pl - PD Google Analytycs 4 Pro 1.6.x and 1.7.x Module © All rights reserved.
*
* DISCLAIMER
*
* Do not edit, modify or copy this file.
* If you wish to customize it, contact us at info@prestadev.pl.
*
* @author Patryk Marek <info@prestadev.pl>
* @copyright 2012-2022 Patryk Marek @ PrestaDev.pl
* @license Do not edit, modify or copy this file, if you wish to customize it, contact us at info@prestadev.pl.
* @link http://prestadev.pl
* @package PD Google Analytycs 4 Pro 1.6.x and 1.7.x Module
* @version 1.0.2
* @date 01-05-2021
*/
if (!defined('_PS_VERSION_')) {
exit;
}
function upgrade_module_1_1_9($module)
{
Db::getInstance(_PS_USE_SQL_SLAVE_)->Execute('ALTER TABLE `'._DB_PREFIX_.'pdgoogleanalytycs4pro` ADD `client_id` varchar(64) NOT NULL');
Configuration::updateValue('PD_GA4P_OS_SEND_ORDER', '5,11,2');
Configuration::updateValue('PD_GA4P_TRANSACTION_SEND_TYPE', 1);
Configuration::updateValue('PD_GA4P_GOOGLE_ANAL_API_SECRET', '');
Configuration::updateValue('PD_GA4P_GOOGLE_ANAL_AEC', 1);
return true;
}

View File

@@ -0,0 +1,10 @@
# Apache 2.2
<IfModule !mod_authz_core.c>
Order deny,allow
Deny from all
</IfModule>
# Apache 2.4
<IfModule mod_authz_core.c>
Require all denied
</IfModule>

View File

@@ -0,0 +1,7 @@
<?php
// autoload.php @generated by Composer
require_once __DIR__ . '/composer/autoload_real.php';
return ComposerAutoloaderInit2e04d69c8d2e7acdacaf965c4df1ec3c::getLoader();

View File

@@ -0,0 +1 @@
service_name: travis-ci

View File

@@ -0,0 +1,14 @@
# Drupal editor configuration normalization
# @see http://editorconfig.org/
# This is the top-most .editorconfig file; do not search in parent directories.
root = true
# All files.
[*]
end_of_line = LF
indent_style = space
indent_size = 4
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

View File

@@ -0,0 +1,5 @@
composer.phar
composer.lock
/vendor/
.idea
.DS_Store

View File

@@ -0,0 +1,14 @@
# .travis.yml
language: php
php:
- 7.4
install:
- curl -s http://getcomposer.org/installer | php
- php composer.phar update --dev --no-interaction
script:
- mkdir -p build/logs
- XDEBUG_MODE=coverage vendor/bin/phpunit -c phpunit.xml.dist
after_success:
- travis_retry php vendor/bin/php-coveralls

View File

@@ -0,0 +1,249 @@
# Google Analytics 4 Measurement Protocol PHP Library
[![Coverage Status](https://coveralls.io/repos/github/br33f/php-GA4-Measurement-Protocol/badge.svg?branch=master)](https://coveralls.io/github/br33f/php-GA4-Measurement-Protocol?branch=master)
[![Latest Stable Version](https://poser.pugx.org/br33f/php-ga4-mp/v/stable.png)](https://packagist.org/packages/br33f/php-ga4-mp)
[![Total Downloads](https://poser.pugx.org/br33f/php-ga4-mp/downloads.png)](https://packagist.org/packages/br33f/php-ga4-mp)
## Overview
This is a PHP Library facilitating the use of Google Analytics 4 (GA4) Measurement Protocol. Measurement Protocol allows developers to send events directly from server-side PHP to Google Analytics.
Full documentation is available here:
https://developers.google.com/analytics/devguides/collection/protocol/ga4
## Requirements
- PHP >= 7.1
- ext-json
- guzzlehttp/guzzle: ^6.5.5 || ^7.0.0
dev:
- phpunit/phpunit: "^9.5"
- fakerphp/faker: "^1.14"
## Installation
The recommended way to install this library is via [Composer](https://getcomposer.org/ "Composer") (packagist package: [br33f/php-ga4-mp](https://packagist.org/packages/br33f/php-ga4-mp "br33f/php-ga4-mp")).
Install by composer command:
```
composer require br33f/php-ga4-mp
```
or `package.json`
```
{
"require": {
"br33f/php-ga4-mp": "^0.1.0"
}
}
```
## Usage
### Send View Item Event
```php
use Br33f\Ga4\MeasurementProtocol\Service;
use Br33f\Ga4\MeasurementProtocol\Dto\Request\BaseRequest;
use Br33f\Ga4\MeasurementProtocol\Dto\Event\ViewItemEvent;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\ItemParameter;
// Create service instance
$ga4Service = new Service('MEASUREMENT_PROTOCOL_API_SECRET');
$ga4Service->setMeasurementId('MEASUREMENT_ID');
// Create base request
$baseRequest = new BaseRequest();
$baseRequest->setClientId('CLIENT_ID');
// Create Event Data
$viewItemEventData = new ViewItemEvent();
$viewItemEventData
->setValue(51.10)
->setCurrency('EUR');
// Create Item
$viewedItem = new ItemParameter();
$viewedItem
->setItemId('ITEM_ID')
->setItemName('ITEM_NAME')
->setPrice(25.55)
->setQuantity(2);
// Add this item to viewItemEventData
$viewItemEventData->addItem($viewedItem);
// Add event to base request (you can add up to 25 events to single request)
$baseRequest->addEvent($viewItemEventData);
// We have all the data we need. Just send the request.
$ga4Service->send($baseRequest);
```
### Send Purchase Event
```php
use Br33f\Ga4\MeasurementProtocol\Service;
use Br33f\Ga4\MeasurementProtocol\Dto\Request\BaseRequest;
use Br33f\Ga4\MeasurementProtocol\Dto\Event\PurchaseEvent;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\ItemParameter;
// Create service instance
$ga4Service = new Service('MEASUREMENT_PROTOCOL_API_SECRET');
$ga4Service->setMeasurementId('MEASUREMENT_ID');
// Create base request
$baseRequest = new BaseRequest();
$baseRequest->setClientId('CLIENT_ID');
// Create Event Data
$purchaseEventData = new PurchaseEvent();
$purchaseEventData
->setValue(250.00)
->setCurrency('USD');
// Create Item
$purchasedItem1 = new ItemParameter();
$purchasedItem1
->setItemId('FIRST_ITEM_ID')
->setItemName('FIRST_ITEM_NAME')
->setPrice(100.00)
->setQuantity(2);
// Add this item to purchaseEventData
$purchaseEventData->addItem($purchasedItem1);
// You can also fill item data via constructor
$purchaseEventData->addItem(new ItemParameter([
'item_id' => 'SECOND_ITEM_ID',
'item_name' => 'SECOND_ITEM_NAME',
'price' => 50.00,
'quantity' => 1
]));
// Add event to base request (you can add up to 25 events to single request)
$baseRequest->addEvent($purchaseEventData);
// We have all the data we need. Just send the request.
$ga4Service->send($baseRequest);
```
At the moment, the library contains the defined structures of the following events:
| Event name | Structure | Documentation |
| ---------- | --------- | --------------|
| add_payment_info | AddPaymentInfoEvent | [see documentation](https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference/events#add_payment_info)
| add_shipping_info | AddShippingInfoEvent | [see documentation](https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference/events#add_shipping_info)
| add_to_cart | AddToCartEvent | [see documentation](https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference/events#add_to_cart)
| begin_checkout | BeginCheckoutEvent | [see documentation](https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference/events#begin_checkout)
| login | LoginEvent | [see documentation](https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference/events#login)
| purchase | PurchaseEvent | [see documentation](https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference/events#purchase)
| refund | RefundEvent | [see documentation](https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference/events#refund)
| remove_from_cart | RemoveFromCartEvent | [see documentation](https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference/events#remove_from_cart)
| search | SearchEvent | [see documentation](https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference/events#search)
| select_item | SelectItemEvent | [see documentation](https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference/events#select_item)
| sign_up | SignUpEvent | [see documentation](https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference/events#sign_up)
| view_cart | ViewCartEvent | [see documentation](https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference/events#view_cart)
| view_item | ViewItemEvent | [see documentation](https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference/events#view_item)
| view_search_results | ViewSearchResultsEvent | [see documentation](https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference/events#view_search_results)
These events are sent analogously to the examples presented above.
### Other events
In order to send any event one can use `BaseEvent` structure and add any data. Please note that specific event structure should be used instead if already defined, since BaseEvent does not force any structure or provide data validation.
```php
use Br33f\Ga4\MeasurementProtocol\Service;
use Br33f\Ga4\MeasurementProtocol\Dto\Request\BaseRequest;
use Br33f\Ga4\MeasurementProtocol\Dto\Event\BaseEvent;
// Create Service and request same as above
// ...
// Create Base Event Data (for example: 'share' event - https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference/events#share)
$eventName = 'share';
$anyEventData = new BaseEvent($eventName);
$anyEventData
->setMethod('Twitter')
->setContentType('Post')
->setItemId('example_item_id')
->setAnyParamYouWish('test'); // means 'any_param_you_wish' is set
// Add event to base request (you can add up to 25 events to single request) and send, same as above
// ...
```
### Firebase Support
It is possible to use this library to send Firebase events. To do so, just initialize Service and BaseRequest as in following example:
```php
use Br33f\Ga4\MeasurementProtocol\Service;
use Br33f\Ga4\MeasurementProtocol\Dto\Request\BaseRequest;
// Create service instance
$ga4Service = new Service('MEASUREMENT_PROTOCOL_API_SECRET');
$ga4Service->setFirebaseId('FIREBASE_APP_ID'); // instead of setMeasurementId(...)
// Create base request
$baseRequest = new BaseRequest();
$baseRequest->setAppInstanceId('APP_INSTANCE_ID'); // instead of setClientId(...)
```
## Debug event data and requests
Debuging event data is possible by sending them to debug endpoint (Measurement Protocol Validation Server), since default endpoint for Google Analytics 4 Measurement Protocol does not return any HTTP error codes or messages. In order to validate event one should use `sendDebug($request)` method instead of `send($request)`.
Method `sendDebug($request)` returns `DebugResponse` object, which is hydrated with response data such as: `status_code` and `validation_messages`.
### Example:
```php
use Br33f\Ga4\MeasurementProtocol\Service;
use Br33f\Ga4\MeasurementProtocol\Dto\Request\BaseRequest;
use Br33f\Ga4\MeasurementProtocol\Dto\Event\AddToCartEvent;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\ItemParameter;
// Create service instance
$ga4Service = new Service('MEASUREMENT_PROTOCOL_API_SECRET');
$ga4Service->setMeasurementId('MEASUREMENT_ID');
// Create base request
$baseRequest = new BaseRequest();
$baseRequest->setClientId('CLIENT_ID');
// Create Invalid Event Data
$addToCartEventData = new AddToCartEvent();
$addToCartEventData
->setValue(99.99)
->setCurrency('SOME_INVALID_CURRENCY_CODE'); // invalid currency code
// addItem
$addToCartEventData->addItem(new ItemParameter([
'item_id' => 'ITEM_ID',
'item_name' => 'ITEM_NAME',
'price' => 99.99,
'quantity' => 1
]));
// Add event to base request (you can add up to 25 events to single request)
$baseRequest->addEvent($addToCartEventData);
// Instead of sending data to production Measurement Protocol endpoint
// $ga4Service->send($baseRequest);
// Send data to validation endpoint, which responds with status cude and validation messages.
$debugResponse = $ga4Service->sendDebug($baseRequest);
// Now debug response contains status code, and validation messages if request is invalid
var_dump($debugResponse->getStatusCode());
var_dump($debugResponse->getValidationMessages());
```
## Unit Testing
Unit Testing for this module is done using PHPUnit 9.
Running unit tests:
```
composer install
php vendor/bin/phpunit
```
## License
This library is released under the MIT License.

View File

@@ -0,0 +1,32 @@
{
"name": "br33f/php-ga4-mp",
"description": "PHP GoogleAnalytics4 Measurement Protocol Library",
"minimum-stability": "stable",
"license": "MIT",
"authors": [
{
"name": "Damian Zamojski",
"email": "damian.zamojski1@gmail.com"
}
],
"require": {
"php": ">=7.1",
"guzzlehttp/guzzle": "^6.5.5 || ^7.0.0",
"ext-json": "*"
},
"autoload": {
"psr-4": {
"Br33f\\Ga4\\MeasurementProtocol\\": "src/"
}
},
"require-dev": {
"phpunit/phpunit": "^9.5",
"fakerphp/faker": "^1.14",
"php-coveralls/php-coveralls": "^2.4"
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
}
}

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.5/phpunit.xsd"
bootstrap="vendor/autoload.php"
cacheResultFile=".phpunit.cache/test-results"
executionOrder="depends,defects"
forceCoversAnnotation="false"
beStrictAboutCoversAnnotation="true"
beStrictAboutOutputDuringTests="true"
beStrictAboutTodoAnnotatedTests="true"
failOnRisky="true"
failOnWarning="false"
verbose="true">
<testsuites>
<testsuite name="default">
<directory>tests</directory>
</testsuite>
</testsuites>
<coverage cacheDirectory=".phpunit.cache/code-coverage"
processUncoveredFiles="true">
<include>
<directory suffix=".php">src</directory>
</include>
<report>
<clover outputFile="build/logs/clover.xml"></clover>
</report>
</coverage>
</phpunit>

View File

@@ -0,0 +1,78 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 22.06.2021
* Time: 13:51
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto\Common;
use Br33f\Ga4\MeasurementProtocol\Dto\Event\AbstractEvent;
use Br33f\Ga4\MeasurementProtocol\Dto\ExportableInterface;
use Br33f\Ga4\MeasurementProtocol\Dto\ValidateInterface;
use Br33f\Ga4\MeasurementProtocol\Enum\ErrorCode;
use Br33f\Ga4\MeasurementProtocol\Exception\ValidationException;
use InvalidArgumentException;
class EventCollection implements ExportableInterface, ValidateInterface
{
/**
* @var AbstractEvent[]
*/
protected $eventList = [];
/**
* @param AbstractEvent $event
*/
public function addEvent(AbstractEvent $event)
{
if (count($this->eventList) >= 25) {
throw new InvalidArgumentException('Event list must not exceed 25 items', ErrorCode::MAX_EVENT_COUNT_EXCEED);
}
$this->eventList[] = $event;
}
/**
* @return array
*/
public function export(): array
{
return array_map(function ($userProperty) {
return $userProperty->export();
}, $this->getEventList());
}
/**
* @return array
*/
public function getEventList(): array
{
return $this->eventList;
}
/**
* @param array $eventList
*/
public function setEventList(array $eventList)
{
if (count($eventList) > 25) {
throw new InvalidArgumentException('Event list must not exceed 25 items', ErrorCode::MAX_EVENT_COUNT_EXCEED);
}
$this->eventList = $eventList;
}
/**
* @throws ValidationException
*/
public function validate()
{
if (count($this->getEventList()) === 0) {
throw new ValidationException('Event list must not be empty', ErrorCode::VALIDATION_EVENTS_MUST_NOT_BE_EMPTY, 'events');
}
return true;
}
}

View File

@@ -0,0 +1,62 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 22.06.2021
* Time: 12:23
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto\Common;
use Br33f\Ga4\MeasurementProtocol\Dto\ExportableInterface;
class UserProperties implements ExportableInterface
{
/**
* @var UserProperty[]
*/
protected $userPropertiesList;
/**
* UserProperties constructor.
* @param UserProperty[] $userPropertiesList
*/
public function __construct(array $userPropertiesList = null)
{
$this->userPropertiesList = $userPropertiesList ?? [];
}
/**
* @param UserProperty $userProperty
*/
public function addUserProperty(UserProperty $userProperty)
{
$this->userPropertiesList[] = $userProperty;
}
/**
* @return array
*/
public function export(): array
{
return array_reduce($this->getUserPropertiesList(), function ($last, UserProperty $userProperty) {
return array_merge($last, $userProperty->export());
}, []);
}
/**
* @return UserProperty[]
*/
public function getUserPropertiesList(): array
{
return $this->userPropertiesList;
}
/**
* @param UserProperty[] $userPropertiesList
*/
public function setUserPropertiesList(array $userPropertiesList)
{
$this->userPropertiesList = $userPropertiesList;
}
}

View File

@@ -0,0 +1,78 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 22.06.2021
* Time: 12:23
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto\Common;
use Br33f\Ga4\MeasurementProtocol\Dto\ExportableInterface;
class UserProperty implements ExportableInterface
{
/**
* User property name
* @var string
*/
protected $name;
/**
* User property value
* @var mixed
*/
protected $value;
/**
* UserProperty constructor.
* @param string|null $name
* @param mixed $value
*/
public function __construct(?string $name = null, $value = null)
{
$this->name = $name;
$this->value = $value;
}
public function export(): array
{
return [
$this->getName() => [
'value' => $this->getValue()
]
];
}
/**
* @return string|null
*/
public function getName(): ?string
{
return $this->name;
}
/**
* @param string|null $name
*/
public function setName(?string $name)
{
$this->name = $name;
}
/**
* @return mixed
*/
public function getValue()
{
return $this->value;
}
/**
* @param mixed $value
*/
public function setValue($value)
{
$this->value = $value;
}
}

View File

@@ -0,0 +1,102 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 22.06.2021
* Time: 12:23
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto\Common;
use Br33f\Ga4\MeasurementProtocol\Dto\HydratableInterface;
use Br33f\Ga4\MeasurementProtocol\Enum\ValidationCode;
use Psr\Http7\Message\ResponseInterface;
class ValidationMessage implements HydratableInterface
{
/**
* The path to the field that was invalid
* @var string|null
*/
protected $fieldPath;
/**
* A description of the error
* @var string|null
*/
protected $description;
/**
* A ValidationCode that corresponds to the error
* @var string|null
* @see ValidationCode
*/
protected $validationCode;
/**
* ValidationMessage constructor.
* @param array|null $blueprint
*/
public function __construct(?array $blueprint = null)
{
if ($blueprint !== null) {
$this->hydrate($blueprint);
}
}
/**
* @param array|ResponseInterface $blueprint
*/
public function hydrate($blueprint)
{
$this->setFieldPath(array_key_exists('fieldPath', $blueprint) ? $blueprint['fieldPath'] : null);
$this->setDescription(array_key_exists('description', $blueprint) ? $blueprint['description'] : null);
$this->setValidationCode(array_key_exists('validationCode', $blueprint) ? $blueprint['validationCode'] : null);
}
/**
* @return string|null
*/
public function getFieldPath(): ?string
{
return $this->fieldPath;
}
/**
* @param string|null $fieldPath
*/
public function setFieldPath(?string $fieldPath)
{
$this->fieldPath = $fieldPath;
}
/**
* @return string|null
*/
public function getDescription(): ?string
{
return $this->description;
}
/**
* @param string|null $description
*/
public function setDescription(?string $description)
{
$this->description = $description;
}
/**
* @return string|null
*/
public function getValidationCode(): ?string
{
return $this->validationCode;
}
/**
* @param string|null $validationCode
*/
public function setValidationCode(?string $validationCode)
{
$this->validationCode = $validationCode;
}
}

View File

@@ -0,0 +1,195 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 22.06.2021
* Time: 14:16
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto\Event;
use BadMethodCallException;
use Br33f\Ga4\MeasurementProtocol\Dto\ExportableInterface;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\AbstractParameter;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\BaseParameter;
use Br33f\Ga4\MeasurementProtocol\Dto\ValidateInterface;
use InvalidArgumentException;
abstract class AbstractEvent implements ExportableInterface, ValidateInterface
{
/**
* @var string
*/
protected $name;
/**
* @var AbstractParameter[]
*/
protected $paramList;
/**
* AbstractEvent constructor.
* @param string|null $name
* @param AbstractParameter[] $paramList
*/
public function __construct(?string $name = null, array $paramList = [])
{
$this->name = $name;
$this->paramList = $paramList ?? [];
}
/**
* @param string $methodName
* @param array $methodArguments
* @return mixed|null
*/
public function __call(string $methodName, array $methodArguments)
{
$methodPrefix = substr($methodName, 0, 3);
$paramName = $this->convertCamelCaseToSnakeCase(substr($methodName, 3));
if ($methodPrefix === "set") {
if (!isset($methodArguments[0])) {
throw new InvalidArgumentException('First argument is expected to be paramter value, none specified.');
}
return $this->setParamValue($paramName, $methodArguments[0]);
}
if ($methodPrefix === "get") {
return $this->getParamValue($paramName);
}
throw new BadMethodCallException('Method ' . $methodName . ' is not defined.');
}
/**
* @param string $input
* @return string
*/
protected function convertCamelCaseToSnakeCase(string $input)
{
preg_match_all('!([A-Z][A-Z0-9]*(?=$|[A-Z][a-z0-9])|[A-Za-z][a-z0-9]+)!', $input, $matches);
$ret = $matches[0];
foreach ($ret as &$match) {
$match = $match == strtoupper($match) ? strtolower($match) : lcfirst($match);
}
return implode('_', $ret);
}
/**
* @param string $paramName
* @param mixed $paramValue
* @return AbstractEvent
*/
public function setParamValue(string $paramName, $paramValue)
{
$this->findOrCreateParameter($paramName)->setValue($paramValue);
return $this;
}
/**
* @param string $paramName
* @return AbstractParameter
*/
public function findOrCreateParameter(string $paramName)
{
$foundParameter = $this->findParameter($paramName);
if ($foundParameter === null) {
$foundParameter = new BaseParameter();
$this->addParam($paramName, $foundParameter);
}
return $foundParameter;
}
/**
* @param string $paramName
* @return AbstractParameter|null
*/
public function findParameter(string $paramName)
{
if (array_key_exists($paramName, $this->getParamList())) {
return $this->getParamList()[$paramName];
} else {
return null;
}
}
/**
* @return AbstractParameter[]
*/
public function getParamList(): array
{
return $this->paramList;
}
/**
* @param AbstractParameter[] $paramList
*/
public function setParamList(array $paramList)
{
$this->paramList = $paramList;
}
/**
* @param string $parameterName
* @param AbstractParameter $parameter
*/
public function addParam(string $parameterName, AbstractParameter $parameter)
{
$this->paramList[$parameterName] = $parameter;
}
/**
* @param string $paramName
* @return mixed|null
*/
public function getParamValue(string $paramName)
{
return $this->findOrCreateParameter($paramName)->getValue();
}
/**
* @param string $paramName
*/
public function deleteParameter(string $paramName)
{
if (array_key_exists($paramName, $this->getParamList())) {
unset($this->paramList[$paramName]);
}
}
public function export(): array
{
$preparedParams = [];
foreach ($this->getParamList() as $parameterName => $parameter) {
$parameterExportedValue = $parameter->export();
if (!is_null($parameterExportedValue)) {
$preparedParams[$parameterName] = $parameterExportedValue;
}
}
return [
'name' => $this->getName(),
// Note that we need to return an \ArrayObject here. As otherwise json_encode will serialize params to `[]`. And
// Google Analytics will error on this, as it expects a map. Whereas new \ArrayObject will export correctly to `{}`.
// See https://github.com/br33f/php-GA4-Measurement-Protocol/issues/10.
'params' => new \ArrayObject($preparedParams),
];
}
/**
* @return string|null
*/
public function getName(): ?string
{
return $this->name;
}
/**
* @param string|null $name
*/
protected function setName(?string $name)
{
$this->name = $name;
}
}

View File

@@ -0,0 +1,51 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 25.06.2021
* Time: 13:33
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto\Event;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\AbstractParameter;
use Br33f\Ga4\MeasurementProtocol\Enum\ErrorCode;
use Br33f\Ga4\MeasurementProtocol\Exception\ValidationException;
/**
* Class AddPaymentInfoEvent
* @package Br33f\Ga4\MeasurementProtocol\Dto\Event
* @method string getCurrency()
* @method AddPaymentInfoEvent setCurrency(string $currency)
* @method float getValue()
* @method AddPaymentInfoEvent setValue(float $value)
* @method string getCoupon()
* @method AddPaymentInfoEvent setCoupon(string $coupon)
* @method string getPaymentType()
* @method AddPaymentInfoEvent setPaymentType(string $paymentType)
*/
class AddPaymentInfoEvent extends ItemBaseEvent
{
private $eventName = 'add_payment_info';
/**
* AddPaymentInfoEvent constructor.
* @param AbstractParameter[] $paramList
*/
public function __construct(array $paramList = [])
{
parent::__construct($this->eventName, $paramList);
}
public function validate()
{
parent::validate();
if (!empty($this->getValue())) {
if (empty($this->getCurrency())) {
throw new ValidationException('Field "currency" is required if "value" is set', ErrorCode::VALIDATION_FIELD_REQUIRED, 'currency');
}
}
return true;
}
}

View File

@@ -0,0 +1,51 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 25.06.2021
* Time: 13:33
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto\Event;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\AbstractParameter;
use Br33f\Ga4\MeasurementProtocol\Enum\ErrorCode;
use Br33f\Ga4\MeasurementProtocol\Exception\ValidationException;
/**
* Class AddShippingInfoEvent
* @package Br33f\Ga4\MeasurementProtocol\Dto\Event
* @method string getCurrency()
* @method AddShippingInfoEvent setCurrency(string $currency)
* @method float getValue()
* @method AddShippingInfoEvent setValue(float $value)
* @method string getCoupon()
* @method AddShippingInfoEvent setCoupon(string $coupon)
* @method string getShippingTier()
* @method AddShippingInfoEvent setShippingTier(string $shippingTier)
*/
class AddShippingInfoEvent extends ItemBaseEvent
{
private $eventName = 'add_shipping_info';
/**
* AddShippingInfoEvent constructor.
* @param AbstractParameter[] $paramList
*/
public function __construct(array $paramList = [])
{
parent::__construct($this->eventName, $paramList);
}
public function validate()
{
parent::validate();
if (!empty($this->getValue())) {
if (empty($this->getCurrency())) {
throw new ValidationException('Field "currency" is required if "value" is set', ErrorCode::VALIDATION_FIELD_REQUIRED, 'currency');
}
}
return true;
}
}

View File

@@ -0,0 +1,47 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 25.06.2021
* Time: 13:33
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto\Event;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\AbstractParameter;
use Br33f\Ga4\MeasurementProtocol\Enum\ErrorCode;
use Br33f\Ga4\MeasurementProtocol\Exception\ValidationException;
/**
* Class AddToCartEvent
* @package Br33f\Ga4\MeasurementProtocol\Dto\Event
* @method string getCurrency()
* @method AddToCartEvent setCurrency(string $currency)
* @method float getValue()
* @method AddToCartEvent setValue(float $value)
*/
class AddToCartEvent extends ItemBaseEvent
{
private $eventName = 'add_to_cart';
/**
* AddToCartEvent constructor.
* @param AbstractParameter[] $paramList
*/
public function __construct(array $paramList = [])
{
parent::__construct($this->eventName, $paramList);
}
public function validate()
{
parent::validate();
if (!empty($this->getValue())) {
if (empty($this->getCurrency())) {
throw new ValidationException('Field "currency" is required if "value" is set', ErrorCode::VALIDATION_FIELD_REQUIRED, 'currency');
}
}
return true;
}
}

View File

@@ -0,0 +1,34 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 22.06.2021
* Time: 13:52
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto\Event;
use Br33f\Ga4\MeasurementProtocol\Exception\ValidationException;
class BaseEvent extends AbstractEvent
{
/**
* @param string|null $name
*/
public function setName(?string $name)
{
parent::setName($name);
}
/**
* @return bool
* @throws ValidationException
*/
public function validate()
{
foreach ($this->getParamList() as $parameter) {
$parameter->validate();
}
return true;
}
}

View File

@@ -0,0 +1,49 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 25.06.2021
* Time: 13:33
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto\Event;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\AbstractParameter;
use Br33f\Ga4\MeasurementProtocol\Enum\ErrorCode;
use Br33f\Ga4\MeasurementProtocol\Exception\ValidationException;
/**
* Class AddToCartEvent
* @package Br33f\Ga4\MeasurementProtocol\Dto\Event
* @method string getCurrency()
* @method BeginCheckoutEvent setCurrency(string $currency)
* @method float getValue()
* @method BeginCheckoutEvent setValue(float $value)
* @method string getCoupon()
* @method BeginCheckoutEvent setCoupon(string $coupon)
*/
class BeginCheckoutEvent extends ItemBaseEvent
{
private $eventName = 'begin_checkout';
/**
* BeginCheckoutEvent constructor.
* @param AbstractParameter[] $paramList
*/
public function __construct(array $paramList = [])
{
parent::__construct($this->eventName, $paramList);
}
public function validate()
{
parent::validate();
if (!empty($this->getValue())) {
if (empty($this->getCurrency())) {
throw new ValidationException('Field "currency" is required if "value" is set', ErrorCode::VALIDATION_FIELD_REQUIRED, 'currency');
}
}
return true;
}
}

View File

@@ -0,0 +1,67 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 25.06.2021
* Time: 13:25
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto\Event;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\ItemCollectionParameter;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\ItemParameter;
use Br33f\Ga4\MeasurementProtocol\Exception\ValidationException;
/**
* Class ItemBaseEvent
* @package Br33f\Ga4\MeasurementProtocol\Dto\Event
*/
abstract class ItemBaseEvent extends AbstractEvent
{
/**
* @param ItemParameter $item
* @return self
*/
public function addItem(ItemParameter $item)
{
$this->getItems()->addItem($item);
return $this;
}
/**
* @return ItemCollectionParameter
*/
public function getItems()
{
$items = $this->findParameter('items');
if ($items === null) {
$items = new ItemCollectionParameter();
$this->setItems($items);
}
return $items;
}
/**
* @param ItemCollectionParameter|null $items
* @return self
*/
public function setItems(?ItemCollectionParameter $items)
{
$this->deleteParameter('items');
$this->addParam('items', $items);
return $this;
}
/**
* @return bool
* @throws ValidationException
*/
public function validate()
{
$this->getItems()->validate();
return true;
}
}

View File

@@ -0,0 +1,38 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 25.06.2021
* Time: 13:52
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto\Event;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\AbstractParameter;
/**
* Class LoginEvent
* @package Br33f\Ga4\MeasurementProtocol\Dto\Event
* @method string getMethod()
* @method LoginEvent setMethod(string $method)
*/
class LoginEvent extends AbstractEvent
{
private $eventName = 'login';
/**
* LoginEvent constructor.
* @param AbstractParameter[] $paramList
*/
public function __construct(array $paramList = [])
{
parent::__construct($this->eventName, $paramList);
}
/**
* @return bool
*/
public function validate()
{
return true;
}
}

View File

@@ -0,0 +1,61 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 25.06.2021
* Time: 13:33
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto\Event;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\AbstractParameter;
use Br33f\Ga4\MeasurementProtocol\Enum\ErrorCode;
use Br33f\Ga4\MeasurementProtocol\Exception\ValidationException;
/**
* Class PurchaseEvent
* @package Br33f\Ga4\MeasurementProtocol\Dto\Event
* @method string getCurrency()
* @method PurchaseEvent setCurrency(string $currency)
* @method string getTransactionId()
* @method PurchaseEvent setTransactionId(string $transactionId)
* @method float getValue()
* @method PurchaseEvent setValue(float $value)
* @method string getAffiliation()
* @method PurchaseEvent setAffiliation(string $affiliation)
* @method string getCoupon()
* @method PurchaseEvent setCoupon(string $coupon)
* @method float getShipping()
* @method PurchaseEvent setShipping(float $shipping)
* @method float getTax()
* @method PurchaseEvent setTax(float $tax)
*/
class PurchaseEvent extends ItemBaseEvent
{
private $eventName = 'purchase';
/**
* PurchaseEvent constructor.
* @param AbstractParameter[] $paramList
*/
public function __construct(array $paramList = [])
{
parent::__construct($this->eventName, $paramList);
}
public function validate()
{
parent::validate();
if (empty($this->getTransactionId())) {
throw new ValidationException('Field "transaction_id" is required if "value" is set', ErrorCode::VALIDATION_FIELD_REQUIRED, 'curtransaction_idrency');
}
if (!empty($this->getValue())) {
if (empty($this->getCurrency())) {
throw new ValidationException('Field "currency" is required if "value" is set', ErrorCode::VALIDATION_FIELD_REQUIRED, 'currency');
}
}
return true;
}
}

View File

@@ -0,0 +1,61 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 25.06.2021
* Time: 13:33
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto\Event;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\AbstractParameter;
use Br33f\Ga4\MeasurementProtocol\Enum\ErrorCode;
use Br33f\Ga4\MeasurementProtocol\Exception\ValidationException;
/**
* Class RefundEvent
* @package Br33f\Ga4\MeasurementProtocol\Dto\Event
* @method string getCurrency()
* @method RefundEvent setCurrency(string $currency)
* @method string getTransactionId()
* @method RefundEvent setTransactionId(string $transactionId)
* @method float getValue()
* @method RefundEvent setValue(float $value)
* @method string getAffiliation()
* @method RefundEvent setAffiliation(string $affiliation)
* @method string getCoupon()
* @method RefundEvent setCoupon(string $coupon)
* @method float getShipping()
* @method RefundEvent setShipping(float $shipping)
* @method float getTax()
* @method RefundEvent setTax(float $tax)
*/
class RefundEvent extends ItemBaseEvent
{
private $eventName = 'refund';
/**
* RefundEvent constructor.
* @param AbstractParameter[] $paramList
*/
public function __construct(array $paramList = [])
{
parent::__construct($this->eventName, $paramList);
}
public function validate()
{
parent::validate();
if (empty($this->getTransactionId())) {
throw new ValidationException('Field "transaction_id" is required if "value" is set', ErrorCode::VALIDATION_FIELD_REQUIRED, 'curtransaction_idrency');
}
if (!empty($this->getValue())) {
if (empty($this->getCurrency())) {
throw new ValidationException('Field "currency" is required if "value" is set', ErrorCode::VALIDATION_FIELD_REQUIRED, 'currency');
}
}
return true;
}
}

View File

@@ -0,0 +1,47 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 25.06.2021
* Time: 13:33
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto\Event;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\AbstractParameter;
use Br33f\Ga4\MeasurementProtocol\Enum\ErrorCode;
use Br33f\Ga4\MeasurementProtocol\Exception\ValidationException;
/**
* Class RemoveFromCartEvent
* @package Br33f\Ga4\MeasurementProtocol\Dto\Event
* @method string getCurrency()
* @method RemoveFromCartEvent setCurrency(string $currency)
* @method float getValue()
* @method RemoveFromCartEvent setValue(float $value)
*/
class RemoveFromCartEvent extends ItemBaseEvent
{
private $eventName = 'remove_from_cart';
/**
* AddToCartEvent constructor.
* @param AbstractParameter[] $paramList
*/
public function __construct(array $paramList = [])
{
parent::__construct($this->eventName, $paramList);
}
public function validate()
{
parent::validate();
if (!empty($this->getValue())) {
if (empty($this->getCurrency())) {
throw new ValidationException('Field "currency" is required if "value" is set', ErrorCode::VALIDATION_FIELD_REQUIRED, 'currency');
}
}
return true;
}
}

View File

@@ -0,0 +1,45 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 25.06.2021
* Time: 13:52
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto\Event;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\AbstractParameter;
use Br33f\Ga4\MeasurementProtocol\Enum\ErrorCode;
use Br33f\Ga4\MeasurementProtocol\Exception\ValidationException;
/**
* Class SearchEvent
* @package Br33f\Ga4\MeasurementProtocol\Dto\Event
* @method string getSearchTerm()
* @method SearchEvent setSearchTerm(string $searchTerm)
*/
class SearchEvent extends AbstractEvent
{
private $eventName = 'search';
/**
* SearchEvent constructor.
* @param AbstractParameter[] $paramList
*/
public function __construct(array $paramList = [])
{
parent::__construct($this->eventName, $paramList);
}
/**
* @return bool
* @throws ValidationException
*/
public function validate()
{
if (empty($this->getSearchTerm())) {
throw new ValidationException('Field "search_term" is required if "value" is set', ErrorCode::VALIDATION_FIELD_REQUIRED, 'search_term');
}
return true;
}
}

View File

@@ -0,0 +1,32 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 25.06.2021
* Time: 13:33
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto\Event;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\AbstractParameter;
/**
* Class SelectItemEvent
* @package Br33f\Ga4\MeasurementProtocol\Dto\Event
* @method string getItemListId()
* @method SelectItemEvent setItemListId(string $itemListId)
* @method string getItemListName()
* @method SelectItemEvent setItemListName(string $itemListName)
*/
class SelectItemEvent extends ItemBaseEvent
{
private $eventName = 'select_item';
/**
* SelectItemEvent constructor.
* @param AbstractParameter[] $paramList
*/
public function __construct(array $paramList = [])
{
parent::__construct($this->eventName, $paramList);
}
}

View File

@@ -0,0 +1,38 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 25.06.2021
* Time: 13:52
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto\Event;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\AbstractParameter;
/**
* Class SignUpEvent
* @package Br33f\Ga4\MeasurementProtocol\Dto\Event
* @method string getMethod()
* @method SignUpEvent setMethod(string $method)
*/
class SignUpEvent extends AbstractEvent
{
private $eventName = 'sign_up';
/**
* SignUpEvent constructor.
* @param AbstractParameter[] $paramList
*/
public function __construct(array $paramList = [])
{
parent::__construct($this->eventName, $paramList);
}
/**
* @return bool
*/
public function validate()
{
return true;
}
}

View File

@@ -0,0 +1,47 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 25.06.2021
* Time: 13:33
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto\Event;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\AbstractParameter;
use Br33f\Ga4\MeasurementProtocol\Enum\ErrorCode;
use Br33f\Ga4\MeasurementProtocol\Exception\ValidationException;
/**
* Class ViewCartEvent
* @package Br33f\Ga4\MeasurementProtocol\Dto\Event
* @method string getCurrency()
* @method ViewCartEvent setCurrency(string $currency)
* @method float getValue()
* @method ViewCartEvent setValue(float $value)
*/
class ViewCartEvent extends ItemBaseEvent
{
private $eventName = 'view_cart';
/**
* ViewCartEvent constructor.
* @param AbstractParameter[] $paramList
*/
public function __construct(array $paramList = [])
{
parent::__construct($this->eventName, $paramList);
}
public function validate()
{
parent::validate();
if (!empty($this->getValue())) {
if (empty($this->getCurrency())) {
throw new ValidationException('Field "currency" is required if "value" is set', ErrorCode::VALIDATION_FIELD_REQUIRED, 'currency');
}
}
return true;
}
}

View File

@@ -0,0 +1,32 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 24.06.2021
* Time: 15:22
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto\Event;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\AbstractParameter;
/**
* Class ViewItemEvent
* @package Br33f\Ga4\MeasurementProtocol\Dto\Event
* @method string getCurrency()
* @method ViewItemEvent setCurrency(string $currency)
* @method string getValue()
* @method ViewItemEvent setValue(string $value)
*/
class ViewItemEvent extends ItemBaseEvent
{
private $eventName = 'view_item';
/**
* ViewItemEvent constructor.
* @param AbstractParameter[] $paramList
*/
public function __construct(array $paramList = [])
{
parent::__construct($this->eventName, $paramList);
}
}

View File

@@ -0,0 +1,32 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 25.06.2021
* Time: 13:33
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto\Event;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\AbstractParameter;
/**
* Class ViewItemListEvent
* @package Br33f\Ga4\MeasurementProtocol\Dto\Event
* @method string getItemListId()
* @method ViewItemListEvent setItemListId(string $itemListId)
* @method string getItemListName()
* @method ViewItemListEvent setItemListName(string $itemListName)
*/
class ViewItemListEvent extends ItemBaseEvent
{
private $eventName = 'view_item_list';
/**
* ViewItemListEvent constructor.
* @param AbstractParameter[] $paramList
*/
public function __construct(array $paramList = [])
{
parent::__construct($this->eventName, $paramList);
}
}

View File

@@ -0,0 +1,30 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 25.06.2021
* Time: 13:33
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto\Event;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\AbstractParameter;
/**
* Class ViewSearchResultsEvent
* @package Br33f\Ga4\MeasurementProtocol\Dto\Event
* @method string getSearchTerm()
* @method ViewSearchResultsEvent setSearchTerm(string $itemListId)
*/
class ViewSearchResultsEvent extends ItemBaseEvent
{
private $eventName = 'view_search_results';
/**
* ViewSearchResultsEvent constructor.
* @param AbstractParameter[] $paramList
*/
public function __construct(array $paramList = [])
{
parent::__construct($this->eventName, $paramList);
}
}

View File

@@ -0,0 +1,17 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 22.06.2021
* Time: 11:10
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto;
interface ExportableInterface
{
/**
* Method returns prepared data
* @return mixed
*/
public function export();
}

View File

@@ -0,0 +1,21 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 22.06.2021
* Time: 13:42
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto;
use Br33f\Ga4\MeasurementProtocol\Exception\HydrationException;
use Psr\Http7\Message\ResponseInterface;
interface HydratableInterface
{
/**
* Method hydrates DTO with data from blueprint
* @param ResponseInterface|array $blueprint
* @throws HydrationException
*/
public function hydrate($blueprint);
}

View File

@@ -0,0 +1,15 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 22.06.2021
* Time: 13:56
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto\Parameter;
use Br33f\Ga4\MeasurementProtocol\Dto\ExportableInterface;
use Br33f\Ga4\MeasurementProtocol\Dto\ValidateInterface;
abstract class AbstractParameter implements ExportableInterface, ValidateInterface
{
}

View File

@@ -0,0 +1,63 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 22.06.2021
* Time: 13:56
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto\Parameter;
use Br33f\Ga4\MeasurementProtocol\Dto\ExportableInterface;
class BaseParameter extends AbstractParameter
{
/**
* @var mixed
*/
protected $value;
/**
* BaseParameter constructor.
* @param mixed|null $value
*/
public function __construct($value = null)
{
$this->value = $value;
}
/**
* @return mixed
*/
public function export()
{
if ($this->getValue() instanceof ExportableInterface) {
return $this->getValue()->export();
} else {
return $this->getValue();
}
}
/**
* @return mixed
*/
public function getValue()
{
return $this->value;
}
/**
* @param mixed $value
*/
public function setValue($value)
{
$this->value = $value;
}
/**
* @return bool
*/
public function validate()
{
return true;
}
}

View File

@@ -0,0 +1,86 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 24.06.2021
* Time: 15:40
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto\Parameter;
use Br33f\Ga4\MeasurementProtocol\Exception\ValidationException;
/**
* Class ItemCollectionParameter
* @package Br33f\Ga4\MeasurementProtocol\Dto\Parameter
*/
class ItemCollectionParameter extends AbstractParameter
{
/**
* @var ItemParameter[]
*/
protected $itemList;
/**
* ItemCollectionParameter constructor.
* @param ItemParameter[]|null $itemList
*/
public function __construct(?array $itemList = [])
{
$this->itemList = $itemList;
}
/**
* @param ItemParameter $item
* @return ItemCollectionParameter
*/
public function addItem(ItemParameter $item)
{
$this->itemList[] = $item;
return $this;
}
/**
* @return bool
* @throws ValidationException
*/
public function validate()
{
foreach ($this->getItemList() as $item) {
$item->validate();
}
return true;
}
/**
* @return ItemParameter[]
*/
public function getItemList(): array
{
return $this->itemList;
}
/**
* @param ItemParameter[] $itemList
* @return ItemCollectionParameter
*/
public function setItemList(array $itemList)
{
$this->itemList = $itemList;
return $this;
}
/**
* @return array
*/
public function export()
{
$exportableObject = [];
foreach ($this->getItemList() as $item) {
$exportableObject[] = $item->export();
}
return $exportableObject;
}
}

View File

@@ -0,0 +1,626 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 24.06.2021
* Time: 15:40
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto\Parameter;
use Br33f\Ga4\MeasurementProtocol\Dto\HydratableInterface;
use Br33f\Ga4\MeasurementProtocol\Enum\ErrorCode;
use Br33f\Ga4\MeasurementProtocol\Exception\ValidationException;
/**
* Class ItemParameter
* @package Br33f\Ga4\MeasurementProtocol\Dto\Parameter
*/
class ItemParameter extends AbstractParameter implements HydratableInterface
{
/**
* The ID of the item
* One of itemId or itemName is required.
* @var string|null
*/
protected $itemId;
/**
* The name of the item
* One of itemId or itemName is required.
* @var string|null
*/
protected $itemName;
/**
* A product affiliation to designate a supplying company or brick and mortar store location
* Not required
* @var string|null
*/
protected $affiliation;
/**
* The coupon name/code associated with the item
* Not required
* @var string|null
*/
protected $coupon;
/**
* The currency in 3-lettery ISO 4217 format
* Not required
* @var string|null
*/
protected $currency;
/**
* The monetary discount value associated with the item
* Not required
* @var float|null
*/
protected $discount;
/**
* The index/position of the item in a list
* Not required
* @var float|null
*/
protected $index;
/**
* The brand of the item
* Not required
* @var string|null
*/
protected $itemBrand;
/**
* The category of the item.
* If used as part of a category hierarchy or taxonomy then this will be the first category.
* Not required
* @var string|null
*/
protected $itemCategory;
/**
* The second category of the item.
* If used as part of a category hierarchy or taxonomy then this will be the first category.
* Not required
* @var string|null
*/
protected $itemCategory2;
/**
* The third category of the item.
* If used as part of a category hierarchy or taxonomy then this will be the first category.
* Not required
* @var string|null
*/
protected $itemCategory3;
/**
* The fourth category of the item.
* If used as part of a category hierarchy or taxonomy then this will be the first category.
* Not required
* @var string|null
*/
protected $itemCategory4;
/**
* The fifth category of the item.
* If used as part of a category hierarchy or taxonomy then this will be the first category.
* Not required
* @var string|null
*/
protected $itemCategory5;
/**
* The ID of the list in which the item was presented to the user
* Not required
* @var string|null
*/
protected $itemListId;
/**
* The name of the list in which the item was presented to the user
* Not required
* @var string|null
*/
protected $itemListName;
/**
* The item variant or unique code or description for additional item details/options.
* Not required
* @var string|null
*/
protected $itemVariant;
/**
* The location associated with the item. It's recommended to use the Google Place ID that corresponds to the associated item. A custom location ID can also be used
* Not required
* @var string|null
*/
protected $locationId;
/**
* The monetary price of the item, in units of the specified currency parameter
* Not required
* @var float|null
*/
protected $price;
/**
* Item quantity
* Not required
* @var float|null
*/
protected $quantity;
/**
* ItemParameter constructor.
* @param array|null $blueprint
*/
public function __construct(?array $blueprint = null)
{
if ($blueprint !== null) {
$this->hydrate($blueprint);
}
}
/**
* @param array $blueprint
*/
public function hydrate($blueprint)
{
if (array_key_exists('item_id', $blueprint)) {
$this->setItemId($blueprint['item_id']);
}
if (array_key_exists('item_name', $blueprint)) {
$this->setItemName($blueprint['item_name']);
}
if (array_key_exists('affiliation', $blueprint)) {
$this->setAffiliation($blueprint['affiliation']);
}
if (array_key_exists('coupon', $blueprint)) {
$this->setCoupon($blueprint['coupon']);
}
if (array_key_exists('currency', $blueprint)) {
$this->setCurrency($blueprint['currency']);
}
if (array_key_exists('discount', $blueprint)) {
$this->setDiscount($blueprint['discount']);
}
if (array_key_exists('index', $blueprint)) {
$this->setIndex($blueprint['index']);
}
if (array_key_exists('item_brand', $blueprint)) {
$this->setItemBrand($blueprint['item_brand']);
}
if (array_key_exists('item_category', $blueprint)) {
$this->setItemCategory($blueprint['item_category']);
}
if (array_key_exists('item_category2', $blueprint)) {
$this->setItemCategory2($blueprint['item_category2']);
}
if (array_key_exists('item_category3', $blueprint)) {
$this->setItemCategory3($blueprint['item_category3']);
}
if (array_key_exists('item_category4', $blueprint)) {
$this->setItemCategory4($blueprint['item_category4']);
}
if (array_key_exists('item_category5', $blueprint)) {
$this->setItemCategory5($blueprint['item_category5']);
}
if (array_key_exists('item_list_id', $blueprint)) {
$this->setItemListId($blueprint['item_list_id']);
}
if (array_key_exists('item_list_name', $blueprint)) {
$this->setItemListName($blueprint['item_list_name']);
}
if (array_key_exists('item_variant', $blueprint)) {
$this->setItemVariant($blueprint['item_variant']);
}
if (array_key_exists('location_id', $blueprint)) {
$this->setLocationId($blueprint['location_id']);
}
if (array_key_exists('price', $blueprint)) {
$this->setPrice($blueprint['price']);
}
if (array_key_exists('quantity', $blueprint)) {
$this->setQuantity($blueprint['quantity']);
}
}
/**
* @return bool
* @throws ValidationException
*/
public function validate()
{
if (empty($this->getItemId()) && empty($this->getItemName())) {
throw new ValidationException("At least one of item_id or item_name is required", ErrorCode::VALIDATION_ITEM_AT_LEAST_ITEM_ID_OR_ITEM_NAME_REQUIRED, 'item_id|item_name');
}
return true;
}
/**
* @return string|null
*/
public function getItemId(): ?string
{
return $this->itemId;
}
/**
* @param string|null $itemId
* @return ItemParameter
*/
public function setItemId(?string $itemId): ItemParameter
{
$this->itemId = $itemId;
return $this;
}
/**
* @return string|null
*/
public function getItemName(): ?string
{
return $this->itemName;
}
/**
* @param string|null $itemName
* @return ItemParameter
*/
public function setItemName(?string $itemName): ItemParameter
{
$this->itemName = $itemName;
return $this;
}
/**
* @return array
*/
public function export()
{
$exportableObject = [
'item_id' => $this->getItemId(),
'item_name' => $this->getItemName(),
'affiliation' => $this->getAffiliation(),
'coupon' => $this->getCoupon(),
'currency' => $this->getCurrency(),
'discount' => $this->getDiscount(),
'index' => $this->getIndex(),
'item_brand' => $this->getItemBrand(),
'item_category' => $this->getItemCategory(),
'item_category2' => $this->getItemCategory2(),
'item_category3' => $this->getItemCategory3(),
'item_category4' => $this->getItemCategory4(),
'item_category5' => $this->getItemCategory5(),
'item_list_id' => $this->getItemListId(),
'item_list_name' => $this->getItemListName(),
'item_variant' => $this->getItemVariant(),
'location_id' => $this->getLocationId(),
'price' => $this->getPrice(),
'quantity' => $this->getQuantity()
];
$preparedExportableObject = [];
foreach ($exportableObject as $exportableItemName => $exportableItemValue) {
if (!is_null($exportableItemValue)) {
$preparedExportableObject[$exportableItemName] = $exportableItemValue;
}
}
return $preparedExportableObject;
}
/**
* @return string|null
*/
public function getAffiliation(): ?string
{
return $this->affiliation;
}
/**
* @param string|null $affiliation
* @return ItemParameter
*/
public function setAffiliation(?string $affiliation): ItemParameter
{
$this->affiliation = $affiliation;
return $this;
}
/**
* @return string|null
*/
public function getCoupon(): ?string
{
return $this->coupon;
}
/**
* @param string|null $coupon
* @return ItemParameter
*/
public function setCoupon(?string $coupon): ItemParameter
{
$this->coupon = $coupon;
return $this;
}
/**
* @return string|null
*/
public function getCurrency(): ?string
{
return $this->currency;
}
/**
* @param string|null $currency
* @return ItemParameter
*/
public function setCurrency(?string $currency): ItemParameter
{
$this->currency = $currency;
return $this;
}
/**
* @return float|null
*/
public function getDiscount(): ?float
{
return $this->discount;
}
/**
* @param float|null $discount
* @return ItemParameter
*/
public function setDiscount(?float $discount): ItemParameter
{
$this->discount = $discount;
return $this;
}
/**
* @return float|null
*/
public function getIndex(): ?float
{
return $this->index;
}
/**
* @param float|null $index
* @return ItemParameter
*/
public function setIndex(?float $index): ItemParameter
{
$this->index = $index;
return $this;
}
/**
* @return string|null
*/
public function getItemBrand(): ?string
{
return $this->itemBrand;
}
/**
* @param string|null $itemBrand
* @return ItemParameter
*/
public function setItemBrand(?string $itemBrand): ItemParameter
{
$this->itemBrand = $itemBrand;
return $this;
}
/**
* @return string|null
*/
public function getItemCategory(): ?string
{
return $this->itemCategory;
}
/**
* @param string|null $itemCategory
* @return ItemParameter
*/
public function setItemCategory(?string $itemCategory): ItemParameter
{
$this->itemCategory = $itemCategory;
return $this;
}
/**
* @return string|null
*/
public function getItemCategory2(): ?string
{
return $this->itemCategory2;
}
/**
* @param string|null $itemCategory2
* @return ItemParameter
*/
public function setItemCategory2(?string $itemCategory2): ItemParameter
{
$this->itemCategory2 = $itemCategory2;
return $this;
}
/**
* @return string|null
*/
public function getItemCategory3(): ?string
{
return $this->itemCategory3;
}
/**
* @param string|null $itemCategory3
* @return ItemParameter
*/
public function setItemCategory3(?string $itemCategory3): ItemParameter
{
$this->itemCategory3 = $itemCategory3;
return $this;
}
/**
* @return string|null
*/
public function getItemCategory4(): ?string
{
return $this->itemCategory4;
}
/**
* @param string|null $itemCategory4
* @return ItemParameter
*/
public function setItemCategory4(?string $itemCategory4): ItemParameter
{
$this->itemCategory4 = $itemCategory4;
return $this;
}
/**
* @return string|null
*/
public function getItemCategory5(): ?string
{
return $this->itemCategory5;
}
/**
* @param string|null $itemCategory5
* @return ItemParameter
*/
public function setItemCategory5(?string $itemCategory5): ItemParameter
{
$this->itemCategory5 = $itemCategory5;
return $this;
}
/**
* @return string|null
*/
public function getItemListId(): ?string
{
return $this->itemListId;
}
/**
* @param string|null $itemListId
* @return ItemParameter
*/
public function setItemListId(?string $itemListId): ItemParameter
{
$this->itemListId = $itemListId;
return $this;
}
/**
* @return string|null
*/
public function getItemListName(): ?string
{
return $this->itemListName;
}
/**
* @param string|null $itemListName
* @return ItemParameter
*/
public function setItemListName(?string $itemListName): ItemParameter
{
$this->itemListName = $itemListName;
return $this;
}
/**
* @return string|null
*/
public function getItemVariant(): ?string
{
return $this->itemVariant;
}
/**
* @param string|null $itemVariant
* @return ItemParameter
*/
public function setItemVariant(?string $itemVariant): ItemParameter
{
$this->itemVariant = $itemVariant;
return $this;
}
/**
* @return string|null
*/
public function getLocationId(): ?string
{
return $this->locationId;
}
/**
* @param string|null $locationId
* @return ItemParameter
*/
public function setLocationId(?string $locationId): ItemParameter
{
$this->locationId = $locationId;
return $this;
}
/**
* @return float|null
*/
public function getPrice(): ?float
{
return $this->price;
}
/**
* @param float|null $price
* @return ItemParameter
*/
public function setPrice(?float $price): ItemParameter
{
$this->price = $price;
return $this;
}
/**
* @return float|null
*/
public function getQuantity(): ?float
{
return $this->quantity;
}
/**
* @param float|null $quantity
* @return ItemParameter
*/
public function setQuantity(?float $quantity): ItemParameter
{
$this->quantity = $quantity;
return $this;
}
}

View File

@@ -0,0 +1,16 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 22.06.2021
* Time: 11:10
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto\Request;
use Br33f\Ga4\MeasurementProtocol\Dto\ExportableInterface;
use Br33f\Ga4\MeasurementProtocol\Dto\RequestValidateInterface;
abstract class AbstractRequest implements ExportableInterface, RequestValidateInterface
{
}

View File

@@ -0,0 +1,289 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 22.06.2021
* Time: 11:22
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto\Request;
use Br33f\Ga4\MeasurementProtocol\Dto\Common\EventCollection;
use Br33f\Ga4\MeasurementProtocol\Dto\Common\UserProperties;
use Br33f\Ga4\MeasurementProtocol\Dto\Common\UserProperty;
use Br33f\Ga4\MeasurementProtocol\Dto\Event\AbstractEvent;
use Br33f\Ga4\MeasurementProtocol\Enum\ErrorCode;
use Br33f\Ga4\MeasurementProtocol\Exception\ValidationException;
class BaseRequest extends AbstractRequest
{
/**
* Unique identifier of user instance.
* Required
* @var string
*/
protected $clientId = null;
/**
* App Instance ID.
* @var string
*/
protected $appInstanceId = null;
/**
* Unique identifier for a user.
* Not required
* @var string
*/
protected $userId;
/**
* An unix timestamp (microseconds) for the time to associate with the event.
* Not requied
* @var int
*/
protected $timestampMicros = null;
/**
* The user properties for the measurement.
* Not required
* @var UserProperties
*/
protected $userProperties = null;
/**
* If set true - indicates that events should not be use for personalized ads.
* Default false
* @var bool
*/
protected $nonPersonalizedAds = false;
/**
* Collection of event items. Maximum 25 events.
* Required
* @var EventCollection
*/
protected $events;
/**
* BaseRequest constructor.
* @param string|null $clientId
* @param AbstractEvent|EventCollection|null $events - Single Event or EventsCollection
*/
public function __construct(?string $clientId = null, $events = null)
{
if ($clientId !== null) {
@trigger_error('Creating a request by passing a web client ID to the constructor is deprecated in v0.1.3 and removed in v0.2.0. Use ::setClientId() or ::setAppInstanceId() directly, instead.', E_USER_DEPRECATED);
$this->clientId = $clientId;
}
if ($events !== null) {
if ($events instanceof EventCollection) {
$this->events = $events;
} else if ($events instanceof AbstractEvent) {
$this->events = new EventCollection();
$this->events->addEvent($events);
}
} else {
$this->events = new EventCollection();
}
}
/**
* @param UserProperty $userProperty
* @return BaseRequest
*/
public function addUserProperty(UserProperty $userProperty)
{
if ($this->getUserProperties() === null) {
$this->setUserProperties(new UserProperties());
}
$this->getUserProperties()->addUserProperty($userProperty);
return $this;
}
/**
* @return UserProperties|null
*/
public function getUserProperties(): ?UserProperties
{
return $this->userProperties;
}
/**
* @param UserProperties|null $userProperties
* @return BaseRequest
*/
public function setUserProperties(?UserProperties $userProperties)
{
$this->userProperties = $userProperties;
return $this;
}
/**
* @param AbstractEvent $event
* @return BaseRequest
*/
public function addEvent(AbstractEvent $event)
{
$this->getEvents()->addEvent($event);
return $this;
}
/**
* @return EventCollection
*/
public function getEvents(): EventCollection
{
return $this->events;
}
/**
* @param EventCollection $events
* @return BaseRequest
*/
public function setEvents(EventCollection $events)
{
$this->events = $events;
return $this;
}
/**
* @return array
*/
public function export(): array
{
$exportBaseRequest = array_filter([
'client_id' => $this->getClientId(),
'app_instance_id' => $this->getAppInstanceId(),
'non_personalized_ads' => $this->isNonPersonalizedAds(),
'events' => $this->getEvents()->export(),
]);
if ($this->getUserId() !== null) {
$exportBaseRequest['user_id'] = $this->getUserId();
}
if ($this->getTimestampMicros() !== null) {
$exportBaseRequest['timestamp_micros'] = $this->getTimestampMicros();
}
if ($this->getUserProperties() !== null) {
$exportBaseRequest['user_properties'] = $this->getUserProperties()->export();
}
return $exportBaseRequest;
}
/**
* @return string
*/
public function getClientId(): ?string
{
return $this->clientId;
}
/**
* @param string $clientId
* @return BaseRequest
*/
public function setClientId(string $clientId): self
{
$this->clientId = $clientId;
return $this;
}
/**
* @return string|null
*/
public function getAppInstanceId(): ?string
{
return $this->appInstanceId;
}
/**
* @param string $appInstanceId
* @return BaseRequest
*/
public function setAppInstanceId(string $appInstanceId): self
{
$this->appInstanceId = $appInstanceId;
return $this;
}
/**
* @return bool
*/
public function isNonPersonalizedAds(): bool
{
return $this->nonPersonalizedAds;
}
/**
* @param bool $nonPersonalizedAds
* @return BaseRequest
*/
public function setNonPersonalizedAds(bool $nonPersonalizedAds)
{
$this->nonPersonalizedAds = $nonPersonalizedAds;
return $this;
}
/**
* @return string|null
*/
public function getUserId(): ?string
{
return $this->userId;
}
/**
* @param string|null $userId
* @return BaseRequest
*/
public function setUserId(?string $userId)
{
$this->userId = $userId;
return $this;
}
/**
* @return ?int
*/
public function getTimestampMicros(): ?int
{
return $this->timestampMicros;
}
/**
* @param ?int $timestampMicros
* @return BaseRequest
*/
public function setTimestampMicros(?int $timestampMicros)
{
$this->timestampMicros = $timestampMicros;
return $this;
}
/**
* @param string|null $context Context for request, either 'web' or 'firebase'.
* @return bool
* @throws ValidationException
*/
public function validate(?string $context = 'web')
{
if ($context === 'web' && empty($this->getClientId())) {
throw new ValidationException('Parameter "client_id" is required.', ErrorCode::VALIDATION_CLIENT_ID_REQUIRED, 'client_id');
}
if ($context === 'firebase' && empty($this->getAppInstanceId())) {
throw new ValidationException('Parameter "app_instance_id" is required.', ErrorCode::VALIDATION_APP_INSTANCE_ID_REQUIRED, 'app_instance_id');
}
if ($this->getClientId() && $this->getAppInstanceId()) {
throw new ValidationException('Cannot specify both "client_id" and "app_instance_id".', ErrorCode::VALIDATION_CLIENT_IDENTIFIER_MISCONFIGURED);
}
$this->getEvents()->validate();
return true;
}
}

View File

@@ -0,0 +1,21 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 22.06.2021
* Time: 11:10
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto;
use Br33f\Ga4\MeasurementProtocol\Exception\ValidationException;
interface RequestValidateInterface
{
/**
* Method validates object. Throws exception if error, returns true if valid.
* @param string|null $context
* @return boolean
* @throws ValidationException
*/
public function validate(?string $context);
}

View File

@@ -0,0 +1,28 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 22.06.2021
* Time: 11:10
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto\Response;
use Br33f\Ga4\MeasurementProtocol\Dto\HydratableInterface;
use Br33f\Ga4\MeasurementProtocol\Exception\HydrationException;
use Psr\Http7\Message\ResponseInterface;
abstract class AbstractResponse implements HydratableInterface
{
/**
* AbstractResponse constructor.
* @param ResponseInterface|null $blueprint
* @throws HydrationException
*/
public function __construct(ResponseInterface $blueprint = null)
{
if ($blueprint !== null) {
$this->hydrate($blueprint);
}
}
}

View File

@@ -0,0 +1,77 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 22.06.2021
* Time: 11:10
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto\Response;
use Psr\Http7\Message\ResponseInterface;
class BaseResponse extends AbstractResponse
{
/**
* @var int|null
*/
protected $statusCode;
/**
* @var string
*/
protected $body;
/**
* @return int|null
*/
public function getStatusCode(): ?int
{
return $this->statusCode;
}
/**
* @param int|null $statusCode
* @return BaseResponse
*/
public function setStatusCode(?int $statusCode)
{
$this->statusCode = $statusCode;
return $this;
}
/**
* Get parsed body
* @return array
*/
public function getData()
{
return json_decode($this->getBody(), true);
}
/**
* @return string
*/
public function getBody(): string
{
return $this->body;
}
/**
* @param string $body
* @return BaseResponse
*/
public function setBody(string $body)
{
$this->body = $body;
return $this;
}
/**
* @param array|ResponseInterface $blueprint
*/
public function hydrate($blueprint)
{
$this->setStatusCode($blueprint->getStatusCode());
$this->setBody($blueprint->getBody()->getContents());
}
}

View File

@@ -0,0 +1,51 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 22.06.2021
* Time: 11:10
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto\Response;
use Br33f\Ga4\MeasurementProtocol\Dto\Common\ValidationMessage;
use Psr\Http7\Message\ResponseInterface;
class DebugResponse extends BaseResponse
{
/**
* @var ValidationMessage[]
*/
protected $validationMessages = [];
/**
* @return ValidationMessage[]
*/
public function getValidationMessages(): array
{
return $this->validationMessages;
}
/**
* @param ValidationMessage[] $validationMessages
* @return DebugResponse
*/
public function setValidationMessages(array $validationMessages)
{
$this->validationMessages = $validationMessages;
return $this;
}
/**
* @param array|ResponseInterface $blueprint
*/
public function hydrate($blueprint)
{
parent::hydrate($blueprint);
$validationMessages = [];
foreach ($this->getData()['validationMessages'] as $validationMessage) {
$validationMessages[] = new ValidationMessage($validationMessage);
}
$this->setValidationMessages($validationMessages);
}
}

View File

@@ -0,0 +1,20 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 22.06.2021
* Time: 11:10
*/
namespace Br33f\Ga4\MeasurementProtocol\Dto;
use Br33f\Ga4\MeasurementProtocol\Exception\ValidationException;
interface ValidateInterface
{
/**
* Method validates object. Throws exception if error, returns true if valid.
* @return boolean
* @throws ValidationException
*/
public function validate();
}

View File

@@ -0,0 +1,20 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 22.06.2021
* Time: 15:29
*/
namespace Br33f\Ga4\MeasurementProtocol\Enum;
class ErrorCode
{
const MAX_EVENT_COUNT_EXCEED = 100001;
const VALIDATION_CLIENT_ID_REQUIRED = 1000002;
const VALIDATION_EVENTS_MUST_NOT_BE_EMPTY = 1000003;
const VALIDATION_ITEM_AT_LEAST_ITEM_ID_OR_ITEM_NAME_REQUIRED = 1000004;
const VALIDATION_FIELD_REQUIRED = 1000005;
const VALIDATION_APP_INSTANCE_ID_REQUIRED = 1000006;
const VALIDATION_CLIENT_IDENTIFIER_MISCONFIGURED = 1000007;
}

View File

@@ -0,0 +1,19 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 24.06.2021
* Time: 13:49
*/
namespace Br33f\Ga4\MeasurementProtocol\Enum;
class ValidationCode
{
const VALUE_INVALID = 'VALUE_INVALID';
const VALUE_REQUIRED = 'VALUE_REQUIRED';
const NAME_INVALID = 'NAME_INVALID';
const NAME_RESERVED = 'NAME_RESERVED';
const VALUE_OUT_OF_BOUNDS = 'VALUE_OUT_OF_BOUNDS';
const EXCEEDED_MAX_ENTITIES = 'EXCEEDED_MAX_ENTITIES';
const NAME_DUPLICATED = 'NAME_DUPLICATED';
}

View File

@@ -0,0 +1,5 @@
<?php
namespace Br33f\Ga4\MeasurementProtocol\Exception;
abstract class AnalyticsException extends \Exception {};

View File

@@ -0,0 +1,16 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 22.06.2021
* Time: 11:20
*/
namespace Br33f\Ga4\MeasurementProtocol\Exception;
use Exception;
class HydrationException extends AnalyticsException
{
}

View File

@@ -0,0 +1,10 @@
<?php
namespace Br33f\Ga4\MeasurementProtocol\Exception;
use Exception;
class MisconfigurationException extends AnalyticsException
{
}

View File

@@ -0,0 +1,42 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 22.06.2021
* Time: 11:20
*/
namespace Br33f\Ga4\MeasurementProtocol\Exception;
use Exception;
use Throwable;
class ValidationException extends AnalyticsException
{
/**
* @var string|null
*/
protected $fieldName = null;
public function __construct($message = "", $code = 0, $fieldName = null, Throwable $previous = null)
{
parent::__construct($message, $code, $previous);
$this->fieldName = $fieldName;
}
/**
* @return string|null
*/
public function getFieldName(): ?string
{
return $this->fieldName;
}
/**
* @param string|null $fieldName
*/
public function setFieldName(?string $fieldName): void
{
$this->fieldName = $fieldName;
}
}

View File

@@ -0,0 +1,83 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 22.06.2021
* Time: 10:35
*/
namespace Br33f\Ga4\MeasurementProtocol;
use GuzzleHttp7\Client;
use GuzzleHttp7\Exception\BadResponseException;
use GuzzleHttp7\RequestOptions;
use Psr\Http7\Message\ResponseInterface;
class HttpClient
{
const DEFAULT_REQUEST_TIMEOUT = 30;
/**
* Guzzle Client
* @var Client
*/
protected $client;
/**
* Sends request to Google Analytics.
*
* @param string $url
* @param array $data
* @param array|null $options
* @return ResponseInterface
*/
public function post(string $url, array $data, ?array $options = [])
{
try {
return $this->getClient()->post($url, $this->getPreparedOptions($options, $data));
} catch (BadResponseException $e) {
return $e->getResponse();
}
}
/**
* Returns guzzle client if set or creates a new instance and returns it
* @return Client
*/
public function getClient(): Client
{
if ($this->client === null) {
$this->client = new Client();
}
return $this->client;
}
/**
* @param Client $client
*/
public function setClient(Client $client)
{
$this->client = $client;
}
/**
* @param $options
* @param $data
* @return array
*/
protected function getPreparedOptions($options, $data)
{
$options[RequestOptions::JSON] = $data;
if (!isset($options['timeout'])) {
$options['timeout'] = self::DEFAULT_REQUEST_TIMEOUT;
}
if (!isset($options['connect_timeout'])) {
$options['connect_timeout'] = self::DEFAULT_REQUEST_TIMEOUT;
}
return $options;
}
}

View File

@@ -0,0 +1,331 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 21.06.2021
* Time: 16:15
*/
namespace Br33f\Ga4\MeasurementProtocol;
use Br33f\Ga4\MeasurementProtocol\Dto\Request\AbstractRequest;
use Br33f\Ga4\MeasurementProtocol\Dto\Response\BaseResponse;
use Br33f\Ga4\MeasurementProtocol\Dto\Response\DebugResponse;
use Br33f\Ga4\MeasurementProtocol\Exception\MisconfigurationException;
class Service
{
const SSL_SCHEME = 'https://';
const NOT_SSL_SCHEME = 'http://';
const PREPENDED_WWW = 'www';
/**
* Indicates if connection to endpoint should be made with HTTPS (true) or HTTP (false)
* @var bool
*/
protected $useSsl = true;
/**
* Indicates if connection to endpoint should be made with prepended WWW
* @var bool
*/
protected $useWww = false;
/**
* Collect Endpoint
* @var string
*/
protected $collectEndpoint = 'google-analytics.com/mp/collect';
/**
* Collect Debug Endpoint. Used for validating events.
* @var string
*/
protected $collectDebugEndpoint = 'google-analytics.com/debug/mp/collect';
/**
* Http Client
* @var HttpClient
*/
protected $httpClient;
/**
* An API SECRET generated in the Google Analytics UI
* @var string
*/
protected $apiSecret = null;
/**
* The measurement ID associated with a data stream
* @var string
*/
protected $measurementId = null;
/**
* The Firebase App ID associated with a data stream
* @var string
*/
protected $firebaseId = null;
/**
* The custom ip address of the visitor
* @var string
*/
protected $ipOverride;
/**
* Http Options
* @var array
*/
protected $options;
/**
* Client constructor.
* @param string $apiSecret
* @param string|null $measurementId
*/
public function __construct(string $apiSecret, ?string $measurementId = null)
{
$this->setApiSecret($apiSecret);
if ($measurementId) {
@trigger_error('Creating a measurement service instance with a measurement ID passed to the constructor is deprecated in v0.1.3 and removed in v0.2.0. Use ::setMeasurementId() or ::setFirebaseId() directly, instead.', E_USER_DEPRECATED);
$this->setMeasurementId($measurementId);
}
}
/**
* @param AbstractRequest $request
* @param bool|null $debug
* @return BaseResponse
* @throws Exception\ValidationException
* @throws Exception\HydrationException
*/
public function send(AbstractRequest $request, ?bool $debug = false)
{
$request->validate($this->measurementId ? 'web' : 'firebase');
$response = $this->getHttpClient()->post($this->getEndpoint($debug), $request->export(), $this->getOptions());
return !$debug
? new BaseResponse($response)
: new DebugResponse($response);
}
/**
* @param AbstractRequest $request
* @return BaseResponse
* @throws Exception\ValidationException
* @throws Exception\HydrationException
*/
public function sendDebug(AbstractRequest $request)
{
return $this->send($request, true);
}
/**
* Returns Http Client if set or creates a new instance and returns it
* @return HttpClient
*/
public function getHttpClient(): HttpClient
{
if ($this->httpClient === null) {
$this->httpClient = new HttpClient();
}
return $this->httpClient;
}
/**
* @param HttpClient $httpClient
*/
public function setHttpClient(HttpClient $httpClient)
{
$this->httpClient = $httpClient;
}
/**
* Returns prepared endpoint url
* @return string
*/
public function getEndpoint(?bool $isDebug = false): string
{
$protocolScheme = $this->isUseSsl() ? self::SSL_SCHEME : self::NOT_SSL_SCHEME;
$collectEndpoint = $isDebug ? $this->getCollectDebugEndpoint() : $this->getCollectEndpoint();
$prependedWww = $this->isUseWww() ? (self::PREPENDED_WWW . '.') : '';
return $protocolScheme . $prependedWww . $collectEndpoint . "?" . http_build_query($this->getQueryParameters());
}
/**
* @return bool
*/
public function isUseSsl(): bool
{
return $this->useSsl;
}
/**
* @param bool $useSsl
*/
public function setUseSsl(bool $useSsl)
{
$this->useSsl = $useSsl;
}
/**
* @return bool
*/
public function isUseWww(): bool
{
return $this->useWww;
}
/**
* @param bool $useWww
*/
public function setUseWww(bool $useWww)
{
$this->useWww = $useWww;
}
/**
* @return string
*/
public function getCollectDebugEndpoint(): string
{
return $this->collectDebugEndpoint;
}
/**
* @param string $collectDebugEndpoint
*/
public function setCollectDebugEndpoint(string $collectDebugEndpoint)
{
$this->collectDebugEndpoint = $collectDebugEndpoint;
}
/**
* @return string
*/
public function getCollectEndpoint(): string
{
return $this->collectEndpoint;
}
/**
* @param string $collectEndpoint
*/
public function setCollectEndpoint(string $collectEndpoint)
{
$this->collectEndpoint = $collectEndpoint;
}
/**
* Returns query parameters
* @return array
* @throws MisconfigurationException
*/
public function getQueryParameters(): array
{
$parameters = [
'api_secret' => $this->getApiSecret(),
'measurement_id' => $this->getMeasurementId(),
'firebase_app_id' => $this->getFirebaseId(),
];
if ($parameters['firebase_app_id'] && $parameters['measurement_id']) {
throw new MisconfigurationException("Cannot specify both 'measurement_id' and 'firebase_app_id'.");
}
$ip = $this->getIpOverride();
if (!empty($ip)) {
$parameters['uip'] = $ip;
// TODO Remove the following line when the GA4 API will support the IP override
// https://github.com/dataunlocker/save-analytics-from-content-blockers/issues/25#issuecomment-864392422
$parameters['_uip'] = $ip;
}
return array_filter($parameters);
}
/**
* @return string
*/
public function getMeasurementId(): ?string
{
return $this->measurementId;
}
/**
* @param string $measurementId
* @return self
*/
public function setMeasurementId(string $measurementId): self
{
$this->measurementId = $measurementId;
return $this;
}
/**
* @return string|null
*/
public function getFirebaseId(): ?string
{
return $this->firebaseId;
}
/**
* @param string $firebaseId
* @return self
*/
public function setFirebaseId(string $firebaseId): self
{
$this->firebaseId = $firebaseId;
return $this;
}
/**
* @return string
*/
public function getApiSecret(): string
{
return $this->apiSecret;
}
/**
* @param string $apiSecret
*/
public function setApiSecret(string $apiSecret)
{
$this->apiSecret = $apiSecret;
}
/**
* @return string
*/
public function getIpOverride(): ?string
{
return $this->ipOverride;
}
/**
* @param string $ipOverride
*/
public function setIpOverride(string $ipOverride)
{
$this->ipOverride = $ipOverride;
}
/**
* @return array|null
*/
public function getOptions(): ?array
{
return $this->options;
}
/**
* @param array|null $options
*/
public function setOptions(?array $options)
{
$this->options = $options;
}
}

View File

@@ -0,0 +1,25 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 22.06.2021
* Time: 14:49
*/
namespace Tests\Common;
use Faker\Factory;
use PHPUnit\Framework\TestCase;
class BaseTestCase extends TestCase
{
protected $faker;
/**
* BaseTestCase constructor.
*/
public function __construct()
{
parent::__construct();
$this->faker = Factory::create();
}
}

View File

@@ -0,0 +1,109 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 22.06.2021
* Time: 15:23
*/
namespace Tests\Ga4\MeasurementProtocol\Dto\Common;
use Br33f\Ga4\MeasurementProtocol\Dto\Common\EventCollection;
use Br33f\Ga4\MeasurementProtocol\Dto\Event\BaseEvent;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\BaseParameter;
use Br33f\Ga4\MeasurementProtocol\Enum\ErrorCode;
use Tests\Common\BaseTestCase;
class EventCollectionTest extends BaseTestCase
{
/**
* @var EventCollection
*/
protected $eventCollection;
public function testEventList()
{
$setEventList = [];
for ($i = 0; $i < rand(1, 25); $i++) {
$setEventList[] = new BaseEvent();
}
$this->eventCollection->setEventList($setEventList);
$this->assertEquals($setEventList, $this->eventCollection->getEventList());
}
public function testSetEventListExceed25()
{
$setEventList = [];
for ($i = 0; $i < rand(26, 50); $i++) {
$setEventList[] = new BaseEvent();
}
$this->expectExceptionCode(ErrorCode::MAX_EVENT_COUNT_EXCEED);
$this->eventCollection->setEventList($setEventList);
}
public function testAddEvent()
{
$this->eventCollection->setEventList([]);
$newEvent = new BaseEvent();
$this->eventCollection->addEvent($newEvent);
$this->assertEquals(1, count($this->eventCollection->getEventList()));
$this->assertEquals($newEvent, $this->eventCollection->getEventList()[0]);
}
public function testAddEventExceed25()
{
$setEventList = [];
for ($i = 0; $i < 25; $i++) {
$setEventList[] = new BaseEvent();
}
$this->eventCollection->setEventList($setEventList);
$newEvent = new BaseEvent();
$this->expectExceptionCode(ErrorCode::MAX_EVENT_COUNT_EXCEED);
$this->eventCollection->addEvent($newEvent);
}
public function testExport()
{
$setEventListExport = [];
$setEventList = [];
for ($i = 0; $i < rand(1, 25); $i++) {
$event = new BaseEvent($this->faker->word);
$event->addParam($this->faker->word, new BaseParameter($this->faker->word));
$setEventList[] = $event;
$setEventListExport[] = $event->export();
}
$this->eventCollection->setEventList($setEventList);
$this->assertEquals($setEventListExport, $this->eventCollection->export());
}
public function testValidateFailed()
{
$newEventCollection = new EventCollection();
$this->expectExceptionCode(ErrorCode::VALIDATION_EVENTS_MUST_NOT_BE_EMPTY);
$newEventCollection->validate();
}
public function testValidateSuccess()
{
$newEventCollection = new EventCollection();
$event = new BaseEvent($this->faker->word);
$event->addParam($this->faker->word, new BaseParameter($this->faker->word));
$newEventCollection->addEvent($event);
$this->assertTrue($newEventCollection->validate());
}
protected function setUp(): void
{
parent::setUp();
$this->eventCollection = new EventCollection();
}
}

View File

@@ -0,0 +1,90 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 22.06.2021
* Time: 15:56
*/
namespace Tests\Ga4\MeasurementProtocol\Dto\Common;
use Br33f\Ga4\MeasurementProtocol\Dto\Common\UserProperties;
use Br33f\Ga4\MeasurementProtocol\Dto\Common\UserProperty;
use Tests\Common\BaseTestCase;
class UserPropertiesTest extends BaseTestCase
{
/**
* @var UserProperties
*/
protected $userProperties;
public function testDefaultConstructor()
{
$constructedUserProperties = new UserProperties();
$this->assertEquals([], $constructedUserProperties->getUserPropertiesList());
}
public function testConstructor()
{
$setUserProperties = [
new UserProperty(),
new UserProperty()
];
$constructedUserProperties = new UserProperties($setUserProperties);
$this->assertEquals($setUserProperties, $constructedUserProperties->getUserPropertiesList());
}
public function testUserPropertiesList()
{
$setUserProperties = [
new UserProperty($this->faker->word, $this->faker->word),
new UserProperty($this->faker->word, $this->faker->word),
new UserProperty($this->faker->word, $this->faker->word)
];
$this->userProperties->setUserPropertiesList($setUserProperties);
$this->assertEquals($setUserProperties, $this->userProperties->getUserPropertiesList());
}
public function testUserPropertyAdd()
{
$this->userProperties->setUserPropertiesList([]);
$addUserProperty = new UserProperty($this->faker->word, $this->faker->word);
$this->userProperties->addUserProperty($addUserProperty);
$this->assertEquals(1, count($this->userProperties->getUserPropertiesList()));
$this->assertEquals($addUserProperty, $this->userProperties->getUserPropertiesList()[0]);
}
public function testExport()
{
$setUserProperties = [
new UserProperty($this->faker->word, $this->faker->word),
new UserProperty($this->faker->word, $this->faker->word),
new UserProperty($this->faker->word, $this->faker->word)
];
$this->userProperties->setUserPropertiesList($setUserProperties);
$this->assertEquals([
$setUserProperties[0]->getName() => [
'value' => $setUserProperties[0]->getValue()
],
$setUserProperties[1]->getName() => [
'value' => $setUserProperties[1]->getValue()
],
$setUserProperties[2]->getName() => [
'value' => $setUserProperties[2]->getValue()
],
], $this->userProperties->export());
}
protected function setUp(): void
{
$this->userProperties = new UserProperties();
}
}

View File

@@ -0,0 +1,75 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 22.06.2021
* Time: 15:47
*/
namespace Tests\Ga4\MeasurementProtocol\Dto\Common;
use Br33f\Ga4\MeasurementProtocol\Dto\Common\UserProperty;
use Tests\Common\BaseTestCase;
class UserPropertyTest extends BaseTestCase
{
/**
* @var UserProperty
*/
protected $userProperty;
public function testDefaultConstructor()
{
$constructedUserProperty = new UserProperty();
$this->assertEquals(null, $constructedUserProperty->getName());
$this->assertEquals(null, $constructedUserProperty->getValue());
}
public function testParametrizedConstructor()
{
$setName = $this->faker->word;
$setValue = $this->faker->word;
$constructedUserProperty = new UserProperty($setName, $setValue);
$this->assertEquals($setName, $constructedUserProperty->getName());
$this->assertEquals($setValue, $constructedUserProperty->getValue());
}
public function testName()
{
$setName = $this->faker->word;
$this->userProperty->setName($setName);
$this->assertEquals($setName, $this->userProperty->getName());
}
public function testValue()
{
$setValue = $this->faker->word;
$this->userProperty->setValue($setValue);
$this->assertEquals($setValue, $this->userProperty->getValue());
}
public function testExportEmpty()
{
$emptyUserProperty = new UserProperty();
$this->assertEquals([null => ['value' => null]], $emptyUserProperty->export());
}
public function testExport()
{
$setName = $this->faker->word;
$setValue = $this->faker->word;
$emptyUserProperty = new UserProperty($setName, $setValue);
$this->assertEquals([$setName => ['value' => $setValue]], $emptyUserProperty->export());
}
protected function setUp(): void
{
parent::setUp();
$this->userProperty = new UserProperty();
}
}

View File

@@ -0,0 +1,83 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 24.06.2021
* Time: 13:54
*/
namespace Tests\Ga4\MeasurementProtocol\Dto\Common;
use Br33f\Ga4\MeasurementProtocol\Dto\Common\ValidationMessage;
use Br33f\Ga4\MeasurementProtocol\Enum\ValidationCode;
use Tests\Common\BaseTestCase;
class ValidationMessageTest extends BaseTestCase
{
/**
* @var ValidationMessage
*/
protected $validationMessage;
public function testDefaultConstructor()
{
$constructedValidationMessage = new ValidationMessage();
$this->assertNotNull($constructedValidationMessage);
}
public function testArrayBlueprintConstructor()
{
$blueprint = ['fieldPath' => $this->faker->word];
$constructedValidationMessage = new ValidationMessage($blueprint);
$this->assertNotNull($constructedValidationMessage);
$this->assertEquals($blueprint['fieldPath'], $constructedValidationMessage->getFieldPath());
$this->assertEquals(null, $constructedValidationMessage->getDescription());
$this->assertEquals(null, $constructedValidationMessage->getValidationCode());
}
public function testHydrate()
{
$blueprint = [
'fieldPath' => $this->faker->word,
'description' => $this->faker->text,
'validationCode' => $this->faker->randomElement([ValidationCode::EXCEEDED_MAX_ENTITIES, ValidationCode::NAME_DUPLICATED, ValidationCode::NAME_RESERVED])
];
$constructedValidationMessage = new ValidationMessage($blueprint);
$this->assertNotNull($constructedValidationMessage);
$this->assertEquals($blueprint['fieldPath'], $constructedValidationMessage->getFieldPath());
$this->assertEquals($blueprint['description'], $constructedValidationMessage->getDescription());
$this->assertEquals($blueprint['validationCode'], $constructedValidationMessage->getValidationCode());
}
public function testFieldPath()
{
$setFieldPath = $this->faker->word;
$this->validationMessage->setFieldPath($setFieldPath);
$this->assertEquals($setFieldPath, $this->validationMessage->getFieldPath());
}
public function testValidationCode()
{
$setValidationCode = $this->faker->randomElement([ValidationCode::EXCEEDED_MAX_ENTITIES, ValidationCode::NAME_DUPLICATED, ValidationCode::NAME_RESERVED]);
$this->validationMessage->setValidationCode($setValidationCode);
$this->assertEquals($setValidationCode, $this->validationMessage->getValidationCode());
}
public function testDescription()
{
$setDescription = $this->faker->text;
$this->validationMessage->setDescription($setDescription);
$this->assertEquals($setDescription, $this->validationMessage->getDescription());
}
protected function setUp(): void
{
parent::setUp();
$this->validationMessage = new ValidationMessage();
}
}

View File

@@ -0,0 +1,50 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 25.06.2021
* Time: 13:40
*/
namespace Tests\Ga4\MeasurementProtocol\Dto\Event;
use Br33f\Ga4\MeasurementProtocol\Dto\Event\AddPaymentInfoEvent;
use Br33f\Ga4\MeasurementProtocol\Exception\ValidationException;
use Tests\Common\BaseTestCase;
class AddPaymentInfoEventTest extends BaseTestCase
{
/**
* @var AddPaymentInfoEvent
*/
protected $event;
public function testDefaultConstructor()
{
$constructedEvent = new AddPaymentInfoEvent();
$this->assertNotNull($constructedEvent);
$this->assertEquals('add_payment_info', $constructedEvent->getName());
}
public function testValidateSuccess()
{
$this->event->setValue($this->faker->randomFloat(2, 10, 3000));
$this->event->setCurrency($this->faker->currencyCode);
$this->assertTrue($this->event->validate());
}
public function testValidateFail()
{
$this->event->setValue($this->faker->randomFloat(2, 10, 3000));
$this->expectException(ValidationException::class);
$this->event->validate();
}
protected function setUp(): void
{
parent::setUp();
$this->event = new AddPaymentInfoEvent();
}
}

View File

@@ -0,0 +1,50 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 25.06.2021
* Time: 13:40
*/
namespace Tests\Ga4\MeasurementProtocol\Dto\Event;
use Br33f\Ga4\MeasurementProtocol\Dto\Event\AddShippingInfoEvent;
use Br33f\Ga4\MeasurementProtocol\Exception\ValidationException;
use Tests\Common\BaseTestCase;
class AddShippingInfoEventTest extends BaseTestCase
{
/**
* @var AddShippingInfoEvent
*/
protected $event;
public function testDefaultConstructor()
{
$constructedEvent = new AddShippingInfoEvent();
$this->assertNotNull($constructedEvent);
$this->assertEquals('add_shipping_info', $constructedEvent->getName());
}
public function testValidateSuccess()
{
$this->event->setValue($this->faker->randomFloat(2, 10, 3000));
$this->event->setCurrency($this->faker->currencyCode);
$this->assertTrue($this->event->validate());
}
public function testValidateFail()
{
$this->event->setValue($this->faker->randomFloat(2, 10, 3000));
$this->expectException(ValidationException::class);
$this->event->validate();
}
protected function setUp(): void
{
parent::setUp();
$this->event = new AddShippingInfoEvent();
}
}

View File

@@ -0,0 +1,50 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 25.06.2021
* Time: 13:40
*/
namespace Tests\Ga4\MeasurementProtocol\Dto\Event;
use Br33f\Ga4\MeasurementProtocol\Dto\Event\AddToCartEvent;
use Br33f\Ga4\MeasurementProtocol\Exception\ValidationException;
use Tests\Common\BaseTestCase;
class AddToCartEventTest extends BaseTestCase
{
/**
* @var AddToCartEvent
*/
protected $event;
public function testDefaultConstructor()
{
$constructedEvent = new AddToCartEvent();
$this->assertNotNull($constructedEvent);
$this->assertEquals('add_to_cart', $constructedEvent->getName());
}
public function testValidateSuccess()
{
$this->event->setValue($this->faker->randomFloat(2, 10, 3000));
$this->event->setCurrency($this->faker->currencyCode);
$this->assertTrue($this->event->validate());
}
public function testValidateFail()
{
$this->event->setValue($this->faker->randomFloat(2, 10, 3000));
$this->expectException(ValidationException::class);
$this->event->validate();
}
protected function setUp(): void
{
parent::setUp();
$this->event = new AddToCartEvent();
}
}

View File

@@ -0,0 +1,171 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 22.06.2021
* Time: 15:05
*/
namespace Tests\Ga4\MeasurementProtocol\Dto\Event;
use BadMethodCallException;
use Br33f\Ga4\MeasurementProtocol\Dto\Event\BaseEvent;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\BaseParameter;
use InvalidArgumentException;
use Tests\Common\BaseTestCase;
class BaseEventTest extends BaseTestCase
{
/**
* @var BaseEvent
*/
protected $event;
public function testDefaultConstructor()
{
$constructedEvent = new BaseEvent();
$this->assertEquals(null, $constructedEvent->getName());
$this->assertEquals([], $constructedEvent->getParamList());
}
public function testNameOnlyConstructor()
{
$setupName = $this->faker->word;
$constructedEvent = new BaseEvent($setupName);
$this->assertEquals($setupName, $constructedEvent->getName());
$this->assertEquals([], $constructedEvent->getParamList());
}
public function testParamListOnlyConstructor()
{
$baseParams = [];
for ($i = 0; $i < rand(4, 10); $i++) {
$baseParams[$this->faker->word] = new BaseParameter($this->faker->word);
}
$constructedEvent = new BaseEvent(null, $baseParams);
$this->assertEquals(null, $constructedEvent->getName());
$this->assertEquals($baseParams, $constructedEvent->getParamList());
}
public function testFullConstructor()
{
$setupName = $this->faker->word;
$baseParams = [];
for ($i = 0; $i < rand(4, 10); $i++) {
$baseParams[$this->faker->word] = new BaseParameter($this->faker->word);
}
$constructedEvent = new BaseEvent($setupName, $baseParams);
$this->assertEquals($setupName, $constructedEvent->getName());
$this->assertEquals($baseParams, $constructedEvent->getParamList());
}
public function testName()
{
$setupName = $this->faker->word;
$this->event->setName($setupName);
$this->assertEquals($setupName, $this->event->getName());
}
public function testParamList()
{
$baseParams = [];
for ($i = 0; $i < rand(4, 10); $i++) {
$baseParams[$this->faker->word] = new BaseParameter($this->faker->word);
}
$this->event->setParamList($baseParams);
$this->assertEquals($baseParams, $this->event->getParamList());
}
public function testAddParam()
{
$this->event->setParamList([]);
$paramName = $this->faker->word;
$paramToAdd = new BaseParameter($this->faker->word);
$this->event->addParam($paramName, $paramToAdd);
$this->assertEquals(1, count($this->event->getParamList()));
$this->assertEquals($paramToAdd, $this->event->getParamList()[$paramName]);
}
public function testDeleteParam()
{
$this->event->setParamList([]);
$paramName = $this->faker->word;
$paramToAdd = new BaseParameter($this->faker->word);
$this->event->addParam($paramName, $paramToAdd);
$this->assertEquals(1, count($this->event->getParamList()));
$this->event->deleteParameter($paramName);
$this->assertEquals(0, count($this->event->getParamList()));
}
public function testExportEmpty()
{
$emptyEvent = new BaseEvent();
$this->assertEquals(['name' => null, 'params' => new \ArrayObject()], $emptyEvent->export());
}
public function testExport()
{
$setupName = $this->faker->word;
$baseParamsExport = [];
$baseParams = [];
for ($i = 0; $i < rand(4, 10); $i++) {
$baseParamName = $this->faker->word;
$baseParam = new BaseParameter($this->faker->word);
$baseParams[$baseParamName] = $baseParam;
$baseParamsExport[$baseParamName] = $baseParam->export();
}
$constructedEvent = new BaseEvent($setupName, $baseParams);
$this->assertEquals(['name' => $setupName, 'params' => new \ArrayObject($baseParamsExport)], $constructedEvent->export());
}
public function testSetGetCall()
{
$this->event->setTest1('test1value');
$this->assertEquals('test1value', $this->event->getTest1());
}
public function testSetCallNoParams()
{
$this->expectException(InvalidArgumentException::class);
$this->event->setTest2();
}
public function testUnknownCallMethod()
{
$this->expectException(BadMethodCallException::class);
$this->event->invalidMethodName();
}
public function testValidate()
{
$setupName = $this->faker->word;
$baseParams = [];
for ($i = 0; $i < rand(4, 10); $i++) {
$baseParam = new BaseParameter($this->faker->word);
$baseParams[$this->faker->word] = $baseParam;
}
$constructedEvent = new BaseEvent($setupName, $baseParams);
$this->assertTrue($constructedEvent->validate());
}
protected function setUp(): void
{
$this->event = new BaseEvent();
}
}

View File

@@ -0,0 +1,50 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 25.06.2021
* Time: 13:40
*/
namespace Tests\Ga4\MeasurementProtocol\Dto\Event;
use Br33f\Ga4\MeasurementProtocol\Dto\Event\BeginCheckoutEvent;
use Br33f\Ga4\MeasurementProtocol\Exception\ValidationException;
use Tests\Common\BaseTestCase;
class BeginCheckoutEventTest extends BaseTestCase
{
/**
* @var BeginCheckoutEvent
*/
protected $event;
public function testDefaultConstructor()
{
$constructedEvent = new BeginCheckoutEvent();
$this->assertNotNull($constructedEvent);
$this->assertEquals('begin_checkout', $constructedEvent->getName());
}
public function testValidateSuccess()
{
$this->event->setValue($this->faker->randomFloat(2, 10, 3000));
$this->event->setCurrency($this->faker->currencyCode);
$this->assertTrue($this->event->validate());
}
public function testValidateFail()
{
$this->event->setValue($this->faker->randomFloat(2, 10, 3000));
$this->expectException(ValidationException::class);
$this->event->validate();
}
protected function setUp(): void
{
parent::setUp();
$this->event = new BeginCheckoutEvent();
}
}

View File

@@ -0,0 +1,40 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 25.06.2021
* Time: 13:40
*/
namespace Tests\Ga4\MeasurementProtocol\Dto\Event;
use Br33f\Ga4\MeasurementProtocol\Dto\Event\LoginEvent;
use Tests\Common\BaseTestCase;
class LoginEventTest extends BaseTestCase
{
/**
* @var LoginEvent
*/
protected $event;
public function testDefaultConstructor()
{
$constructedEvent = new LoginEvent();
$this->assertNotNull($constructedEvent);
$this->assertEquals('login', $constructedEvent->getName());
}
public function testValidateSuccess()
{
$this->event->setMethod($this->faker->word);
$this->assertTrue($this->event->validate());
}
protected function setUp(): void
{
parent::setUp();
$this->event = new LoginEvent();
}
}

View File

@@ -0,0 +1,61 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 25.06.2021
* Time: 13:40
*/
namespace Tests\Ga4\MeasurementProtocol\Dto\Event;
use Br33f\Ga4\MeasurementProtocol\Dto\Event\PurchaseEvent;
use Br33f\Ga4\MeasurementProtocol\Exception\ValidationException;
use Tests\Common\BaseTestCase;
class PurchaseEventTest extends BaseTestCase
{
/**
* @var PurchaseEvent
*/
protected $event;
public function testDefaultConstructor()
{
$constructedEvent = new PurchaseEvent();
$this->assertNotNull($constructedEvent);
$this->assertEquals('purchase', $constructedEvent->getName());
}
public function testValidateSuccess()
{
$this->event->setValue($this->faker->randomFloat(2, 10, 3000));
$this->event->setCurrency($this->faker->currencyCode);
$this->event->setTransactionId($this->faker->bothify('*#*#*#_transaction'));
$this->assertTrue($this->event->validate());
}
public function testValidateFailNoCurrency()
{
$this->event->setValue($this->faker->randomFloat(2, 10, 3000));
$this->event->setTransactionId($this->faker->bothify('*#*#*#_transaction'));
$this->expectException(ValidationException::class);
$this->event->validate();
}
public function testValidateFailNoTransaction()
{
$this->event->setValue($this->faker->randomFloat(2, 10, 3000));
$this->event->setCurrency($this->faker->currencyCode);
$this->expectException(ValidationException::class);
$this->event->validate();
}
protected function setUp(): void
{
parent::setUp();
$this->event = new PurchaseEvent();
}
}

View File

@@ -0,0 +1,61 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 25.06.2021
* Time: 13:40
*/
namespace Tests\Ga4\MeasurementProtocol\Dto\Event;
use Br33f\Ga4\MeasurementProtocol\Dto\Event\RefundEvent;
use Br33f\Ga4\MeasurementProtocol\Exception\ValidationException;
use Tests\Common\BaseTestCase;
class RefundEventTest extends BaseTestCase
{
/**
* @var RefundEvent
*/
protected $event;
public function testDefaultConstructor()
{
$constructedEvent = new RefundEvent();
$this->assertNotNull($constructedEvent);
$this->assertEquals('refund', $constructedEvent->getName());
}
public function testValidateSuccess()
{
$this->event->setValue($this->faker->randomFloat(2, 10, 3000));
$this->event->setCurrency($this->faker->currencyCode);
$this->event->setTransactionId($this->faker->bothify('*#*#*#_transaction'));
$this->assertTrue($this->event->validate());
}
public function testValidateFailNoCurrency()
{
$this->event->setValue($this->faker->randomFloat(2, 10, 3000));
$this->event->setTransactionId($this->faker->bothify('*#*#*#_transaction'));
$this->expectException(ValidationException::class);
$this->event->validate();
}
public function testValidateFailNoTransaction()
{
$this->event->setValue($this->faker->randomFloat(2, 10, 3000));
$this->event->setCurrency($this->faker->currencyCode);
$this->expectException(ValidationException::class);
$this->event->validate();
}
protected function setUp(): void
{
parent::setUp();
$this->event = new RefundEvent();
}
}

View File

@@ -0,0 +1,50 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 25.06.2021
* Time: 13:40
*/
namespace Tests\Ga4\MeasurementProtocol\Dto\Event;
use Br33f\Ga4\MeasurementProtocol\Dto\Event\RemoveFromCartEvent;
use Br33f\Ga4\MeasurementProtocol\Exception\ValidationException;
use Tests\Common\BaseTestCase;
class RemoveFromCartEventTest extends BaseTestCase
{
/**
* @var RemoveFromCartEvent
*/
protected $event;
public function testDefaultConstructor()
{
$constructedEvent = new RemoveFromCartEvent();
$this->assertNotNull($constructedEvent);
$this->assertEquals('remove_from_cart', $constructedEvent->getName());
}
public function testValidateSuccess()
{
$this->event->setValue($this->faker->randomFloat(2, 10, 3000));
$this->event->setCurrency($this->faker->currencyCode);
$this->assertTrue($this->event->validate());
}
public function testValidateFail()
{
$this->event->setValue($this->faker->randomFloat(2, 10, 3000));
$this->expectException(ValidationException::class);
$this->event->validate();
}
protected function setUp(): void
{
parent::setUp();
$this->event = new RemoveFromCartEvent();
}
}

View File

@@ -0,0 +1,49 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 25.06.2021
* Time: 13:40
*/
namespace Tests\Ga4\MeasurementProtocol\Dto\Event;
use Br33f\Ga4\MeasurementProtocol\Dto\Event\SearchEvent;
use Br33f\Ga4\MeasurementProtocol\Exception\ValidationException;
use Tests\Common\BaseTestCase;
class SearchEventTest extends BaseTestCase
{
/**
* @var SearchEvent
*/
protected $event;
public function testDefaultConstructor()
{
$constructedEvent = new SearchEvent();
$this->assertNotNull($constructedEvent);
$this->assertEquals('search', $constructedEvent->getName());
}
public function testValidateSuccess()
{
$this->event->setSearchTerm($this->faker->paragraph);
$this->assertTrue($this->event->validate());
}
public function testValidateFail()
{
$this->event = new SearchEvent();
$this->expectException(ValidationException::class);
$this->event->validate();
}
protected function setUp(): void
{
parent::setUp();
$this->event = new SearchEvent();
}
}

View File

@@ -0,0 +1,55 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 25.06.2021
* Time: 10:44
*/
namespace Tests\Ga4\MeasurementProtocol\Dto\Event;
use Br33f\Ga4\MeasurementProtocol\Dto\Event\SelectItemEvent;
use Br33f\Ga4\MeasurementProtocol\Dto\Event\ViewItemEvent;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\BaseParameter;
use Tests\Common\BaseTestCase;
class SelectItemEventTest extends BaseTestCase
{
/**
* @var SelectItemEvent
*/
protected $event;
public function testDefaultConstructor()
{
$constructedEvent = new SelectItemEvent();
$this->assertNotNull($constructedEvent);
$this->assertEquals('select_item', $constructedEvent->getName());
}
public function testParameterConstructor()
{
$setParameters = [
$this->faker->word => new BaseParameter($this->faker->word),
$this->faker->word => new BaseParameter($this->faker->word)
];
$constructedEvent = new ViewItemEvent($setParameters);
$this->assertNotNull($constructedEvent);
$this->assertEquals($setParameters, $constructedEvent->getParamList());
}
public function testValidateSuccess()
{
$newViewItemEvent = new ViewItemEvent();
$this->assertTrue($newViewItemEvent->validate());
}
protected function setUp(): void
{
parent::setUp();
$this->event = new SelectItemEvent();
}
}

View File

@@ -0,0 +1,40 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 25.06.2021
* Time: 13:40
*/
namespace Tests\Ga4\MeasurementProtocol\Dto\Event;
use Br33f\Ga4\MeasurementProtocol\Dto\Event\SignUpEvent;
use Tests\Common\BaseTestCase;
class SignUpEventTest extends BaseTestCase
{
/**
* @var SignUpEvent
*/
protected $event;
public function testDefaultConstructor()
{
$constructedEvent = new SignUpEvent();
$this->assertNotNull($constructedEvent);
$this->assertEquals('sign_up', $constructedEvent->getName());
}
public function testValidateSuccess()
{
$this->event->setMethod($this->faker->word);
$this->assertTrue($this->event->validate());
}
protected function setUp(): void
{
parent::setUp();
$this->event = new SignUpEvent();
}
}

View File

@@ -0,0 +1,50 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 25.06.2021
* Time: 13:40
*/
namespace Tests\Ga4\MeasurementProtocol\Dto\Event;
use Br33f\Ga4\MeasurementProtocol\Dto\Event\ViewCartEvent;
use Br33f\Ga4\MeasurementProtocol\Exception\ValidationException;
use Tests\Common\BaseTestCase;
class ViewCartEventTest extends BaseTestCase
{
/**
* @var ViewCartEvent
*/
protected $event;
public function testDefaultConstructor()
{
$constructedEvent = new ViewCartEvent();
$this->assertNotNull($constructedEvent);
$this->assertEquals('view_cart', $constructedEvent->getName());
}
public function testValidateSuccess()
{
$this->event->setValue($this->faker->randomFloat(2, 10, 3000));
$this->event->setCurrency($this->faker->currencyCode);
$this->assertTrue($this->event->validate());
}
public function testValidateFail()
{
$this->event->setValue($this->faker->randomFloat(2, 10, 3000));
$this->expectException(ValidationException::class);
$this->event->validate();
}
protected function setUp(): void
{
parent::setUp();
$this->event = new ViewCartEvent();
}
}

View File

@@ -0,0 +1,109 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 25.06.2021
* Time: 10:44
*/
namespace Tests\Ga4\MeasurementProtocol\Dto\Event;
use Br33f\Ga4\MeasurementProtocol\Dto\Event\ViewItemEvent;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\BaseParameter;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\ItemCollectionParameter;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\ItemParameter;
use Tests\Common\BaseTestCase;
class ViewItemEventTest extends BaseTestCase
{
protected $viewItemEvent;
public function testDefaultConstructor()
{
$constructedEvent = new ViewItemEvent();
$this->assertNotNull($constructedEvent);
}
public function testParameterConstructor()
{
$setParameters = [
$this->faker->word => new BaseParameter($this->faker->word),
$this->faker->word => new BaseParameter($this->faker->word)
];
$constructedEvent = new ViewItemEvent($setParameters);
$this->assertNotNull($constructedEvent);
$this->assertEquals($setParameters, $constructedEvent->getParamList());
}
public function testSetGetItems()
{
$setItems = new ItemCollectionParameter([
new ItemParameter(['item_name' => $this->faker->word]),
new ItemParameter(['item_name' => $this->faker->word, 'price' => $this->faker->randomFloat(2, 10, 100)])
]);
$this->viewItemEvent->setItems($setItems);
$this->assertEquals($setItems, $this->viewItemEvent->getItems());
}
public function testGetItemsEmpty()
{
$newViewItemEvent = new ViewItemEvent();
$this->assertNotNull($newViewItemEvent->getItems());
}
public function testAddItem()
{
$this->viewItemEvent->setItems(new ItemCollectionParameter());
$itemToAdd = new ItemParameter(['item_name' => $this->faker->word]);
$this->viewItemEvent->addItem($itemToAdd);
$this->assertEquals(1, count($this->viewItemEvent->getItems()->getItemList()));
$this->assertEquals($itemToAdd, $this->viewItemEvent->getItems()->getItemList()[0]);
}
public function testCurrency()
{
$setCurrency = $this->faker->currencyCode;
$this->viewItemEvent->setCurrency($setCurrency);
$this->assertEquals($setCurrency, $this->viewItemEvent->getCurrency());
}
public function testValue()
{
$setValue = $this->faker->randomFloat(2, 10, 2000);
$this->viewItemEvent->setValue($setValue);
$this->assertEquals($setValue, $this->viewItemEvent->getValue());
}
public function testValidateEmpty()
{
$newViewItemEvent = new ViewItemEvent();
$this->assertTrue($newViewItemEvent->validate());
}
public function testValidate()
{
$setItems = new ItemCollectionParameter([
new ItemParameter(['item_name' => $this->faker->word]),
new ItemParameter(['item_name' => $this->faker->word, 'price' => $this->faker->randomFloat(2, 10, 100)])
]);
$newViewItemEvent = new ViewItemEvent([$setItems]);
$this->assertTrue($newViewItemEvent->validate());
}
protected function setUp(): void
{
parent::setUp();
$this->viewItemEvent = new ViewItemEvent();
}
}

View File

@@ -0,0 +1,103 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 25.06.2021
* Time: 10:44
*/
namespace Tests\Ga4\MeasurementProtocol\Dto\Event;
use Br33f\Ga4\MeasurementProtocol\Dto\Event\ViewItemEvent;
use Br33f\Ga4\MeasurementProtocol\Dto\Event\ViewItemListEvent;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\BaseParameter;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\ItemCollectionParameter;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\ItemParameter;
use Tests\Common\BaseTestCase;
class ViewItemListEventTest extends BaseTestCase
{
/**
* @var ViewItemEvent
*/
protected $event;
public function testDefaultConstructor()
{
$constructedEvent = new ViewItemListEvent();
$this->assertNotNull($constructedEvent);
$this->assertEquals('view_item_list', $constructedEvent->getName());
}
public function testParameterConstructor()
{
$setParameters = [
$this->faker->word => new BaseParameter($this->faker->word),
$this->faker->word => new BaseParameter($this->faker->word)
];
$constructedEvent = new ViewItemEvent($setParameters);
$this->assertNotNull($constructedEvent);
$this->assertEquals($setParameters, $constructedEvent->getParamList());
}
public function testSetGetItems()
{
$setItems = new ItemCollectionParameter([
new ItemParameter(['item_name' => $this->faker->word]),
new ItemParameter(['item_name' => $this->faker->word, 'price' => $this->faker->randomFloat(2, 10, 100)])
]);
$this->event->setItems($setItems);
$this->assertEquals($setItems, $this->event->getItems());
}
public function testGetItemsEmpty()
{
$newViewItemEvent = new ViewItemEvent();
$this->assertNotNull($newViewItemEvent->getItems());
}
public function testAddItem()
{
$this->event->setItems(new ItemCollectionParameter());
$itemToAdd = new ItemParameter(['item_name' => $this->faker->word]);
$this->event->addItem($itemToAdd);
$this->assertEquals(1, count($this->event->getItems()->getItemList()));
$this->assertEquals($itemToAdd, $this->event->getItems()->getItemList()[0]);
}
public function testCurrency()
{
$setCurrency = $this->faker->currencyCode;
$this->event->setCurrency($setCurrency);
$this->assertEquals($setCurrency, $this->event->getCurrency());
}
public function testValue()
{
$setValue = $this->faker->randomFloat(2, 10, 2000);
$this->event->setValue($setValue);
$this->assertEquals($setValue, $this->event->getValue());
}
public function testValidate()
{
$newViewItemEvent = new ViewItemEvent();
$this->assertTrue($newViewItemEvent->validate());
}
protected function setUp(): void
{
parent::setUp();
$this->event = new ViewItemListEvent();
}
}

View File

@@ -0,0 +1,40 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 25.06.2021
* Time: 13:40
*/
namespace Tests\Ga4\MeasurementProtocol\Dto\Event;
use Br33f\Ga4\MeasurementProtocol\Dto\Event\ViewSearchResultsEvent;
use Tests\Common\BaseTestCase;
class ViewSearchResultsEventTest extends BaseTestCase
{
/**
* @var ViewSearchResultsEvent
*/
protected $event;
public function testDefaultConstructor()
{
$constructedEvent = new ViewSearchResultsEvent();
$this->assertNotNull($constructedEvent);
$this->assertEquals('view_search_results', $constructedEvent->getName());
}
public function testValidateSuccess()
{
$this->event->setSearchTerm($this->faker->paragraph);
$this->assertTrue($this->event->validate());
}
protected function setUp(): void
{
parent::setUp();
$this->event = new ViewSearchResultsEvent();
}
}

View File

@@ -0,0 +1,69 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 22.06.2021
* Time: 14:22
*/
namespace Tests\Ga4\MeasurementProtocol\Dto\Parameter;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\BaseParameter;
use Tests\Common\BaseTestCase;
class BaseParameterTest extends BaseTestCase
{
/**
* @var BaseParameter
*/
protected $baseParameter;
public function setUp(): void
{
$this->baseParameter = new BaseParameter();
}
public function testValueString()
{
$valueToSet = $this->faker->word;
$this->baseParameter->setValue($valueToSet);
$this->assertEquals($valueToSet, $this->baseParameter->getValue());
}
public function testValueArray()
{
$valueToSet = [];
for ($i = 0; $i < $this->faker->randomDigit; $i++) {
$valueToSet[] = $this->faker->word;
}
$this->baseParameter->setValue($valueToSet);
$this->assertEquals($valueToSet, $this->baseParameter->getValue());
}
public function testValueBaseParam()
{
$valueToSet = new BaseParameter();
$valueToSet->setValue($this->faker->word);
$this->baseParameter->setValue($valueToSet);
$this->assertEquals($valueToSet, $this->baseParameter->getValue());
}
public function testExportSimple()
{
$valueToSet = $this->faker->word;
$this->baseParameter->setValue($valueToSet);
$this->assertEquals($valueToSet, $this->baseParameter->export());
}
public function testExportBaseParameter()
{
$valueToSet = new BaseParameter();
$valueToSet->setValue($this->faker->word);
$this->baseParameter->setValue($valueToSet);
$this->assertEquals($valueToSet->getValue(), $this->baseParameter->export());
}
}

View File

@@ -0,0 +1,92 @@
<?php
/**
* User: Damian Zamojski (br33f)
* Date: 22.06.2021
* Time: 14:22
*/
namespace Tests\Ga4\MeasurementProtocol\Dto\Parameter;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\ItemCollectionParameter;
use Br33f\Ga4\MeasurementProtocol\Dto\Parameter\ItemParameter;
use Br33f\Ga4\MeasurementProtocol\Exception\ValidationException;
use Tests\Common\BaseTestCase;
class ItemCollectionParameterTest extends BaseTestCase
{
/**
* @var ItemCollectionParameter
*/
protected $itemCollectionParameter;
public function setUp(): void
{
$this->itemCollectionParameter = new ItemCollectionParameter();
}
public function testDefaultContructor()
{
$constructedItemCollectionParameter = new ItemCollectionParameter();
$this->assertNotNull($constructedItemCollectionParameter);
}
public function testItemList()
{
$setItemList = [
new ItemParameter(['item_name' => 'test1']),
new ItemParameter(['item_id' => '123', 'price' => 15.55])
];
$this->itemCollectionParameter->setItemList($setItemList);
$this->assertEquals($setItemList, $this->itemCollectionParameter->getItemList());
}
public function testAddItem()
{
$itemToAdd = new ItemParameter(['item_name' => $this->faker->name, 'item_id' => '123', 'price' => 15.55]);
$this->itemCollectionParameter
->setItemList([])
->addItem($itemToAdd);
$this->assertEquals(1, count($this->itemCollectionParameter->getItemList()));
$this->assertEquals($itemToAdd, $this->itemCollectionParameter->getItemList()[0]);
}
public function testExportSimple()
{
$setItemList = [
new ItemParameter(['item_name' => 'test1']),
new ItemParameter(['item_id' => '123', 'price' => 15.55])
];
$this->itemCollectionParameter->setItemList($setItemList);
$this->assertEquals([
['item_name' => 'test1'],
['item_id' => '123', 'price' => 15.55]
], $this->itemCollectionParameter->export());
}
public function testValidateSuccess()
{
$setItemList = [
new ItemParameter(['item_name' => 'test1']),
new ItemParameter(['item_id' => '123', 'price' => 15.55])
];
$this->itemCollectionParameter->setItemList($setItemList);
$this->assertTrue($this->itemCollectionParameter->validate());
}
public function testValidateError()
{
$setItemList = [
new ItemParameter(['item_name' => 'test1']),
new ItemParameter(['price' => 15.55])
];
$this->itemCollectionParameter->setItemList($setItemList);
$this->expectException(ValidationException::class);
$this->itemCollectionParameter->validate();
}
}

Some files were not shown because too many files have changed in this diff Show More