Определение получателя первого сообщения

Общие вопросы по использованию второй версии фреймворка. Если не знаете как что-то сделать и это про Yii 2, вам сюда.
Ответить
Dimitri
Сообщения: 3
Зарегистрирован: 2024.01.15, 17:40

Определение получателя первого сообщения

Сообщение Dimitri »

Здравствуйте. Есть такой код в плагине платных приватных сообщений:

Код: Выделить всё

class PayedMessage extends \app\plugins\Plugin implements BootstrapInterface, HasSettings
{
    const SETTINGS_MESSAGES_COST_PER_MESSAGE = 'messagePrice';
    const SETTINGS_POSTS_COST_PER_POST = 'postPrice';

    /**
     * @param \yii\base\Application $app
     */
    public function bootstrap($app)
    {
        if ($app instanceof ConsoleApplication) {
            return;
        }

        if (Yii::$app->user->isGuest || Yii::$app->user->identity->isAdmin) {
            return;
        }

        $this->setupMessages();
    }

    private function setupMessages()
    {
        Event::on(MessageForm::class, Message::EVENT_BEFORE_VALIDATE, function (ModelEvent $event) {
            /** @var MessageForm $messageForm */
            $messageForm = $event->sender;
            $messagePrice = $this->getSetting(self::SETTINGS_MESSAGES_COST_PER_MESSAGE);
            $userId = Yii::$app->user->id;

            if (!Yii::$app->balanceManager->hasEnoughCredits($userId, $messagePrice)) {
                $messageForm->addError('message',
                    Yii::t('app', 'youre out of credits: {upgradeLink}', [
                        'upgradeLink' => Html::a(Yii::t('app', 'get more credits'), ['/balance/services'])
                    ])
                );
                $event->isValid = false;
            } else if ($messagePrice > 0) {
                Yii::$app->balanceManager->decrease(['user_id' => $userId], $messagePrice, [
                    'class' => MessageTransaction::class,
                    'toUserId' => $messageForm->contactId,
                ]);
            }
        });
И так же код плагина премиум пользователя.

Код: Выделить всё

public function activatePremium($userId)
    {
        $premiumPrice = $this->getPremiumPrice();
        if (!$this->hasEnoughCredits($userId, $premiumPrice)) {
            return false;
        }
 
        $userPremium = UserPremium::activatePremium($userId, $this->getPremiumDuration());
        $this->decrease(['user_id' => $userId], $premiumPrice, [
            'class' => PremiumTransaction::class,
            'premiumAt' => $userPremium->created_at,
            'premiumUntil' => $userPremium->premium_until,
        ]);
 
        return true;
, Так же есть раздел в balance manager:

Код: Выделить всё

$userPremium = UserPremium::activatePremium($userId, $this->getPremiumDuration());
        $this->decrease(['user_id' => $userId], $premiumPrice, [
            'class' => PremiumTransaction::class,
            'premiumAt' => $userPremium->created_at,
            'premiumUntil' => $userPremium->premium_until,
        ]);

        return true;
    }
Как сделать так, чтобы если начал диалог не ты, а собеседник, то ограничения премиум тебя не касались и ты мог продолжать диалог без платных подписок?
Аватара пользователя
SiZE
Сообщения: 2817
Зарегистрирован: 2011.09.21, 12:39
Откуда: Perm
Контактная информация:

Re: Определение получателя первого сообщения

Сообщение SiZE »

Через паттерн стратегия

Код: Выделить всё

<?php

declare(strict_types=1);

final class PremiumService
{
}

interface MessagePayment
{
    public function pay(int $userId): bool;
}

final class MessagePremium implements MessagePayment
{

    private PremiumService $premiumService;

    public function __construct(PremiumService $premiumService)
    {
        $this->premiumService = $premiumService;
    }

    public function pay(int $userId): bool
    {
        $premiumPrice = $this->premiumService->getPremiumPrice();
        if (!$this->premiumService->hasEnoughCredits($userId, $premiumPrice)) {
            return false;
        }

        try {
            $userPremium = $this->premiumService->activatePremium($userId, $this->premiumService->getPremiumDuration());
            $this->premiumService->decrease(['user_id' => $userId], $premiumPrice, [
                'premiumAt' => $userPremium->created_at,
                'premiumUntil' => $userPremium->premium_until,
            ]);
        } catch (\Exception $e) {
            return false;
        }

        return true;
    }
}

final class MessageFree implements MessagePayment
{

    public function pay(int $userId): bool
    {
        return true;
    }
}

final class MessagePaymentDispatcher
{

    private MessagePayment $messagePayment;

    public function setMessagePayment(MessagePayment $messagePayment)
    {
        $this->messagePayment = $messagePayment;
    }

    public function processMessagePayment($userId): bool
    {
        return $this->messagePayment->pay($userId);
    }
}

final class MessageService
{

    private MessagePaymentDispatcher $messagePaymentDispatcher;

    public function __construct(MessagePaymentDispatcher $messagePaymentDispatcher)
    {
        $this->messagePaymentDispatcher = $messagePaymentDispatcher;
    }

    public function processPayment(int $userId)
    {
        if ($this->isAuthor($userId)) {
            $messagePayment = new MessagePremium();
        } else {
            $messagePayment = new MessageFree();
        }

        $this->messagePaymentDispatcher->setMessagePayment($messagePayment);
        
        return $this->messagePaymentDispatcher->processMessagePayment($userId);
    }

    private function isAuthor(int $userId): bool
    {
        return true;
    }
}


Dimitri
Сообщения: 3
Зарегистрирован: 2024.01.15, 17:40

Re: Определение получателя первого сообщения

Сообщение Dimitri »

Большое спасибо, но вставляю код в файл UserPremium в директории models, выдает ошибку "yii\base\ErrorException: strict_types declaration must be the very first statement in the script ". Или код надо поместить в отдельный файл?
Аватара пользователя
SiZE
Сообщения: 2817
Зарегистрирован: 2011.09.21, 12:39
Откуда: Perm
Контактная информация:

Re: Определение получателя первого сообщения

Сообщение SiZE »

Dimitri писал(а): 2024.01.16, 16:39 Или код надо поместить в отдельный файл?
Я написал это только в качестве примера. Ознакомьтесь с паттерном стратегия, какие решает он задачи. И затем уже адаптируйте код для себя.
Dimitri
Сообщения: 3
Зарегистрирован: 2024.01.15, 17:40

Re: Определение получателя первого сообщения

Сообщение Dimitri »

SiZE писал(а): 2024.01.17, 11:10
Dimitri писал(а): 2024.01.16, 16:39 Или код надо поместить в отдельный файл?
Я написал это только в качестве примера. Ознакомьтесь с паттерном стратегия, какие решает он задачи. И затем уже адаптируйте код для себя.
Скажите а здесь не должно быть знаков препинания?

Код: Выделить всё

construct(PremiumService $premiumService)
    {
И подскажите пожалуйста, этот паттерн вставлять в код плагина , или отдельным файлом?
Аватара пользователя
SiZE
Сообщения: 2817
Зарегистрирован: 2011.09.21, 12:39
Откуда: Perm
Контактная информация:

Re: Определение получателя первого сообщения

Сообщение SiZE »

Dimitri писал(а): 2024.01.21, 11:54 И подскажите пожалуйста, этот паттерн вставлять в код плагина , или отдельным файлом?
Отдельными файлами. Но раз вы задаете такие вопросы, вам бы почитать про шаблоны проектирования и потом уже про организацию кода в РНР и тп.
Ответить