/**
  * Create a new PDO instance from ProcessWire $config API variable
  * 
  * If you need to make other PDO connections, just instantiate a new WireDatabasePDO (or native PDO)
  * rather than calling this getInstance method. 
  * 
  * @param Config $config
  * @return WireDatabasePDO 
  * @throws WireException
  * 
  */
 public static function getInstance(Config $config)
 {
     if (!class_exists('PDO')) {
         throw new WireException('Required PDO class (database) not found - please add PDO support to your PHP.');
     }
     $host = $config->dbHost;
     $username = $config->dbUser;
     $password = $config->dbPass;
     $name = $config->dbName;
     $socket = $config->dbSocket;
     $charset = $config->dbCharset;
     if ($socket) {
         // if socket is provided ignore $host and $port and use $socket instead:
         $dsn = "mysql:unix_socket={$socket};dbname={$name};";
     } else {
         $dsn = "mysql:dbname={$name};host={$host}";
         $port = $config->dbPort;
         if ($port) {
             $dsn .= ";port={$port}";
         }
     }
     $driver_options = array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES '{$charset}'", PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION);
     $database = new WireDatabasePDO($dsn, $username, $password, $driver_options);
     $database->setDebugMode($config->debug);
     return $database;
 }
 /**
  * Set the database connection
  * 
  * @param PDO|WireDatabasePDO $database
  * @throws PDOException on invalid connection
  * 
  */
 public function setDatabase($database)
 {
     $query = $database->prepare('SELECT DATABASE()');
     $query->execute();
     list($dbName) = $query->fetch(PDO::FETCH_NUM);
     if ($dbName) {
         $this->databaseConfig['dbName'] = $dbName;
     }
     $this->database = $database;
 }
 /**
  * Load's ProcessWire using the supplied Config and populates all API fuel
  *
  * $param Config $config
  *
  */
 public function load(Config $config)
 {
     if ($this->debug) {
         Debug::timer('boot');
         Debug::timer('boot.load');
     }
     $this->wire('wire', $this, true);
     $this->wire('log', new WireLog(), true);
     $this->wire('notices', new Notices(), true);
     $this->wire('sanitizer', new Sanitizer());
     try {
         $database = WireDatabasePDO::getInstance($config);
         $this->wire('database', $database);
         $db = new DatabaseMysqli($config);
         $this->wire('db', $db);
     } catch (Exception $e) {
         // catch and re-throw to prevent DB connect info from ever appearing in debug backtrace
         throw new WireDatabaseException($e->getMessage());
     }
     $cache = new WireCache();
     $this->wire('cache', $cache);
     try {
         if ($this->debug) {
             Debug::timer('boot.load.modules');
         }
         $modules = new Modules($config->paths->modules);
         $modules->addPath($config->paths->siteModules);
         $this->wire('modules', $modules, true);
         $modules->setSubstitutes($config->substituteModules);
         $modules->init();
         if ($this->debug) {
             Debug::saveTimer('boot.load.modules');
         }
     } catch (Exception $e) {
         if (!$modules) {
             throw new WireException($e->getMessage());
         }
         $this->error($e->getMessage());
     }
     $updater = $modules->get('SystemUpdater');
     if (!$updater) {
         $modules->resetCache();
         $modules->get('SystemUpdater');
     }
     $fieldtypes = new Fieldtypes();
     $fields = new Fields();
     $fieldgroups = new Fieldgroups();
     $templates = new Templates($fieldgroups, $config->paths->templates);
     $this->wire('fieldtypes', $fieldtypes, true);
     $this->wire('fields', $fields, true);
     $this->wire('fieldgroups', $fieldgroups, true);
     $this->wire('templates', $templates, true);
     $pages = new Pages();
     $this->wire('pages', $pages, true);
     $this->initVar('fieldtypes', $fieldtypes);
     $this->initVar('fields', $fields);
     $this->initVar('fieldgroups', $fieldgroups);
     $this->initVar('templates', $templates);
     $this->initVar('pages', $pages);
     if ($this->debug) {
         Debug::timer('boot.load.permissions');
     }
     if (!($t = $templates->get('permission'))) {
         throw new WireException("Missing system template: 'permission'");
     }
     $permissions = new Permissions($t, $config->permissionsPageID);
     $this->wire('permissions', $permissions, true);
     if ($this->debug) {
         Debug::saveTimer('boot.load.permissions');
     }
     if ($this->debug) {
         Debug::timer('boot.load.roles');
     }
     if (!($t = $templates->get('role'))) {
         throw new WireException("Missing system template: 'role'");
     }
     $roles = new Roles($t, $config->rolesPageID);
     $this->wire('roles', $roles, true);
     if ($this->debug) {
         Debug::saveTimer('boot.load.roles');
     }
     if ($this->debug) {
         Debug::timer('boot.load.users');
     }
     if (!($t = $templates->get('user'))) {
         throw new WireException("Missing system template: 'user'");
     }
     $users = new Users($t, $config->usersPageID);
     $this->wire('users', $users, true);
     if ($this->debug) {
         Debug::saveTimer('boot.load.users');
     }
     // the current user can only be determined after the session has been initiated
     $session = new Session();
     $this->wire('session', $session, true);
     $this->wire('user', $users->getCurrentUser());
     $this->wire('input', new WireInput(), true);
     // populate admin URL before modules init()
     $config->urls->admin = $config->urls->root . ltrim($pages->_path($config->adminRootPageID), '/');
     if ($this->debug) {
         Debug::saveTimer('boot.load', 'includes all boot.load timers');
     }
     $this->setStatus(self::statusInit);
 }