Compare commits

..

No commits in common. "master" and "v4" have entirely different histories.
master ... v4

23 changed files with 302 additions and 574 deletions

View file

@ -2,96 +2,34 @@
### All notable changes to `CRM CLient V4` will be documented in this file.
# version 4.1.8
- fix: 🐛 remove sending brand id in claim call #52
# version 4.1.7
- fix: 🏷️ add Germany to the valid countries
# version 4.1.6
- Changed: move claim customer association into server side
# version 4.1.4
- Changed: update claim customer relation with hashcode
# version 4.1.4
- Changed: update claim file validation
- Changed: resolve phpcs errors
# version 4.1.3
- Added: client tests for registering a claim
# version 4.1.2
- Changed: force string cast in ctype_digit method
# version 4.1.1
- Changed: update optionnal answer id parameter when set new single optin for laravel and wordpress
# version 4.1.0
- Added: new api route for sending new claim
- Added: optionnal answer id parameter when set new single optin
# version 4.0.4
- chore: :arrow_up: bump to v4.0.4
# version 4.0.3
- chore: :arrow_up: bump to v4.0.3
# version 4.0.2
- chore: :arrow_up: bump to v4.0.2
# version 4.0.1
- chore: :arrow_up: bump to v4.0.1
- fix: 🏷️ add Netherlands to the valid countries
# version 4.0.0
- Changed: CRM is now php 8.2 only
- Changed: CRM is now php 8.2 only
# version 3.0.6
- Added: SingleOptin::unsetStatusWithHashcode to allow customers to unsubscribe using a hashcode, now single optins do have hashcodes
- Added: SingleOptin::unsetStatusWithHashcode to allow customers to unsubscribe using a hashcode, now single optins do have hashcodes
# version 3.0.5
- Bumped to follow CRM updates
- Bumped to follow CRM updates
# version 3.0.4
- Added CI configuration
- Added CI configuration
# version 3.0.3
- Update Country enum
- Fixed : request merge method of data to query (Request.php)
- Fixed : validate json check should check if really false (Response.php)
- Bumped composer deps
- Update Country enum
- Fixed : request merge method of data to query (Request.php)
- Fixed : validate json check should check if really false (Response.php)
- Bumped composer deps
# version 3.0.2
- Regen documentation with php documentor
- Regen documentation with php documentor
# version 3.0.1
- Fixed : Customer do not call update if there are no updated fields
- Fixed : WPCrm bootSessionIfNeeded trying to access $\_SESSION['wpcrm'] before session was started
- Fixed : WPCrm now only returns a boolean
- Fixed : get crm info when client used in laravel
- Changed : WpCrm::makeApiV4Call Change LogLevel on error from Emerge to Critical
- Changed : WPCrm readd forceLogin()
- Fixed : Customer do not call update if there are no updated fields
- Fixed : WPCrm bootSessionIfNeeded trying to access $_SESSION['wpcrm'] before session was started
- Fixed : WPCrm now only returns a boolean
- Fixed : get crm info when client used in laravel
- Changed : WpCrm::makeApiV4Call Change LogLevel on error from Emerge to Critical
- Changed : WPCrm readd forceLogin()
# version 3.0.0
@ -99,68 +37,60 @@ This removes api authentication with token in favor of signature method.
Refactored code and clean up. It add more unit test plus code coverage
in test/coverage.
- Added : mardown documentation.
- Changed : WPCrm::login now only returns a boolean
- Changed : model Stats::getQuestionStats to pass question as route parameter
- Changed : now requests need to have a signature generated with a private key (crm password) using hmac sha256 wrapping url, method and parameters
- Changed : now timestamp will timeout if request is slower than "timestampTimeout", this means crm will reject the request
- Changed : throw ValidationException s instead of TypeErrors
- Changed : timestamp has to be send in request with a DateTime format, it also has to a UTC value
- Fixed : Change WPCRM dynamic session key, this could prevent spoofing session in some cases.
- Fixed : closure validation
- Fixed : model mutator not catching reflectionException
- Fixed : really send json request using Guzzle internal lib methods.
- Removed : Api AUTH system with api token
- Removed : ApiError::needAuth
- Removed : composer vlucas/dotenv, .env file is not handled any more.
- Removed : LoginException
- Removed : memcached dependency
- Removed : need of memcached
- Removed : unused service provider
- Removed : WpCrm::forceLogin
- Removed : WpCrm::sendArcadiaMailDefault
- Removed : WpCrm::sendArcadiaMailGame
- Updated : PHPCS rules, phpcs fixes and refactored code
- Added : mardown documentation.
- Changed : WPCrm::login now only returns a boolean
- Changed : model Stats::getQuestionStats to pass question as route parameter
- Changed : now requests need to have a signature generated with a private key (crm password) using hmac sha256 wrapping url, method and parameters
- Changed : now timestamp will timeout if request is slower than "timestampTimeout", this means crm will reject the request
- Changed : throw ValidationException s instead of TypeErrors
- Changed : timestamp has to be send in request with a DateTime format, it also has to a UTC value
- Fixed : Change WPCRM dynamic session key, this could prevent spoofing session in some cases.
- Fixed : closure validation
- Fixed : model mutator not catching reflectionException
- Fixed : really send json request using Guzzle internal lib methods.
- Removed : Api AUTH system with api token
- Removed : ApiError::needAuth
- Removed : composer vlucas/dotenv, .env file is not handled any more.
- Removed : LoginException
- Removed : memcached dependency
- Removed : need of memcached
- Removed : unused service provider
- Removed : WpCrm::forceLogin
- Removed : WpCrm::sendArcadiaMailDefault
- Removed : WpCrm::sendArcadiaMailGame
- Updated : PHPCS rules, phpcs fixes and refactored code
# version 2.3.2
- Hotfixed arcadia order
- Hotfixed arcadia order
# version 2.3.1
- Fixed Consider fill attributes as can be nullable
- Fixed Respect sometimes validation
- Fixed Consider fill attributes as can be nullable
- Fixed Respect sometimes validation
# version 2.3.0
- Added Stats call by brand and by question
- Added min rule valdation for integers as well as for strings in Utils
- Added Stats call by brand and by question
- Added min rule valdation for integers as well as for strings in Utils
# version 2.2.3
- Changed for bool casting for response parse field 'status' when is int 1 or 0
- Changed, properties are filled from CRM after a save or update action, this will allow for props to be set on model as it is on the crm, after all checks and casts (firstname capitalized, ... etc)
- Changed for bool casting for response parse field 'status' when is int 1 or 0
- Changed, properties are filled from CRM after a save or update action, this will allow for props to be set on model as it is on the crm, after all checks and casts (firstname capitalized, ... etc)
# version 2.2.2
- Fixed Arcadia mail where sending parameters as query instead of Data
- Fixed Arcadia mail where sending parameters as query instead of Data
# version 2.2.1
- Fixed fill methods on models to handle all enums + arrays
- Changed validation on customer, city minimum is now 2 chars,
firstname and lastname min are now 1 char, phone min 10 has been removed,
other validations are made on backend side such as limit countries,
right now limit is FR, BE, NL.
Anyway dont forget to handle ValidationException which returns crm message.
- Include Drom Com to allowed countries
- Update Country enum to remove '-' chars
- Fixed fill methods on models to handle all enums + arrays
- Changed validation on customer, city minimum is now 2 chars,
firstname and lastname min are now 1 char, phone min 10 has been removed,
other validations are made on backend side such as limit countries,
right now limit is FR, BE, NL.
Anyway dont forget to handle ValidationException which returns crm message.
- Include Drom Com to allowed countries
- Update Country enum to remove '-' chars
# version 2.2.0
- Fixed Utils.php getResquest method
- Changed Arcadia mails, add customer parameters for these calls
- Fixed Utils.php getResquest method
- Changed Arcadia mails, add customer parameters for these calls
# version 2.1.9
- Fixed method CrmClientModel::fill now validates data and put value to updatedValues array
- Fixed method CrmClientModel::fill now validates data and put value to updatedValues array

View file

@ -1,5 +1,5 @@
{
"version": "4.1.8",
"version": "4.0.0",
"timestampTimeout": 30,
"apiRequestRatePerMinute": 256,
"servicesDBCache": 10

View file

@ -1,12 +1,17 @@
{
"name": "ldc/ldccrmv4client",
"version": "4.1.8",
"type": "library",
"description": "LDC CRM Client V4",
"license": "MIT",
"support": {
"email": "digital@ldc.fr"
},
"version": "4.0.0",
"authors": [
{
"name": "Jérémy Munsch",
"email": "jeremy.munsch@ldc.fr",
"homepage": "https://jeremydev.ovh"
}
],
"homepage": "https://github.com/kwaadpepper",
"keywords": [
"Laravel",
"CRM",
@ -15,7 +20,6 @@
],
"require": {
"php": "^8.2",
"doctrine/inflector": "^2.0",
"ext-curl": "*",
"guzzlehttp/guzzle": "^7.4",
"respect/validation": "^2.2"

186
composer.lock generated
View file

@ -4,99 +4,8 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "eb380867bcf551762b352ecb8f201c22",
"content-hash": "46d0f076c74afaa5b636e0b6283ad48e",
"packages": [
{
"name": "doctrine/inflector",
"version": "2.0.10",
"source": {
"type": "git",
"url": "https://github.com/doctrine/inflector.git",
"reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/inflector/zipball/5817d0659c5b50c9b950feb9af7b9668e2c436bc",
"reference": "5817d0659c5b50c9b950feb9af7b9668e2c436bc",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^11.0",
"phpstan/phpstan": "^1.8",
"phpstan/phpstan-phpunit": "^1.1",
"phpstan/phpstan-strict-rules": "^1.3",
"phpunit/phpunit": "^8.5 || ^9.5",
"vimeo/psalm": "^4.25 || ^5.4"
},
"type": "library",
"autoload": {
"psr-4": {
"Doctrine\\Inflector\\": "lib/Doctrine/Inflector"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
}
],
"description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.",
"homepage": "https://www.doctrine-project.org/projects/inflector.html",
"keywords": [
"inflection",
"inflector",
"lowercase",
"manipulation",
"php",
"plural",
"singular",
"strings",
"uppercase",
"words"
],
"support": {
"issues": "https://github.com/doctrine/inflector/issues",
"source": "https://github.com/doctrine/inflector/tree/2.0.10"
},
"funding": [
{
"url": "https://www.doctrine-project.org/sponsorship.html",
"type": "custom"
},
{
"url": "https://www.patreon.com/phpdoctrine",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector",
"type": "tidelift"
}
],
"time": "2024-02-18T20:23:39+00:00"
},
{
"name": "guzzlehttp/guzzle",
"version": "7.8.0",
@ -1188,6 +1097,97 @@
},
"time": "2022-10-27T11:44:00+00:00"
},
{
"name": "doctrine/inflector",
"version": "2.0.8",
"source": {
"type": "git",
"url": "https://github.com/doctrine/inflector.git",
"reference": "f9301a5b2fb1216b2b08f02ba04dc45423db6bff"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/doctrine/inflector/zipball/f9301a5b2fb1216b2b08f02ba04dc45423db6bff",
"reference": "f9301a5b2fb1216b2b08f02ba04dc45423db6bff",
"shasum": ""
},
"require": {
"php": "^7.2 || ^8.0"
},
"require-dev": {
"doctrine/coding-standard": "^11.0",
"phpstan/phpstan": "^1.8",
"phpstan/phpstan-phpunit": "^1.1",
"phpstan/phpstan-strict-rules": "^1.3",
"phpunit/phpunit": "^8.5 || ^9.5",
"vimeo/psalm": "^4.25 || ^5.4"
},
"type": "library",
"autoload": {
"psr-4": {
"Doctrine\\Inflector\\": "lib/Doctrine/Inflector"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Guilherme Blanco",
"email": "guilhermeblanco@gmail.com"
},
{
"name": "Roman Borschel",
"email": "roman@code-factory.org"
},
{
"name": "Benjamin Eberlei",
"email": "kontakt@beberlei.de"
},
{
"name": "Jonathan Wage",
"email": "jonwage@gmail.com"
},
{
"name": "Johannes Schmitt",
"email": "schmittjoh@gmail.com"
}
],
"description": "PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural forms of words.",
"homepage": "https://www.doctrine-project.org/projects/inflector.html",
"keywords": [
"inflection",
"inflector",
"lowercase",
"manipulation",
"php",
"plural",
"singular",
"strings",
"uppercase",
"words"
],
"support": {
"issues": "https://github.com/doctrine/inflector/issues",
"source": "https://github.com/doctrine/inflector/tree/2.0.8"
},
"funding": [
{
"url": "https://www.doctrine-project.org/sponsorship.html",
"type": "custom"
},
{
"url": "https://www.patreon.com/phpdoctrine",
"type": "patreon"
},
{
"url": "https://tidelift.com/funding/github/packagist/doctrine%2Finflector",
"type": "tidelift"
}
],
"time": "2023-06-16T13:40:37+00:00"
},
{
"name": "doctrine/instantiator",
"version": "2.0.0",
@ -8972,7 +8972,7 @@
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": "^8.2",
"php": "^8.1",
"ext-curl": "*"
},
"platform-dev": [],

View file

@ -27,7 +27,8 @@
<rule ref="Generic.Files.LineLength"/>
<rule ref="Generic.Formatting.DisallowMultipleStatements"/>
<rule ref="Generic.Formatting.MultipleStatementAlignment"/>
<rule ref="Generic.Formatting.SpaceAfterCast"/>
<rule ref="Generic.Formatting.NoSpaceAfterCast"/>
<rule ref="Generic.Functions.CallTimePassByReference"/>
<rule ref="Generic.Functions.FunctionCallArgumentSpacing"/>
<rule ref="Generic.Metrics.CyclomaticComplexity"/>
<rule ref="Generic.Metrics.NestingLevel"/>
@ -41,7 +42,9 @@
<rule ref="Generic.Strings.UnnecessaryStringConcat"/>
<rule ref="Generic.WhiteSpace.DisallowTabIndent"/>
<rule ref="Generic.WhiteSpace.ScopeIndent"/>
<rule ref="Generic.WhiteSpace.LanguageConstructSpacing"/>
<rule ref="MySource.PHP.EvalObjectFactory"/>
<rule ref="MySource.PHP.GetRequestData"/>
<rule ref="MySource.PHP.AjaxNullComparison"/>
<rule ref="PEAR.Classes.ClassDeclaration"/>
<rule ref="PEAR.Commenting.InlineComment"/>
<rule ref="PSR1.Classes.ClassDeclaration"/>
@ -74,6 +77,7 @@
<rule ref="Squiz.Scope.MemberVarScope"/>
<rule ref="Squiz.Scope.MethodScope"/>
<rule ref="Squiz.Scope.StaticThisUsage"/>
<rule ref="Squiz.WhiteSpace.LanguageConstructSpacing"/>
<rule ref="Squiz.WhiteSpace.LogicalOperatorSpacing"/>
<rule ref="Squiz.WhiteSpace.MemberVarSpacing">
<properties>

View file

@ -3,27 +3,26 @@
namespace LDC\LDCCRM;
use LDC\LDCCRM\Enums\ApiStatus;
use LDC\LDCCRM\Models\Claim;
use LDC\LDCCRM\Models\Customer;
use LDC\LDCCRM\Models\SingleOptin;
use LDC\LDCCRM\Transport\ApiInterface;
/**
* This is the main class to interact with the CRM.
* This is the main class to interact with the CRM
*
* @package LDCCrmClient
*/
class CrmApiV4
{
/**
* The Api object that will handle requests and responses.
* The Api object that will handle requests and responses
*
* @var \LDC\LDCCRM\Transport\ApiInterface
*/
private static $apiInterface;
/**
* CrmApiV4.
* CrmApiV4
*
* @param string|null $endpoint
* @param string|null $bearerToken
@ -43,7 +42,7 @@ class CrmApiV4
}
/**
* Use this the ping the crm and know its current status.
* Use this the ping the crm and know its current status
*
* @return boolean
* @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs
@ -58,7 +57,7 @@ class CrmApiV4
/**
*
* Get a customer from its hashcode or email.
* Get a customer from its hashcode or email
* If it does not exists a new instance
* will be returned. You would have
* to call its save method later on.
@ -76,7 +75,7 @@ class CrmApiV4
}
/**
* Get a customer from its hashcode or email.
* Get a customer from its hashcode or email
* If it does not exists a new instance
* will be returned. You would have
* to call its save method later on.
@ -94,11 +93,10 @@ class CrmApiV4
}
/**
* Set the single optin status for an email.
* Set the single optin status for an email
*
* @param string $email
* @param boolean $opt_in
* @param array|null $answerId
* @param string $email
* @param boolean $opt_in
* @return boolean true if succeeded
* @throws \LDC\LDCCRM\Exceptions\ValidationException If a field email could not be validated.
* @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
@ -106,13 +104,13 @@ class CrmApiV4
* Possibles are : - singleOptinCustomerExists, If a customer exists with this email.
* @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
*/
public static function setStatus(#[\SensitiveParameter] string $email, bool $opt_in, ?array $answerId = null): bool
public static function setStatus(#[\SensitiveParameter] string $email, bool $opt_in): bool
{
return SingleOptin::setStatus($email, $opt_in, $answerId);
return SingleOptin::setStatus($email, $opt_in);
}
/**
* Unset the single optin status for an email.
* Set the single optin status for an email
*
* @param string $hashcode
* @return boolean true if succeeded
@ -128,50 +126,7 @@ class CrmApiV4
}
/**
* Set new claim.
*
* @param string $last_name
* @param string $first_name
* @param string $email
* @param string $message
* @param integer $subject_id
* @param string|null $address
* @param string|null $city
* @param string|null $postcode
* @param string|null $file
* @return boolean true if succeeded
* @throws \LDC\LDCCRM\Exceptions\ValidationException If a field email could not be validated.
* @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
* @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
* Possibles are : - singleOptinCustomerExists, If a customer exists with this email.
* @phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.WrongNumber
*/
public static function setClaim(
#[\SensitiveParameter] string $last_name,
#[\SensitiveParameter] string $first_name,
#[\SensitiveParameter] string $email,
#[\SensitiveParameter] string $message,
#[\SensitiveParameter] int $subject_id,
#[\SensitiveParameter] ?string $address = null,
#[\SensitiveParameter] ?string $city = null,
#[\SensitiveParameter] ?string $postcode = null,
#[\SensitiveParameter] ?string $file = null,
): bool {
return Claim::setClaim(
$last_name,
$first_name,
$email,
$message,
$subject_id,
$address,
$city,
$postcode,
$file,
);
}
/**
* Test a customer credentials to see if it can login.
* Test a customer credentials to see if it can login
*
* @param string $email
* @param string $password

View file

@ -517,30 +517,33 @@ enum Country: int
* Get valid countries label.
*
* @return array<string>
* @codeCoverageIgnore
*/
public static function getValidCountriesLabel(): array
{
return \array_map(function (self $country) {
return collect(self::getValidCountries())->map(function (self $country) {
return $country->label();
}, self::getValidCountries());
})->all();
}
/**
* Get valid countries value.
*
* @return array<string|integer>
* @codeCoverageIgnore
*/
public static function getValidCountriesValues(): array
{
return \array_map(function (self $country) {
return collect(self::getValidCountries())->map(function (self $country) {
return $country->value();
}, self::getValidCountries());
})->all();
}
/**
* Get Alpha 2 ISO code of valid countries
*
* @return array
* @codeCoverageIgnore
*/
public static function getValidIsoAplha2Codes(): array
{
@ -551,6 +554,7 @@ enum Country: int
* Get valid countries
*
* @return array
* @codeCoverageIgnore
*/
public static function getValidCountries(): array
{
@ -568,9 +572,7 @@ enum Country: int
Country::saintMartinFrenchPart,
Country::wallisAndFutuna,
Country::frenchPolynesia,
Country::newCaledonia,
Country::netherlands,
Country::germany,
Country::newCaledonia
];
}
@ -578,32 +580,32 @@ enum Country: int
* Enum classes
*
* @return array
* @codeCoverageIgnore
*/
protected static function isoCodes(): array
{
return [
'france' => 'FR',
'belgium' => 'BE',
'luxembourg' => 'LU',
'guadeloupe' => 'GP',
'martinique' => 'MQ',
'frenchGuiana' => 'GF',
'reunion' => 'RE',
'france' => 'FR',
'belgium' => 'BE',
'luxembourg' => 'LU',
'guadeloupe' => 'GP',
'martinique' => 'MQ',
'frenchGuiana' => 'GF',
'reunion' => 'RE',
'saintPierreAndMiquelon' => 'PM',
'mayotte' => 'YT',
'saintBarthelemy' => 'BL',
'saintMartinFrenchPart' => 'MF',
'wallisAndFutuna' => 'WF',
'frenchPolynesia' => 'PF',
'newCaledonia' => 'NC',
'netherlands' => 'NL',
'germany' => 'DE',
'mayotte' => 'YT',
'saintBarthelemy' => 'BL',
'saintMartinFrenchPart' => 'MF',
'wallisAndFutuna' => 'WF',
'frenchPolynesia' => 'PF',
'newCaledonia' => 'NC',
];
}
/**
* @param string $attribute
* @return integer|string|null
* @codeCoverageIgnore
*/
public function get(string $attribute): int|string|null
{

View file

@ -4,7 +4,7 @@ namespace LDC\LDCCRM\Enums;
use LDC\LDCCRM\Traits\BaseEnum;
enum LogLevel: string
enum LogLevel: int
{
use BaseEnum;

View file

@ -11,7 +11,6 @@ use Illuminate\Support\Facades\Log;
*
* @package LDCCrmClient
* @subpackage exceptions
*
*/
class CrmException extends \RuntimeException
{

View file

@ -125,7 +125,6 @@ class Answer extends ClientModel
*
* @return array
*/
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
return [

View file

@ -327,11 +327,11 @@ class ArcadiaMailDefault extends ClientModel
try {
$properties['state_order'] = (\is_object($properties['state_order']) and
get_class($properties['state_order']) === ArcadiaOrderType::class) ?
$properties['state_order']->value() : (ctype_digit((string) $properties['state_order']) ?
(int) $properties['state_order'] : $properties['state_order']);
$properties['state_order']->value() : (ctype_digit($properties['state_order']) ?
(int)$properties['state_order'] : $properties['state_order']);
} catch (\TypeError | \BadMethodCallException) {
// * Cast anyway
$properties['state_order'] = (int) $properties['state_order'];
$properties['state_order'] = (int)$properties['state_order'];
}
}
parent::fill($properties);
@ -391,7 +391,6 @@ class ArcadiaMailDefault extends ClientModel
*
* @return array
*/
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
return [

View file

@ -296,11 +296,11 @@ class ArcadiaMailGame extends ClientModel
try {
$properties['state_order'] = (\is_object($properties['state_order']) and
get_class($properties['state_order']) === ArcadiaOrderType::class) ?
$properties['state_order']->value : (ctype_digit((string) $properties['state_order']) ?
(int) $properties['state_order'] : $properties['state_order']);
$properties['state_order']->value : (ctype_digit($properties['state_order']) ?
(int)$properties['state_order'] : $properties['state_order']);
} catch (\TypeError | \BadMethodCallException) {
// * Cast anyway
$properties['state_order'] = (int) $properties['state_order'];
$properties['state_order'] = (int)$properties['state_order'];
}
}
parent::fill($properties);
@ -334,7 +334,6 @@ class ArcadiaMailGame extends ClientModel
*
* @return array
*/
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
return [

View file

@ -1,88 +0,0 @@
<?php
namespace LDC\LDCCRM\Models;
use LDC\LDCCRM\Enums\ApiStatus;
use LDC\LDCCRM\Utils;
/**
* This class allows to handle claim.
*
* @category Api Models
* @package LDCCrmClient
* @subpackage models
*/
abstract class Claim extends ClientModel
{
/**
* Validation rules.
*
* @var array
*/
protected static array $validation = [
'first_name' => 'required|string|min:3|max:255',
'last_name' => 'required|string|min:3|max:255',
'email' => 'required|email:rfc,dns,spoof,filter|max:255',
'address' => 'sometimes|nullable|string|max:255',
'city' => 'sometimes|nullable|string|min:2|max:255',
'postcode' => 'sometimes|nullable|string',
'file' => 'sometimes|nullable|string',
'message' => 'required|string|min:3',
'subject_id' => 'required|int|min:1',
];
/**
* Set new claim.
*
* @param string $last_name
* @param string $first_name
* @param string $email
* @param string $message
* @param integer $subject_id
* @param string|null $address
* @param string|null $city
* @param string|null $postcode
* @param string|null $file
* @return boolean True if succeeded.
* @throws \LDC\LDCCRM\Exceptions\ValidationException If a field could not be validated.
* @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
* @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
* @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassAfterLastUsed,Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
*/
public static function setClaim(
#[\SensitiveParameter] string $last_name,
#[\SensitiveParameter] string $first_name,
#[\SensitiveParameter] string $email,
#[\SensitiveParameter] string $message,
#[\SensitiveParameter] int $subject_id,
#[\SensitiveParameter] ?string $address = null,
#[\SensitiveParameter] ?string $city = null,
#[\SensitiveParameter] ?string $postcode = null,
#[\SensitiveParameter] string|null $file = null,
): bool {
// @phpcs:enable
$params = compact(
'last_name',
'first_name',
'email',
'message',
'subject_id',
'address',
'city',
'postcode',
'file',
);
// Validate all data.
foreach ($params as $key => $value) {
self::validateValue($key, $value);
}
static::setUpApiInterface();
$response = static::$apiInterface->call(
Utils::getResquest('apiV4.claim.store', [], $params)
);
return $response->status->equals(ApiStatus::OK);
}
}

View file

@ -146,7 +146,7 @@ abstract class ClientModel implements \JsonSerializable
$type = $this->getPropType($field);
// * Force boolean
if ($type === 'bool') {
$value = (\is_int($value) and ($value === 1 or $value === 0)) ? (bool) $value : $value;
$value = (\is_int($value) and ($value === 1 or $value === 0)) ? (bool)$value : $value;
}
if (!is_null($value) and !$this->checkFieldType($type, $value)) {
throw new ValidationException("Wrong type for $field");
@ -270,7 +270,7 @@ abstract class ClientModel implements \JsonSerializable
case '\\' . ArcadiaOrderType::class:
return $checkValueIsEnum(\ltrim($type, '\\'), $value);
case 'boolean':
return \is_bool(\is_int($value) ? (bool) $value : $value);
return \is_bool(\is_int($value) ? (bool)$value : $value);
case 'array':
return \is_array($value);
case 'string':

View file

@ -355,11 +355,11 @@ class Customer extends ClientModel
try {
$properties['country'] = (\is_object($properties['country']) and
get_class($properties['country']) === Country::class) ?
$properties['country']->value : (is_numeric(trim($properties['country'])) ?
(int) $properties['country'] : $properties['country']);
$properties['country']->value : (ctype_digit($properties['country']) ?
(int)$properties['country'] : $properties['country']);
} catch (TypeError | \BadMethodCallException $e) {
// * Cast anyway
$properties['country'] = (int) $properties['country'];
$properties['country'] = (int)$properties['country'];
}
}
parent::fill($properties);
@ -614,7 +614,6 @@ class Customer extends ClientModel
*
* @return array
*/
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
return [

View file

@ -154,11 +154,11 @@ class Question extends ClientModel
try {
$properties['type'] = (\is_object($properties['type']) and
get_class($properties['type']) === QuestionType::class) ?
$properties['type']->value : (ctype_digit((string) $properties['type']) ?
(int) $properties['type'] : $properties['type']);
$properties['type']->value : (ctype_digit($properties['type']) ?
(int)$properties['type'] : $properties['type']);
} catch (\TypeError | \BadMethodCallException) {
// * Cast anyway
$properties['type'] = (int) $properties['type'];
$properties['type'] = (int)$properties['type'];
}
}
parent::fill($properties);
@ -298,7 +298,6 @@ class Question extends ClientModel
*
* @return array
*/
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
return [

View file

@ -27,32 +27,26 @@ abstract class SingleOptin extends ClientModel
];
/**
* Set the single opt in status for an email,
* with an optionnal answer associated.
* Set the single opt in status for an email
*
* @param string $email
* @param boolean $opt_in
* @param array<int,int>|null $answerId
* @param string $email
* @param boolean $opt_in
* @return boolean true if succeeded
* @throws \LDC\LDCCRM\Exceptions\ValidationException If a field email could not be validated.
* @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
* @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
* Possibles are : - singleOptinCustomerExists, If a customer exists with this email.
*/
public static function setStatus(#[\SensitiveParameter] string $email, bool $opt_in, ?array $answerId = null): bool
public static function setStatus(#[\SensitiveParameter] string $email, bool $opt_in): bool
{
self::validateValue('email', $email);
static::setUpApiInterface();
$request = Utils::getResquest('apiV4.optin', [], [
'email' => $email,
'opt_in' => $opt_in
]);
$payload = [
'email' => $email,
'opt_in' => $opt_in,
'answer_id' => (!empty($answerId)) ? $answerId : null,
];
$response = static::$apiInterface->call(
Utils::getResquest('apiV4.optin', [], array_filter($payload, fn($v) => !is_null($v)))
);
$response = static::$apiInterface->call($request);
return $response->status->equals(ApiStatus::OK);
}

View file

@ -2,7 +2,7 @@
namespace LDC\LDCCRM\Traits;
use Doctrine\Inflector\InflectorFactory;
use Illuminate\Support\Str;
trait BaseEnum
{
@ -48,16 +48,15 @@ trait BaseEnum
{
if (empty(self::getCache('labels'))) {
$labels = self::getLabelsConstant();
$array = [];
\array_map(function ($enum) use (&$array, $labels) {
if (!\is_null($labels) and !isset($labels[$enum->name])) {
throw new \Error('Missing definition label ' . self::class . " for {$enum->name}");
}
$array = array_merge($array, [$enum->name => __(
!\is_null($labels) ? $labels[$enum->name] : ucfirst($enum->name)
)]);
}, self::cases());
self::setCache('labels', $array);
self::setCache('labels', \collect(self::cases())
->mapWithKeys(function ($enum) use ($labels) {
if (!\is_null($labels) and !isset($labels[$enum->name])) {
throw new \Error('Missing definition label ' . self::class . " for {$enum->name}");
}
return [$enum->name => \trans(
!\is_null($labels) ? $labels[$enum->name] : Str::ucfirst($enum->name)
)];
})->all());
}
return self::getCache('labels');
}
@ -70,11 +69,8 @@ trait BaseEnum
public static function toValues(): array
{
if (empty(self::getCache('values'))) {
$array = [];
\array_map(function ($enum) use (&$array) {
$array = array_merge($array, [$enum->name => $enum->value]);
}, self::cases());
self::setCache('values', $array);
self::setCache('values', \collect(self::cases())
->mapWithKeys(fn ($enum) => [$enum->name => $enum->value])->all());
}
return self::getCache('values');
}
@ -98,25 +94,23 @@ trait BaseEnum
{
if (empty(self::getCache('enums'))) {
$definitions = self::getCustomDefinitions();
$array = [];
$inflector = InflectorFactory::create()->build();
\array_map(function ($enum) use (&$array, $definitions, $inflector) {
$baseArray = [
'name' => $enum->name,
'label' => $enum->label(),
'value' => $enum->value,
];
foreach ($definitions as $index => $elements) {
$index = $inflector->singularize(strtolower($index));
if (!isset($elements[$enum->name])) {
throw new \Error("Missing definition {$index} " . self::class . " for {$enum->name}");
self::setCache('enums', \collect(self::cases())
->mapWithKeys(function ($enum) use ($definitions) {
$baseArray = [
'name' => $enum->name,
'label' => $enum->label(),
'value' => $enum->value,
];
foreach ($definitions as $index => $elements) {
$index = Str::lower(Str::singular($index));
if (!isset($elements[$enum->name])) {
throw new \Error("Missing definition {$index} " . self::class . " for {$enum->name}");
}
$baseArray[$index] = $elements[$enum->name];
}
$baseArray[$index] = $elements[$enum->name];
}
$array = array_merge($array, [$enum->name => (object) $baseArray]);
}, self::cases());
self::setCache('enums', $array);
} //end if
return [$enum->name => (object)$baseArray];
})->all());
}
return self::getCache('enums');
}
@ -129,7 +123,8 @@ trait BaseEnum
*/
public static function make(self|int|string $value, string $field = 'value'): self|null
{
return !\is_object($value) ? self::cases()[array_search($value, array_column(self::cases(), $field))] : $value;
return !\is_object($value) ?
\collect(self::cases())->keyBy($field)->get($value) : $value;
}
/**
@ -142,7 +137,7 @@ trait BaseEnum
public function equals(object ...$others): bool
{
foreach ($others as $other) {
if (!\in_array(BaseEnum::class, $this->classUsesRecursive($other))) {
if (!\in_array(BaseEnum::class, \class_uses_recursive($other))) {
throw new \Error(__METHOD__ .
' requires $enum to use ' . BaseEnum::class);
}
@ -209,8 +204,8 @@ trait BaseEnum
{
if (!isset($GLOBALS[self::class])) {
$GLOBALS[self::class] = [
'props' => [
'enums' => [],
'props' => [
'enums' => [],
'values' => [],
'labels' => []
],
@ -246,65 +241,17 @@ trait BaseEnum
{
// ? Has custom props in cache ?
if (!isset($GLOBALS[self::class]) or \is_null($GLOBALS[self::class]['customProps'])) {
$names = [];
\array_map(function (self $enum) use (&$names) {
$names = array_merge($names, [$enum->name => $enum]);
}, self::cases());
$names = \collect(self::cases())->keyBy('name');
$GLOBALS[self::class]['customProps'] = \array_filter(
(new \ReflectionClass(self::class))->getConstants(),
function (mixed $constant, string $key) use ($names) {
$GLOBALS[self::class]['customProps'] = \collect((new \ReflectionClass(self::class))->getConstants())
->filter(function (mixed $constant, string $key) use ($names) {
if ($key === 'LABELS' or !\is_array($constant)) {
return false;
}
return count(\array_filter(
array_flip($constant),
function (string $name) use ($names) {
return array_key_exists($name, $names);
}
));
},
ARRAY_FILTER_USE_BOTH
);
} //end if
return \collect($constant)->keys()
->filter(fn (string $name) => $names->has($name))->count();
})->all();
}
return $GLOBALS[self::class]['customProps'];
}
/**
* Returns all traits used by a class, its parent classes and trait of their traits.
*
* @param object|string $class
* @return array
*/
private function classUsesRecursive($class)
{
if (is_object($class)) {
$class = get_class($class);
}
$results = [];
foreach (array_reverse(class_parents($class) ?: []) + [$class => $class] as $class) {
$results += $this->traitUsesRecursive($class);
}
return array_unique($results);
}
/**
* Returns all traits used by a trait and its traits.
*
* @param object|string $trait
* @return array
*/
private function traitUsesRecursive($trait)
{
$traits = class_uses($trait) ?: [];
foreach ($traits as $trait) {
$traits += $this->traitUsesRecursive($trait);
}
return $traits;
}
}

View file

@ -101,10 +101,11 @@ class Response
$this->message = $response->getReasonPhrase();
}
// * Body should be json data.
if (($decodedJson = $this->tryDecodeJson($this->body->getContents())) === false) {
if (Utils::getConfig('app.env') === 'testing') {
dump((string) $this->body);
dump((string)$this->body);
}
throw new CrmException('The Api should have returned JSON data');
}

View file

@ -9,6 +9,7 @@ use LDC\LDCCRM\Exceptions\SkipValidationException;
use LDC\LDCCRM\Exceptions\ValidationException;
use LDC\LDCCRM\Transport\Request;
use Respect\Validation\Validator;
use Illuminate\Support\Str;
/**
* This is the LDCCRM utility class
@ -280,7 +281,7 @@ class Utils
),
'validate' => function () use ($value, $params) {
if (\is_string($value)) {
return \strlen($value) === (int) $params[0];
return \strlen($value) === (int)$params[0];
}
return false;
}
@ -307,10 +308,10 @@ class Utils
),
'validate' => function () use ($value, $params) {
if (\is_string($value)) {
return \strlen($value) >= (int) $params[0];
return \strlen($value) >= (int)$params[0];
}
if (\is_int($value)) {
return $value >= (int) $params[0];
return $value >= (int)$params[0];
}
return false;
}
@ -337,10 +338,10 @@ class Utils
),
'validate' => function () use ($value, $params) {
if (\is_string($value)) {
return \strlen($value) <= (int) $params[0];
return \strlen($value) <= (int)$params[0];
}
if (\is_int($value)) {
return $value <= (int) $params[0];
return $value <= (int)$params[0];
}
return false;
}
@ -569,10 +570,10 @@ class Utils
): Request {
// Convert bool to integer.
$query = \array_map(function ($v) {
return is_bool($v) ? (int) $v : $v;
return is_bool($v) ? (int)$v : $v;
}, $query);
$data = \array_map(function ($v) {
return is_bool($v) ? (int) $v : $v;
return is_bool($v) ? (int)$v : $v;
}, $data);
$routes = \json_decode(\file_get_contents(__DIR__ . '/routes.json'), true);
@ -599,7 +600,7 @@ class Utils
$route['uri'] = sprintf('%s?%s', $route['uri'], \http_build_query($query));
}
return new Request(
HttpMethods::make(strtolower($route['methods'][0]), 'name'),
HttpMethods::make(Str::lower($route['methods'][0]), 'name'),
$route['uri'],
[],
$data
@ -654,29 +655,29 @@ class Utils
{
$message = "LDC CRM: $message";
if (\class_exists('\Illuminate\Support\Facades\Log')) {
switch ($level) {
case LogLevel::EMERG:
switch ($level->value) {
case LogLevel::EMERG->value():
\Illuminate\Support\Facades\Log::emergency($message);
break;
case LogLevel::ALERT:
case LogLevel::ALERT->value():
\Illuminate\Support\Facades\Log::alert($message);
break;
case LogLevel::CRIT:
case LogLevel::CRIT->value():
\Illuminate\Support\Facades\Log::critical($message);
break;
case LogLevel::ERR:
case LogLevel::ERR->value():
\Illuminate\Support\Facades\Log::error($message);
break;
case LogLevel::WARNING:
case LogLevel::WARNING->value():
\Illuminate\Support\Facades\Log::warning($message);
break;
case LogLevel::NOTICE:
case LogLevel::NOTICE->value():
\Illuminate\Support\Facades\Log::notice($message);
break;
case LogLevel::INFO:
case LogLevel::INFO->value():
\Illuminate\Support\Facades\Log::info($message);
break;
case LogLevel::DEBUG:
case LogLevel::DEBUG->value():
\Illuminate\Support\Facades\Log::debug($message);
break;
} //end switch

View file

@ -181,7 +181,7 @@ class WPCrm
public static function check()
{
self::bootSessionIfNeeded();
return (bool) self::getUser();
return (bool)self::getUser();
}
/**
@ -264,7 +264,6 @@ class WPCrm
return false;
}
try {
$customer->opt_in = !$customer->opt_in;
if (!self::makeApiV4Call($customer, 'save')) {
return false;
}
@ -277,6 +276,7 @@ class WPCrm
throw $e;
}
}
$customer->opt_in = !$customer->opt_in;
return true;
}
@ -284,9 +284,8 @@ class WPCrm
* Set the single optin status for an email
* on the crm
*
* @param string $email
* @param boolean $opt_in
* @param array|null $answerId
* @param string $email
* @param boolean $opt_in
*
* @return boolean true if the operation succeeded false otherwise
* @throws \LDC\LDCCRM\Exceptions\ValidationException If a field email could not be validated.
@ -294,19 +293,20 @@ class WPCrm
* @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
* Possibles are : - singleOptinCustomerExists, If a customer exists with this email.
*/
public static function setSingleOptin(string $email, bool $opt_in, ?array $answerId = null): bool
public static function setSingleOptin(string $email, bool $opt_in): bool
{
return self::makeApiV4Call(
SingleOptin::class,
'setStatus',
array_filter([$email, $opt_in, $answerId], fn($v) => !is_null($v))
);
return self::makeApiV4Call(SingleOptin::class, 'setStatus', [
$email, $opt_in
]);
}
/**
* Activate the current user
* Toggle the current user optin value
* on the current user and the crm
*
* @return boolean True if the operation succeeded.
* @throws \LDC\LDCCRM\Exceptions\ValidationException If a customer's hashcode could not be validated.
* @throws \LDC\LDCCRM\Exceptions\CrmException If an error occurs on server side or on getting response.
* @throws \LDC\LDCCRM\Exceptions\ApiErrorException If any error or \LDC\LDCCRM\Enums\ApiError occurs.
* Possibles are : - modelNotFound, If this customer hashcode could not be found.
* - customerAlreadyActive, It the customer is already activated.
@ -319,19 +319,10 @@ class WPCrm
if ($customer->status) {
return true;
}
try {
if (!self::makeApiV4Call($customer, 'activate')) {
return false;
}
} catch (ApiErrorException $e) {
switch ($e->getApiError()) {
case ApiError::authorizationException->value():
case ApiError::modelNotFound->value():
return false;
default:
throw $e;
}
if (!self::makeApiV4Call($customer, 'activate')) {
return false;
}
$customer->opt_in = !$customer->opt_in;
return true;
}
@ -451,7 +442,7 @@ class WPCrm
return \forward_static_call_array([$obj, $method], $arguments);
} catch (ApiErrorException $e) {
switch ($e->getApiError()) {
case ApiError::apiAuthFailed:
case ApiError::apiAuthFailed->value():
Utils::log($e->getMessage(), LogLevel::CRIT);
throw $e;
default:

View file

@ -187,7 +187,6 @@ class WPCrmUser implements JsonSerializable
*
* @return array
*/
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
return [

View file

@ -108,11 +108,5 @@
"GET",
"HEAD"
]
},
"apiV4.claim.store": {
"uri": "api/v4/claim",
"methods": [
"POST"
]
}
}