Location: PHPKode > projects > Mocovie web framework > webs/common/controls/dbreader.php
<?php
/**
 *  Copyright (C) 2010  Kai Dorschner
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * @author Kai Dorschner <the-hide@address.com>
 * @copyright Copyright 2010, Kai Dorschner
 * @license http://www.gnu.org/licenses/gpl.html GPLv3
 * @package mocovi
 * @subpackage controls
 */

class dbreader_control extends Control
{
	protected $db;
	protected $fetched;

	protected $defaultOptions = array
		( 'where'				=> ''		// MySQL WHERE clause
		, 'orderby'				=> ''		// MySQL ORDER BY clause
		, 'limit'				=> '30'		// MySQL LIMIT clause
		, 'preserveReferences'	=> 'false'	// Show only results from different tables if references do match! (foreign key constraints)
		);

	/**
	 * @override
	 */
	protected function _beforeCreateNode(DomNode $parent)
	{
		$this->node = $this->parentNode;
		$this->parentNode = $parent->parentNode;
		return false;
	}

	/**
	 * @override
	 */
	protected function _beforeRunChilds()
	{
		if(!$this->connectDatabase())
			return false;
		if($result = $this->db->query($this->createQuery()))
		{
			$all = array();
			while($fetched = $result->fetch_array(MYSQLI_ASSOC))
				$all[] = $fetched;
			if(count($all) > 0)
				foreach($this->find('dbfield') as $child)
					$child->fetched = $all[0];
			$clones = array();
			for($i = 1; $i < count($all); $i++)
				foreach($this->controls as $sub)
				{
					$clones[] = $clone = $sub->getClone()->load($this->node);
					foreach($clone->find('dbfield') as $cloneChild)
						$cloneChild->fetched = $all[$i];
					$clone->run();
				}
			$result->close();
		}
		if(($difference = $this->countAll() - $this->count()) > 0)
			ControlFactory::create(new DomElement('paragraph', 'and '.$difference.' more...'))->load($this->parentNode)->run();
		return true;
	}

	/**
	 * Creates a new MySQL database connection and sets encoding as utf8.
	 *
	 * @access protected
	 * @return $this
	 */
	protected function connectDatabase()
	{
		$this->db = new MySQLi();
		$this->db->connect
			( $GLOBALS['database']['host']
			, $GLOBALS['database']['username']
			, $GLOBALS['database']['password']
			, $this->getOption('use')
			);
		if ($this->db->connect_error)
			$this->error('Connect Error (' . $this->db->connect_errno . ') '.$this->db->connect_error);
		$this->db->query('SET NAMES utf8');
		$this->db->query('SET CHARACTER SET utf8');
		return $this;
	}

	public function countAll()
	{
		$tables = array();
		$fields = array();
		foreach($this->find('dbfield') as $field)
		{
			$val				= explode('.', $field->getOption('name'));
			$tables[$val[0]]	= $val[0];
			$fieldname			= $val[0].'.'.$val[1].' AS '.$val[0].'_'.$val[1];
			$fields[$fieldname]	= $fieldname;
		}
		if(count($tables) > 0)
		{
			if(strtolower($this->getOption('preserveReferences')) == 'true')
				$this->smartWHERE($tables);
			return	$this->db->query(
						 'SELECT COUNT(*) as count'
						.' FROM '.implode(', ', $tables)
						.($this->getOption('where') ? ' WHERE '.$this->getOption('where') : '')
					)
					->fetch_object()
					->count;
		}
		return null;
	}

	public function count()
	{
		$count = (int)$this->countAll();
		$limits = preg_split('/\s*,\s*/', $this->getOption('limit'));
		$limit = (int)$limits[count($limits) - 1];
		return ($count > $limit ? $limit : $count);
	}

	protected function createQuery()
	{
		$tables = array();
		$fields = array();
		foreach($this->find('dbfield') as $field)
		{
			$val				= explode('.', $field->getOption('name'));
			$tables[$val[0]]	= $val[0];
			$fieldname			= $val[0].'.'.$val[1].' AS '.$val[0].'_'.$val[1];
			$fields[$fieldname]	= $fieldname;
		}
		if(count($tables) > 0)
		{
			if(strtolower($this->getOption('preserveReferences')) == 'true')
				$this->smartWHERE($tables);
			return	 'SELECT '.implode(', ', $fields)
					.' FROM '.implode(', ', $tables)
					.($this->getOption('where')		? ' WHERE '.$this->getOption('where') : '')
					.($this->getOption('orderby')	? ' ORDER BY '.$this->getOption('orderby') : '')
					.($this->getOption('limit')		? ' LIMIT '.$this->getOption('limit') : '')
					;
		}
		return null;
	}

	/**
	 * This method enables following and regarding the references.
	 *
	 * Automatically adds "WHERE table1.table2_id = table2.id"
	 *
	 * Attention: Only use with InnoDB!
	 *
	 * @access protected
	 * @return void
	 * @param Array $tables
	 */
	protected function smartWHERE(Array $tables)
	{
		$information_schema = new MySQLi();
		$information_schema->connect
			( $GLOBALS['database']['host']
			, $GLOBALS['database']['username']
			, $GLOBALS['database']['password']
			, 'information_schema'
			);

		$conditions = array();
		foreach($tables as $table)
		{
			$result = $information_schema->query
				('
					SELECT
						  `TABLE_NAME`
						, `COLUMN_NAME`
						, `REFERENCED_TABLE_NAME`
						, `REFERENCED_COLUMN_NAME`
					FROM
						`KEY_COLUMN_USAGE`
					WHERE
						(`TABLE_NAME` = "'.$table.'")
						AND `REFERENCED_TABLE_NAME` IS NOT NULL
						AND `REFERENCED_COLUMN_NAME` IS NOT NULL
				');
			if($result)
				while($o = $result->fetch_object())
					if(in_array($o->REFERENCED_TABLE_NAME, $tables) && in_array($o->TABLE_NAME, $tables))
						$conditions[] = $o;
		}
		$where = array();
		foreach($conditions as $condition)
			$where[] = $condition->TABLE_NAME . '.' . $condition->COLUMN_NAME . ' = ' . $condition->REFERENCED_TABLE_NAME . '.' . $condition->REFERENCED_COLUMN_NAME;
		$this->options['where'] .= (strlen($this->options['where']) > 0 ? ' AND ' : '').implode(' AND ', $where);
		$information_schema->close();
	}
}
Return current item: Mocovie web framework