aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/classes/restapi/consumer/OAuth.php12
-rw-r--r--lib/models/CourseDate.class.php8
-rw-r--r--lib/models/FileRef.php2
-rw-r--r--lib/models/ModuleManagementModel.php30
-rw-r--r--lib/models/Semester.class.php4
-rw-r--r--lib/models/SimpleORMap.class.php521
-rw-r--r--lib/models/StudiengangStgteil.php6
-rw-r--r--lib/models/User.class.php25
-rw-r--r--tests/unit/lib/classes/SimpleOrMapNodbTest.php16
9 files changed, 321 insertions, 303 deletions
diff --git a/lib/classes/restapi/consumer/OAuth.php b/lib/classes/restapi/consumer/OAuth.php
index daed763..f5d87ec 100644
--- a/lib/classes/restapi/consumer/OAuth.php
+++ b/lib/classes/restapi/consumer/OAuth.php
@@ -24,6 +24,8 @@ class OAuth extends Base
{
$config['default_values']['consumer_type'] = 'oauth';
+ $config['registered_callbacks']['before_store'][] = 'before_store';
+
parent::configure($config);
}
@@ -107,16 +109,6 @@ class OAuth extends Base
}
/**
- * SimpleORMap constructor, registers neccessary callbacks.
- */
- public function __construct($id = null)
- {
- parent::__construct($id);
-
- $this->registerCallback('before_store', 'before_store');
- }
-
- /**
* "Before store" trigger. Creates a clone of the consumer in the
* tables for the vendor oauth library.
*/
diff --git a/lib/models/CourseDate.class.php b/lib/models/CourseDate.class.php
index e98308d..5d8c60d 100644
--- a/lib/models/CourseDate.class.php
+++ b/lib/models/CourseDate.class.php
@@ -106,6 +106,8 @@ class CourseDate extends SimpleORMap implements PrivacyObject
'on_delete' => 'delete',
];
$config['default_values']['date_typ'] = 1;
+ $config['registered_callbacks']['before_store'][] = 'cbStudipLog';
+ $config['registered_callbacks']['after_create'][] = 'cbStudipLog';
parent::configure($config);
}
@@ -185,12 +187,6 @@ class CourseDate extends SimpleORMap implements PrivacyObject
);
}
- public function __construct($id = null)
- {
- parent::__construct($id);
- $this->registerCallback('before_store after_create', 'cbStudipLog');
- }
-
/**
* Adds a topic to this date.
*
diff --git a/lib/models/FileRef.php b/lib/models/FileRef.php
index afdc541..48c64dc 100644
--- a/lib/models/FileRef.php
+++ b/lib/models/FileRef.php
@@ -199,7 +199,7 @@ class FileRef extends SimpleORMap implements PrivacyObject, FeedbackRange
$this->downloads += 1;
if (!$this->isNew()) {
$where_query = join(' AND ' , $this->getWhereQuery());
- $query = "UPDATE `{$this->db_table}`
+ $query = "UPDATE `{$this->db_table()}`
SET `downloads` = `downloads` + 1
WHERE {$where_query}";
return DBManager::get()->exec($query);
diff --git a/lib/models/ModuleManagementModel.php b/lib/models/ModuleManagementModel.php
index 39b7d75..d6b3eab 100644
--- a/lib/models/ModuleManagementModel.php
+++ b/lib/models/ModuleManagementModel.php
@@ -170,10 +170,10 @@ abstract class ModuleManagementModel extends SimpleORMap implements ModuleManage
// check the permissions for every single db field except primary keys
if ($this->isNew()) {
- $fields = array_diff(array_keys($this->db_fields),
- array_values($this->pk));
+ $fields = array_diff(array_keys($this->db_fields()),
+ array_values($this->pk()));
} else {
- $fields = array_keys($this->db_fields);
+ $fields = array_keys($this->db_fields());
}
foreach ($fields as $field) {
if ($this->isFieldDirty($field)
@@ -307,7 +307,7 @@ abstract class ModuleManagementModel extends SimpleORMap implements ModuleManage
*/
protected function logChanges ($action = null) {
- switch ($this->db_table) {
+ switch ($this->db_table()) {
case 'abschluss' :
$logging = 'MVV_ABSCHLUSS';
$num_index = 1;
@@ -467,11 +467,11 @@ abstract class ModuleManagementModel extends SimpleORMap implements ModuleManage
}
if ($this->isFieldDirty($name)) {
$info = ($num_index == 3) ? $debuginfo.';'.$value : $value;
- StudipLog::log($logging, $aff, $coaff, $this->db_table.'.'.$name, $info);
+ StudipLog::log($logging, $aff, $coaff, $this->db_table().'.'.$name, $info);
}
}
} else {
- StudipLog::log($logging, $aff, $coaff, $this->db_table, $debuginfo);
+ StudipLog::log($logging, $aff, $coaff, $this->db_table(), $debuginfo);
}
return true;
@@ -519,12 +519,12 @@ abstract class ModuleManagementModel extends SimpleORMap implements ModuleManage
$model_object = new static();
foreach ($stmt->fetchAll(PDO::FETCH_ASSOC) as $data) {
$pkey = [];
- foreach ($model_object->pk as $pk) {
- $pkey[]= $data[$model_object->db_fields[$pk]['name']];
+ foreach (static::pk() as $pk) {
+ $pkey[]= $data[static::db_fields()[$pk]['name']];
}
$data_object = clone $model_object;
foreach ($data as $key => $value) {
- if (isset($data_object->db_fields[$key])) {
+ if (isset($data_object->db_fields()[$key])) {
$data_object->setValue($key, $value);
} else {
$data_object->content[mb_strtolower($key)] = $value;
@@ -661,9 +661,8 @@ abstract class ModuleManagementModel extends SimpleORMap implements ModuleManage
if (!is_array($sort)) {
$sort = explode(',', $sort);
}
- $sorm = new static();
if (sizeof(array_intersect(
- array_merge(array_keys($sorm->db_fields), $additional_fields),
+ array_merge(array_keys(static::db_fields()), $additional_fields),
$sort))) {
return implode(',', $sort);
}
@@ -687,12 +686,10 @@ abstract class ModuleManagementModel extends SimpleORMap implements ModuleManage
$sort = explode(',', $sort);
}
$sort = array_map('trim', $sort);
- $sorm_name = static::class;
- $sorm = new $sorm_name();
$allowed_fields = array_intersect(
$sort,
array_merge(
- array_keys($sorm->db_fields),
+ array_keys(static::db_fields()),
$additional_fields
)
);
@@ -731,9 +728,8 @@ abstract class ModuleManagementModel extends SimpleORMap implements ModuleManage
} else {
$filter_sql = '';
}
- $sorm = new static();
$db = DBManager::get()->query('SELECT COUNT(*) FROM '
- . $sorm->db_table . $filter_sql);
+ . static::db_table() . $filter_sql);
return $db->fetchColumn(0);
}
@@ -795,7 +791,7 @@ abstract class ModuleManagementModel extends SimpleORMap implements ModuleManage
$stmt = DBManager::get()->prepare('SELECT DISTINCT `lang` '
. 'FROM i18n '
. 'WHERE `object_id` = ? AND `table` = ?');
- $stmt->execute([$this->id, $this->db_table]);
+ $stmt->execute([$this->id, $this->db_table()]);
foreach ($stmt->fetchAll() as $locale) {
$language = mb_strtoupper(mb_strstr($locale['lang'], '_', true));
if (is_array($GLOBALS['MVV_LANGUAGES']['values'][$language])) {
diff --git a/lib/models/Semester.class.php b/lib/models/Semester.class.php
index 84d90ab..94a6605 100644
--- a/lib/models/Semester.class.php
+++ b/lib/models/Semester.class.php
@@ -461,7 +461,7 @@ class Semester extends SimpleORMap
public function toArray($only_these_fields = null)
{
if (!isset($only_these_fields)) {
- $fields = array_flip(array_diff($this->known_slots, array_keys($this->relations)));
+ $fields = array_flip(array_diff($this->known_slots(), array_keys($this->relations)));
unset($fields['absolute_seminars_count']);
unset($fields['duration_seminars_count']);
unset($fields['continuous_seminars_count']);
@@ -505,7 +505,7 @@ class Semester extends SimpleORMap
continue;
}
- if (in_array('sem_wechsel', $semester->known_slots) && $semester['sem_wechsel']) {
+ if ($semester['sem_wechsel']) {
$timestamp = $semester['sem_wechsel'];
} else {
$timestamp = $semester['beginn'] - (int)Config::get()->SEMESTER_TIME_SWITCH * 7 * 24 * 60 * 60;
diff --git a/lib/models/SimpleORMap.class.php b/lib/models/SimpleORMap.class.php
index 476e646..4bce0cf 100644
--- a/lib/models/SimpleORMap.class.php
+++ b/lib/models/SimpleORMap.class.php
@@ -26,161 +26,217 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
* @var array $content
*/
protected $content = [];
+
/**
* table row data
* @var array $content_db
*/
protected $content_db = [];
+
/**
* new state of entry
* @var boolean $is_new
*/
protected $is_new = true;
+
/**
* deleted state of entry
* @var boolean $is_deleted
*/
protected $is_deleted = false;
+
+ /**
+ * db table metadata
+ * @var ?array $schemes;
+ */
+ public static $schemes = null;
+
/**
- * name of db table
- * @var string $db_table
+ * configuration data for subclasses
+ * @see self::configure()
+ * @var array $config;
*/
- protected $db_table = '';
+ protected static $config = [];
+
/**
- * table columns
- * @var array $db_fields
+ * stores instantiated related objects
+ * @var array $relations
*/
- protected $db_fields = null;
+ protected $relations = [];
+
/**
- * primary key columns
- * @var array $pk
+ * assoc array for storing values for additional fields
+ *
+ * @var array $additional_data
*/
- protected $pk = null;
+ protected $additional_data = [];
/**
- * default values for columns
- * @var array $default_values
+ * reserved indentifiers, fields with those names must not have an explicit getXXX() method
+ * @var array $reserved_slots
*/
- protected $default_values = [];
+ protected static $reserved_slots = ['value','newid','iterator','tablemetadata', 'relationvalue','wherequery','relationoptions','data','new','id'];
/**
- * list of columns to deserialize
- * @var array key is name of column, value is name of ArrayObject class
+ * indicator for batch operations in findEachBySQL
+ *
+ * @var bool $performs_batch_operation
*/
- protected $serialized_fields = [];
+ protected static $performs_batch_operation = false;
- /**
- * db table metadata
- * @var ?array $schemes;
+ /**
+ * name of db table
+ * @return string
*/
- public static $schemes = null;
+ protected static function db_table()
+ {
+ return static::config('db_table');
+ }
/**
- * configuration data for subclasses
- * @see self::configure()
- * @var array $config;
+ * table columns
+ * @return array
*/
- protected static $config = [];
+ protected static function db_fields()
+ {
+ return static::config('db_fields');
+ }
+
+ /**
+ * primary key columns
+ * @return array
+ */
+ protected static function pk()
+ {
+ return static::config('pk');
+ }
+
+ /**
+ * default values for columns
+ * @return array
+ */
+ protected static function default_values()
+ {
+ return static::config('default_values');
+ }
+
+ /**
+ * list of columns to deserialize
+ * @return array key is name of column, value is name of ArrayObject class
+ */
+ protected static function serialized_fields()
+ {
+ return static::config('serialized_fields');
+ }
/**
* aliases for columns
* alias => column
- * @var array $alias_fields
+ * @return array
*/
- protected $alias_fields = [];
+ protected static function alias_fields()
+ {
+ return static::config('alias_fields');
+ }
/**
* multi-language fields
* name => boolean
- * @var array $i18n_fields
+ * @return array
*/
- protected $i18n_fields = [];
+ protected static function i18n_fields()
+ {
+ return static::config('i18n_fields');
+ }
/**
* additional computed fields
* name => callable
- * @var array $additional_fields
- */
- protected $additional_fields = [];
-
- /**
- * stores instantiated related objects
- * @var array $relations
+ * @return array
*/
- protected $relations = [];
+ protected static function additional_fields()
+ {
+ return static::config('additional_fields');
+ }
/**
* 1:n relation
- * @var array $has_many
+ * @return array
*/
- protected $has_many = [];
+ protected static function has_many()
+ {
+ return static::config('has_many');
+ }
/**
* 1:1 relation
- * @var array $has_one
+ * @return array
*/
- protected $has_one = [];
+ protected static function has_one()
+ {
+ return static::config('has_one');
+ }
/**
* n:1 relations
- * @var array $belongs_to
+ * @return array
*/
- protected $belongs_to = [];
+ protected static function belongs_to()
+ {
+ return static::config('belongs_to');
+ }
/**
* n:m relations
- * @var array $has_and_belongs_to_many
+ * @return array
*/
- protected $has_and_belongs_to_many = [];
+ protected static function has_and_belongs_to_many()
+ {
+ return static::config('has_and_belongs_to_many');
+ }
/**
* callbacks
- * @var array<string, array<string|Closure>> registered_callbacks
+ * @return array<string, array<string|Closure>>
*/
- protected $registered_callbacks = [];
+ protected static function registered_callbacks()
+ {
+ return static::config('registered_callbacks');
+ }
/**
* contains an array of all used identifiers for fields
* (db columns + aliased columns + additional columns + relations)
- * @var array $known_slots
- */
- protected $known_slots = [];
-
- /**
- * reserved indentifiers, fields with those names must not have an explicit getXXX() method
- * @var array $reserved_slots
+ * @return array
*/
- protected static $reserved_slots = ['value','newid','iterator','tablemetadata', 'relationvalue','wherequery','relationoptions','data','new','id'];
+ protected static function known_slots()
+ {
+ return static::config('known_slots');
+ }
/**
* assoc array used to map SORM callback to NotificationCenter
* keys are SORM callbacks, values notifications
* eg. 'after_create' => 'FooDidCreate'
*
- * @var array $notification_map
- */
- protected $notification_map = [];
-
- /**
- * assoc array for storing values for additional fields
- *
- * @var array $additional_data
+ * @return array
*/
- protected $additional_data = [];
+ protected static function notification_map()
+ {
+ return static::config('notification_map');
+ }
/**
* assoc array for mapping get/set Methods
*
- * @var array $getter_setter_map
+ * @return array
*/
- protected $getter_setter_map = [];
+ protected static function getter_setter_map()
+ {
+ return static::config('getter_setter_map');
+ }
- /**
- * indicator for batch operations in findEachBySQL
- *
- * @var bool $performs_batch_operation
- */
- protected static $performs_batch_operation = false;
+ //////////////////////////////////////////////////
/**
* set configuration data from subclass
@@ -241,11 +297,19 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
}
}
+ foreach (['default_values', 'serialized_fields', 'alias_fields', 'i18n_fields', 'additional_fields'] as $fields) {
+ if (!isset($config[$fields])) {
+ $config[$fields] = [];
+ }
+ }
+
foreach (['has_many', 'belongs_to', 'has_one', 'has_and_belongs_to_many'] as $type) {
if (isset($config[$type]) && is_array($config[$type])) {
foreach (array_keys($config[$type]) as $one) {
$config['relations'][$one] = null;
}
+ } else {
+ $config[$type] = [];
}
}
@@ -298,12 +362,7 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
}
}
- if (I18N::isEnabled()) {
- if (isset($config['i18n_fields']) && count($config['i18n_fields']) > 0) {
- $config['registered_callbacks']['before_store'][] = 'cbI18N';
- $config['registered_callbacks']['after_delete'][] = 'cbI18N';
- }
- } else {
+ if (!I18N::isEnabled()) {
$config['i18n_fields'] = [];
}
@@ -416,7 +475,7 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
public static function exists($id)
{
$ret = false;
- $db_table = static::config('db_table');
+ $db_table = static::db_table();
$class = get_called_class();
$record = new $class();
call_user_func_array([$record, 'setId'], func_get_args());
@@ -438,7 +497,7 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
*/
public static function countBySql($sql = '1', $params = [])
{
- $db_table = static::config('db_table');
+ $db_table = static::db_table();
$db = DBManager::get();
$has_join = stripos($sql, 'JOIN ');
if ($has_join === false || $has_join > 10) {
@@ -562,7 +621,7 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
*/
public static function findBySQL($sql, $params = [])
{
- $db_table = static::config('db_table');
+ $db_table = static::db_table();
$class = get_called_class();
$record = new $class();
$db = DBManager::get();
@@ -617,7 +676,7 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
$thru_assoc_key = $options['thru_assoc_key'];
$assoc_foreign_key = $options['assoc_foreign_key'];
- $db_table = static::config('db_table');
+ $db_table = static::db_table();
$class = get_called_class();
$record = new $class();
$sql = "SELECT `$db_table`.* FROM `$thru_table`
@@ -658,7 +717,7 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
$record = new $class();
$record->setNew(false);
- $db_table = static::config('db_table');
+ $db_table = static::db_table();
$st = DBManager::get()->prepare("SELECT `{$db_table}`.* FROM `{$db_table}` {$sql}");
$st->execute($params);
$st->setFetchMode(PDO::FETCH_INTO , $record);
@@ -691,8 +750,8 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
*/
public static function findMany($pks = [], $order = '', $order_params = [])
{
- $db_table = static::config('db_table');
- $pk = static::config('pk');
+ $db_table = static::db_table();
+ $pk = static::pk();
$db = DBManager::get();
if (count($pk) > 1) {
throw new Exception('not implemented yet');
@@ -712,8 +771,8 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
*/
public static function findEachMany($callable, $pks = [], $order = '', $order_params = [])
{
- $db_table = static::config('db_table');
- $pk = static::config('pk');
+ $db_table = static::db_table();
+ $pk = static::pk();
$db = DBManager::get();
if (count($pk) > 1) {
throw new Exception('not implemented yet');
@@ -757,8 +816,8 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
$calleach = function($m) use (&$ret, $callable) {
$ret[] = $callable($m);
};
- $db_table = static::config('db_table');
- $pk = static::config('pk');
+ $db_table = static::db_table();
+ $pk = static::pk();
$db = DBManager::get();
if (count($pk) > 1) {
throw new Exception('not implemented yet');
@@ -795,7 +854,7 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
return $id_or_object;
}
if (is_array($id_or_object)) {
- $pk = static::config('pk');
+ $pk = static::pk();
$key_values = [];
foreach($pk as $key) {
if (array_key_exists($key, $id_or_object)) {
@@ -825,9 +884,9 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
*/
public static function __callStatic($name, $arguments)
{
- $db_table = static::config('db_table');
- $alias_fields = static::config('alias_fields');
- $db_fields = static::config('db_fields');
+ $db_table = static::db_table();
+ $alias_fields = static::alias_fields();
+ $db_fields = static::db_fields();
$name = strtolower($name);
$class = get_called_class();
$order = '';
@@ -886,15 +945,9 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
*/
function __construct($id = null)
{
- $class = get_class($this);
- //initialize configuration for subclass, only one time
- if (!array_key_exists($class, self::$config)) {
- static::configure();
- }
- //if configuration data for subclass is found, point internal properties to it
- if (self::$config[$class] !== null) {
- foreach (array_keys(self::$config[$class]) as $config_key) {
- $this->{$config_key} = self::$config[$class][$config_key];
+ foreach(['has_many', 'belongs_to', 'has_one', 'has_and_belongs_to_many'] as $type) {
+ foreach (array_keys($this->$type()) as $one) {
+ $this->relations[$one] = null;
}
}
@@ -935,8 +988,8 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
*/
protected function _getAdditionalValueFromRelation($field)
{
- list($relation, $relation_field) = [$this->additional_fields[$field]['relation'],
- $this->additional_fields[$field]['relation_field']];
+ list($relation, $relation_field) = [$this->additional_fields()[$field]['relation'],
+ $this->additional_fields()[$field]['relation_field']];
if (!array_key_exists($field, $this->additional_data)) {
$this->_setAdditionalValue($field, $this->getRelationValue($relation, $relation_field));
}
@@ -952,8 +1005,8 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
*/
protected function _setAdditionalValueFromRelation($field, $value)
{
- list($relation, $relation_field) = [$this->additional_fields[$field]['relation'],
- $this->additional_fields[$field]['relation_field']];
+ list($relation, $relation_field) = [$this->additional_fields()[$field]['relation'],
+ $this->additional_fields()[$field]['relation_field']];
$this->$relation->$field = $value;
unset($this->additional_data[$field]);
return $this->_getAdditionalValueFromRelation($field);
@@ -985,8 +1038,8 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
function __clone()
{
//all references link still to old object => reset all aliases
- foreach ($this->alias_fields as $alias => $field) {
- if (isset($this->db_fields[$field])) {
+ foreach ($this->alias_fields() as $alias => $field) {
+ if (isset($this->db_fields()[$field])) {
$content_value = $this->content[$field];
$content_db_value = $this->content_db[$field];
unset($this->content[$alias]);
@@ -1010,7 +1063,7 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
//unset all relations for now
//TODO: maybe a deep copy of all belonging objects is more appropriate
foreach(['has_many', 'belongs_to', 'has_one', 'has_and_belongs_to_many'] as $type) {
- foreach (array_keys($this->{$type}) as $one) {
+ foreach (array_keys($this->$type()) as $one) {
$this->relations[$one] = null;
}
}
@@ -1034,7 +1087,7 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
}
if (empty($options['assoc_foreign_key'])) {
if ($type === 'has_many' || $type === 'has_one') {
- $options['assoc_foreign_key'] = $this->pk[0];
+ $options['assoc_foreign_key'] = $this->pk()[0];
} else if ($type === 'belongs_to') {
$options['assoc_foreign_key'] = 'id';
}
@@ -1042,7 +1095,7 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
if ($type === 'has_and_belongs_to_many') {
$thru_table = $options['thru_table'];
if (!$options['thru_key']) {
- $options['thru_key'] = $this->pk[0];
+ $options['thru_key'] = $this->pk()[0];
}
if (empty($options['thru_assoc_key']) || empty($options['assoc_foreign_key'])) {
$class = $options['class_name'];
@@ -1125,13 +1178,12 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
{
$options = [];
foreach(['has_many', 'belongs_to', 'has_one', 'has_and_belongs_to_many'] as $type) {
- if (isset($this->{$type}[$relation])) {
- $options = self::$config[get_class($this)][$type][$relation] ?: $this->{$type}[$relation];
+ if (isset($this->$type()[$relation])) {
+ $options = self::$config[get_class($this)][$type][$relation];
if (!isset($options['type'])) {
- $options = $this->parseRelationOptions($type, $relation, $options, $this->db_table);
+ $options = $this->parseRelationOptions($type, $relation, $options, $this->db_table());
$options['type'] = $type;
self::$config[get_class($this)][$type][$relation] = $options;
- $this->{$type}[$relation] = $options;
}
break;
}
@@ -1146,11 +1198,11 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
*/
function getTableMetadata()
{
- return ['fields' => $this->db_fields,
- 'pk' => $this->pk,
- 'table' => $this->db_table,
- 'additional_fields' => $this->additional_fields,
- 'alias_fields' => $this->alias_fields,
+ return ['fields' => $this->db_fields(),
+ 'pk' => $this->pk(),
+ 'table' => $this->db_table(),
+ 'additional_fields' => $this->additional_fields(),
+ 'alias_fields' => $this->alias_fields(),
'relations' => array_keys($this->relations)];
}
@@ -1161,7 +1213,7 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
*/
function hasAutoIncrementColumn()
{
- return $this->db_fields[$this->pk[0]]['extra'] == 'auto_increment';
+ return $this->db_fields()[$this->pk()[0]]['extra'] == 'auto_increment';
}
/**
@@ -1175,10 +1227,10 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
if (!is_array($id)){
$id = [$id];
}
- if (count($this->pk) != count($id)){
- throw new InvalidArgumentException("Invalid ID, Primary Key {$this->db_table} is " .join(",",$this->pk));
+ if (count($this->pk()) != count($id)){
+ throw new InvalidArgumentException("Invalid ID, Primary Key {$this->db_table()} is " .join(",",$this->pk()));
} else {
- foreach ($this->pk as $count => $key){
+ foreach ($this->pk() as $count => $key){
$this->content[$key] = $id[$count];
}
return true;
@@ -1192,16 +1244,16 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
*/
function getId()
{
- if (count($this->pk) == 1) {
- return $this->content[$this->pk[0]] ?? null;
+ if (count($this->pk()) == 1) {
+ return $this->content[$this->pk()[0]] ?? null;
} else {
$id = [];
- foreach ($this->pk as $key) {
+ foreach ($this->pk() as $key) {
if (array_key_exists($key, $this->content)) {
$id[] = $this->content[$key];
}
}
- return (count($this->pk) == count($id) ? $id : null);
+ return (count($this->pk()) == count($id) ? $id : null);
}
}
@@ -1213,11 +1265,11 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
function getNewId()
{
$id = false;
- if (count($this->pk) == 1) {
+ if (count($this->pk()) == 1) {
do {
- $id = md5(uniqid($this->db_table, 1));
- $db = DBManager::get()->query("SELECT `{$this->pk[0]}` FROM `{$this->db_table}` "
- . "WHERE `{$this->pk[0]}` = '$id'");
+ $id = md5(uniqid($this->db_table(), 1));
+ $db = DBManager::get()->query("SELECT `{$this->pk()[0]}` FROM `{$this->db_table()}` "
+ . "WHERE `{$this->pk()[0]}` = '$id'");
} while($db->fetch());
}
return $id;
@@ -1237,7 +1289,7 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
if (is_string($only_these_fields)) {
$only_these_fields = words($only_these_fields);
}
- $fields = array_diff($this->known_slots, array_keys($this->relations));
+ $fields = array_diff($this->known_slots(), array_keys($this->relations));
if (is_array($only_these_fields)) {
$only_these_fields = array_filter(array_map(function($s) {
return is_string($s) ? strtolower($s) : null;
@@ -1268,7 +1320,7 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
if (is_string($only_these_fields)) {
$only_these_fields = words($only_these_fields);
}
- $fields = array_keys($this->db_fields);
+ $fields = array_keys($this->db_fields());
if (is_array($only_these_fields)) {
$only_these_fields = array_filter(array_map(function ($s) {
return is_string($s) ? strtolower($s) : null;
@@ -1313,7 +1365,7 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
$only_these_fields = words($only_these_fields);
}
if (is_null($only_these_fields)) {
- $only_these_fields = $this->known_slots;
+ $only_these_fields = $this->known_slots();
}
$ret = $this->toArray($only_these_fields);
$relations = [];
@@ -1363,13 +1415,13 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
$field = strtolower($field);
// No value defined, throw exception
- if (!in_array($field, $this->known_slots)) {
+ if (!in_array($field, $this->known_slots())) {
throw new InvalidArgumentException(static::class . '::'.$field . ' not found.');
}
// Get value by getter
- if (isset($this->getter_setter_map[$field]['get'])) {
- return call_user_func([$this, $this->getter_setter_map[$field]['get']]);
+ if (isset($this->getter_setter_map()[$field]['get'])) {
+ return call_user_func([$this, $this->getter_setter_map()[$field]['get']]);
}
// Get value from content
@@ -1384,14 +1436,14 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
}
// Get value from additional_field
- if (isset($this->additional_fields[$field]['get'])) {
+ if (isset($this->additional_fields()[$field]['get'])) {
// Getter is defined as a closure
- if ($this->additional_fields[$field]['get'] instanceof Closure) {
- return call_user_func_array($this->additional_fields[$field]['get'], [$this, $field]);
+ if ($this->additional_fields()[$field]['get'] instanceof Closure) {
+ return call_user_func_array($this->additional_fields()[$field]['get'], [$this, $field]);
}
// Getter is defined as a method of this object
- return call_user_func([$this, $this->additional_fields[$field]['get']], $field);
+ return call_user_func([$this, $this->additional_fields()[$field]['get']], $field);
}
// No value found, throw exception
@@ -1428,9 +1480,9 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
function getDefaultValue($field)
{
$default_value = null;
- if (!isset($this->default_values[$field])) {
- if (!in_array($field, $this->pk)) {
- $meta = $this->db_fields[$field];
+ if (!isset($this->default_values()[$field])) {
+ if (!in_array($field, $this->pk())) {
+ $meta = $this->db_fields()[$field];
if (isset($meta['default'])) {
$default_value = $meta['default'];
} elseif ($meta['null'] == 'NO') {
@@ -1443,7 +1495,7 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
}
}
} else {
- $default_value = $this->default_values[$field];
+ $default_value = $this->default_values()[$field];
}
return $default_value;
}
@@ -1461,23 +1513,23 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
{
$field = strtolower($field);
$ret = false;
- if (in_array($field, $this->known_slots)) {
- if (isset($this->getter_setter_map[$field]['set'])) {
- return call_user_func([$this, $this->getter_setter_map[$field]['set']], $value);
+ if (in_array($field, $this->known_slots())) {
+ if (isset($this->getter_setter_map()[$field]['set'])) {
+ return call_user_func([$this, $this->getter_setter_map()[$field]['set']], $value);
}
if (array_key_exists($field, $this->content)) {
- if (array_key_exists($field, $this->serialized_fields)) {
+ if (array_key_exists($field, $this->serialized_fields())) {
$ret = $this->setSerializedValue($field, $value);
} elseif ($this->isI18nField($field)) {
$ret = $this->setI18nValue($field, $value);
} else {
$ret = ($this->content[$field] = $value);
}
- } elseif (isset($this->additional_fields[$field]['set'])) {
- if ($this->additional_fields[$field]['set'] instanceof Closure) {
- return call_user_func_array($this->additional_fields[$field]['set'], [$this, $field, $value]);
+ } elseif (isset($this->additional_fields()[$field]['set'])) {
+ if ($this->additional_fields()[$field]['set'] instanceof Closure) {
+ return call_user_func_array($this->additional_fields()[$field]['set'], [$this, $field, $value]);
} else {
- return call_user_func([$this, $this->additional_fields[$field]['set']], $field, $value);
+ return call_user_func([$this, $this->additional_fields()[$field]['set']], $field, $value);
}
} elseif (array_key_exists($field, $this->relations)) {
$options = $this->getRelationOptions($field);
@@ -1570,7 +1622,7 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
function __isset($field)
{
$field = strtolower($field);
- if (in_array($field, $this->known_slots)) {
+ if (in_array($field, $this->known_slots())) {
$value = $this->getValue($field);
return $value instanceOf SimpleORMapCollection ? (bool)count($value) : !is_null($value);
} else {
@@ -1640,7 +1692,7 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
*/
public function count()
{
- return count($this->known_slots) - count($this->relations);
+ return count($this->known_slots()) - count($this->relations);
}
/**
@@ -1651,7 +1703,7 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
function isField($field)
{
$field = strtolower($field);
- return isset($this->db_fields[$field]);
+ return isset($this->db_fields()[$field]);
}
/**
@@ -1662,7 +1714,7 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
function isAdditionalField($field)
{
$field = strtolower($field);
- return isset($this->additional_fields[$field]);
+ return isset($this->additional_fields()[$field]);
}
/**
@@ -1673,7 +1725,7 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
function isAliasField($field)
{
$field = strtolower($field);
- return isset($this->alias_fields[$field]);
+ return isset($this->alias_fields()[$field]);
}
/**
@@ -1684,7 +1736,7 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
function isI18nField($field)
{
$field = strtolower($field);
- return isset($this->i18n_fields[$field]);
+ return isset($this->i18n_fields()[$field]);
}
/**
@@ -1709,9 +1761,9 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
if (is_iterable($data)) {
foreach($data as $key => $value) {
$key = strtolower($key);
- if (isset($this->db_fields[$key])
- || isset($this->alias_fields[$key])
- || isset($this->additional_fields[$key]['set'])
+ if (isset($this->db_fields()[$key])
+ || isset($this->alias_fields()[$key])
+ || isset($this->additional_fields()[$key]['set'])
) {
$this->setValue($key, $value);
++$count;
@@ -1762,10 +1814,10 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
{
$where_query = null;
$pk_not_set = [];
- foreach ($this->pk as $key) {
+ foreach ($this->pk() as $key) {
$pk = $this->content_db[$key] ?? $this->content[$key] ?? null;
if (isset($pk)) {
- $where_query[] = "`{$this->db_table}`.`{$key}` = " . DBManager::get()->quote($pk);
+ $where_query[] = "`{$this->db_table()}`.`{$key}` = " . DBManager::get()->quote($pk);
} else {
$pk_not_set[] = $key;
}
@@ -1793,7 +1845,7 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
return false;
}
$this->initializeContent();
- $query = "SELECT * FROM `{$this->db_table}` WHERE "
+ $query = "SELECT * FROM `{$this->db_table()}` WHERE "
. join(" AND ", $where_query);
$st = DBManager::get()->prepare($query);
$st->execute();
@@ -1834,7 +1886,18 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
return false;
}
}
- foreach ($this->db_fields as $field => $meta) {
+
+ // Collect i18n contents
+ $i18ncontent = [];
+ foreach (array_keys($this->i18n_fields()) as $field) {
+ if ($this->content[$field] instanceof I18NString) {
+ $i18ncontent[$field] = $this->content[$field];
+ $this->content[$field] = $this->content[$field]->original();
+ $this->content_db[$field] = $this->content_db[$field]->original();
+ }
+ }
+
+ foreach ($this->db_fields() as $field => $meta) {
$value = $this->content[$field];
if ($field == 'chdate' && !$this->isFieldDirty($field) && $this->isDirty()) {
$value = time();
@@ -1849,7 +1912,7 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
}
}
if ($value === null && $meta['null'] == 'NO') {
- throw new UnexpectedValueException($this->db_table . '.' . $field . ' must not be null.');
+ throw new UnexpectedValueException($this->db_table() . '.' . $field . ' must not be null.');
}
if (is_float($value)) {
$value = str_replace(',', '.', $value);
@@ -1859,14 +1922,31 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
}
if (!$this->isNew()) {
$where_query = $this->getWhereQuery();
- $query = "UPDATE `{$this->db_table}` SET "
+ $query = "UPDATE `{$this->db_table()}` SET "
. implode(',', $query_part);
$query .= " WHERE " . join(" AND ", $where_query);
} else {
- $query = "INSERT INTO `{$this->db_table}` SET "
+ $query = "INSERT INTO `{$this->db_table()}` SET "
. implode(',', $query_part);
}
$ret = DBManager::get()->exec($query);
+
+ // Store i18n contents
+ if (count($i18ncontent) > 0) {
+ foreach ($i18ncontent as $field => $one) {
+ $meta = [
+ 'object_id' => $this->getId(),
+ 'table' => $this->db_table(),
+ 'field' => $field
+ ];
+ $one->setMetadata($meta);
+ $one->storeTranslations();
+ if (!$this->content[$field] instanceof I18NString) {
+ $this->content[$field] = $one;
+ $this->content_db[$field] = clone $one;
+ }
+ }
+ }
if ($this->isNew()) {
$this->applyCallbacks('after_create');
} else {
@@ -1950,10 +2030,10 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
*/
function triggerChdate()
{
- if ($this->db_fields['chdate']) {
+ if ($this->db_fields()['chdate']) {
$this->content['chdate'] = time();
if ($where_query = $this->getWhereQuery()) {
- DBManager::get()->exec("UPDATE `{$this->db_table}` SET chdate={$this->content['chdate']}
+ DBManager::get()->exec("UPDATE `{$this->db_table()}` SET chdate={$this->content['chdate']}
WHERE ". join(" AND ", $where_query));
return true;
}
@@ -1977,12 +2057,21 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
$ret = $this->deleteRelations();
$where_query = $this->getWhereQuery();
if ($where_query) {
- $query = "DELETE FROM `{$this->db_table}` WHERE "
+ $query = "DELETE FROM `{$this->db_table()}` WHERE "
. join(" AND ", $where_query);
$ret += DBManager::get()->exec($query);
}
$this->is_deleted = true;
$this->applyCallbacks('after_delete');
+
+ // Remove i18n translations
+ if (I18N::isEnabled()) {
+ foreach (array_keys($this->i18n_fields()) as $field) {
+ if ($this->content[$field] instanceof I18NString) {
+ $this->content[$field]->removeTranslations();
+ }
+ }
+ }
}
$this->setData([], true);
return $ret;
@@ -2039,13 +2128,13 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
protected function initializeContent()
{
$this->content = [];
- foreach (array_keys($this->db_fields) as $field) {
+ foreach (array_keys($this->db_fields()) as $field) {
$this->content[$field] = null;
$this->content_db[$field] = null;
$this->setValue($field, $this->getDefaultValue($field));
}
- foreach ($this->alias_fields as $alias => $field) {
- if (isset($this->db_fields[$field])) {
+ foreach ($this->alias_fields() as $alias => $field) {
+ if (isset($this->db_fields()[$field])) {
$this->content[$alias] =& $this->content[$field];
$this->content_db[$alias] =& $this->content_db[$field];
} else {
@@ -2065,7 +2154,7 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
*/
public function isDirty()
{
- foreach (array_keys($this->db_fields) as $field) {
+ foreach (array_keys($this->db_fields()) as $field) {
if ($this->isFieldDirty($field)) {
return true;
}
@@ -2183,7 +2272,7 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
protected function applyCallbacks($type)
{
$ok = true;
- foreach ($this->registered_callbacks[$type] as $cb) {
+ foreach ($this->registered_callbacks()[$type] as $cb) {
if ($cb instanceof Closure) {
$function = $cb;
$params = [$this, $type, $cb];
@@ -2208,14 +2297,19 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
* @throws InvalidArgumentException if the callback type is not known
* @return number of registered callbacks
*/
- protected function registerCallback($types, $cb)
+ protected static function registerCallback($types, $cb)
{
+ trigger_error(__METHOD__ . ' is deprecated. Please use the configuration in configure().', E_USER_DEPRECATED);
+
$types = is_array($types) ? $types : words($types);
$reg = 0;
foreach ($types as $type) {
- if (isset($this->registered_callbacks[$type])) {
- $this->registered_callbacks[$type][] = $cb;
- $reg++;
+ if (isset(static::registered_callbacks()[$type])) {
+ $found = array_search($cb, self::$config[static::class]['registered_callbacks'][$type], true);
+ if ($found === false) {
+ self::$config[static::class]['registered_callbacks'][$type][] = $cb;
+ $reg++;
+ }
} else {
throw new InvalidArgumentException('Unknown callback type: ' . $type);
}
@@ -2231,15 +2325,17 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
* @throws InvalidArgumentException if the callback type is not known
* @return number of unregistered callbacks
*/
- protected function unregisterCallback($types, $cb)
+ protected static function unregisterCallback($types, $cb)
{
+ trigger_error(__METHOD__ . ' is deprecated. Please use the configuration in configure().', E_USER_DEPRECATED);
+
$types = is_array($types) ? $types : words($types);
foreach ($types as $type) {
- if (isset($this->registered_callbacks[$type])) {
- $found = array_search($cb, $this->registered_callbacks[$type], true);
+ if (isset(static::registered_callbacks()[$type])) {
+ $found = array_search($cb, self::$config[static::class]['registered_callbacks'][$type], true);
if ($found !== false) {
$unreg++;
- unset($this->registered_callbacks[$type][$found]);
+ unset(self::$config[static::class]['registered_callbacks'][$type][$found]);
}
} else {
throw new InvalidArgumentException('Unknown callback type: ' . $type);
@@ -2284,9 +2380,9 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
*/
protected function cbNotificationMapper($cb_type)
{
- if (isset($this->notification_map[$cb_type])) {
+ if (isset($this->notification_map()[$cb_type])) {
try {
- foreach(words($this->notification_map[$cb_type]) as $notification) {
+ foreach(words($this->notification_map()[$cb_type]) as $notification) {
NotificationCenter::postNotification($notification, $this);
}
} catch (NotificationVetoException $e) {
@@ -2303,7 +2399,7 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
*/
protected function cbAfterInitialize($cb_type)
{
- foreach (array_keys($this->db_fields) as $field) {
+ foreach (array_keys($this->db_fields()) as $field) {
if (is_object($this->content[$field])) {
$this->content_db[$field] = clone $this->content[$field];
} else {
@@ -2322,7 +2418,7 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
*/
protected function setSerializedValue($field, $value)
{
- $object_type = $this->serialized_fields[$field];
+ $object_type = $this->serialized_fields()[$field];
if (is_null($value) || $value instanceof $object_type) {
$this->content[$field] = $value;
} else {
@@ -2342,7 +2438,7 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
protected function setI18nValue($field, $value)
{
$meta = ['object_id' => $this->getId(),
- 'table' => $this->db_table,
+ 'table' => $this->db_table(),
'field' => $field];
if ($value instanceof I18NString) {
$value->setMetadata($meta);
@@ -2353,53 +2449,6 @@ class SimpleORMap implements ArrayAccess, Countable, IteratorAggregate
return $this->content[$field];
}
- /**
- * default callback for tables with I18N fields
- * @param string $type
- * @return bool
- */
- protected function cbI18N($type)
- {
-
- if ($type == 'before_store') {
- $i18ncontent = [];
- foreach (array_keys($this->i18n_fields) as $field) {
- if ($this->content[$field] instanceof I18NString) {
- $i18ncontent[$field] = $this->content[$field];
- $this->content[$field] = $this->content[$field]->original();
- $this->content_db[$field] = $this->content_db[$field]->original();
- }
- }
- if (count($i18ncontent)) {
- $after_store = function($that, $type, $myself) use ($i18ncontent) {
- foreach ($i18ncontent as $field => $one) {
- $meta = ['object_id' => $this->getId(),
- 'table' => $this->db_table,
- 'field' => $field];
- $one->setMetadata($meta);
- $one->storeTranslations();
- if (!$this->content[$field] instanceof I18NString) {
- $this->content[$field] = $one;
- $this->content_db[$field] = clone $one;
- }
- }
- $this->unregisterCallback('after_store', $myself);
- };
- $this->registerCallback('after_store', $after_store);
- }
-
- }
-
- if ($type == 'after_delete') {
- foreach (array_keys($this->i18n_fields) as $field) {
- if ($this->content[$field] instanceof I18NString) {
- $this->content[$field]->removeTranslations();
- }
- }
- }
- return true;
- }
-
/**
* Cleans up this object. This essentially reset all relations of
* this object and marks them as unused so that the garbage collector may
diff --git a/lib/models/StudiengangStgteil.php b/lib/models/StudiengangStgteil.php
index 76d01ff..9914022 100644
--- a/lib/models/StudiengangStgteil.php
+++ b/lib/models/StudiengangStgteil.php
@@ -51,12 +51,6 @@ class StudiengangStgteil extends ModuleManagementModel
private $stgbez_name;
private $stgbez_id;
- function __construct($id = null)
- {
- $this->default_values['position'] = 10000;
- parent::__construct($id);
- }
-
/**
* Retrieves the StudiengangStgteil and all related data and some
* additional fields.
diff --git a/lib/models/User.class.php b/lib/models/User.class.php
index cbd5e90..7ce868b 100644
--- a/lib/models/User.class.php
+++ b/lib/models/User.class.php
@@ -232,7 +232,7 @@ class User extends AuthUserMd5 implements Range, PrivacyObject
$user->info = new UserInfo();
$user->setData($data);
$user->setNew($is_new);
- foreach (array_keys($user->db_fields) as $field) {
+ foreach (array_keys($user->db_fields()) as $field) {
$user->content_db[$field] = $user->content[$field];
}
$user->info = UserInfo::build($data, $is_new);
@@ -305,29 +305,6 @@ class User extends AuthUserMd5 implements Range, PrivacyObject
);
}
- public static function findDozentenByTermin_id($termin_id)
- {
- $record = new User();
- $db = DBManager::get();
- $sql = "SELECT `{$record->db_table}`.*
- FROM `{$record->db_table}`
- INNER JOIN `termin_related_persons` USING (user_id)
- WHERE `termin_related_persons`.`range_id` = ?
- ORDER BY Nachname, Vorname ASC";
- $statement = $db->prepare($sql);
- $statement->execute([$termin_id]);
-
- $ret = [];
- while($row = $statement->fetch(PDO::FETCH_ASSOC)) {
- $item = new User();
- $item->setData($row, true);
- $item->setNew(false);
-
- $ret[] = $item;
- }
- return $ret;
- }
-
/**
* Wraps a search parameter in %..% if the parameter itself does not
* contain % or _.
diff --git a/tests/unit/lib/classes/SimpleOrMapNodbTest.php b/tests/unit/lib/classes/SimpleOrMapNodbTest.php
index f6b4e0b..e5c333b 100644
--- a/tests/unit/lib/classes/SimpleOrMapNodbTest.php
+++ b/tests/unit/lib/classes/SimpleOrMapNodbTest.php
@@ -38,7 +38,7 @@ class auth_user_md5 extends SimpleORMap
return $this->content['perms'] = mb_strtolower($perm);
}
- public function registerCallback($types, $cb)
+ public static function registerCallback($types, $cb)
{
return parent::registerCallback($types, $cb);
}
@@ -274,4 +274,18 @@ class SimpleOrMapNodbTest extends \Codeception\Test\Unit
$this->assertEquals(3, $a->id);
$this->assertEquals('auth_user_md5WillStore', $callback_was_here);
}
+
+
+ /**
+ * @depends testConstruct
+ */
+ public function testSerialization($a)
+ {
+ $serialized = serialize($a);
+ $this->assertIsString($serialized);
+
+ $unserialized = unserialize($serialized);
+
+ $this->assertEquals($a->toArray(), $unserialized->toArray());
+ }
}