Passed
Push — master ( c0f32c...e879f4 )
by Chema
04:17 queued 41s
created

StockTickerFactory::createTwigEnvironment()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 0
Metric Value
eloc 6
c 0
b 0
f 0
dl 0
loc 11
ccs 0
cts 7
cp 0
rs 10
cc 2
nc 2
nop 0
crap 6
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Chemaclass\StockTicker;
6
7
use Chemaclass\StockTicker\Domain\Crawler\Mapper\CrawledInfoMapper;
8
use Chemaclass\StockTicker\Domain\Crawler\Mapper\CrawledInfoMapperInterface;
9
use Chemaclass\StockTicker\Domain\Crawler\QuoteCrawler;
10
use Chemaclass\StockTicker\Domain\Crawler\QuoteCrawlerInterface;
11
use Chemaclass\StockTicker\Domain\Crawler\Site\Barrons\BarronsSiteCrawler;
12
use Chemaclass\StockTicker\Domain\Crawler\Site\Barrons\HtmlCrawler\News;
13
use Chemaclass\StockTicker\Domain\Crawler\Site\FinanceYahoo\FinanceYahooSiteCrawler;
14
use Chemaclass\StockTicker\Domain\Crawler\Site\FinanceYahoo\JsonExtractor;
15
use Chemaclass\StockTicker\Domain\Crawler\Site\Shared\NewsNormalizer;
16
use Chemaclass\StockTicker\Domain\Crawler\SiteCrawlerInterface;
17
use Chemaclass\StockTicker\Domain\Notifier\Channel\Email\EmailChannel;
18
use Chemaclass\StockTicker\Domain\Notifier\Channel\Slack\HttpSlackClient;
19
use Chemaclass\StockTicker\Domain\Notifier\Channel\Slack\SlackChannel;
20
use Chemaclass\StockTicker\Domain\Notifier\Channel\TwigTemplateGenerator;
21
use Chemaclass\StockTicker\Domain\Notifier\ChannelInterface;
22
use Chemaclass\StockTicker\Domain\Notifier\Notifier;
23
use Chemaclass\StockTicker\Domain\Notifier\NotifierInterface;
24
use Chemaclass\StockTicker\Domain\Notifier\NotifierPolicy;
25
use Chemaclass\StockTicker\Domain\WriteModel\Quote;
26
use DateTimeZone;
27
use Symfony\Component\HttpClient\HttpClient;
28
use Symfony\Component\Mailer\Bridge\Google\Transport\GmailSmtpTransport;
29
use Symfony\Component\Mailer\Mailer;
30
use Twig\Environment;
31
use Twig\Extension\DebugExtension;
32
use Twig\Loader\FilesystemLoader;
33
34
final class StockTickerFactory implements StockTickerFactoryInterface
35
{
36
    private const URLS = 'URLS';
37
38
    private StockTickerConfigInterface $config;
39
40 4
    public function __construct(StockTickerConfigInterface $config)
41
    {
42 4
        $this->config = $config;
43 4
    }
44
45 4
    public function createQuoteCrawler(SiteCrawlerInterface ...$siteCrawlers): QuoteCrawlerInterface
46
    {
47 4
        return new QuoteCrawler(
48 4
            HttpClient::create(),
49 4
            $this->createCrawledInfoMapper(),
50 4
            ...$siteCrawlers
51
        );
52
    }
53
54 2
    public function createNotifier(NotifierPolicy $policy, ChannelInterface ...$channels): NotifierInterface
55
    {
56 2
        return new Notifier($policy, ...$channels);
57
    }
58
59
    /**
60
     * @return Domain\Crawler\SiteCrawlerInterface[]
61
     */
62 4
    public function createSiteCrawlers(int $maxNewsToFetch): array
63
    {
64
        return [
65 4
            $this->createFinanceYahooSiteCrawler($maxNewsToFetch),
66 4
            $this->createBarronsSiteCrawler($maxNewsToFetch),
67
        ];
68
    }
69
70
    /**
71
     * @return ChannelInterface[]
72
     */
73 2
    public function createChannels(array $channelNames): array
74
    {
75 2
        $flipped = array_flip($channelNames);
76 2
        $channels = [];
77
78 2
        if (isset($flipped[EmailChannel::class])) {
79
            $channels[] = $this->createEmailChannel();
80
        }
81
82 2
        if (isset($flipped[SlackChannel::class])) {
83
            $channels[] = $this->createSlackChannel();
84
        }
85
86 2
        return $channels;
87
    }
88
89 4
    private function createCrawledInfoMapper(): CrawledInfoMapperInterface
90
    {
91 4
        return new CrawledInfoMapper(function (array $info): array {
92 4
            $info[Quote::URL] = $info[self::URLS][0];
93
94 4
            return $info;
95 4
        });
96
    }
97
98 4
    private function createFinanceYahooSiteCrawler(int $maxNewsToFetch): FinanceYahooSiteCrawler
99
    {
100 4
        return new FinanceYahooSiteCrawler([
101 4
            Quote::COMPANY_NAME => new JsonExtractor\QuoteSummaryStore\CompanyName(),
102 4
            Quote::REGULAR_MARKET_PRICE => new JsonExtractor\QuoteSummaryStore\RegularMarketPrice(),
103 4
            Quote::CURRENCY => new JsonExtractor\QuoteSummaryStore\Currency(),
104 4
            Quote::REGULAR_MARKET_CHANGE => new JsonExtractor\QuoteSummaryStore\RegularMarketChange(),
105 4
            Quote::REGULAR_MARKET_CHANGE_PERCENT => new JsonExtractor\QuoteSummaryStore\RegularMarketChangePercent(),
106 4
            Quote::MARKET_CAP => new JsonExtractor\QuoteSummaryStore\MarketCap(),
107 4
            Quote::LAST_TREND => new JsonExtractor\QuoteSummaryStore\RecommendationTrend(),
108 4
            Quote::LATEST_NEWS => new JsonExtractor\StreamStore\News($this->createNewsNormalizer($maxNewsToFetch)),
0 ignored issues
show
Bug introduced by
The type Chemaclass\StockTicker\D...ractor\StreamStore\News was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
109 4
            self::URLS => new JsonExtractor\RouteStore\ExternalUrl(),
110
        ]);
111
    }
112
113 4
    private function createNewsNormalizer(int $maxNewsToFetch): NewsNormalizer
114
    {
115 4
        return new NewsNormalizer(new DateTimeZone('Europe/Berlin'), $maxNewsToFetch);
116
    }
117
118 4
    private function createBarronsSiteCrawler(int $maxNewsToFetch): BarronsSiteCrawler
119
    {
120 4
        return new BarronsSiteCrawler([
121 4
            Quote::LATEST_NEWS => new News($this->createNewsNormalizer($maxNewsToFetch)),
122
        ]);
123
    }
124
125
    private function createEmailChannel(string $templateName = 'email.twig'): EmailChannel
126
    {
127
        return new EmailChannel(
128
            $this->config->getToAddress(),
129
            new Mailer(new GmailSmtpTransport(
130
                $this->config->getMailerUsername(),
131
                $this->config->getMailerPassword()
132
            )),
133
            new TwigTemplateGenerator(
134
                $this->createTwigEnvironment(),
135
                $templateName
136
            )
137
        );
138
    }
139
140
    private function createSlackChannel(string $templateName = 'slack.twig'): SlackChannel
141
    {
142
        return new SlackChannel(
143
            $this->config->getSlackDestinyChannelId(),
144
            new HttpSlackClient(HttpClient::create([
145
                'auth_bearer' => $this->config->getSlackBotUserOauthAccessToken(),
146
            ])),
147
            new TwigTemplateGenerator(
148
                $this->createTwigEnvironment(),
149
                $templateName
150
            )
151
        );
152
    }
153
154
    private function createTwigEnvironment(): Environment
155
    {
156
        $loader = new FilesystemLoader($this->config->getTemplatesDir());
157
        $isDebug = $this->config->isDebug();
158
        $twig = new Environment($loader, ['debug' => $isDebug]);
159
160
        if ($isDebug) {
161
            $twig->addExtension(new DebugExtension());
162
        }
163
164
        return $twig;
165
    }
166
}
167