Index: branches/5.3.x/admin/system_presets/simple/email_templates_email-template.php =================================================================== --- branches/5.3.x/admin/system_presets/simple/email_templates_email-template.php (revision 16322) +++ branches/5.3.x/admin/system_presets/simple/email_templates_email-template.php (revision 16323) @@ -1,64 +1,68 @@ Array (/*'new_item', 'edit', 'delete', 'approve', 'decline', 'frontend_mail', 'view',*/ 'export', /*'dbl-click'*/), // edit email template - general tab -// 'email_template_edit' => Array ('select', 'cancel', 'reset_edit', 'prev', 'next'), + 'email_template_edit' => Array (/*'select',*/ 'setprimary', /*'cancel', 'reset_edit', 'prev', 'next'*/), // edit email template - settings tab // 'email_template_edit_settings' => Array ('select', 'cancel', 'reset_edit', 'prev', 'next'), ); // fields to hide $hidden_fields = Array ( /*'TemplateId', 'TemplateName', 'ReplacementTags', 'AllowChangingSender', 'CustomSender', 'SenderName', 'SenderAddressType', 'SenderAddress', 'AllowChangingRecipient', 'CustomRecipient', 'Recipients', 'Subject', 'HtmlBody', 'PlainTextBody', 'Headers', 'Enabled', 'FrontEndOnly', 'Module', 'BindToSystemEvent', 'Description', 'Type'*/ ); // virtual fields to hide $virtual_hidden_fields = Array ( /*'RecipientType', 'RecipientName', 'RecipientAddressType', - 'RecipientAddress', 'Tag', 'Replacement', 'ReplacementTagsXML',*/ + 'RecipientAddress', 'Tag', 'Replacement', 'ReplacementTagsXML',*/ 'TranslationInSync', 'TranslateFromLanguage' ); // fields to make required $required_fields = Array ( /*'TemplateId',*/ 'TemplateName', /*'ReplacementTags', 'AllowChangingSender', 'CustomSender', 'SenderName', 'SenderAddressType', 'SenderAddress', 'AllowChangingRecipient', 'CustomRecipient', 'Recipients',*/ 'Subject', /*'HtmlBody', 'PlainTextBody', 'Headers',*/ /*'Enabled', 'FrontEndOnly',*/ 'Module', /*'BindToSystemEvent', 'Description',*/ 'Type' ); // virtual fields to make required $virtual_required_fields = Array ( /*'RecipientType', 'RecipientName', 'RecipientAddressType', 'RecipientAddress', 'Tag', 'Replacement', 'ReplacementTagsXML',*/ ); + $debug_only_virtual_fields = Array ( + 'SourceSubject', 'SourceHtmlBody', 'SourcePlainTextBody', + ); + // tabs during editing $hide_edit_tabs = Array ( 'Default' => Array (/*'general',*/ 'settings'), ); // hide columns in grids $hide_columns = Array ( // 'Default' => Array ('TemplateId', 'Description', 'TemplateName', 'Module', 'Type', 'Enabled', 'LastChanged'), -// 'Emails' => Array ('TemplateId', 'TemplateName', 'Subject', 'Description', 'Type', 'Enabled', 'Module', 'FrontEndOnly', 'LastChanged'), - ); \ No newline at end of file + 'Emails' => Array (/*'EventId', 'Event', 'Subject', 'Description', 'Type', 'Enabled', 'Module', 'FrontEndOnly', 'LastChanged',*/ 'TranslationInSync', 'TranslateFromLanguage'), + ); Index: branches/5.3.x/core/units/email_templates/email_templates_config.php =================================================================== --- branches/5.3.x/core/units/email_templates/email_templates_config.php (revision 16322) +++ branches/5.3.x/core/units/email_templates/email_templates_config.php (revision 16323) @@ -1,264 +1,309 @@ 'email-template', 'ItemClass' => Array ('class' => 'kDBItem', 'file' => '', 'build_event' => 'OnItemBuild'), 'ListClass' => Array ('class' => 'kDBList', 'file' => '', 'build_event' => 'OnListBuild'), 'EventHandlerClass' => Array ('class' => 'EmailTemplateEventHandler', 'file' => 'email_template_eh.php', 'build_event' => 'OnBuild'), 'TagProcessorClass' => Array ('class' => 'EmailTemplateTagProcessor', 'file' => 'email_template_tp.php', 'build_event' => 'OnBuild'), 'AutoLoad' => true, 'QueryString' => Array ( 1 => 'id', 2 => 'Page', 3 => 'PerPage', 4 => 'event', 5 => 'mode', ), 'IDField' => 'TemplateId', 'StatusField' => Array ('Enabled'), 'TitleField' => 'TemplateName', 'TitlePresets' => Array ( 'default' => Array ( 'new_status_labels' => Array ('email-template' => '!la_title_AddingEmailTemplate!'), 'edit_status_labels' => Array ('email-template' => '!la_title_EditingEmailTemplate!'), 'new_titlefield' => Array ('email-template' => '!la_title_NewEmailTemplate!'), ), // for separate grid with email editing 'email_template_list' => Array ( 'prefixes' => Array ('email-template_List'), 'format' => "!la_title_EmailTemplates!", 'toolbar_buttons' => Array ('new_item', 'edit', 'delete', 'approve', 'decline', 'frontend_mail', 'export', 'process', 'view', 'dbl-click'), ), 'email_template_edit' => Array ( 'prefixes' => Array ('email-template'), 'format' => '#email-template_status# - #email-template_titlefield# - !la_section_General!', - 'toolbar_buttons' => Array ('select', 'cancel', 'reset_edit', 'prev', 'next'), + 'toolbar_buttons' => Array ('select', 'setprimary', 'cancel', 'reset_edit', 'prev', 'next'), ), 'email_template_edit_settings' => Array ( 'prefixes' => Array ('email-template'), 'format' => '#email-template_status# - #email-template_titlefield# - !la_section_Settings!', 'toolbar_buttons' => Array ('select', 'cancel', 'reset_edit', 'prev', 'next'), ), // for mass mailing 'email_send_form' => Array ('prefixes' => Array (), 'format' => '!la_title_SendEmail!'), ), 'EditTabPresets' => Array ( 'Default' => Array ( 'general' => Array ('title' => 'la_tab_General', 't' => 'languages/email_template_edit', 'priority' => 1), 'settings' => Array ('title' => 'la_tab_Settings', 't' => 'languages/email_template_settings', 'priority' => 2), ), ), + 'CheckSimulatniousEdit' => true, + 'PermSection' => Array ('main' => 'in-portal:configemail'), 'Sections' => Array ( 'in-portal:configemail' => Array ( 'parent' => 'in-portal:site', 'icon' => 'email_templates', 'label' => 'la_title_EmailTemplates', 'url' => Array ('t' => 'languages/email_template_list', 'pass' => 'm'), 'permissions' => Array ('view', 'add', 'edit', 'delete'), 'priority' => 5, 'type' => stTREE, ), ), 'TableName' => TABLE_PREFIX . 'EmailTemplates', + 'CalculatedFields' => Array ( + '' => Array ( + 'SourceSubject' => 'l%4$s_Subject', + 'SourceHtmlBody' => 'l%4$s_HtmlBody', + 'SourcePlainTextBody' => 'l%4$s_PlainTextBody', + + 'CurrentSubject' => 'l%5$s_Subject', + 'CurrentHtmlBody' => 'l%5$s_HtmlBody', + 'CurrentPlainTextBody' => 'l%5$s_PlainTextBody', + + 'TranslationInSync' => 'IF(l%5$s_TranslateFrom = 0, 1, 0)', + 'TranslateFromLanguage' => 'l%5$s_TranslateFrom', + ), + ), + 'ListSQLs' => Array ( - '' => ' SELECT %1$s.* %2$s FROM %1$s', + '' => ' SELECT %1$s.* %2$s + FROM %1$s', ), 'ListSortings' => Array ( '' => Array ( 'ForcedSorting' => Array ('Enabled' => 'desc'), 'Sorting' => Array ('TemplateName' => 'asc'), ), 'module' => Array ( 'ForcedSorting' => Array ('Enabled' => 'desc'), 'Sorting' => Array ('Description' => 'asc') ), ), 'Fields' => Array ( 'TemplateId' => Array ('type' => 'int', 'not_null' => 1, 'default' => 0), 'TemplateName' => Array ('type' => 'string', 'not_null' => 1, 'unique' => Array ('Type'), 'required' => 1, 'default' => ''), 'Headers' => Array ('type' => 'string', 'default' => NULL), 'ReplacementTags' => Array ('type' => 'string', 'default' => NULL), 'AllowChangingSender' => Array ( 'type' => 'int', 'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'la_Yes', 0 => 'la_No'), 'use_phrases' => 1, 'not_null' => 1, 'default' => 0 ), 'CustomSender' => Array ( 'type' => 'int', 'formatter' => 'kOptionsFormatter', 'options' => Array (0 => 'la_opt_DefaultAddress', 1 => 'la_opt_CustomSender'), 'use_phrases' => 1, 'not_null' => 1, 'default' => 0 ), 'SenderName' => Array ('type' => 'string', 'max_len' => 255, 'not_null' => 1, 'default' => ''), 'SenderAddressType' => Array ( 'type' => 'int', 'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'la_opt_Email', 2 => 'la_opt_User'), 'use_phrases' => 1, 'not_null' => 1, 'error_field' => 'SenderAddress', 'default' => 0 ), 'SenderAddress' => Array ( 'type' => 'string', 'max_len' => 255, 'error_msgs' => Array ( 'invalid_email' => '!la_err_invalid_format!', 'invalid_user' => '!la_error_UserNotFound!', ), 'not_null' => 1, 'default' => '' ), 'AllowChangingRecipient' => Array ( 'type' => 'int', 'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'la_Yes', 0 => 'la_No'), 'use_phrases' => 1, 'not_null' => 1, 'default' => 0 ), 'CustomRecipient' => Array ( 'type' => 'int', 'formatter' => 'kOptionsFormatter', 'options' => Array (0 => 'la_opt_DefaultAddress', 1 => 'la_opt_CustomRecipients'), 'use_phrases' => 1, 'not_null' => 1, 'default' => 0 ), 'Recipients' => Array ('type' => 'string', 'default' => NULL), 'Subject' => Array ( 'type' => 'string', 'formatter' => 'kMultiLanguage', 'db_type' => 'text', 'error_msgs' => Array ('parsing_error' => '!la_error_ParsingError!'), 'required' => 1, 'default' => null ), 'HtmlBody' => Array ( 'type' => 'string', 'formatter' => 'kMultiLanguage', 'db_type' => 'longtext', 'error_msgs' => Array ('parsing_error' => '!la_error_ParsingError!'), 'default' => null ), 'PlainTextBody' => Array ( 'type' => 'string', 'formatter' => 'kMultiLanguage', 'db_type' => 'longtext', 'error_msgs' => Array ('parsing_error' => '!la_error_ParsingError!'), 'default' => null ), + 'TranslateFrom' => Array ( + 'type' => 'int', + 'formatter' => 'kMultiLanguage', 'db_type' => 'int', 'index_type' => 'int', + 'not_null' => 1, 'default' => 0 + ), + 'Enabled' => Array ( 'type' => 'int', 'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'la_Yes', 0 => 'la_No'), 'use_phrases' => 1, 'not_null' => 1, 'default' => 1 ), 'FrontEndOnly' => Array ( 'type' => 'int', 'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'la_Yes', 0 => 'la_No'), 'use_phrases' => 1, 'not_null' => 1, 'default' => 0 ), 'Module' => Array ( 'type' => 'string', 'formatter' => 'kOptionsFormatter', 'options' => Array (), 'not_null' => 1, 'required' => 1, 'default' => 'Core' ), 'Description' => Array ('type' => 'string', 'default' => NULL), 'Type' => Array ( 'type' => 'int', 'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'la_Text_Admin', 0 => 'la_Text_User'), 'use_phrases' => 1, 'not_null' => 1, 'unique' => Array ('TemplateName'), 'required' => 1, 'default' => 0 ), 'LastChanged' => Array ('type' => 'int', 'formatter' => 'kDateFormatter', 'default' => NULL), 'BindToSystemEvent' => Array ('type' => 'string', 'max_len' => 255, 'not_null' => 1, 'default' => ''), ), 'VirtualFields' => Array ( 'RecipientType' => Array ( 'type' => 'int', 'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'To', 2 => 'Cc', 3 => 'Bcc'), 'default' => 1 ), 'RecipientName' => Array ('type' => 'string', 'max_len' => 255, 'default' => ''), 'RecipientAddressType' => Array ( 'type' => 'int', 'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'la_opt_Email', 2 => 'la_opt_User', 3 => 'la_opt_Group'), 'use_phrases' => 1, 'error_field' => 'RecipientAddress', 'default' => 0 ), 'RecipientAddress' => Array ( 'type' => 'string', 'max_len' => 255, 'error_msgs' => Array ( 'invalid_email' => '!la_err_invalid_format!', 'invalid_user' => '!la_error_UserNotFound!', 'invalid_group' => '!la_error_GroupNotFound!', ), 'default' => '' ), 'Tag' => Array ('type' => 'string', 'default' => ''), 'Replacement' => Array ('type' => 'string', 'default' => ''), 'ReplacementTagsXML' => Array ('type' => 'string', 'default' => ''), + + 'SourceSubject' => Array ('type' => 'string', 'default' => ''), + 'SourceHtmlBody' => Array ('type' => 'string', 'default' => ''), + 'SourcePlainTextBody' => Array ('type' => 'string', 'default' => ''), + + 'CurrentSubject' => Array ('type' => 'string', 'default' => ''), + 'CurrentHtmlBody' => Array ('type' => 'string', 'default' => ''), + 'CurrentPlainTextBody' => Array ('type' => 'string', 'default' => ''), + + 'TranslationInSync' => Array ( + 'type' => 'int', + 'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'la_Yes', 0 => 'la_No'), 'use_phrases' => 1, + 'default' => 0, + ), + 'TranslateFromLanguage' => Array ( + 'type' => 'int', + 'formatter' => 'kOptionsFormatter', 'options_sql' => 'SELECT %s FROM ' . TABLE_PREFIX . 'Languages ORDER BY PackName', 'option_title_field' => 'PackName', 'option_key_field' => 'LanguageId', + 'default' => 0, + ), ), 'Grids' => Array ( // used on "Email Events" tab in language editing in "Regional" section 'Default' => Array ( 'Icons' => Array ( 'default' => 'icon16_item.png', 0 => 'icon16_disabled.png', 1 => 'icon16_item.png', ), 'Fields' => Array ( 'TemplateId' => Array ('title' => 'column:la_fld_Id', 'filter_block' => 'grid_range_filter', 'width' => 70, ), 'Description' => Array ('filter_block' => 'grid_like_filter', 'width' => 250, ), 'TemplateName' => Array ('filter_block' => 'grid_like_filter', 'width' => 250, ), 'Module' => Array ('filter_block' => 'grid_multioptions_filter', 'width' => 100, ), 'Type' => Array ('filter_block' => 'grid_options_filter', 'width' => 120, ), 'Enabled' => Array ('title' => 'column:la_fld_Status', 'filter_block' => 'grid_options_filter', 'width' => 80, ), 'LastChanged' => Array ('title' => 'column:la_fld_Modified', 'filter_block' => 'grid_date_range_filter', 'width' => 150), ), ), // used on "Email Templates" section 'Emails' => Array ( 'Icons' => Array ( 'default' => 'icon16_item.png', 0 => 'icon16_disabled.png', 1 => 'icon16_item.png', ), 'Fields' => Array ( 'TemplateId' => Array ('title' => 'column:la_fld_Id', 'filter_block' => 'grid_range_filter', 'width' => 60, ), 'TemplateName' => Array ('filter_block' => 'grid_like_combo_filter', 'width' => 250, ), - 'Subject' => Array ('filter_block' => 'grid_like_filter', 'no_special' => 0, 'width' => 300, ), + 'CurrentSubject' => Array ('title' => 'column:la_fld_Subject', 'filter_block' => 'grid_like_filter', 'no_special' => 0, 'width' => 300, ), 'Description' => Array ('filter_block' => 'grid_like_filter', 'width' => 250, ), 'Type' => Array ('filter_block' => 'grid_options_filter', 'width' => 60, ), 'Enabled' => Array ('filter_block' => 'grid_options_filter', 'width' => 70, ), 'Module' => Array ('filter_block' => 'grid_multioptions_filter', 'width' => 100, ), 'FrontEndOnly' => Array ('filter_block' => 'grid_options_filter', 'width' => 120, 'hidden' => 1), 'LastChanged' => Array ('title' => 'column:la_fld_Modified', 'filter_block' => 'grid_date_range_filter', 'width' => 150), + 'TranslationInSync' => Array ('filter_block' => 'grid_options_filter', 'width' => 100, 'hidden' => 1), + 'TranslateFromLanguage' => Array ('filter_block' => 'grid_multioptions_filter', 'width' => 100, 'hidden' => 1), ), ), ), - ); \ No newline at end of file + ); Index: branches/5.3.x/core/units/email_templates/email_template_eh.php =================================================================== --- branches/5.3.x/core/units/email_templates/email_template_eh.php (revision 16322) +++ branches/5.3.x/core/units/email_templates/email_template_eh.php (revision 16323) @@ -1,681 +1,741 @@ Array ('self' => 'edit'), 'OnSaveSelected' => Array ('self' => 'view'), 'OnExportEmailTemplates' => Array ('self' => 'view'), 'OnSuggestAddressJSON' => Array ('self' => 'add|edit'), // events only for developers 'OnPreCreate' => Array ('self' => 'debug'), 'OnDelete' => Array ('self' => 'debug'), 'OnDeleteAll' => Array ('self' => 'debug'), 'OnMassDelete' => Array ('self' => 'debug'), 'OnMassApprove' => Array ('self' => 'debug'), 'OnMassDecline' => Array ('self' => 'debug'), 'OnSend' => Array ('self' => 'debug'), ); $this->permMapping = array_merge($this->permMapping, $permissions); } /** * Changes permission section to one from REQUEST, not from config * * @param kEvent $event * @return bool * @access public */ public function CheckPermission(kEvent $event) { $module = $this->Application->GetVar('module'); if ( strlen($module) > 0 ) { // checking permission when listing module email events in separate section $module = explode(':', $module, 2); if ( count($module) == 1 ) { $main_prefix = $this->Application->findModule('Name', $module[0], 'Var'); } else { $exceptions = Array ('Category' => 'c', 'Users' => 'u'); $main_prefix = $exceptions[$module[1]]; } $section = $this->Application->getUnitConfig($main_prefix)->getPermSectionByName('email'); $event->setEventParam('PermSection', $section); } // checking permission when listing all email events when editing language return parent::CheckPermission($event); } /** * Apply any custom changes to list's sql query * * @param kEvent $event * @return void * @access protected * @see kDBEventHandler::OnListBuild() */ protected function SetCustomQuery(kEvent $event) { parent::SetCustomQuery($event); $object = $event->getObject(); /* @var $object kDBList */ if ( $event->Special == 'module' ) { $module = $this->Application->GetVar('module'); $object->addFilter('module_filter', '%1$s.Module = ' . $this->Conn->qstr($module)); } else { $object->addFilter('module_filter', '%1$s.Module IN (SELECT Name FROM ' . TABLE_PREFIX . 'Modules WHERE Loaded = 1)'); } if ( !$event->Special && !$this->Application->isDebugMode() ) { // no special $object->addFilter('enabled_filter', '%1$s.Enabled <> ' . STATUS_DISABLED); } } /** * Prepares new kDBItem object * * @param kEvent $event * @return void * @access protected */ protected function OnNew(kEvent $event) { parent::OnNew($event); $mapping = Array ('conf' => 'VariableValue', 'site-domain' => 'DefaultEmailRecipients'); if ( isset($mapping[$event->Special]) ) { $object = $event->getObject(); /* @var $object kDBItem */ $target_object = $this->Application->recallObject($event->Special); /* @var $target_object kDBList */ $object->SetDBField('Recipients', $target_object->GetDBField($mapping[$event->Special])); } } /** * Set default headers * * @param kEvent $event * @return void * @access protected */ protected function OnPreCreate(kEvent $event) { parent::OnPreCreate($event); $object = $event->getObject(); /* @var $object kDBItem */ $object->SetDBField('Headers', $this->Application->ConfigValue('Smtp_DefaultHeaders')); $this->setRequired($event); } /** * Sets status Front-End Only to selected email events * * @param kEvent $event */ function OnFrontOnly($event) { if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) { $event->status = kEvent::erFAIL; return; } $config = $event->getUnitConfig(); $sql = 'UPDATE ' . $config->getTableName() . ' SET FrontEndOnly = 1 WHERE ' . $config->getIDField() . ' IN (' . implode(',', $this->StoreSelectedIDs($event)) . ')'; $this->Conn->Query($sql); $this->clearSelectedIDs($event); } /** * Sets selected user to email events selected * * @param kEvent $event * @return void * @access protected */ protected function OnSelectUser(kEvent $event) { if ( $event->Special != 'module' ) { parent::OnSelectUser($event); return; } if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) { $event->status = kEvent::erFAIL; return; } $items_info = $this->Application->GetVar('u'); if ( $items_info ) { list ($user_id, ) = each($items_info); $config = $event->getUnitConfig(); $ids = $this->Application->RecallVar($event->getPrefixSpecial() . '_selected_ids'); $sql = 'UPDATE ' . $config->getTableName() . ' SET ' . $this->Application->RecallVar('dst_field') . ' = ' . $user_id . ' WHERE ' . $config->getIDField() . ' IN (' . $ids . ')'; $this->Conn->Query($sql); } $this->finalizePopup($event); } /** * Saves selected ids to session * * @param kEvent $event */ function OnSaveSelected($event) { $this->StoreSelectedIDs($event); } /** * Prefills module dropdown * * @param kEvent $event * @return void * @access protected */ protected function OnAfterConfigRead(kEvent $event) { parent::OnAfterConfigRead($event); - $options = Array (); + $config = $event->getUnitConfig(); - foreach ($this->Application->ModuleInfo as $module_name => $module_info) { - if ( $module_name == 'In-Portal' ) { - continue; - } + $fields = $config->getFields(); + $fields['Module']['options'] = $this->_getModules(); - $options[$module_name] = $module_name; + if ( $this->Application->findModule('Name', 'Custom') ) { + $fields['Module']['default'] = 'Custom'; } - $config = $event->getUnitConfig(); - - $fields = $config->getFields(); - $fields['Module']['options'] = $options; $config->setFields($fields); + $ml_helper = $this->Application->recallObject('kMultiLanguageHelper'); + /* @var $ml_helper kMultiLanguageHelper */ + + $ml_helper->replaceMLCalculatedFields($event); + if ( $this->Application->GetVar('regional') ) { $config->setPopulateMlFields(true); } } /** + * Returns modules, where e-mail event can be added to + * + * @return Array + * @access protected + */ + protected function _getModules() + { + $ret = Array (); + + foreach ($this->Application->ModuleInfo as $module_name => $module_info) { + if ( $module_name == 'In-Portal' ) { + continue; + } + + $ret[$module_name] = $module_name; + } + + return $ret; + } + + /** * Prepare temp tables and populate it * with items selected in the grid * * @param kEvent $event * @return void * @access protected */ protected function OnEdit(kEvent $event) { parent::OnEdit($event); // use language from grid, instead of primary language used by default $event->SetRedirectParam('m_lang', $this->Application->GetVar('m_lang')); } /** * Fixes default recipient type * * @param kEvent $event * @return void * @access protected */ protected function OnAfterItemLoad(kEvent $event) { parent::OnAfterItemLoad($event); $object = $event->getObject(); /* @var $object kDBItem */ if ( !$this->Application->isDebugMode(false) ) { if ( $object->GetDBField('AllowChangingRecipient') ) { $object->SetDBField('RecipientType', EmailTemplate::RECIPIENT_TYPE_TO); } else { $object->SetDBField('RecipientType', EmailTemplate::RECIPIENT_TYPE_CC); } } // process replacement tags $records = Array (); $replacement_tags = $object->GetDBField('ReplacementTags'); $replacement_tags = $replacement_tags ? unserialize($replacement_tags) : Array (); foreach ($replacement_tags as $tag => $replacement) { $records[] = Array ('Tag' => $tag, 'Replacement' => $replacement); } $minput_helper = $this->Application->recallObject('MInputHelper'); /* @var $minput_helper MInputHelper */ $xml = $minput_helper->prepareMInputXML($records, Array ('Tag', 'Replacement')); $object->SetDBField('ReplacementTagsXML', $xml); $this->setRequired($event); + + $ml_helper = $this->Application->recallObject('kMultiLanguageHelper'); + /* @var $ml_helper kMultiLanguageHelper */ + + $translation_fields = $this->getTranslationFields(); + $source_language = $ml_helper->getSourceLanguage($object->GetDBField('TranslateFromLanguage')); + + foreach ($translation_fields as $translation_field) { + $object->SetDBField('Source' . $translation_field, $object->GetDBField('l' . $source_language . '_' . $translation_field)); + } } /** * Performs custom validation + keep read-only fields * * @param kEvent $event */ function _itemChanged($event) { $object = $event->getObject(); /* @var $object kDBItem */ if ( !$this->Application->isDebugMode(false) ) { // only allow to enable/disable event while in debug mode $to_restore = Array ('Enabled', 'AllowChangingSender', 'AllowChangingRecipient'); if ( !$object->GetOriginalField('AllowChangingSender') ) { $to_restore = array_merge($to_restore, Array ('CustomSender', 'SenderName', 'SenderAddressType', 'SenderAddress')); } if ( !$object->GetOriginalField('AllowChangingRecipient') ) { $to_restore = array_merge($to_restore, Array ('CustomRecipient' /*, 'Recipients'*/)); } // prevent specific fields from editing foreach ($to_restore as $restore_field) { $original_value = $object->GetOriginalField($restore_field); if ( $object->GetDBField($restore_field) != $original_value ) { $object->SetDBField($restore_field, $original_value); } } } // process replacement tags if ( $object->GetDBField('ReplacementTagsXML') ) { $minput_helper = $this->Application->recallObject('MInputHelper'); /* @var $minput_helper MInputHelper */ $replacement_tags = Array (); $records = $minput_helper->parseMInputXML($object->GetDBField('ReplacementTagsXML')); foreach ($records as $record) { $replacement_tags[trim($record['Tag'])] = trim($record['Replacement']); } $object->SetDBField('ReplacementTags', $replacement_tags ? serialize($replacement_tags) : NULL); } if ( $this->translationChanged($object) ) { $object->SetDBField('LastChanged_date', TIMENOW); $object->SetDBField('LastChanged_time', TIMENOW); } $this->setRequired($event); } /** * Dynamically changes required fields * * @param kEvent $event * @return void * @access protected */ protected function setRequired(kEvent $event) { $object = $event->getObject(); /* @var $object kDBItem */ $language_prefix = 'l' . $this->Application->GetVar('m_lang') . '_'; $object->setRequired($language_prefix . 'HtmlBody', !$object->GetField('PlainTextBody')); $object->setRequired($language_prefix . 'PlainTextBody', !$object->GetField('HtmlBody')); } /** * Checks, that at least one of phrase's translations was changed * * @param kDBItem $object * @return bool */ function translationChanged($object) { + $translation_fields = $this->getTranslationFields(); $changed_fields = array_keys($object->GetChangedFields()); - $translation_fields = Array ('Subject', 'HtmlBody', 'PlainTextBody'); foreach ($changed_fields as $changed_field) { $changed_field = preg_replace('/^l[\d]+_/', '', $changed_field); if ( in_array($changed_field, $translation_fields) ) { return true; } } return false; } /** + * Returns fields, that can be translated + * + * @return Array + * @access protected + */ + protected function getTranslationFields() + { + return Array ('Subject', 'HtmlBody', 'PlainTextBody'); + } + + /** * Don't allow to enable/disable events in non-debug mode * * @param kEvent $event * @return void * @access protected */ protected function OnBeforeItemCreate(kEvent $event) { parent::OnBeforeItemCreate($event); $this->_itemChanged($event); } /** * Don't allow to enable/disable events in non-debug mode * * @param kEvent $event * @return void * @access protected */ protected function OnBeforeItemUpdate(kEvent $event) { parent::OnBeforeItemUpdate($event); $this->_itemChanged($event); } /** * Suggest address based on typed address and selected address type * * @param kEvent $event */ function OnSuggestAddressJSON($event) { $event->status = kEvent::erSTOP; $address_type = $this->Application->GetVar('type'); $address = $this->Application->GetVar('term'); $limit = $this->Application->GetVar('limit'); if ( !$limit ) { $limit = 20; } switch ($address_type) { case EmailTemplate::ADDRESS_TYPE_EMAIL: $field = 'Email'; $table_name = TABLE_PREFIX . 'Users'; break; case EmailTemplate::ADDRESS_TYPE_USER: $field = 'Username'; $table_name = TABLE_PREFIX . 'Users'; break; case EmailTemplate::ADDRESS_TYPE_GROUP: $field = 'Name'; $table_name = TABLE_PREFIX . 'UserGroups'; break; default: $field = $table_name = ''; break; } if ( $field ) { $sql = 'SELECT DISTINCT ' . $field . ' FROM ' . $table_name . ' WHERE ' . $field . ' LIKE ' . $this->Conn->qstr($address . '%') . ' ORDER BY ' . $field . ' ASC LIMIT 0,' . $limit; $data = $this->Conn->GetCol($sql); } else { $data = Array (); } echo json_encode($data); } /** * Does custom validation * * @param kEvent $event * @return void * @access protected */ protected function OnBeforeItemValidate(kEvent $event) { parent::OnBeforeItemValidate($event); $object = $event->getObject(); /* @var $object kDBItem */ // validate email subject and body for parsing errors $this->_validateEmailTemplate($object); // validate sender and recipient addresses if ( $object->GetDBField('CustomSender') ) { $this->_validateAddress($event, 'Sender'); } $this->_validateAddress($event, 'Recipient'); $this->_validateBindEvent($object); } /** * Validates subject and body fields of Email template * * @param kDBItem $object * @return void * @access protected */ protected function _validateEmailTemplate($object) { $email_template_helper = $this->Application->recallObject('kEmailTemplateHelper'); /* @var $email_template_helper kEmailTemplateHelper */ $email_template_helper->parseField($object, 'Subject'); $email_template_helper->parseField($object, 'HtmlBody'); $email_template_helper->parseField($object, 'PlainTextBody'); } /** * Validates address using given field prefix * * @param kEvent $event * @param string $field_prefix * @return void * @access protected */ protected function _validateAddress($event, $field_prefix) { $object = $event->getObject(); /* @var $object kDBItem */ $address_type = $object->GetDBField($field_prefix . 'AddressType'); $object->setRequired($field_prefix . 'Address', $address_type > 0); $address = $object->GetDBField($field_prefix . 'Address'); if ( !$address ) { // don't validate against empty address return; } switch ($address_type) { case EmailTemplate::ADDRESS_TYPE_EMAIL: if ( !preg_match('/^(' . REGEX_EMAIL_USER . '@' . REGEX_EMAIL_DOMAIN . ')$/i', $address) ) { $object->SetError($field_prefix . 'Address', 'invalid_email'); } break; case EmailTemplate::ADDRESS_TYPE_USER: $sql = 'SELECT PortalUserId FROM ' . TABLE_PREFIX . 'Users WHERE Username = ' . $this->Conn->qstr($address); if ( !$this->Conn->GetOne($sql) ) { $object->SetError($field_prefix . 'Address', 'invalid_user'); } break; case EmailTemplate::ADDRESS_TYPE_GROUP: $sql = 'SELECT GroupId FROM ' . TABLE_PREFIX . 'UserGroups WHERE Name = ' . $this->Conn->qstr($address); if ( !$this->Conn->GetOne($sql) ) { $object->SetError($field_prefix . 'Address', 'invalid_group'); } break; } } /** * Checks that bind event is specified in correct format and exists * * @param kDBItem $object */ protected function _validateBindEvent($object) { $event_string = $object->GetDBField('BindToSystemEvent'); if ( !$event_string ) { return; } try { $this->Application->eventImplemented(new kEvent($event_string)); } catch (Exception $e) { $object->SetError('BindToSystemEvent', 'invalid_event', '+' . $e->getMessage()); } } /** * Stores ids of selected phrases and redirects to export language step 1 * * @param kEvent $event * @return void * @access protected */ protected function OnExportEmailTemplates(kEvent $event) { if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) { $event->status = kEvent::erFAIL; return; } $this->Application->getUnitConfig('phrases')->setAutoLoad(false); $this->StoreSelectedIDs($event); $this->Application->StoreVar('export_language_ids', $this->Application->GetVar('m_lang')); $event->setRedirectParams( Array ( 'phrases.export_event' => 'OnNew', 'pass' => 'all,phrases.export', 'export_mode' => $event->Prefix, ) ); } /** * Deletes all subscribers to e-mail event after it was deleted * * @param kEvent $event * @return void * @access protected */ protected function OnAfterItemDelete(kEvent $event) { parent::OnAfterItemDelete($event); $object = $event->getObject(); /* @var $object kDBItem */ $sql = 'SELECT SubscriptionId FROM ' . TABLE_PREFIX . 'SystemEventSubscriptions WHERE EmailTemplateId = ' . $object->GetID(); $ids = $this->Conn->GetCol($sql); if ( !$ids ) { return; } $temp_handler = $this->Application->recallObject('system-event-subscription_TempHandler', 'kTempTablesHandler', Array ('parent_event' => $event->MasterEvent)); /* @var $temp_handler kTempTablesHandler */ $temp_handler->DeleteItems('system-event-subscription', '', $ids); } /** * Sends selected e-mail event * * @param kEvent $event * @return void * @access protected */ protected function OnSend(kEvent $event) { $object = $event->getObject(Array ('skip_autoload' => true)); /* @var $object kDBItem */ $ids = $this->StoreSelectedIDs($event); foreach ($ids as $id) { $object->Load($id); if ( $object->GetDBField('Type') == EmailTemplate::TEMPLATE_TYPE_ADMIN ) { $this->Application->emailAdmin($object->GetDBField('TemplateName')); } else { $this->Application->emailUser($object->GetDBField('TemplateName')); } } $this->clearSelectedIDs($event); } - } \ No newline at end of file + + /** + * Updates translation state for all saved phrases + * + * @param kEvent $event + * @return void + * @access protected + */ + protected function OnBeforeCopyToLive(kEvent $event) + { + parent::OnBeforeCopyToLive($event); + + $ml_helper = $this->Application->recallObject('kMultiLanguageHelper'); + /* @var $ml_helper kMultiLanguageHelper */ + + $ml_helper->updateTranslationState($event); + } + + } Index: branches/5.3.x/core/units/email_templates/email_template_tp.php =================================================================== --- branches/5.3.x/core/units/email_templates/email_template_tp.php (revision 16322) +++ branches/5.3.x/core/units/email_templates/email_template_tp.php (revision 16323) @@ -1,102 +1,142 @@ Application->isDebugMode() ) { $config = $this->getUnitConfig(); $grids = $config->getGrids(Array ()); foreach ($grids as $grid_name => $grid_data) { if ( array_key_exists('Enabled', $grid_data['Fields']) ) { unset($grids[$grid_name]['Fields']['Enabled']); } } $config->setGrids($grids); } } /** * Checks, that field can be edited * * @param Array $params * @return string */ function IsEditable($params) { if ($this->Application->isDebugMode()) { return true; } $object = $this->getObject($params); /* @var $object kDBItem */ return $object->GetDBField($params['check_field']); } /** * To recipient read-only * * @param Array $params * @return string * @access protected */ protected function ToRecipientReadOnly($params) { return !$this->IsEditable(Array ('check_field' => 'AllowChangingRecipient')); } /** * Removes "To" options from possible options in "RecipientType" field * * @param Array $params */ function RemoveToRecipientType($params) { $object = $this->getObject($params); /* @var $object kDBItem */ $field_options = $object->GetFieldOptions('RecipientType'); unset($field_options['options'][ EmailTemplate::RECIPIENT_TYPE_TO ]); $object->SetFieldOptions('RecipientType', $field_options); } /** * Restores "To" option in possible option list in "RecipientType" field * * @param Array $params */ function RestoreRecipientType($params) { $object = $this->getObject($params); /* @var $object kDBItem */ $field_options = $object->GetFieldOptions('RecipientType'); $virtual_field_options = $this->getUnitConfig()->getVirtualFieldByName('RecipientType'); $field_options['options'] = $virtual_field_options['options']; $object->SetFieldOptions('RecipientType', $field_options); } - } \ No newline at end of file + /** + * Determine if primary translation should be shown + * + * @param Array $params + * @return string + * @access protected + */ + protected function ShowSourceLanguage($params) + { + if ( $this->IsNewItem($params) ) { + return false; + } + + $object = $this->getObject($params); + /* @var $object kDBItem */ + + $ml_helper = $this->Application->recallObject('kMultiLanguageHelper'); + /* @var $ml_helper kMultiLanguageHelper */ + + return !$ml_helper->editingInSourceLanguage($object->GetDBField('TranslateFromLanguage')); + } + + /** + * Shows field label with %s replaced with source translation language + * + * @param Array $params + * @return string + * @access protected + */ + protected function SourceLanguageTitle($params) + { + $object = $this->getObject($params); + /* @var $object kDBItem */ + + $ml_helper = $this->Application->recallObject('kMultiLanguageHelper'); + /* @var $ml_helper kMultiLanguageHelper */ + + return $ml_helper->replaceSourceLanguage($object, $params['label']); + } + + } Index: branches/5.3.x/core/admin_templates/languages/email_template_edit.tpl =================================================================== --- branches/5.3.x/core/admin_templates/languages/email_template_edit.tpl (revision 16322) +++ branches/5.3.x/core/admin_templates/languages/email_template_edit.tpl (revision 16323) @@ -1,82 +1,124 @@
+ + + +
+ +
+ +
+
+
+ + + + + + + + + + + + + + + +
- \ No newline at end of file +