Array('self' => true), 'OnSetPrimary' => Array('self' => 'advanced:set_primary|add|edit'), 'OnImportLanguage' => Array('self' => 'advanced:import'), 'OnExportLanguage' => Array('self' => 'advanced:export'), 'OnExportProgress' => Array('self' => 'advanced:export'), 'OnReflectMultiLingualFields' => Array ('self' => 'view'), 'OnSynchronizeLanguages' => Array ('self' => 'edit'), ); $this->permMapping = array_merge($this->permMapping, $permissions); } /** * Checks user permission to execute given $event * * @param kEvent $event * @return bool * @access public */ public function CheckPermission(&$event) { if ($event->Name == 'OnItemBuild') { // check permission without using $event->getSection(), // so first cache rebuild won't lead to "ldefault_Name" field being used return true; } return parent::CheckPermission($event); } /** * Allows to get primary language object * * @param kEvent $event */ function getPassedID(&$event) { if ($event->Special == 'primary') { return $this->Application->GetDefaultLanguageId(); } return parent::getPassedID($event); } /** * [HOOK] Updates table structure on new language adding/removing language * * @param kEvent $event */ function OnReflectMultiLingualFields(&$event) { if ($this->Application->GetVar('ajax') == 'yes') { $event->status = kEvent::erSTOP; } if (is_object($event->MasterEvent)) { if ($event->MasterEvent->status != kEvent::erSUCCESS) { // only rebuild when all fields are validated return ; } if (($event->MasterEvent->Name == 'OnSave') && !$this->Application->GetVar('new_language')) { // only rebuild during new language adding return ; } } $ml_helper =& $this->Application->recallObject('kMultiLanguageHelper'); /* @var $ml_helper kMultiLanguageHelper */ $this->Application->UnitConfigReader->ReReadConfigs(); foreach ($this->Application->UnitConfigReader->configData as $prefix => $config_data) { $ml_helper->createFields($prefix); } $event->SetRedirectParam('action_completed', 1); } /** * Allows to set selected language as primary * * @param kEvent $event */ function OnSetPrimary(&$event) { if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) { $event->status = kEvent::erFAIL; return; } $this->StoreSelectedIDs($event); $ids = $this->getSelectedIDs($event); if ($ids) { $id = array_shift($ids); $object =& $event->getObject( Array('skip_autoload' => true) ); /* @var $object LanguagesItem */ $object->Load($id); $object->copyMissingData( $object->setPrimary() ); } } /** * [HOOK] Reset primary status of other languages if we are saving primary language * * @param kEvent $event */ function OnUpdatePrimary(&$event) { if ($event->MasterEvent->status != kEvent::erSUCCESS) { return ; } $object =& $event->getObject( Array('skip_autoload' => true) ); /* @var $object LanguagesItem */ $object->SwitchToLive(); // set primary for each languages, that have this checkbox checked $ids = explode(',', $event->MasterEvent->getEventParam('ids')); foreach ($ids as $id) { $object->Load($id); if ($object->GetDBField('PrimaryLang')) { $object->copyMissingData( $object->setPrimary(true, false) ); } if ($object->GetDBField('AdminInterfaceLang')) { $object->setPrimary(true, true); } } // if no primary language left, then set primary last language (not to load again) from edited list $sql = 'SELECT '.$object->IDField.' FROM '.$object->TableName.' WHERE PrimaryLang = 1'; $primary_language = $this->Conn->GetOne($sql); if (!$primary_language) { $object->setPrimary(false, false); // set primary language } $sql = 'SELECT '.$object->IDField.' FROM '.$object->TableName.' WHERE AdminInterfaceLang = 1'; $primary_language = $this->Conn->GetOne($sql); if (!$primary_language) { $object->setPrimary(false, true); // set admin interface language } } /** * Prefills options with dynamic values * * @param kEvent $event */ function OnAfterConfigRead(&$event) { parent::OnAfterConfigRead($event); $fields = $this->Application->getUnitOption($event->Prefix, 'Fields'); // set dynamic hints for options in date format fields $options = $fields['InputDateFormat']['options']; if ($options) { foreach ($options as $i => $v) { $options[$i] = $v . ' (' . adodb_date($i) . ')'; } $fields['InputDateFormat']['options'] = $options; } $options = $fields['InputTimeFormat']['options']; if ($options) { foreach ($options as $i => $v) { $options[$i] = $v . ' (' . adodb_date($i) . ')'; } $fields['InputTimeFormat']['options'] = $options; } $this->Application->setUnitOption($event->Prefix, 'Fields', $fields); } /** * Occurs before updating item * * @param kEvent $event * @return void * @access protected */ protected function OnBeforeItemUpdate(&$event) { $object =& $event->getObject(); /* @var $object kDBItem */ $status_fields = $this->Application->getUnitOption($event->Prefix, 'StatusField'); $status_field = array_shift($status_fields); if ( $object->GetDBField('PrimaryLang') == 1 && $object->GetDBField($status_field) == 0 ) { $object->SetDBField($status_field, 1); } } /** * Shows only enabled languages on front * * @param kEvent $event * @return void * @access protected * @see kDBEventHandler::OnListBuild() */ protected function SetCustomQuery(&$event) { $object =& $event->getObject(); /* @var $object kDBList */ if (in_array($event->Special, Array ('enabled', 'selected', 'available'))) { $object->addFilter('enabled_filter', '%1$s.Enabled = ' . STATUS_ACTIVE); } // site domain language picker if ($event->Special == 'selected' || $event->Special == 'available') { $edit_picker_helper =& $this->Application->recallObject('EditPickerHelper'); /* @var $edit_picker_helper EditPickerHelper */ $edit_picker_helper->applyFilter($event, 'Languages'); } // apply domain-based language filtering $languages = $this->Application->siteDomainField('Languages'); if (strlen($languages)) { $languages = explode('|', substr($languages, 1, -1)); $object->addFilter('domain_filter', '%1$s.LanguageId IN (' . implode(',', $languages) . ')'); } } /** * Copy labels from another language * * @param kEvent $event * @return void * @access protected */ protected function OnAfterItemCreate(&$event) { parent::OnAfterItemCreate($event); $object =& $event->getObject(); /* @var $object kDBItem */ $src_language = $object->GetDBField('CopyFromLanguage'); if ( $object->GetDBField('CopyLabels') && $src_language ) { $dst_language = $object->GetID(); // 1. schedule data copy after OnSave event is executed $var_name = $event->getPrefixSpecial() . '_copy_data' . $this->Application->GetVar('m_wid'); $pending_actions = $this->Application->RecallVar($var_name, Array ()); if ( $pending_actions ) { $pending_actions = unserialize($pending_actions); } $pending_actions[$src_language] = $dst_language; $this->Application->StoreVar($var_name, serialize($pending_actions)); $object->SetDBField('CopyLabels', 0); } } /** * Saves language from temp table to live * * @param kEvent $event * @return void * @access protected */ protected function OnSave(&$event) { parent::OnSave($event); if ( $event->status != kEvent::erSUCCESS ) { return; } $var_name = $event->getPrefixSpecial() . '_copy_data' . $this->Application->GetVar('m_wid'); $pending_actions = $this->Application->RecallVar($var_name, Array ()); if ( $pending_actions ) { $pending_actions = unserialize($pending_actions); } // create multilingual columns for phrases & email events table first (actual for 6+ language) $ml_helper =& $this->Application->recallObject('kMultiLanguageHelper'); /* @var $ml_helper kMultiLanguageHelper */ $ml_helper->createFields('phrases'); $ml_helper->createFields('emailevents'); foreach ($pending_actions as $src_language => $dst_language) { // phrases import $sql = 'UPDATE ' . $this->Application->getUnitOption('phrases', 'TableName') . ' SET l' . $dst_language . '_Translation = l' . $src_language . '_Translation'; $this->Conn->Query($sql); // events import $sql = 'UPDATE ' . $this->Application->getUnitOption('emailevents', 'TableName') . ' SET l' . $dst_language . '_Subject = l' . $src_language . '_Subject, l' . $dst_language . '_Body = l' . $src_language . '_Body'; $this->Conn->Query($sql); } $this->Application->RemoveVar($var_name); $event->CallSubEvent('OnReflectMultiLingualFields'); $event->CallSubEvent('OnUpdatePrimary'); } /** * Prepare temp tables for creating new item * but does not create it. Actual create is * done in OnPreSaveCreated * * @param kEvent $event * @return void * @access protected */ protected function OnPreCreate(&$event) { parent::OnPreCreate($event); $object =& $event->getObject(); /* @var $object kDBItem */ $object->SetDBField('CopyLabels', 1); $sql = 'SELECT ' . $object->IDField . ' FROM ' . $this->Application->getUnitOption($event->Prefix, 'TableName') . ' WHERE PrimaryLang = 1'; $primary_lang_id = $this->Conn->GetOne($sql); $object->SetDBField('CopyFromLanguage', $primary_lang_id); $object->SetDBField('SynchronizationModes', Language::SYNCHRONIZE_DEFAULT); } /** * Sets new language mark * * @param kEvent $event * @return void * @access protected */ protected function OnBeforeDeleteFromLive(&$event) { parent::OnBeforeDeleteFromLive($event); $id_field = $this->Application->getUnitOption($event->Prefix, 'IDField'); $sql = 'SELECT ' . $id_field . ' FROM ' . $this->Application->getUnitOption($event->Prefix, 'TableName') . ' WHERE ' . $id_field . ' = ' . $event->getEventParam('id'); $id = $this->Conn->GetOne($sql); if ( !$id ) { $this->Application->SetVar('new_language', 1); } } function OnChangeLanguage(&$event) { $language_id = $this->Application->GetVar('language'); if ($this->Application->isAdmin) { // admin data only $this->Application->SetVar('m_lang', $language_id); // set new language for this session (admin interface only) $this->Application->Session->SetField('Language', $language_id); // remember last user language in administrative console if ($this->Application->RecallVar('user_id') == USER_ROOT) { $this->Application->StorePersistentVar('AdminLanguage', $language_id); } else { $object =& $this->Application->recallObject('u.current'); /* @var $object kDBItem */ $object->SetDBField('AdminLanguage', $language_id); $object->Update(); } // without this language change in admin will cause erase of last remembered tree section $this->Application->SetVar('skip_last_template', 1); } else { // changing language on Front-End $this->Application->SetVar('m_lang', $language_id); if (MOD_REWRITE) { $mod_rewrite_helper =& $this->Application->recallObject('ModRewriteHelper'); /* @var $mod_rewrite_helper kModRewriteHelper */ $mod_rewrite_helper->removePages(); } } } /** * Parse language XML file into temp tables and redirect to progress bar screen * * @param kEvent $event */ function OnImportLanguage(&$event) { if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) { $event->status = kEvent::erFAIL; return; } $items_info = $this->Application->GetVar('phrases_import'); if ($items_info) { list ($id, $field_values) = each($items_info); $object =& $this->Application->recallObject('phrases.import', 'phrases', Array('skip_autoload' => true)); /* @var $object kDBItem */ $object->setID($id); $object->SetFieldsFromHash($field_values); if (!$object->Validate()) { $event->status = kEvent::erFAIL; return ; } $filename = $object->GetField('LangFile', 'full_path'); if (!filesize($filename)) { $object->SetError('LangFile', 'la_empty_file', 'la_EmptyFile'); $event->status = kEvent::erFAIL; } $language_import_helper =& $this->Application->recallObject('LanguageImportHelper'); /* @var $language_import_helper LanguageImportHelper */ $language_import_helper->performImport( $filename, $object->GetDBField('PhraseType'), $object->GetDBField('Module'), $object->GetDBField('ImportOverwrite') ? LANG_OVERWRITE_EXISTING : LANG_SKIP_EXISTING ); // delete uploaded language pack after import is finished unlink($filename); $event->SetRedirectParam('opener', 'u'); } } /** * Stores ids of selected languages and redirects to export language step 1 * * @param kEvent $event */ function OnExportLanguage(&$event) { if ($this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1)) { $event->status = kEvent::erFAIL; return; } $this->Application->setUnitOption('phrases','AutoLoad',false); $this->StoreSelectedIDs($event); $this->Application->StoreVar('export_language_ids', implode(',', $this->getSelectedIDs($event)) ); $event->setRedirectParams( Array('phrases.export_event' => 'OnNew', 'pass' => 'all,phrases.export') ); } /** * Saves selected languages to xml file passed * * @param kEvent $event */ function OnExportProgress(&$event) { $items_info = $this->Application->GetVar('phrases_export'); if ($items_info) { list($id, $field_values) = each($items_info); $object =& $this->Application->recallObject('phrases.export', null, Array('skip_autoload' => true)); /* @var $object kDBItem */ $object->setID($id); $object->SetFieldsFromHash($field_values); if (!$object->Validate()) { $event->status = kEvent::erFAIL; return ; } $file_helper =& $this->Application->recallObject('FileHelper'); /* @var $file_helper FileHelper */ $file_helper->CheckFolder(EXPORT_PATH); if (!is_writable(EXPORT_PATH)) { $event->status = kEvent::erFAIL; $object->SetError('LangFile', 'write_error', 'la_ExportFolderNotWritable'); return ; } if ( substr($field_values['LangFile'], -5) != '.lang') { $field_values['LangFile'] .= '.lang'; } $filename = EXPORT_PATH . '/' . $field_values['LangFile']; $language_import_helper =& $this->Application->recallObject('LanguageImportHelper'); /* @var $language_import_helper LanguageImportHelper */ if ($object->GetDBField('DoNotEncode')) { $language_import_helper->setExportEncoding('plain'); } $language_import_helper->setExportLimits($field_values['ExportPhrases'], $field_values['ExportEmailEvents']); $lang_ids = explode(',', $this->Application->RecallVar('export_language_ids') ); $language_import_helper->performExport($filename, $field_values['PhraseType'], $lang_ids, $field_values['Module']); } $event->redirect = 'regional/languages_export_step2'; $event->SetRedirectParam('export_file', $field_values['LangFile']); } /** * Returns to previous template in opener stack * * @param kEvent $event */ function OnGoBack(&$event) { $event->SetRedirectParam('opener', 'u'); } function OnScheduleTopFrameReload(&$event) { $this->Application->StoreVar('RefreshTopFrame',1); } /** * Do now allow deleting current language * * @param kEvent $event */ function OnBeforeItemDelete(&$event) { $object =& $event->getObject(); /* @var $object kDBItem */ if ( $object->GetDBField('PrimaryLang') || $object->GetDBField('AdminInterfaceLang') || $object->GetID() == $this->Application->GetVar('m_lang') ) { $event->status = kEvent::erFAIL; } } /** * Deletes phrases and email events on given language * * @param kEvent $event */ function OnAfterItemDelete(&$event) { parent::OnAfterItemDelete($event); $object =& $event->getObject(); /* @var $object kDBItem */ // clean Events table $fields_hash = Array ( 'l' . $object->GetID() . '_Subject' => NULL, 'l' . $object->GetID() . '_Body' => NULL, ); $this->Conn->doUpdate($fields_hash, $this->Application->getUnitOption('emailevents', 'TableName'), 1); // clean Phrases table $fields_hash = Array ( 'l' . $object->GetID() . '_Translation' => NULL, ); $this->Conn->doUpdate($fields_hash, $this->Application->getUnitOption('phrases', 'TableName'), 1); } /** * Copy missing phrases across all system languages (starting from primary) * * @param kEvent $event * @return void * @access protected */ protected function OnSynchronizeLanguages(&$event) { if ( $this->Application->CheckPermission('SYSTEM_ACCESS.READONLY', 1) ) { $event->status = kEvent::erFAIL; return; } $source_languages = $target_languages = Array (); // get language list with primary language first $sql = 'SELECT SynchronizationModes, LanguageId FROM ' . TABLE_PREFIX . 'Language WHERE SynchronizationModes <> "" ORDER BY PrimaryLang DESC'; $languages = $this->Conn->GetCol($sql, 'LanguageId'); foreach ($languages as $language_id => $synchronization_modes) { $synchronization_modes = explode('|', substr($synchronization_modes, 1, -1)); if ( in_array(Language::SYNCHRONIZE_TO_OTHERS, $synchronization_modes) ) { $source_languages[] = $language_id; } if ( in_array(Language::SYNCHRONIZE_FROM_OTHERS, $synchronization_modes) ) { $target_languages[] = $language_id; } } foreach ($source_languages as $source_id) { foreach ($target_languages as $target_id) { if ( $source_id == $target_id ) { continue; } $sql = 'UPDATE ' . TABLE_PREFIX . 'Phrase SET l' . $target_id . '_Translation = l' . $source_id . '_Translation WHERE COALESCE(l' . $target_id . '_Translation, "") = "" AND COALESCE(l' . $source_id . '_Translation, "") <> ""'; $this->Conn->Query($sql); } } } }