Passed
Push — master ( c85300...3ec09a )
by Sullivan
07:20
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
     * Create a new message with defaults.
87
     *
88
     * @return \Nexy\Slack\Message
89
     */
90
    public function createMessage()
91
    {
92
        return (new Message($this))
93
            ->setChannel($this->options['channel'])
94
            ->setUsername($this->options['username'])
95
            ->setIcon($this->options['icon'])
96
            ->setAllowMarkdown($this->options['allow_markdown'])
97
            ->setMarkdownInAttachments($this->options['markdown_in_attachments'])
98
        ;
99
    }
100
101
    /**
102
     * Send a message.
103
     *
104
     * @param \Nexy\Slack\Message $message
105
     *
106
     * @throws Exception
107
     */
108
    public function sendMessage(Message $message): void
109
    {
110
        $payload = $this->preparePayload($message);
111
112
        $encoded = \json_encode($payload, JSON_UNESCAPED_UNICODE);
113
114
        if (false === $encoded) {
0 ignored issues
show
introduced by
The condition false === $encoded can never be true.
Loading history...
115
            throw new \RuntimeException(\sprintf('JSON encoding error %s: %s', \json_last_error(), \json_last_error_msg()));
116
        }
117
118
        $this->httpClient->post('', [], $encoded);
119
    }
120
121
    /**
122
     * Prepares the payload to be sent to the webhook.
123
     *
124
     * @param \Nexy\Slack\Message $message The message to send
125
     *
126
     * @return array
127
     */
128
    private function preparePayload(Message $message)
129
    {
130
        $payload = [
131
            'text' => $message->getText(),
132
            'channel' => $message->getChannel(),
133
            'username' => $message->getUsername(),
134
            'link_names' => $this->options['link_names'] ? 1 : 0,
135
            'unfurl_links' => $this->options['unfurl_links'],
136
            'unfurl_media' => $this->options['unfurl_media'],
137
            'mrkdwn' => $this->options['allow_markdown'],
138
        ];
139
140
        if ($icon = $message->getIcon()) {
141
            $payload[$message->getIconType()] = $icon;
142
        }
143
144
        $payload['attachments'] = $this->getAttachmentsAsArrays($message);
145
146
        return $payload;
147
    }
148
149
    /**
150
     * Get the attachments in array form.
151
     *
152
     * @param \Nexy\Slack\Message $message
153
     *
154
     * @return array
155
     */
156
    private function getAttachmentsAsArrays(Message $message)
157
    {
158
        $attachments = [];
159
160
        foreach ($message->getAttachments() as $attachment) {
161
            $attachments[] = $attachment->toArray();
162
        }
163
164
        return $attachments;
165
    }
166
}
167