diff --git a/e107_handlers/admin_ui.php b/e107_handlers/admin_ui.php index 8a7e93772..f8365587c 100644 --- a/e107_handlers/admin_ui.php +++ b/e107_handlers/admin_ui.php @@ -3547,7 +3547,7 @@ class e_admin_ui extends e_admin_controller_ui $this->_model->setModelTable($this->table) ->setFieldIdName($this->pid) ->setValidationRules($this->validationRules) - ->setFieldTypes($this->fieldTypes) + ->setDbTypes($this->fieldTypes) ->setDataFields($this->dataFields) ->setMessageStackName('admin_ui_model_'.$this->table) ->setParam('db_query', $this->editQry); diff --git a/e107_handlers/e107_class.php b/e107_handlers/e107_class.php index d13722279..0a6f83dd4 100644 --- a/e107_handlers/e107_class.php +++ b/e107_handlers/e107_class.php @@ -610,7 +610,7 @@ class e107 */ public static function getSingleton($class_name, $path = true, $regpath = '') { - + $id = 'core/e107/singleton/'.$class_name.$regpath; //singleton object found - overload not possible @@ -859,23 +859,23 @@ class e107 { return self::getSingleton('e_parse_shortcode', true); } - + /** * Retrieve registered sc object (batch) by class name * Note - '_shortcodes' part of the class/override is added by the method * Override is possible only if class is not already instantiated by shortcode parser - * - * myplugin/core/shortcodes/batch/my_shortcodes.php - * e107::getScObject('my', 'myplugin'); + * e107::getScObject('my', 'myplugin'); * // news override - plugin_myplugin_news_shortcodes extends news_shortcodes -> myplugin/core/shortcodes/batch/news_shortcodes.php * e107::getScObject('news', 'myplugin', true); * // news override - plugin_myplugin_mynews_shortcodes extends news_shortcodes -> myplugin/core/shortcodes/batch/mynews_shortcodes.php * e107::getScObject('news', 'myplugin', 'mynews'); * - * + * * @param string $className * @param string $pluginName * @param string|true $overrideClass @@ -1089,19 +1089,25 @@ class e107 * Retrieve user model object. * * @param integer $user_id target user + * @param boolean $checkIfCurrent if tru user_id will be compared to current user, if there is a match + * current user object will be returned * @return e_system_user */ - public static function getSystemUser($user_id) + public static function getSystemUser($user_id, $checkIfCurrent = true) { + if($checkIfCurrent && $user_id && $user_id === self::getUser()->getId()) + { + return self::getUser(); + } $user = self::getRegistry('targets/core/user/'.$user_id); if(null === $user) { - $user = self::getObject('e_system_user'); + $user = self::getObject('e_system_user'); if($user_id) $user->load($user_id); // self registered on load } return $user; } - + /** * Retrieve current user model object. * @@ -1111,7 +1117,7 @@ class e107 { return self::getSingleton('e_user', true, 'targets/core/current_user'); } - + /** * Retrieve user model object. * @@ -1131,7 +1137,7 @@ class e107 { return self::getSingleton('e107_user_extended', true); } - + /** * Retrieve User Perms (admin perms) handler singleton object * @return comment @@ -2121,8 +2127,8 @@ class e107 $e_QUERY = $_SERVER['QUERY_STRING']; define('e_LANCODE', ''); } - - $e_QUERY = str_replace("&","&", self::getParser()->post_toForm($e_QUERY)); + + $e_QUERY = str_replace("&","&", self::getParser()->post_toForm($e_QUERY)); define('e_QUERY', $e_QUERY); define('e_TBQS', $_SERVER['QUERY_STRING']); diff --git a/e107_handlers/model_class.php b/e107_handlers/model_class.php index 14ba54063..7cb9b71d0 100644 --- a/e107_handlers/model_class.php +++ b/e107_handlers/model_class.php @@ -76,16 +76,6 @@ class e_model * @var string */ protected $_field_id; - - /** - * DB format array - see db::_getTypes() and db::_getFieldValue() (mysql_class.php) - * for example - * - * This can/should be overwritten by extending the class - * - * @var array - */ - protected $_FIELD_TYPES = array(); /** * Namespace to be used for model related system messages in {@link eMessage} handler @@ -93,18 +83,18 @@ class e_model * @var string */ protected $_message_stack = 'default'; - + /** * Cache string to be used from _get/set/clearCacheData() methods * * @var string */ protected $_cache_string = null; - + /** * Force Cache even if system cahche is disabled * Default is false - * + * * @var boolean */ protected $_cache_force = false; @@ -373,6 +363,19 @@ class e_model return $this->_isData($key); } + /** + * @param boolean $new_state new object state if set + * @return boolean + */ + public function isModified($new_state = null) + { + if(is_bool($new_state)) + { + $this->data_has_changed = $new_state; + } + return $this->data_has_changed; + } + /** * Retrieves data from the object * @@ -892,7 +895,7 @@ class e_model { return $this; } - + if($force) { $this->setData(array()) @@ -903,7 +906,7 @@ class e_model { return $this; } - + $cached = $this->_getCacheData(); if($cached !== false) { @@ -946,23 +949,23 @@ class e_model return $this; } - + protected function _getCacheData() { if(!$this->isCacheEnabled()) { return false; } - + $cached = e107::getCache()->retrieve_sys($this->getCacheString(true), false, $this->_cache_force); - if(false !== $cached) + if(false !== $cached) { return e107::getArrayStorage()->ReadArray($cached); } - + return false; } - + protected function _setCacheData() { if(!$this->isCacheEnabled()) @@ -972,7 +975,7 @@ class e_model e107::getCache()->set_sys($this->getCacheString(true), $this->toString(false), $this->_cache_force, false); return $this; } - + protected function _clearCacheData() { if(!$this->isCacheEnabled(false)) @@ -981,70 +984,21 @@ class e_model } e107::getCache()->clear_sys($this->getCacheString(true), false); } - + public function isCacheEnabled($checkId = true) { return (null !== $this->getCacheString() && (!$checkId || $this->getId())); } - + public function getCacheString($replace = false) { return ($replace ? str_replace('{ID}', $this->getId(), $this->_cache_string) : $this->_cache_string); } - + public function setCacheString($str) { $this->_cache_string = $str; } - - - /** - * Predefined data fields types, passed to DB handler - * @return array - */ - public function getFieldTypes() - { - return $this->_FIELD_TYPES; - } - - /** - * Predefined data fields types, passed to DB handler - * - * @param array $field_types - * @return e_model - */ - public function setFieldTypes($field_types) - { - $this->_FIELD_TYPES = $field_types; - return $this; - } - - /** - * Auto field type definitions - * - * @param boolean $force - * @return boolean - */ - public function setFieldTypeDefs($force = false) - { - if($force || !$this->getFieldTypes()) - { - $ret = e107::getDb()->getFieldDefs($this->getModelTable()); - if($ret) - { - foreach ($ret as $k => $v) - { - if('todb' == $v) - { - $ret[$k] = 'string'; - } - } - $this->setFieldTypes($ret); - return true; - } - } - return false; - } /** * Save data to DB @@ -1055,12 +1009,30 @@ class e_model { } + /** + * Delete DB record + * Awaiting for child class implementation + * @see e_model_admin + */ + public function delete() + { + } + + /** + * Create new DB recorrd + * Awaiting for child class implementation + * @see e_model_admin + */ + public function create() + { + } + /** * Insert data to DB * Awaiting for child class implementation * @see e_model_admin */ - public function dbInsert() + protected function dbInsert() { } @@ -1069,7 +1041,7 @@ class e_model * Awaiting for child class implementation * @see e_model_admin */ - public function dbUpdate() + protected function dbUpdate() { } @@ -1078,7 +1050,7 @@ class e_model * Awaiting for child class implementation * @see e_model_admin */ - public function dbReplace() + protected function dbReplace() { } @@ -1087,7 +1059,7 @@ class e_model * Awaiting for child class implementation * @see e_model_admin */ - public function dbDelete() + protected function dbDelete() { } @@ -1262,10 +1234,8 @@ class e_model } } -//FIXME - move e_model_admin to e_model_admin.php - /** - * Base e107 Admin Model class + * Base e107 Fron Model class interface * * Some important points: * - model data should be always in toDB() format: @@ -1286,11 +1256,11 @@ class e_model * * @package e107 * @category e107_handlers - * @version 1.0 + * @version $Id$ * @author SecretR - * @copyright Copyright (C) 2009, e107 Inc. + * @copyright Copyright (C) 2008-2010 e107 Inc. */ -class e_admin_model extends e_model +class e_front_model extends e_model { /** * Posted data @@ -1300,6 +1270,17 @@ class e_admin_model extends e_model */ protected $_posted_data = array(); + + /** + * DB format array - see db::_getTypes() and db::_getFieldValue() (mysql_class.php) + * for example + * + * This can/should be overwritten by extending the class + * + * @var array + */ + protected $_FIELD_TYPES = array(); + /** * Validation structure - see {@link e_validator::$_required_rules} for * more information about the array format. @@ -1311,6 +1292,8 @@ class e_admin_model extends e_model */ protected $_validation_rules = array(); + protected $_optional_rules = array(); + /** * @var integer Last SQL error number */ @@ -1340,17 +1323,100 @@ class e_admin_model extends e_model * Set object validation rules if $_validation_rules array is empty * * @param array $vrules - * @return e_admin_model + * @return e_front_model */ - public function setValidationRules(array $vrules) + public function setValidationRules(array $vrules, $force = false) { - if(empty($this->_validation_rules)) + if($force || empty($this->_validation_rules)) { $this->_validation_rules = $vrules; } return $this; } + /** + * @return array + */ + public function getOptionalRules() + { + return $this->_optional_rules; + } + + /** + * @param array $rules + * @return e_front_model + */ + public function setOptionalRules(array $rules) + { + $this->_optional_rules = $rules; + return $this; + } + + /** + * Set object validation rules if $_validation_rules array is empty + * + * @param string $field + * @param array $rule + * @param boolean $required + * @return e_front_model + */ + public function setValidationRule($field, $rule, $required = true) + { + $pname = $required ? '_validation_rules' : '_optional_rules'; + $rules = &$this->$pname; + $rules[$field] = $rule; + + return $this; + } + + /** + * Predefined data fields types, passed to DB handler + * @return array + */ + public function getDbTypes() + { + return ($this->_FIELD_TYPES ? $this->_FIELD_TYPES : $this->getDataFields()); + } + + /** + * Predefined data fields types, passed to DB handler + * + * @param array $field_types + * @return e_model + */ + public function setDbTypes($field_types) + { + $this->_FIELD_TYPES = $field_types; + return $this; + } + + /** + * Auto field type definitions + * Disabled for now, it should auto-create _data_types + * @param boolean $force + * @return boolean + */ +// public function setFieldTypeDefs($force = false) +// { +// if($force || !$this->getFieldTypes()) +// { +// $ret = e107::getDb()->getFieldDefs($this->getModelTable()); +// if($ret) +// { +// foreach ($ret as $k => $v) +// { +// if('todb' == $v) +// { +// $ret[$k] = 'string'; +// } +// } +// $this->setFieldTypes($ret); +// return true; +// } +// } +// return false; +// } + /** * Retrieves data from the object ($_posted_data) without * key parsing (performance wise, prefered when possible) @@ -1413,7 +1479,7 @@ class e_admin_model extends e_model * @param string $key * @param mixed $value * @param boolean $strict update only - * @return e_admin_model + * @return e_front_model */ public function setPosted($key, $value, $strict = false) { @@ -1429,7 +1495,7 @@ class e_admin_model extends e_model * @param string|array $key * @param mixed $value * @param boolean $strict update only - * @return e_admin_model + * @return e_front_model */ public function setPostedData($key, $value = null, $strict = false) { @@ -1446,7 +1512,7 @@ class e_admin_model extends e_model * @param string|array $key * @param mixed $value * @param boolean $override override existing data - * @return e_admin_model + * @return e_front_model */ public function addPostedData($key, $value = null, $override = true) { @@ -1458,7 +1524,7 @@ class e_admin_model extends e_model * Public proxy of {@link _unsetDataSimple()} * * @param string $key - * @return e_admin_model + * @return e_front_model */ public function removePosted($key) { @@ -1474,7 +1540,7 @@ class e_admin_model extends e_model * Public proxy of {@link _unsetData()} * * @param string|null $key - * @return e_admin_model + * @return e_front_model */ public function removePostedData($key = null) { @@ -1555,7 +1621,7 @@ class e_admin_model extends e_model * @param boolean $strict * @param boolean $sanitize sanitize posted data before move it to the object data * @param boolean $validate perform validation check - * @return e_admin_model + * @return e_front_model */ public function mergePostedData($strict = true, $sanitize = true, $validate = true) { @@ -1576,6 +1642,8 @@ class e_admin_model extends e_model }*/ $data = $this->getPostedData(); + $valid_data = $this->getValidator()->getValidData(); + if($sanitize) { // search for db_field types @@ -1591,6 +1659,10 @@ class e_admin_model extends e_model foreach ($data as $field => $dt) { + // get values form validated array when possible + // we need it because of advanced validation methods e.g. 'compare' + if(isset($valid_data[$field])) $dt = $valid_data[$field]; + $this->setData($field, $dt, $strict) ->removePostedData($field); } @@ -1607,7 +1679,7 @@ class e_admin_model extends e_model * @param array $src_data * @param boolean $sanitize * @param boolean $validate perform validation check - * @return e_admin_model + * @return e_front_model */ public function mergeData(array $src_data, $strict = true, $sanitize = true, $validate = true) { @@ -1684,7 +1756,9 @@ class e_admin_model extends e_model if(null === $this->_validator) { $this->_validator = e107::getObject('e_validator'); - $this->_validator->setRules($this->getValidationRules())->setMessageStack($this->_message_stack.'_validator'); + $this->_validator->setRules($this->getValidationRules()) + ->setOptionalRules($this->getOptionalRules()) + ->setMessageStack($this->_message_stack.'_validator'); //TODO - optional check rules } return $this->_validator; @@ -1745,7 +1819,7 @@ class e_admin_model extends e_model * * @param boolean $session store messages to session * @param boolean $validation move validation messages as well - * @return e_admin_model + * @return e_front_model */ public function setMessages($session = false, $validation = true) { @@ -1763,7 +1837,7 @@ class e_admin_model extends e_model * @param boolean|string $type E_MESSAGE_INFO | E_MESSAGE_SUCCESS | E_MESSAGE_WARNING | E_MESSAGE_WARNING | E_MESSAGE_DEBUG | false (all) * @param boolean $session reset session messages * @param boolean $validation reset validation messages as well - * @return e_admin_model + * @return e_front_model */ public function resetMessages($type = false, $session = false, $validation = false) { @@ -1818,7 +1892,7 @@ class e_admin_model extends e_model /** * Generic load data from DB * @param boolean $force - * @return e_admin_model + * @return e_front_model */ public function load($id, $force = false) { @@ -1835,177 +1909,6 @@ class e_admin_model extends e_model return $this; } - /** - * Save data to DB - * - * @param boolen $from_post - */ - public function save($from_post = true, $force = false, $session_messages = false) - { - if(!$this->getFieldIdName()) - { - return false; - } - - if($from_post) - { - //no strict copy, validate & sanitize - $this->mergePostedData(false, true, true); - } - - if($this->getId()) - { - return $this->dbUpdate($force, $session_messages); - } - - return $this->dbInsert($force, $session_messages); - } - - public function delete($destroy = true, $session_messages = false) - { - $ret = $this->dbDelete(); - if($ret) - { - if($destroy) - { - $this->setMessages($session_messages)->destroy(); - } - } - return $ret; - } - - /** - * Insert data to DB - * - * @param boolean $force force query even if $data_has_changed is false - * @param boolean $session_messages to use or not session to store system messages - */ - public function dbInsert($force = false, $session_messages = false) - { - $this->_db_errno = 0; - $this->_db_errmsg = ''; - if($this->hasError() || (!$this->data_has_changed && !$force)) - { - return 0; - } - $sql = e107::getDb(); - $res = $sql->db_Insert($this->getModelTable(), $this->toSqlQuery('create')); - if(!$res) - { - $this->_db_errno = $sql->getLastErrorNumber(); - $this->_db_errmsg = $sql->getLastErrorText(); - $this->addMessageError('SQL Insert Error', $session_messages); //TODO - Lan - $this->addMessageDebug('SQL Error #'.$this->_db_errno.': '.$sql->getLastErrorText()); - return false; - } - - // Set the reutrned ID - $this->setId($res); - $this->addMessageSuccess(LAN_CREATED); - - return $res; - } - - /** - * Replace data in DB - * - * @param boolean $force force query even if $data_has_changed is false - * @param boolean $session_messages to use or not session to store system messages - */ - public function dbReplace($force = false, $session_messages = false) - { - $this->_db_errno = 0; - $this->_db_errmsg = ''; - if($this->hasError() || (!$this->data_has_changed && !$force)) - { - return 0; - } - $sql = e107::getDb(); - $res = $sql->db_Insert($this->getModelTable(), $this->toSqlQuery('replace')); - if(!$res) - { - $this->_db_errno = $sql->getLastErrorNumber(); - $this->_db_errmsg = $sql->getLastErrorText(); - if($this->_db_errno) - { - $this->addMessageError('SQL Replace Error', $session_messages); //TODO - Lan - $this->addMessageDebug('SQL Error #'.$this->_db_errno.': '.$sql->getLastErrorText()); - } - } - - return $res; - } - - /** - * Update DB data - * - * @param boolean $force force query even if $data_has_changed is false - * @param boolean $session_messages to use or not session to store system messages - */ - public function dbUpdate($force = false, $session_messages = false) - { - $this->_db_errno = 0; - $this->_db_errmsg = ''; - if($this->hasError() || (!$this->data_has_changed && !$force)) - { - $this->addMessageInfo(LAN_NO_CHANGE); - return 0; - } - $sql = e107::getDb(); - $res = $sql->db_Update($this->getModelTable(), $this->toSqlQuery('update')); - if(!$res) - { - $this->_db_errno = $sql->getLastErrorNumber(); - $this->_db_errmsg = $sql->getLastErrorText(); - if($this->_db_errno) - { - $this->addMessageError('SQL Update Error', $session_messages); //TODO - Lan - $this->addMessageDebug('SQL Error #'.$this->_db_errno.': '.$sql->getLastErrorText()); - return false; - } - - $this->addMessageInfo(LAN_NO_CHANGE); - return 0; - } - $this->addMessageSuccess(LAN_UPDATED); - return $res; - } - - /** - * Delete DB data - * - * @param boolean $force force query even if $data_has_changed is false - * @param boolean $session_messages to use or not session to store system messages - */ - public function dbDelete($session_messages = false) - { - $this->_db_errno = 0; - $this->_db_errmsg = ''; - if($this->hasError()) - { - return 0; - } - - if(!$this->getId()) - { - $this->addMessageError('Record not found', $session_messages); //TODO - Lan - return 0; - } - $sql = e107::getDb(); - $res = $sql->db_Delete($this->getModelTable(), $this->getFieldIdName().'='.intval($this->getId())); - if(!$res) - { - $this->_db_errno = $sql->getLastErrorNumber(); - $this->_db_errmsg = $sql->getLastErrorText(); - if($this->_db_errno) - { - $this->addMessageError('SQL Delete Error', $session_messages); //TODO - Lan - $this->addMessageDebug('SQL Error #'.$this->_db_errno.': '.$sql->getLastErrorText()); - } - } - - return $res; - } /** * Build query array to be used with db methods (db_Update, db_Insert, db_Replace) @@ -2142,12 +2045,260 @@ class e_admin_model extends e_model $this->data_has_changed = array(); $this->_FIELD_TYPES = array(); } + + + /** + * Update DB data + * + * @param boolean $force force query even if $data_has_changed is false + * @param boolean $session_messages to use or not session to store system messages + */ + protected function dbUpdate($force = false, $session_messages = false) + { + $this->_db_errno = 0; + $this->_db_errmsg = ''; + if($this->hasError() || (!$this->data_has_changed && !$force)) + { + $this->addMessageInfo(LAN_NO_CHANGE); + return 0; + } + $sql = e107::getDb(); + $res = $sql->db_Update($this->getModelTable(), $this->toSqlQuery('update')); + if(!$res) + { + $this->_db_errno = $sql->getLastErrorNumber(); + $this->_db_errmsg = $sql->getLastErrorText(); + if($this->_db_errno) + { + $this->addMessageError('SQL Update Error', $session_messages); //TODO - Lan + $this->addMessageDebug('SQL Error #'.$this->_db_errno.': '.$sql->getLastErrorText()); + return false; + } + + $this->addMessageInfo(LAN_NO_CHANGE); + return 0; + } + $this->addMessageSuccess(LAN_UPDATED); + return $res; + } + + /** + * Save data to DB + * + * @param boolen $from_post + * @return boolean|integer + */ + public function save($from_post = true, $force = false, $session_messages = false) + { + if(!$this->getFieldIdName()) + { + return false; + } + + if($from_post) + { + //no strict copy, validate & sanitize + $this->mergePostedData(false, true, true); + } + + if($this->getId()) + { + return $this->dbUpdate($force, $session_messages); + } + + return false; + } + + /** + * Exactly what it says - your debug helper + * @param boolean $retrun + * @param boolean $undo + * @return void + */ + public function saveDebug($return = false, $undo = true) + { + $ret = array(); + + $ret['validation_rules'] = $this->getValidationRules(); + $ret['optional_validation_rules'] = $this->getOptionalRules(); + $ret['model_base_ismodfied'] = $this->isModified(); + $ret['model_base_data'] = $this->getData(); + $ret['posted_data'] = $this->getPostedData(); + + $this->mergePostedData(false, true, true); + + $ret['model_modified_data'] = $this->getData(); + $ret['model_modified_ismodfied'] = $this->isModified(); + $ret['validator_valid_data'] = $this->getValidator()->getValidData(); + + // undo + if($undo) + { + $this->setData($ret['model_base_data']) + ->isModified($ret['model_base_ismodfied']) + ->setPostedData($ret['posted_data']); + } + if($return) return $ret; + + print_a($ret); + } +} + +//FIXME - move e_model_admin to e_model_admin.php + +/** + * Base e107 Admin Model class + * + * @package e107 + * @category e107_handlers + * @version $Id$ + * @author SecretR + * @copyright Copyright (C) 2008-2010 e107 Inc. + */ +class e_admin_model extends e_front_model +{ + /** + * Save data to DB + * + * @param boolen $from_post + */ + public function save($from_post = true, $force = false, $session_messages = false) + { + if(!$this->getFieldIdName()) + { + return false; + } + + if($from_post) + { + //no strict copy, validate & sanitize + $this->mergePostedData(false, true, true); + } + + if($this->getId()) + { + return $this->dbUpdate($force, $session_messages); + } + + return $this->dbInsert($force, $session_messages); + } + + public function delete($destroy = true, $session_messages = false) + { + $ret = $this->dbDelete(); + if($ret) + { + if($destroy) + { + $this->setMessages($session_messages)->destroy(); + } + } + return $ret; + } + + /** + * Insert data to DB + * + * @param boolean $force force query even if $data_has_changed is false + * @param boolean $session_messages to use or not session to store system messages + */ + protected function dbInsert($force = false, $session_messages = false) + { + $this->_db_errno = 0; + $this->_db_errmsg = ''; + if($this->hasError() || (!$this->data_has_changed && !$force)) + { + return 0; + } + $sql = e107::getDb(); + $res = $sql->db_Insert($this->getModelTable(), $this->toSqlQuery('create')); + if(!$res) + { + $this->_db_errno = $sql->getLastErrorNumber(); + $this->_db_errmsg = $sql->getLastErrorText(); + $this->addMessageError('SQL Insert Error', $session_messages); //TODO - Lan + $this->addMessageDebug('SQL Error #'.$this->_db_errno.': '.$sql->getLastErrorText()); + return false; + } + + // Set the reutrned ID + $this->setId($res); + $this->addMessageSuccess(LAN_CREATED); + + return $res; + } + + /** + * Replace data in DB + * + * @param boolean $force force query even if $data_has_changed is false + * @param boolean $session_messages to use or not session to store system messages + */ + protected function dbReplace($force = false, $session_messages = false) + { + $this->_db_errno = 0; + $this->_db_errmsg = ''; + if($this->hasError() || (!$this->data_has_changed && !$force)) + { + return 0; + } + $sql = e107::getDb(); + $res = $sql->db_Insert($this->getModelTable(), $this->toSqlQuery('replace')); + if(!$res) + { + $this->_db_errno = $sql->getLastErrorNumber(); + $this->_db_errmsg = $sql->getLastErrorText(); + if($this->_db_errno) + { + $this->addMessageError('SQL Replace Error', $session_messages); //TODO - Lan + $this->addMessageDebug('SQL Error #'.$this->_db_errno.': '.$sql->getLastErrorText()); + } + } + + return $res; + } + + /** + * Delete DB data + * + * @param boolean $force force query even if $data_has_changed is false + * @param boolean $session_messages to use or not session to store system messages + */ + protected function dbDelete($session_messages = false) + { + $this->_db_errno = 0; + $this->_db_errmsg = ''; + if($this->hasError()) + { + return 0; + } + + if(!$this->getId()) + { + $this->addMessageError('Record not found', $session_messages); //TODO - Lan + return 0; + } + $sql = e107::getDb(); + $res = $sql->db_Delete($this->getModelTable(), $this->getFieldIdName().'='.intval($this->getId())); + if(!$res) + { + $this->_db_errno = $sql->getLastErrorNumber(); + $this->_db_errmsg = $sql->getLastErrorText(); + if($this->_db_errno) + { + $this->addMessageError('SQL Delete Error', $session_messages); //TODO - Lan + $this->addMessageDebug('SQL Error #'.$this->_db_errno.': '.$sql->getLastErrorText()); + } + } + + return $res; + } } /** * Model collection handler */ -class e_tree_model extends e_model +class e_tree_model extends e_front_model { /** * Current model DB table, used in all db calls @@ -2229,7 +2380,7 @@ class e_tree_model extends e_model return $this; } - + /** * Unset all current data * @return e_tree_model @@ -2239,54 +2390,54 @@ class e_tree_model extends e_model $this->remove('__tree'); return $this; } - + public function isCacheEnabled() { return (null !== $this->getCacheString()); } - + public function getCacheString() { return $this->_cache_string; } - + protected function _setCacheData() { if(!$this->isCacheEnabled()) { return $this; } - + e107::getCache()->set_sys( - $this->getCacheString(true), - $this->toString(false, null, $this->getParam('nocount') ? false : true), - $this->_cache_force, + $this->getCacheString(true), + $this->toString(false, null, $this->getParam('nocount') ? false : true), + $this->_cache_force, false ); return $this; } - + protected function _loadFromArray($array) { - if(isset($array['total'])) + if(isset($array['total'])) { $this->setTotal((integer) $array['total']); unset($array['total']); } $class_name = $this->getParam('model_class', 'e_model'); $tree = array(); - foreach ($array as $id => $data) + foreach ($array as $id => $data) { $tree[$id] = new $class_name($data); $this->_onLoad($tree[$id]); } - + $this->setTree($tree, true); } - + /** * Additional on load logic to be set from subclasses - * + * * @param e_model $node * @return e_tree_model */ @@ -2312,29 +2463,29 @@ class e_tree_model extends e_model { $this->unsetTree() ->_clearCacheData(); - + $this->_total = false; } - - $cached = $this->_getCacheData(); + + $cached = $this->_getCacheData(); if($cached !== false) { $this->_loadFromArray($cached); return $this; } - + $class_name = $this->getParam('model_class', 'e_model'); // auto-load all if(!$this->getParam('db_query') && $this->getModelTable()) { $this->setParam('db_query', 'SELECT'.(!$this->getParam('nocount') ? ' SQL_CALC_FOUND_ROWS' : '').' * FROM #'.$this->getModelTable()); } - + if($this->getParam('db_query') && $class_name && class_exists($class_name)) { $sql = e107::getDb(); $this->_total = $sql->total_results = false; - + if($sql->db_Select_gen($this->getParam('db_query'))) { $this->_total = is_integer($sql->total_results) ? $sql->total_results : false; //requires SQL_CALC_FOUND_ROWS in query - see db handler @@ -2356,7 +2507,7 @@ class e_tree_model extends e_model unset($tmp); } - + if($sql->getLastErrorNumber()) { // TODO - admin log? @@ -2368,7 +2519,7 @@ class e_tree_model extends e_model { $this->_setCacheData(); } - + } return $this; } @@ -2453,7 +2604,7 @@ class e_tree_model extends e_model { return $this->has('__tree'); } - + /** * Render model data, all 'sc_*' methods will be recongnized * as shortcodes. @@ -2467,7 +2618,7 @@ class e_tree_model extends e_model { $ret = ''; $i == 1; - foreach ($this->getTree() as $model) + foreach ($this->getTree() as $model) { if($eVars) $eVars->treeCounter = $i; $ret .= $model->toHTML($template, $parsesc, $eVars); @@ -2490,12 +2641,12 @@ class e_tree_model extends e_model public function toArray($total = false) { $ret = array(); - foreach ($this->getTree() as $id => $model) + foreach ($this->getTree() as $id => $model) { $ret[$id] = $model->toArray(); } if($total) $ret['total'] = $this->getTotal(); - + return $ret; } @@ -2515,9 +2666,17 @@ class e_tree_model extends e_model } return (string) e107::getArrayStorage()->WriteArray($this->toArray($total), $AddSlashes); } + + public function update() + { + } + + public function delete() + { + } } -class e_admin_tree_model extends e_tree_model +class e_front_tree_model extends e_tree_model { /** * @var integer Last SQL error number @@ -2561,53 +2720,6 @@ class e_admin_tree_model extends e_tree_model return $this->hasSqlError(); } - /** - * Batch Delete records - * @param mixed $ids - * @param boolean $destroy [optional] destroy object instance after db delete - * @param boolean $session_messages [optional] - * @return integer deleted records number or false on DB error - */ - public function delete($ids, $destroy = true, $session_messages = false) - { - if(!$ids) return 0; - - if(!is_array($ids)) - { - $ids = explode(',', $ids); - } - - $ids = array_map('intval', $ids); - $idstr = implode(', ', $ids); - - $sql = e107::getDb(); - $res = $sql->db_Delete($this->getModelTable(), $this->getFieldIdName().' IN ('.$idstr.')'); - $this->_db_errno = $sql->getLastErrorNumber(); - $this->_db_errmsg = $sql->getLastErrorText(); - if(!$res) - { - if($sql->getLastErrorNumber()) - { - $this->addMessageError('SQL Delete Error', $session_messages); //TODO - Lan - $this->addMessageDebug('SQL Error #'.$sql->getLastErrorNumber().': '.$sql->getLastErrorText()); - } - } - elseif($destroy) - { - foreach ($ids as $id) - { - if($this->hasNode($id)) - { - $this->getNode($id)->setMessages($session_messages); - call_user_func(array($this->getNode(trim($id)), 'destroy')); // first call model destroy method if any - $this->setNode($id, null); - } - } - } - - return $res; - } - /** * Batch update tree records/nodes * @param string $field field name @@ -2666,6 +2778,58 @@ class e_admin_tree_model extends e_tree_model ->setMessages($session_messages); } } + return $res; + } +} + +class e_admin_tree_model extends e_front_tree_model +{ + + + /** + * Batch Delete records + * @param mixed $ids + * @param boolean $destroy [optional] destroy object instance after db delete + * @param boolean $session_messages [optional] + * @return integer deleted records number or false on DB error + */ + public function delete($ids, $destroy = true, $session_messages = false) + { + if(!$ids) return 0; + + if(!is_array($ids)) + { + $ids = explode(',', $ids); + } + + $ids = array_map('intval', $ids); + $idstr = implode(', ', $ids); + + $sql = e107::getDb(); + $res = $sql->db_Delete($this->getModelTable(), $this->getFieldIdName().' IN ('.$idstr.')'); + $this->_db_errno = $sql->getLastErrorNumber(); + $this->_db_errmsg = $sql->getLastErrorText(); + if(!$res) + { + if($sql->getLastErrorNumber()) + { + $this->addMessageError('SQL Delete Error', $session_messages); //TODO - Lan + $this->addMessageDebug('SQL Error #'.$sql->getLastErrorNumber().': '.$sql->getLastErrorText()); + } + } + elseif($destroy) + { + foreach ($ids as $id) + { + if($this->hasNode($id)) + { + $this->getNode($id)->setMessages($session_messages); + call_user_func(array($this->getNode(trim($id)), 'destroy')); // first call model destroy method if any + $this->setNode($id, null); + } + } + } + return $res; } } \ No newline at end of file diff --git a/e107_handlers/user_model.php b/e107_handlers/user_model.php index 4bbaeff6e..bc9e01d52 100644 --- a/e107_handlers/user_model.php +++ b/e107_handlers/user_model.php @@ -12,151 +12,75 @@ * $Id$ */ - /** - * @package e107 - * @category user - * @version $Id$ - * @author SecretR - * - * Front-end User Models - */ - -if (!defined('e107_INIT')) { exit; } - /** - * e_model abstract extension candidate (model_class.php) - * TODO - e_model & e_admin_model need refactoring, make e_admin_model extension of e_front_model - * We need DB interface, data validation, data security, etc. on front-end in most cases, - * the only way is additional class between e_model and e_admin_model (to avoid code duplication) + * @package e107 + * @category user + * @version $Id$ + * @author SecretR + * + * Front-end User Models */ -class e_front_model extends e_model + +if (!defined('e107_INIT')) { - /** - * Field type definitions - * @var array - */ - protected $_posted_data = array(); - - /** - * Get stored non-trusted data - * @param string $field - * @param mixed $default - * @return mixed - */ - public function getPosted($field = null, $default = null) - { - if(null === $field) return e107::getParser()->post_toForm($this->_posted_data); - if(isset($this->_posted_data[$field])) - { - return e107::getParser()->post_toForm($this->_posted_data[$field]); - } - return $default; - } - - /** - * Get non-trusted data if present, else model data - * @param string $field - * @param mixed $default - * @return mixed - */ - public function getIfPosted($field, $default = null) - { - $posted = $this->getPosted($field); - if(null === $posted) - { - return $this->get($field, $default); - } - return e107::getParser()->post_toForm($posted); - } - - /** - * Set non-trusted data - * @param string $field - * @param mixed $value - * @return e_user_model - */ - public function setPosted($field, $value = null) - { - if(is_array($field)) - { - $this->_posted_data = $field; - } - else $this->_posted_data[$field] = $value; - return $this; - } - - public function unsetPosted($field) - { - if(null === $field) $this->_posted_data = array(); - else unset($this->_posted_data[$field]); - return $this; - } - /** - * Try to merge posted data with current user data - * TODO - validate first - */ - final protected function mergePosted() - { - $this->setFieldTypeDefs(false); - $error = false; - foreach ($this->_posted_data as $field => $value) - { - if(!$this->isWritable($field) || !isset($this->_FIELD_TYPES[$field])) continue; - - if($this->sanitize($this->_FIELD_TYPES[$field], $value)) - { - $this->set($field, $value); - } - else - { - $error = true; - $this->addMessageError($field.': TODO message errors'); - } - } - - return $error; - } - - public function sanitize($type, &$value) - { - $tp = e107::getParser(); - switch ($type) - { - case 'int': - case 'integer': - $value = intval($this->toNumber($value)); - return true; - break; - - case 'str': - case 'string': - $value = $tp->toDB($value); - return true; - break; - - case 'float': - $value = $this->toNumber($value); - return true; - break; - - case 'bool': - case 'boolean': - $value = ($value ? true : false); - return true; - break; - - case 'null': - $value = ($value ? $tp->toDB($value) : null); - return true; - break; - } - - return false; - } + exit; } class e_user_model extends e_front_model { + /** + * Describes all model data, used as _FIELD_TYPE array as well + * @var array + */ + protected $_data_fields = array( + 'user_id' => 'integer', + 'user_name' => 'string', + 'user_loginname' => 'string', + 'user_customtitle' => 'string', + 'user_password' => 'string', + 'user_sess' => 'string', + 'user_email' => 'string', + 'user_signature' => 'string', + 'user_image' => 'string', + 'user_hideemail' => 'integer', + 'user_join' => 'integer', + 'user_lastvisit' => 'integer', + 'user_currentvisit' => 'integer', + 'user_lastpost' => 'integer', + 'user_chats' => 'integer', + 'user_comments' => 'integer', + 'user_ip' => 'string', + 'user_ban' => 'integer', + 'user_prefs' => 'string', + 'user_visits' => 'integer', + 'user_admin' => 'integer', + 'user_login' => 'string', + 'user_class' => 'string', + 'user_perms' => 'string', + 'user_realm' => 'string', + 'user_pwchange' => 'integer', + 'user_xup' => 'string', + ); + + /** + * Validate required fields + * @var array + */ + protected $_validation_rules = array( + 'user_name' => array('string', '1', 'LAN_USER_01', 'LAN_USER_HELP_01'), // TODO - regex + 'user_loginname' => array('string', '1', 'LAN_USER_02', 'LAN_USER_HELP_02'), // TODO - regex + 'user_password' => array('string', '5', 'LAN_USER_05', 'LAN_USER_HELP_05'), // TODO - pref - modify it somewhere below + 'user_email' => array('email', '', 'LAN_USER_08', 'LAN_USER_HELP_08'), + ); + + /** + * Validate optional fields - work in progress, not working yet + * @var array + */ + protected $_optional_rules = array( + 'user_customtitle' => array('string', '1', 'LAN_USER_01'), // TODO - regex + ); + /** * @see e_model * @var string @@ -168,74 +92,68 @@ class e_user_model extends e_front_model * @var string */ protected $_field_id = 'user_id'; - - /** - * Field type definitions - * @var array - */ - protected $_FIELD_TYPES = array(); /** * @see e_model * @var string */ protected $_message_stack = 'user'; - + /** * Extended data - * + * * @var e_user_extended_model */ protected $_extended_model = null; - + /** * Extended structure - * + * * @var e_user_extended_structure */ protected $_extended_structure = null; - + /** * User model of current editor * @var e_user_model */ protected $_editor = null; - + /** * Always return integer - * + * * @see e107_handlers/e_model#getId() */ public function getId() { return (integer) parent::getId(); } - + final public function getAdminId() { return ($this->isAdmin() ? $this->getId() : false); } - + final public function getAdminName() { return ($this->isAdmin() ? $this->getValue('name') : ''); } - + final public function getAdminEmail() { return ($this->isAdmin() ? $this->getValue('email') : ''); } - + final public function getAdminPwchange() { return ($this->isAdmin() ? $this->getValue('pwchange') : ''); } - + final public function getAdminPerms() { return $this->getValue('perms'); } - + public function isCurrent() { return false; @@ -245,37 +163,37 @@ class e_user_model extends e_front_model { return ($this->getValue('admin') ? true : false); } - + final public function isMainAdmin() { return $this->checkAdminPerms('0'); } - + final public function isUser() { return ($this->getId() ? true : false); } - + public function hasEditor() { return null !== $this->_editor; } - + final protected function _setClassList($uid = '') { $this->_class_list = array(); - if($this->isUser()) + if ($this->isUser()) { - if($this->getValue('class')) + if ($this->getValue('class')) { $this->_class_list = explode(',', $this->getValue('class')); } $this->_class_list[] = e_UC_MEMBER; - if($this->isAdmin()) + if ($this->isAdmin()) { $this->_class_list[] = e_UC_ADMIN; } - if($this->isMainAdmin()) + if ($this->isMainAdmin()) { $this->_class_list[] = e_UC_MAINADMIN; } @@ -286,39 +204,41 @@ class e_user_model extends e_front_model } $this->_class_list[] = e_UC_READONLY; $this->_class_list[] = e_UC_PUBLIC; - + return $this; } - + final public function getClassList($toString = false) { - if(null === $this->_class_list) + if (null === $this->_class_list) { $this->_setClassList(); } return ($toString ? implode(',', $this->_class_list) : $this->_class_list); } - + final public function checkClass($class, $allowMain = true) { // FIXME - replace check_class() here return (($allowMain && $this->isMainAdmin()) || check_class($class, $this->getClassList(), 0)); } - + final public function checkAdminPerms($perm_str) { // FIXME - method to replace getperms() return ($this->isAdmin() && getperms($perm_str, $this->getAdminPerms())); } - + final public function checkEditorPerms($class = '') { - if(!$this->hasEditor()) return false; - + if (!$this->hasEditor()) + return false; + $editor = $this->getEditor(); - - if('' !== $class) return ($editor->isAdmin() && $editor->checkClass($class)); - + + if ('' !== $class) + return ($editor->isAdmin() && $editor->checkClass($class)); + return $editor->isAdmin(); } @@ -347,7 +267,7 @@ class e_user_model extends e_front_model $this->set($field, $value, true); return $this; } - + /** * Get User extended value * @@ -362,7 +282,7 @@ class e_user_model extends e_front_model /** * Set User extended value - * + * * @param string $field * @param mixed $value * @return e_user_model @@ -372,24 +292,24 @@ class e_user_model extends e_front_model $this->getExtendedModel()->setValue($field, $value); return $this; } - + /** * Get user extended model - * + * * @return e_user_extended_model */ public function getExtendedModel() { - if(null === $this->_extended_model) + if (null === $this->_extended_model) { $this->_extended_model = new e_user_extended_model($this); } return $this->_extended_model; } - + /** * Set user extended model - * + * * @param e_user_extended_model $extended_model * @return e_user_model */ @@ -398,7 +318,7 @@ class e_user_model extends e_front_model $this->_extended_model = $extended_model; return $this; } - + /** * Get current user editor model * @return e_user_model @@ -407,7 +327,7 @@ class e_user_model extends e_front_model { return $this->_editor; } - + /** * Get current user editor model * @return e_user_model @@ -417,7 +337,7 @@ class e_user_model extends e_front_model $this->_editor = $user_model; return $this; } - + /** * Check if passed field is writable * @param string $field @@ -425,24 +345,25 @@ class e_user_model extends e_front_model */ public function isWritable($field) { - if(!is_string($field)) return true; + if (!is_string($field)) + return true; return !in_array($field, array($this->getFieldIdName(), 'user_admin', 'user_perms')); } /** * Set current object as a target - * + * * @return e_user_model */ protected function setAsTarget() { - e107::setRegistry('targets/core/user/'.$this->getId() , $this); + e107::setRegistry('targets/core/user/'.$this->getId(), $this); return $this; } /** * Clear registered target - * + * * @return e_user_model */ protected function clearTarget() @@ -457,44 +378,56 @@ class e_user_model extends e_front_model public function load($user_id = 0, $force = false) { parent::load($user_id, $force); - if($this->getId()) + if ($this->getId()) { // no errors - register $this->setAsTarget() ->setEditor(e107::getUser()); //set current user as default editor } } - + /** * Send model data to DB */ - public function save() + public function save($force = false, $session = false) { - if(!$this->getId()) - { - return false; // TODO - message - } - if(!$this->checkEditorPerms()) + if (!$this->checkEditorPerms()) { return false; // TODO - message, admin log - } - - if($this->mergePosted() && $this->data_has_changed) - { - $update['data'] = $this->getData(); - $upate['WHERE'] = $this->getFieldIdName().'='.$this->getId(); - $upate['_FIELD_TYPES'] = $this->getFieldTypes(); - - return e107::getDb()->db_Update($this->getModelTable(), $upate); } - return 0; + + // TODO - do the save manual in this order: validate() on user model, save() on extended fields, save() on user model + $ret = parent::save(true, $force, $session); + if(false !== $ret && null !== $this->_extended_model) // don't load extended fields if not already used + { + $ret_e = $this->_extended_model->save($force, $session); + if(false !== $ret_e) + { + return ($ret_e + $ret); + } + return false; + } + return $ret; } - + + public function saveDebug($extended = true, $return = false, $undo = true) + { + $ret = array(); + $ret['CORE_FIELDS'] = parent::saveDebug(true, $undo); + if($extended && null !== $this->_extended_model) + { + $ret['EXTENDED_FIELDS'] = $this->_extended_model->saveDebug(true, $undo); + } + + if($return) return $ret; + print_a($ret); + } + public function destroy() { $this->clearTarget() ->removeData(); - if(null !== $this->_extended_model) + if (null !== $this->_extended_model) { $this->_extended_model->destroy(); } @@ -506,23 +439,31 @@ class e_system_user extends e_user_model { /** * Constructor - * + * * @param array $user_data trusted data, loaded from DB * @return void */ public function __construct($user_data = array()) { - if($user_data) + if ($user_data) { $this->_data = $user_data; $this->setEditor(e107::getUser()); } } - + + /** + * Returns always false + * Even if user data belongs to the current user, Current User interface + * is not available + * + * @return boolean + */ final public function isCurrent() { // check against current system user - return ($this->getId() && $this->getId() == e107::getUser()->getId()); + //return ($this->getId() && $this->getId() == e107::getUser()->getId()); + return false; } } @@ -531,13 +472,13 @@ class e_system_user extends e_user_model * @author SecretR */ class e_user extends e_user_model -{ +{ public function __construct() { // reference to self - $this->setEditor($this); + $this->load()->setEditor($this); } - + /** * Yes, it's current user - return always true * NOTE: it's not user check, use isUser() instead! @@ -547,18 +488,18 @@ class e_user extends e_user_model { return true; } - + // TODO login by name/password, load, set cookie/session data final public function login($uname, $upass_plain, $uauto = false, $uchallange = false) { - // FIXME - rewrite userlogin - clean up redirects and + // FIXME - rewrite userlogin - clean up redirects and //$userlogin = new userlogin($uname, $upass_plain, $uauto, $uchallange); // if($userlogin->getId()) $this->load() --> use the previously set user COOKIE/SESSION data return $this->isUser(); } - + /** - * + * * @return unknown_type */ protected function initConstants() @@ -566,22 +507,22 @@ class e_user extends e_user_model //FIXME - BC - constants from init_session() should be defined here //init_session(); // the old way } - + /** * TODO destroy cookie/session data, self destroy * @return void */ final public function logout() { - // FIXME - destoy cookie/session data first + // FIXME - destoy cookie/session data first $this->_data = array(); - if(null !== $this->_extended_model) + if (null !== $this->_extended_model) { $this->_extended_model->destroy(); } e107::setRegistry('targets/core/current_user', null); } - + /** * TODO load user data by cookie/session data * @return e_user @@ -590,15 +531,17 @@ class e_user extends e_user_model { // init_session() should come here // $this->initConstants(); - called after data is loaded - + // FIXME - temporary here, for testing only!!! - if(USER) $this->setData(get_user_data(USERID)); + + if (USER) + $this->setData(get_user_data(USERID)); return $this; } - + /** * Not allowed - * + * * @return e_user_model */ final protected function setAsTarget() @@ -608,22 +551,31 @@ class e_user extends e_user_model /** * Not allowed - * + * * @return e_user_model */ final protected function clearTarget() { return $this; } - + public function destroy() { // not allowed - see logout() } } -class e_user_extended_model extends e_model +class e_user_extended_model extends e_front_model { + /** + * Describes known model fields + * @var array + */ + protected $_data_fields = array( + 'user_extended_id' => 'integer', + 'user_hidden_fields' => 'string', + ); + /** * @see e_model * @var string @@ -641,30 +593,30 @@ class e_user_extended_model extends e_model * @var string */ protected $_message_stack = 'user'; - + /** * @var e_user_extended_structure_tree */ protected $_structure = null; - + /** * User model, the owner of extended fields model * @var e_user_model */ protected $_user = null; - + /** * User model * @var e_user_model */ protected $_editor = null; - + /** * Stores access classes and default value per custom field * @var array */ protected $_struct_index = array(); - + /** * Constructor * @param e_user_model $user_model @@ -674,9 +626,9 @@ class e_user_extended_model extends e_model { $this->setUser($user_model) ->setEditor(e107::getUser()) // current by default - ->load(); + ->load(); } - + /** * Get user model * @return e_user_model @@ -685,7 +637,7 @@ class e_user_extended_model extends e_model { return $this->_user; } - + /** * Set User model * @param $user_model @@ -696,7 +648,7 @@ class e_user_extended_model extends e_model $this->_user = $user_model; return $this; } - + /** * Get current user editor model * @return e_user_model @@ -705,7 +657,7 @@ class e_user_extended_model extends e_model { return $this->_editor; } - + /** * Get current user editor model * @return e_user_model @@ -715,7 +667,7 @@ class e_user_extended_model extends e_model $this->_editor = $user_model; return $this; } - + /** * Get User extended field value * Returns NULL when field/default value not found or not enough permissions @@ -724,8 +676,9 @@ class e_user_extended_model extends e_model */ public function getValue($field) { - $field = 'user_'.$field; - if(!$this->checkRead($field)) return null; + $field = 'user_'.$field; + if (!$this->checkRead($field)) + return null; return $this->get($field, $this->getDefault($field)); } @@ -739,11 +692,12 @@ class e_user_extended_model extends e_model public function setValue($field, $value) { $field = 'user_'.$field; - if(!$this->checkWrite($field)) return $this; + if (!$this->checkWrite($field)) + return $this; $this->set($field, $value, true); return $this; } - + /** * Get default field value, defined by extended field structure * Returns NULL if field/default value not found @@ -754,7 +708,7 @@ class e_user_extended_model extends e_model { return varset($this->_struct_index[$field]['default'], null); } - + /** * Check field read permissions against current editor * @param string $field @@ -764,7 +718,7 @@ class e_user_extended_model extends e_model { return $this->getEditor()->checkClass(varset($this->_struct_index[$field]['read'])); } - + /** * Check field write permissions * @param string $field @@ -774,7 +728,7 @@ class e_user_extended_model extends e_model { return $this->getEditor()->checkClass(varset($this->_struct_index[$field]['write'])); } - + /** * Check field signup permissions * @param string $field @@ -784,7 +738,7 @@ class e_user_extended_model extends e_model { return $this->getEditor()->checkClass(varset($this->_struct_index[$field]['signup'])); } - + /** * Check field applicable permissions * @param string $field @@ -794,20 +748,21 @@ class e_user_extended_model extends e_model { return $this->getEditor()->checkClass(varset($this->_struct_index[$field]['applicable'])); } - + /** * @see e_model#load($id, $force) * @return e_user_extended_model */ public function load($force = false) { - if($this->getId() && !$force) return $this; - + if ($this->getId() && !$force) + return $this; + parent::load($this->getUser()->getId(), $force); $this->_loadAccess(); return $this; } - + /** * Load extended fields permissions once (performance) * @return e_user_extended_model @@ -815,37 +770,100 @@ class e_user_extended_model extends e_model protected function _loadAccess() { $struct_tree = $this->getExtendedStructure(); - if($this->getId() && $struct_tree->hasTree()) - { + if (/*$this->getId() && */$struct_tree->hasTree()) + { // load structure dependencies $ignore = array($this->getFieldIdName(), 'user_hidden_fields'); // TODO - user_hidden_fields? Old? $fields = $struct_tree->getTree(); - foreach ($fields as $id => $field) + foreach ($fields as $id => $field) { - if(!in_array($field->getValue('name'), $ignore)) + if (!in_array($field->getValue('name'), $ignore)) { $this->_struct_index['user_'.$field->getValue('name')] = array( - 'read' => $field->getValue('read'), - 'write' => $field->getValue('write'), - 'signup' => $field->getValue('signup'), - 'apply' => $field->getValue('applicable'), - 'default' => $field->getValue('default'), + 'read' => $field->getValue('read'), + 'write' => $field->getValue('write'), + 'signup' => $field->getValue('signup'), + 'apply' => $field->getValue('applicable'), + 'default' => $field->getValue('default'), ); } } } return $this; } - + + /** + * Build manage rules for single field + * @param $structure_model + * @return e_user_extended_model + */ + protected function _buildManageField(e_user_extended_structure_model $structure_model) + { + $ftype = $structure_model->getValue('type') == 6 ? 'integer' : 'string'; + + // 0- field control (html) attributes;1 - regex; 2 - validation error msg; + $parms = explode('^,^', $structure_model->getValue('parms')); + + // validaton rules + $vtype = $parms[1] ? 'regex' : $ftype; + $this->setValidationRule($structure_model->getValue('name'), array($vtype, $parms[1], $structure_model->getValue('text'), $parms[2]), $structure_model->getValue('required')); + + // data type, required for sql query + $this->_data_fields[$structure_model->getValue('name')] = $ftype; + return $this; + } + + /** + * Build manage rules for single field + * @param $structure_model + * @return e_user_extended_model + */ + protected function _buildManageRules() + { + $struct_tree = $this->getExtendedStructure(); + if ($this->getId() && $struct_tree->hasTree()) + { + // load structure dependencies TODO protected fields check as method + $ignore = array($this->getFieldIdName(), 'user_hidden_fields'); // TODO - user_hidden_fields? Old? + $fields = $struct_tree->getTree(); + foreach ($fields as $id => $field) + { + if (!in_array($field->getValue('name'), $ignore)) + { + // build _data_type and rules + $this->_buildManageField($field); + } + } + } + return $this; + } + /** * Get extended structure tree * @return e_user_extended_structure_tree */ public function getExtendedStructure() { - if(null === $this->_structure) $this->_structure = e107::getUserStructure(); + if (null === $this->_structure) + $this->_structure = e107::getUserStructure(); return $this->_structure; } + + /** + * Build data types and rules on the fly and save + * @see e107_handlers/e_front_model#save($from_post, $force, $session_messages) + */ + public function save($force = false, $session = false) + { + $this->_buildManageRules(); + return parent::save(true, $force, $session); + } + + public function saveDebug($retrun = false, $undo = true) + { + $this->_buildManageRules(); + parent::saveDebug($return, $undo); + } } class e_user_extended_structure_model extends e_model @@ -855,19 +873,19 @@ class e_user_extended_structure_model extends e_model * @var string */ protected $_db_table = 'user_extended_struct'; - + /** * @see e_model * @var string */ protected $_field_id = 'user_extended_struct_id'; - + /** * @see e_model * @var string */ protected $_message_stack = 'user_struct'; - + /** * Get User extended structure field value * @@ -883,7 +901,7 @@ class e_user_extended_structure_model extends e_model /** * Set User extended structure field value - * + * * @param string $field * @param mixed $value * @return e_user_model @@ -894,7 +912,7 @@ class e_user_extended_structure_model extends e_model $this->set($field, $value, false); return $this; } - + /** * Loading of single structure row not allowed for front model */ @@ -911,36 +929,36 @@ class e_user_extended_structure_tree extends e_tree_model * @var string */ protected $_db_table = 'user_extended_struct'; - + /** * @see e_model * @var string */ protected $_field_id = 'user_extended_struct_id'; - + /** * @see e_model * @var string */ protected $_message_stack = 'user'; - + /** * @var string */ protected $_cache_string = 'nomd5_user_extended_struct'; - + /** * Force system cache (cache used even if disabled by site admin) * @var boolen */ protected $_cache_force = true; - + /** * Force system cache (cache used even if disabled by site admin) * @var boolen */ protected $_name_index = true; - + /** * Constructor - auto-load * @return void @@ -949,29 +967,29 @@ class e_user_extended_structure_tree extends e_tree_model { $this->load(); } - + public function getNodeByName($name) { - if($this->isNodeName($name)) + if ($this->isNodeName($name)) { return $this->getNode($this->getNodeId($name)); } return null; } - + public function isNodeName($name) { return (isset($this->_name_index[$name]) && $this->isNode($this->_name_index[$name])); } - + public function getNodeId($name) { return $this->_name_index[$name]; } - + /** * Load tree data - * + * * @param boolean $force */ public function load($force = false) @@ -979,10 +997,10 @@ class e_user_extended_structure_tree extends e_tree_model $this->setParam('nocount', true) ->setParam('model_class', 'e_user_extended_structure_model'); parent::load($force); - + return $this; } - + /** * Build name index on load * @param e_user_extended_structure_model $model @@ -992,4 +1010,4 @@ class e_user_extended_structure_tree extends e_tree_model $this->_name_index['user_'.$model->getValue('name')] = $model->getId(); return $this; } -} \ No newline at end of file +} diff --git a/e107_handlers/validator_class.php b/e107_handlers/validator_class.php index 74245b247..abd1cce76 100644 --- a/e107_handlers/validator_class.php +++ b/e107_handlers/validator_class.php @@ -655,14 +655,6 @@ class e_validator return false; } - if('varchar' == $type && !varset($tmp[1])) $tmp[1] = 255; - - if(is_numeric(varset($tmp[1])) && (integer) $tmp[1] < $length) - { - $this->addValidateResult($name, self::ERR_TOO_LONG); - return false; - } - if(!($value[0] && $value[1] && $value[0] == $value[1])) { $this->addValidateResult($name, self::ERR_FIELDS_MATCH); diff --git a/e107_languages/English/lan_user.php b/e107_languages/English/lan_user.php index cf81d298c..e5b7ba0ec 100644 --- a/e107_languages/English/lan_user.php +++ b/e107_languages/English/lan_user.php @@ -117,6 +117,7 @@ define('LAN_USER_86', 'Maximum avatar size is --WIDTH-- x --HEIGHT-- pixels'); // Error messages for when user data is missing. Done this way so that other code can override the default messages +// FIXME - do we need this? if (!defined('USER_ERR_01')) { define('USER_ERR_01','Missing value'); } if (!defined('USER_ERR_02')) { define('USER_ERR_02','Unexpected value'); } if (!defined('USER_ERR_03')) { define('USER_ERR_03','Value contains invalid characters'); }