<commit_before><?php defined('SYSPATH') or die('No direct script access.');

/**
 * Jelly_Builder is a class used for query building. It handles
 * automatic aliasing of all models and columns (but also supports
 * unknown models and fields).
 *
 * Because of the limitations of PHP and Kohana's class structure,
 * it must extend a Database_Query_Builder_Select. However, the
 * instance is properly transposed into its actual type when compiled
 * or executed.
 *
 * It is possible to use un-executed() query builder instances in other
 * query builder statements, just as you would with Kohana's native
 * facilities.
 *
 * @package  Jelly
 */
abstract class Jelly_Core_Builder extends Kohana_Database_Query_Builder_Select
{
	/**
	 * @var  string  The inital model used to construct the builder
	 */
	protected $_model = NULL;

	/**
	 * @var  Jelly_Meta  The meta object (if found) that is attached to this builder
	 */
	protected $_meta = NULL;

	/**
	 * @var  array  Data to be UPDATEd
	 */
	protected $_set = array();

	/**
	 * @var  array  Columns to be INSERTed
	 */
	protected $_columns = array();

	/**
	 * @var  array  Values to be INSERTed
	 */
	protected $_values = array();
	
	/**
	 * @var  boolean  The result, if the query has been executed
	 */
	protected $_result = NULL;
	
	/**
	 * @var  boolean  The type of the query, if provided
	 */
	protected $_type = NULL;
	
	/**
	 * @var  array  Alias cache
	 */
	protected $_model_cache = array();
	
	/**
	 * @var  array  Alias cache
	 */
	protected $_alias_cache = array();

	/**
	 * Constructs a new Jelly_Builder instance.
	 *
	 * $model is not actually allowed to be NULL. It has
	 * a default because PHP throws strict errors otherwise.
	 *
	 * @param string $model
	 */
	public function __construct($model = NULL, $key = NULL)
	{
		parent::__construct();

		if ( ! $model)
		{
			throw new Kohana_Exception(get_class($this) . ' requires $model to be set in the constructor');
		}

		// Set the model and the initial from()
		$this->_model = Jelly::model_name($model);
		$this->_meta  = Jelly::meta($this->_model);
		$this->_initialize();
		
		// Default to using our key
		if ($key !== NULL)
		{
			$this->key($key);
		}
	}

	/**
	 * Passes unknown methods along to the behaviors.
	 *
	 * @param   string  $method
	 * @param   array   $args
	 * @return  mixed
	 **/
	public function __call($method, $args)
	{
		if ($this->_meta)
		{
			return $this->_meta->events()->trigger('builder.call_'.$method, $this, $args);
		}
		
		throw new Kohana_Exception('Invalid method :method called on class :class',
			array(':method' => $method, ':class' => get_class($this)));
	}

	/**
	 * Executes the query as a SELECT statement
	 *
	 * @param   string  $db 
	 * @return  Jelly_Collection | Jelly_Model
	 */
	public function select($db = NULL)
	{
		$db   = $this->_db($db);
		$meta = $this->_meta;
		
		if ($meta)
		{
			// Select all of the columns for the model if we haven't already
			empty($this->_select) AND $this->select_column('*');
			
			// Trigger before_select callback
			$meta->events()->trigger('builder.before_select', $this);
		}
		
		// Ready to leave the builder, we need to figure out what type to return
		$this->_result = $this->_build(Database::SELECT);
		
		// Return an actual array
		if ($this->_as_object === FALSE OR Jelly::meta($this->_as_object))
		{
			$this->_result->as_assoc();
		}
		else
		{
			$this->_result->as_object($this->_as_object);
		}
		
		// Pass off to Jelly_Collection, which manages the result
		$this->_result = new Jelly_Collection($this->_result->execute($db), $this->_as_object);
		
		// Trigger after_query callbacks
		if ($meta)
		{
			$meta->events()->trigger('builder.after_select', $this);
		}

		// If the record was limited to 1, we only return that model
		// Otherwise we return the whole result set.
		if ($this->_limit === 1)
		{
			$this->_result = $this->_result->current();
		}
		
		return $this->_result;
	}
	
	/**
	 * Executes the query as an INSERT statement
	 *
	 * @param   string  $db 
	 * @return  array
	 */
	public function insert($db = NULL)
	{
		$db   = $this->_db($db);
		$meta = $this->_meta;
		
		// Trigger callbacks
		$meta AND $meta->events()->trigger('builder.before_insert', $this);
		
		// Ready to leave the builder
		$result = $this->_build(Database::INSERT)->execute($db);
		
		// Trigger after_query callbacks
		$meta AND $meta->events()->trigger('builder.after_insert', $this);
		
		return $result;
	}
	
	/**
	 * Executes the query as an UPDATE statement
	 *
	 * @param   string  $db 
	 * @return  int
	 */
	public function update($db = NULL)
	{
		$db   = $this->_db($db);
		$meta = $this->_meta;
		
		// Trigger callbacks
		$meta AND $meta->events()->trigger('builder.before_update', $this);
		
		// Ready to leave the builder
		$result = $this->_build(Database::UPDATE)->execute($db);
		
		// Trigger after_query callbacks
		$meta AND $meta->events()->trigger('builder.after_update', $this);
			
		return $result;
	}
	
	/**
	 * Executes the query as a DELETE statement
	 *
	 * @param   string  $db 
	 * @return  int
	 */
	public function delete($db = NULL)
	{
		$db     = $this->_db($db);
		$meta   = $this->_meta;
		$result = NULL;
		
		// Trigger callbacks
		if ($meta)
		{
			// Listen for a result to see if we need to actually delete the record
			$result = $meta->events()->trigger('builder.before_delete', $this);
		}
		
		if ($result === NULL)
		{
			$result = $this->_build(Database::DELETE)->execute($db);
		}
		
		// Trigger after_query callbacks
		if ($meta)
		{
			// Allow the events to modify the result
			$result = $meta->events()->trigger('builder.after_delete', $this);
		}
		
		return $result;
	}
	
	/**
	 * Counts the current query builder
	 *
	 * @param   string  $db 
	 * @return  int
	 */
	public function count($db = NULL)
	{
		$db   = $this->_db($db);
		$meta = $this->_meta;
		
		// Trigger callbacks
		$meta AND $meta->events()->trigger('builder.before_select', $this);
		
		// Start with a basic SELECT
		$query = $this->_build(Database::SELECT)->as_object(FALSE);
		
		// Dump a few unecessary bits that cause problems
		$query->_select = $query->_order_by = array();

		// Find the count
		$result = (int) $query
		               ->select(array('COUNT("*")', 'total'))
		               ->execute($db)
		               ->get('total');
		
		// Trigger after_query callbacks
		$meta AND $meta->events()->trigger('builder.after_select', $this);
		
		return $result;
	}

	/**
	 * Builds the builder into a native query
	 *
	 * @param   string  $type
	 * @return  void
	 */
	public function execute($db = NULL, $type = NULL)
	{
		$type === NULL AND $type = $this->_type;
		
		switch ($type)
		{
			case Database::SELECT:
				return $this->select($db);
			case Database::INSERT:
				return $this->insert($db);
			case Database::UPDATE:
				return $this->update($db);
			case Database::DELETE:
				return $this->delete($db);
		}
	}

	/**
	 * Compiles the builder into a usable expression
	 *
	 * @param   Database $db
	 * @return  Database_Query
	 */
	public function compile(Database $db, $type = NULL)
	{
		$type === NULL AND $type = $this->_type;
		
		// Select all of the columns for the model if we haven't already
		$this->_meta AND empty($this->_select) AND $this->select_column('*');
		
		return $this->_build($type)->compile($db);
	}
	
	/**
	 * Selects for a specific key and limits the selection to 1 so that
	 * a single model is returned.
	 *
	 * @param   mixed  $key 
	 * @return  $this
	 */
	public function key($key)
	{
		return $this->where($this->_model.'.'.$this->unique_key($key), '=', $key)->limit(1);
	}
	
	/**
	 * Allows setting the type for dynamic execution
	 *
	 * @param   int  $type 
	 * @return  mixed
	 */
	public function type($type = NULL)
	{
		if ($type !== NULL)
		{
			$this->_type = $type;
			return $this;
		}
		
		return $this->_type;
	}
	
	/**
	 * Returns results as objects
	 *
	 * @param   string  classname or TRUE for stdClass
	 * @return  $this
	 */
	public function as_object($class = TRUE, $params = array())
	{
		// Class is TRUE, default to the model
		if ($class === TRUE AND $this->_meta)
		{
			$class = Jelly::class_name($this->_meta->model());
		}
		
		return parent::as_object($class);
	}
	
	/**
	 * Returns the unique key for a specific value. This method is expected
	 * to be overloaded in builders if the table has other unique columns.
	 *
	 * @param  mixed  $value
	 * @return string
	 */
	public function unique_key($value)
	{
		return $this->_meta->primary_key();
	}
	
	/**
	 * Returns the meta object attached to this builder 
	 * or NULL if nothing is attached.
	 * 
	 * @return  Jelly_Meta
	 */<commit_msg>Fixing strict errors with latest database<commit_after><?php defined('SYSPATH') or die('No direct script access.');

/**
 * Jelly_Builder is a class used for query building. It handles
 * automatic aliasing of all models and columns (but also supports
 * unknown models and fields).
 *
 * Because of the limitations of PHP and Kohana's class structure,
 * it must extend a Database_Query_Builder_Select. However, the
 * instance is properly transposed into its actual type when compiled
 * or executed.
 *
 * It is possible to use un-executed() query builder instances in other
 * query builder statements, just as you would with Kohana's native
 * facilities.
 *
 * @package  Jelly
 */
abstract class Jelly_Core_Builder extends Kohana_Database_Query_Builder_Select
{
	/**
	 * @var  string  The inital model used to construct the builder
	 */
	protected $_model = NULL;

	/**
	 * @var  Jelly_Meta  The meta object (if found) that is attached to this builder
	 */
	protected $_meta = NULL;

	/**
	 * @var  array  Data to be UPDATEd
	 */
	protected $_set = array();

	/**
	 * @var  array  Columns to be INSERTed
	 */
	protected $_columns = array();

	/**
	 * @var  array  Values to be INSERTed
	 */
	protected $_values = array();
	
	/**
	 * @var  boolean  The result, if the query has been executed
	 */
	protected $_result = NULL;
	
	/**
	 * @var  boolean  The type of the query, if provided
	 */
	protected $_type = NULL;
	
	/**
	 * @var  array  Alias cache
	 */
	protected $_model_cache = array();
	
	/**
	 * @var  array  Alias cache
	 */
	protected $_alias_cache = array();

	/**
	 * Constructs a new Jelly_Builder instance.
	 *
	 * $model is not actually allowed to be NULL. It has
	 * a default because PHP throws strict errors otherwise.
	 *
	 * @param string $model
	 */
	public function __construct($model = NULL, $key = NULL)
	{
		parent::__construct();

		if ( ! $model)
		{
			throw new Kohana_Exception(get_class($this) . ' requires $model to be set in the constructor');
		}

		// Set the model and the initial from()
		$this->_model = Jelly::model_name($model);
		$this->_meta  = Jelly::meta($this->_model);
		$this->_initialize();
		
		// Default to using our key
		if ($key !== NULL)
		{
			$this->key($key);
		}
	}

	/**
	 * Passes unknown methods along to the behaviors.
	 *
	 * @param   string  $method
	 * @param   array   $args
	 * @return  mixed
	 **/
	public function __call($method, $args)
	{
		if ($this->_meta)
		{
			return $this->_meta->events()->trigger('builder.call_'.$method, $this, $args);
		}
		
		throw new Kohana_Exception('Invalid method :method called on class :class',
			array(':method' => $method, ':class' => get_class($this)));
	}

	/**
	 * Executes the query as a SELECT statement
	 *
	 * @param   string  $db 
	 * @return  Jelly_Collection | Jelly_Model
	 */
	public function select($db = NULL)
	{
		$db   = $this->_db($db);
		$meta = $this->_meta;
		
		if ($meta)
		{
			// Select all of the columns for the model if we haven't already
			empty($this->_select) AND $this->select_column('*');
			
			// Trigger before_select callback
			$meta->events()->trigger('builder.before_select', $this);
		}
		
		// Ready to leave the builder, we need to figure out what type to return
		$this->_result = $this->_build(Database::SELECT);
		
		// Return an actual array
		if ($this->_as_object === FALSE OR Jelly::meta($this->_as_object))
		{
			$this->_result->as_assoc();
		}
		else
		{
			$this->_result->as_object($this->_as_object);
		}
		
		// Pass off to Jelly_Collection, which manages the result
		$this->_result = new Jelly_Collection($this->_result->execute($db), $this->_as_object);
		
		// Trigger after_query callbacks
		if ($meta)
		{
			$meta->events()->trigger('builder.after_select', $this);
		}

		// If the record was limited to 1, we only return that model
		// Otherwise we return the whole result set.
		if ($this->_limit === 1)
		{
			$this->_result = $this->_result->current();
		}
		
		return $this->_result;
	}
	
	/**
	 * Executes the query as an INSERT statement
	 *
	 * @param   string  $db 
	 * @return  array
	 */
	public function insert($db = NULL)
	{
		$db   = $this->_db($db);
		$meta = $this->_meta;
		
		// Trigger callbacks
		$meta AND $meta->events()->trigger('builder.before_insert', $this);
		
		// Ready to leave the builder
		$result = $this->_build(Database::INSERT)->execute($db);
		
		// Trigger after_query callbacks
		$meta AND $meta->events()->trigger('builder.after_insert', $this);
		
		return $result;
	}
	
	/**
	 * Executes the query as an UPDATE statement
	 *
	 * @param   string  $db 
	 * @return  int
	 */
	public function update($db = NULL)
	{
		$db   = $this->_db($db);
		$meta = $this->_meta;
		
		// Trigger callbacks
		$meta AND $meta->events()->trigger('builder.before_update', $this);
		
		// Ready to leave the builder
		$result = $this->_build(Database::UPDATE)->execute($db);
		
		// Trigger after_query callbacks
		$meta AND $meta->events()->trigger('builder.after_update', $this);
			
		return $result;
	}
	
	/**
	 * Executes the query as a DELETE statement
	 *
	 * @param   string  $db 
	 * @return  int
	 */
	public function delete($db = NULL)
	{
		$db     = $this->_db($db);
		$meta   = $this->_meta;
		$result = NULL;
		
		// Trigger callbacks
		if ($meta)
		{
			// Listen for a result to see if we need to actually delete the record
			$result = $meta->events()->trigger('builder.before_delete', $this);
		}
		
		if ($result === NULL)
		{
			$result = $this->_build(Database::DELETE)->execute($db);
		}
		
		// Trigger after_query callbacks
		if ($meta)
		{
			// Allow the events to modify the result
			$result = $meta->events()->trigger('builder.after_delete', $this);
		}
		
		return $result;
	}
	
	/**
	 * Counts the current query builder
	 *
	 * @param   string  $db 
	 * @return  int
	 */
	public function count($db = NULL)
	{
		$db   = $this->_db($db);
		$meta = $this->_meta;
		
		// Trigger callbacks
		$meta AND $meta->events()->trigger('builder.before_select', $this);
		
		// Start with a basic SELECT
		$query = $this->_build(Database::SELECT)->as_object(FALSE);
		
		// Dump a few unecessary bits that cause problems
		$query->_select = $query->_order_by = array();

		// Find the count
		$result = (int) $query
		               ->select(array('COUNT("*")', 'total'))
		               ->execute($db)
		               ->get('total');
		
		// Trigger after_query callbacks
		$meta AND $meta->events()->trigger('builder.after_select', $this);
		
		return $result;
	}

	/**
	 * Builds the builder into a native query
	 *
	 * @param   string  $type
	 * @return  void
	 */
	public function execute($db = NULL, $type = NULL)
	{
		$type === NULL AND $type = $this->_type;
		
		switch ($type)
		{
			case Database::SELECT:
				return $this->select($db);
			case Database::INSERT:
				return $this->insert($db);
			case Database::UPDATE:
				return $this->update($db);
			case Database::DELETE:
				return $this->delete($db);
		}
	}

	/**
	 * Compiles the builder into a usable expression
	 *
	 * @param   Database $db
	 * @return  Database_Query
	 */
	public function compile(Database $db, $type = NULL)
	{
		$type === NULL AND $type = $this->_type;
		
		// Select all of the columns for the model if we haven't already
		$this->_meta AND empty($this->_select) AND $this->select_column('*');
		
		return $this->_build($type)->compile($db);
	}
	
	/**
	 * Selects for a specific key and limits the selection to 1 so that
	 * a single model is returned.
	 *
	 * @param   mixed  $key 
	 * @return  $this
	 */
	public function key($key)
	{
		return $this->where($this->_model.'.'.$this->unique_key($key), '=', $key)->limit(1);
	}
	
	/**
	 * Allows setting the type for dynamic execution
	 *
	 * @param   int  $type 
	 * @return  mixed
	 */
	public function type($type = NULL)
	{
		if ($type !== NULL)
		{
			$this->_type = $type;
			return $this;
		}
		
		return $this->_type;
	}
	
	/**
	 * Returns results as objects
	 *
	 * @param   string  classname or TRUE for stdClass
	 * @return  $this
	 */
	public function as_object($class = TRUE, array $params = NULL)
	{
		// Class is TRUE, default to the model
		if ($class === TRUE AND $this->_meta)
		{
			$class = Jelly::class_name($this->_meta->model());
		}
		
		return parent::as_object($class);
	}
	
	/**
	 * Returns the unique key for a specific value. This method is expected
	 * to be overloaded in builders if the table has other unique columns.
	 *
	 * @param  mixed  $value
	 * @return string
	 */
	public function unique_key($value)
	{
		return $this->_meta->primary_key();
	}
	
	/**
	 * Returns the meta object attached to this builder 
	 * or NULL if nothing is attached.
	 * 
	 * @return  Jelly_Meta
	 */
{'fraction_non_alphanumeric': 0.1474851302188601, 'fraction_numerical': 0.00046197378298781544, 'mean_word_length': 2.933227344992051, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 195, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6061900', 'n_tokens_mistral': 6202, 'n_tokens_neox': 5325, 'n_words': 1680}