<commit_before><?php
namespace Phwoolcon\Model;

use Phalcon\Di;
use Phwoolcon\Events;
use Phwoolcon\Exception\OrderException;
use Phwoolcon\Model;

/**
 * Class Order
 * @package Phwoolcon\Model
 *
 * @property Di     $_dependencyInjector
 * @property string $status
 * @method string getStatus()
 * @method string getTradeId()
 * @method Order setStatus(string $status)
 */
class Order extends Model
{
    const STATUS_CANCELED = 'canceled';
    const STATUS_COMPLETE = 'complete';
    const STATUS_FAILED = 'failed';
    const STATUS_PENDING = 'pending';
    const STATUS_PROCESSING = 'processing';

    const CALLBACK_STATUS_DONE = 'done';
    const CALLBACK_STATUS_FAILED = 'failed';
    const CALLBACK_STATUS_TRIED = 'tried';

    protected $_table = 'orders';
    protected $keyFields = [
        'product_name',
        'user_id',
        'amount',
    ];

    protected $protectedFieldsOnPreparation = [
        'id',
        'txn_id',
        'created_at',
        'completed_at',
        'status',
    ];

    protected $orderData;

    /**
     * @return $this
     * @codeCoverageIgnore
     */
    public function generateDistributedId()
    {
        return $this->generateOrderId('NA');
    }

    public function generateOrderId($prefix = '')
    {
        $orderId = $prefix . (date('Y') - 2004) . date('md') . substr(time(), -5) . substr(microtime(), 2, 3) .
            static::$_distributedOptions['node_id'] . mt_rand(100, 999);
        $hasOrderId = $this->findFirst([
            'id = :id:',
            'bind' => [
                'id' => $orderId,
            ],
        ]);
        // @codeCoverageIgnoreStart
        if ($hasOrderId) {
            return $this->generateOrderId($prefix);
        }
        // @codeCoverageIgnoreEnd
        $this->setId($orderId);
        return $this;
    }

    public function getByTradeId($tradeId, $clientId)
    {
        return $this->findFirst([
            'trade_id = :tradeId: AND client_id = :clientId:',
            'bind' => compact('tradeId', 'clientId'),
        ]);
    }

    public function getKeyFields()
    {
        $fields = array_values($this->keyFields);
        return array_combine($fields, $fields);
    }

    /**
     * @param string $key
     * @return mixed|OrderData
     */
    public function getOrderData($key = null)
    {
        if ($this->orderData === null) {
            if ($existingOrderData = $this->__get('order_data')) {
                $this->orderData = $existingOrderData;
            } else {
                $this->orderData = $this->_dependencyInjector->get(OrderData::class);
                $this->__set('order_data', $this->orderData);
            }
        }
        $data = $this->orderData->getData('data');
        return $key ? fnGet($data, $key) : $this->orderData;
    }

    public function getProtectedFieldsOnPreparation()
    {
        return $this->protectedFieldsOnPreparation;
    }

    public function initialize()
    {
        $class = OrderData::class;
        $this->_dependencyInjector->has($class) and $class = $this->_dependencyInjector->getRaw($class);
        $this->hasOne('id', $class, 'order_id', ['alias' => 'order_data']);
        parent::initialize();
    }

    public static function prepareOrder($data)
    {
        /* @var Order $order */
        $order = Di::getDefault()->get(static::class);
        // Load existing order if any
        $existingOrder = $order->getByTradeId(fnGet($data, 'trade_id'), fnGet($data, 'client_id'));
        if (isset($existingOrder->id)) {
            $order = $existingOrder;
            $status = $order->getStatus();
            if ($status != static::STATUS_PENDING) {
                $failureMessages = [
                    static::STATUS_PROCESSING => 'Order is under processing, please do not submit repeatedly',<commit_msg>feat: check trade_id and client_id in Order::prepareOrder()<commit_after><?php
namespace Phwoolcon\Model;

use Phalcon\Di;
use Phwoolcon\Events;
use Phwoolcon\Exception\OrderException;
use Phwoolcon\Model;

/**
 * Class Order
 * @package Phwoolcon\Model
 *
 * @property Di     $_dependencyInjector
 * @property string $status
 * @method string getStatus()
 * @method string getTradeId()
 * @method Order setStatus(string $status)
 */
class Order extends Model
{
    const STATUS_CANCELED = 'canceled';
    const STATUS_COMPLETE = 'complete';
    const STATUS_FAILED = 'failed';
    const STATUS_PENDING = 'pending';
    const STATUS_PROCESSING = 'processing';

    const CALLBACK_STATUS_DONE = 'done';
    const CALLBACK_STATUS_FAILED = 'failed';
    const CALLBACK_STATUS_TRIED = 'tried';

    protected $_table = 'orders';
    protected $keyFields = [
        'product_name',
        'user_id',
        'amount',
    ];

    protected $protectedFieldsOnPreparation = [
        'id',
        'txn_id',
        'created_at',
        'completed_at',
        'status',
    ];

    protected $orderData;

    /**
     * @return $this
     * @codeCoverageIgnore
     */
    public function generateDistributedId()
    {
        return $this->generateOrderId('NA');
    }

    public function generateOrderId($prefix = '')
    {
        $orderId = $prefix . (date('Y') - 2004) . date('md') . substr(time(), -5) . substr(microtime(), 2, 3) .
            static::$_distributedOptions['node_id'] . mt_rand(100, 999);
        $hasOrderId = $this->findFirst([
            'id = :id:',
            'bind' => [
                'id' => $orderId,
            ],
        ]);
        // @codeCoverageIgnoreStart
        if ($hasOrderId) {
            return $this->generateOrderId($prefix);
        }
        // @codeCoverageIgnoreEnd
        $this->setId($orderId);
        return $this;
    }

    public function getByTradeId($tradeId, $clientId)
    {
        return $this->findFirst([
            'trade_id = :tradeId: AND client_id = :clientId:',
            'bind' => compact('tradeId', 'clientId'),
        ]);
    }

    public function getKeyFields()
    {
        $fields = array_values($this->keyFields);
        return array_combine($fields, $fields);
    }

    /**
     * @param string $key
     * @return mixed|OrderData
     */
    public function getOrderData($key = null)
    {
        if ($this->orderData === null) {
            if ($existingOrderData = $this->__get('order_data')) {
                $this->orderData = $existingOrderData;
            } else {
                $this->orderData = $this->_dependencyInjector->get(OrderData::class);
                $this->__set('order_data', $this->orderData);
            }
        }
        $data = $this->orderData->getData('data');
        return $key ? fnGet($data, $key) : $this->orderData;
    }

    public function getProtectedFieldsOnPreparation()
    {
        return $this->protectedFieldsOnPreparation;
    }

    public function initialize()
    {
        $class = OrderData::class;
        $this->_dependencyInjector->has($class) and $class = $this->_dependencyInjector->getRaw($class);
        $this->hasOne('id', $class, 'order_id', ['alias' => 'order_data']);
        parent::initialize();
    }

    public static function prepareOrder($data)
    {
        /* @var Order $order */
        $order = Di::getDefault()->get(static::class);
        if (!$tradeId = fnGet($data, 'trade_id')) {
            throw new OrderException(__('Invalid trade_id'), OrderException::ERROR_CODE_BAD_PARAMETERS);
        }
        if (!$clientId = fnGet($data, 'client_id')) {
            throw new OrderException(__('Invalid client_id'), OrderException::ERROR_CODE_BAD_PARAMETERS);
        }
        // Load existing order if any
        $existingOrder = $order->getByTradeId($tradeId, $clientId);
        if (isset($existingOrder->id)) {
            $order = $existingOrder;
            $status = $order->getStatus();
            if ($status != static::STATUS_PENDING) {
                $failureMessages = [
                    static::STATUS_PROCESSING => 'Order is under processing, please do not submit repeatedly',
{'fraction_non_alphanumeric': 0.1422850707045426, 'fraction_numerical': 0.003253660367913903, 'mean_word_length': 2.3707296499367354, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 67, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4184558', 'n_tokens_mistral': 2423, 'n_tokens_neox': 2352, 'n_words': 473}