Completed
Pull Request — master (#34)
by
unknown
02:24
created

Ratings::filterCustomMetaData()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 10
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 10
rs 9.4285
cc 3
eloc 5
nc 3
nop 1
1
<?php
2
3
namespace MovingImage\Client\VMPro\Services;
4
5
use MovingImage\Client\VMPro\Entity\Video;
6
use MovingImage\Client\VMPro\Entity\VideoRequestParameters;
7
use MovingImage\Client\VMPro\Interfaces\ApiClientInterface;
8
9
/**
10
 * Class Ratings.
11
 *
12
 * @author Robert Szeker <[email protected]>
13
 */
14
class Ratings
15
{
16
    /** @var ApiClientInterface */
17
    private $client;
18
19
    /** @var Video [] */
20
    private $videos = [];
21
22
    /** @var int */
23
    private $vmId;
24
25
    /** @var string */
26
    private $metadataFieldAverage;
27
28
    /** @var string */
29
    private $metadataFieldCount;
30
31
    public function __construct(
32
        ApiClientInterface $client,
33
        $vmId,
34
        $metadataFieldAverage,
35
        $metadataFieldCount
36
    ) {
37
        $this->client = $client;
38
        $this->metadataFieldAverage = $metadataFieldAverage;
39
        $this->metadataFieldCount = $metadataFieldCount;
40
        $this->vmId = $vmId;
41
    }
42
43
    /**
44
     * Increases the count of all ratings by one and calculates a new average rating value.
45
     *
46
     * @param string $videoId
47
     * @param int    $rating
48
     */
49
    public function addRating($videoId, $rating)
50
    {
51
        $customMetaData = $this->getVideo($videoId)->getCustomMetadata();
52
53
        $average = $this->getRatingAverage($videoId);
54
        $count = $this->getRatingCount($videoId);
55
        $newCount = $count + 1;
56
57
        $customMetaData[$this->metadataFieldCount] = $newCount;
58
        $customMetaData[$this->metadataFieldAverage] = (($average * $count) + $rating) / $newCount;
59
60
        $this->storeCustomMetaData($customMetaData, $videoId);
61
    }
62
63
    /**
64
     * Modifies the average rating value. Count of all ratings stays the same (will not be increased).
65
     * The use case of this function is, when someone wants to change its rating (video was already rated by that person).
66
     *
67
     * @param string $videoId
68
     * @param int    $rating
69
     * @param int    $oldRating
70
     */
71
    public function modifyRating($videoId, $rating, $oldRating)
72
    {
73
        $customMetaData = $this->getVideo($videoId)->getCustomMetadata();
74
75
        $average = $this->getRatingAverage($videoId);
76
        $count = $this->getRatingCount($videoId);
77
78
        $customMetaData[$this->metadataFieldAverage] = (($average * $count) - $oldRating + $rating) / $count;
79
80
        $this->storeCustomMetaData($customMetaData, $videoId);
81
    }
82
83
    /**
84
     * Returns the average rating value from the custom meta data fields from a given video.
85
     *
86
     * @param string $videoId
87
     *
88
     * @return float|int
89
     */
90
    public function getRatingAverage($videoId)
91
    {
92
        return $this->getCustomMetaDataField($videoId, $this->metadataFieldAverage);
93
    }
94
95
    /**
96
     * Returns the count of all ratings from the custom meta data fields from a given video.
97
     *
98
     * @param string $videoId
99
     *
100
     * @return float|int
101
     */
102
    private function getRatingCount($videoId)
103
    {
104
        return $this->getCustomMetaDataField($videoId, $this->metadataFieldCount);
105
    }
106
107
    /**
108
     * Returns a meta data field of a video always as a number.
109
     *
110
     * @param $videoId
111
     * @param $customMetaDataField
112
     *
113
     * @return float|int
114
     */
115
    private function getCustomMetaDataField($videoId, $customMetaDataField)
116
    {
117
        $customMetaData = $this->getVideo($videoId)->getCustomMetadata();
118
119
        return array_key_exists($customMetaDataField, $customMetaData)
120
            ? (float) $customMetaData[$customMetaDataField]
121
            : 0;
122
    }
123
124
    /**
125
     * Stores the custom meta data fields with the api client.
126
     *
127
     * @param array  $customMetaData
128
     * @param string $videoId
129
     */
130
    private function storeCustomMetaData($customMetaData, $videoId)
131
    {
132
        // only update custom meta data fields related to rating
133
        $this->client->setCustomMetaData(
134
            $this->vmId,
135
            $videoId,
136
            $this->filterCustomMetaData($customMetaData)
137
        );
138
139
        // also store custom meta data fields locally, if video is fetched again by function $this->getVideo($videoId)
140
        $this->getVideo($videoId)->setCustomMetadata($customMetaData);
141
    }
142
143
    /**
144
     * Fetches and returns video from api client and stores it locally.
145
     * This way api client will be requested only once for every video.
146
     *
147
     * @param string $videoId
148
     *
149
     * @return Video
150
     */
151
    private function getVideo($videoId)
152
    {
153
        if (!array_key_exists($videoId, $this->videos)) {
154
            $options = new VideoRequestParameters();
155
            $options->setIncludeCustomMetadata(true);
156
            $this->videos[$videoId] = $this->client->getVideo($this->vmId, $videoId, $options);
157
        }
158
159
        return $this->videos[$videoId];
160
    }
161
162
    /**
163
     * Returns custom meta data fields which are related to rating.
164
     *
165
     * @param array $customMetaData
166
     *
167
     * @return array
168
     */
169
    private function filterCustomMetaData($customMetaData)
170
    {
171
        foreach ($customMetaData as $key => $data) {
172
            if (!in_array($key, [$this->metadataFieldCount, $this->metadataFieldAverage])) {
173
                unset($customMetaData[$key]);
174
            }
175
        }
176
177
        return $customMetaData;
178
    }
179
}
180