Current File : /var/www/vinorea/modules/klaviyopsautomation/classes/Webservice/QueryServices/QueryServiceTrait.php
<?php

namespace KlaviyoPs\Classes\Webservice\QueryServices;

if (!defined('_PS_VERSION_')) {
    exit;
}

use KlaviyoPs\Classes\KlaviyoValue;
use ObjectModel;
use PrestaShop\PrestaShop\Adapter\Entity\WebserviceRequest;
use WebserviceException;

trait QueryServiceTrait
{
    /**
     * Removes last record returned from query if results count equals one greater than batch size. Format and encode
     * cursor from this record.
     *
     * Example cursor to be encoded (primary key field name and value): 'id_cart:10'
     *
     * @param $records array
     * @return string
     */
    public function getCursorValue(&$records, $batchSize): string
    {
        $nextCursor = '';
        if (!(count($records) < $batchSize)) {
            $cursorRecord = array_pop($records);
            $recordKey = key($cursorRecord);
            $nextCursor = base64_encode($recordKey . ':' . $cursorRecord[$recordKey]);
        }

        return $nextCursor;
    }

    /**
     * Validate batch size parameter does not exceed maximum, cast to integer and increment by one for cursor pagination.
     *
     * Note that actually a max of ($batchSize + 1) records will be returned from the DB.
     * @param string $batchSize
     * @return int
     */
    public function handleBatchSizeParam($batchSize): int
    {
        $validatedBatchSize = KlaviyoValue::WEBSERVICE_DEFAULT_BATCH_SIZE;
        if (ctype_digit((string) $batchSize)) {
            $validatedBatchSize = min($batchSize, KlaviyoValue::WEBSERVICE_MAX_BATCH_SIZE);
        }
        // Fetch one extra record than batch size to use as next cursor.
        return $validatedBatchSize + 1;
    }

    /**
     * Ensure that shop ID exists in the db.
     *
     * @param string $shopId
     * @return int|null
     * @throws WebserviceException
     */
    public function handleShopParam($shopId)
    {
        if ('' === $shopId || !$shopId) {
            return null;
        } elseif (ctype_digit((string) $shopId) && ObjectModel::existsInDatabase((int) $shopId, 'shop')) {
            return (int) $shopId;
        } else {
            throw new WebserviceException(
                sprintf('\'%s\' is not a valid Shop ID.', $shopId),
                [$this->DEFAULT_ERROR_CODE, 400]
            );
        }
    }

    /**
     * Handles productIds params. Ensures it is valid stringified array literal
     *
     *  handleProductIdsParam('[1,2,4]') => [1,2,4]
     *  handleProductIdsParam('[1,,4]') => WebserviceException
     *  handleProductIdsParam('[word]') => WebserviceException
     *  handleProductIdsParam('[  1]') => [1]
     *
     *
     * @param string $productIds
     * @return non-empty-array|null
     * @throws WebserviceException in case of malformed literal or non-int values as members
     */
    public function handleProductIdsParam(string $productIds)
    {
        $idFields = $this->parseStrArray($productIds);
        if (!$idFields) {
            throw new WebserviceException(
                sprintf('\'%s\' is not a valid array of Product IDs.', $productIds),
                [$this->DEFAULT_ERROR_CODE, 400]
            );
        }
        foreach ($idFields as $val) {
            $val = (int)$val;
            if (!$val) { // product ids are autoinc values.
                throw new WebserviceException(
                    sprintf('\'%s\' is not a valid array of Product IDs.', $productIds),
                    [$this->DEFAULT_ERROR_CODE, 400]
                );
            }
        }

        return $idFields;
    }


    /**
     * Parses string representation of an array
     *
     * @param string $str
     * @return array Parsed array
     */
    public static function parseStrArray(string $str)
    {
        $wsProxy = new class extends WebserviceRequest {
            public function parseDisplayFields($str)
            {
                return array_values(parent::parseDisplayFields($str))[0];
            }
        };
        return $wsProxy->parseDisplayFields($str);
    }

    /**
     * Decode and validate next parameter for cursor pagination.
     *
     * Example cursor: array('id_cart' => 10)
     *
     * @param $nextParam
     * @return false|string[]|null
     * @throws WebserviceException
     */
    public function handleNextParam($nextParam)
    {
        // Return null if $nextParam is empty string or null (wasn't included in query params).
        if (!$nextParam) {
            return null;
        }
        try {
            $nextValue = explode(':', base64_decode($nextParam));
        } catch (Exception $e) {
            throw new WebserviceException(
                $e->getMessage(),
                [$this->DEFAULT_ERROR_CODE, 400]
            );
        }
        if (count($nextValue) != 2) {
            throw new WebserviceException(
                'Invalid next parameter.',
                [$this->DEFAULT_ERROR_CODE, 400]
            );
        }
        return $nextValue;
    }

    /**
     * Format array containing query results and cursor to retrieve next page.
     *
     * @param $records
     * @param $cursorValue
     * @return array
     */
    public function buildCursorResultsPayload($records, $cursorValue)
    {
        return array(
            'data' => $records,
            'next_cursor' => $cursorValue,
        );
    }
}