Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for private columns and filtered objects #124

Open
wants to merge 3 commits into
base: 3.3/develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 132 additions & 4 deletions classes/Kohana/ORM.php
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,18 @@ public static function factory($model, $id = NULL)
*/
protected $_errors_filename = NULL;

/**
* List of private columns that will not appear in array or object
* @var array
*/
protected $_private_columns = FALSE;

/**
* List of behaviors
* @var array
*/
protected $_behaviors = array();

/**
* Constructs a new model and loads a record if given
*
Expand All @@ -253,6 +265,13 @@ public function __construct($id = NULL)
{
$this->_initialize();

// Invoke all behaviors
foreach ($this->_behaviors as $behavior)
{
if ( ! $behavior->on_construct($this, $id) || $this->_loaded)
return;
}

if ($id !== NULL)
{
if (is_array($id))
Expand Down Expand Up @@ -390,6 +409,12 @@ protected function _initialize()

// Clear initial model state
$this->clear();

// Create the behaviors classes
foreach ($this->behaviors() as $behavior => $behavior_config)
{
$this->_behaviors[] = ORM_Behavior::factory($behavior, $behavior_config);
}
}

/**
Expand Down Expand Up @@ -808,20 +833,65 @@ public function values(array $values, array $expected = NULL)
return $this;
}

/**
* Returns the type of the column
*
* @return string
*/
protected function table_column_type($column)
{
if ( ! array_key_exists($column, $this->_table_columns))
return FALSE;

return $this->_table_columns[$column]['type'];
}

/**
* Returns a value as the native type, will return FALSE if the
* value could not be casted.
*
* @return float, int, string or FALSE
*/
protected function get_typed($column)
{
$value = $this->get($column);

switch($this->table_column_type($column))
{
case 'float': return floatval($this->__get($column));
case 'int': return intval($this->__get($column));
case 'string': return strval($this->__get($column));
}

return FALSE;
}

/**
* Returns the values of this object as an array, including any related one-one
* models that have already been loaded using with()
*
* @return array
*/
public function as_array()
public function as_array($show_all=FALSE)
{
$object = array();

foreach ($this->_object as $column => $value)
if ($show_all OR !is_array($this->_private_columns))
{
// Call __get for any user processing
$object[$column] = $this->__get($column);
foreach ($this->_object as $column => $value)
{
// Call __get for any user processing
$object[$column] = $this->__get($column);
}
}
else
{
foreach ($this->_object as $column => $value)
{
// Call __get for any user processing
if (!in_array($column, $this->_private_columns))
$object[$column] = $this->__get($column);
}
}

foreach ($this->_related as $column => $model)
Expand All @@ -833,6 +903,42 @@ public function as_array()
return $object;
}

/**
* Returns the values of this object as an new object, including any related
* one-one models that have already been loaded using with(). Removes private
* columns.
*
* @return array
*/
public function as_object($show_all=FALSE)
{
$object = new stdClass;

if ($show_all OR !is_array($this->_private_columns))
{
foreach ($this->_object as $column => $value)
{
$object->{$column} = $this->get_typed($column);
}
}
else
{
foreach ($this->_object as $column => $value)
{
if (!in_array($column, $this->_private_columns))
$object->{$column} = $this->get_typed($column);
}
}

foreach ($this->_related as $column => $model)
{
// Include any related objects that are already loaded
$object->{$column} = $model->as_object();
}

return $object;
}

/**
* Binds another one-to-one object to this model. One-to-one objects
* can be nested using 'object1:object2' syntax
Expand Down Expand Up @@ -1253,6 +1359,16 @@ public function labels()
return array();
}

/**
* Behavior definition for the model
*
* @return array
*/
public function behaviors()
{
return array();
}

/**
* Validates the current model's data
*
Expand Down Expand Up @@ -1296,6 +1412,12 @@ public function create(Validation $validation = NULL)
if ($this->_loaded)
throw new Kohana_Exception('Cannot create :model model because it is already loaded.', array(':model' => $this->_object_name));

// Invoke all behaviors
foreach ($this->_behaviors as $behavior)
{
$behavior->on_create($this);
}

// Require model validation before saving
if ( ! $this->_valid OR $validation)
{
Expand Down Expand Up @@ -1356,6 +1478,12 @@ public function update(Validation $validation = NULL)
if ( ! $this->_loaded)
throw new Kohana_Exception('Cannot update :model model because it is not loaded.', array(':model' => $this->_object_name));

// Invoke all behaviors
foreach ($this->_behaviors as $behavior)
{
$behavior->on_update($this);
}

// Run validation if the model isn't valid or we have additional validation rules.
if ( ! $this->_valid OR $validation)
{
Expand Down
44 changes: 44 additions & 0 deletions classes/Kohana/ORM/Behavior.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php defined('SYSPATH') OR die('No direct script access.');

class Kohana_ORM_Behavior {

/**
* Database query builder
* @var Database_Query_Builder_Select
*/
protected $_config;

/**
* Creates and returns a new ORM behavior.
*
* @chainable
* @param string $type Type name
* @param mixed $id Parameter for find()
* @return ORM
*/
public static function factory($behavior, $config = NULL)
{
if ( ! is_string($behavior) AND is_array($config))
{
if ( ! is_callable($config))
throw new Kohana_Exception('Behavior cannot be created: function does not exists');

// This is either a callback as an array or a lambda
return new ORM_Behavior_LocalBehavior($config);
}

// Set class name
$behavior_name = 'ORM_Behavior_'.ucfirst($behavior);

return new $behavior_name($config);
}

protected function __construct($config)
{
$this->_config = $config;
}

public function on_construct($model, $id) { return TRUE; }
public function on_create($model) { }
public function on_update($model) { }
}
58 changes: 58 additions & 0 deletions classes/Kohana/ORM/Behavior/LocalBehavior.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php defined('SYSPATH') OR die('No direct script access.');

class Kohana_ORM_Behavior_LocalBehavior extends ORM_Behavior {

/**
* Callback to execute
* @var array
*/
protected $_callback;

/**
* Constructs a behavior object
*
* @param mixed $callback Callback to execute
*/
protected function __construct($callback)
{
$this->_callback = $callback;
}

/**
* Constructs a new model and loads a record if given
*
*@param ORM $model The model
* @param mixed $id Parameter for find or object to load
*/
public function on_construct($model, $id)
{
$params = array('construct', $id);
$result = call_user_func_array($this->_callback, $params);

if (is_bool($result))
return $result;

// Continue loading the record
return TRUE;
}

/**
* The model is updated
*/
public function on_update($model)
{
$params = array('update');
call_user_func_array($this->_callback, $params);
}

/**
* A new model is created
*
* @param ORM $model The model
*/
public function on_create($model)
{
$params = array('create');
call_user_func_array($this->_callback, $params);
}
}
3 changes: 3 additions & 0 deletions classes/ORM/Behavior.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<?php defined('SYSPATH') OR die('No direct script access.');

class ORM_Behavior extends Kohana_ORM_Behavior {}
Loading