Completed
Pull Request — master (#41)
by
unknown
63:48
created

buildCampaignFromData()   B

Complexity

Conditions 8
Paths 5

Size

Total Lines 26
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 8.0109

Importance

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