<?php
namespace Jackbooted\DB;
use \Jackbooted\Config\Cfg;
use \Jackbooted\Util\Log4PHP;
/**
* @copyright Confidential and copyright (c) 2016 Jackbooted Software. All rights reserved.
*
* Written by Brett Dutton of Jackbooted Software
* brett at brettdutton dot com
*
* This software is written and distributed under the GNU General Public
* License which means that its source code is freely-distributed and
* available to the general public.
*/
class MDB extends \Jackbooted\Util\JB {
/**
* Default DB is Local
*/
const DEF = 'mongo';
// Keep a cache of the connections
private static $connections = [];
// Thelast accessed database
private static $lastDB = null;
// Keep a log of the number of calls
private static $callNumber = 0;
// Logging
private static $log;
private static $queryLoggingFunction;
private static $queryLoggingLevel;
private static $queryLogFlag;
private static $errorLoggingFunction;
private static $errorLoggingLevel;
/**
* Set up the statics, sets up the logging level in one place.
*
* If you want to change this throughout this class, you can adjust here.
* @since 1.0
* @return void
*/
public static function init() {
self::$log = Log4PHP::logFactory ( __CLASS__ );
// Sets up the logging level in one place
// If you want to change this throughout this class, you can adjust here
self::$queryLoggingFunction = [ self::$log, 'debug' ];
self::$queryLoggingLevel = Log4PHP::DEBUG;
self::$queryLogFlag = self::$log->isDisplayed ( self::$queryLoggingLevel );
self::$errorLoggingFunction = [ self::$log, 'error' ];
self::$errorLoggingLevel = Log4PHP::ERROR;
}
/**
* Returns the log object so that you can selectively turn on log flags.
*
* Eg:
* <pre>
* $dbLogger = DB::getLogger ();
* $dbLogger->setClassOutputDevice ( Log4PHP::SCREEN );
* $dbLogger->setClassErrorLevel ( Log4PHP::ALL );
* DB::init();
* </pre>
* @since 1.0
* @return Log4PHP - returns the log object.
*/
public static function getLogger () {
return self::$log;
}
public static function addDB($name, $host, $user, $password, $database, $options='', $driver = 'mongodb') {
Cfg::set($name.'-host', $host);
Cfg::set($name.'-db', $database);
Cfg::set($name.'-user', $user);
Cfg::set($name.'-pass', $password);
Cfg::set($name.'-options', $options);
Cfg::set($name.'-driver', $driver);
}
private static function connectionFactory ( $db=null ) {
if ( is_string ( $db ) ) {
// If this is a string then a key has been passed.
// The key may have been set up as PDO object or
// it might be a key from legacy config
return self::connectionFactoryFromString ( $db );
}
else if ( is_object ( $db ) ) {
// If this is an objecct then it is likely a Mongo object
self::$lastDB = $db;
return self::$lastDB;
}
else if ( is_array ( $db ) ) {
// If this is an array then it might be a database information
return self::connectionFactoryFromArray ( $db );
}
else {
return self::$lastDB;
}
}
private static function connectionFactoryFromString ( $db ) {
if ( isset ( self::$connections[$db] ) ) {
self::$lastDB = self::$connections[$db];
return self::$lastDB;
}
else {
$dbConnection = [ 'hostname' => Cfg::get ( $db . '-host' ),
'dbname' => Cfg::get ( $db . '-db' ),
'username' => Cfg::get ( $db . '-user' ),
'password' => Cfg::get ( $db . '-pass' ),
'options' => Cfg::get ( $db . '-options', '' ),
'driver' => Cfg::get ( $db . '-driver', 'mongodb' ) ];
if ( $dbConnection['hostname'] != '' ) {
return self::connectionFactoryFromArray ( $dbConnection );
}
else {
self::logErrorMessage ( 'Unknown DB: ' . $db );
return false;
}
}
}
private static function connectionFactoryFromArray ( $db ) {
if ( ! isset ( $db['driver'] ) ) {
$db['driver'] = 'mongodb';
}
if ( empty( $db['username'] ) && empty ( $db['password'] ) ) {
$pw = '';
}
else {
$pw = $db['username'] . ':' . $db['password'] . '@';
}
$connectionString = $db['driver'] . '://' . $pw . $db['hostname'];
$keyConn = hash ( 'md4', $connectionString . '*NO-DATABASE*' . $db['username'] . $db['password'] );
$keyDB = hash ( 'md4', $connectionString . $db['dbname'] . $db['username'] . $db['password'] );
try {
if ( isset( self::$connections[$keyDB] ) ) {
self::$lastDB = self::$connections[$keyDB];
return self::$lastDB;
}
else if ( isset( self::$connections[$keyConn] ) ) {
$mongo = self::$connections[$keyConn];
self::$lastDB = self::$connections[$keyDB] = $mongo->selectDB( $db['dbname'] );
return self::$lastDB;
}
else {
if ( empty( $db['options'] ) ) {
$options = [];
}
else {
$options = json_decode( $db['options'], true );
}
$mongo = self::$connections[$keyConn] = new MongoClient( $connectionString, $options );
self::$lastDB = self::$connections[$keyDB] = $mongo->selectDB( $db['dbname'] );
return self::$lastDB;
}
}
catch ( Exception $ex ) {
self::logErrorMessage ( 'Error Setting up new MongoDB conn: ' . $db['dbname'] . ' - ' . $db['username'] . ' - ' . $ex->getMessage() );
}
return false;
}
public static function collection ( $dbh, $collection, $log=false ) {
if ( self::$queryLogFlag || $log ) {
self::dbg ( $collection );
}
if ( ( $dbResource = self::connectionFactory ( $dbh ) ) === false ) {
return false;
}
try {
return new MongoCollection( $dbResource, $collection );
}
catch ( Exception $ex ) {
return self::logErrorMessage ( 'Trying to get new collection: ' . $collection . ' - ' . $ex->getMessage() );
}
}
private static function logErrorMessage( $message ) {
//echo $message . self::calculateCallLocation();
self::$log->error ( $message, self::calculateCallLocation() );
return false;
}
private static function dbg ( $qry, &$params=null ) {
$msg = self::$callNumber . ':"' . $qry . '"';
self::$callNumber ++;
if ( $params != null ) {
$msg .= ( is_array ( $params ) ) ? join ( ':', $params ) : $params;
}
self::$log->debug ( $msg, self::calculateCallLocation() );
}
private static function calculateCallLocation ( ) {
$stack = debug_backtrace ();
$stackLength = count ( $stack );
for ( $origin = 1; $origin<$stackLength; $origin++ ) {
if ( __FILE__ != $stack[$origin]['file'] ) break;
}
$fileLocation = basename ( $stack[$origin]['file'] );
$lineNumber = '(L:' . $stack[$origin]['line'] . ')';
$origin ++;
$calledFrom = ( ( isset ( $stack[$origin]['class'] ) ) ? $stack[$origin]['class'] : '' ) .
( ( isset ( $stack[$origin]['type'] ) ) ? $stack[$origin]['type'] : '' ) .
( ( isset ( $stack[$origin]['function'] ) ) ? $stack[$origin]['function'] : '' );
if ( $calledFrom == '' ) {
$calledFrom = $fileLocation;
}
return $lineNumber . $calledFrom;
}
public static function reset() {
if ( isset( self::$connections ) AND is_array( self::$connections ) AND count( self::$connections ) > 0) {
foreach ( self::$connections as $db => $connection ) {
unset( self::$connections[$db] );
}
}
else {
self::$connections = [];
}
}
}
|