Completed
Push — master ( 8d75cc...d50988 )
by Dmitry
14:44 queued 21s
created

src/actions/RequestAction.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace hiqdev\yii2\merchant\actions;
4
5
use hiqdev\yii2\merchant\events\TransactionInsertEvent;
6
use hiqdev\yii2\merchant\models\DepositRequest;
7
use hiqdev\yii2\merchant\models\PurchaseRequest;
8
use hiqdev\yii2\merchant\Module;
9
use Yii;
10
use yii\base\Action;
11
use yii\base\Event;
12
use yii\web\BadRequestHttpException;
13
14
class RequestAction extends Action
15
{
16
    const EVENT_BEFORE_TRANSACTION_INSERT = 'before_transaction_insert';
17
    const EVENT_AFTER_TRANSACTION_INSERT = 'after_transaction_insert';
18
19
    /**
20
     * @return Module
21
     */
22
    protected function getMerchantModule()
23
    {
24
        return $this->controller->getMerchantModule();
25
    }
26
27
    public function run()
28
    {
29
        $depositRequest = $this->loadDepositRequest();
30
        $this->registerTransaction($depositRequest);
31
        $request = $this->createPurchaseRequest($depositRequest);
32
33
        return $this->handlePurchaseRequest($request);
34
    }
35
36
    /**
37
     * @return DepositRequest
38
     * @throws BadRequestHttpException
39
     */
40
    protected function loadDepositRequest()
41
    {
42
        $depositRequest = new DepositRequest();
43
        $depositRequest->load(Yii::$app->request->post());
44
        if (!$depositRequest->validate()) {
45
            throw new BadRequestHttpException('Deposit request is not loaded: ' . reset($depositRequest->getFirstErrors()));
46
        }
47
48
        $this->getMerchantModule()->prepareRequestData($depositRequest);
49
50
        return $depositRequest;
51
    }
52
53
    /**
54
     * @param DepositRequest $depositRequest
55
     * @return \hiqdev\yii2\merchant\models\PurchaseRequest
56
     */
57
    protected function createPurchaseRequest($depositRequest)
58
    {
59
        $request = $this->getMerchantModule()->getPurchaseRequest($depositRequest->merchant, $depositRequest);
60
61
        return $request;
62
    }
63
64
    /**
65
     * @param DepositRequest $depositRequest
66
     */
67
    protected function registerTransaction($depositRequest)
68
    {
69
        $this->trigger(self::EVENT_BEFORE_TRANSACTION_INSERT, new TransactionInsertEvent(['depositRequest' => $depositRequest]));
70
71
        $transaction = $this->getMerchantModule()->insertTransaction($depositRequest->id, $depositRequest->merchant, array_merge([
72
            'username' => $depositRequest->username,
73
        ], $depositRequest->toArray()));
74
75
        $this->trigger(self::EVENT_AFTER_TRANSACTION_INSERT, new TransactionInsertEvent([
76
            'depositRequest' => $depositRequest,
77
            'transaction' => $transaction
78
        ]));
79
80
    }
81
82
    /**
83
     * @param PurchaseRequest $response
84
     * @return \yii\web\Response
85
     * @throws BadRequestHttpException
86
     */
87
    protected function handlePurchaseRequest($response)
88
    {
89
        if ('GET' === $response->getFormMethod()) {
90
            return $this->controller->redirect($response->getFormAction());
91
        } elseif ('POST' === $response->getFormMethod()) {
92
            $hiddenFields = '';
93
            foreach ($response->getFormInputs() as $key => $value) {
94
                $hiddenFields .= sprintf(
95
                        '<input type="hidden" name="%1$s" value="%2$s" />',
96
                        htmlentities($key, ENT_QUOTES, 'UTF-8', false),
97
                        htmlentities($value, ENT_QUOTES, 'UTF-8', false)
98
                    )."\n";
99
            }
100
101
            $output = '<!DOCTYPE html>
102
<html>
103
    <head>
104
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
105
        <title>Redirecting...</title>
106
    </head>
107
    <body onload="document.forms[0].submit();">
108
        <form action="%1$s" method="post">
109
            <p>Redirecting to payment page...</p>
110
            <p>
111
                %2$s
112
                <input type="submit" value="Continue" />
113
            </p>
114
        </form>
115
    </body>
116
</html>';
117
            $output = sprintf(
118
                $output,
119
                htmlentities($response->getFormAction(), ENT_QUOTES, 'UTF-8', false),
120
                $hiddenFields
121
            );
122
123
            return $output;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $output; (string) is incompatible with the return type documented by hiqdev\yii2\merchant\act...::handlePurchaseRequest of type yii\web\Response.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

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

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
124
        }
125
126
        throw new BadRequestHttpException();
127
    }
128
}
129