Current Directory: /home/astoriaah/www/plugins/system/shlib/shl_packages/db
Viewing File: /home/astoriaah/www/plugins/system/shlib/shl_packages/db/log.php
<?php
/**
* Shlib - programming library
*
* @author Yannick Gaultier
* @copyright (c) Yannick Gaultier 2020
* @package shlib
* @license http://www.gnu.org/copyleft/gpl.html GNU/GPL
* @version 0.4.0.716
* @date 2020-12-07
*/
/* Security check to ensure this file is being included by a parent file.*/
defined('_JEXEC') or die;
/**
* Generic log to database
*
* ShlDb_Log::log(
* 'downloads', // scope
* array(
* 'name_1' => 'value_1',
* 'name_2' => 'value_2',
* 'name_3' => 'value_3',
* 'name_4' => 'value_4',
* 'name_5' => 'value_5',
* 'name_6' => 'value_6',
* ),
* $user = null
* );
*
* The values to use as index are defined at instance creation:
*
* \ShlDb_Log::create(
* 'downloads' // scope
* array( // indices
* 'name_3',
* 'name_5'
* )
* );
*
* The indices (max 3) are listed when creating the logger. In this example,
* assuming $data[..] is passed to be logged, then its values with keys name_3 and name_5
* will be used as index, being stored in the, respectively, key_1 and key_2 columns
* (the last key_3 column being left empty)
*
* Scope is used to identify the logger instance and thus db table to use.
* When logging an item, a secondary scope is passed and stored in the scope column. That way, the same db table/logger
* instance can host multiple data type - even though the key_1,key_2,key_3 will have to be the same. This is really
* equivalent to having a 4rth index, mut more readable maybe?
*
*/
class ShlDb_Log
{
/**
* Default db table name
*
*
* CREATE TABLE `<table_name>`
* (
* `id` INT PRIMARY KEY NOT NULL AUTO_INCREMENT,
* `scope` VARCHAR(180) NOT NULL,
* `description` VARCHAR(255) NOT NULL,
* `key_1` VARCHAR(180) NOT NULL,
* `key_2` VARCHAR(180) NOT NULL,
* `key_3` VARCHAR(180) NOT NULL,
* `data` LONGTEXT NOT NULL,
* `user_id` INT NOT NULL,
* `user_name` VARCHAR (100) NOT NULL,
* `user_email` VARCHAR (100) NOT NULL,
* `created_at` DATETIME DEFAULT '0000-00-00 00:00:00' NOT NULL,
* );
* CREATE INDEX `scope` ON `<table_name>` (`scope`);
* CREATE INDEX `user_name` ON `<table_name>` (`user_name`);
* CREATE INDEX `key_1` ON `<table_name>` (`key_1`);
* CREATE INDEX `key_2` ON `<table_name>` (`key_2`);
* CREATE INDEX `key_3` ON `<table_name>` (`key_3`);
*
*/
/**
* Cache for current user id
*
* @var int
*/
protected $userId = null;
/**
* Cache for current user email
*
* @var string
*/
protected $userEmail = '';
/**
* Cache for current user name
*
* @var string
*/
protected $userName = '';
/**
* The global scope name for this logger
*
* @var string
*/
protected $scope = '';
/**
* An array listing data keys to be used as indexed data
*
* @var array
*/
protected $indices = array();
/**
* @var string name of db table to hold keystore values
*/
protected $tableName = '';
/**
* Singleton
*
* @var \ShlDbKeystore
*/
private static $instance = array();
/**
* Public creation method for a logger
*
* @param string $scope Name of logger, used to derive table name
* @param array $indices List of data keys to be used as index
*
* @return \ShlDbKeystore
*/
public static function create($scope, $indices = array())
{
if (empty(self::$instance[$scope]))
{
self::$instance[$scope] = new self(
$scope,
$indices
);
}
return self::$instance[$scope];
}
/**
* Store parameters for the logger
*
* @param $scope
* @param $indices
*/
protected function __construct($rawScope, $indices)
{
if (empty($rawScope))
{
$message = 'Trying to create a database logger with an empty scope.';
\ShlSystem_Log::error('shLib', __METHOD__ . ': shLib: ' . $message);
throw new \InvalidArgumentException(
$message
);
}
$this->scope = $rawScope;
$this->tableName = '#__wbl_log_' . preg_replace('/[^a-zA-Z0-9_-]+/', '', $this->scope);
$this->indices = $indices;
}
/**
* Get a specific instance of a logger
*
* @param string $scope
*
* @return \ShlDb_Log
*
* @throws \InvalidArgumentException
*/
protected static function get($scope)
{
if (empty(self::$instance[$scope]))
{
\ShlSystem_Log::error('shLib', __METHOD__ . ': shLib: Trying to log to a database logger (' . $scope . ') that has not yet been created.');
return false;
}
return self::$instance[$scope];
}
/**
*
* \ShlDb_Log::log(
* 'downloads',
* array(
* 'name_1' => 'value_1',
* 'name_2' => 'value_2',
* 'name_3' => 'value_3',
* 'name_4' => 'value_4',
* 'name_5' => 'value_5',
* 'name_6' => 'value_6',
* )
* );
*
* The values to use as index are defined at instance creation
*
* @param string $subScope
* @param string $description
* @param mixed $data
* @param int|JUser $user Id or user object of the requester. Default to current user of not provided
*/
public function log(
$subScope,
$description,
$data,
$user = null
)
{
// get logger, fail immediately if not created
// this is logged by the get() method
$logger = self::get($this->scope);
if (empty($logger))
{
return false;
}
$written = $logger->write(
$subScope,
$description,
$data,
$user
);
return $written;
}
/**
* Internal method to write a log record to database
*
* @params string $subScope The scope for this specific item
* @param string $description
* @param mixed $data Object or Array of data
*/
protected function write($subScope, $description, $data, $user)
{
$dbData = array(
'scope' => $subScope,
'description' => $description,
'data' => json_encode($data),
'created_at' => \ShlSystem_Date::getUTCNow(),
'timestamp' => $this->getTimestamp()
);
$dbData = array_merge(
$dbData,
$this->getUserData($user),
$this->getIndices($data)
);
// insert or update the record in database
\ShlDbHelper::insert(
$this->tableName,
$dbData
);
}
/**
* Builds an array of user data, to be stored. If not user is provided
* then currently logged in one is used
*
* @param int|JUser $user
*
* @return array
*/
protected function getUserData($user)
{
if (!is_object($user))
{
// getUser requires a real NULL to fetch current user
$user = empty($user) ? null : (int) $user;
$user = \JFactory::getUser($user);
}
if (empty($user) || empty($user->id))
{
$userData = array(
'user_id' => '0',
'user_name' => 'n/a',
'user_email' => 'n/a',
);
}
else
{
$userData = array(
'user_id' => $user->id,
'user_name' => $user->email,
'user_email' => $user->username,
);
}
return $userData;
}
/**
* Finds the data set indexable properties and prepare an array
* with them, ready to be written to database
*
* @param mixed $data
*
* @return array
*/
protected function getIndices($data)
{
$indices = array();
for ($counter = 0; $counter < 3; $counter++)
{
$value = '';
$keyName = wbArrayGet($this->indices, $counter, '');
if (!empty($keyName))
{
if (is_array($data))
{
$value = wbArrayGet($data, $keyName, '');
}
else if (is_object($data))
{
$value = empty($data->{$keyName}) ? '' : $data->{$keyName};
}
}
$indices['key_' . ($counter + 1)] = $value;
}
return $indices;
}
private function getTimestamp()
{
$t = microtime();
$timestamp = substr($t, 11) + substr($t, 0, 9);
return $timestamp;
}
}