Passed
Push — master ( ccff23...5e5d56 )
by Tim
37s
created

CampaignConfigurationLoader::buildBucketFromData()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 12
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 4.0218

Importance

Changes 0
Metric Value
cc 4
eloc 8
nc 4
nop 1
dl 0
loc 12
ccs 8
cts 9
cp 0.8889
crap 4.0218
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare( strict_types = 1 );
4
5
namespace WMDE\BannerServer\UseCase\BannerSelection;
6
7
use Psr\Log\LoggerInterface;
8
use Symfony\Component\Yaml\Exception\ParseException;
9
use Symfony\Component\Yaml\Yaml;
10
use WMDE\BannerServer\Entity\BannerSelection\Banner;
11
use WMDE\BannerServer\Entity\BannerSelection\Bucket;
12
use WMDE\BannerServer\Entity\BannerSelection\Campaign;
13
use WMDE\BannerServer\Entity\BannerSelection\CampaignCollection;
14
use WMDE\BannerServer\Utils\SystemRandomIntegerGenerator;
15
16
/**
17
 * @license GNU GPL v2+
18
 */
19
class CampaignConfigurationLoader {
20
21
	private $configFile;
22
	private $logger;
23
24 5
	public function __construct( LoggerInterface $logger, string $configFile ) {
25 5
		$this->configFile = $configFile;
26 5
		$this->logger = $logger;
27 5
	}
28
29 5
	public function getCampaignCollection(): CampaignCollection {
30 5
		$campaigns = [];
31 5
		foreach ( $this->parseConfiguration() as $campaignName => $campaignData ) {
32
			try {
33 4
				$campaign = $this->buildCampaignFromData( $campaignName, $campaignData );
34 1
				$campaigns[] = $campaign;
35
			}
36 3
			catch ( \Exception $e ) {
37 4
				$this->logger->critical( $e->getMessage(), [ 'exception' => $e ] );
38
			}
39
		}
40 5
		return new CampaignCollection( ...$campaigns );
41
	}
42
43
	/**
44
	 * @throws \Exception
45
	 */
46 4
	private function buildCampaignFromData( string $campaignName, array $campaignData ): Campaign {
47 4
		$buckets = $this->buildBucketsFromData( $campaignData );
48 2
		if ( empty( $buckets ) ) {
49
			throw new \Exception( 'Campaign contains no buckets.' );
50
		}
51 2
		if ( empty( $campaignData['start'] ) || empty( $campaignData['end'] ) || !isset( $campaignData['trafficLimit'] ) ) {
52 1
			throw new \Exception( 'Campaign data is incomplete.' );
53
		}
54 1
		return new Campaign(
55 1
			$campaignName,
56 1
			new \DateTime( $campaignData['start'] ),
57 1
			new \DateTime( $campaignData['end'] ),
58 1
			(int)$campaignData['trafficLimit'],
59 1
			new SystemRandomIntegerGenerator(),
60 1
			array_shift( $buckets ),
61 1
			...$buckets
62
		);
63
	}
64
65
	/**
66
	 * @throws \Exception
67
	 */
68 4
	private function buildBucketsFromData( array $campaignData ): array {
69 4
		$buckets = [];
70 4
		foreach ( $campaignData['buckets'] as $bucketData ) {
71 4
			$bucket = $this->buildBucketFromData( $bucketData );
72 2
			$buckets[] = $bucket;
73
		}
74 2
		return $buckets;
75
	}
76
77
	/**
78
	 * @throws \Exception
79
	 */
80 4
	private function buildBucketFromData( array $bucketData ): Bucket {
81 4
		if ( !isset( $bucketData['name'] ) ) {
82 1
			throw new \Exception( 'A configured bucket has no name.' );
83
		}
84 3
		if ( !isset( $bucketData['banners'] ) ) {
85 1
			throw new \Exception( 'A configured bucket has no associated banners.' );
86
		}
87 2
		$banners = $this->buildBannersFromData( $bucketData['banners'] );
88 2
		if ( empty( $banners ) ) {
89
			throw new \Exception( 'A configured bucket has no valid banners associated with it.' );
90
		}
91 2
		return new Bucket( $bucketData['name'], array_shift( $banners ), ...$banners );
92
	}
93
94
	/**
95
	 * @throws \Exception
96
	 */
97 2
	private function buildBannersFromData( array $bannerData ): array {
98 2
		$banners = [];
99 2
		foreach ( $bannerData as $bannerIdentifier ) {
100 2
			if ( !$bannerIdentifier ) {
101
				throw new \Exception( 'A configured banner has an empty name.' );
102
			}
103 2
			$banners[] = new Banner( $bannerIdentifier );
104
		}
105 2
		return $banners;
106
	}
107
108 5
	private function parseConfiguration(): array {
109
		try {
110 5
			return Yaml::parseFile( $this->configFile );
111
		}
112 1
		catch ( ParseException $exception ) {
113 1
			$this->logger->critical( 'Unable to read banner server config file.', [ 'exception' => $exception ] );
114 1
			return [];
115
		}
116
	}
117
}