PHP Classes

File: src/Factory.php

Recommend this page to a friend!
  Classes of Scott Arciszewski   EasyDB   src/Factory.php   Download  
File: src/Factory.php
Role: Class source
Content type: text/plain
Description: Class source
Class: EasyDB
Simple Database Abstraction Layer around PDO
Author: By
Last change: Include return type
Clean up Factory class
Support Psalm taint analysis
Date: 1 year ago
Size: 3,190 bytes
 

Contents

Class file image Download
<?php
declare(strict_types=1);

namespace
ParagonIE\EasyDB;

use
ParagonIE\EasyDB\Exception\{
   
ConstructorFailed
};
use
PDO;
use
PDOException;
use function
   
explode,
   
is_string,
   
str_contains;

/**
 * Class Factory
 *
 * @package ParagonIE\EasyDB
 */
abstract class Factory
{
   
/**
     * Create a new EasyDB object based on PDO constructors
     *
     * @param string $dsn
     * @param ?string $username
     * @param ?string $password
     * @param array $options
     * @return EasyDB
     *
     * @throws ConstructorFailed
     *
     * @psalm-taint-sink user_secret $password
     */
   
public static function create(
       
string $dsn,
       
string $username = null,
       
string $password = null,
        array
$options = []
    ):
EasyDB {
        return static::
fromArray([$dsn, $username, $password, $options]);
    }
   
   
/**
     * Create a new EasyDB object from array of parameters
     *
     * @param array $config
     * @return EasyDB
     *
     * @throws ConstructorFailed
     */
   
public static function fromArray(array $config): EasyDB
   
{
       
/** @var string $dsn */
       
$dsn = $config[0];
       
/** @var string|null $username */
       
$username = $config[1] ?? null;
       
/** @var string|null $password */
       
$password = $config[2] ?? null;
       
/** @var array $options */
       
$options = $config[3] ?? [];

       
$dbEngine = '';
       
$post_query = null;

        if (!
is_string($username)) {
           
$username = '';
        }
        if (!
is_string($password)) {
           
$password = '';
        }

       
// Let's grab the DB engine
       
if (str_contains($dsn, ':')) {
           
$dbEngine = explode(':', $dsn)[0];
        }

       
$post_query = '';

       
// If no charset is specified, default to UTF-8
       
switch ($dbEngine) {
            case
'mysql':
                if (!
str_contains($dsn, ';charset=')) {
                   
$dsn .= ';charset=utf8mb4';
                }
                break;
            case
'pgsql':
               
$post_query = "SET NAMES 'UNICODE'";
                break;
        }

        try {
           
$pdo = new PDO($dsn, $username, $password, $options);
        } catch (
PDOException $e) {
            if (
str_contains($e->getMessage(), 'could not find driver')) {
                throw (new
ConstructorFailed(
                   
'Could not create a PDO connection. Is the driver installed/enabled?'
               
))->setRealException($e);
            }
           
            if (
str_contains($e->getMessage(), 'unknown database')) {
                throw (new
ConstructorFailed(
                   
'Could not create a PDO connection. Check that your database exists.'
               
))->setRealException($e);
            }
           
           
// Don't leak credentials directly if we can.
           
throw (new ConstructorFailed(
               
'Could not create a PDO connection. Please check your username and password.'
           
))->setRealException($e);
        }

        if (!empty(
$post_query)) {
           
$pdo->query($post_query);
        }

        return new
EasyDB($pdo, $dbEngine, $options);
    }
}