| 
<?phpnamespace 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 = [];
 }
 }
 }
 
 |