ACC SHELL

Path : /srv/www/vhosts/usoenergy/libs/Nette/Database/Reflection/
File Upload :
Current File : /srv/www/vhosts/usoenergy/libs/Nette/Database/Reflection/DiscoveredReflection.php

<?php

/**
 * This file is part of the Nette Framework (http://nette.org)
 *
 * Copyright (c) 2004, 2011 David Grudl (http://davidgrudl.com)
 *
 * For the full copyright and license information, please view
 * the file license.txt that was distributed with this source code.
 */

namespace Nette\Database\Reflection;

use Nette;



/**
 * Reflection metadata class with discovery for a database.
 *
 * @author     Jakuv Vrana
 */
class DiscoveredReflection extends Nette\Object implements Nette\Database\IReflection
{
	/** @var Nette\Caching\Cache */
	protected $cache;

	/** @var Nette\Caching\IStorage */
	protected $cacheStorage;

	/** @var Nette\Database\Connection */
	protected $connection;

	/** @var string */
	protected $foreign;

	/** @var array */
	protected $structure = array();



	/**
	 * Create autodisovery structure.
	 * @param  Nette\Caching\IStorage
	 * @param  string use "%s_id" to access $name . "_id" column in $row->$name
	 */
	public function __construct(Nette\Caching\IStorage $storage = NULL, $foreign = '%s_id')
	{
		$this->cacheStorage = $storage;
		$this->foreign = (string) $foreign;
	}



	public function setConnection(Nette\Database\Connection $connection)
	{
		$this->connection = $connection;

		if ($this->cacheStorage) {
			$this->cache = new Nette\Caching\Cache($this->cacheStorage, 'Nette.Database.Discovery/' . $connection->getDsn());
			$this->structure = $this->cache->load('structure');
		}
	}



	public function __destruct()
	{
		if ($this->cache) {
			$this->cache->save('structure', $this->structure);
		}
	}



	public function getPrimary($table)
	{
		if (isset($this->structure['primary'][$table]))
			return $this->structure['primary'][$table];

		$primary = NULL;
		if ($this->connection->getSupplementalDriver() instanceof Nette\Database\Drivers\SqliteDriver) {
			$query = $this->connection->query("PRAGMA table_info($table)");
			$primaryKey = 'pk';
			$primaryVal = '1';
			$primaryKeyColumn = 'name';
		} else {
			$query = $this->connection->query("EXPLAIN $table");
			$primaryKey = 3;
			$primaryVal = 'PRI';
			$primaryKeyColumn = 0;
		}

		foreach ($query as $column) {
			if ($column[$primaryKey] === $primaryVal) { // 3 - "Key" is not compatible with PDO::CASE_LOWER
				if ($primary !== NULL) {
					$primary = NULL; // multi-column primary key is not supported
					break;
				}
				$primary = $column[$primaryKeyColumn];
			}
		}

		return $this->structure['primary'][$table] = $primary;
	}



	public function getReferencingColumn($name, $table)
	{
		$name = strtolower($name);
		if (isset($this->structure['referencing'][$table][$name]))
			return $this->structure['referencing'][$table][$name];

		$columns = & $this->structure['referencing'][$table];
		if ($this->connection->getSupplementalDriver() instanceof Nette\Database\Drivers\SqliteDriver) {
			foreach ($this->connection->query("PRAGMA foreign_key_list($name)") as $row) {
				if ($row[2] === $table && $row[4] === $this->getPrimary($table)) {
					$columns[$name] = $row[3];
				}
			}
		} else {
			foreach ($this->connection->query('
				SELECT TABLE_NAME, COLUMN_NAME
				FROM information_schema.KEY_COLUMN_USAGE
				WHERE TABLE_SCHEMA = DATABASE()
				AND REFERENCED_TABLE_SCHEMA = DATABASE()
				AND REFERENCED_TABLE_NAME = ' . $this->connection->quote($table) . '
				AND REFERENCED_COLUMN_NAME = ' . $this->connection->quote($this->getPrimary($table)) //! may not reference primary key
			) as $row) {
				$columns[strtolower($row[0])] = $row[1];
			}
		}

		return $columns[$name];
	}



	public function getReferencedColumn($name, $table)
	{
		return sprintf($this->foreign, $name);
	}



	public function getReferencedTable($name, $table)
	{
		$column = strtolower($this->getReferencedColumn($name, $table));
		if (isset($this->structure['referenced'][$table][$name]))
			return $this->structure['referenced'][$table][$name];

		$tables = & $this->structure['referenced'][$table];

		if ($this->connection->getSupplementalDriver() instanceof Nette\Database\Drivers\SqliteDriver) {
			foreach ($this->connection->query("PRAGMA foreign_key_list($table)") as $row) {
				$tables[strtolower($row[3])] = $row[2];
			}
		} else {
			foreach ($this->connection->query('
				SELECT COLUMN_NAME, REFERENCED_TABLE_NAME
				FROM information_schema.KEY_COLUMN_USAGE
				WHERE TABLE_SCHEMA = DATABASE()
				AND REFERENCED_TABLE_SCHEMA = DATABASE()
				AND TABLE_NAME = ' . $this->connection->quote($table)
			) as $row) {
				$tables[strtolower($row[0])] = $row[1];
			}
		}

		return $tables[$column];
	}

}

ACC SHELL 2018