Index: releases/5.2.0-B3/README =================================================================== diff -u -N --- releases/5.2.0-B3/README (revision 0) +++ releases/5.2.0-B3/README (revision 15451) @@ -0,0 +1,48 @@ +INTRODUCTION TO IN-PORTAL +------------------------- + +In-Portal is Open Source object-oriented framework that is developed +in PHP and provides quick and easy way to build websites and web applications. + +In-Portal Framework has modular structure that allows painlessly +add and extend already existing features via new modules. + +In-Portal has three Open Source modules + + In-Link - Directory Management + In-News - News Management + In-Bulletin - Discussions Forum + +These and other modules can be downloaded at + + http://www.in-portal.com/download.html + +In-Portal Development Kit is available for users looking to +highly customize and extend In-Portal. Development Kit can be +freely downloaded at + + http://www.in-portal.com/download.html + +In-Portal Community is working hard to improve the In-Portal, +develop new modules and make them available to the everyone. + +In-Portal Community greatly appreciates any type of involvement +and contributions to the project. + +Please visit + + http://www.in-portal.org/contribute.html + +to see how You can participate and be a part of In-Portal Community. + + +LICENSING & COPYRIGHTS +---------------------- + +Please see COPYRIGHT file for details. + + +INSTALLATION +------------ + +Please see INSTALL file for instructions. Index: releases/5.2.0-B3/core/install/upgrades.php =================================================================== diff -u -N --- releases/5.2.0-B3/core/install/upgrades.php (revision 0) +++ releases/5.2.0-B3/core/install/upgrades.php (revision 15451) @@ -0,0 +1,2153 @@ + Array ('from' => 'BanRules', 'to' => 'UserBanRules'), + 'conf' => Array ('from' => 'ConfigurationValues', 'to' => 'SystemSettings'), + 'c' => Array ('from' => 'Category', 'to' => 'Categories'), + 'cf' => Array ('from' => 'CustomField', 'to' => 'CustomFields'), + 'draft' => Array ('from' => 'Drafts', 'to' => 'FormSubmissionReplyDrafts'), + 'emailevents' => Array ('from' => 'Events', 'to' => 'EmailEvents'), + 'fav' => Array ('from' => 'Favorites', 'to' => 'UserFavorites'), + 'img' => Array ('from' => 'Images', 'to' => 'CatalogImages'), + '#file' => Array ('from' => 'ItemFiles', 'to' => 'CatalogFiles'), + 'rev' => Array ('from' => 'ItemReview', 'to' => 'CatalogReviews'), + 'lang' => Array ('from' => 'Language', 'to' => 'Languages'), + 'permission-type' => Array ('from' => 'PermissionConfig', 'to' => 'CategoryPermissionsConfig'), + 'phrases' => Array ('from' => 'Phrase', 'to' => 'LanguageLabels'), + 'g' => Array ('from' => 'PortalGroup', 'to' => 'UserGroups'), + 'user-profile' => Array ('from' => 'PersistantSessionData', 'to' => 'UserPersistentSessionData'), + 'u' => Array ('from' => 'PortalUser', 'to' => 'Users'), + 'u-cdata' => Array ('from' => 'PortalUserCustomData', 'to' => 'UserCustomData'), + 'search' => Array ('from' => 'RelatedSearches', 'to' => 'CategoryRelatedSearches'), + 'rel' => Array ('from' => 'Relationship', 'to' => 'CatalogRelationships'), + 'search-log' => Array ('from' => 'SearchLog', 'to' => 'SearchLogs'), + 'skin' => Array ('from' => 'Skins', 'to' => 'AdminSkins'), + 'submission-log' => Array ('from' => 'SubmissionLog', 'to' => 'FormSubmissionReplies'), + 'theme' => Array ('from' => 'Theme', 'to' => 'Themes'), + 'ug' => Array ('from' => 'UserGroup', 'to' => 'UserGroupRelations'), + 'visits' => Array ('from' => 'Visits', 'to' => 'UserVisits'), + 'session-log' => Array ('from' => 'SessionLogs', 'to' => 'UserSessionLogs'), + ); + + /** + * Changes table structure, where multilingual fields of TEXT type are present + * + * @param string $mode when called mode {before, after) + */ + function Upgrade_4_1_0($mode) + { + if ($mode == 'before') { + // don't user after, because In-Portal calls this method too + $this->_toolkit->SaveConfig(); + } + + if ($mode == 'after') { + $ml_helper = $this->Application->recallObject('kMultiLanguageHelper'); + /* @var $ml_helper kMultiLanguageHelper */ + + $this->Application->UnitConfigReader->iterateConfigs(Array (&$this, 'updateTextFields'), $ml_helper->getLanguages()); + } + } + + /** + * Moves ReplacementTags functionality from EmailMessage to Events table + * + * @param string $mode when called mode {before, after) + */ + function Upgrade_4_1_1($mode) + { + if ($mode == 'after') { + $sql = 'SELECT ReplacementTags, EventId + FROM '.TABLE_PREFIX.'EmailMessage + WHERE (ReplacementTags IS NOT NULL) AND (ReplacementTags <> "") AND (LanguageId = 1)'; + $replacement_tags = $this->Conn->GetCol($sql, 'EventId'); + + foreach ($replacement_tags as $event_id => $replacement_tag) { + $sql = 'UPDATE '.TABLE_PREFIX.'Events + SET ReplacementTags = '.$this->Conn->qstr($replacement_tag).' + WHERE EventId = '.$event_id; + $this->Conn->Query($sql); + } + + // drop moved field from source table + $sql = 'ALTER TABLE '.TABLE_PREFIX.'EmailMessage + DROP `ReplacementTags`'; + $this->Conn->Query($sql); + } + } + + /** + * Callback function, that makes all ml fields of text type null with same default value + * + * @param string $prefix + * @param Array $config_data + * @param Array $languages + * @return bool + */ + function updateTextFields($prefix, &$config_data, $languages) + { + if (!isset($config_data['TableName']) || !isset($config_data['Fields'])) { + // invalid config found or prefix not found + return false; + } + + $table_name = $config_data['TableName']; + $table_structure = $this->Conn->Query('DESCRIBE '.$table_name, 'Field'); + if (!$table_structure) { + // table not found + return false; + } + + $sqls = Array (); + foreach ($config_data['Fields'] as $field => $options) { + if (isset($options['formatter']) && $options['formatter'] == 'kMultiLanguage' && !isset($options['master_field'])) { + // update all l_ fields (new format) + + foreach ($languages as $language_id) { + $ml_field = 'l'.$language_id.'_'.$field; + + if ($table_structure[$ml_field]['Type'] == 'text') { + $sqls[] = 'CHANGE '.$ml_field.' '.$ml_field.' TEXT NULL DEFAULT NULL'; + } + } + + // update if found (old format) + if (isset($table_structure[$field]) && $table_structure[$field]['Type'] == 'text') { + $sqls[] = 'CHANGE '.$field.' '.$field.' TEXT NULL DEFAULT NULL'; + } + } + } + + if ($sqls) { + $sql = 'ALTER TABLE '.$table_name.' '.implode(', ', $sqls); + $this->Conn->Query($sql); + } + + return true; + } + + /** + * Replaces In-Portal tags in Forgot Password related email events to K4 ones + * + * @param string $mode when called mode {before, after) + */ + function Upgrade_4_2_0($mode) + { + if ($mode == 'after') { + // 1. get event ids based on their name and type combination + $event_names = Array ( + 'USER.PSWD_' . EmailEvent::EVENT_TYPE_ADMIN, + 'USER.PSWD_' . EmailEvent::EVENT_TYPE_FRONTEND, + 'USER.PSWDC_' . EmailEvent::EVENT_TYPE_FRONTEND, + ); + + $event_sql = Array (); + foreach ($event_names as $mixed_event) { + list ($event_name, $event_type) = explode('_', $mixed_event, 2); + $event_sql[] = 'Event = "'.$event_name.'" AND Type = '.$event_type; + } + + $sql = 'SELECT EventId + FROM '.TABLE_PREFIX.'Events + WHERE ('.implode(') OR (', $event_sql).')'; + $event_ids = implode(',', $this->Conn->GetCol($sql)); + + // 2. replace In-Portal tags to K4 tags + $replacements = Array ( + '' => '', + '' => '', + ); + + foreach ($replacements as $old_tag => $new_tag) { + $sql = 'UPDATE '.TABLE_PREFIX.'EmailMessage + SET Template = REPLACE(Template, '.$this->Conn->qstr($old_tag).', '.$this->Conn->qstr($new_tag).') + WHERE EventId IN ('.$event_ids.')'; + $this->Conn->Query($sql); + } + + } + } + + /** + * Makes admin primary language same as front-end - not needed, done in SQL + * + * @param string $mode when called mode {before, after) + */ + function Upgrade_4_2_1($mode) + { + + } + + function Upgrade_4_2_2($mode) + { + if ($mode == 'before') { + if ($this->Conn->GetOne('SELECT LanguageId FROM '.TABLE_PREFIX.'Language WHERE PrimaryLang = 1')) return ; + $this->Conn->Query('UPDATE '.TABLE_PREFIX.'Language SET PrimaryLang = 1 ORDER BY LanguageId LIMIT 1'); + } + } + + /** + * Adds index to "dob" field in "PortalUser" table when it's missing + * + * @param string $mode when called mode {before, after) + */ + function Upgrade_4_3_1($mode) + { + if ($mode == 'after') { + $sql = 'DESCRIBE ' . TABLE_PREFIX . 'PortalUser'; + $structure = $this->Conn->Query($sql); + + foreach ($structure as $field_info) { + if ($field_info['Field'] == 'dob') { + if (!$field_info['Key']) { + $sql = 'ALTER TABLE ' . TABLE_PREFIX . 'PortalUser + ADD INDEX (dob)'; + $this->Conn->Query($sql); + } + break; + } + } + } + } + + /** + * Removes duplicate phrases, update file paths in database + * + * @param string $mode when called mode {before, after) + */ + function Upgrade_4_3_9($mode) + { + // 1. find In-Portal old Conn->GetCol($sql)); + + // 2. replace In-Portal old ' ' ' ' ' ' ' $new_tag) { + $sql = 'UPDATE '.TABLE_PREFIX.'EmailMessage + SET Template = REPLACE(Template, '.$this->Conn->qstr($old_tag).', '.$this->Conn->qstr($new_tag).') + WHERE EventId IN ('.$event_ids.')'; + $this->Conn->Query($sql); + } + } + + if ($mode == 'after') { + $this->_insertInPortalData(); + $this->_moveDatabaseFolders(); + + // in case, when In-Portal module is enabled -> turn AdvancedUserManagement on too + if ($this->Application->findModule('Name', 'In-Portal')) { + $sql = 'UPDATE ' . TABLE_PREFIX . 'ConfigurationValues + SET VariableValue = 1 + WHERE VariableName = "AdvancedUserManagement"'; + $this->Conn->Query($sql); + } + } + + if ($mode == 'languagepack') { + $this->_removeDuplicatePhrases(); + } + } + + function _insertInPortalData() + { + $data = Array ( + 'ConfigurationAdmin' => Array ( + 'UniqueField' => 'VariableName', + 'Records' => Array ( + 'AllowDeleteRootCats' => "('AllowDeleteRootCats', 'la_Text_General', 'la_AllowDeleteRootCats', 'checkbox', NULL , NULL , 10.09, 0, 0)", + 'Catalog_PreselectModuleTab' => "('Catalog_PreselectModuleTab', 'la_Text_General', 'la_config_CatalogPreselectModuleTab', 'checkbox', NULL, NULL, 10.10, 0, 1)", + 'RecycleBinFolder' => "('RecycleBinFolder', 'la_Text_General', 'la_config_RecycleBinFolder', 'text', NULL , NULL , 10.11, 0, 0)", + 'AdvancedUserManagement' => "('AdvancedUserManagement', 'la_Text_General', 'la_prompt_AdvancedUserManagement', 'checkbox', NULL, NULL, '10.011', 0, 1)", + ), + ), + + 'ConfigurationValues' => Array ( + 'UniqueField' => 'VariableName', + 'Records' => Array ( + 'AdvancedUserManagement' => "(DEFAULT, 'AdvancedUserManagement', 0, 'In-Portal:Users', 'in-portal:configure_users')", + ), + ), + + 'ItemTypes' => Array ( + 'UniqueField' => 'ItemType', + 'Records' => Array ( + '1' => "(1, 'In-Portal', 'c', 'Category', 'Name', 'CreatedById', NULL, NULL, 'la_ItemTab_Categories', 1, 'admin/category/addcategory.php', 'clsCategory', 'Category')", + '6' => "(6, 'In-Portal', 'u', 'PortalUser', 'Login', 'PortalUserId', NULL, NULL, '', 0, '', 'clsPortalUser', 'User')", + ), + ), + + 'PermissionConfig' => Array ( + 'UniqueField' => 'PermissionName', + 'Records' => Array ( + 'CATEGORY.ADD' => "(DEFAULT, 'CATEGORY.ADD', 'lu_PermName_Category.Add_desc', 'lu_PermName_Category.Add_error', 'In-Portal')", + 'CATEGORY.DELETE' => "(DEFAULT, 'CATEGORY.DELETE', 'lu_PermName_Category.Delete_desc', 'lu_PermName_Category.Delete_error', 'In-Portal')", + 'CATEGORY.ADD.PENDING' => "(DEFAULT, 'CATEGORY.ADD.PENDING', 'lu_PermName_Category.AddPending_desc', 'lu_PermName_Category.AddPending_error', 'In-Portal')", + 'CATEGORY.MODIFY' => "(DEFAULT, 'CATEGORY.MODIFY', 'lu_PermName_Category.Modify_desc', 'lu_PermName_Category.Modify_error', 'In-Portal')", + 'ADMIN' => "(DEFAULT, 'ADMIN', 'lu_PermName_Admin_desc', 'lu_PermName_Admin_error', 'Admin')", + 'LOGIN' => "(DEFAULT, 'LOGIN', 'lu_PermName_Login_desc', 'lu_PermName_Admin_error', 'Front')", + 'DEBUG.ITEM' => "(DEFAULT, 'DEBUG.ITEM', 'lu_PermName_Debug.Item_desc', '', 'Admin')", + 'DEBUG.LIST' => "(DEFAULT, 'DEBUG.LIST', 'lu_PermName_Debug.List_desc', '', 'Admin')", + 'DEBUG.INFO' => "(DEFAULT, 'DEBUG.INFO', 'lu_PermName_Debug.Info_desc', '', 'Admin')", + 'PROFILE.MODIFY' => "(DEFAULT, 'PROFILE.MODIFY', 'lu_PermName_Profile.Modify_desc', '', 'Admin')", + 'SHOWLANG' => "(DEFAULT, 'SHOWLANG', 'lu_PermName_ShowLang_desc', '', 'Admin')", + 'FAVORITES' => "(DEFAULT, 'FAVORITES', 'lu_PermName_favorites_desc', 'lu_PermName_favorites_error', 'In-Portal')", + 'SYSTEM_ACCESS.READONLY' => "(DEFAULT, 'SYSTEM_ACCESS.READONLY', 'la_PermName_SystemAccess.ReadOnly_desc', 'la_PermName_SystemAccess.ReadOnly_error', 'Admin')", + ), + ), + + 'Permissions' => Array ( + 'UniqueField' => 'Permission;GroupId;Type;CatId', + 'Records' => Array ( + 'LOGIN;12;1;0' => "(DEFAULT, 'LOGIN', 12, 1, 1, 0)", + 'in-portal:site.view;11;1;0' => "(DEFAULT, 'in-portal:site.view', 11, 1, 1, 0)", + 'in-portal:browse.view;11;1;0' => "(DEFAULT, 'in-portal:browse.view', 11, 1, 1, 0)", + 'in-portal:advanced_view.view;11;1;0' => "(DEFAULT, 'in-portal:advanced_view.view', 11, 1, 1, 0)", + 'in-portal:reviews.view;11;1;0' => "(DEFAULT, 'in-portal:reviews.view', 11, 1, 1, 0)", + 'in-portal:configure_categories.view;11;1;0' => "(DEFAULT, 'in-portal:configure_categories.view', 11, 1, 1, 0)", + 'in-portal:configure_categories.edit;11;1;0' => "(DEFAULT, 'in-portal:configure_categories.edit', 11, 1, 1, 0)", + 'in-portal:configuration_search.view;11;1;0' => "(DEFAULT, 'in-portal:configuration_search.view', 11, 1, 1, 0)", + 'in-portal:configuration_search.edit;11;1;0' => "(DEFAULT, 'in-portal:configuration_search.edit', 11, 1, 1, 0)", + 'in-portal:configuration_email.view;11;1;0' => "(DEFAULT, 'in-portal:configuration_email.view', 11, 1, 1, 0)", + 'in-portal:configuration_email.edit;11;1;0' => "(DEFAULT, 'in-portal:configuration_email.edit', 11, 1, 1, 0)", + 'in-portal:configuration_custom.view;11;1;0' => "(DEFAULT, 'in-portal:configuration_custom.view', 11, 1, 1, 0)", + 'in-portal:configuration_custom.add;11;1;0' => "(DEFAULT, 'in-portal:configuration_custom.add', 11, 1, 1, 0)", + 'in-portal:configuration_custom.edit;11;1;0' => "(DEFAULT, 'in-portal:configuration_custom.edit', 11, 1, 1, 0)", + 'in-portal:configuration_custom.delete;11;1;0' => "(DEFAULT, 'in-portal:configuration_custom.delete', 11, 1, 1, 0)", + 'in-portal:users.view;11;1;0' => "(DEFAULT, 'in-portal:users.view', 11, 1, 1, 0)", + 'in-portal:user_list.advanced:ban;11;1;0' => "(DEFAULT, 'in-portal:user_list.advanced:ban', 11, 1, 1, 0)", + 'in-portal:user_list.advanced:send_email;11;1;0' => "(DEFAULT, 'in-portal:user_list.advanced:send_email', 11, 1, 1, 0)", + 'in-portal:user_groups.view;11;1;0' => "(DEFAULT, 'in-portal:user_groups.view', 11, 1, 1, 0)", + 'in-portal:user_groups.add;11;1;0' => "(DEFAULT, 'in-portal:user_groups.add', 11, 1, 1, 0)", + 'in-portal:user_groups.edit;11;1;0' => "(DEFAULT, 'in-portal:user_groups.edit', 11, 1, 1, 0)", + 'in-portal:user_groups.delete;11;1;0' => "(DEFAULT, 'in-portal:user_groups.delete', 11, 1, 1, 0)", + 'in-portal:user_groups.advanced:send_email;11;1;0' => "(DEFAULT, 'in-portal:user_groups.advanced:send_email', 11, 1, 1, 0)", + 'in-portal:user_groups.advanced:manage_permissions;11;1;0' => "(DEFAULT, 'in-portal:user_groups.advanced:manage_permissions', 11, 1, 1, 0)", + 'in-portal:configure_users.view;11;1;0' => "(DEFAULT, 'in-portal:configure_users.view', 11, 1, 1, 0)", + 'in-portal:configure_users.edit;11;1;0' => "(DEFAULT, 'in-portal:configure_users.edit', 11, 1, 1, 0)", + 'in-portal:user_email.view;11;1;0' => "(DEFAULT, 'in-portal:user_email.view', 11, 1, 1, 0)", + 'in-portal:user_email.edit;11;1;0' => "(DEFAULT, 'in-portal:user_email.edit', 11, 1, 1, 0)", + 'in-portal:user_custom.view;11;1;0' => "(DEFAULT, 'in-portal:user_custom.view', 11, 1, 1, 0)", + 'in-portal:user_custom.add;11;1;0' => "(DEFAULT, 'in-portal:user_custom.add', 11, 1, 1, 0)", + 'in-portal:user_custom.edit;11;1;0' => "(DEFAULT, 'in-portal:user_custom.edit', 11, 1, 1, 0)", + 'in-portal:user_custom.delete;11;1;0' => "(DEFAULT, 'in-portal:user_custom.delete', 11, 1, 1, 0)", + 'in-portal:user_banlist.view;11;1;0' => "(DEFAULT, 'in-portal:user_banlist.view', 11, 1, 1, 0)", + 'in-portal:user_banlist.add;11;1;0' => "(DEFAULT, 'in-portal:user_banlist.add', 11, 1, 1, 0)", + 'in-portal:user_banlist.edit;11;1;0' => "(DEFAULT, 'in-portal:user_banlist.edit', 11, 1, 1, 0)", + 'in-portal:user_banlist.delete;11;1;0' => "(DEFAULT, 'in-portal:user_banlist.delete', 11, 1, 1, 0)", + 'in-portal:reports.view;11;1;0' => "(DEFAULT, 'in-portal:reports.view', 11, 1, 1, 0)", + 'in-portal:log_summary.view;11;1;0' => "(DEFAULT, 'in-portal:log_summary.view', 11, 1, 1, 0)", + 'in-portal:searchlog.view;11;1;0' => "(DEFAULT, 'in-portal:searchlog.view', 11, 1, 1, 0)", + 'in-portal:searchlog.delete;11;1;0' => "(DEFAULT, 'in-portal:searchlog.delete', 11, 1, 1, 0)", + 'in-portal:sessionlog.view;11;1;0' => "(DEFAULT, 'in-portal:sessionlog.view', 11, 1, 1, 0)", + 'in-portal:sessionlog.delete;11;1;0' => "(DEFAULT, 'in-portal:sessionlog.delete', 11, 1, 1, 0)", + 'in-portal:emaillog.view;11;1;0' => "(DEFAULT, 'in-portal:emaillog.view', 11, 1, 1, 0)", + 'in-portal:emaillog.delete;11;1;0' => "(DEFAULT, 'in-portal:emaillog.delete', 11, 1, 1, 0)", + 'in-portal:visits.view;11;1;0' => "(DEFAULT, 'in-portal:visits.view', 11, 1, 1, 0)", + 'in-portal:visits.delete;11;1;0' => "(DEFAULT, 'in-portal:visits.delete', 11, 1, 1, 0)", + 'in-portal:configure_general.view;11;1;0' => "(DEFAULT, 'in-portal:configure_general.view', 11, 1, 1, 0)", + 'in-portal:configure_general.edit;11;1;0' => "(DEFAULT, 'in-portal:configure_general.edit', 11, 1, 1, 0)", + 'in-portal:modules.view;11;1;0' => "(DEFAULT, 'in-portal:modules.view', 11, 1, 1, 0)", + 'in-portal:mod_status.view;11;1;0' => "(DEFAULT, 'in-portal:mod_status.view', 11, 1, 1, 0)", + 'in-portal:mod_status.edit;11;1;0' => "(DEFAULT, 'in-portal:mod_status.edit', 11, 1, 1, 0)", + 'in-portal:mod_status.advanced:approve;11;1;0' => "(DEFAULT, 'in-portal:mod_status.advanced:approve', 11, 1, 1, 0)", + 'in-portal:mod_status.advanced:decline;11;1;0' => "(DEFAULT, 'in-portal:mod_status.advanced:decline', 11, 1, 1, 0)", + 'in-portal:addmodule.view;11;1;0' => "(DEFAULT, 'in-portal:addmodule.view', 11, 1, 1, 0)", + 'in-portal:addmodule.add;11;1;0' => "(DEFAULT, 'in-portal:addmodule.add', 11, 1, 1, 0)", + 'in-portal:addmodule.edit;11;1;0' => "(DEFAULT, 'in-portal:addmodule.edit', 11, 1, 1, 0)", + 'in-portal:tag_library.view;11;1;0' => "(DEFAULT, 'in-portal:tag_library.view', 11, 1, 1, 0)", + 'in-portal:configure_themes.view;11;1;0' => "(DEFAULT, 'in-portal:configure_themes.view', 11, 1, 1, 0)", + 'in-portal:configure_themes.add;11;1;0' => "(DEFAULT, 'in-portal:configure_themes.add', 11, 1, 1, 0)", + 'in-portal:configure_themes.edit;11;1;0' => "(DEFAULT, 'in-portal:configure_themes.edit', 11, 1, 1, 0)", + 'in-portal:configure_themes.delete;11;1;0' => "(DEFAULT, 'in-portal:configure_themes.delete', 11, 1, 1, 0)", + 'in-portal:configure_styles.view;11;1;0' => "(DEFAULT, 'in-portal:configure_styles.view', 11, 1, 1, 0)", + 'in-portal:configure_styles.add;11;1;0' => "(DEFAULT, 'in-portal:configure_styles.add', 11, 1, 1, 0)", + 'in-portal:configure_styles.edit;11;1;0' => "(DEFAULT, 'in-portal:configure_styles.edit', 11, 1, 1, 0)", + 'in-portal:configure_styles.delete;11;1;0' => "(DEFAULT, 'in-portal:configure_styles.delete', 11, 1, 1, 0)", + 'in-portal:configure_lang.advanced:set_primary;11;1;0' => "(DEFAULT, 'in-portal:configure_lang.advanced:set_primary', 11, 1, 1, 0)", + 'in-portal:configure_lang.advanced:import;11;1;0' => "(DEFAULT, 'in-portal:configure_lang.advanced:import', 11, 1, 1, 0)", + 'in-portal:configure_lang.advanced:export;11;1;0' => "(DEFAULT, 'in-portal:configure_lang.advanced:export', 11, 1, 1, 0)", + 'in-portal:tools.view;11;1;0' => "(DEFAULT, 'in-portal:tools.view', 11, 1, 1, 0)", + 'in-portal:backup.view;11;1;0' => "(DEFAULT, 'in-portal:backup.view', 11, 1, 1, 0)", + 'in-portal:restore.view;11;1;0' => "(DEFAULT, 'in-portal:restore.view', 11, 1, 1, 0)", + 'in-portal:export.view;11;1;0' => "(DEFAULT, 'in-portal:export.view', 11, 1, 1, 0)", + 'in-portal:main_import.view;11;1;0' => "(DEFAULT, 'in-portal:main_import.view', 11, 1, 1, 0)", + 'in-portal:sql_query.view;11;1;0' => "(DEFAULT, 'in-portal:sql_query.view', 11, 1, 1, 0)", + 'in-portal:sql_query.edit;11;1;0' => "(DEFAULT, 'in-portal:sql_query.edit', 11, 1, 1, 0)", + 'in-portal:server_info.view;11;1;0' => "(DEFAULT, 'in-portal:server_info.view', 11, 1, 1, 0)", + 'in-portal:help.view;11;1;0' => "(DEFAULT, 'in-portal:help.view', 11, 1, 1, 0)", + ), + ), + + 'SearchConfig' => Array ( + 'UniqueField' => 'TableName;FieldName;ModuleName', + 'Records' => Array ( + 'Category;NewItem;In-Portal' => "('Category', 'NewItem', 0, 1, 'lu_fielddesc_category_newitem', 'lu_field_newitem', 'In-Portal', 'la_text_category', 18, DEFAULT, 0, 'boolean', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'Category;PopItem;In-Portal' => "('Category', 'PopItem', 0, 1, 'lu_fielddesc_category_popitem', 'lu_field_popitem', 'In-Portal', 'la_text_category', 19, DEFAULT, 0, 'boolean', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'Category;HotItem;In-Portal' => "('Category', 'HotItem', 0, 1, 'lu_fielddesc_category_hotitem', 'lu_field_hotitem', 'In-Portal', 'la_text_category', 17, DEFAULT, 0, 'boolean', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'Category;MetaDescription;In-Portal' => "('Category', 'MetaDescription', 0, 1, 'lu_fielddesc_category_metadescription', 'lu_field_metadescription', 'In-Portal', 'la_text_category', 16, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'Category;ParentPath;In-Portal' => "('Category', 'ParentPath', 0, 1, 'lu_fielddesc_category_parentpath', 'lu_field_parentpath', 'In-Portal', 'la_text_category', 15, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'Category;ResourceId;In-Portal' => "('Category', 'ResourceId', 0, 1, 'lu_fielddesc_category_resourceid', 'lu_field_resourceid', 'In-Portal', 'la_text_category', 14, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'Category;CreatedById;In-Portal' => "('Category', 'CreatedById', 0, 1, 'lu_fielddesc_category_createdbyid', 'lu_field_createdbyid', 'In-Portal', 'la_text_category', 13, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'Category;CachedNavbar;In-Portal' => "('Category', 'CachedNavbar', 0, 1, 'lu_fielddesc_category_cachednavbar', 'lu_field_cachednavbar', 'In-Portal', 'la_text_category', 12, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'Category;CachedDescendantCatsQty;In-Portal' => "('Category', 'CachedDescendantCatsQty', 0, 1, 'lu_fielddesc_category_cacheddescendantcatsqty', 'lu_field_cacheddescendantcatsqty', 'In-Portal', 'la_text_category', 11, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'Category;MetaKeywords;In-Portal' => "('Category', 'MetaKeywords', 0, 1, 'lu_fielddesc_category_metakeywords', 'lu_field_metakeywords', 'In-Portal', 'la_text_category', 10, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'Category;Priority;In-Portal' => "('Category', 'Priority', 0, 1, 'lu_fielddesc_category_priority', 'lu_field_priority', 'In-Portal', 'la_text_category', 9, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'Category;Status;In-Portal' => "('Category', 'Status', 0, 1, 'lu_fielddesc_category_status', 'lu_field_status', 'In-Portal', 'la_text_category', 7, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'Category;EditorsPick;In-Portal' => "('Category', 'EditorsPick', 0, 1, 'lu_fielddesc_category_editorspick', 'lu_field_editorspick', 'In-Portal', 'la_text_category', 6, DEFAULT, 0, 'boolean', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'Category;CreatedOn;In-Portal' => "('Category', 'CreatedOn', 0, 1, 'lu_fielddesc_category_createdon', 'lu_field_createdon', 'In-Portal', 'la_text_category', 5, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'Category;Description;In-Portal' => "('Category', 'Description', 1, 1, 'lu_fielddesc_category_description', 'lu_field_description', 'In-Portal', 'la_text_category', 4, DEFAULT, 2, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'Category;Name;In-Portal' => "('Category', 'Name', 1, 1, 'lu_fielddesc_category_name', 'lu_field_name', 'In-Portal', 'la_text_category', 3, DEFAULT, 2, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'Category;ParentId;In-Portal' => "('Category', 'ParentId', 0, 1, 'lu_fielddesc_category_parentid', 'lu_field_parentid', 'In-Portal', 'la_text_category', 2, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'Category;CategoryId;In-Portal' => "('Category', 'CategoryId', 0, 1, 'lu_fielddesc_category_categoryid', 'lu_field_categoryid', 'In-Portal', 'la_text_category', 0, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'Category;Modified;In-Portal' => "('Category', 'Modified', 0, 1, 'lu_fielddesc_category_modified', 'lu_field_modified', 'In-Portal', 'la_text_category', 20, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'Category;ModifiedById;In-Portal' => "('Category', 'ModifiedById', 0, 1, 'lu_fielddesc_category_modifiedbyid', 'lu_field_modifiedbyid', 'In-Portal', 'la_text_category', 21, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + + 'PortalUser;PortalUserId;In-Portal' => "('PortalUser', 'PortalUserId', -1, 0, 'lu_fielddesc_user_portaluserid', 'lu_field_portaluserid', 'In-Portal', 'la_text_user', 0, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'PortalUser;Login;In-Portal' => "('PortalUser', 'Login', -1, 0, 'lu_fielddesc_user_login', 'lu_field_login', 'In-Portal', 'la_text_user', 1, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'PortalUser;Password;In-Portal' => "('PortalUser', 'Password', -1, 0, 'lu_fielddesc_user_password', 'lu_field_password', 'In-Portal', 'la_text_user', 2, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'PortalUser;tz;In-Portal' => "('PortalUser', 'tz', -1, 0, 'lu_fielddesc_user_tz', 'lu_field_tz', 'In-Portal', 'la_text_user', 17, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'PortalUser;dob;In-Portal' => "('PortalUser', 'dob', -1, 0, 'lu_fielddesc_user_dob', 'lu_field_dob', 'In-Portal', 'la_text_user', 16, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'PortalUser;Modified;In-Portal' => "('PortalUser', 'Modified', -1, 0, 'lu_fielddesc_user_modified', 'lu_field_modified', 'In-Portal', 'la_text_user', 15, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'PortalUser;Status;In-Portal' => "('PortalUser', 'Status', -1, 0, 'lu_fielddesc_user_status', 'lu_field_status', 'In-Portal', 'la_text_user', 14, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'PortalUser;ResourceId;In-Portal' => "('PortalUser', 'ResourceId', -1, 0, 'lu_fielddesc_user_resourceid', 'lu_field_resourceid', 'In-Portal', 'la_text_user', 13, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'PortalUser;Country;In-Portal' => "('PortalUser', 'Country', -1, 0, 'lu_fielddesc_user_country', 'lu_field_country', 'In-Portal', 'la_text_user', 12, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'PortalUser;Zip;In-Portal' => "('PortalUser', 'Zip', -1, 0, 'lu_fielddesc_user_zip', 'lu_field_zip', 'In-Portal', 'la_text_user', 11, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'PortalUser;State;In-Portal' => "('PortalUser', 'State', -1, 0, 'lu_fielddesc_user_state', 'lu_field_state', 'In-Portal', 'la_text_user', 10, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'PortalUser;City;In-Portal' => "('PortalUser', 'City', -1, 0, 'lu_fielddesc_user_city', 'lu_field_city', 'In-Portal', 'la_text_user', 9, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'PortalUser;Street;In-Portal' => "('PortalUser', 'Street', -1, 0, 'lu_fielddesc_user_street', 'lu_field_street', 'In-Portal', 'la_text_user', 8, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'PortalUser;Phone;In-Portal' => "('PortalUser', 'Phone', -1, 0, 'lu_fielddesc_user_phone', 'lu_field_phone', 'In-Portal', 'la_text_user', 7, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'PortalUser;CreatedOn;In-Portal' => "('PortalUser', 'CreatedOn', -1, 0, 'lu_fielddesc_user_createdon', 'lu_field_createdon', 'In-Portal', 'la_text_user', 6, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'PortalUser;Email;In-Portal' => "('PortalUser', 'Email', -1, 0, 'lu_fielddesc_user_email', 'lu_field_email', 'In-Portal', 'la_text_user', 5, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'PortalUser;LastName;In-Portal' => "('PortalUser', 'LastName', -1, 0, 'lu_fielddesc_user_lastname', 'lu_field_lastname', 'In-Portal', 'la_text_user', 4, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + 'PortalUser;FirstName;In-Portal' => "('PortalUser', 'FirstName', -1, 0, 'lu_fielddesc_user_firstname', 'lu_field_firstname', 'In-Portal', 'la_text_user', 3, DEFAULT, 0, 'text', NULL, NULL, NULL, NULL, NULL, NULL, NULL)", + ), + ), + + 'StatItem' => Array ( + 'UniqueField' => 'Module;ListLabel', + 'Records' => Array ( + 'In-Portal;la_prompt_ActiveCategories' => "(DEFAULT, 'In-Portal', 'SELECT count(*) FROM <%prefix%>Category WHERE Status=1 ', NULL, 'la_prompt_ActiveCategories', '0', '1')", + 'In-Portal;la_prompt_ActiveUsers' => "(DEFAULT, 'In-Portal', 'SELECT count(*) FROM <%prefix%>PortalUser WHERE Status=1 ', NULL, 'la_prompt_ActiveUsers', '0', '1')", + 'In-Portal;la_prompt_CurrentSessions' => "(DEFAULT, 'In-Portal', 'SELECT count(*) FROM <%prefix%>UserSession', NULL, 'la_prompt_CurrentSessions', '0', '1')", + 'In-Portal;la_prompt_TotalCategories' => "(DEFAULT, 'In-Portal', 'SELECT COUNT(*) as CategoryCount FROM <%prefix%>Category', NULL, 'la_prompt_TotalCategories', 0, 2)", + 'In-Portal;la_prompt_ActiveCategories' => "(DEFAULT, 'In-Portal', 'SELECT COUNT(*) AS ActiveCategories FROM <%prefix%>Category WHERE Status = 1', NULL, 'la_prompt_ActiveCategories', 0, 2)", + 'In-Portal;la_prompt_PendingCategories' => "(DEFAULT, 'In-Portal', 'SELECT COUNT(*) AS PendingCategories FROM <%prefix%>Category WHERE Status = 2', NULL, 'la_prompt_PendingCategories', 0, 2)", + 'In-Portal;la_prompt_DisabledCategories' => "(DEFAULT, 'In-Portal', 'SELECT COUNT(*) AS DisabledCategories FROM <%prefix%>Category WHERE Status = 0', NULL, 'la_prompt_DisabledCategories', 0, 2)", + 'In-Portal;la_prompt_NewCategories' => "(DEFAULT, 'In-Portal', 'SELECT COUNT(*) AS NewCategories FROM <%prefix%>Category WHERE (NewItem = 1) OR ( (UNIX_TIMESTAMP() - CreatedOn) <= <%m:config name=\"Category_DaysNew\"%>*86400 AND (NewItem = 2) )', NULL, 'la_prompt_NewCategories', 0, 2)", + 'In-Portal;la_prompt_CategoryEditorsPick' => "(DEFAULT, 'In-Portal', 'SELECT COUNT(*) FROM <%prefix%>Category WHERE EditorsPick = 1', NULL, 'la_prompt_CategoryEditorsPick', 0, 2)", + 'In-Portal;la_prompt_NewestCategoryDate' => "(DEFAULT, 'In-Portal', 'SELECT <%m:post_format field=\"MAX(CreatedOn)\" type=\"date\"%> FROM <%prefix%>Category', NULL, 'la_prompt_NewestCategoryDate', 0, 2)", + 'In-Portal;la_prompt_LastCategoryUpdate' => "(DEFAULT, 'In-Portal', 'SELECT <%m:post_format field=\"MAX(Modified)\" type=\"date\"%> FROM <%prefix%>Category', NULL, 'la_prompt_LastCategoryUpdate', 0, 2)", + 'In-Portal;la_prompt_TopicsUsers' => "(DEFAULT, 'In-Portal', 'SELECT COUNT(*) AS TotalUsers FROM <%prefix%>PortalUser', NULL, 'la_prompt_TopicsUsers', 0, 2)", + 'In-Portal;la_prompt_UsersActive' => "(DEFAULT, 'In-Portal', 'SELECT COUNT(*) AS ActiveUsers FROM <%prefix%>PortalUser WHERE Status = 1', NULL, 'la_prompt_UsersActive', 0, 2)", + 'In-Portal;la_prompt_UsersPending' => "(DEFAULT, 'In-Portal', 'SELECT COUNT(*) AS PendingUsers FROM <%prefix%>PortalUser WHERE Status = 2', NULL, 'la_prompt_UsersPending', 0, 2)", + 'In-Portal;la_prompt_UsersDisabled' => "(DEFAULT, 'In-Portal', 'SELECT COUNT(*) AS DisabledUsers FROM <%prefix%>PortalUser WHERE Status = 0', NULL, 'la_prompt_UsersDisabled', 0, 2)", + 'In-Portal;la_prompt_NewestUserDate' => "(DEFAULT, 'In-Portal', 'SELECT <%m:post_format field=\"MAX(CreatedOn)\" type=\"date\"%> FROM <%prefix%>PortalUser', NULL, 'la_prompt_NewestUserDate', 0, 2)", + 'In-Portal;la_prompt_UsersUniqueCountries' => "(DEFAULT, 'In-Portal', 'SELECT COUNT( DISTINCT LOWER( Country ) ) FROM <%prefix%>PortalUser WHERE LENGTH(Country) > 0', NULL, 'la_prompt_UsersUniqueCountries', 0, 2)", + 'In-Portal;la_prompt_UsersUniqueStates' => "(DEFAULT, 'In-Portal', 'SELECT COUNT( DISTINCT LOWER( State ) ) FROM <%prefix%>PortalUser WHERE LENGTH(State) > 0', NULL, 'la_prompt_UsersUniqueStates', 0, 2)", + 'In-Portal;la_prompt_TotalUserGroups' => "(DEFAULT, 'In-Portal', 'SELECT COUNT(*) AS TotalUserGroups FROM <%prefix%>PortalGroup', NULL, 'la_prompt_TotalUserGroups', 0, 2)", + 'In-Portal;la_prompt_BannedUsers' => "(DEFAULT, 'In-Portal', 'SELECT COUNT(*) AS BannedUsers FROM <%prefix%>PortalUser WHERE IsBanned = 1', NULL, 'la_prompt_BannedUsers', 0, 2)", + 'In-Portal;la_prompt_NonExpiredSessions' => "(DEFAULT, 'In-Portal', 'SELECT COUNT(*) AS NonExipedSessions FROM <%prefix%>UserSession WHERE Status = 1', NULL, 'la_prompt_NonExpiredSessions', 0, 2)", + 'In-Portal;la_prompt_ThemeCount' => "(DEFAULT, 'In-Portal', 'SELECT COUNT(*) AS ThemeCount FROM <%prefix%>Theme', NULL, 'la_prompt_ThemeCount', 0, 2)", + 'In-Portal;la_prompt_RegionsCount' => "(DEFAULT, 'In-Portal', 'SELECT COUNT(*) AS RegionsCount FROM <%prefix%>Language', NULL, 'la_prompt_RegionsCount', 0, 2)", + 'In-Portal;la_prompt_TablesCount' => "(DEFAULT, 'In-Portal', '<%m:sql_action sql=\"SHOW+TABLES\" action=\"COUNT\" field=\"*\"%>', NULL, 'la_prompt_TablesCount', 0, 2)", + 'In-Portal;la_prompt_RecordsCount' => "(DEFAULT, 'In-Portal', '<%m:sql_action sql=\"SHOW+TABLE+STATUS\" action=\"SUM\" field=\"Rows\"%>', NULL, 'la_prompt_RecordsCount', 0, 2)", + 'In-Portal;la_prompt_SystemFileSize' => "(DEFAULT, 'In-Portal', '<%m:custom_action sql=\"empty\" action=\"SysFileSize\"%>', NULL, 'la_prompt_SystemFileSize', 0, 2)", + 'In-Portal;la_prompt_DataSize' => "(DEFAULT, 'In-Portal', '<%m:sql_action sql=\"SHOW+TABLE+STATUS\" action=\"SUM\" format_as=\"file\" field=\"Data_length\"%>', NULL, 'la_prompt_DataSize', 0, 2)", + ), + ), + + 'StylesheetSelectors' => Array ( + 'UniqueField' => 'SelectorId', + 'Records' => Array ( + '169' => "(169, 8, 'Calendar''s selected days', '.calendar tbody .selected', 'a:0:{}', '', 1, 'font-weight: bold;\\\r\\nbackground-color: #9ED7ED;\\r\\nborder: 1px solid #83B2C5;', 0)", + '118' => "(118, 8, 'Data grid row', 'td.block-data-row', 'a:0:{}', '', 2, 'border-bottom: 1px solid #cccccc;', 48)", + '81' => "(81, 8, '\"More\" link', 'a.link-more', 'a:0:{}', '', 2, 'text-decoration: underline;', 64)", + '88' => "(88, 8, 'Block data, separated rows', 'td.block-data-grid', 'a:0:{}', '', 2, 'border: 1px solid #cccccc;', 48)", + '42' => "(42, 8, 'Block Header', 'td.block-header', 'a:4:{s:5:\"color\";s:16:\"rgb(0, 159, 240)\";s:9:\"font-size\";s:4:\"20px\";s:11:\"font-weight\";s:6:\"normal\";s:7:\"padding\";s:3:\"5px\";}', 'Block Header', 1, 'font-family: Verdana, Helvetica, sans-serif;', 0)", + '76' => "(76, 8, 'Navigation bar menu', 'tr.head-nav td', 'a:0:{}', '', 1, 'vertical-align: middle;', 0)", + '48' => "(48, 8, 'Block data', 'td.block-data', 'a:2:{s:9:\"font-size\";s:5:\"12px;\";s:7:\"padding\";s:3:\"5px\";}', '', 1, '', 0)", + '78' => "(78, 8, 'Body main style', 'body', 'a:0:{}', '', 1, 'padding: 0px; \\r\\nbackground-color: #ffffff; \\r\\nfont-family: arial, verdana, helvetica; \\r\\nfont-size: small;\\r\\nwidth: auto;\\r\\nmargin: 0px;', 0)", + '58' => "(58, 8, 'Main table', 'table.main-table', 'a:0:{}', '', 1, 'width: 770px;\\r\\nmargin: 0px;\\r\\n/*table-layout: fixed;*/', 0)", + '79' => "(79, 8, 'Block: header of data block', 'span.block-data-grid-header', 'a:0:{}', '', 1, 'font-family: Arial, Helvetica, sans-serif;\\r\\ncolor: #009DF6;\\r\\nfont-size: 12px;\\r\\nfont-weight: bold;\\r\\nbackground-color: #E6EEFF;\\r\\npadding: 6px;\\r\\nwhite-space: nowrap;', 0)", + '64' => "(64, 8, 'Link', 'a', 'a:0:{}', '', 1, '', 0)", + '46' => "(46, 8, 'Product title link', 'a.link-product1', 'a:0:{}', 'Product title link', 1, 'color: #62A1DE;\\r\\nfont-size: 14px;\\r\\nfont-weight: bold;\\r\\nline-height: 20px;\\r\\npadding-bottom: 10px;', 0)", + '75' => "(75, 8, 'Copy of Main path link', 'table.main-path td a:hover', 'a:0:{}', '', 1, 'color: #ffffff;', 0)", + '160' => "(160, 8, 'Current item in navigation bar', '.checkout-step-current', 'a:0:{}', '', 1, 'color: #A20303;\\r\\nfont-weight: bold;', 0)", + '51' => "(51, 8, 'Right block data', 'td.right-block-data', 'a:1:{s:9:\"font-size\";s:4:\"11px\";}', '', 2, 'padding: 7px;\\r\\nbackground: #e3edf6 url(\"/in-commerce4/themes/default/img/bgr_login.jpg\") repeat-y scroll left top;\\r\\nborder-bottom: 1px solid #64a1df;', 48)", + '67' => "(67, 8, 'Pagination bar: text', 'table.block-pagination td', 'a:3:{s:5:\"color\";s:7:\"#8B898B\";s:9:\"font-size\";s:4:\"12px\";s:11:\"font-weight\";s:6:\"normal\";}', '', 1, '', 0)", + '45' => "(45, 8, 'Category link', 'a.subcat', 'a:0:{}', 'Category link', 1, 'color: #2069A4', 0)", + '68' => "(68, 8, 'Pagination bar: link', 'table.block-pagination td a', 'a:3:{s:5:\"color\";s:7:\"#8B898B\";s:9:\"font-size\";s:5:\"12px;\";s:11:\"font-weight\";s:6:\"normal\";}', '', 1, '', 0)", + '69' => "(69, 8, 'Product description in product list', '.product-list-description', 'a:2:{s:5:\"color\";s:7:\"#8B898B\";s:9:\"font-size\";s:4:\"12px\";}', '', 1, '', 0)", + '73' => "(73, 8, 'Main path link', 'table.main-path td a', 'a:0:{}', '', 1, 'color: #d5e231;', 0)", + '83' => "(83, 8, 'Product title link in list (shopping cart)', 'a.link-product-cart', 'a:0:{}', 'Product title link', 1, 'color: #18559C;\\r\\nfont-size: 12px;\\r\\nfont-weight: bold;\\r\\ntext-decoration: none;\\r\\n\\r\\n', 0)", + '72' => "(72, 8, 'Main path block text', 'table.main-path td', 'a:0:{}', '', 1, 'color: #ffffff;\\r\\nfont-size: 10px;\\r\\nfont-weight: normal;\\r\\npadding: 1px;\\r\\n', 0)", + '61' => "(61, 8, 'Block: header of data table', 'td.block-data-grid-header', 'a:6:{s:4:\"font\";s:28:\"Arial, Helvetica, sans-serif\";s:5:\"color\";s:7:\"#009DF6\";s:9:\"font-size\";s:4:\"12px\";s:11:\"font-weight\";s:4:\"bold\";s:16:\"background-color\";s:7:\"#E6EEFF\";s:7:\"padding\";s:3:\"6px\";}', '', 1, 'white-space: nowrap;\\r\\npadding-left: 10px;\\r\\n/*\\r\\nbackground-image: url(/in-commerce4/themes/default/img/bullet1.gif);\\r\\nbackground-position: 10px 12px;\\r\\nbackground-repeat: no-repeat;\\r\\n*/', 0)", + '65' => "(65, 8, 'Link in product list additional row', 'td.product-list-additional a', 'a:1:{s:5:\"color\";s:7:\"#8B898B\";}', '', 2, '', 64)", + '55' => "(55, 8, 'Main table, left column', 'td.main-column-left', 'a:0:{}', '', 1, 'width:180px;\\r\\nborder: 1px solid #62A1DE;\\r\\nborder-top: 0px;', 0)", + '70' => "(70, 8, 'Product title link in list (category)', 'a.link-product-category', 'a:0:{}', 'Product title link', 1, 'color: #18559C;\\r\\nfont-size: 12px;\\r\\nfont-weight: bold;\\r\\ntext-decoration: none;\\r\\n\\r\\n', 0)", + '66' => "(66, 8, 'Pagination bar block', 'table.block-pagination', 'a:0:{}', '', 1, '', 0)", + '49' => "(49, 8, 'Bulleted list inside block', 'td.block-data ul li', 'a:0:{}', '', 1, ' list-style-image: url(/in-commerce4/themes/default/img/bullet2.gif);\\r\\n margin-bottom: 10px;\\r\\n font-size: 11px;', 0)", + '87' => "(87, 8, 'Cart item input form element', 'td.cart-item-atributes input', 'a:0:{}', '', 1, 'border: 1px solid #7BB2E6;', 0)", + '119' => "(119, 8, 'Data grid row header', 'td.block-data-row-hdr', 'a:0:{}', 'Used in order preview', 2, 'background-color: #eeeeee;\\r\\nborder-bottom: 1px solid #dddddd;\\r\\nborder-top: 1px solid #cccccc;\\r\\nfont-weight: bold;', 48)", + '82' => "(82, 8, '\"More\" link image', 'a.link-more img', 'a:0:{}', '', 2, 'text-decoration: none;\\r\\npadding-left: 5px;', 64)", + '63' => "(63, 8, 'Additional info under product description in list', 'td.product-list-additional', 'a:5:{s:5:\"color\";s:7:\"#8B898B\";s:9:\"font-size\";s:4:\"11px\";s:11:\"font-weight\";s:6:\"normal\";s:10:\"border-top\";s:18:\"1px dashed #8B898B\";s:13:\"border-bottom\";s:18:\"1px dashed #8B898B\";}', '', 2, '', 48)", + '43' => "(43, 8, 'Block', 'table.block', 'a:2:{s:16:\"background-color\";s:7:\"#E3EEF9\";s:6:\"border\";s:17:\"1px solid #64A1DF\";}', 'Block', 1, 'border: 0; \\r\\nmargin-bottom: 1px;\\r\\nwidth: 100%;', 0)", + '84' => "(84, 8, 'Cart item cell', 'td.cart-item', 'a:0:{}', '', 1, 'background-color: #F6FAFF;\\r\\nborder-left: 1px solid #ffffff;\\r\\nborder-bottom: 1px solid #ffffff;\\r\\npadding: 4px;', 0)", + '57' => "(57, 8, 'Main table, right column', 'td.main-column-right', 'a:0:{}', '', 1, 'width:220px;\\r\\nborder: 1px solid #62A1DE;\\r\\nborder-top: 0px;', 0)", + '161' => "(161, 8, 'Block for sub categories', 'td.block-data-subcats', 'a:0:{}', '', 2, ' background: #FFFFFF\\r\\nurl(/in-commerce4/themes/default/in-commerce/img/bgr_categories.jpg);\\r\\n background-repeat: no-repeat;\\r\\n background-position: top right;\\r\\nborder-bottom: 5px solid #DEEAFF;\\r\\npadding-left: 10px;', 48)", + '77' => "(77, 8, 'Left block header', 'td.left-block-header', 'a:0:{}', '', 2, 'font-family : verdana, helvetica, sans-serif;\\r\\ncolor : #ffffff;\\r\\nfont-size : 12px;\\r\\nfont-weight : bold;\\r\\ntext-decoration : none;\\r\\nbackground-color: #64a1df;\\r\\npadding: 5px;\\r\\npadding-left: 7px;', 42)", + '80' => "(80, 8, 'Right block data - text', 'td.right-block-data td', 'a:1:{s:9:\"font-size\";s:5:\"11px;\";}', '', 2, '', 48)", + '53' => "(53, 8, 'Right block header', 'td.right-block-header', 'a:0:{}', '', 2, 'font-family : verdana, helvetica, sans-serif;\\r\\ncolor : #ffffff;\\r\\nfont-size : 12px;\\r\\nfont-weight : bold;\\r\\ntext-decoration : none;\\r\\nbackground-color: #64a1df;\\r\\npadding: 5px;\\r\\npadding-left: 7px;', 42)", + '85' => "(85, 8, 'Cart item cell with attributes', 'td.cart-item-attributes', 'a:0:{}', '', 1, 'background-color: #E6EEFF;\\r\\nborder-left: 1px solid #ffffff;\\r\\nborder-bottom: 1px solid #ffffff;\\r\\npadding: 4px;\\r\\ntext-align: center;\\r\\nvertical-align: middle;\\r\\nfont-size: 12px;\\r\\nfont-weight: normal;', 0)", + '86' => "(86, 8, 'Cart item cell with name', 'td.cart-item-name', 'a:0:{}', '', 1, 'background-color: #F6FAFF;\\r\\nborder-left: 1px solid #ffffff;\\r\\nborder-bottom: 1px solid #ffffff;\\r\\npadding: 3px;', 0)", + '47' => "(47, 8, 'Block content of featured product', 'td.featured-block-data', 'a:0:{}', '', 1, 'font-family: Arial,Helvetica,sans-serif;\\r\\nfont-size: 12px;', 0)", + '56' => "(56, 8, 'Main table, middle column', 'td.main-column-center', 'a:0:{}', '', 1, '\\r\\n', 0)", + '50' => "(50, 8, 'Product title link in list', 'a.link-product2', 'a:0:{}', 'Product title link', 1, 'color: #62A1DE;\\r\\nfont-size: 12px;\\r\\nfont-weight: bold;\\r\\ntext-decoration: none;\\r\\n\\r\\n', 0)", + '71' => "(71, 8, 'Main path block', 'table.main-path', 'a:0:{}', '', 1, 'background: #61b0ec url(\"/in-commerce4/themes/default/img/bgr_path.jpg\") repeat-y scroll left top;\\r\\nwidth: 100%;\\r\\nmargin-bottom: 1px;\\r\\nmargin-right: 1px; \\r\\nmargin-left: 1px;', 0)", + '62' => "(62, 8, 'Block: columns header for data table', 'table.block-no-border th', 'a:6:{s:4:\"font\";s:28:\"Arial, Helvetica, sans-serif\";s:5:\"color\";s:7:\"#18559C\";s:9:\"font-size\";s:4:\"11px\";s:11:\"font-weight\";s:4:\"bold\";s:16:\"background-color\";s:7:\"#B4D2EE\";s:7:\"padding\";s:3:\"6px\";}', '', 1, 'text-align: left;', 0)", + '59' => "(59, 8, 'Block without border', 'table.block-no-border', 'a:0:{}', '', 1, 'border: 0px; \\r\\nmargin-bottom: 10px;\\r\\nwidth: 100%;', 0)", + '74' => "(74, 8, 'Main path language selector cell', 'td.main-path-language', 'a:0:{}', '', 1, 'vertical-align: middle;\\r\\ntext-align: right;\\r\\npadding-right: 6px;', 0)", + '171' => "(171, 8, 'Calendar''s highlighted day', '.calendar tbody .hilite', 'a:0:{}', '', 1, 'background-color: #f6f6f6;\\r\\nborder: 1px solid #83B2C5 !important;', 0)", + '175' => "(175, 8, 'Calendar''s days', '.calendar tbody .day', 'a:0:{}', '', 1, 'text-align: right;\\r\\npadding: 2px 4px 2px 2px;\\r\\nwidth: 2em;\\r\\nborder: 1px solid #fefefe;', 0)", + '170' => "(170, 8, 'Calendar''s weekends', '.calendar .weekend', 'a:0:{}', '', 1, 'color: #990000;', 0)", + '173' => "(173, 8, 'Calendar''s control buttons', '.calendar .calendar_button', 'a:0:{}', '', 1, 'color: black;\\r\\nfont-size: 12px;\\r\\nbackground-color: #eeeeee;', 0)", + '174' => "(174, 8, 'Calendar''s day names', '.calendar thead .name', 'a:0:{}', '', 1, 'background-color: #DEEEF6;\\r\\nborder-bottom: 1px solid #000000;', 0)", + '172' => "(172, 8, 'Calendar''s top and bottom titles', '.calendar .title', 'a:0:{}', '', 1, 'color: #FFFFFF;\\r\\nbackground-color: #62A1DE;\\r\\nborder: 1px solid #107DC5;\\r\\nborder-top: 0px;\\r\\npadding: 1px;', 0)", + '60' => "(60, 8, 'Block header for featured product', 'td.featured-block-header', 'a:0:{}', '', 2, '\\r\\n', 42)", + '54' => "(54, 8, 'Right block', 'table.right-block', 'a:0:{}', '', 2, 'background-color: #E3EEF9;\\r\\nborder: 0px;\\r\\nwidth: 100%;', 43)", + '44' => "(44, 8, 'Block content', 'td.block-data-big', 'a:0:{}', 'Block content', 1, ' background: #DEEEF6\\r\\nurl(/in-commerce4/themes/default/img/menu_bg.gif);\\r\\n background-repeat: no-repeat;\\r\\n background-position: top right;\\r\\n', 0)", + ), + ), + + 'Stylesheets' => Array ( + 'UniqueField' => 'StylesheetId', + 'Records' => Array ( + '8' => "(8, 'Default', 'In-Portal Default Theme', '', 1124952555, 1)", + ), + ), + + 'Counters' => Array ( + 'UniqueField' => 'Name', + 'Records' => Array ( + 'members_count' => "(DEFAULT, 'members_count', 'SELECT COUNT(*) FROM <%PREFIX%>PortalUser WHERE Status = 1', NULL , NULL , '3600', '0', '|PortalUser|')", + 'members_online' => "(DEFAULT, 'members_online', 'SELECT COUNT(*) FROM <%PREFIX%>UserSession WHERE PortalUserId > 0', NULL , NULL , '3600', '0', '|UserSession|')", + 'guests_online' => "(DEFAULT, 'guests_online', 'SELECT COUNT(*) FROM <%PREFIX%>UserSession WHERE PortalUserId <= 0', NULL , NULL , '3600', '0', '|UserSession|')", + 'users_online' => "(DEFAULT, 'users_online', 'SELECT COUNT(*) FROM <%PREFIX%>UserSession', NULL , NULL , '3600', '0', '|UserSession|')", + ), + ), + ); + + // check & insert if not found defined before data + foreach ($data as $table_name => $table_info) { + $unique_fields = explode(';', $table_info['UniqueField']); + foreach ($table_info['Records'] as $unique_value => $insert_sql) { + $unique_values = explode(';', $unique_value); + + $where_clause = Array (); + foreach ($unique_fields as $field_index => $unique_field) { + $where_clause[] = $unique_field . ' = ' . $this->Conn->qstr($unique_values[$field_index]); + } + + $sql = 'SELECT ' . implode(', ', $unique_fields) . ' + FROM ' . TABLE_PREFIX . $table_name . ' + WHERE (' . implode(') AND (', $where_clause) . ')'; + $found = $this->Conn->GetRow($sql); + if ($found) { + $found = implode(';', $found); + } + + if ($found != $unique_value) { + $this->Conn->Query('INSERT INTO ' . TABLE_PREFIX . $table_name . ' VALUES ' . $insert_sql); + } + } + } + } + + /** + * Removes duplicate phrases per language basis (created during proj-base and in-portal shared installation) + * + */ + function _removeDuplicatePhrases() + { + $id_field = $this->Application->getUnitOption('phrases', 'IDField'); + $table_name = $this->Application->getUnitOption('phrases', 'TableName'); + + $sql = 'SELECT LanguageId, Phrase, MIN(LastChanged) AS LastChanged, COUNT(*) AS DupeCount + FROM ' . $table_name . ' + GROUP BY LanguageId, Phrase + HAVING COUNT(*) > 1'; + $duplicate_phrases = $this->Conn->Query($sql); + + foreach ($duplicate_phrases as $phrase_record) { + // 1. keep phrase, that was added first, because it is selected in PhrasesCache::LoadPhraseByLabel + $where_clause = Array ( + 'LanguageId = ' . $phrase_record['LanguageId'], + 'Phrase = ' . $this->Conn->qstr($phrase_record['Phrase']), + 'LastChanged' . ' = ' . $phrase_record['LastChanged'], + ); + + $sql = 'SELECT ' . $id_field . ' + FROM ' . $table_name . ' + WHERE (' . implode(') AND (', $where_clause) . ')'; + $phrase_id = $this->Conn->GetOne($sql); + + // 2. delete all other duplicates + $where_clause = Array ( + 'LanguageId = ' . $phrase_record['LanguageId'], + 'Phrase = ' . $this->Conn->qstr($phrase_record['Phrase']), + $id_field . ' <> ' . $phrase_id, + ); + + $sql = 'DELETE FROM ' . $table_name . ' + WHERE (' . implode(') AND (', $where_clause) . ')'; + $this->Conn->Query($sql); + } + } + + function _moveDatabaseFolders() + { + // Tables: PageContent, Images + if ($this->Conn->TableFound('PageContent', true)) { + // 1. replaces "/kernel/user_files/" references in content blocks + $ml_helper = $this->Application->recallObject('kMultiLanguageHelper'); + /* @var $ml_helper kMultiLanguageHelper */ + + $languages = $ml_helper->getLanguages(); + $replace_sql = '%1$s = REPLACE(%1$s, "/kernel/user_files/", "/system/user_files/")'; + + $update_sqls = Array (); + + foreach ($languages as $language_id) { + $update_sqls[] = sprintf($replace_sql, 'l' . $language_id . '_Content'); + } + + if ($update_sqls) { + $sql = 'UPDATE ' . TABLE_PREFIX . 'PageContent + SET ' . implode(', ', $update_sqls); + $this->Conn->Query($sql); + } + } + + // 2. replace path of images uploaded via "Images" tab of category items + $this->_replaceImageFolder('/kernel/images/', '/system/images/'); + + // 3. replace path of images uploaded via "Images" tab of category items (when badly formatted) + $this->_replaceImageFolder('kernel/images/', 'system/images/'); + + // 4. replace images uploaded via "In-Bulletin -> Emoticons" section + $this->_replaceImageFolder('in-bulletin/images/emoticons/', 'system/images/emoticons/'); + + // 5. update backup path in config + $this->_toolkit->saveConfigValues( + Array ( + 'Backup_Path' => FULL_PATH . '/system/backupdata' + ) + ); + } + + /** + * Replaces mentions of "/kernel/images" folder in Images table + * + * @param string $from + * @param string $to + */ + function _replaceImageFolder($from, $to) + { + $replace_sql = '%1$s = REPLACE(%1$s, "' . $from . '", "' . $to . '")'; + $sql = 'UPDATE ' . TABLE_PREFIX . 'Images + SET ' . sprintf($replace_sql, 'ThumbPath') . ', ' . sprintf($replace_sql, 'LocalPath'); + $this->Conn->Query($sql); + } + + + /** + * Update colors in skin (only if they were not changed manually) + * + * @param string $mode when called mode {before, after) + */ + function Upgrade_5_0_0($mode) + { + if ($mode == 'before') { + $this->_removeDuplicatePhrases(); // because In-Commerce & In-Link share some phrases with Proj-CMS + $this->_createProjCMSTables(); + $this->_addMissingConfigurationVariables(); + } + + if ($mode == 'after') { + $this->_fixSkinColors(); + $this->_restructureCatalog(); + $this->_sortImages(); + +// $this->_sortConfigurationVariables('In-Portal', 'in-portal:configure_general'); +// $this->_sortConfigurationVariables('In-Portal', 'in-portal:configure_advanced'); + } + } + + function _sortConfigurationVariables($module, $section) + { + $sql = 'SELECT ca.heading, cv.VariableName + FROM ' . TABLE_PREFIX . 'ConfigurationAdmin ca + LEFT JOIN ' . TABLE_PREFIX . 'ConfigurationValues cv USING(VariableName) + WHERE (cv.ModuleOwner = ' . $this->Conn->qstr($module) . ') AND (cv.Section = ' . $this->Conn->qstr($section) . ') + ORDER BY ca.DisplayOrder asc, ca.GroupDisplayOrder asc'; + $variables = $this->Conn->GetCol($sql, 'VariableName'); + + if (!$variables) { + return ; + } + + $variables = $this->_groupRecords($variables); + + $group_number = 0; + $variable_order = 1; + + $prev_heading = ''; + + foreach ($variables as $variable_name => $variable_heading) { + if ($prev_heading != $variable_heading) { + $group_number++; + $variable_order = 1; + } + + $sql = 'UPDATE ' . TABLE_PREFIX . 'ConfigurationAdmin + SET DisplayOrder = ' . $this->Conn->qstr($group_number * 10 + $variable_order / 100) . ' + WHERE VariableName = ' . $this->Conn->qstr($variable_name); + $this->Conn->Query($sql); + + $variable_order++; + $prev_heading = $variable_heading; + } + } + + /** + * Group list records by header, saves internal order in group + * + * @param Array $variables + * @return Array + */ + function _groupRecords($variables) + { + $sorted = Array(); + + foreach ($variables as $variable_name => $variable_heading) { + $sorted[$variable_heading][] = $variable_name; + } + + $variables = Array(); + foreach ($sorted as $heading => $heading_records) { + foreach ($heading_records as $variable_name) { + $variables[$variable_name] = $heading; + } + } + + return $variables; + } + + /** + * Returns module root category + * + * @param string $module_name + * @param string $module_prefix + * @return int + */ + function _getRootCategory($module_name, $module_prefix) + { + // don't cache anything here (like in static variables), because database value is changed on the fly !!! + $sql = 'SELECT RootCat + FROM ' . TABLE_PREFIX . 'Modules + WHERE LOWER(Name) = ' . $this->Conn->qstr( strtolower($module_name) ); + $root_category = $this->Conn->GetOne($sql); + + // put to cache too, because CategoriesEventHandler::_prepareAutoPage uses kApplication::findModule + $this->Application->ModuleInfo[$module_name]['Name'] = $module_name; + $this->Application->ModuleInfo[$module_name]['RootCat'] = $root_category; + $this->Application->ModuleInfo[$module_name]['Var'] = $module_prefix; + + return $root_category; + } + + /** + * Move all categories (except "Content") from "Home" to "Content" category and hide them from menu + * + */ + function _restructureCatalog() + { + $root_category = $this->_getRootCategory('Core', 'adm'); + + $sql = 'SELECT CategoryId + FROM ' . TABLE_PREFIX . 'Category + WHERE ParentId = 0 AND CategoryId <> ' . $root_category; + $top_categories = $this->Conn->GetCol($sql); + + if ($top_categories) { + // hide all categories located outside "Content" category from menu + $sql = 'UPDATE ' . TABLE_PREFIX . 'Category + SET IsMenu = 0 + WHERE (ParentPath LIKE "|' . implode('|%") OR (ParentPath LIKE "|', $top_categories) . '|%")'; + $this->Conn->Query($sql); + + // move all top level categories under "Content" category and make them visible in menu + $sql = 'UPDATE ' . TABLE_PREFIX . 'Category + SET IsMenu = 1, ParentId = ' . $root_category . ' + WHERE ParentId = 0 AND CategoryId <> ' . $root_category; + $this->Conn->Query($sql); + } + + // make sure, that all categories have valid value for Priority field + + $priority_helper = $this->Application->recallObject('PriorityHelper'); + /* @var $priority_helper kPriorityHelper */ + + $event = new kEvent('c:OnListBuild'); + + // update all categories, because they are all under "Content" category now + $sql = 'SELECT CategoryId + FROM ' . TABLE_PREFIX . 'Category'; + $categories = $this->Conn->GetCol($sql); + + foreach ($categories as $category_id) { + $priority_helper->recalculatePriorities($event, 'ParentId = ' . $category_id); + } + + // create initial theme structure in Category table + $this->_toolkit->rebuildThemes(); + + // make sure, that all system templates have ThemeId set (only possible during platform project upgrade) + $sql = 'SELECT ThemeId + FROM ' . TABLE_PREFIX . 'Theme + WHERE PrimaryTheme = 1'; + $primary_theme_id = $this->Conn->GetOne($sql); + + if ($primary_theme_id) { + $sql = 'UPDATE ' . TABLE_PREFIX . 'Category + SET ThemeId = ' . $primary_theme_id . ' + WHERE IsSystem = 1 AND ThemeId = 0'; + $this->Conn->Query($sql); + } + } + + /** + * Changes skin colors to match new ones (only in case, when they match default values) + * + */ + function _fixSkinColors() + { + $skin = $this->Application->recallObject('skin', null, Array ('skip_autoload' => 1)); + /* @var $skin kDBItem */ + + $skin->Load(1, 'IsPrimary'); + if ($skin->isLoaded()) { + $skin_options = unserialize( $skin->GetDBField('Options') ); + + $changes = Array ( + // option: from -> to + 'HeadBgColor' => Array ('#1961B8', '#007BF4'), + 'HeadBarColor' => Array ('#FFFFFF', '#000000'), + + 'HeadColor' => Array ('#CCFF00', '#FFFFFF'), + 'TreeColor' => Array ('#006F99', '#000000'), + 'TreeHoverColor' => Array ('', '#009FF0'), + 'TreeHighHoverColor' => Array ('', '#FFFFFF'), + 'TreeHighBgColor' => Array ('#4A92CE', '#4A92CE'), + 'TreeBgColor' => Array ('#FFFFFF', '#DCECF6'), + ); + + $can_change = true; + foreach ($changes as $option_name => $change) { + list ($change_from, $change_to) = $change; + + $can_change = $can_change && ($change_from == $skin_options[$option_name]['Value']); + if ($can_change) { + $skin_options[$option_name]['Value'] = $change_to; + } + } + + if ($can_change) { + $skin->SetDBField('Options', serialize($skin_options)); + $skin->Update(); + + $skin_helper = $this->Application->recallObject('SkinHelper'); + /* @var $skin_helper SkinHelper */ + + $skin_file = $skin_helper->getSkinPath(); + if (file_exists($skin_file)) { + unlink($skin_file); + } + } + } + } + + /** + * 1. Set root category not to generate filename automatically and hide it from catalog + * 2. Hide root category of In-Edit and set it's fields + * + * @param int $category_id + */ + function _resetRootCategory($category_id) + { + $fields_hash = Array ( + 'l1_Name' => 'Content', 'Filename' => 'Content', 'AutomaticFilename' => 0, + 'l1_Description' => 'Content', 'Status' => 4, + ); + + $this->Conn->doUpdate($fields_hash, TABLE_PREFIX . 'Category', 'CategoryId = ' . $category_id); + } + + function _createProjCMSTables() + { + // 0. make sure, that Content category exists + $root_category = $this->_getRootCategory('Proj-CMS', 'st'); + if ($root_category) { + // proj-cms module found -> remove it + $sql = 'DELETE FROM ' . TABLE_PREFIX . 'Modules + WHERE Name = "Proj-CMS"'; + $this->Conn->Query($sql); + unset($this->Application->ModuleInfo['Proj-CMS']); + + $this->_resetRootCategory($root_category); + + // unhide all structure categories + $sql = 'UPDATE ' . TABLE_PREFIX . 'Category + SET Status = 1 + WHERE (Status = 4) AND (CategoryId <> ' . $root_category . ')'; + $this->Conn->Query($sql); + } else { + $root_category = $this->_getRootCategory('In-Edit', 'cms'); + if ($root_category) { + // in-edit module found -> remove it + $sql = 'DELETE FROM ' . TABLE_PREFIX . 'Modules + WHERE Name = "In-Edit"'; + $this->Conn->Query($sql); + unset($this->Application->ModuleInfo['In-Edit']); + + $this->_resetRootCategory($root_category); + } + } + + if (!$root_category) { + // create "Content" category when Proj-CMS/In-Edit module was not installed before + // use direct sql here, because category table structure doesn't yet match table structure in object + + $fields_hash = Array ( + 'l1_Name' => 'Content', 'Filename' => 'Content', 'AutomaticFilename' => 0, + 'l1_Description' => 'Content', 'Status' => 4, + ); + + $this->Conn->doInsert($fields_hash, TABLE_PREFIX . 'Category'); + + $root_category = $this->Conn->getInsertID(); + } + + $this->_toolkit->deleteCache(); + $this->_toolkit->SetModuleRootCategory('Core', $root_category); + + // 1. process "Category" table + $structure = $this->Conn->Query('DESCRIBE ' . TABLE_PREFIX . 'Category', 'Field'); + if (!array_key_exists('Template', $structure)) { + // fields from "Pages" table were not added to "Category" table (like before "Proj-CMS" module install) + $sql = "ALTER TABLE " . TABLE_PREFIX . "Category + ADD COLUMN Template varchar(255) default NULL, + ADD COLUMN l1_Title varchar(255) default '', + ADD COLUMN l2_Title varchar(255) default '', + ADD COLUMN l3_Title varchar(255) default '', + ADD COLUMN l4_Title varchar(255) default '', + ADD COLUMN l5_Title varchar(255) default '', + ADD COLUMN l1_MenuTitle varchar(255) NOT NULL default '', + ADD COLUMN l2_MenuTitle varchar(255) NOT NULL default '', + ADD COLUMN l3_MenuTitle varchar(255) NOT NULL default '', + ADD COLUMN l4_MenuTitle varchar(255) NOT NULL default '', + ADD COLUMN l5_MenuTitle varchar(255) NOT NULL default '', + ADD COLUMN MetaTitle text, + ADD COLUMN IndexTools text, + ADD COLUMN IsIndex tinyint(1) NOT NULL default '0', + ADD COLUMN IsMenu TINYINT(4) NOT NULL DEFAULT '1', + ADD COLUMN IsSystem tinyint(4) NOT NULL default '0', + ADD COLUMN FormId int(11) default NULL, + ADD COLUMN FormSubmittedTemplate varchar(255) default NULL, + ADD COLUMN l1_Translated tinyint(4) NOT NULL default '0', + ADD COLUMN l2_Translated tinyint(4) NOT NULL default '0', + ADD COLUMN l3_Translated tinyint(4) NOT NULL default '0', + ADD COLUMN l4_Translated tinyint(4) NOT NULL default '0', + ADD COLUMN l5_Translated tinyint(4) NOT NULL default '0', + ADD COLUMN FriendlyURL varchar(255) NOT NULL default '', + ADD INDEX IsIndex (IsIndex), + ADD INDEX l1_Translated (l1_Translated), + ADD INDEX l2_Translated (l2_Translated), + ADD INDEX l3_Translated (l3_Translated), + ADD INDEX l4_Translated (l4_Translated), + ADD INDEX l5_Translated (l5_Translated)"; + $this->Conn->Query($sql); + } + + if (array_key_exists('Path', $structure)) { + $sql = 'ALTER TABLE ' . TABLE_PREFIX . 'Category + DROP Path'; + $this->Conn->Query($sql); + } + + // 2. process "PageContent" table + if ($this->Conn->TableFound(TABLE_PREFIX . 'PageContent', true)) { + $structure = $this->Conn->Query('DESCRIBE ' . TABLE_PREFIX . 'PageContent', 'Field'); + if (!array_key_exists('l1_Translated', $structure)) { + $sql = "ALTER TABLE " . TABLE_PREFIX . "PageContent + ADD COLUMN l1_Translated tinyint(4) NOT NULL default '0', + ADD COLUMN l2_Translated tinyint(4) NOT NULL default '0', + ADD COLUMN l3_Translated tinyint(4) NOT NULL default '0', + ADD COLUMN l4_Translated tinyint(4) NOT NULL default '0', + ADD COLUMN l5_Translated tinyint(4) NOT NULL default '0'"; + $this->Conn->Query($sql); + } + } + + // 3. process "FormFields" table + if ($this->Conn->TableFound(TABLE_PREFIX . 'FormFields', true)) { + $structure = $this->Conn->Query('DESCRIBE ' . TABLE_PREFIX . 'FormFields', 'Field'); + if (!$structure['FormId']['Key']) { + $sql = "ALTER TABLE " . TABLE_PREFIX . "FormFields + CHANGE Validation Validation TINYINT NOT NULL DEFAULT '0', + ADD INDEX FormId (FormId), + ADD INDEX Priority (Priority), + ADD INDEX IsSystem (IsSystem), + ADD INDEX DisplayInGrid (DisplayInGrid)"; + $this->Conn->Query($sql); + } + } + else { + $this->Conn->Query("INSERT INTO " . TABLE_PREFIX . "Permissions VALUES (DEFAULT, 'in-portal:forms.view', 11, 1, 1, 0)"); + $this->Conn->Query("INSERT INTO " . TABLE_PREFIX . "Permissions VALUES (DEFAULT, 'in-portal:forms.add', 11, 1, 1, 0)"); + $this->Conn->Query("INSERT INTO " . TABLE_PREFIX . "Permissions VALUES (DEFAULT, 'in-portal:forms.edit', 11, 1, 1, 0)"); + $this->Conn->Query("INSERT INTO " . TABLE_PREFIX . "Permissions VALUES (DEFAULT, 'in-portal:forms.delete', 11, 1, 1, 0)"); + } + + // 4. process "FormSubmissions" table + if ($this->Conn->TableFound(TABLE_PREFIX . 'FormSubmissions', true)) { + $structure = $this->Conn->Query('DESCRIBE ' . TABLE_PREFIX . 'FormSubmissions', 'Field'); + if (!$structure['SubmissionTime']['Key']) { + $sql = "ALTER TABLE " . TABLE_PREFIX . "FormSubmissions + ADD INDEX SubmissionTime (SubmissionTime)"; + $this->Conn->Query($sql); + } + } + else { + $this->Conn->Query("INSERT INTO " . TABLE_PREFIX . "Permissions VALUES (DEFAULT, 'in-portal:submissions.view', 11, 1, 1, 0)"); + } + + // 5. add missing event + $sql = 'SELECT EventId + FROM ' . TABLE_PREFIX . 'Events + WHERE (Event = "FORM.SUBMITTED") AND (Type = 1)'; + $event_id = $this->Conn->GetOne($sql); + + if (!$event_id) { + $sql = "INSERT INTO " . TABLE_PREFIX . "Events VALUES (DEFAULT, 'FORM.SUBMITTED', NULL, 1, 0, 'Core:Category', 'la_event_FormSubmitted', 1)"; + $this->Conn->Query($sql); + } + + $sql = 'SELECT EventId + FROM ' . TABLE_PREFIX . 'Events + WHERE (Event = "FORM.SUBMITTED") AND (Type = 0)'; + $event_id = $this->Conn->GetOne($sql); + + if (!$event_id) { + $sql = "INSERT INTO " . TABLE_PREFIX . "Events VALUES (DEFAULT, 'FORM.SUBMITTED', NULL, 1, 0, 'Core:Category', 'la_event_FormSubmitted', 0)"; + $this->Conn->Query($sql); + } + } + + function _addMissingConfigurationVariables() + { + $variables = Array ( + 'cms_DefaultDesign' => Array ( + "INSERT INTO " . TABLE_PREFIX . "ConfigurationAdmin VALUES ('cms_DefaultDesign', 'la_Text_General', 'la_prompt_DefaultDesignTemplate', 'text', NULL, NULL, 10.15, 0, 0)", + "INSERT INTO " . TABLE_PREFIX . "ConfigurationValues VALUES (DEFAULT, 'cms_DefaultDesign', '/platform/designs/general', 'In-Portal', 'in-portal:configure_categories')", + ), + + 'Require_AdminSSL' => Array ( + "INSERT INTO " . TABLE_PREFIX . "ConfigurationAdmin VALUES ('Require_AdminSSL', 'la_Text_Website', 'la_config_RequireSSLAdmin', 'checkbox', '', '', 10.105, 0, 1)", + "INSERT INTO " . TABLE_PREFIX . "ConfigurationValues VALUES (DEFAULT, 'Require_AdminSSL', '', 'In-Portal', 'in-portal:configure_advanced')", + ), + + 'UsePopups' => Array ( + "INSERT INTO " . TABLE_PREFIX . "ConfigurationAdmin VALUES ('UsePopups', 'la_Text_Website', 'la_config_UsePopups', 'radio', '', '1=la_Yes,0=la_No', 10.221, 0, 0)", + "INSERT INTO " . TABLE_PREFIX . "ConfigurationValues VALUES (DEFAULT, 'UsePopups', '1', 'In-Portal', 'in-portal:configure_advanced')", + ), + + 'UseDoubleSorting' => Array ( + "INSERT INTO " . TABLE_PREFIX . "ConfigurationAdmin VALUES ('UseDoubleSorting', 'la_Text_Website', 'la_config_UseDoubleSorting', 'radio', '', '1=la_Yes,0=la_No', 10.222, 0, 0)", + "INSERT INTO " . TABLE_PREFIX . "ConfigurationValues VALUES (DEFAULT, 'UseDoubleSorting', '0', 'In-Portal', 'in-portal:configure_advanced')", + ), + + 'MenuFrameWidth' => Array ( + "INSERT INTO " . TABLE_PREFIX . "ConfigurationAdmin VALUES ('MenuFrameWidth', 'la_title_General', 'la_prompt_MenuFrameWidth', 'text', NULL, NULL, 10.31, 0, 0)", + "INSERT INTO " . TABLE_PREFIX . "ConfigurationValues VALUES (DEFAULT, 'MenuFrameWidth', 200, 'In-Portal', 'in-portal:configure_advanced')", + ), + + 'DefaultSettingsUserId' => Array ( + "INSERT INTO " . TABLE_PREFIX . "ConfigurationAdmin VALUES ('DefaultSettingsUserId', 'la_title_General', 'la_prompt_DefaultUserId', 'text', NULL, NULL, '10.06', '0', '0')", + "INSERT INTO " . TABLE_PREFIX . "ConfigurationValues VALUES (DEFAULT, 'DefaultSettingsUserId', -1, 'In-Portal:Users', 'in-portal:configure_users')", + ), + ); + + foreach ($variables as $variable_name => $variable_sqls) { + $sql = 'SELECT VariableId + FROM ' . TABLE_PREFIX . 'ConfigurationValues + WHERE VariableName = ' . $this->Conn->qstr($variable_name); + $variable_id = $this->Conn->GetOne($sql); + + if ($variable_id) { + continue; + } + + foreach ($variable_sqls as $variable_sql) { + $this->Conn->Query($variable_sql); + } + } + } + + /** + * Sort images in database (update Priority field) + * + */ + function _sortImages() + { + $sql = 'SELECT * + FROM ' . TABLE_PREFIX . 'Images + ORDER BY ResourceId ASC , DefaultImg DESC , ImageId ASC'; + $images = $this->Conn->Query($sql); + + $priority = 0; + $last_resource_id = false; + + foreach ($images as $image) { + if ($image['ResourceId'] != $last_resource_id) { + // each item have own priorities among it's images + $priority = 0; + $last_resource_id = $image['ResourceId']; + } + + if (!$image['DefaultImg']) { + $priority--; + } + + $sql = 'UPDATE ' . TABLE_PREFIX . 'Images + SET Priority = ' . $priority . ' + WHERE ImageId = ' . $image['ImageId']; + $this->Conn->Query($sql); + } + } + + /** + * Update to 5.0.1 + * + * @param string $mode when called mode {before, after) + */ + function Upgrade_5_0_1($mode) + { + if ($mode == 'after') { + // delete old events + $events_to_delete = Array ('CATEGORY.MODIFY', 'CATEGORY.DELETE'); + + $sql = 'SELECT EventId + FROM ' . TABLE_PREFIX . 'Events + WHERE Event IN ("' . implode('","', $events_to_delete) . '")'; + $event_ids = $this->Conn->GetCol($sql); + + if ($event_ids) { + $this->_deleteEvents($event_ids); + + $sql = 'DELETE FROM ' . TABLE_PREFIX . 'Phrase + WHERE Phrase IN ("la_event_category.modify", "la_event_category.delete")'; + $this->Conn->Query($sql); + } + + // partially delete events + $sql = 'SELECT EventId + FROM ' . TABLE_PREFIX . 'Events + WHERE (Event IN ("CATEGORY.APPROVE", "CATEGORY.DENY")) AND (Type = ' . EmailEvent::EVENT_TYPE_ADMIN . ')'; + $event_ids = $this->Conn->GetCol($sql); + + if ($event_ids) { + $this->_deleteEvents($event_ids); + } + } + } + + function _deleteEvents($ids) + { + $sql = 'DELETE FROM ' . TABLE_PREFIX . 'EmailMessage + WHERE EventId IN (' . implode(',', $ids) . ')'; + $this->Conn->Query($sql); + + $sql = 'DELETE FROM ' . TABLE_PREFIX . 'Events + WHERE EventId IN (' . implode(',', $ids) . ')'; + $this->Conn->Query($sql); + } + + /** + * Update to 5.0.2-B2; Transforms IsIndex field values to SymLinkCategoryId field + * + * @param string $mode when called mode {before, after) + */ + function Upgrade_5_0_2_B2($mode) + { + // 0 - Regular, 1 - Category Index, 2 - Container + + if ($mode == 'before') { + // fix "Content" category + $fields_hash = Array ( + 'CreatedById' => USER_ROOT, + 'CreatedOn' => time(), + 'ResourceId' => $this->Application->NextResourceId(), + ); + + $category_id = $this->Application->findModule('Name', 'Core', 'RootCat'); + $this->Conn->doUpdate($fields_hash, TABLE_PREFIX . 'Category', 'CategoryId = ' . $category_id); + + // get all categories, marked as category index + $sql = 'SELECT ParentPath, CategoryId + FROM ' . TABLE_PREFIX . 'Category + WHERE IsIndex = 1'; + $category_indexes = $this->Conn->GetCol($sql, 'CategoryId'); + + foreach ($category_indexes as $category_id => $parent_path) { + $parent_path = explode('|', substr($parent_path, 1, -1)); + + // set symlink to $category_id for each category, marked as container in given category path + $sql = 'SELECT CategoryId + FROM ' . TABLE_PREFIX . 'Category + WHERE CategoryId IN (' . implode(',', $parent_path) . ') AND (IsIndex = 2)'; + $category_containers = $this->Conn->GetCol($sql); + + if ($category_containers) { + $sql = 'UPDATE ' . TABLE_PREFIX . 'Category + SET SymLinkCategoryId = ' . $category_id . ' + WHERE CategoryId IN (' . implode(',', $category_containers) . ')'; + $this->Conn->Query($sql); + } + + } + } + + if ($mode == 'after') { + // scan theme to fill Theme.TemplateAliases and ThemeFiles.TemplateAlias fields + $this->_toolkit->rebuildThemes(); + + $sql = 'SELECT TemplateAliases, ThemeId + FROM ' . TABLE_PREFIX . 'Theme + WHERE (Enabled = 1) AND (TemplateAliases <> "")'; + $template_aliases = $this->Conn->GetCol($sql, 'ThemeId'); + + $all_template_aliases = Array (); // reversed alias (from real template to alias) + + foreach ($template_aliases as $theme_id => $theme_template_aliases) { + $theme_template_aliases = unserialize($theme_template_aliases); + + if (!$theme_template_aliases) { + continue; + } + + $all_template_aliases = array_merge($all_template_aliases, array_flip($theme_template_aliases)); + } + + $default_design_replaced = false; + $default_design = trim($this->Application->ConfigValue('cms_DefaultDesign'), '/'); + + foreach ($all_template_aliases as $from_template => $to_alias) { + // replace default design in configuration variable (when matches alias) + if ($from_template == $default_design) { + // specific alias matched + $sql = 'UPDATE ' . TABLE_PREFIX . 'ConfigurationValues + SET VariableValue = ' . $this->Conn->qstr($to_alias) . ' + WHERE VariableName = "cms_DefaultDesign"'; + $this->Conn->Query($sql); + + $default_design_replaced = true; + } + + // replace Category.Template and Category.CachedTemplate fields (when matches alias) + $sql = 'UPDATE ' . TABLE_PREFIX . 'Category + SET Template = ' . $this->Conn->qstr($to_alias) . ' + WHERE Template IN (' . $this->Conn->qstr('/' . $from_template) . ',' . $this->Conn->qstr($from_template) . ')'; + $this->Conn->Query($sql); + + $sql = 'UPDATE ' . TABLE_PREFIX . 'Category + SET CachedTemplate = ' . $this->Conn->qstr($to_alias) . ' + WHERE CachedTemplate IN (' . $this->Conn->qstr('/' . $from_template) . ',' . $this->Conn->qstr($from_template) . ')'; + $this->Conn->Query($sql); + } + + if (!$default_design_replaced) { + // in case if current default design template doesn't + // match any of aliases, then set it to #default_design# + $sql = 'UPDATE ' . TABLE_PREFIX . 'ConfigurationValues + SET VariableValue = "#default_design#" + WHERE VariableName = "cms_DefaultDesign"'; + $this->Conn->Query($sql); + } + + // replace data in category custom fields used for category item template storage + $rewrite_processor = $this->Application->recallObject('kRewriteUrlProcessor'); + /* @var $rewrite_processor kRewriteUrlProcessor */ + + foreach ($this->Application->ModuleInfo as $module_name => $module_info) { + $custom_field_id = $rewrite_processor->getItemTemplateCustomField($module_info['Var']); + + if (!$custom_field_id) { + continue; + } + + foreach ($all_template_aliases as $from_template => $to_alias) { + $sql = 'UPDATE ' . TABLE_PREFIX . 'CategoryCustomData + SET l1_cust_' . $custom_field_id . ' = ' . $this->Conn->qstr($to_alias) . ' + WHERE l1_cust_' . $custom_field_id . ' = ' . $this->Conn->qstr($from_template); + $this->Conn->Query($sql); + } + } + } + } + + /** + * Update to 5.0.3-B2; Moves CATEGORY.* permission from module root categories to Content category + * + * @param string $mode when called mode {before, after) + */ + function Upgrade_5_0_3_B2($mode) + { + if ($mode == 'before') { + // get permissions + $sql = 'SELECT PermissionName + FROM ' . TABLE_PREFIX . 'PermissionConfig + WHERE PermissionName LIKE "CATEGORY.%"'; + $permission_names = $this->Conn->GetCol($sql); + + // get groups + $sql = 'SELECT GroupId + FROM ' . TABLE_PREFIX . 'PortalGroup'; + $user_groups = $this->Conn->GetCol($sql); + $user_group_count = count($user_groups); + + // get module root categories + $sql = 'SELECT RootCat + FROM ' . TABLE_PREFIX . 'Modules'; + $module_categories = $this->Conn->GetCol($sql); + + $module_categories[] = 0; + $module_categories = implode(',', array_unique($module_categories)); + + $permissions = $delete_permission_ids = Array (); + + foreach ($permission_names as $permission_name) { + foreach ($user_groups as $group_id) { + $sql = 'SELECT PermissionId + FROM ' . TABLE_PREFIX . 'Permissions + WHERE (Permission = ' . $this->Conn->qstr($permission_name) . ') AND (PermissionValue = 1) AND (GroupId = ' . $group_id . ') AND (`Type` = 0) AND (CatId IN (' . $module_categories . '))'; + $permission_ids = $this->Conn->GetCol($sql); + + if ($permission_ids) { + if (!array_key_exists($permission_name, $permissions)) { + $permissions[$permission_name] = Array (); + } + + $permissions[$permission_name][] = $group_id; + $delete_permission_ids = array_merge($delete_permission_ids, $permission_ids); + } + } + } + + if ($delete_permission_ids) { + // here we can delete some of permissions that will be added later + $sql = 'DELETE FROM ' . TABLE_PREFIX . 'Permissions + WHERE PermissionId IN (' . implode(',', $delete_permission_ids) . ')'; + $this->Conn->Query($sql); + } + + $home_category = $this->Application->findModule('Name', 'Core', 'RootCat'); + + foreach ($permissions as $permission_name => $permission_groups) { + // optimize a bit + $has_everyone = in_array(15, $permission_groups); + + if ($has_everyone || (!$has_everyone && count($permission_groups) == $user_group_count - 1)) { + // has permission for "Everyone" group OR allowed in all groups except "Everyone" group + // so remove all other explicitly allowed permissions + $permission_groups = Array (15); + } + + foreach ($permission_groups as $group_id) { + $fields_hash = Array ( + 'Permission' => $permission_name, + 'GroupId' => $group_id, + 'PermissionValue' => 1, + 'Type' => 0, // category-based permission, + 'CatId' => $home_category, + ); + + $this->Conn->doInsert($fields_hash, TABLE_PREFIX . 'Permissions'); + } + } + + $updater = $this->Application->makeClass('kPermCacheUpdater'); + /* @var $updater kPermCacheUpdater */ + + $updater->OneStepRun(); + } + } + + /** + * Update to 5.1.0-B1; Makes email message fields multilingual + * + * @param string $mode when called mode {before, after) + */ + function Upgrade_5_1_0_B1($mode) + { + if ( $mode == 'before' ) { + $this->_renameTables('from'); + + // migrate email events + $table_structure = $this->Conn->Query('DESCRIBE ' . TABLE_PREFIX . 'Events', 'Field'); + + if (!array_key_exists('Headers', $table_structure)) { + $sql = 'ALTER TABLE ' . TABLE_PREFIX . 'Events + ADD `Headers` TEXT NULL AFTER `ReplacementTags`, + ADD `MessageType` VARCHAR(4) NOT NULL default "text" AFTER `Headers`'; + $this->Conn->Query($sql); + } + + // alter here, because kMultiLanguageHelper::createFields + // method, called after will expect that to be in database + $sql = 'ALTER TABLE ' . TABLE_PREFIX . 'Events + ADD AllowChangingSender TINYINT NOT NULL DEFAULT "0" AFTER MessageType , + ADD CustomSender TINYINT NOT NULL DEFAULT "0" AFTER AllowChangingSender , + ADD SenderName VARCHAR(255) NOT NULL DEFAULT "" AFTER CustomSender , + ADD SenderAddressType TINYINT NOT NULL DEFAULT "0" AFTER SenderName , + ADD SenderAddress VARCHAR(255) NOT NULL DEFAULT "" AFTER SenderAddressType , + ADD AllowChangingRecipient TINYINT NOT NULL DEFAULT "0" AFTER SenderAddress , + ADD CustomRecipient TINYINT NOT NULL DEFAULT "0" AFTER AllowChangingRecipient , + ADD Recipients TEXT AFTER CustomRecipient, + ADD INDEX (AllowChangingSender), + ADD INDEX (CustomSender), + ADD INDEX (SenderAddressType), + ADD INDEX (AllowChangingRecipient), + ADD INDEX (CustomRecipient)'; + $this->Conn->Query($sql); + + // create multilingual fields for phrases and email events + $ml_helper = $this->Application->recallObject('kMultiLanguageHelper'); + /* @var $ml_helper kMultiLanguageHelper */ + + $ml_helper->createFields('phrases'); + $ml_helper->createFields('emailevents'); + $languages = $ml_helper->getLanguages(); + + if ($this->Conn->TableFound(TABLE_PREFIX . 'EmailMessage', true)) { + $email_message_helper = $this->Application->recallObject('kEmailMessageHelper'); + /* @var $email_message_helper kEmailMessageHelper */ + + foreach ($languages as $language_id) { + $sql = 'SELECT EmailMessageId, Template, EventId + FROM ' . TABLE_PREFIX . 'EmailMessage + WHERE LanguageId = ' . $language_id; + $translations = $this->Conn->Query($sql, 'EventId'); + + foreach ($translations as $event_id => $translation_data) { + $parsed = $email_message_helper->parseTemplate($translation_data['Template'], 'html'); + + $fields_hash = Array ( + 'l' . $language_id . '_Subject' => $parsed['Subject'], + 'l' . $language_id . '_Body' => $parsed['HtmlBody'], + ); + + if ( $parsed['Headers'] ) { + $fields_hash['Headers'] = $parsed['Headers']; + } + + $this->Conn->doUpdate($fields_hash, TABLE_PREFIX . 'Events', 'EventId = ' . $event_id); + + $sql = 'DELETE FROM ' . TABLE_PREFIX . 'EmailMessage + WHERE EmailMessageId = ' . $translation_data['EmailMessageId']; + $this->Conn->Query($sql); + } + } + } + + // migrate phrases + $temp_table = $this->Application->GetTempName(TABLE_PREFIX . 'Phrase'); + + $sqls = Array ( + 'DROP TABLE IF EXISTS ' . $temp_table, + 'CREATE TABLE ' . $temp_table . ' LIKE ' . TABLE_PREFIX . 'Phrase', + 'ALTER TABLE ' . $temp_table . ' DROP LanguageId, DROP Translation', + 'ALTER IGNORE TABLE ' . $temp_table . ' DROP INDEX LanguageId_2', + 'ALTER TABLE ' . $temp_table . ' DROP PhraseId', + 'ALTER TABLE ' . $temp_table . ' ADD PhraseId INT NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST', + ); + + foreach ($sqls as $sql) { + $this->Conn->Query($sql); + } + + $already_added = Array (); + $primary_language_id = $this->Application->GetDefaultLanguageId(); + + foreach ($languages as $language_id) { + $sql = 'SELECT Phrase, PhraseKey, Translation AS l' . $language_id . '_Translation, PhraseType, LastChanged, LastChangeIP, Module + FROM ' . TABLE_PREFIX . 'Phrase + WHERE LanguageId = ' . $language_id; + $phrases = $this->Conn->Query($sql, 'Phrase'); + + foreach ($phrases as $phrase => $fields_hash) { + if (array_key_exists($phrase, $already_added)) { + $this->Conn->doUpdate($fields_hash, $temp_table, 'PhraseId = ' . $already_added[$phrase]); + } + else { + $this->Conn->doInsert($fields_hash, $temp_table); + $already_added[$phrase] = $this->Conn->getInsertID(); + } + } + + // in case some phrases were found in this language, but not in primary language -> copy them + if ($language_id != $primary_language_id) { + $sql = 'UPDATE ' . $temp_table . ' + SET l' . $primary_language_id . '_Translation = l' . $language_id . '_Translation + WHERE l' . $primary_language_id . '_Translation IS NULL'; + $this->Conn->Query($sql); + } + } + + $this->Conn->Query('DROP TABLE IF EXISTS ' . TABLE_PREFIX . 'Phrase'); + $this->Conn->Query('RENAME TABLE ' . $temp_table . ' TO ' . TABLE_PREFIX . 'Phrase'); + + $this->_updateCountryStatesTable(); + $this->_replaceConfigurationValueSeparator(); + + // save "config.php" in php format, not ini format as before + $this->_toolkit->SaveConfig(); + } + + if ($mode == 'after') { + $this->_transformEmailRecipients(); + $this->_fixSkinColors(); + } + } + + /** + * Makes sure we rename tables to legacy names before doing other upgrades before 5.2.0-B1 upgrade + * + * @param string $name + * @param Array $arguments + */ + public function __call($name, $arguments) + { + if ( substr($name, 0, 12) == 'Upgrade_5_1_' && $arguments[0] == 'before' ) { + $this->_renameTables('from'); + } + + if ( substr($name, 0, 13) == 'Upgrade_5_2_0' && $arguments[0] == 'before' ) { + $this->_renameTables('to'); + } + } + + /** + * Move country/state translations from Phrase to CountryStates table + * + */ + function _updateCountryStatesTable() + { + // refactor StdDestinations table + $sql = 'RENAME TABLE ' . TABLE_PREFIX . 'StdDestinations TO ' . TABLE_PREFIX . 'CountryStates'; + $this->Conn->Query($sql); + + $sql = 'ALTER TABLE ' . TABLE_PREFIX . 'CountryStates + CHANGE DestId CountryStateId INT(11) NOT NULL AUTO_INCREMENT, + CHANGE DestType Type INT(11) NOT NULL DEFAULT \'1\', + CHANGE DestParentId StateCountryId INT(11) NULL DEFAULT NULL, + CHANGE DestAbbr IsoCode CHAR(3) NOT NULL DEFAULT \'\', + CHANGE DestAbbr2 ShortIsoCode CHAR(2) NULL DEFAULT NULL, + DROP INDEX DestType, + DROP INDEX DestParentId, + ADD INDEX (`Type`), + ADD INDEX (StateCountryId)'; + $this->Conn->Query($sql); + + $ml_helper = $this->Application->recallObject('kMultiLanguageHelper'); + /* @var $ml_helper kMultiLanguageHelper */ + + $ml_helper->createFields('country-state'); + $languages = $ml_helper->getLanguages(); + + foreach ($languages as $language_id) { + $sub_select = ' SELECT l' . $language_id . '_Translation + FROM ' . TABLE_PREFIX . 'Phrase + WHERE Phrase = DestName'; + + $sql = 'UPDATE ' . TABLE_PREFIX . 'CountryStates + SET l' . $language_id . '_Name = (' . $sub_select . ')'; + $this->Conn->Query($sql); + } + + $sql = 'ALTER TABLE ' . TABLE_PREFIX . 'CountryStates + DROP DestName'; + $this->Conn->Query($sql); + + $sql = 'DELETE FROM ' . TABLE_PREFIX . 'Phrase + WHERE Phrase LIKE ' . $this->Conn->qstr('la_country_%') . ' OR Phrase LIKE ' . $this->Conn->qstr('la_state_%'); + $this->Conn->Query($sql); + } + + /** + * Makes configuration values dropdowns use "||" as separator + * + */ + function _replaceConfigurationValueSeparator() + { + $custom_field_helper = $this->Application->recallObject('InpCustomFieldsHelper'); + /* @var $custom_field_helper InpCustomFieldsHelper */ + + $sql = 'SELECT ValueList, VariableName + FROM ' . TABLE_PREFIX . 'ConfigurationAdmin + WHERE ValueList LIKE "%,%"'; + $variables = $this->Conn->GetCol($sql, 'VariableName'); + + foreach ($variables as $variable_name => $value_list) { + $ret = Array (); + $options = $custom_field_helper->GetValuesHash($value_list, ',', false); + + foreach ($options as $option_key => $option_title) { + if (substr($option_key, 0, 3) == 'SQL') { + $ret[] = $option_title; + } + else { + $ret[] = $option_key . '=' . $option_title; + } + } + + $fields_hash = Array ( + 'ValueList' => implode(VALUE_LIST_SEPARATOR, $ret), + ); + + $this->Conn->doUpdate($fields_hash, TABLE_PREFIX . 'ConfigurationAdmin', 'VariableName = ' . $this->Conn->qstr($variable_name)); + } + } + + /** + * Transforms "FromUserId" into Sender* and Recipients columns + * + */ + function _transformEmailRecipients() + { + $sql = 'SELECT FromUserId, Type, EventId + FROM ' . TABLE_PREFIX . 'Events + WHERE FromUserId IS NOT NULL AND (FromUserId <> ' . USER_ROOT . ')'; + $events = $this->Conn->Query($sql, 'EventId'); + + $minput_helper = $this->Application->recallObject('MInputHelper'); + /* @var $minput_helper MInputHelper */ + + foreach ($events as $event_id => $event_data) { + $sql = 'SELECT Login + FROM ' . TABLE_PREFIX . 'PortalUser + WHERE PortalUserId = ' . $event_data['FromUserId']; + $username = $this->Conn->GetOne($sql); + + if (!$username) { + continue; + } + + if ($event_data['Type'] == EmailEvent::EVENT_TYPE_FRONTEND) { + // from user + $fields_hash = Array ( + 'CustomSender' => 1, + 'SenderAddressType' => EmailEvent::ADDRESS_TYPE_USER, + 'SenderAddress' => $username + ); + } + + if ($event_data['Type'] == EmailEvent::EVENT_TYPE_ADMIN) { + // to user + $records = Array ( + Array ( + 'RecipientType' => EmailEvent::RECIPIENT_TYPE_TO, + 'RecipientName' => '', + 'RecipientAddressType' => EmailEvent::ADDRESS_TYPE_USER, + 'RecipientAddress' => $username + ) + ); + + $fields_hash = Array ( + 'CustomRecipient' => 1, + 'Recipients' => $minput_helper->prepareMInputXML($records, array_keys( reset($records) )) + ); + } + + $this->Conn->doUpdate($fields_hash, TABLE_PREFIX . 'Events', 'EventId = ' . $event_id); + } + + $this->Conn->Query('ALTER TABLE ' . TABLE_PREFIX . 'Events DROP FromUserId'); + } + + /** + * Update to 5.1.0; Fixes refferer of form submissions + * + * @param string $mode when called mode {before, after) + */ + function Upgrade_5_1_0($mode) + { + if ( $mode == 'before' ) { + $this->_renameTables('from'); + } + + if ( $mode == 'after' ) { + $base_url = $this->Application->BaseURL(); + + $sql = 'UPDATE ' . TABLE_PREFIX . 'FormSubmissions + SET ReferrerURL = REPLACE(ReferrerURL, ' . $this->Conn->qstr($base_url) . ', "/")'; + $this->Conn->Query($sql); + } + } + + /** + * Update to 5.1.1-B1; Transforms DisplayToPublic logic + * + * @param string $mode when called mode {before, after) + */ + function Upgrade_5_1_1_B1($mode) + { + if ( $mode == 'before' ) { + $this->_renameTables('from'); + } + + if ($mode == 'after') { + $this->processDisplayToPublic(); + } + } + + function processDisplayToPublic() + { + $profile_mapping = Array ( + 'pp_firstname' => 'FirstName', + 'pp_lastname' => 'LastName', + 'pp_dob' => 'dob', + 'pp_email' => 'Email', + 'pp_phone' => 'Phone', + 'pp_street' => 'Street', + 'pp_city' => 'City', + 'pp_state' => 'State', + 'pp_zip' => 'Zip', + 'pp_country' => 'Country', + ); + + $fields = array_keys($profile_mapping); + $fields = $this->Conn->qstrArray($fields); + $where_clause = 'VariableName IN (' . implode(',', $fields) . ')'; + + // 1. get user, that have saved their profile at least once + $sql = 'SELECT DISTINCT PortalUserId + FROM ' . TABLE_PREFIX . 'PersistantSessionData + WHERE ' . $where_clause; + $users = $this->Conn->GetCol($sql); + + foreach ($users as $user_id) { + // 2. convert to new format + $sql = 'SELECT VariableValue, VariableName + FROM ' . TABLE_PREFIX . 'PersistantSessionData + WHERE (PortalUserId = ' . $user_id . ') AND ' . $where_clause; + $user_variables = $this->Conn->GetCol($sql, 'VariableName'); + + // go through mapping to preserve variable order + $value = Array (); + + foreach ($profile_mapping as $from_name => $to_name) { + if (array_key_exists($from_name, $user_variables) && $user_variables[$from_name]) { + $value[] = $to_name; + } + } + + if ($value) { + $fields_hash = Array ( + 'DisplayToPublic' => '|' . implode('|', $value) . '|', + ); + + $this->Conn->doUpdate($fields_hash, TABLE_PREFIX . 'PortalUser', 'PortalUserId = ' . $user_id); + } + + // 3. delete old style variables + $sql = 'DELETE FROM ' . TABLE_PREFIX . 'PersistantSessionData + WHERE (PortalUserId = ' . $user_id . ') AND ' . $where_clause; + $this->Conn->Query($sql); + } + } + + /** + * Update to 5.1.3; Merges column and field phrases + * + * @param string $mode when called mode {before, after) + */ + function Upgrade_5_1_3($mode) + { + if ( $mode == 'before' ) { + $this->_renameTables('from'); + } + + if ( $mode == 'after' ) { + $this->moveTranslation('LA_COL_', 'LA_FLD_', 'ColumnTranslation'); + } + } + + /** + * Makes sure table names match upgrade script + * + * @param string $key + * @return void + * @access private + */ + private function _renameTables($key) + { + foreach ($this->renamedTables as $prefix => $table_info) { + $this->Application->setUnitOption($prefix, 'TableName', TABLE_PREFIX . $table_info[$key]); + } + } + + /** + * Update to 5.2.0-B1; Transform list sortings storage + * + * @param string $mode when called mode {before, after) + */ + public function Upgrade_5_2_0_B1($mode) + { + if ( $mode == 'before' ) { + $this->_renameTables('to'); + } + + if ( $mode == 'after' ) { + $this->transformSortings(); + $this->moveTranslation('LA_COL_', 'LA_FLD_', 'ColumnTranslation'); // because of "la_col_ItemPrefix" phrase + $this->moveTranslation('LA_HINT_', 'LA_FLD_', 'HintTranslation'); + $this->moveTranslation('LA_HINT_', 'LA_CONFIG_', 'HintTranslation'); + $this->moveTranslation('LA_HINT_', 'LA_TITLE_', 'HintTranslation'); + $this->createPageRevisions(); + } + } + + /** + * Transforms a way, how list sortings are stored + * + * @return void + */ + function transformSortings() + { + $sql = 'SELECT VariableName, PortalUserId + FROM ' . TABLE_PREFIX . 'UserPersistentSessionData + WHERE VariableName LIKE "%_Sort1.%"'; + $sortings = $this->Conn->Query($sql); + + foreach ($sortings AS $sorting) { + if ( !preg_match('/^(.*)_Sort1.(.*)$/', $sorting['VariableName'], $regs) ) { + continue; + } + + $user_id = $sorting['PortalUserId']; + $prefix_special = $regs[1] . '_'; + $view_name = '.' . $regs[2]; + + $old_variable_names = Array ( + $prefix_special . 'Sort1' . $view_name, $prefix_special . 'Sort1_Dir' . $view_name, + $prefix_special . 'Sort2' . $view_name, $prefix_special . 'Sort2_Dir' . $view_name, + ); + $old_variable_names = $this->Conn->qstrArray($old_variable_names); + + $sql = 'SELECT VariableValue, VariableName + FROM ' . TABLE_PREFIX . 'UserPersistentSessionData + WHERE PortalUserId = ' . $user_id . ' AND VariableName IN (' . implode(',', $old_variable_names) . ')'; + $sorting_data = $this->Conn->GetCol($sql, 'VariableName'); + + // prepare & save new sortings + $new_sorting = Array ( + 'Sort1' => $sorting_data[$prefix_special . 'Sort1' . $view_name], + 'Sort1_Dir' => $sorting_data[$prefix_special . 'Sort1_Dir' . $view_name], + ); + + if ( isset($sorting_data[$prefix_special . 'Sort2' . $view_name]) ) { + $new_sorting['Sort2'] = $sorting_data[$prefix_special . 'Sort2' . $view_name]; + $new_sorting['Sort2_Dir'] = $sorting_data[$prefix_special . 'Sort2_Dir' . $view_name]; + } + + $fields_hash = Array ( + 'PortalUserId' => $user_id, + 'VariableName' => $prefix_special . 'Sortings' . $view_name, + 'VariableValue' => serialize($new_sorting), + ); + + $this->Conn->doInsert($fields_hash, TABLE_PREFIX . 'UserPersistentSessionData'); + + // delete sortings, that were already processed + $sql = 'DELETE FROM ' . TABLE_PREFIX . 'UserPersistentSessionData + WHERE PortalUserId = ' . $user_id . ' AND VariableName IN (' . implode(',', $old_variable_names) . ')'; + $this->Conn->Query($sql); + } + } + + /** + * Merges several phrases into one (e.g. la_col_ + la_hint_ into designated columns of la_fld_ phrases) + * + * @param string $source_prefix + * @param string $target_prefix + * @param string $db_column + * @return void + * @access protected + */ + public function moveTranslation($source_prefix, $target_prefix, $db_column) + { + $source_phrases = $this->getPhrasesByMask($source_prefix . '%'); + $target_phrases = $this->getPhrasesByMask($target_prefix . '%'); + + $ml_helper = $this->Application->recallObject('kMultiLanguageHelper'); + /* @var $ml_helper kMultiLanguageHelper */ + + $delete_ids = Array (); + $ml_helper->createFields('phrases'); + $languages = $ml_helper->getLanguages(); + $phrase_table = $this->Application->getUnitOption('phrases', 'TableName'); + + foreach ($source_phrases as $phrase_key => $phrase_info) { + $target_phrase_key = $target_prefix . substr($phrase_key, strlen($source_prefix)); + + if ( !isset($target_phrases[$target_phrase_key]) ) { + continue; + } + + $fields_hash = Array (); + + // copy column phrase main translation into field phrase column translation + foreach ($languages as $language_id) { + $fields_hash['l' . $language_id . '_' . $db_column] = $phrase_info['l' . $language_id . '_Translation']; + } + + $delete_ids[] = $phrase_info['PhraseId']; + $this->Conn->doUpdate($fields_hash, $phrase_table, 'PhraseId = ' . $target_phrases[$target_phrase_key]['PhraseId']); + } + + // delete all column phrases, that were absorbed by field phrases + if ( $delete_ids ) { + $sql = 'DELETE FROM ' . $phrase_table . ' + WHERE PhraseId IN (' . implode(',', $delete_ids) . ')'; + $this->Conn->Query($sql); + + $sql = 'DELETE FROM ' . TABLE_PREFIX . 'PhraseCache'; + $this->Conn->Query($sql); + } + } + + /** + * Returns phrases by mask + * + * @param string $mask + * @return Array + * @access protected + */ + protected function getPhrasesByMask($mask) + { + $sql = 'SELECT * + FROM ' . $this->Application->getUnitOption('phrases', 'TableName') . ' + WHERE PhraseKey LIKE ' . $this->Conn->qstr($mask); + + return $this->Conn->Query($sql, 'PhraseKey'); + } + + protected function createPageRevisions() + { + $sql = 'SELECT DISTINCT PageId + FROM ' . TABLE_PREFIX . 'PageContent'; + $page_ids = $this->Conn->GetCol($sql); + + foreach ($page_ids as $page_id) { + $fields_hash = Array ( + 'PageId' => $page_id, + 'RevisionNumber' => 1, + 'IsDraft' => 0, + 'FromRevisionId' => 0, + 'CreatedById' => USER_ROOT, + 'CreatedOn' => adodb_mktime(), + 'Status' => STATUS_ACTIVE, + ); + + $this->Conn->doInsert($fields_hash, TABLE_PREFIX . 'PageRevisions'); + + $fields_hash = Array ( + 'RevisionId' => $this->Conn->getInsertID(), + ); + + $this->Conn->doUpdate($fields_hash, TABLE_PREFIX . 'PageContent', 'PageId = ' . $page_id); + } + } + + /** + * Update to 5.2.0-B3; Introduces separate field for plain-text e-mail event translations + * + * @param string $mode when called mode {before, after) + */ + public function Upgrade_5_2_0_B3($mode) + { + if ( $mode == 'before' ) { + $this->_renameTables('to'); + } + + if ( $mode == 'after' ) { + $this->_splitEmailBody(); + $this->_migrateCommonFooter(); + } + } + + /** + * Splits e-mail body into HTML and Text fields + * + * @return void + * @access private + */ + private function _splitEmailBody() + { + $id_field = $this->Application->getUnitOption('emailevents', 'IDField'); + $table_name = $this->Application->getUnitOption('emailevents', 'TableName'); + $fields = $this->Conn->Query('DESCRIBE ' . $table_name, 'Field'); + + if ( !isset($fields['l1_Body']) ) { + // column dropped - nothing to convert anymore + return; + } + + $ml_helper = $this->Application->recallObject('kMultiLanguageHelper'); + /* @var $ml_helper kMultiLanguageHelper */ + + $languages = $ml_helper->getLanguages(); + $ml_helper->createFields('emailevents'); + + $sql = 'SELECT * + FROM ' . $table_name; + $email_events = $this->Conn->Query($sql); + + // 1. move data to new columns + foreach ($email_events as $email_event) { + $fields_hash = Array (); + $translation_field = $email_event['MessageType'] == 'html' ? 'HtmlBody' : 'PlainTextBody'; + + foreach ($languages as $language_id) { + $fields_hash['l' . $language_id . '_' . $translation_field] = $email_event['l' . $language_id . '_Body']; + } + + if ( $fields_hash ) { + $this->Conn->doUpdate($fields_hash, $table_name, $id_field . ' = ' . $email_event[$id_field]); + } + } + + // 2. drop old columns + $drops = Array ('DROP COLUMN MessageType'); + + foreach ($languages as $language_id) { + $lang_field = 'l' . $language_id . '_Body'; + + if ( isset($fields[$lang_field]) ) { + $drops[] = 'DROP COLUMN ' . $lang_field; + } + } + + $this->Conn->Query('ALTER TABLE ' . $table_name . ' ' . implode(', ', $drops)); + } + + /** + * Transforms COMMON.FOOTER e-mail event into new field in Languages table + */ + private function _migrateCommonFooter() + { + $ml_helper = $this->Application->recallObject('kMultiLanguageHelper'); + /* @var $ml_helper kMultiLanguageHelper */ + + $languages = $ml_helper->getLanguages(); + + $event_table = $this->Application->getUnitOption('emailevents', 'TableName'); + + $sql = 'SELECT * + FROM ' . $event_table . ' + WHERE Event = "COMMON.FOOTER"'; + $footer_data = $this->Conn->GetRow($sql); + + if ( !$footer_data ) { + return; + } + + $primary_language_id = $this->Application->GetDefaultLanguageId(); + $table_name = $this->Application->getUnitOption('lang', 'TableName'); + + foreach ($languages as $language_id) { + $is_primary = $language_id == $primary_language_id; + + $fields_hash = Array ( + 'HtmlEmailTemplate' => $this->_appendEmailDesignBody($footer_data['l' . $language_id . '_HtmlBody'], $is_primary), + 'TextEmailTemplate' => $this->_appendEmailDesignBody($footer_data['l' . $language_id . '_PlainTextBody'], $is_primary), + ); + + $this->Conn->doUpdate($fields_hash, $table_name, 'LanguageId = ' . $language_id); + } + + $sql = 'DELETE FROM ' . $event_table . ' + WHERE EventId = ' . $footer_data['EventId']; + $this->Conn->Query($sql); + } + + /** + * Adds "$body" to given string + * + * @param string $string + * @param bool $is_primary for primary language + * @return string + * @access private + */ + private function _appendEmailDesignBody($string, $is_primary) + { + if ( !$string ) { + return $is_primary ? '$body' : $string; + } + + return '$body' . "\n" . str_replace(Array ("\r\n", "\r"), "\n", $string); + } + } \ No newline at end of file Index: releases/5.2.0-B3/COPYRIGHT =================================================================== diff -u -N --- releases/5.2.0-B3/COPYRIGHT (revision 0) +++ releases/5.2.0-B3/COPYRIGHT (revision 15451) @@ -0,0 +1,21 @@ +In-Portal is Open Source object-oriented framework that is developed +in PHP and provides quick and easy way to build websites and web applications. + +Copyright (C) 1997 - 2009 Intechnic. All rights reserved. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +A full text version of the GNU GPL version 2 can be found +in the LICENSE file. Please see the CREDITS for a list of contributors. +A full text version of the other licenses that In-Portal includes +can be found in LICENSES file. + +Any questions can be emailed to license@in-portal.com \ No newline at end of file Index: releases/5.2.0-B3/LICENSES =================================================================== diff -u -N --- releases/5.2.0-B3/LICENSES (revision 0) +++ releases/5.2.0-B3/LICENSES (revision 15451) @@ -0,0 +1,526 @@ +In-Portal includes or is derivative of works distributed under the licenses listed below. + +This file includes the full text of the following licenses: +------------------------------------------------------------------ + + * GNU Lesser General Public License (GNU LGPL) version 2.1 + * PHP License version 3.0 + + +GNU LGPL: +--------------------- +GNU LESSER GENERAL PUBLIC LICENSE +Version 2.1, February 1999 + +Copyright (C) 1991, 1999 Free Software Foundation, Inc. +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +Everyone is permitted to copy and distribute verbatim copies +of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts +as the successor of the GNU Library Public License, version 2, hence +the version number 2.1.] + +Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + +GNU LESSER GENERAL PUBLIC LICENSE +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. +------------------------------------------------------------------ + + +PHP License: +--------------------- +The PHP License, version 3.0 +Copyright (c) 1999 - 2006 The PHP Group. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, is permitted provided that the following conditions +are met: + + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + 3. The name "PHP" must not be used to endorse or promote products + derived from this software without prior written permission. For + written permission, please contact group@php.net. + + 4. Products derived from this software may not be called "PHP", nor + may "PHP" appear in their name, without prior written permission + from group@php.net. You may indicate that your software works in + conjunction with PHP by saying "Foo for PHP" instead of calling + it "PHP Foo" or "phpfoo" + + 5. The PHP Group may publish revised and/or new versions of the + license from time to time. Each version will be given a + distinguishing version number. + Once covered code has been published under a particular version + of the license, you may always continue to use it under the terms + of that version. You may also choose to use such covered code + under the terms of any subsequent version of the license + published by the PHP Group. No one other than the PHP Group has + the right to modify the terms applicable to covered code created + under this License. + + 6. Redistributions of any form whatsoever must retain the following + acknowledgment: + "This product includes PHP, freely available from + ". + +THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND +ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE PHP +DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, +INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED +OF THE POSSIBILITY OF SUCH DAMAGE. +------------------------------------------------------------------ \ No newline at end of file Index: releases/5.2.0-B3/CREDITS =================================================================== diff -u -N --- releases/5.2.0-B3/CREDITS (revision 0) +++ releases/5.2.0-B3/CREDITS (revision 15451) @@ -0,0 +1,66 @@ +IN-PORTAL CREDITS +================= + +Project Contributors: +--------------------- +* Alexander Obuhovich +* Dmitry Andrejev +* Andrew Kucheriavy +* Phil Banks +* Konstantin Tjuterev +* Sergey Grib +* Gleb Kozlov +* Stas Filipov +* Nikita Filatov +* Erik Snarski +* Ilya Bernshteyn +* Valentin Poddubnyak +* Vjacheslav Vishnjakov +* Pavel Kharitonov +* Gene Averbuch +* David Chen +* Stoyan Vlaikov +* Chis Walker +* Maris Kocins +* John Aba +* Paul Korenevesky +* Anya Nikogosian +* Katia Seidametova +* Peter Droppa +* Eugene Hohlov +* Sergey Mesropyan +* Franck Nussbaumer aka side +* Aleksey Mlokits +* Andrey Isaev +* Anton Zotov +* Arnis Pridans +* Arvids Godjuks +* Denis Badulin +* Dmitrijs Trofimosvs +* Eldar Sharafudinov +* Elena Panova +* Erik Harcev +* Grigorij Pilipenko +* Igor Savinov +* Ivan Vasiljev +* Konstantin Kotchetkov +* Max Voronin +* Maxim Sakuta +* Nikita Dukhovny +* Pavel Veretennikov +* Vadim Upesleja +* Valentin Garkavy +* Victor Grjaznov +* Vladimit Pashedko +* Yaroslav Goncharuck + + + +In-Portal is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +A full text version of the GNU GPL version 2 can be found +in the LICENSE file. A full text version of the other licenses +that In-Portal includes can be found in LICENSES file. \ No newline at end of file Index: releases/5.2.0-B3/INSTALL =================================================================== diff -u -N --- releases/5.2.0-B3/INSTALL (revision 0) +++ releases/5.2.0-B3/INSTALL (revision 15451) @@ -0,0 +1,276 @@ +IN-PORTAL INSTALLATION +---------------------- + +First you should start with the base setup of your server environment. +In-Portal can be effectively run on any UNIX/Linux or Windows platforms. + +If you don't have a hosting account (virtual/shared or dedicated) yet +you should setup one. + +If you are looking to setup the environment your own, below is the list of resources: + +HOWTO setup LAMP (Apache/PHP/MySQL on Linux) -> http://en.wikipedia.org/wiki/LAMP_(software_bundle) + +* Apache -> http://www.apache.org +* MySQL -> http://www.mysql.com +* PHP -> http://www.php.net + +* WAMP Server (for Windows) -> http://www.wampserver.com + +Additional Resources/tools: + +* eAccelerator (optional) -> http://www.eaccelerator.net +* Zend Optimizer (optional) -> http://www.zend.com/en/products/guard/downloads +* phpMyAdmin (optional) -> http://www.phpmyadmin.net + + + +MINIMUM SERVER REQUIREMENTS +--------------------------- + +* PHP 4.3.9 and higher with memory_limit = 24M +* Apache 1.3.X and higher or Microsoft IIS 5.0 and higher +* MySQL 4.1.11 and higher + +You MUST ensure that PHP has been compiled with support for +MySQL in order to run In-Portal. + +While In-Portal works on IIS server we recommend Apache +for running In-Portal on Windows. + + +RECOMMENDED SERVER REQUIREMENTS +------------------------------- + +* PHP 4.3.9 and higher. It is recommended to use the latest stable release of PHP. + The following PHP extensions are recommended: + * GD – image handling library; (or ImageMagic) + * FreeType – required for CAPTCHA; + * Regular Expressions support; + * Zlib compression – required to decrease the amount of transferred data; + * Memcache - interface to highly effective caching daemon. + +* PHP enabled web server: + Apache (recommended) 1.3.X and higher. The system also runs successfully on Apache 2.X; + MS IIS 5.0 or 6.0. PHP should be installed as ISAPI. + +* MySQL version 4.1.11 and higher is recommended. To work with MySQL properly, +the system requires the MySQL support for PHP to be installed; + +* eAccelerator or Zend Optimizer 3.0 (or higher) is recommended for high traffic websites. + +* Memory limit: + memory_limit = 24M - minimum amount of PHP memory required by the system core. + memory_limit = 32M - recommended amount of PHP memory. + +This parameter can be changed: + 1. by editing the file php.ini directly; + 2. from within a script by calling ini_set("memory_limit", "32M"); + 3. in the file .htaccess using the directive: php_value memory_limit 32M. + + + +MOD-REWRITE +------------------- + +If you want support for Search Engine Friendly URLs, you'll need +mod_rewrite Apache module to be installed and the ability to use local .htaccess file. + + + +INSTALLATION +------------ + +1. DOWNLOAD In-Portal + + a. You can obtain the latest In-Portal release and modules from + + http://www.in-portal.com + + b. Copy the tar.gz (or zip) file(s) into a working directory e.g. + + $ cp in-portal_X_X_X.tar.gz to /tmp/in-portal/ + + If you want to install additional modules like In-Link, In-Bulletin or In-News + you can do so by downloading and copying them following the same rules. + + Note that these modules are optional and will provide additional + functionality to your website. + + For example: + + $ cp in-link_X_X_X.tar.gz to /tmp + $ cp in-newz_X_X_X.tar.gz to /tmp + $ cp in-bulletin_X_X_X.tar.gz to /tmp + + + c. Change to the working directory e.g. + + $ cd /tmp + + d. Extract the files e.g. + + $ tar -zxvf in-portal_X_X_X.tar.gz + + Optional module(s): + + $ tar -zxvf in-link_X_X_X.tar.gz + $ tar -zxvf in-bulletin_X_X_X.tar.gz + $ tar -zxvf in-newz_X_X_X.tar.gz + + This will automatically create /tmp/in-portal folder and extract all + In-Portal (and modules) files and directories inside. + As a result inside /tmp/in-portal you should have: + + - admin/ + - core/ + - system/ + - themes/ + - tools/ + - index.php + - other LICENSE and README files + + You should see modules specific folders (ie. in-link, in-news, in-bulletin) + in case if they were downloaded and extracted. + + + e. Move the contents of that directory into a directory within + your web server's document root or your public HTML directory e.g. + + $ mv /tmp/in-portal/* /var/www/html + + + ALTERNATIVELY if you downloaded the file(s) to your computer and unpacked + it locally use a FTP program to upload all files to your server. + Make sure all PHP, HTML, CSS, XML and JS files are sent in ASCII mode and + image files (GIF, JPG, PNG) in BINARY mode. + + You can use FileZilla if you don't have any FTP program + + http://www.filezilla-project.org + + +2. CREATE THE In-Portal DATABASE + +In-Portal will currently only work with MySQL. In the following examples, +"db_user" is an example MySQL user which has the CREATE and GRANT +privileges. You will need to use the appropriate user name for your +system. + +NOTE that you can skip to the next step if you already have both +a database and user setup. + +There are two ways doing it: + +1. Use your WEB CONTROL PANEL such as Plesk or cPanel (or other) +or phpMyAdmin to create a database for In-Portal + + a. Create a new database for your In-Portal site. Let's call it + inportal + + b. Create a new database user for newly added 'inportal' database + for your In-Portal site e.g. + + +2. Do it by hand which requires a bit more work: + + a. Create a new database for your In-Portal site e.g. + + $ mysqladmin -u db_user -p create inportal + + MySQL will prompt for the 'db_user' database password and then create + the database. + + b. Next you must login and set the access database rights e.g. + + $ mysql -u db_user -p + + Again, you will be asked for the 'db_user' database password. + + c. Grant permissions + + At the MySQL prompt, enter following command: + + GRANT ALL PRIVILEGES ON inportal.* + TO yourdbuser@localhost IDENTIFIED BY 'password'; + + where: + + 'inportal' is the name of your database + 'yourdbuser@localhost' is the userid of your webserver MySQL account + 'password' is the password required to log in as the MySQL user + + If successful, MySQL will reply with + + Query OK, 0 rows affected + + d. Activate new permissions by entering the command + + flush privileges; + + e. Exit MySQL prompt by typing + + quit; + + +3. WEB INSTALLATION + +Now you ready to proceed with web installation of In-Portal. +In your browser open + + http://www.my-inpotal.com/core/install.php + +will guide you through the rest of the installation. + +Once installation completed you should have /system/config.php file +created in the root folder of your In-Portal installation. + +In some rare cases servers might be configured the way when +WEB INSTALLATION fails to create /system/config.php. In this case +and you'll have to manually + + a. copy /tools/config.php-dist file into the /system subfolder + of your In-Portal installation. + + b. rename it from config.php-dist to config.php. Make sure you + do NOT have config.php already and if you do rename original one + to something like config.bak.php. Later you can delete old one once + installation completed successfully. + + c. change permission on config.php to 777 permission. This is + necessary for the time of installation. + + d. open config.php, carefully put in your database information + and save it. + + e. now you proceed to installation again. + + http://www.my-inpotal.com/core/install.php + + +4. CONFIGURE In-Portal + +You can now launch your browser and point it to your In-Portal site e.g. + + Front -> http://www.my-inportal.com + Admin -> http://www.my-inportal.com/admin + +You can log into Admin using the username 'root' along with the +password that you chose during the web based installation process. + + +ADMINISTRATION +-------------- + +Upon a new installation, your In-Portal website defaults to a very basic +configuration. + +Use Admin->Configuration section to configure your website and much more. + +Feel free to ask questions on Community forums available via http://www.in-portal.com + + +Thank you for installing In-Portal and Welcome on board! + + +In-Portal Community \ No newline at end of file Index: releases/5.2.0-B3/index.php =================================================================== diff -u -N --- releases/5.2.0-B3/index.php (revision 0) +++ releases/5.2.0-B3/index.php (revision 15451) @@ -0,0 +1,25 @@ +Init(); +$application->Run(); +$application->Done(); + +$end = microtime(true); \ No newline at end of file Index: releases/5.2.0-B3/.htaccess =================================================================== diff -u -N --- releases/5.2.0-B3/.htaccess (revision 0) +++ releases/5.2.0-B3/.htaccess (revision 15451) @@ -0,0 +1,66 @@ +### File security +# Exclude direct access to tpl, tpl.xml, inc.php, sql extensions +# + + order allow,deny + deny from all + satisfy all + + + + ExpiresActive on + ExpiresByType text/css "access plus 1 month" + ExpiresByType application/x-javascript "access plus 1 month" + ExpiresByType application/javascript "access plus 1 month" + ExpiresByType image/gif "access plus 1 month" + ExpiresByType image/jpeg "access plus 1 month" + ExpiresByType image/png "access plus 1 month" + ExpiresByType image/x-icon "access plus 1 month" + ExpiresByType image/icon "access plus 1 month" + + +## Enable mod-rewrite +RewriteEngine On + +###### Rewrite rule to force 'www.' prefix. Use only if needed +# If your site can be accessed both with and without the 'www.' prefix, +# use the following setting to redirect all users to access the site with the 'www.' +# when they access without 'www.'. Uncomment and MAKE sure to adapt for your domain name +# +# RewriteCond %{HTTP_HOST} ^example\.com$ [NC] +# RewriteRule ^(.*)$ http://www.example.com/$1 [L,R=301] + +###### Rewrite rules to block common hacks +## If you experience problems comment out the operations listed below +## Block out any script trying to base64_encode crap to send via URL +RewriteCond %{QUERY_STRING} base64_encode.*\(.*\) [OR] +## Block out any script that includes a