diff --git a/BasicObject.php b/BasicObject.php index a0ddc01..e5426d6 100644 --- a/BasicObject.php +++ b/BasicObject.php @@ -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. @@ -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']; @@ -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); @@ -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(); } diff --git a/tests/models/ModelExtraFields.php b/tests/models/ModelExtraFields.php new file mode 100644 index 0000000..03bfb08 --- /dev/null +++ b/tests/models/ModelExtraFields.php @@ -0,0 +1,31 @@ +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); + } + } +}; diff --git a/tests/suites/BasicObject/ExtraFieldsTest.php b/tests/suites/BasicObject/ExtraFieldsTest.php new file mode 100644 index 0000000..05810d8 --- /dev/null +++ b/tests/suites/BasicObject/ExtraFieldsTest.php @@ -0,0 +1,37 @@ + 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'); + } +} diff --git a/tests/tests.sh b/tests/tests.sh index 83aeaf0..75db250 100755 --- a/tests/tests.sh +++ b/tests/tests.sh @@ -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" $@