forena-8.x-1.x-dev/src/DataManager.php

src/DataManager.php
<?php
/**
 * @file DataManager.inc
 * Enter description here ...
 * @author davidmetzler
 *
 */

namespace Drupal\forena;
use Drupal\forena\Context\DataContext;
use Drupal\forena\File\DataFileSystem;

class DataManager {
  // Singleton factory.
  protected static $instance;

  // The data context service in use by the app.
  public $dataSvc;
  public $app;
  public $repositories;
  public $drivers = [
    'FrxDrupal' => '\Drupal\forena\FrxPlugin\Driver\FrxDrupal',
    'FrxFiles' => '\Drupal\forena\FrxPlugin\Driver\FrxFiles',
    'FrxMSSQL' => '\Drupal\forena\FrxPlugin\Driver\FrxMSSQl',
    'FrxOracle' => '\Drupal\forena\FrxPlugin\Driver\FrxOracle',
    'FrxPDO' => '\Drupal\forena\FrxPlugin\Driver\FrxPDO',
    'FrxPostgres' => '\Drupal\forena\FrxPlugin\Driver\FrxPostgres',
  ];

  /**
   * Returns the Data Manager instance.
   * @return \Drupal\forena\DataManager
   * Static factory metion
   */
  public static function instance($force_new = FALSE) {
    if ((NULL === static::$instance) || $force_new) {
      static::$instance = new static();
    }
    return static::$instance;
  }

  //Determine data sources.
  public function __construct() {
    global $_forena_repositories;
    // Initialize services
    $app = AppService::instance();
    $this->dataSvc = new DataContext();
    $this->dataSvc->setContext('site', $app->siteContext);

    // Empty repository so we need to initialize
    // Build the default sample one
    $providers = array();

    // Load the repository list from the global settings.php file.
    if ($_forena_repositories) {
      $providers = $_forena_repositories;
    }

    $this->drivers = $app->getDriverPlugins();
    $data = AppService::instance()->getForenaProviders();
    foreach ($data as $module => $provider) {
      if (isset($provider['data'])) {
        $providers = array_merge($providers, $provider['data']);
      }
    }


    // Retrieve the repositories defined in the database;
    $results = db_query('SELECT * FROM {forena_repositories}');
    foreach ($results as $r) {
      if ($r->config) {
        $new_r = unserialize($r->config);
      }
      else {
        $new_r = array();
      }
      $r_name = $r->repository;
      if (is_array(@$providers[$r_name])) {
        $new_r = array_merge($new_r, $providers[$r_name]);
      }
      else {
        $new_r['source'] = 'user';
      }
      $new_r ['title'] = $r->title;
      $new_r ['enabled'] = $r->enabled;

      $providers[$r_name] = $new_r;
    }

    if ($_forena_repositories) {
      array_merge($providers, $_forena_repositories);
    }

    \Drupal::moduleHandler()->alter('forena_data_provider', $providers);

    $this->repositories = $providers;

  }

  /**
   * Load repository
   * @param string $name
   *   Name of the repository
   * @return \Drupal\forena\FrxPlugin\Driver\DriverBase
   */
  public function repository($name) {
    // Now determine if the object exists
    $object = NULL;
    if (isset($this->repositories[$name])) {
      if (@!is_object($this->repositories[$name]['data'])) {
        $this->loadRepositoryConfig($this->repositories[$name], $name);
      }
      $object = $this->repositories[$name]['data'];
    }
    else {
      AppService::instance()->error('Undefined repository' . $name, "Undefined Repository: $name ");
    }
    return $object;
  }

  // Putting this in a function to sandbox the repository settings
  protected function loadRepositoryConfig(&$repo, $name) {
    // First determine if the class file exisits
    $path = @$repo['source'];
    $conf = array();

    if (file_exists($path . '/settings.php')) {
      // Override with repository specific data
      include($path . '/settings.php');
    }

    $repo = array_merge($conf, $repo);
    if (!isset($repos['data'])||!is_object($repo['data'])) $repo['data'] = $this->createDataSource($repo, $path, $name);

  }

  /**
   * Load the driver class based on the class name.
   *
   * @param string $name
   * @return \Drupal\forena\FrxPlugin\Driver\DriverBase The data provider object
   */
  public function createDataSource($conf, $repo_path, $repos_name) {
    $o = NULL;
    @$name = $conf['driver'];
    $drivers = $this->drivers;
    // Instantiate the Data Driver object.
    if (isset($drivers[$name]) && class_exists($drivers[$name])) {
      $fileSystem = new DataFileSystem($name, $repo_path, $this);
      $class = $drivers[$name];
      $o = new $class($repos_name, $conf, $fileSystem);
    }
    else {
      AppService::instance()->error('Driver not found for ' . $conf['title']);
    }
    return $o;
  }


  /**
   * Load Block
   * Enter description here ...
   * @param $data_block string name of data block.
   * @return array 
   *   block definition. 
   */
  public function loadBlock($data_block) {
    $block = array();
    list($provider, $block_name) = explode('/', $data_block, 2);
    $repos = @$this->repositories[$provider];
    if (isset($repos['enabled']) && !$repos['enabled']) {
      return array();
    }

    $o = $this->repository($provider);
    if ($o) {
      $block = $o->loadBlock($block_name);
    }
    return $block;
  }

  /**
   * Save a data block ...
   * @param string $data_block
   * @param array $data
   */
  public function saveBlock($data_block, $data) {
    list($provider, $block_name) = explode('/', $data_block, 2);
    $file = isset($data['access']) ?  "--ACCESS=" . $data['access'] . "\n" . $data['file'] : $data['file'];
    $this->repository($provider)->fileSvc->save($data_block .'.sql', $file);
  }

  /**
   * Save a data block ...
   * @param string $data_block
   */
  public function deleteBlock($data_block) {
    list($provider) = explode('/', $data_block, 2);
    $this->repository($provider)->fileSvc->delete($data_block . '.sql');
  }



  /**
   * Extract the data by running a block
   *
   * @param $data_block String name ob block to load
   * @return \SimpleXMLElement
   */
  function data($data_block, $raw_mode=FALSE, array $data = []) {
    list($provider) = explode('/', $data_block, 2);
    //Intstantiate the provider
    $o = $this->repository($provider);
    $repos = @$this->repositories[$provider];
    if (isset($repos['enabled']) && !$repos['enabled']) {
      return '';
    }
    //Populate user callback.
    if (isset($repos['user callback'])) {
      $user_fn = $repos['user callback'];
      if (is_callable($user_fn)) {
        $current_user =   $user_fn();
        $this->dataSvc->setValue('current_user', $current_user);
      }
    }
    if ($data) foreach ($data as $key=>$value) {
      $this->dataSvc->setValue($key, $value);
    }


    $xml = NULL;
    if ($o) {
      $block = $this->loadBlock($data_block);
      $xml = $o->data($block, $raw_mode);
    }
    return $xml;
  }

  /**
   * Execute sql on a provider
   * @param $provider String Data provider index to reference
   * @param $sql String sql command to execute
   * @return \SimpleXMLElement | array 
   *   Data returned by executed sql query. 
   */
  public function sqlData($provider, $sql, $parms = array()) {
    $xml = '';

    //Intstantiate the provider
    /** @var \Drupal\forena\FrxPlugin\Driver\DriverBase $o */
    $o = $this->repository($provider);

    $repos = @$this->repositories[$provider];
    if (isset($repos['enabled']) && !$repos['enabled']) {
      return '';
    }
    //Populate user callback.
    if (isset($repos['user callback'])) {
      $user_fn = $repos['user callback'];
      if (is_callable($user_fn)) {
        $current_user =   $user_fn();
        $parms['current_user'] = $current_user;
      }
    }


    if ($o && $sql) {
      $this->dataSvc->push($parms, 'parm');

      // Parse the sql file
      $data = $o->parseSQLFile($sql);
      //now get the built SQL back
      $sql = $data['source'];
      $xml = $o->sqlData($sql, @$data['options']);
      $this->dataSvc->pop();
    }
    return $xml;
  }

  /**
   * Parse a block into its data
   * @param string $source
   *   Text data of the SQL block definition
   * @return array
   *   block definition.
   */
  public function sqlBlock($provider, $source) {      //Instantiate the provider
    $o = $this->repository($provider);

    $repos = @$this->repositories[$provider];
    if (isset($repos['enabled']) && !$repos['enabled']) {
      return '';
    }
    if ($o) {
      return $o->parseSQLFile($source);
    }
    else {
      return NULL; 
    }
  }

  /**
   * Build an SQL statement from the data provider
   * @param string $provider
   *   Data provider name
   * @param array $builder
   *   Build information.
   * @return string
   *   SQL query. 
   */
  public function buildSQL($provider, $builder) {
    $repos = @$this->repositories[$provider];
    if (isset($repos['enabled']) && !$repos['enabled']) {
      return '';
    }
    $o = $this->repository($provider);
    $sql = "SELECT * FROM (\n";
    $sql .= '--INCLUDE=' . $builder['block_name'] . "\n";
    $sql .= ") t\n";
    if (!empty($builder['where'])) {
      $sql .= "WHERE " . $o->buildFilterSQL($builder['where']);
    }
    return $sql;

  }


  /**
   * Check access control using the block in a data block.  In this case
   * public assess returns true.
   * @param string $block
   *   Repository block used to test access
   * @param string $path
   *   xpath to user right within xml data.
   * @param string $access
   *   Access to test
   * @pararm $cache
   *   Allow caching of block access check
   * @return boolean
   */
  function blockAccess($block, $path, $access, $cache=TRUE) {
    // PUBLIC always returns true.
    if ($access=='PUBLIC') return TRUE;
    if (!isset($_SESSION['forena_access'])) $_SESSION['forena_access'] = array();
    if ($cache && isset($_SESSION['forena_access'][$block])) {
      $rights = $_SESSION['forena_access'][$block];
    }
    else {
      $rights = array();
      // Get the block from the repository

      $this->dataSvc->push(array(), 'frx-block-access');
      $data = $this->data($block);
      $this->dataSvc->pop();
      if ($data) {
        if (!$path) {
          $path ='*/*';
        }
        $nodes = $data->xpath($path);
        if ($nodes) foreach ($nodes as $node) {
          $rights[] = (string)$node;
        }
        $_SESSION['forena_access'][$block]=$rights;
      }
    }
    foreach ($rights as $right) {
      if ($access == $right) return TRUE;
    }
    return FALSE;
  }


  /*
   * Recieves a datablock and returns an array of values from the data block.
   * @data_block: name of the data block to be invoked for values
   * @field: Specific field name within the data block. The values returned will only
   * come from this field.
   * @params: filtering for the data block
   * @where_clause: Where clause for data block to be filtered against.
   *
   */
  function dataBlockParams($data_block, $field, $label) {
    /** @var \SimpleXMLElement $xml */
    $xml = $this->data($data_block);

    $list = array();
    if ($xml) {
      $path = ($field) ? $field : '*[1]';
      $label_path = ($label) ? $label : '*[2]';


      //walk through the $xml.
      //$rows = $xml->xpath('*');

      if ($xml) {
        /** @var \SimpleXMLElement $row */
        foreach ($xml as $row) {
          $value = $row->xpath($path);
          $label_field = $row->xpath($label_path);
          $label_value =  $label_field ? (string)$label_field[0] : (string)$value[0];
          $list[(string)$value[0]] = (string)$label_value;
        }
      }
    }
    return $list;
  }

  public function listRepos() {
    $r = array();

    foreach ($this->repositories as $k=>$repos) {
      if (forena_user_access_check("access $k data")) {
        $r[$k] = $repos['title'];
      }
    }
    asort($r);
    return $r;
  }

}

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

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