Passed
Push — master ( 3ec09a...2dbf9c )
by Sullivan
18:50 queued 14:05
created

Client::__call()   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 2
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($endpoint, array $options = [], HttpClient $httpClient = null)
49
    {
50
        $resolver = (new OptionsResolver())
51
            ->setDefaults([
52
                'channel' => null,
53
                'username' => null,
54
                'icon' => null,
55
                'link_names' => false,
56
                'unfurl_links' => false,
57
                'unfurl_media' => true,
58
                'allow_markdown' => true,
59
                'markdown_in_attachments' => [],
60
            ])
61
            ->setAllowedTypes('channel', ['string', 'null'])
62
            ->setAllowedTypes('username', ['string', 'null'])
63
            ->setAllowedTypes('icon', ['string', 'null'])
64
            ->setAllowedTypes('link_names', 'bool')
65
            ->setAllowedTypes('unfurl_links', 'bool')
66
            ->setAllowedTypes('unfurl_media', 'bool')
67
            ->setAllowedTypes('allow_markdown', 'bool')
68
            ->setAllowedTypes('markdown_in_attachments', 'array')
69
        ;
70
        $this->options = $resolver->resolve($options);
71
72
        $this->httpClient = new HttpMethodsClient(
73
            new PluginClient(
74
                $httpClient ?: HttpClientDiscovery::find(),
75
                [
76
                    new BaseUriPlugin(
77
                        UriFactoryDiscovery::find()->createUri($endpoint)
78
                    ),
79
                ]
80
            ),
81
            MessageFactoryDiscovery::find()
82
        );
83
    }
84
85
    /**
86
     * Pass any unhandled methods through to a new Message
87
     * instance.
88
     *
89
     * @param string $name      The name of the method
90
     * @param array  $arguments The method arguments
91
     *
92
     * @return \Nexy\Slack\Message
93
     */
94
    public function __call($name, $arguments)
95
    {
96
        return \call_user_func_array([$this->createMessage(), $name], $arguments);
97
    }
98
99
    /**
100
     * Create a new message with defaults.
101
     *
102
     * @return \Nexy\Slack\Message
103
     */
104
    public function createMessage()
105
    {
106
        return (new Message($this))
107
            ->setChannel($this->options['channel'])
108
            ->setUsername($this->options['username'])
109
            ->setIcon($this->options['icon'])
110
            ->setAllowMarkdown($this->options['allow_markdown'])
111
            ->setMarkdownInAttachments($this->options['markdown_in_attachments'])
112
        ;
113
    }
114
115
    /**
116
     * Send a message.
117
     *
118
     * @param \Nexy\Slack\Message $message
119
     *
120
     * @throws Exception
121
     */
122
    public function sendMessage(Message $message): void
123
    {
124
        $payload = $this->preparePayload($message);
125
126
        $encoded = \json_encode($payload, JSON_UNESCAPED_UNICODE);
127
128
        if (false === $encoded) {
0 ignored issues
show
introduced by
The condition false === $encoded can never be true.
Loading history...
129
            throw new \RuntimeException(\sprintf('JSON encoding error %s: %s', \json_last_error(), \json_last_error_msg()));
130
        }
131
132
        $this->httpClient->post('', [], $encoded);
133
    }
134
135
    /**
136
     * Prepares the payload to be sent to the webhook.
137
     *
138
     * @param \Nexy\Slack\Message $message The message to send
139
     *
140
     * @return array
141
     */
142
    private function preparePayload(Message $message)
143
    {
144
        $payload = [
145
            'text' => $message->getText(),
146
            'channel' => $message->getChannel(),
147
            'username' => $message->getUsername(),
148
            'link_names' => $this->options['link_names'] ? 1 : 0,
149
            'unfurl_links' => $this->options['unfurl_links'],
150
            'unfurl_media' => $this->options['unfurl_media'],
151
            'mrkdwn' => $this->options['allow_markdown'],
152
        ];
153
154
        if ($icon = $message->getIcon()) {
155
            $payload[$message->getIconType()] = $icon;
156
        }
157
158
        $payload['attachments'] = $this->getAttachmentsAsArrays($message);
159
160
        return $payload;
161
    }
162
163
    /**
164
     * Get the attachments in array form.
165
     *
166
     * @param \Nexy\Slack\Message $message
167
     *
168
     * @return array
169
     */
170
    private function getAttachmentsAsArrays(Message $message)
171
    {
172
        $attachments = [];
173
174
        foreach ($message->getAttachments() as $attachment) {
175
            $attachments[] = $attachment->toArray();
176
        }
177
178
        return $attachments;
179
    }
180
}
181