forena-8.x-1.x-dev/src/FrxPlugin/Driver/FrxPDO.php

src/FrxPlugin/Driver/FrxPDO.php
<?php
/**
 * @file
 * General database engine used to do sql queries.
 *
 */
namespace Drupal\forena\FrxPlugin\Driver;
use Drupal\forena\Token\SQLReplacer;
use Drupal\forena\File\DataFileSystem;
use \SimpleXMLElement;

/**
 * Class FrxPDO
 * @FrxDriver(
 *   id="FrxPDO",
 *   name="PDO Driver"
 * )
 */
class FrxPDO extends DriverBase {


  private $db;
  public $debug;


  /**
   * Object constructor
   *
   * @param string $name
   *   PDO data connection name
   * @param array $conf
   *   Array containing configuration data. 
   */
  public function __construct($name, $conf, DataFileSystem $fileSystem) {
    parent::__construct($name, $conf, $fileSystem);
    $uri = $conf['uri'];
    $this->debug = @$conf['debug'];
    if ($uri) {
      // Test for PDO suport
      if (!class_exists('PDO')) {
        $this->app()->error('PDO support not installed.', 'PDO support not installed.');
        return NULL; 
      }

      $options = array();
      if (@$conf['mysql_charset']) {
        $options = array(
        \PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES ' . $conf['mysql_charset'],
        );
      }

      // Test for driver support
      @list($prot, $c) = explode(':', $uri, 2);
      $drivers = \PDO::getAvailableDrivers();
      $this->db_type = $prot;

      if ($drivers && (array_search($prot, $drivers)===FALSE)) {
        $msg = 'PDO driver support for ' . $prot . ' not installed';
        $this->app()->error($msg, $msg);
        return NULL; 
      }
      try {
        if (isset($conf['user'])) {
          $db = new \PDO($uri, $conf['user'], @$conf['password'], $options);
        }
        else {
          $db = new \PDO($uri, NULL, NULL, $options);
        }
        $this->db = $db;
        if (!is_object($db)) {
          $this->app()->error('Unknown error connecting to database ' . $uri);
        }
      } catch (\PDOException $e) {
        $this->app()->error('Unable to connect to database', $e->getMessage());
      }
      if($this->db) $this->db->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_OBJ);

    }
    else {
      $this->app()->error('No database connection string specified');
    }

    // Set up the stuff required to translate.
    $this->te = new SQLReplacer($this);
  }

  public function parseConnectionStr() {
    $uri = @$this->conf['uri'];
    @list($prot, $conn) = explode(':', $uri, 2);
    $conn = str_replace(';', ' ', $conn);
    $info = array();
    foreach(explode(' ', $conn) as $pairs) {
      if (strpos($pairs, '=')!==FALSE) {
        list($key, $value) = @explode('=', $pairs, 2);
        $info[trim($key)] = trim($value);
      }
    }
    return $info;
  }

  /**
   * Get data based on file data block in the repository.
   *
   * @param string $sql 
   *   Query to execute
   * @param array $options
   *   Array of parameter types for the query.
   * @return SimpleXMLElement | array 
   *   Data from executed SQL query. 
   */
  public function sqlData($sql, $options = array()) {
    // Load the block from the file
    $db = $this->db;
    $xml ='';
    // Load the types array based on data
    $this->types = isset($options['type']) ? $options['type'] : array();

    if ($sql && $db) {
      $sql = $this->te->replace($sql);
      try {
        $rs = $db->query($sql);

      }
      catch ( \PDOException $e) {
        $line = $e->getLine();
        $text = $e->getMessage();
       $this->app()->error('PDO_error: $line', $text);
       return NULL;

      }
      if (@$options['return_type'] == 'raw') {
        return $rs;
      }
      $xml = new \SimpleXMLElement('<table/>');
      $e = $db->errorCode();

      if ($e != '00000') {
        $i = $db->errorInfo();
        $text =  $i[0] . ':' . $i[2];
        //if (forena_user_access_check('build forena sql blocks')) {
        if (!$this->block_name) {
          $short = t('%e', array('%e' => $text));
        } else {
          $short = t('SQL Error in %b.sql', array('%b' => $this->block_name));
        }
        $this->app()->error($short, $text);

      }
      else if ($rs && $rs->columnCount())  {
        if (@$options['return_type'] == 'raw') return $rs;
        $rownum = 0;
        foreach ($rs as $data) {
          $rownum++;
          $row_node = $xml->addChild('row');
          $row_node['num'] = $rownum;
          foreach ($data as $key => $value) {
            $row_node->addChild($key, htmlspecialchars($value));
          }
        }
      }

      if ($this->debug) {
        $d = '';
        if ($xml)  {
          $d = htmlspecialchars($xml->asXML());
        }
        $this->app()->debug('SQL: ' . $sql, '<pre> SQL:' . $sql . "\n XML: " . $d . "/n</pre>");
      }
      return $xml;
    }
    else {
      return NULL; 
    }

  }

  /**
   * Wrapper method cause some ODBC providers do not support
   * quoting.   We're going to assume the MSSQL method of quoting.
   * @param string $value
   *   Value to be quoted. 
   * @return string 
   *   Properly quoted value. 
   */
  public function quote($value) {
    $new_value =  $this->db->quote($value);
    if (($value!=='' || $value!==NULL) && !$new_value) {
      $value = "'" . str_replace("'", "''", $value) . "'";
    }
    else {
      $value = $new_value;
    }
    return $value;
  }

  /**
   * Implement custom SQL formatter to make sure that strings are properly escaped.
   * Ideally we'd replace this with something that handles prepared statements, but it
   * wouldn't work for
   *
   * @param string $value
   *   The value being formatted. 
   * @param string $key
   *   The name of the token being replaced. 
   * @param bool $raw
   *   TRUE implies the value should not be formatted for human consumption. 
   * @return string 
   *   Formatted value. 
   */
  public function format($value, $key, $raw = FALSE) {
    if ($raw) return $value;
    $db = $this->db;
    $value = $this->parmConvert($key, $value);
    if ($db) {
      if ($value==='' || $value ===NULL || $value === array()) {
        $value = 'NULL';
      }
      elseif (is_int($value)) {
        $value = (int)$value;
        $value = (string)$value;
      }
      elseif (is_float($value)) {
        $value = (float)$value;
        $value = (string)$value;
      }
      elseif (is_array($value)) {
        if ($value == array()) {
          $value = 'NULL';
        }
        else {
          // Build a array of values string
          $i=0;
          $val ='';
          foreach ($value as $v) {
            $i++;
            if ($i!=1) {
              $val .= ',';
            }
            $val .= $this->quote($v);
          }
          $value = $val;
        }
      }
      else  $value =  $this->quote($value);
    }
    return (string)$value;
  }

  public function searchTables($str) {
    $str .= '%';
    $sql = $this->searchTablesSQL();
    if ($sql) {
      $st = $this->db->prepare($sql);
      if ($st) $st->execute(array(':str' => $str));
      if ($st) {
        return $st->fetchAll(\PDO::FETCH_COLUMN, 0);
      }
      else {
        return NULL; 
      }
    }
    else {
      return NULL; 
    }
  }

  public function searchTableColumns($table, $str) {
    $str .= '%';
    $sql = $this->searchTableColumnsSQL();
    $info = $this->parseConnectionStr();
    $database = isset($info['dbname']) ? $info['dbname'] : @$info['database'];
    if ($sql) {
      $st = $this->db->prepare($sql);
      if ($st) $st->execute(array(':table' => $table, ':database' => $database, ':str' => $str));
      if ($st) {
        return $st->fetchAll(\PDO::FETCH_COLUMN, 0);
      }
      else {
        return NULL;
      }
    }
    else {
      return NULL; 
    }
  }
}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc