Completed
Push — master ( 20b0b4...0ce164 )
by Camilo
13s
created

FormConstructor::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 7
ccs 5
cts 5
cp 1
rs 9.4285
c 0
b 0
f 0
cc 2
eloc 4
nc 2
nop 1
crap 2
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace unreal4u\TelegramAPI\InternalFunctionality;
6
7
use Psr\Log\LoggerInterface;
8
use unreal4u\TelegramAPI\Abstracts\TelegramMethods;
9
use unreal4u\TelegramAPI\Telegram\Types\Custom\InputFile;
10
11
class FormConstructor
12
{
13
    /**
14
     * With this flag we'll know what type of request to send to Telegram
15
     *
16
     * 'application/x-www-form-urlencoded' is the "normal" one, which is simpler and quicker.
17
     * 'multipart/form-data' should be used only when you upload documents, photos, etc.
18
     *
19
     * @var string
20
     */
21
    public $formType = 'application/x-www-form-urlencoded';
22
23
    /**
24
     * @var LoggerInterface
25
     */
26
    protected $logger;
27
28 41
    public function __construct(LoggerInterface $logger = null)
29
    {
30 41
        if ($logger === null) {
31 41
            $logger = new DummyLogger();
32
        }
33 41
        $this->logger = $logger;
34 41
    }
35
36
    /**
37
     * Builds up the form elements to be sent to Telegram
38
     *
39
     * @TODO Move this to apart function
40
     *
41
     * @param TelegramMethods $method
42
     * @return array
43
     * @throws \unreal4u\TelegramAPI\Exceptions\MissingMandatoryField
44
     */
45 31
    public function constructFormData(TelegramMethods $method): array
46
    {
47 31
        $result = $this->checkSpecialConditions($method);
48
49 31
        switch ($this->formType) {
50 31
            case 'application/x-www-form-urlencoded':
51 27
                $this->logger->debug('Creating x-www-form-urlencoded form (AKA fast request)');
52
                $formData = [
53 27
                    'headers' => [
54
                        'Content-Type' => 'application/x-www-form-urlencoded',
55
                    ],
56 27
                    'body' => http_build_query($method->export(), '', '&'),
57
                ];
58 25
                break;
59 4
            case 'multipart/form-data':
60
                $formData = [
61 4
                    'headers' => [
62
                        'Content-Type' => 'multipart/form-data',
63
                    ],
64 4
                    'body' => $this->buildMultipartFormData($method->export(), $result['id'], $result['stream'])
65
                ];
66 4
                break;
67
            default:
68
                $this->logger->critical(sprintf(
69
                    'Invalid form-type detected, if you incur in such a situation, this is most likely a product to ' .
70
                    'a bug. Please copy entire line and report at %s',
71
                    'https://github.com/unreal4u/telegram-api/issues'
72
                ), [
73
                    $this->formType
74
                ]);
75
                $formData = [
76
                    'headers' => [
77
                        'Content-Type' => $this->formType
78
                    ]
79
                ];
80
                break;
81
        }
82 29
        $this->logger->debug('About to send following data', $formData);
83
84 29
        return $formData;
85
    }
86
87
    /**
88
     * Can perform any special checks needed to be performed before sending the actual request to Telegram
89
     *
90
     * This will return an array with data that will be different in each case (for now). This can be changed in the
91
     * future.
92
     *
93
     * @param TelegramMethods $method
94
     * @return array
95
     */
96 31
    private function checkSpecialConditions(TelegramMethods $method): array
97
    {
98 31
        $this->logger->debug('Checking whether to apply special conditions to this request');
99 31
        $method->performSpecialConditions();
100
101 31
        $return = [false];
102
103 31
        foreach ($method as $key => $value) {
0 ignored issues
show
Bug introduced by
The expression $method of type object<unreal4u\Telegram...tracts\TelegramMethods> is not traversable.
Loading history...
104 27
            if (is_object($value) && $value instanceof InputFile) {
105 4
                $this->logger->debug('About to send a file, so changing request to use multi-part instead');
106
                // If we are about to send a file, we must use the multipart/form-data way
107 4
                $this->formType = 'multipart/form-data';
108
                $return = [
109 4
                    'id' => $key,
110 27
                    'stream' => $value->getStream(),
111
                ];
112
            }
113
        }
114
115 31
        return $return;
116
    }
117
118
    /**
119
     * Builds up a multipart form-like array for Guzzle
120
     *
121
     * @param array $data The original object in array form
122
     * @param string $fileKeyName A file handler will be sent instead of a string, state here which field it is
123
     * @param resource $stream The actual file handler
124
     * @return array Returns the actual formdata to be sent
125
     */
126 5
    public function buildMultipartFormData(array $data, string $fileKeyName, $stream): array
127
    {
128 5
        $this->logger->debug('Creating multi-part form array data (complex and expensive)');
129
130 5
        $multiPartArray = [];
131 5
        foreach ($data as $id => $value) {
132
            // Always send as a string unless it's a file
133
            $multiPart = [
134 5
                'name' => $id,
135
                'contents' => null,
136
            ];
137
138 5
            if ($id === $fileKeyName) {
139 4
                $multiPart['contents'] = $stream;
140
            } else {
141 5
                $multiPart['contents'] = (string)$value;
142
            }
143
144 5
            $multiPartArray[] = $multiPart;
145
        }
146 5
        return $multiPartArray;
147
    }
148
}
149