Test Setup Failed
Pull Request — master (#133)
by Gabriel
64:32
created

getCampaignCollection()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 5
c 0
b 0
f 0
dl 0
loc 7
ccs 2
cts 2
cp 1
rs 10
cc 2
nc 2
nop 0
crap 2
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 GPL-2.0-or-later
15
 */
16
class CampaignConfigurationLoader {
17
18
	private string $configFile;
19
20 5
	public function __construct( string $configFile ) {
21 5
		$this->configFile = $configFile;
22 5
	}
23
24
	public function getCampaignCollection(): CampaignCollection {
25
		$campaigns = [];
26
		foreach ( $this->parseConfiguration() as $campaignName => $campaignData ) {
27
				$campaign = $this->buildCampaignFromData( $campaignName, $campaignData );
28
				$campaigns[] = $campaign;
29 5
		}
30 5
		return new CampaignCollection( ...$campaigns );
31 5
	}
32 4
33 1
	private function buildCampaignFromData( string $campaignName, array $campaignData ): Campaign {
34
		$buckets = $this->buildBucketsFromData( $campaignData );
35 1
		if ( empty( $buckets ) ) {
36
			throw new \DomainException( 'Campaign contains no buckets.' );
37
		}
38
		if ( empty( $campaignData['start'] ) || empty( $campaignData['end'] ) || !isset( $campaignData['trafficLimit'] ) ) {
39
			throw new \DomainException( 'Campaign data is incomplete.' );
40
		}
41
		$minDisplayWidth = $this->integerOrNullValue( $campaignData, 'minDisplayWidth' );
42 4
		$maxDisplayWidth = $this->integerOrNullValue( $campaignData, 'maxDisplayWidth' );
43 4
		if ( $minDisplayWidth && $maxDisplayWidth && $minDisplayWidth > $maxDisplayWidth ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $minDisplayWidth of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
Bug Best Practice introduced by
The expression $maxDisplayWidth of type integer|null is loosely compared to true; this is ambiguous if the integer can be 0. You might want to explicitly use !== null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For integer values, zero is a special case, in particular the following results might be unexpected:

0   == false // true
0   == null  // true
123 == false // false
123 == null  // false

// It is often better to use strict comparison
0 === false // false
0 === null  // false
Loading history...
44 2
			throw new \DomainException(
45
				'Campaign data display width values are invalid (if defined, max must be higher than min).'
46
			);
47 2
		}
48 1
		return new Campaign(
49
			$campaignName,
50 1
			new \DateTime( $campaignData['start'] ),
51 1
			new \DateTime( $campaignData['end'] ),
52 1
			(int)$campaignData['trafficLimit'],
53 1
			$campaignData['category'] ?? 'default',
54 1
			new SystemRandomIntegerGenerator(),
55 1
			$minDisplayWidth,
56 1
			$maxDisplayWidth,
57 1
			array_shift( $buckets ),
58
			...$buckets
59
		);
60
	}
61
62
	private function buildBucketsFromData( array $campaignData ): array {
63
		$buckets = [];
64 4
		foreach ( $campaignData['buckets'] as $bucketData ) {
65 4
			$bucket = $this->buildBucketFromData( $bucketData );
66 4
			$buckets[] = $bucket;
67 4
		}
68 2
		return $buckets;
69
	}
70 2
71
	private function buildBucketFromData( array $bucketData ): Bucket {
72
		if ( !isset( $bucketData['name'] ) ) {
73
			throw new \DomainException( 'A configured bucket has no name.' );
74
		}
75
		if ( !isset( $bucketData['banners'] ) ) {
76 4
			throw new \DomainException( 'A configured bucket has no associated banners.' );
77 4
		}
78 1
		$banners = $this->buildBannersFromData( $bucketData['banners'] );
79
		if ( empty( $banners ) ) {
80 3
			throw new \DomainException( 'A configured bucket has no valid banners associated with it.' );
81 1
		}
82
		return new Bucket( $bucketData['name'], array_shift( $banners ), ...$banners );
83 2
	}
84 2
85
	private function buildBannersFromData( array $bannerData ): array {
86
		$banners = [];
87 2
		foreach ( $bannerData as $bannerIdentifier ) {
88
			if ( !$bannerIdentifier ) {
89
				throw new \DomainException( 'A configured banner has an empty name.' );
90
			}
91
			$banners[] = new Banner( $bannerIdentifier );
92
		}
93 2
		return $banners;
94 2
	}
95 2
96 2
	private function parseConfiguration(): array {
97
		return Yaml::parseFile( $this->configFile );
98
	}
99 2
100
	private function integerOrNullValue( array $campaignData, string $key ): ?int {
101 2
		if ( !isset( $campaignData[$key] ) ) {
102
			return null;
103
		}
104
		$value = $campaignData[$key];
105
		if ( !is_numeric( $value ) ) {
106
			return null;
107 5
		}
108 5
		return intval( $value );
109
	}
110
}
111