ConfigMappings * StatusField -> StatusFields * PermSection -> PermSections */ /** * @method Array getFilterMenu(mixed $default = false) * @method kUnitConfig setFilterMenu(Array $value) * * @method Array getConfigMapping(mixed $default = false) * @method kUnitConfig setConfigMapping(Array $value) * * * @method string getModuleFolder(mixed $default = false) * @method kUnitConfig setModuleFolder(string $value) * * @method string getBasePath(mixed $default = false) * @method kUnitConfig setBasePath(string $value) * * @method Array getEventHandlerClass(mixed $default = false) * @method kUnitConfig setEventHandlerClass(Array $value) * * @method Array getTagProcessorClass(mixed $default = false) * @method kUnitConfig setTagProcessorClass(Array $value) * * @method Array getItemClass(mixed $default = false) * @method kUnitConfig setItemClass(Array $value) * * @method Array getListClass(mixed $default = false) * @method kUnitConfig setListClass(Array $value) * * @method Array getValidatorClass(mixed $default = false) * @method kUnitConfig setValidatorClass(Array $value) * * @method Array getQueryString(mixed $default = false) * @method kUnitConfig setQueryString(Array $value) * * @method string getPermItemPrefix(mixed $default = false) * @method kUnitConfig setPermItemPrefix(string $value) * * @method string getPermTabText(mixed $default = false) * @method kUnitConfig setPermTabText(string $value) * * @method Array getPermSection(mixed $default = false) * @method kUnitConfig setPermSection(Array $value) * * @method bool getAutoLoad(mixed $default = false) * @method kUnitConfig setAutoLoad(bool $value) * * @method string getIDField(mixed $default = false) * @method kUnitConfig setIDField(string $value) * * @method string getTableName(mixed $default = false) * @method kUnitConfig setTableName(string $value) * * @method string getCustomDataTableName(mixed $default = false) * @method kUnitConfig setCustomDataTableName(string $value) * * @method kUnitConfig setStatusField(Array $value) * * @method string getTitleField(mixed $default = false) * @method kUnitConfig setTitleField(string $value) * * @method string getOrderField(mixed $default = false) * @method kUnitConfig setOrderField(string $value) * * @method string getOwnerField(mixed $default = false) * @method kUnitConfig setOwnerField(string $value) * * @method int getConfigPriority(mixed $default = false) * @method kUnitConfig setConfigPriority(int $value) * * @method bool getCatalogItem(mixed $default = false) * @method kUnitConfig setCatalogItem(bool $value) * * @method string getCatalogSelectorName(mixed $default = false) * @method kUnitConfig setCatalogSelectorName(string $value) * * @method string getAdminTemplatePath(mixed $default = false) * @method kUnitConfig setAdminTemplatePath(string $value) * * @method string getAdminTemplatePrefix(mixed $default = false) * @method kUnitConfig setAdminTemplatePrefix(string $value) * * @method string getSearchConfigPostfix(mixed $default = false) * @method kUnitConfig setSearchConfigPostfix(string $value) * * @method string getTitlePhrase(mixed $default = false) * @method kUnitConfig setTitlePhrase(string $value) * * @method int getItemType(mixed $default = false) * @method kUnitConfig setItemType(int $value) * * @method Array getStatisticsInfo(mixed $default = false) * @method kUnitConfig setStatisticsInfo(Array $value) * * @method string getViewMenuPhrase(mixed $default = false) * @method kUnitConfig setViewMenuPhrase(string $value) * * @method string getCatalogTabIcon(mixed $default = false) * @method kUnitConfig setCatalogTabIcon(string $value) * * @method bool getCacheModRewrite(mixed $default = false) * @method kUnitConfig setCacheModRewrite(bool $value) * * @method kUnitConfig setParentTableKey(mixed $value) * * @method kUnitConfig setForeignKey(mixed $value) * * @method string getConstrain(mixed $default = false) * @method kUnitConfig setConstrain(string $value) * * @method bool getAutoDelete(mixed $default = false) * @method kUnitConfig setAutoDelete(bool $value) * * @method bool getAutoClone(mixed $default = false) * @method kUnitConfig setAutoClone(bool $value) * * @method string getParentPrefix(mixed $default = false) * @method kUnitConfig setParentPrefix(string $value) * * @method bool getCheckSimulatniousEdit(mixed $default = false) * @method kUnitConfig setCheckSimulatniousEdit(bool $value) * * @method bool getPortalStyleEnv(mixed $default = false) * @method kUnitConfig setPortalStyleEnv(bool $value) * * @method bool getForceDontLogChanges(mixed $default = false) * @method kUnitConfig setForceDontLogChanges(bool $value) * * @method Array getUserProfileMapping(mixed $default = false) * @method kUnitConfig setUserProfileMapping(Array $value) * * @method bool getUsePendingEditing(mixed $default = false) * @method kUnitConfig setUsePendingEditing(bool $value) * * @method string getNavigationSelectClause(mixed $default = false) * @method kUnitConfig setNavigationSelectClause(string $value) * * @method bool getPopulateMlFields(bool $default = false) * @method kUnitConfig setPopulateMlFields(bool $value) * * @method bool getLogChanges(bool $default = false) * @method kUnitConfig setLogChanges(bool $value) * * @method int getFileCount(bool $default = false) * @method kUnitConfig setFileCount(int $value) * * @method int getImageCount(bool $default = false) * @method kUnitConfig setImageCount(int $value) * * @method string getDownloadHelperClass(bool $default = false) * @method kUnitConfig setDownloadHelperClass(string $value) * * @method string getSectionPrefix(bool $default = false) * @method kUnitConfig setSectionPrefix(string $value) * * @method bool getSiteConfigProcessed(bool $default = false) * @method kUnitConfig setSiteConfigProcessed(bool $value) * * * @method Array getRegisterClasses(mixed $default = false) * @method kUnitConfig setRegisterClasses(Array $value) * @method kUnitConfig addRegisterClasses(Array $value, string $name = null) * @method kUnitConfig removeRegisterClasses(string $name = null) * * @method Array getScheduledTasks(mixed $default = false) * @method Array getScheduledTaskByName(string $name, mixed $default = false) * @method kUnitConfig setScheduledTasks(Array $value) * @method kUnitConfig addScheduledTasks(Array $value, string $name = null) * @method kUnitConfig removeScheduledTasks(string $name = null) * * @method Array getTitlePresets(mixed $default = false) * @method Array getTitlePresetByName(string $name, mixed $default = false) * @method kUnitConfig setTitlePresets(Array $value) * @method kUnitConfig addTitlePresets(Array $value, string $name = null) * @method kUnitConfig removeTitlePresets(string $name = null) * * @method Array getSections(mixed $default = false) * @method Array getSectionByName(string $name, mixed $default = false) * @method kUnitConfig setSections(Array $value) * @method kUnitConfig addSections(Array $value, string $name = null) * @method kUnitConfig removeSections(string $name = null) * * @method Array getFields(mixed $default = false) * @method Array getFieldByName(string $name, mixed $default = false) * @method kUnitConfig setFields(Array $value) * @method kUnitConfig addFields(Array $value, string $name = null) * @method kUnitConfig removeFields(string $name = null) * * @method Array getVirtualFields(mixed $default = false) * @method Array getVirtualFieldByName(string $name, mixed $default = false) * @method kUnitConfig setVirtualFields(Array $value) * @method kUnitConfig addVirtualFields(Array $value, string $name = null) * @method kUnitConfig removeVirtualFields(string $name = null) * * @method Array getGrids(mixed $default = false) * @method Array getGridByName(string $name, mixed $default = false) * @method kUnitConfig setGrids(Array $value) * @method kUnitConfig addGrids(Array $value, string $name = null) * @method kUnitConfig removeGrids(string $name = null) * * @method Array getHooks(mixed $default = false) * @method kUnitConfig setHooks(Array $value) * @method kUnitConfig addHooks(Array $value, string $name = null) * @method kUnitConfig removeHooks(string $name = null) * * @method Array getAggregateTags(mixed $default = false) * @method kUnitConfig setAggregateTags(Array $value) * @method kUnitConfig addAggregateTags(Array $value, string $name = null) * @method kUnitConfig removeAggregateTags(string $name = null) * * @method Array getEditTabPresets(mixed $default = false) * @method Array getEditTabPresetByName(string $name, mixed $default = false) * @method kUnitConfig setEditTabPresets(Array $value) * @method kUnitConfig addEditTabPresets(Array $value, string $name = null) * @method kUnitConfig removeEditTabPresets(string $name = null) * * @method Array getSubItems(mixed $default = false) * @method kUnitConfig setSubItems(Array $value) * @method kUnitConfig addSubItems(string $value, string $name = null) * @method kUnitConfig removeSubItems(string $name = null) * * @method Array getCustomFields(mixed $default = false) * @method string getCustomFieldByName(string $name, mixed $default = false) * @method kUnitConfig setCustomFields(Array $value) * @method kUnitConfig addCustomFields(Array $value, string $name = null) * @method kUnitConfig removeCustomFields(string $name = null) * * @method Array getClones(mixed $default = false) * @method Array getCloneByName(string $name, mixed $default = false) * @method kUnitConfig setClones(Array $value) * @method kUnitConfig addClones(Array $value, string $name = null) * @method kUnitConfig removeClones(string $name = null) * * @method Array getProcessPrefixes(mixed $default = false) * @method kUnitConfig setProcessPrefixes(Array $value) * @method kUnitConfig addProcessPrefixes(string $value, string $name = null) * @method kUnitConfig removeProcessPrefixes(string $name = null) * * @method Array getForms(mixed $default = false) * @method Array getFormByName(string $name, mixed $default = false) * @method kUnitConfig setForms(Array $value) * @method kUnitConfig addForms(Array $value, string $name = null) * @method kUnitConfig removeForms(string $name = null) * * @method Array getReplacementTemplates(mixed $default = false) * @method string getReplacementTemplateByName(string $name, mixed $default = false) * @method kUnitConfig setReplacementTemplates(Array $value) * @method kUnitConfig addReplacementTemplates(string $value, string $name = null) * @method kUnitConfig removeReplacementTemplates(string $name = null) * * @method Array getItemPropertyMappings(mixed $default = false) * @method string getItemPropertyMappingByName(string $name, mixed $default = false) * @method kUnitConfig setItemPropertyMappings(Array $value) * @method kUnitConfig addItemPropertyMappings(string $value, string $name = null) * @method kUnitConfig removeItemPropertyMappings(string $name = null) * * @method Array getSectionAdjustments(mixed $default = false) * @method mixed getSectionAdjustmentByName(string $name, mixed $default = false) * @method kUnitConfig setSectionAdjustments(Array $value) * @method kUnitConfig addSectionAdjustments(mixed $value, string $name = null) * @method kUnitConfig removeSectionAdjustments(string $name = null) * * @method Array getImportKeys(mixed $default = false) * @method kUnitConfig setImportKeys(Array $value) * @method kUnitConfig addImportKeys(mixed $value, string $name = null) * @method kUnitConfig removeImportKeys(string $name = null) * * * @method Array getCalculatedFieldSpecials(mixed $default = Array ()) * @method Array getCalculatedFieldsBySpecial(mixed $special, mixed $default = Array ()) * @method kUnitConfig setCalculatedFieldsBySpecial(mixed $special, Array $value) * @method kUnitConfig addCalculatedFieldsBySpecial(mixed $special, mixed $value, string $name = null) * @method kUnitConfig removeCalculatedFieldsBySpecial(mixed $special, string $name = null) * * @method Array getAggregatedCalculatedFieldSpecials(mixed $default = Array ()) * @method Array getAggregatedCalculatedFieldsBySpecial(mixed $special, mixed $default = Array ()) * @method kUnitConfig setAggregatedCalculatedFieldsBySpecial(mixed $special, Array $value) * @method kUnitConfig addAggregatedCalculatedFieldsBySpecial(mixed $special, mixed $value, string $name = null) * @method kUnitConfig removeAggregatedCalculatedFieldsBySpecial(mixed $special, string $name = null) * * @method Array getListSQLSpecials(mixed $default = Array ()) * @method string getListSQLsBySpecial(mixed $special, mixed $default = Array ()) * @method kUnitConfig setListSQLsBySpecial(mixed $special, string $value) * @method kUnitConfig removeListSQLsBySpecial(mixed $special, string $name = null) * * @method Array getListSortingSpecials(mixed $default = Array ()) * @method Array getListSortingsBySpecial(mixed $special, mixed $default = Array ()) * @method kUnitConfig setListSortingsBySpecial(mixed $special, Array $value) * @method kUnitConfig addListSortingsBySpecial(mixed $special, mixed $value, string $name = null) * @method kUnitConfig removeListSortingsBySpecial(mixed $special, string $name = null) * * @method Array getItemSQLSpecials(mixed $default = Array ()) * @method string getItemSQLsBySpecial(mixed $special, mixed $default = Array ()) * @method kUnitConfig setItemSQLsBySpecial(mixed $special, string $value) * @method kUnitConfig removeItemSQLsBySpecial(mixed $special, string $name = null) */ class kUnitConfig { /** * Reference to global kApplication instance * * @var kApplication * @access protected */ protected $Application = null; /** * Connection to database * * @var IDBConnection * @access protected */ protected $Conn = null; /** * Unit config prefix * * @var string * @access protected */ protected $_prefix = ''; /** * Filename, where unit config is stored * * @var string * @access protected */ protected $_filename = ''; /** * Default unit config data * * @var Array * @access protected */ protected static $_defaults = Array ( 'ItemClass' => Array ('class' => 'kDBItem', 'file' => '', 'build_event' => 'OnItemBuild'), 'ListClass' => Array ('class' => 'kDBList', 'file' => '', 'build_event' => 'OnListBuild'), 'EventHandlerClass' => Array ('class' => 'kDBEventHandler', 'file' => '', 'build_event' => 'OnBuild'), 'TagProcessorClass' => Array ('class' => 'kDBTagProcessor', 'file' => '', 'build_event' => 'OnBuild'), 'AutoLoad' => true, 'QueryString' => Array ( 1 => 'id', 2 => 'Page', 3 => 'PerPage', 4 => 'event', 5 => 'mode', ), 'ListSQLs' => Array ( '' => ' SELECT %1$s.* %2$s FROM %1$s', ), 'Fields' => Array (), ); /** * Word endings, that are suffixed with "es" instead of just "s" during pluralisation * * @var string * @access protected */ protected static $_singularEndingsRegExp = '/(x|s|z|sh|ch)$/'; /** * Words, that ends with es/s, but are always singulars * * @var string * @access protected */ protected static $_alwaysSingularRegExp = '/(class|LogChanges|ForceDontLogChanges|PopulateMlFields)$/i'; /** * Unit config data * * @var Array * @access protected */ protected $_data = Array (); /** * Unit config settings that can have different values based on special * * @var Array * @access protected */ protected $_specialBased = Array ( 'CalculatedFields', 'AggregatedCalculatedFields', 'ListSQLs', 'ListSortings', 'ItemSQLs', ); /** * Unit config settings, that allow data to be added without a key * * @var Array * @access protected */ protected $_withoutKeys = Array ( 'RegisterClasses', 'Hooks', 'AggregateTags' ); /** * Dynamic method name, that was called * * @var string * @access protected */ protected $_currentMethodName = ''; /** * Arguments given to dynamic method name, that was called * * @var Array * @access protected */ protected $_currentArguments = Array (); /** * Creates new instance of kUnitConfig class * * @param string $prefix * @param Array $defaults * @param bool $use_global_defaults * @access public */ public function __construct($prefix, $defaults = null, $use_global_defaults = true) { $this->_prefix = $prefix; $merge_with = $use_global_defaults ? self::$_defaults : Array (); $this->_data = array_merge($merge_with, isset($defaults) ? $defaults : Array ()); $this->Application =& kApplication::Instance(); $this->Conn =& $this->Application->GetADODBConnection(); } /** * Sets filename, where unit config is stored * * @param string $filename * @return void * @access public */ public function setFilename($filename) { $this->_filename = $filename; } /** * Returns unit config prefix * * @return string * @access public */ public function getPrefix() { return $this->_prefix; } /** * Ensures, that only unit config data is saved when object is serialized * * @return Array * @access public */ public function __sleep() { return Array ('_prefix', '_data', 'Application', 'Conn'); } /** * Dumps unit config into a file * * @return void * @access public */ public function dump() { kUtil::print_r($this->_data, 'Unit Config', true); } /** * Returns unit config data in raw form * * @return Array * @access public */ public function getRaw() { return $this->_data; } /** * Processed dynamically created methods for changing unit config settings * * @param string $method_name * @param Array $arguments * @return mixed * @throws InvalidArgumentException * @throws RuntimeException * @access public */ public function __call($method_name, $arguments) { // === regular === // get{SettingName}() // set{SettingName}($value) // add{SettingName}s(string $value, string $name = null) // remove{SettingName}(string $name = null) // === by special === // get{SettingName}Specials() // get{SettingName}sBySpecial($special) // set{SettingName}BySpecial($special, $value) // add{SettingName}sBySpecial(string $special, Array $value, string $name = null) // remove{SettingName}sBySpecial(string $special, $name = null) if ( !preg_match('/^(get|set|add|remove)(.*?)(BySpecial|Specials|ByName)*$/', $method_name, $regs) ) { throw new RuntimeException('Unknown method ' . __CLASS__ . '::' . $this->_currentMethodName . ''); } $this->_currentMethodName = $method_name; $this->_currentArguments = $arguments; $to_call = '_process' . ucfirst($regs[1]); return $this->$to_call($regs[2], isset($regs[3]) ? $regs[3] : ''); } /** * Processes calls to "get*" methods * * @param string $setting_name * @param string $suffix * @return mixed * @access protected */ protected function _processGet($setting_name, $suffix = '') { $is_plural = $this->_isPluralSetting($setting_name); if ( $suffix == 'BySpecial' && $is_plural ) { // get{SettingName}BySpecial($special, $default = false) $this->_verifyArguments(Array ('special')); return $this->getSetting($setting_name, $this->_getDefaultValue(1, Array ()), $this->_currentArguments[0]); } elseif ( $suffix == 'Specials' && !$is_plural ) { // get{SettingName}Specials($default = Array ()) $result = $this->getSetting($this->_getPlural($setting_name), $this->_getDefaultValue(0, Array ())); return array_keys($result); } elseif ( $suffix == 'ByName' && !$is_plural ) { $sub_key = $this->_currentArguments[0]; $result = $this->getSetting($this->_getPlural($setting_name), Array ()); return isset($result[$sub_key]) ? $result[$sub_key] : $this->_getDefaultValue(1, false); } // get{SettingName}($default = false) return $this->getSetting($setting_name, $this->_getDefaultValue(0, false)); } /** * Returns default value from given argument or false, when not passed * * @param int $arg_index * @param mixed $default * @return bool * @access protected */ protected function _getDefaultValue($arg_index, $default = false) { return isset($this->_currentArguments[$arg_index]) ? $this->_currentArguments[$arg_index] : $default; } /** * Processes calls to "set*" methods * * @param string $setting_name * @param string $suffix * @return kUnitConfig * @access protected */ protected function _processSet($setting_name, $suffix = '') { $is_plural = $this->_isPluralSetting($setting_name); if ( $suffix == 'BySpecial' && $is_plural ) { // set{SettingName}BySpecial($special, $value) $this->_verifyArguments(Array ('special', 'value')); return $this->setSetting($setting_name, $this->_currentArguments[1], $this->_currentArguments[0]); } // set{SettingName}($value) $this->_verifyArguments(Array ('value')); return $this->setSetting($setting_name, $this->_currentArguments[0]); } /** * Processes calls to "add*" method * * @param string $setting_name * @param string $suffix * @return kUnitConfig * @access protected * @throws InvalidArgumentException */ protected function _processAdd($setting_name, $suffix = '') { $arguments = $this->_currentArguments; if ( !$this->_isPluralSetting($setting_name) ) { throw new InvalidArgumentException('Setting "' . $setting_name . '" isn\'t plural'); } if ( $suffix == 'BySpecial' ) { // add{SettingName}BySpecial(string $special, string $value, string $name = null) $this->_verifyArguments(Array ('special', 'value')); if ( isset($arguments[2]) ) { // add a single value $this->_addToSetting($this->_getSingular($setting_name), $arguments[1], $arguments[2], $arguments[0]); } else { // add multiple values $this->_addToSetting($setting_name, $arguments[1], null, $arguments[0]); } } else { // add{SettingName}(string $value, string $name = null) $this->_verifyArguments(Array ('value')); if ( isset($arguments[1]) ) { // add a single value $this->_addToSetting($this->_getSingular($setting_name), $arguments[0], $arguments[1]); } else { // add multiple value $this->_addToSetting($setting_name, $arguments[0], null); } } return $this; } /** * Adds a value to a setting * * @param string $name * @param mixed $value * @param string $array_key * @param string $special * @return kUnitConfig * @throws InvalidArgumentException */ protected function _addToSetting($name, $value, $array_key, $special = null) { if ( $this->_isPluralSetting($name) ) { // multiple values given - merge with current values if ( !is_array($value) ) { throw new InvalidArgumentException('Argument $value must be an array'); } $result = $this->getSetting($name, Array (), $special); $this->setSetting($name, array_merge($result, $value), $special); } else { // single value given $result = $this->getSetting($this->_getPlural($name), Array (), $special); if ( $this->_isWithoutKeySetting($name) ) { $result[] = $value; } else { $result[$array_key] = $value; } $this->setSetting($this->_getPlural($name), $result, $special); } return $this; } /** * Processes calls to "remove*" method * * @param string $setting_name * @param string $suffix * @return kUnitConfig * @access protected * @throws InvalidArgumentException */ protected function _processRemove($setting_name, $suffix = '') { $arguments = $this->_currentArguments; if ( !$this->_isPluralSetting($setting_name) ) { throw new InvalidArgumentException('Setting "' . $setting_name . '" isn\'t plural'); } if ( $suffix == 'BySpecial' ) { // remove{SettingName}BySpecial(string $special, string $name = null) $this->_verifyArguments(Array ('special')); if ( isset($arguments[1]) ) { // remove single value $this->_removeFromSetting($this->_getSingular($setting_name), $arguments[1], $arguments[0]); } else { // remove multiple value $this->_removeFromSetting($setting_name, null, $arguments[0]); } } else { // remove{SettingName}(string $name = null) if ( isset($arguments[0]) ) { // remove single value $this->_removeFromSetting($this->_getSingular($setting_name), $arguments[0]); } else { // remove multiple values $this->_removeFromSetting($setting_name, null); } } return $this; } /** * Removes a value from a setting * * @param string $name * @param string $array_key * @param string $special * @return kUnitConfig * @access protected * @throws RuntimeException */ protected function _removeFromSetting($name, $array_key = null, $special = null) { if ( $this->_isPluralSetting($name) ) { // remove multiple values if ( $this->getSetting($name, false, $special) !== false ) { $this->setSetting($name, null, $special); } } else { // remove single value if ( $this->_isWithoutKeySetting($name) ) { throw new RuntimeException('Unable to change setting without key'); } $result = $this->getSetting($this->_getPlural($name), false, $special); if ( $result !== false ) { unset($result[$array_key]); $this->setSetting($this->_getPlural($name), $result, $special); } } return $this; } /** * Verifies argument count given * * @param Array $argument_names * @return void * @access protected * @throws InvalidArgumentException */ protected function _verifyArguments($argument_names) { if ( count($this->_currentArguments) < count($argument_names) ) { throw new InvalidArgumentException('Method ' . __CLASS__ . '::' . $this->_currentMethodName . ' expects following arguments: $' . implode(', $', $argument_names) . ''); } } /** * Returns setting value by name and filter by special (if passed) * * @param string $name * @param mixed $default * @param string|kBase $special * @return mixed * @access public */ public function getSetting($name, $default = false, $special = null) { if ( in_array($name, $this->_specialBased) && isset($special) ) { $use_special = $this->_guessSpecial($name, $special); return isset($this->_data[$name][$use_special]) ? $this->_data[$name][$use_special] : $default; } return isset($this->_data[$name]) ? $this->_data[$name] : $default; } /** * Changes value of a setting * * @param string $name * @param mixed $value * @param string|kBase $special * @return kUnitConfig * @access public */ public function setSetting($name, $value, $special = null) { if ( in_array($name, $this->_specialBased) && isset($special) ) { if ( !isset($this->_data[$name]) ) { $this->_data[$name] = Array (); } $use_special = $this->_guessSpecial($name, $special); if ( !isset($value) ) { unset($this->_data[$name][$use_special]); } else { $this->_data[$name][$use_special] = $value; } } else { if ( !isset($value) ) { unset($this->_data[$name]); } else { $this->_data[$name] = $value; } } return $this; } /** * Detects settings, that accept arrays * * @param string $name * @return bool * @access protected */ protected function _isPluralSetting($name) { if ( preg_match(self::$_alwaysSingularRegExp, $name) ) { // simplified exceptions return false; } return preg_match('/(es|s)$/', $name); } /** * Detects anonymous settings * * @param string $name * @return bool * @access protected */ protected function _isWithoutKeySetting($name) { return in_array($this->_getPlural($name), $this->_withoutKeys); } /** * Returns plural form given word * * @param string $name * @return string * @access protected */ protected function _getPlural($name) { return preg_match(self::$_singularEndingsRegExp, $name) ? $name . 'es' : $name . 's'; } /** * Returns singular form of given word * * @param $name * @return mixed * @throws InvalidArgumentException */ protected function _getSingular($name) { if ( !$this->_isPluralSetting($name) ) { throw new InvalidArgumentException('Setting "' . $name . '" isn\'t plural'); } return preg_replace('/(es|s)$/', '', $name); } /** * Guesses special to be used by event * * @param string $setting_name * @param string|kBase $special * @return string * @access protected */ protected function _guessSpecial($setting_name, $special) { $use_special = $special instanceof kBase ? $special->Special : $special; $value = $this->getSetting($setting_name, Array ()); return isset($value[$use_special]) ? $use_special : ''; } /** * Adds new tab to existing edit tab preset * * @param string $preset_name * @param Array $value * @param string $name * @return kUnitConfig * @throws InvalidArgumentException * @access public */ public function addEditTabPresetTabs($preset_name, $value, $name = null) { $preset = $this->getEditTabPresetByName($preset_name, false); if ( $preset === false ) { throw new InvalidArgumentException('Edit tab preset "' . $preset_name . '" not defined in "' . $this->_prefix . '" unit config'); } if ( isset($name) ) { $preset[$name] = $value; } else { $preset = array_merge($preset, $value); } $this->addEditTabPresets($preset, $preset_name); return $this; } public function addGridFields($grid_name, $value, $name = null) { $grid = $this->getGridByName($grid_name, false); if ( $grid === false ) { throw new InvalidArgumentException('Grid "' . $grid_name . '" not defined in "' . $this->_prefix . '" unit config'); } if ( isset($name) ) { $grid['Fields'][$name] = $value; } else { $grid['Fields'] = array_merge($grid['Fields'], $value); } $this->addGrids($grid, $grid_name); return $this; } /** * Returns individual permission section * * @param string $name * @param Array $default * @return Array * @access public * @todo Rename setting to plural form and them remove this method */ public function getPermSectionByName($name, $default = Array ()) { $perm_sections = $this->getPermSection(Array ()); return isset($perm_sections[$name]) ? $perm_sections[$name] : $default; } /** * Returns foreign key by given prefix * * @param string $parent_prefix * @param mixed $default * @return string|bool * @access public */ public function getForeignKey($parent_prefix = null, $default = false) { return $this->_getSettingByPrefix('ForeignKey', $parent_prefix, $default); } /** * Returns parent table key by given prefix * * @param string $parent_prefix * @param mixed $default * @return string|bool * @access public */ public function getParentTableKey($parent_prefix = null, $default = false) { return $this->_getSettingByPrefix('ParentTableKey', $parent_prefix, $default); } /** * Returns value of a setting by prefix (special workaround for non-special settings) * * @param string $name * @param string $prefix * @param mixed $default * @return mixed * @access protected */ protected function _getSettingByPrefix($name, $prefix = null, $default = false) { $value = $this->getSetting($name, $default); if ( !is_array($value) || !isset($prefix) ) { return $value; } return isset($value[$prefix]) ? $value[$prefix] : $default; } /** * Returns status field with option to get first field only * * @param bool $first_only * @param mixed $default * @return mixed * @access public */ public function getStatusField($first_only = false, $default = false) { $value = $this->getSetting('StatusField', $default); return $first_only ? $value[0] : $value; } /** * Register necessary classes * This method should only process the data which is cached! * * @return void * @access public */ public function parse() { $this->_parseClasses(); $this->_parseScheduledTasks(); $this->_parseHooks(); $this->_parseAggregatedTags(); } protected function _parseClasses() { $register_classes = $this->_getClasses(); foreach ($register_classes as $class_info) { // Thanks to static class map there is no need to specify file during class registration. $this->Application->registerClass($class_info['class'], '', $class_info['pseudo']); if ( isset($class_info['build_event']) && $class_info['build_event'] && $class_info['build_event'] != 'OnBuild' ) { $this->Application->delayUnitProcessing('registerBuildEvent', Array ($class_info['pseudo'], $class_info['build_event'])); } } } protected function _getClasses() { $register_classes = $this->getRegisterClasses(); $class_params = Array ('ItemClass', 'ListClass', 'EventHandlerClass', 'TagProcessorClass'); foreach ($class_params as $param_name) { $value = $this->getSetting($param_name); if ( !$value ) { continue; } $value['pseudo'] = $this->_getPseudoByOptionName($param_name); $this->setSetting($param_name, $value); $register_classes[] = $value; } return $register_classes; } protected function _getPseudoByOptionName($option_name) { $pseudo_class_map = Array ( 'ItemClass' => '%s', 'ListClass' => '%s_List', 'EventHandlerClass' => '%s_EventHandler', 'TagProcessorClass' => '%s_TagProcessor' ); return sprintf($pseudo_class_map[$option_name], $this->_prefix); } protected function _parseScheduledTasks() { if ( !$this->getScheduledTasks() ) { return ; } $scheduled_tasks = $this->getScheduledTasks(); foreach ($scheduled_tasks as $short_name => $scheduled_task_info) { $event_status = array_key_exists('Status', $scheduled_task_info) ? $scheduled_task_info['Status'] : STATUS_ACTIVE; $this->Application->delayUnitProcessing('registerScheduledTask', Array ($short_name, $this->_prefix . ':' . $scheduled_task_info['EventName'], $scheduled_task_info['RunSchedule'], $this->getModule(), $event_status)); } } /** * Detects module by unit location. * * @return string */ public function getModule() { $module_path = $this->getModuleFolder() . '/'; foreach ( $this->Application->ModuleInfo as $module_name => $module_data ) { if ( $module_name == 'In-Portal' ) { continue; } if ( $module_data['Path'] == $module_path ) { return $module_name; } } return ''; } protected function _parseHooks() { $hooks = $this->getHooks(); if ( !$hooks ) { return; } foreach ($hooks as $hook) { if ( $this->getParentPrefix() && ($hook['HookToPrefix'] == $this->getParentPrefix()) ) { trigger_error('Deprecated Hook Usage [prefix: ' . $this->_prefix . '; do_prefix: ' . $hook['DoPrefix'] . '] use #PARENT# as HookToPrefix value, where HookToPrefix is same as ParentPrefix', defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_NOTICE); } if ( $hook['HookToPrefix'] == '' ) { // new: set hooktoprefix to current prefix if not set $hook['HookToPrefix'] = $this->_prefix; } if ( $this->getParentPrefix() ) { // new: allow to set hook to parent prefix what ever it is if ( $hook['HookToPrefix'] == '#PARENT#' ) { $hook['HookToPrefix'] = $this->getParentPrefix(); } if ( $hook['DoPrefix'] == '#PARENT#' ) { $hook['DoPrefix'] = $this->getParentPrefix(); } } elseif ( $hook['HookToPrefix'] == '#PARENT#' || $hook['DoPrefix'] == '#PARENT#' ) { // we need parent prefix but it's not set ! continue; } $hook_events = (array)$hook['HookToEvent']; $do_prefix = $hook['DoPrefix'] == '' ? $this->_prefix : $hook['DoPrefix']; foreach ($hook_events as $hook_event) { $hook_event = $hook['HookToPrefix'] . '.' . $hook['HookToSpecial'] . ':' . $hook_event; $do_event = $do_prefix . '.' . $hook['DoSpecial'] . ':' . $hook['DoEvent']; $this->Application->delayUnitProcessing('registerHook', Array ($hook_event, $do_event, $hook['Mode'], $hook['Conditional'])); } } } protected function _parseAggregatedTags() { $aggregated_tags = $this->getAggregateTags(); if ( !$aggregated_tags ) { return; } foreach ($aggregated_tags as $aggregate_tag) { if ( $this->getParentPrefix() ) { if ( $aggregate_tag['AggregateTo'] == $this->getParentPrefix() ) { trigger_error('Deprecated Aggregate Tag Usage [prefix: ' . $this->_prefix . '; AggregateTo: ' . $aggregate_tag['AggregateTo'] . '] use #PARENT# as AggregateTo value, where AggregateTo is same as ParentPrefix', defined('E_USER_DEPRECATED') ? E_USER_DEPRECATED : E_USER_NOTICE); } if ( $aggregate_tag['AggregateTo'] == '#PARENT#' ) { $aggregate_tag['AggregateTo'] = $this->getParentPrefix(); } } $aggregate_tag['LocalPrefix'] = $this->_prefix; $this->Application->delayUnitProcessing('registerAggregateTag', Array ($aggregate_tag)); } } public function validate() { global $debugger; $table_name = $this->getTableName(); $float_types = Array ('float', 'double', 'numeric'); $table_found = $this->Conn->Query('SHOW TABLES LIKE "' . $table_name . '"'); if ( !$table_found ) { // config present, but table missing, strange kUtil::safeDefine('DBG_RAISE_ON_WARNINGS', 1); $debugger->appendHTML("Config Warning: Table $table_name missing, but prefix " . $this->_prefix . " requires it!"); $debugger->WarningCount++; return; } $res = $this->Conn->Query('DESCRIBE ' . $table_name); $config_link = $debugger->getFileLink(FULL_PATH . $this->_filename, 1, $this->_prefix); $error_messages = Array ( 'field_not_found' => 'Field %s exists in the database, but is not defined in config', 'default_missing' => 'Default value for field %s not set in config', 'not_null_error1' => 'Field %s is NOT NULL in the database, but is not configured as not_null', // or required', 'not_null_error2' => 'Field %s is described as NOT NULL in config, but does not have DEFAULT value', 'not_null_error3' => 'Field %s is described as NOT NULL in config, but is NULL in db', 'invalid_default' => 'Default value for field %s%s not sync. to db (in config = %s, in db = %s)', 'date_column_not_null_error' => 'Field %s must be NULL in config and database, since it contains date', 'user_column_default_error' => 'Field %s must be have NULL as default value, since it holds user id', 'type_missing' => 'Type definition for field %s missing in config', 'virtual_type_missing' => 'Type definition for virtual field %s missing in config', 'virtual_default_missing' => 'Default value for virtual field %s not set in config', 'virtual_not_null_error' => 'Virtual field %s cannot be not null, since it doesn\'t exist in database', 'invalid_calculated_field' => 'Calculated field %s is missing corresponding virtual field', ); $config_errors = Array (); $fields = $this->getFields(); $table_name = preg_replace('/^' . preg_quote(TABLE_PREFIX, '/') . '(.*)/', '\\1', $table_name); // remove table prefix if ( $fields ) { // validate unit config field declaration in relation to database table structure foreach ($res as $field) { $f_name = $field['Field']; if ( preg_match('/l[\d]+_[\w]/', $f_name) ) { // skip multilingual fields continue; } if ( !array_key_exists($f_name, $fields) ) { $config_errors[] = sprintf($error_messages['field_not_found'], $f_name); } else { $db_default = $field['Default']; if ( is_numeric($db_default) ) { $db_default = preg_match('/[\.,]/', $db_default) ? (float)$db_default : (int)$db_default; } $default_missing = false; $options = $fields[$f_name]; $not_null = isset($options['not_null']) && $options['not_null']; $formatter = array_key_exists('formatter', $options) ? $options['formatter'] : false; if ( !array_key_exists('default', $options) ) { $config_errors[] = sprintf($error_messages['default_missing'], $f_name); $default_missing = true; } if ( $field['Null'] != 'YES' ) { // field is NOT NULL in database (MySQL5 for null returns "NO", but MySQL4 returns "") if ( $f_name != $this->getIDField() && !isset($options['not_null']) /*&& !isset($options['required'])*/ ) { $config_errors[] = sprintf($error_messages['not_null_error1'], $f_name); } if ( $not_null && !isset($options['default']) ) { $config_errors[] = sprintf($error_messages['not_null_error2'], $f_name); } } elseif ( $not_null ) { $config_errors[] = sprintf($error_messages['not_null_error3'], $f_name); } if ( ($formatter == 'kDateFormatter') && $not_null ) { $config_errors[] = sprintf($error_messages['date_column_not_null_error'], $f_name); } // columns, holding userid should have NULL as default value if ( array_key_exists('type', $options) && !$default_missing ) { // both type and default value set if ( preg_match('/ById$/', $f_name) && $options['default'] !== null ) { $config_errors[] = sprintf($error_messages['user_column_default_error'], $f_name); } } if ( !array_key_exists('type', $options) ) { $config_errors[] = sprintf($error_messages['type_missing'], $f_name); } if ( !$default_missing && ($field['Type'] != 'text') ) { if ( is_null($db_default) && $not_null ) { $db_default = $options['type'] == 'string' ? '' : 0; } if ( $f_name == $this->getIDField() && $options['type'] != 'string' && $options['default'] !== 0 ) { $config_errors[] = sprintf($error_messages['invalid_default'], 'IDField ', $f_name, $this->_varDump($options['default']), $this->_varDump($field['Default'])); } else if ( ((string)$options['default'] != '#NOW#') && ($db_default !== $options['default']) && !in_array($options['type'], $float_types) ) { $config_errors[] = sprintf($error_messages['invalid_default'], '', $f_name, $this->_varDump($options['default']), $this->_varDump($db_default)); } } } } } // validate virtual fields $virtual_fields = $this->getVirtualFields(); if ( $virtual_fields ) { foreach ($virtual_fields as $f_name => $options) { if ( !array_key_exists('type', $options) ) { $config_errors[] = sprintf($error_messages['virtual_type_missing'], $f_name); } if ( array_key_exists('not_null', $options) ) { $config_errors[] = sprintf($error_messages['virtual_not_null_error'], $f_name); } if ( !array_key_exists('default', $options) ) { $config_errors[] = sprintf($error_messages['virtual_default_missing'], $f_name); } } } // validate calculated fields if ( $this->getCalculatedFieldSpecials() ) { foreach ($this->getCalculatedFieldSpecials() as $special) { foreach ($this->getCalculatedFieldsBySpecial($special) as $calculated_field => $calculated_field_expr) { if ( !isset($virtual_fields[$calculated_field]) ) { $config_errors[] = sprintf($error_messages['invalid_calculated_field'], $calculated_field); } } } $config_errors = array_unique($config_errors); } if ( $config_errors ) { $error_prefix = 'Config Error' . (count($config_errors) > 1 ? 's' : '') . ': for prefix ' . $config_link . ' (' . $table_name . ') in unit config:
'; $config_errors = $error_prefix . '   ' . implode('
   ', $config_errors); kUtil::safeDefine('DBG_RAISE_ON_WARNINGS', 1); $debugger->appendHTML($config_errors); $debugger->WarningCount++; } } protected function _varDump($value) { return '' . var_export($value, true) . ' of ' . gettype($value); } }