View source  
  <?php
namespace Drupal\Core\Database\Driver\pgsql\Install;
use Drupal\Core\Database\Database;
use Drupal\Core\Database\Install\Tasks as InstallTasks;
use Drupal\Core\Database\Driver\pgsql\Connection;
use Drupal\Core\Database\DatabaseNotFoundException;
class Tasks extends InstallTasks {
  
  protected $pdoDriver = 'pgsql';
  
  public function __construct() {
    $this->tasks[] = array(
      'function' => 'checkEncoding',
      'arguments' => array(),
    );
    $this->tasks[] = array(
      'function' => 'checkBinaryOutput',
      'arguments' => array(),
    );
    $this->tasks[] = array(
      'function' => 'checkStandardConformingStrings',
      'arguments' => array(),
    );
    $this->tasks[] = array(
      'function' => 'initializeDatabase',
      'arguments' => array(),
    );
  }
  
  public function name() {
    return t('PostgreSQL');
  }
  
  public function minimumVersion() {
    return '9.1.2';
  }
  
  protected function connect() {
    try {
      
      db_set_active();
      
      Database::getConnection();
      $this
        ->pass('Drupal can CONNECT to the database ok.');
    } catch (\Exception $e) {
      
      if ($e
        ->getCode() == Connection::DATABASE_NOT_FOUND) {
        
        $connection_info = Database::getConnectionInfo();
        $database = $connection_info['default']['database'];
        unset($connection_info['default']['database']);
        
        Database::removeConnection('default');
        Database::addConnectionInfo('default', 'default', $connection_info['default']);
        try {
          
          Database::getConnection()
            ->createDatabase($database);
          Database::closeConnection();
          
          Database::removeConnection('default');
          $connection_info['default']['database'] = $database;
          Database::addConnectionInfo('default', 'default', $connection_info['default']);
          
          Database::getConnection();
          $this
            ->pass('Drupal can CONNECT to the database ok.');
        } catch (DatabaseNotFoundException $e) {
          
          $this
            ->fail(t('Database %database not found. The server reports the following message when attempting to create the database: %error.', array(
            '%database' => $database,
            '%error' => $e
              ->getMessage(),
          )));
        }
      }
      else {
        
        $this
          ->fail(t('Failed to connect to your database server. The server reports the following message: %error.<ul><li>Is the database server running?</li><li>Does the database exist, and have you entered the correct database name?</li><li>Have you entered the correct username and password?</li><li>Have you entered the correct database hostname?</li></ul>', array(
          '%error' => $e
            ->getMessage(),
        )));
        return FALSE;
      }
    }
    return TRUE;
  }
  
  protected function checkEncoding() {
    try {
      if (db_query('SHOW server_encoding')
        ->fetchField() == 'UTF8') {
        $this
          ->pass(t('Database is encoded in UTF-8'));
      }
      else {
        $this
          ->fail(t('The %driver database must use %encoding encoding to work with Drupal. Recreate the database with %encoding encoding. See <a href="INSTALL.pgsql.txt">INSTALL.pgsql.txt</a> for more details.', array(
          '%encoding' => 'UTF8',
          '%driver' => $this
            ->name(),
        )));
      }
    } catch (\Exception $e) {
      $this
        ->fail(t('Drupal could not determine the encoding of the database was set to UTF-8'));
    }
  }
  
  function checkBinaryOutput() {
    
    $database_connection = Database::getConnection();
    if (version_compare($database_connection
      ->version(), '9') >= 0) {
      if (!$this
        ->checkBinaryOutputSuccess()) {
        
        $connection_options = $database_connection
          ->getConnectionOptions();
        
        $query = "ALTER DATABASE \"" . $connection_options['database'] . "\" SET bytea_output = 'escape';";
        try {
          db_query($query);
        } catch (\Exception $e) {
          
        }
        
        db_close();
        
        if (!$this
          ->checkBinaryOutputSuccess()) {
          $replacements = array(
            '%setting' => 'bytea_output',
            '%current_value' => 'hex',
            '%needed_value' => 'escape',
            '@query' => $query,
          );
          $this
            ->fail(t("The %setting setting is currently set to '%current_value', but needs to be '%needed_value'. Change this by running the following query: <code>@query</code>", $replacements));
        }
      }
    }
  }
  
  protected function checkBinaryOutputSuccess() {
    $bytea_output = db_query("SHOW bytea_output")
      ->fetchField();
    return $bytea_output == 'escape';
  }
  
  public function checkStandardConformingStrings() {
    $database_connection = Database::getConnection();
    if (!$this
      ->checkStandardConformingStringsSuccess()) {
      
      $connection_options = $database_connection
        ->getConnectionOptions();
      
      $query = "ALTER DATABASE \"" . $connection_options['database'] . "\" SET standard_conforming_strings = 'on';";
      try {
        $database_connection
          ->query($query);
      } catch (\Exception $e) {
        
      }
      
      Database::closeConnection();
      
      if (!$this
        ->checkStandardConformingStringsSuccess()) {
        $replacements = array(
          '%setting' => 'standard_conforming_strings',
          '%current_value' => 'off',
          '%needed_value' => 'on',
          '@query' => $query,
        );
        $this
          ->fail(t("The %setting setting is currently set to '%current_value', but needs to be '%needed_value'. Change this by running the following query: <code>@query</code>", $replacements));
      }
    }
  }
  
  protected function checkStandardConformingStringsSuccess() {
    $standard_conforming_strings = Database::getConnection()
      ->query("SHOW standard_conforming_strings")
      ->fetchField();
    return $standard_conforming_strings == 'on';
  }
  
  function initializeDatabase() {
    
    try {
      $connection = Database::getConnection();
      
      if (!$connection
        ->query("SELECT COUNT(*) FROM pg_proc WHERE proname = 'rand'")
        ->fetchField()) {
        $connection
          ->query('CREATE OR REPLACE FUNCTION "rand"() RETURNS float AS
          \'SELECT random();\'
          LANGUAGE \'sql\'', [], [
          'allow_delimiter_in_query' => TRUE,
        ]);
      }
      if (!$connection
        ->query("SELECT COUNT(*) FROM pg_proc WHERE proname = 'substring_index'")
        ->fetchField()) {
        $connection
          ->query('CREATE OR REPLACE FUNCTION "substring_index"(text, text, integer) RETURNS text AS
          \'SELECT array_to_string((string_to_array($1, $2)) [1:$3], $2);\'
          LANGUAGE \'sql\'', [], [
          'allow_delimiter_in_query' => TRUE,
        ]);
      }
      $this
        ->pass(t('PostgreSQL has initialized itself.'));
    } catch (\Exception $e) {
      $this
        ->fail(t('Drupal could not be correctly setup with the existing database due to the following error: @error.', [
        '@error' => $e
          ->getMessage(),
      ]));
    }
  }
  
  public function getFormOptions(array $database) {
    $form = parent::getFormOptions($database);
    if (empty($form['advanced_options']['port']['#default_value'])) {
      $form['advanced_options']['port']['#default_value'] = '5432';
    }
    return $form;
  }
}