Skip to content
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
26 changes: 25 additions & 1 deletion lib/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,30 @@ public function __set($name, $value)
return $this->$item['to']->$delegated_name = $value;
}

$table = static::table();
if ($relationship = $table->get_relationship($name)
)
{
if (is_null($value))
{
$this->__relationships[$name] = $value;
return $this->assign_attribute($relationship->foreign_key[0], $value);
}
elseif (($value instanceof \ActiveRecord\Model) &&
$value instanceof $relationship->class_name)
{
$this->__relationships[$name] = $value;
$pk = $value->get_primary_key(0);
return $this->assign_attribute(
$relationship->foreign_key[0],
$value->is_new_record() ? null : $value->{$pk[0]}
);
}
else
{
throw new RelationshipException();
}
}
throw new UndefinedPropertyException(get_called_class(),$name);
}

Expand Down Expand Up @@ -837,7 +861,7 @@ public static function table()
* @param boolean $guard_attributes Set to true to guard protected/non-accessible attributes
* @return Model
*/
public static function create($attributes, $validate=true, $guard_attributes=true)
public static function create(array $attributes=array(), $validate=true, $guard_attributes=true)
{
$class_name = get_called_class();
$model = new $class_name($attributes, $guard_attributes);
Expand Down
34 changes: 23 additions & 11 deletions lib/Relationship.php
Original file line number Diff line number Diff line change
Expand Up @@ -184,24 +184,36 @@ protected function query_and_attach_related_models_eagerly(Table $table, $models
$model_values_key = $inflector->variablize($model_values_key);
$query_key = $inflector->variablize($query_key);

$all_related_with_value = null;
foreach ($models as $model)
{
if(!isset($all_related_with_value))
{
$all_related_with_value = array();
foreach ($related_models as $related)
{
$all_related_with_value[$related->$query_key][] = $related;
}
}
$matches = 0;
$key_to_match = $model->$model_values_key;

foreach ($related_models as $related)
if(array_key_exists($key_to_match,$all_related_with_value))
{
if ($related->$query_key == $key_to_match)
foreach ($all_related_with_value[$key_to_match] as $related)
{
$hash = spl_object_hash($related);

if (in_array($hash, $used_models))
$model->set_relationship_from_eager_load(clone($related), $this->attribute_name);
else
$model->set_relationship_from_eager_load($related, $this->attribute_name);

$used_models[] = $hash;
$matches++;
if ($related->$query_key == $key_to_match)
{
$hash = spl_object_hash($related);

if (array_key_exists($hash, $used_models))
$model->set_relationship_from_eager_load(clone($related), $this->attribute_name);
else
$model->set_relationship_from_eager_load($related, $this->attribute_name);

$used_models[$hash] = null;
$matches++;
}
}
}

Expand Down
16 changes: 9 additions & 7 deletions lib/Utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,15 @@ function array_flatten(array $array)
/**
* Somewhat naive way to determine if an array is a hash.
*/
function is_hash(&$array)
function is_hash($array)
{
if (!is_array($array))
if (!is_array($array)) {
return false;
}

$keys = array_keys($array);
return @is_string($keys[0]) ? true : false;

return isset($keys[0]) && is_string($keys[0]);
}

/**
Expand Down Expand Up @@ -173,20 +175,20 @@ public static function extract_options($options)
return is_array(end($options)) ? end($options) : array();
}

public static function add_condition(&$conditions=array(), $condition, $conjuction='AND')
public static function add_condition(&$conditions=array(), $condition, $conjunction='AND')
{
if (is_array($condition))
{
if (empty($conditions))
$conditions = array_flatten($condition);
else
{
$conditions[0] .= " $conjuction " . array_shift($condition);
$conditions[0] = "({$conditions[0]}) $conjunction (" . array_shift($condition) . ")";
$conditions[] = array_flatten($condition);
}
}
elseif (is_string($condition))
$conditions[0] .= " $conjuction $condition";
$conditions[0] = "({$conditions[0]}) {$conjunction} ($condition)";

return $conditions;
}
Expand Down Expand Up @@ -367,4 +369,4 @@ public static function add_irregular($singular, $plural)
{
self::$irregular[$singular] = $plural;
}
}
}
62 changes: 61 additions & 1 deletion test/RelationshipTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,7 @@ public function test_gh93_and_gh100_eager_loading_respects_association_options()
Venue::$has_many = array(array('events', 'class_name' => 'Event', 'order' => 'id asc', 'conditions' => array('length(title) = ?', 14)));
$venues = Venue::find(array(2, 6), array('include' => 'events'));

$this->assert_sql_has("WHERE length(title) = ? AND venue_id IN(?,?) ORDER BY id asc",ActiveRecord\Table::load('Event')->last_sql);
$this->assert_sql_has("WHERE (length(title) = ?) AND (venue_id IN(?,?)) ORDER BY id asc",ActiveRecord\Table::load('Event')->last_sql);
$this->assert_equals(1, count($venues[0]->events));
}

Expand Down Expand Up @@ -732,4 +732,64 @@ public function test_dont_attempt_eager_load_when_record_does_not_exist()
{
Author::find(999999, array('include' => array('books')));
}

public function test_gh_125_auto_setter_for_relation()
{
$event = new Event(array(
'venue' => new Venue()
));

$this->assert_not_null($event->venue);
$this->assert_null($event->venue_id);
}

public function test_gh_125_auto_setter_for_relation_with_id()
{
$event = new Event(array(
'venue' => Venue::create()
));

$this->assert_not_null($event->venue);
$this->assert_not_null($event->venue_id);
$event->venue->delete();
}

/**
* @expectedException ActiveRecord\RelationshipException
*/
public function test_gh_125_auto_setter_for_relation_raises_exception()
{
$event = new Event(array(
'venue' => new Book()
));
}

public function test_gh_125_auto_setter_for_relation_using_subclass()
{
$event = new Event(array(
'venue' => new SubVenue()
));

$this->assert_not_null($event->venue);
$this->assert_null($event->venue_id);
}

public function test_gh_125_unset_existing_relation()
{
$event = new Event(array(
'venue' => Venue::create()
));

$event->venue->delete();
$event->venue = null;
$this->assert_null($event->venue);
$this->assert_null($event->venue_id);
}

public function test_gh_125_add_model_to_has_many_relation()
{
$venue = Venue::find('first');
$venue->events = null;
// $venue->events = array(new Event());
}
}
16 changes: 15 additions & 1 deletion test/UtilsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,5 +103,19 @@ public function test_wrap_strings_in_arrays()
$x = '1';
$this->assert_equals(array(array('1')),ActiveRecord\wrap_strings_in_arrays($x));
}
}

public function test_is_hash()
{
$hash = array('key' => 'value');
$this->assert_true(ActiveRecord\is_hash($hash));

$notHash = array(0 => 'value');
$this->assert_false(ActiveRecord\is_hash($notHash));
}

public function test_is_hash_empty_array()
{
$notHash = array();
$this->assert_false(ActiveRecord\is_hash($notHash));
}
};
6 changes: 6 additions & 0 deletions test/models/SubVenue.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?php
class SubVenue extends Venue
{
static $table_name = 'venues';
}
?>
2 changes: 1 addition & 1 deletion test/models/Venue.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class Venue extends ActiveRecord\Model


static $has_many = array(
'events',
array('events'),
array('hosts', 'through' => 'events')
);

Expand Down