* @license MIT https://opensource.org/licenses/MIT * @link / */ namespace LDC\LDCCRM\WordPress; use Exception; use LDC\LDCCRM\CrmApiV2; use LDC\LDCCRM\Enums\ApiError; use LDC\LDCCRM\Exceptions\ApiErrorException; use LDC\LDCCRM\Exceptions\CrmException; use LDC\LDCCRM\Models\ArcadiaMailDefault; use LDC\LDCCRM\Models\ArcadiaMailGame; use LDC\LDCCRM\Models\Customer; use LDC\LDCCRM\Models\SingleOptin; use ReflectionClass; // phpcs:ignore Squiz.PHP.CommentedOutCode.Found // TABLE LDC CUSTOMERS // CREATE TABLE `ldc_wp_customers` ( // `hashcode` VARCHAR(36) NOT NULL DEFAULT '' COMMENT 'Le hashcode (UUID)', // `email` VARCHAR(255) NOT NULL DEFAULT '' COMMENT 'Le customer email', // PRIMARY KEY (`hashcode`) // ) // COMMENT='Les customers sur un WP liées à la CRM' // COLLATE='utf8mb4_unicode_ci'; /** * Class de gestion des users en session avec Wordpress (ce truc immonde) * * @category API * @package LDCCrmClient * @subpackage Wordpress * @author Jérémy Munsch * @license MIT https://opensource.org/licenses/MIT * @link / */ class WPCrm { private static $sessionKey = 'LDC_CRM_USER'; private static $sessionDestroyed = false; /** * The user object * * @var \LDC\LDCCRM\CrmApiV2 */ protected static $api = null; /** * The user object * * @var \LDCCRM\WPCrmUser */ protected static $user = null; /** * Try to login with CRM API * return api response code if an error occurs * * @param string $email The customer email * @param string $password The customer password * * @return \LDCCRM\WPCrmUser|false */ public static function login($email, $password) { self::bootSessionIfNeeded(); return self::loginUserWithApi($email, $password); } /** * Get the current user * return null if the user is not logged in * * @return \LDCCRM\WPCrmUser|null */ public static function getUser() { self::bootSessionIfNeeded(); return self::$user; } /** * Get the current user * return api response code if an error occurs * * @param string $identification The customer hashcode or email * * @return \LDCCRM\WPCrmUser|false */ public static function getUserFromApi(string $identification) { self::initLdcApi(); try { if (!($response = self::makeApiV2Call(self::$api, 'getCustomer', [$identification]))) { return $response; } } catch (ApiErrorException $e) { switch ($e->getApiError()) { case ApiError::modelNotFound(): return false; default: throw $e; } } /** @var \LDC\LDCCRM\Models\Customer */ $customer = $response; self::setUser($customer); return self::$user; } /** * Get the current user * return null if the user is not logged in * * @param string $email The customer email * @param string $password The customer password * * @return \LDCCRM\WPCrmUser|false * @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 */ private static function loginUserWithApi(string $email, string $password) { self::initLdcApi(); try { if (!($response = self::makeApiV2Call(self::$api, 'login', [$email, $password]))) { return $response; } } catch (ApiErrorException $e) { switch ($e->getApiError()) { case ApiError::customerNotActivated(): case ApiError::modelNotFound(): case ApiError::authFailed(): return false; default: throw $e; } } if ($out = self::getUserFromApi($email)) { self::saveOrUpdateUserToTable(); } return $out; } /** * Destroy the customer from session * and therefore logout * * @return void */ public static function logout() { self::bootSessionIfNeeded(); unset($_SESSION[self::$sessionKey]); session_destroy(); self::$sessionDestroyed = true; } /** * Check if the user is Authenticated * * @return bool */ public static function check() { self::bootSessionIfNeeded(); return (bool)self::getUser(); } /** * Save current customer to * the local database and on crm * * @return boolean true if the operation succeeded false otherwise * @throws \LDC\LDCCRM\Exceptions\ApiErrorException * with \LDC\LDCCRM\Enums\ApiError::customerExists() */ public static function saveUser(): bool { if (!self::getUser() or !($customer = self::getCustomer())) { return false; } try { if (!self::makeApiV2Call($customer, 'save')) { return false; } } catch (ApiErrorException $e) { switch ($e->getApiError()) { case ApiError::modelNotFound(): return false; default: throw $e; } } self::saveOrUpdateUserToTable(); return true; } /** * Delete current customer from * the local database and the crm * * @return boolean true if the operation succeeded */ public static function deleteUser(): bool { if (!self::getUser() or !($customer = self::getCustomer())) { return false; } try { if (!self::makeApiV2Call($customer, 'delete')) { return false; } } catch (ApiErrorException $e) { switch ($e->getApiError()) { case ApiError::modelNotFound(): return false; default: throw $e; } } self::deleteUserFromTable(); return true; } /** * Toggle the current user optin value * on the current user and the crm * * @return boolean true if the operation succeeded * @throws \LDC\LDCCRM\Exceptions\ApiErrorException * with \LDC\LDCCRM\Enums\ApiError::singleOptinCustomerExists() */ public static function toggleUserOptin(): bool { if (!self::getUser() or !($customer = self::getCustomer())) { return false; } try { if (!self::makeApiV2Call($customer, 'save')) { return false; } } catch (ApiErrorException $e) { switch ($e->getApiError()) { case ApiError::modelNotFound(): return false; default: throw $e; } } $customer->opt_in = !$customer->opt_in; return true; } /** * Set the single optin status for an email * on the crm * * @param string $email * @param boolean $opt_in * * @return boolean true if the operation succeeded false otherwise * @throws \LDC\LDCCRM\Exceptions\ApiErrorException * with \LDC\LDCCRM\Enums\ApiError::singleOptinCustomerExists() */ public static function setSingleOptin(string $email, bool $opt_in): bool { return self::makeApiV2Call(SingleOptin::class, 'setStatus', [ $email, $opt_in ]); } /** * send An arcadia mail with type default * This methods requires to have a user in session (to be logged in) * * @param ArcadiaMailDefault $mail * @return boolean true if succeed */ public static function sendArcadiaMailDefault(ArcadiaMailDefault $mail): bool { if (!self::getUser() or !($customer = self::getCustomer())) { return false; } $customer = self::getCustomer(); return $mail->send($customer); } /** * send An arcadia mail with type game * This methods requires to have a user in session (to be logged in) * * @param ArcadiaMailGame $mail * @return boolean true if succeed */ public static function sendArcadiaMailGame(ArcadiaMailGame $mail): bool { if (!self::getUser() or !($customer = self::getCustomer())) { return false; } $customer = self::getCustomer(); return $mail->send($customer); } /** * Toggle the current user optin value * on the current user and the crm * * @return boolean true if the operation succeeded */ public static function activateUser(): bool { if (!self::getUser() or !($customer = self::getCustomer())) { return false; } if ($customer->status) { return true; } if (!self::makeApiV2Call($customer, 'activate')) { return false; } $customer->opt_in = !$customer->opt_in; return true; } // --- PRIVATE --- METHODS /** * Get all customer infos * * @return \LDC\LDCCRM\Models\Customer|null */ private static function getCustomer(): ?Customer { if (!self::getUser()) { return null; } if (!self::getRawProperty(self::$user, 'customer')) { self::getUserFromApi(self::$user->hashcode); } /** @var \LDC\LDCCRM\Models\Customer */ $customer = self::getRawProperty(self::$user, 'customer'); return $customer; } /** * Create a user * stores it to the session * and finally saves it to the database if it does not exists * * @var \LDC\LDCCRM\Models\Customer $customer * * @return void */ private static function setUser(Customer $customer) { self::bootSessionIfNeeded(); if (!self::$user) { self::$user = new self($customer->hashcode, $customer->email); } self::$user->setInfo($customer); $_SESSION[self::$sessionKey] = json_encode(self::$user); } /** * Get the initialized API object * * @return \LDCCRM\ApiV1 */ private static function initLdcApi() { if (!self::$api) { if (!extension_loaded('curl')) { throw new Exception( 'WPCrm requires php extension curl' ); } self::$api = new CrmApiV2(); } return self::$api; } /** * Make a call using apiV2 * * @param string $method * @param array $arguments * @return mixed|false */ private static function makeApiV2Call($obj, string $method, array $arguments = []) { try { return \forward_static_call_array([$obj, $method], $arguments); } catch (ApiErrorException $e) { switch ($e->getApiError()) { case ApiError::apiAuthFailed(): default: self::logError($e->getMessage()); throw $e; } } catch (CrmException $e) { self::logError($e->getMessage()); return false; } } private static function logError(string $message): void { // phpcs:ignore Squiz.PHP.DiscouragedFunctions.Found error_log($message); } /** * Boot the php session if needed * * @return void */ private static function bootSessionIfNeeded() { if (!session_id() && !self::$sessionDestroyed) { session_start(); } if (!self::$user and array_key_exists(self::$sessionKey, $_SESSION)) { /** * The user object * * @var \LDCCRM\WPCrmUser */ self::$user = WPCrmUser::parseFromJson( $_SESSION[self::$sessionKey] ?? null ); } } /** * Get a customer from table * * @param string $hashcode The customer hashcode * * @return object|null */ public static function getUserFromTable(string $hashcode) { return self::getWpDb()->get_row( 'SELECT * FROM `ldc_wp_customers` WHERE `hashcode` = ' . $hashcode ); } /** * Get a customer from table by an email * * @param int $email The customer email * * @return object|null */ public static function getUserFromTableByEmail($email) { return self::getWpDb()->get_row( 'SELECT * FROM `ldc_wp_customers` WHERE `email` = "' . $email . '"' ); } /** * Get a customer from table * * @return object|null */ public static function getUserToTable() { return self::getWpDb()->get_row( 'SELECT * FROM `ldc_wp_customers` WHERE `hashcode` = ' . self::$user->hashcode ); } /** * Save or update the user to the table * * @return void */ private static function saveOrUpdateUserToTable() { if (self::getUserToTable()) { self::query( 'UPDATE `ldc_wp_customers` SET `hashcode` = %s, `email` = %s WHERE `hashcode` = %s', [ 'hashcode' => self::$user->hashcode, 'email' => self::$user->email, 'hashcode' => self::$user->hashcode ] ); } else { self::query( 'INSERT INTO `ldc_wp_customers` VALUES (%s, %s)', [ 'hashcode' => self::$user->hashcode, 'email' => self::$user->email, ] ); } } /** * Save or update the user to the table * * @return void */ private static function deleteUserFromTable() { self::query( 'DELETE FROM `ldc_wp_customers` WHERE `hashcode` = %s;', [ 'hashcode' => self::$user->hashcode ] ); } /** * Query in DB * * @param string $query La request avec les variables en points d'interrogation * @param array $params Les paramètres des la requète * * @return object Containing the row columns */ private static function query($query, array $params = []) { return self::getWpDb()->query( self::getWpDb()->prepare($query, $params) ); } /** * Get WP 'pdo instance' * * @return object The $wpdb variable */ private static function getWpDb() { // phpcs:ignore Squiz.PHP.GlobalKeyword.NotAllowed global $wpdb; return $wpdb; } /** * Get a property * * @param string $field * @param mixed $value * @return mixed */ protected static function getRawProperty(object $object, string $field) { $refClass = new ReflectionClass(\get_class($object)); $refProp = $refClass->getProperty($field); $refProp->setAccessible(true); return $refProp->getValue($object); } }