Issues (9)

src/StockTicker/StockTickerFactory.php (1 issue)

Severity
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;
12
use Chemaclass\StockTicker\Domain\Crawler\Site\Barrons\BarronsSiteCrawler;
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\MarketWatch;
16
use Chemaclass\StockTicker\Domain\Crawler\Site\MarketWatch\MarketWatchSiteCrawler;
17
use Chemaclass\StockTicker\Domain\Crawler\Site\Shared\NewsNormalizer;
18
use Chemaclass\StockTicker\Domain\Crawler\SiteCrawlerInterface;
19
use Chemaclass\StockTicker\Domain\Notifier\Channel\Email\EmailChannel;
20
use Chemaclass\StockTicker\Domain\Notifier\Channel\Slack\HttpSlackClient;
21
use Chemaclass\StockTicker\Domain\Notifier\Channel\Slack\SlackChannel;
22
use Chemaclass\StockTicker\Domain\Notifier\Channel\TwigTemplateGenerator;
23
use Chemaclass\StockTicker\Domain\Notifier\ChannelInterface;
24
use Chemaclass\StockTicker\Domain\Notifier\Notifier;
25
use Chemaclass\StockTicker\Domain\Notifier\NotifierInterface;
26
use Chemaclass\StockTicker\Domain\Notifier\NotifierPolicy;
27
use Chemaclass\StockTicker\Domain\WriteModel\Quote;
28
use DateTimeZone;
29
use Gacela\Framework\AbstractFactory;
30
use Symfony\Component\HttpClient\HttpClient;
31
use Symfony\Component\Mailer\Bridge\Google\Transport\GmailSmtpTransport;
32
use Symfony\Component\Mailer\Mailer;
33
use Twig\Environment;
34
use Twig\Extension\DebugExtension;
35
use Twig\Loader\FilesystemLoader;
36
37
/**
38
 * @method StockTickerConfig getConfig()
39
 */
40
final class StockTickerFactory extends AbstractFactory
41
{
42
    private const URLS = 'URLS';
43
44 4
    public function createQuoteCrawler(SiteCrawlerInterface ...$siteCrawlers): QuoteCrawlerInterface
45
    {
46 4
        return new QuoteCrawler(
47 4
            HttpClient::create(),
48 4
            $this->createCrawledInfoMapper(),
49 4
            ...$siteCrawlers,
50
        );
51
    }
52
53 2
    public function createNotifier(NotifierPolicy $policy, ChannelInterface ...$channels): NotifierInterface
54
    {
55 2
        return new Notifier($policy, ...$channels);
56
    }
57
58
    /**
59
     * @return Domain\Crawler\SiteCrawlerInterface[]
60
     */
61 4
    public function createSiteCrawlers(int $maxNewsToFetch): array
62
    {
63
        return [
64 4
//            $this->createFinanceYahooSiteCrawler($maxNewsToFetch),
65 4
            $this->createBarronsSiteCrawler($maxNewsToFetch),
66 4
            $this->createMarketWatchSiteCrawler($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(static function (array $info): array {
92 4
            $info[Quote::URL] = $info[self::URLS][0] ?? 'URLS not found';
93
94 4
            return $info;
95 4
        });
96
    }
97
98 4
    private function createFinanceYahooSiteCrawler(int $maxNewsToFetch): FinanceYahooSiteCrawler
0 ignored issues
show
The method createFinanceYahooSiteCrawler() is not used, and could be removed.

This check looks for private methods that have been defined, but are not used inside the class.

Loading history...
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)),
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 Barrons\HtmlCrawler\News($this->createNewsNormalizer($maxNewsToFetch)),
122
        ]);
123
    }
124
125 4
    private function createMarketWatchSiteCrawler(int $maxNewsToFetch): MarketWatchSiteCrawler
126
    {
127 4
        return new MarketWatchSiteCrawler([
128 4
            Quote::LATEST_NEWS => new MarketWatch\HtmlCrawler\News($this->createNewsNormalizer($maxNewsToFetch)),
129
        ]);
130
    }
131
132
    private function createEmailChannel(string $templateName = 'email.twig'): EmailChannel
133
    {
134
        return new EmailChannel(
135
            $this->getConfig()->getToAddress(),
136
            new Mailer(new GmailSmtpTransport(
137
                $this->getConfig()->getMailerUsername(),
138
                $this->getConfig()->getMailerPassword(),
139
            )),
140
            new TwigTemplateGenerator(
141
                $this->createTwigEnvironment(),
142
                $templateName,
143
            ),
144
        );
145
    }
146
147
    private function createSlackChannel(string $templateName = 'slack.twig'): SlackChannel
148
    {
149
        return new SlackChannel(
150
            $this->getConfig()->getSlackDestinyChannelId(),
151
            new HttpSlackClient(HttpClient::create([
152
                'auth_bearer' => $this->getConfig()->getSlackBotUserOauthAccessToken(),
153
            ])),
154
            new TwigTemplateGenerator(
155
                $this->createTwigEnvironment(),
156
                $templateName,
157
            ),
158
        );
159
    }
160
161
    private function createTwigEnvironment(): Environment
162
    {
163
        $loader = new FilesystemLoader($this->getConfig()->getTemplatesDir());
164
        $isDebug = $this->getConfig()->isDebug();
165
        $twig = new Environment($loader, ['debug' => $isDebug]);
166
167
        if ($isDebug) {
168
            $twig->addExtension(new DebugExtension());
169
        }
170
171
        return $twig;
172
    }
173
}
174