Skip to content
Merged
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
25 changes: 23 additions & 2 deletions BasicObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,17 @@ public static function with_disabled_cache($callback) {
*/
// abstract protected static function table_name();

/**
* Array with names of extra fields supported by this model.
* When using `update_attributes` all fields from this array will be
* set on the instance it present in data. Useful when combied with
* `__set`, e.g. setting `bar` affects `foo` but `bar` isn't present
* in the database table.
*/
protected static function extra_fields(){
return [];
}

/**
* Returns the table name associated with this class.
* @return The name of the table this class is associated with.
Expand Down Expand Up @@ -1125,13 +1136,14 @@ private static function handle_params($params, &$joins, &$wheres, &$order, &$tab
* create: If true new objects can be created if ID is missing or null, otherwise null
* will be returned when the object should've been created.
*/
public static function update_attributes($array, $options=array()) {
public static function update_attributes(array $array, $options=[]) {
$defaults = array(
'empty_to_null' => true,
'commit' => false,
'permit' => false,
'create' => true,
);
$extra_fields = static::extra_fields();
$options = array_merge($defaults, $options);
if ( $options['empty_to_null'] == true || is_array($options['empty_to_null']) ){
$keys = $options['empty_to_null'];
Expand All @@ -1148,7 +1160,9 @@ public static function update_attributes($array, $options=array()) {
/* remove unpermitted keys */
if ( is_array($options['permit']) ){
$permit = array_merge($options['permit'], array('id', static::id_name()));
$array = array_intersect_key($array, array_combine($permit, $permit));
$permit = array_combine($permit, $permit);
$array = array_intersect_key($array, $permit);
$extra_fields = array_intersect($extra_fields, $permit);
}

$obj = new static($array);
Expand Down Expand Up @@ -1176,6 +1190,13 @@ public static function update_attributes($array, $options=array()) {
return null;
}

/* call __set for all extra fields */
foreach ( $extra_fields as $key ){
if ( array_key_exists($key, $array) ){
$obj->$key = $array[$key];
}
}

if(!isset($options["commit"]) || $options["commit"] == true) {
$obj->commit();
}
Expand Down
31 changes: 31 additions & 0 deletions tests/models/ModelExtraFields.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

class ModelExtraFields extends BasicObject {
protected static function table_name() {
return 'model1';
}

protected static function extra_fields() {
return ['int2'];
}

public function __get($key) {
switch ( $key ){
case 'int2':
return $this->int1 - 10;
break;
default:
return parent::__get($key);
}
}

public function __set($key, $value) {
switch ( $key ){
case 'int2':
$this->int1 = $value + 10;
break;
default:
parent::__set($key, $value);
}
}
};
37 changes: 37 additions & 0 deletions tests/suites/BasicObject/ExtraFieldsTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php

class ExtraFieldsTest extends DatabaseTestCase {
public function testSetCalled() {
$data = ['int2' => 5];
$model = ModelExtraFields::update_attributes($data, [
'commit' => false,
]);
$this->assertEquals(15, $model->int1, 'int1 should be set via int2');
}

public function testOrder() {
$data = ['int1' => 4, 'int2' => 5];
$model = ModelExtraFields::update_attributes($data, [
'commit' => false,
]);
$this->assertEquals(15, $model->int1, 'base fields should be set before extra fields');
}

public function testPermitNegative() {
$data = ['int1' => 4, 'int2' => 5];
$model = ModelExtraFields::update_attributes($data, [
'commit' => false,
'permit' => ['int1'],
]);
$this->assertEquals(4, $model->int1, 'int2 should be ignored if not listed in permit');
}

public function testPermitPositive() {
$data = ['int1' => 4, 'int2' => 5];
$model = ModelExtraFields::update_attributes($data, [
'commit' => false,
'permit' => ['int2'],
]);
$this->assertEquals(15, $model->int1, 'int2 should be used when listed in permit');
}
}
13 changes: 9 additions & 4 deletions tests/tests.sh
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
#!/bin/sh

set +e
set -e
cd `dirname $0`

echo -e "Running tests without cache\n"
echo "Running tests without cache"
echo
./phpunit --bootstrap "no_cache.php" --exclude-group cache $@

echo -e "\n----------------------\n"
echo -e "Running tests with cache\n"
echo
echo "----------------------"
echo
echo "Running tests with cache"
echo

./phpunit --bootstrap "with_cache.php" $@