Checker::getAdminChannel()   A
last analyzed

Complexity

Conditions 5
Paths 3

Size

Total Lines 13
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 6
c 1
b 0
f 0
dl 0
loc 13
rs 9.6111
cc 5
nc 3
nop 0
1
<?php
2
namespace PortlandLabs\Slackbot\Permission;
3
4
use Buttress\Collection\GeneratorCollection;
5
use CL\Slack\Exception\SlackException;
6
use CL\Slack\Model\Channel;
7
use CL\Slack\Payload\ChannelsInfoPayload;
8
use CL\Slack\Payload\ChannelsInfoPayloadResponse;
9
use CL\Slack\Payload\ChannelsListPayload;
10
use CL\Slack\Payload\ChannelsListPayloadResponse;
11
use GuzzleHttp\Exception\GuzzleException;
12
use PortlandLabs\Slackbot\Slack\Api\Client;
13
use PortlandLabs\Slackbot\Slack\Api\Payload\ChatUpdatePayload;
14
use PortlandLabs\Slackbot\Slack\Api\Payload\ConversationsListPayload;
15
use PortlandLabs\Slackbot\Slack\Api\Payload\ConversationsListPayloadResponse;
16
use PortlandLabs\Slackbot\Slack\Rtm\Event\Message;
17
use Psr\Log\LoggerAwareTrait;
18
use Psr\Log\LoggerInterface;
19
20
class Checker
21
{
22
    use LoggerAwareTrait;
23
24
    /** @var Client */
25
    protected $client;
26
27
    /** @var Admin */
28
    protected $adminRole;
29
30
    /** @var User */
31
    protected $userRole;
32
33
    /** @var Bot */
34
    protected $botRole;
35
36
    /** @var string */
37
    protected $adminChannelId;
38
39
    public function __construct(Client $client, LoggerInterface $logger, User $userRole, Admin $adminRole, Bot $botRole)
40
    {
41
        $this->client = $client;
42
        $this->setLogger($logger);
43
        $this->userRole = $userRole;
44
        $this->adminRole = $adminRole;
45
        $this->botRole = $botRole;
46
    }
47
48
    /**
49
     * Get the role of a person using the bot
50
     *
51
     * @param Message $message
52
     *
53
     * @return Role
54
     */
55
    public function getRole(Message $message): Role
56
    {
57
        if ($message->getSubtype() === 'bot_message') {
58
            return $this->botRole;
59
        }
60
61
        return $message->getChannel() === $this->getAdminChannel() ? $this->adminRole : $this->userRole;
62
    }
63
64
    /**
65
     * Determine the admin channel ID
66
     *
67
     * @return string
68
     */
69
    private function getAdminChannel(): ?string
70
    {
71
        if ($this->adminChannelId === null) {
72
            $adminChannel = null;
73
74
            if ($channel = getenv('ADMIN_CHANNEL')) {
75
                $adminChannel = $this->resolveAdminChannel($channel);
76
            }
77
78
            $this->adminChannelId = $adminChannel ?: false;
0 ignored issues
show
Documentation Bug introduced by
It seems like $adminChannel ?: false can also be of type false. However, the property $adminChannelId is declared as type string. Maybe add an additional type check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

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

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
79
        }
80
81
        return $this->adminChannelId ?: null;
82
    }
83
84
    /**
85
     * Find the channel that matches our admin channel name
86
     *
87
     * @param string $name
88
     * @return string The admin channel id or null if not found
89
     */
90
    protected function resolveAdminChannel(string $name): ?string
91
    {
92
        foreach ($this->allChannels() as $channel) {
93
            if ($channel->getName() === $name) {
94
                return $channel->getId();
95
            }
96
        }
97
98
        return null;
99
    }
100
101
    /**
102
     * Get all channels
103
     *
104
     * @return Channel[]
105
     */
106
    private function allChannels(): iterable
107
    {
108
        $payload = new ConversationsListPayload();
109
        $payload->setExcludePrivate(false);
110
        $payload->setExcludePublic(true);
111
        $payload->setExcludeArchived(true);
112
        $response = null;
0 ignored issues
show
Unused Code introduced by
The assignment to $response is dead and can be removed.
Loading history...
113
        $nextCursor = null;
114
115
        do {
116
            if ($nextCursor) {
117
                $payload->setCursor($nextCursor);
0 ignored issues
show
Bug introduced by
$nextCursor of type void is incompatible with the type string expected by parameter $cursor of PortlandLabs\Slackbot\Sl...istPayload::setCursor(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

117
                $payload->setCursor(/** @scrutinizer ignore-type */ $nextCursor);
Loading history...
118
            }
119
120
            try {
121
                /** @var ConversationsListPayloadResponse $response */
122
                $response = $this->client->send($payload);
123
            } catch (SlackException | GuzzleException $e) {
124
                $this->logger->notice('Unable to request channel list: ' . $e->getMessage());
0 ignored issues
show
Bug introduced by
The method notice() does not exist on null. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

124
                $this->logger->/** @scrutinizer ignore-call */ 
125
                               notice('Unable to request channel list: ' . $e->getMessage());

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
125
            }
126
127
            if ($response) {
128
                $channels = (array) $response->getChannels();
129
                foreach ($channels as $channel) {
130
                    yield $channel;
131
                }
132
133
                $nextCursor = $response->getNextCursor();
134
            }
135
        } while ($nextCursor);
136
    }
137
138
}