tao-test/app/taoClientDiagnostic/model/storage/Sql.php

228 lines
6.5 KiB
PHP

<?php
/**
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; under version 2
* of the License (non-upgradable).
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright (c) 2015 (original work) Open Assessment Technologies SA;
*
*
*/
namespace oat\taoClientDiagnostic\model\storage;
use Doctrine\DBAL\DBALException;
use oat\oatbox\service\ConfigurableService;
use oat\taoClientDiagnostic\exception\StorageException;
/**
* Class Sql
* @package oat\taoClientDiagnostic\model\storage
*/
class Sql extends ConfigurableService implements Storage
{
/**
* Constant for diagnostic table name
*/
const DIAGNOSTIC_TABLE = 'diagnostic_report';
/**
* Constant for persistence option
*/
const DIAGNOSTIC_PERSISTENCE = 'persistence';
/**
* @var \common_persistence_Persistence
*/
private $persistence;
private const FIELDS_INT = [
self::DIAGNOSTIC_BANDWIDTH_SIZE,
self::DIAGNOSTIC_INTENSIVE_BANDWIDTH_SIZE,
self::DIAGNOSTIC_PERFORMANCE_COUNT,
self::DIAGNOSTIC_BANDWIDTH_COUNT,
self::DIAGNOSTIC_FINGERPRINT_ERRORS,
self::DIAGNOSTIC_FINGERPRINT_CHANGED,
self::DIAGNOSTIC_INTENSIVE_BANDWIDTH_COUNT
];
private const FIELDS_STRING = [
self::DIAGNOSTIC_BROWSERVERSION,
self::DIAGNOSTIC_SCHOOL_NUMBER,
self::DIAGNOSTIC_OSVERSION,
];
/**
* Get persistence with configurable driver option of Sql Storage
* Get default driver if option is not set
* @return \common_persistence_Persistence
*/
public function getPersistence()
{
$persistenceOption = $this->getOption(self::DIAGNOSTIC_PERSISTENCE);
$persistence = (!empty($persistenceOption)) ? $persistenceOption : 'default';
return \common_persistence_Manager::getPersistence($persistence);
}
/**
* If record already exists, update it by new values
* Else insert new entry
* @param $id
* @param array $data
* @return boolean
* @throws StorageException
*/
public function store($id, $data = array())
{
try {
if (empty($id)) {
throw new StorageException('Invalid id parameter.');
}
$this->persistence = $this->getPersistence();
$data = $this->cleanInputData($data);
if (!$this->exists($id)) {
$this->insert($id, $data);
} else {
$this->update($id, $data);
}
return true;
} catch (DBALException $e) {
throw new StorageException($e->getMessage());
}
}
/**
* Check if $input keys are constants of Storage
* @param array $input
* @return array
* @throws StorageException
*/
protected function cleanInputData(array $input)
{
foreach ($input as $key => $value) {
$const = get_called_class() . '::DIAGNOSTIC_' . strtoupper($key);
if (defined($const)) {
$data[constant($const)] = $this->castValue(constant($const), $value);
}
}
if (empty($data)) {
throw new StorageException('No data to insert into storage');
}
return $data;
}
/**
* Check if record is already in database by $this->id
* @param $id
* @return bool
*/
private function exists($id)
{
$query = 'SELECT ' . self::DIAGNOSTIC_ID . ' FROM ' . self::DIAGNOSTIC_TABLE . ' WHERE ' . self::DIAGNOSTIC_ID . ' = ?';
$statement = $this->persistence->query($query, array($id));
return (boolean)$statement->rowCount();
}
/**
* Create new record in SQL table with $data & $this->id
* @param $id
* @param $data
* @return mixed
*/
private function insert($id, $data)
{
$platform = $this->persistence->getPlatform();
$columns = array_merge(array(
self::DIAGNOSTIC_ID => $id,
self::DIAGNOSTIC_CREATED_AT => $platform->getNowExpression()
), $data);
$query = 'INSERT INTO ' . self::DIAGNOSTIC_TABLE . '(' . implode(', ', array_map([$this, 'tableize'], array_keys($columns))) . ')' .
' VALUES (' . str_repeat("?,", count($columns) - 1) . '? )';
return $this->persistence->exec($query, array_values($columns));
}
/**
* @param $word
* @return string
* @throws StorageException
*/
private function tableize($word)
{
$tableized = preg_replace('~(?<=\\w)([A-Z])~u', '_$1', $word);
if ($tableized === null) {
throw new StorageException(sprintf(
'Invalid column name "%s"',
$word
));
}
return mb_strtolower($tableized);
}
/**
* Update record in SQL table with $data by $this->id
* @param $id
* @param $data
* @return mixed
*/
private function update($id, $data)
{
foreach ($data as $key => $value) {
$fields[] = $key . ' = ?';
}
$query = 'UPDATE ' . self::DIAGNOSTIC_TABLE . ' SET ' . implode(', ', $fields) .
' WHERE ' . self::DIAGNOSTIC_ID . ' = ?';
return $this->persistence->exec($query, array_merge(array_values($data), array($id)));
}
public function flush()
{
$query = 'DELETE FROM ' . self::DIAGNOSTIC_TABLE;
try{
$this->getPersistence()->exec($query);
} catch (DBALException $e){
return false;
}
return true;
}
/**
* @param string $field
* @param mixed $value
* @return float|int|string
*/
private function castValue($field, $value)
{
if (in_array($field, self::FIELDS_STRING)) {
return (string)$value;
}
if (is_string($value)) {
if (in_array($field, self::FIELDS_INT)) {
return (int)$value;
}
return is_numeric($value) ? (float)$value : $value;
}
return $value;
}
}