Completed
Push — master ( fd8502...1fc8d0 )
by Sullivan
17s queued 12s
created

Client::getOptions()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 3
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the Nexylan packages.
7
 *
8
 * (c) Nexylan SAS <[email protected]>
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Nexy\Slack;
15
16
use Http\Client\Common\HttpMethodsClient;
17
use Http\Client\Common\Plugin\BaseUriPlugin;
18
use Http\Client\Common\PluginClient;
19
use Http\Client\Exception;
20
use Http\Client\HttpClient;
21
use Http\Discovery\HttpClientDiscovery;
22
use Http\Discovery\MessageFactoryDiscovery;
23
use Http\Discovery\UriFactoryDiscovery;
24
use Symfony\Component\OptionsResolver\OptionsResolver;
25
26
/**
27
 * @author Sullivan Senechal <[email protected]>
28
 */
29
final class Client
30
{
31
    /**
32
     * @var array
33
     */
34
    private $options;
35
36
    /**
37
     * @var HttpMethodsClient
38
     */
39
    private $httpClient;
40
41
    /**
42
     * Instantiate a new Client.
43
     *
44
     * @param string          $endpoint
45
     * @param array           $options
46
     * @param HttpClient|null $httpClient
47
     */
48
    public function __construct(string $endpoint, array $options = [], HttpClient $httpClient = null)
49
    {
50
        $resolver = (new OptionsResolver())
51
            ->setDefaults([
52
                'channel' => null,
53
                'sticky_channel' => false,
54
                'username' => null,
55
                'icon' => null,
56
                'link_names' => false,
57
                'unfurl_links' => false,
58
                'unfurl_media' => true,
59
                'allow_markdown' => true,
60
                'markdown_in_attachments' => [],
61
            ])
62
            ->setAllowedTypes('channel', ['string', 'null'])
63
            ->setAllowedTypes('sticky_channel', ['bool'])
64
            ->setAllowedTypes('username', ['string', 'null'])
65
            ->setAllowedTypes('icon', ['string', 'null'])
66
            ->setAllowedTypes('link_names', 'bool')
67
            ->setAllowedTypes('unfurl_links', 'bool')
68
            ->setAllowedTypes('unfurl_media', 'bool')
69
            ->setAllowedTypes('allow_markdown', 'bool')
70
            ->setAllowedTypes('markdown_in_attachments', 'array')
71
        ;
72
        $this->options = $resolver->resolve($options);
73
74
        $this->httpClient = new HttpMethodsClient(
75
            new PluginClient(
76
                $httpClient ?: HttpClientDiscovery::find(),
77
                [
78
                    new BaseUriPlugin(
79
                        UriFactoryDiscovery::find()->createUri($endpoint)
80
                    ),
81
                ]
82
            ),
83
            MessageFactoryDiscovery::find()
84
        );
85
    }
86
87
    /**
88
     * Pass any unhandled methods through to a new Message
89
     * instance.
90
     *
91
     * @param string $name      The name of the method
92
     * @param array  $arguments The method arguments
93
     *
94
     * @return \Nexy\Slack\Message
95
     */
96
    public function __call(string $name, array $arguments): Message
97
    {
98
        return \call_user_func_array([$this->createMessage(), $name], $arguments);
99
    }
100
101
    /**
102
     * @return array
103
     */
104
    public function getOptions(): array
105
    {
106
        return $this->options;
107
    }
108
109
    /**
110
     * Create a new message with defaults.
111
     *
112
     * @return \Nexy\Slack\Message
113
     */
114
    public function createMessage(): Message
115
    {
116
        return (new Message($this))
117
            ->setChannel($this->options['channel'])
118
            ->setUsername($this->options['username'])
119
            ->setIcon($this->options['icon'])
120
            ->setAllowMarkdown($this->options['allow_markdown'])
121
            ->setMarkdownInAttachments($this->options['markdown_in_attachments'])
122
        ;
123
    }
124
125
    /**
126
     * Send a message.
127
     *
128
     * @param \Nexy\Slack\Message $message
129
     *
130
     * @throws Exception
131
     */
132
    public function sendMessage(Message $message): void
133
    {
134
        // Ensure the message will always be sent to the default channel if asked for.
135
        if ($this->options['sticky_channel']) {
136
            $message->setChannel($this->options['channel']);
137
        }
138
139
        $payload = $this->preparePayload($message);
140
141
        $encoded = \json_encode($payload, JSON_UNESCAPED_UNICODE);
142
143
        if (false === $encoded) {
144
            throw new \RuntimeException(\sprintf('JSON encoding error %s: %s', \json_last_error(), \json_last_error_msg()));
145
        }
146
147
        $this->httpClient->post('', [], $encoded);
148
    }
149
150
    /**
151
     * Prepares the payload to be sent to the webhook.
152
     *
153
     * @param \Nexy\Slack\Message $message The message to send
154
     *
155
     * @return array
156
     */
157
    private function preparePayload(Message $message): array
158
    {
159
        $payload = [
160
            'text' => $message->getText(),
161
            'channel' => $message->getChannel(),
162
            'username' => $message->getUsername(),
163
            'link_names' => $this->options['link_names'] ? 1 : 0,
164
            'unfurl_links' => $this->options['unfurl_links'],
165
            'unfurl_media' => $this->options['unfurl_media'],
166
            'mrkdwn' => $this->options['allow_markdown'],
167
        ];
168
169
        if ($icon = $message->getIcon()) {
170
            $payload[$message->getIconType()] = $icon;
171
        }
172
173
        $payload['attachments'] = $this->getAttachmentsAsArrays($message);
174
175
        return $payload;
176
    }
177
178
    /**
179
     * Get the attachments in array form.
180
     *
181
     * @param \Nexy\Slack\Message $message
182
     *
183
     * @return array
184
     */
185
    private function getAttachmentsAsArrays(Message $message): array
186
    {
187
        $attachments = [];
188
189
        foreach ($message->getAttachments() as $attachment) {
190
            $attachments[] = $attachment->toArray();
191
        }
192
193
        return $attachments;
194
    }
195
}
196