Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 90
0.00% covered (danger)
0.00%
0 / 12
CRAP
0.00% covered (danger)
0.00%
0 / 1
RdsDeliveryLogService
0.00% covered (danger)
0.00%
0 / 90
0.00% covered (danger)
0.00%
0 / 12
992
0.00% covered (danger)
0.00%
0 / 1
 log
0.00% covered (danger)
0.00%
0 / 19
0.00% covered (danger)
0.00%
0 / 1
20
 get
0.00% covered (danger)
0.00%
0 / 15
0.00% covered (danger)
0.00%
0 / 1
6
 flush
0.00% covered (danger)
0.00%
0 / 5
0.00% covered (danger)
0.00%
0 / 1
6
 deleteDeliveryExecutionData
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
2
 insertMultiple
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 search
0.00% covered (danger)
0.00%
0 / 32
0.00% covered (danger)
0.00%
0 / 1
156
 getFields
0.00% covered (danger)
0.00%
0 / 2
0.00% covered (danger)
0.00%
0 / 1
6
 decodeValues
0.00% covered (danger)
0.00%
0 / 6
0.00% covered (danger)
0.00%
0 / 1
12
 decodeData
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 encodeData
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getPersistence
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 getQueryBuilder
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php
2
3/**
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; under version 2
7 * of the License (non-upgradable).
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
17 *
18 * Copyright (c) 2016 (original work) Open Assessment Technologies SA;
19 *
20 */
21
22namespace oat\taoProctoring\model\deliveryLog\implementation;
23
24use Doctrine\DBAL\Connection;
25use Doctrine\DBAL\Query\QueryBuilder;
26use oat\oatbox\event\EventManager;
27use oat\taoDelivery\model\execution\Delete\DeliveryExecutionDeleteRequest;
28use oat\taoProctoring\model\deliveryLog\DeliveryLog;
29use oat\oatbox\service\ConfigurableService;
30use oat\taoProctoring\model\deliveryLog\event\DeliveryLogEvent;
31
32/**
33 * Interface DeliveryLog
34 *
35 * @package oat\taoProctoring\model\deliveryLog
36 * @author Aleh Hutnikau <hutnikau@1pt.com>
37 */
38class RdsDeliveryLogService extends ConfigurableService implements DeliveryLog
39{
40    public const OPTION_PERSISTENCE = 'persistence';
41    public const TABLE_NAME = 'delivery_log';
42
43    /**
44     * Log delivery execution data.
45     * Notice that `$data` parameter will be encoded to JSON before saving
46     *
47     * @param string $deliveryExecutionId
48     * @param string $eventId
49     * @param mixed $data
50     * @param string $user user identifier
51     * @return boolean
52     */
53    public function log($deliveryExecutionId, $eventId, $data, $user = null)
54    {
55        $data = $this->encodeData($data);
56
57        if ($user === null) {
58            $user = \common_session_SessionManager::getSession()->getUser()->getIdentifier();
59        }
60
61        if (empty($user) && PHP_SAPI == 'cli') {
62            $user = 'cli';
63        }
64
65        $createdAt = microtime(true);
66        $result = $this->getPersistence()->insert(
67            self::TABLE_NAME,
68            array(
69                self::DELIVERY_EXECUTION_ID => $deliveryExecutionId,
70                self::EVENT_ID => $eventId,
71                self::DATA => $data,
72                self::CREATED_AT => $createdAt,
73                self::CREATED_BY => $user,
74            )
75        );
76
77        $id = $this->getPersistence()->lastInsertId();
78        $this->getServiceLocator()->get(EventManager::SERVICE_ID)->trigger(new DeliveryLogEvent($id));
79
80        return $result === 1;
81    }
82
83    /**
84     * Get logged data by delivery execution id
85     *
86     * @param string $deliveryExecutionId
87     * @param string|null $eventId - filter data by event id
88     * @return mixed
89     */
90    public function get($deliveryExecutionId, $eventId = null)
91    {
92        $queryBuilder = $this->getQueryBuilder();
93        $queryBuilder
94            ->select('*')
95            ->from(static::TABLE_NAME)
96            ->where(static::DELIVERY_EXECUTION_ID . '=:delivery_execution_id')
97            ->setParameter('delivery_execution_id', $deliveryExecutionId)
98        ;
99
100        if ($eventId !== null) {
101            $queryBuilder
102                ->andWhere(static::EVENT_ID . '=:event_id')
103                ->setParameter('event_id', $eventId);
104            ;
105        }
106
107        $queryBuilder->orderBy(static::ID, 'ASC');
108
109        $data = $queryBuilder->execute()->fetchAll(\PDO::FETCH_ASSOC);
110
111        $result = $this->decodeValues($data);
112
113        return $result;
114    }
115
116
117    public function flush()
118    {
119        $query = 'TRUNCATE ' . self::TABLE_NAME;
120
121        try {
122            $this->getPersistence()->exec($query);
123        } catch (\PDOException $e) {
124            return false;
125        }
126        return true;
127    }
128
129    /**
130     * @inheritdoc
131     */
132    public function deleteDeliveryExecutionData(DeliveryExecutionDeleteRequest $request)
133    {
134        $queryBuilder = $this->getQueryBuilder();
135        $queryBuilder
136            ->delete(static::TABLE_NAME)
137            ->where(self::DELIVERY_EXECUTION_ID . '=:delivery_execution_id')
138            ->setParameter('delivery_execution_id', $request->getDeliveryExecution()->getIdentifier());
139
140        return ($queryBuilder->execute() > 0);
141    }
142
143    /**
144     * @param array $data
145     * @return mixed
146     */
147    public function insertMultiple(array $data)
148    {
149        return $this->getPersistence()->insertMultiple(self::TABLE_NAME, $data);
150    }
151
152    /**
153     * @param array $params
154     *  [
155     *      'delivery_execution_id' => '',
156     *      'event_id' => '',
157     *      'from' => '',
158     *      'to' => '',
159     *      'created_by' => '',
160     *  ]
161     * @param array $options
162     *  [
163     *      'order' => 'created_at',
164     *      'dir' => 'asc',
165     *      'limit' => null, // to get all records
166     *      'offset' => 0,
167     *      'shouldDecodeData' => true
168     *  ]
169     * @return mixed
170     */
171    public function search($params = [], $options = [])
172    {
173        $queryBuilder = $this->getQueryBuilder();
174        $queryBuilder
175            ->select('*')
176            ->from(static::TABLE_NAME)
177        ;
178
179        $fields = $this->getFields();
180        foreach ($params as $key => $val) {
181            if (in_array($key, $fields, false)) {
182                if (is_array($val)) {
183                    $queryBuilder->andWhere($key . ' IN (:' . $key . ')');
184                    $queryBuilder->setParameter($key, $val, Connection::PARAM_STR_ARRAY);
185                } else {
186                    $queryBuilder->andWhere($key . '= :' . $key);
187                    $queryBuilder->setParameter($key, $val);
188                }
189            }
190        }
191
192        if (isset($params['from'])) {
193            $queryBuilder->andWhere(self::CREATED_AT . ' >=:createdAtMore');
194            $queryBuilder->setParameter('createdAtMore', $params['from']);
195        }
196
197        if (isset($params['to'])) {
198            $queryBuilder->andWhere(self::CREATED_AT . ' <=:createdAtLess');
199            $queryBuilder->setParameter('createdAtLess', $params['to']);
200        }
201
202        if (isset($options['limit'])) {
203            $queryBuilder->setMaxResults($options['limit']);
204        }
205
206        if (isset($options['offset'])) {
207            $queryBuilder->setFirstResult($options['offset']);
208        }
209
210        if (isset($options['order']) && isset($options['dir'])) {
211            $queryBuilder->orderBy($options['order'], strtoupper($options['dir']));
212        }
213
214        $shouldDecodeData = isset($options['shouldDecodeData']) ? (bool)$options['shouldDecodeData'] : true;
215        $data             = $queryBuilder->execute()->fetchAll(\PDO::FETCH_ASSOC);
216        if ($shouldDecodeData) {
217            $result = $this->decodeValues($data);
218        } else {
219            $result = $data;
220        }
221        return $result;
222    }
223
224    /**
225     * @return array
226     */
227    protected function getFields()
228    {
229        $fields = $this->getOption(static::OPTION_FIELDS);
230
231        return is_null($fields) ? [] : $fields;
232    }
233
234    /**
235     * @param $data
236     * @return array
237     */
238    private function decodeValues(array $data)
239    {
240        $result = [];
241        foreach ($data as $row) {
242            if (isset($row[self::DATA])) {
243                $row[self::DATA] = $this->decodeData($row[self::DATA]);
244            }
245            $result[] = $row;
246        }
247        return $result;
248    }
249
250    /**
251     * @param $data
252     * @return array
253     */
254    protected function decodeData($data)
255    {
256        return json_decode($data, true);
257    }
258
259    /**
260     * @param array $data
261     * @return string
262     */
263    protected function encodeData($data)
264    {
265        return json_encode($data);
266    }
267
268    /**
269     * @return \common_persistence_SqlPersistence
270     */
271    private function getPersistence()
272    {
273        return \common_persistence_Manager::getPersistence($this->getOption(self::OPTION_PERSISTENCE));
274    }
275
276    /**
277     * @return QueryBuilder
278     */
279    private function getQueryBuilder()
280    {
281        return $this->getPersistence()->getPlatform()->getQueryBuilder();
282    }
283}