Файловый менеджер - Редактировать - /var/www/xthruster/html/wp-content/uploads/flags/package-translation.tar
Назад
wpml-package-translation.php 0000644 00000003014 14721633032 0012160 0 ustar 00 <?php /* WPML Package Translation This is now part of String Translation. */ if ( defined( 'WPML_PACKAGE_TRANSLATION' ) ) { return; } define( 'WPML_PACKAGE_TRANSLATION', '0.0.2' ); define( 'WPML_PACKAGE_TRANSLATION_PATH', dirname( __FILE__ ) ); define( 'WPML_PACKAGE_TRANSLATION_URL', WPML_ST_URL . '/inc/' . basename( WPML_PACKAGE_TRANSLATION_PATH ) ); require WPML_PACKAGE_TRANSLATION_PATH . '/inc/wpml-package-constants.php'; require WPML_PACKAGE_TRANSLATION_PATH . '/inc/wpml-package-translation-exception.class.php'; require WPML_PACKAGE_TRANSLATION_PATH . '/inc/wpml-package-translation-helper.class.php'; require WPML_PACKAGE_TRANSLATION_PATH . '/inc/wpml-package-translation-ui.class.php'; require WPML_PACKAGE_TRANSLATION_PATH . '/inc/wpml-package-translation-html-packages.class.php'; require WPML_PACKAGE_TRANSLATION_PATH . '/inc/wpml-package-translation-metabox.class.php'; require WPML_PACKAGE_TRANSLATION_PATH . '/inc/wpml-package-translation-st.class.php'; require WPML_PACKAGE_TRANSLATION_PATH . '/inc/wpml-package-translation-tm-jobs.class.php'; require WPML_PACKAGE_TRANSLATION_PATH . '/inc/wpml-package-translation-tm.class.php'; require WPML_PACKAGE_TRANSLATION_PATH . '/inc/wpml-package.class.php'; require WPML_PACKAGE_TRANSLATION_PATH . '/inc/wpml-package-translation.class.php'; $WPML_package_translation = new WPML_Package_Translation(); $WPML_Package_Translation_UI = new WPML_Package_Translation_UI(); $WPML_Package_Translation_HTML_Packages = new WPML_Package_Translation_HTML_Packages(); inc/wpml-package-translation-st.class.php 0000644 00000001261 14721633032 0014463 0 ustar 00 <?php class WPML_Package_ST { public function get_string_element( $string_id, $column = false ) { global $wpdb; $package_query = "SELECT * FROM {$wpdb->prefix}icl_strings WHERE id=%d"; $package_prepare = $wpdb->prepare( $package_query, array( $string_id ) ); $result = $wpdb->get_row( $package_prepare ); if ( $result && $column && isset( $result[ $column ] ) ) { $result = $result[ $column ]; } return $result; } public function get_string_title( $title, $string_details ) { $string_title = $this->get_string_element( $string_details['string_id'], 'title' ); if ( $string_title ) { return $string_title; } else { return $title; } } } inc/wpml-package-translation.class.php 0000644 00000064476 14721633032 0014060 0 ustar 00 <?php class WPML_Package_Translation extends WPML_Package_Helper { var $load_priority = 100; var $package_translation_active; var $admin_lang_switcher = null; function __construct() { parent::__construct(); add_action( 'wpml_loaded', array( $this, 'loaded' ), $this->load_priority, 1 ); } function loaded( SitePress $sitepress = null ) { parent::loaded(); if ( null === $sitepress ) { global $sitepress; } $is_setup_complete = (bool) $sitepress->get_setting( 'setup_complete', false ); if ( $is_setup_complete ) { $this->run_db_update(); } if ( $this->passed_dependencies() && $is_setup_complete ) { $this->add_admin_hooks(); $this->add_global_hooks(); if ( is_admin() ) { if ( $this->is_refresh_required() ) { add_action( 'init', array( $this, 'refresh_packages' ), 999, 0 ); $this->set_refresh_not_required(); } } } } private function add_admin_hooks() { if ( is_admin() || $this->is_doing_xmlrpc() || wpml_is_rest_request() || ( defined( 'DOING_CRON' ) && DOING_CRON ) ) { add_action( 'wp_ajax_wpml_delete_packages', array( $this, 'delete_packages_ajax' ) ); add_action( 'wp_ajax_wpml_change_package_lang', array( $this, 'change_package_lang_ajax' ) ); /* Core hooks */ add_filter( 'wpml_pt_all_packages', array( $this, 'get_all_packages' ) ); /* Translation hooks for other plugins to use */ add_filter( 'wpml_tm_element_type', array( $this, 'get_element_type' ), 10, 2 ); add_filter( 'wpml_tm_dashboard_title_locations', array( $this, 'add_title_db_location' ), 10, 1 ); add_filter( 'wpml_string_title_from_id', array( $this, 'string_title_from_id_filter' ), 10, 2 ); // TODO: deprecated, use the 'wpml_register_string' action add_filter( 'WPML_register_string', array( $this, 'register_string_for_translation' ), 10, 5 ); add_action( 'wpml_add_string_translation', array( $this, 'add_string_translation_action' ), 10, 7 ); // TODO: These 3 hooks are deprecated. They are needed for Layouts 1.0. Consider removing them after Layouts 1.2 is released add_filter( 'WPML_get_translated_strings', array( $this, 'get_translated_strings' ), 10, 2 ); add_action( 'WPML_set_translated_strings', array( $this, 'set_translated_strings' ), 10, 2 ); add_action( 'WPML_show_package_language_ui', array( $this, 'show_language_selector' ), 10, 2 ); add_filter( 'wpml_get_translated_strings', array( $this, 'get_translated_strings' ), 10, 2 ); add_action( 'wpml_set_translated_strings', array( $this, 'set_translated_strings' ), 10, 2 ); add_action( 'wpml_show_package_language_ui', array( $this, 'show_language_selector' ), 10, 2 ); add_action( 'wpml_show_package_language_admin_bar', array( $this, 'show_admin_bar_language_selector' ), 10, 2 ); /* WPML hooks */ add_filter( 'wpml_get_translatable_types', array( $this, 'get_translatable_types' ), 10, 1 ); add_filter( 'wpml_get_translatable_item', array( $this, 'get_translatable_item' ), 10, 3 ); add_filter( 'wpml_external_item_url', array( $this, 'get_package_edit_url' ), 10, 2 ); add_filter( 'wpml_external_item_link', array( $this, 'get_package_edit_link' ), 10, 3 ); add_filter( 'wpml_get_external_item_title', array( $this, 'get_package_title' ), 10, 3 ); add_filter( 'wpml_element_id_from_package', array( $this, 'get_element_id_from_package_filter' ), 10, 2 ); add_filter( 'wpml_get_package_type', array( $this, 'get_package_type' ), 10, 2 ); add_filter( 'wpml_get_package_type_prefix', array( $this, 'get_package_type_prefix' ), 10, 2 ); add_filter( 'wpml_language_for_element', array( $this, 'get_language_for_element' ), 10, 2 ); add_filter( 'wpml_st_get_string_package', array( $this, 'get_string_package' ), 10, 2 ); add_action( 'wpml_save_external', [ $this, 'save_package_translations' ], 10, 3 ); /* Translation queue hooks */ add_filter( 'wpml_tm_external_translation_job_title', array( $this, 'get_post_title' ), 10, 2 ); add_filter( 'wpml_tm_add_to_basket', array( $this, 'add_to_basket' ), 10, 1 ); add_filter( 'wpml_tm_translation_jobs_basket', array( $this, 'update_translation_jobs_basket' ), 10, 3 ); add_filter( 'wpml_tm_basket_items_types', array( $this, 'basket_items_types' ), 10, 1 ); /* TM Hooks */ // This is called by \TranslationManagement::send_all_jobs - The hook is dynamically built. add_filter( 'wpml_tm_dashboard_sql', array( $this, 'tm_dashboard_sql_filter' ), 10, 1 ); /* Translation editor hooks */ add_filter( 'wpml_tm_editor_string_name', array( $this, 'get_editor_string_name' ), 10, 2 ); add_filter( 'wpml_tm_editor_string_style', array( $this, 'get_editor_string_style' ), 10, 3 ); /* API Hooks */ // @deprecated @since 3.2 Use 'wpml_delete_package' add_action( 'wpml_delete_package_action', array( $this, 'delete_package_action' ), 10, 2 ); add_action( 'deleted_post', array( $this, 'remove_post_packages' ) ); } } private function is_doing_xmlrpc() { return ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST ); } private function add_global_hooks() { // TODO: deprecated, use the 'wpml_translate_string' filter add_filter( 'WPML_translate_string', array( $this, 'translate_string' ), 10, 3 ); add_filter( 'wpml_translate_string', array( $this, 'translate_string' ), 10, 3 ); add_action( 'wpml_register_string', array( $this, 'register_string_action' ), 10, 5 ); add_action( 'wpml_start_string_package_registration', array( $this, 'start_string_package_registration_action' ), 10, 1 ); add_action( 'wpml_delete_unused_package_strings', array( $this, 'delete_unused_package_strings_action' ), 10, 1 ); add_action( 'wpml_delete_package', array( $this, 'delete_package_action' ), 10, 2 ); add_filter( 'wpml_st_get_post_string_packages', array( $this, 'get_post_string_packages' ), 10, 2 ); add_filter( 'wpml_string_id_from_package', array( $this, 'string_id_from_package_filter' ), 10, 4 ); /* API Hooks */ add_filter( 'wpml_is_external', array( $this, 'is_external' ), 10, 2 ); } private function run_db_update() { if ( is_admin() ) { WPML_Package_Translation_Schema::run_update(); } } /** * @return bool */ private function passed_dependencies() { return defined( 'ICL_SITEPRESS_VERSION' ) && defined( 'WPML_ST_VERSION' ) && defined( 'WPML_TM_VERSION' ); } public function add_title_db_location( $locations ) { global $wpdb; $locations[ $wpdb->prefix . 'icl_string_packages' ] = array( 'id_column' => 'ID', 'title_column' => 'title', 'element_type_prefix' => 'package', 'date_column' => false, ); return $locations; } function get_package_edit_url( $url, $post_id ) { $package = new WPML_Package( $post_id ); if ( ! $package ) { return false; } //not ours if ( isset( $package->edit_link ) ) { $url = $package->edit_link; } return $url; } public function get_package_title( $title, $kind, $id ) { $package = new WPML_Package( $id ); if ( ! $package ) { return $title; } //not ours if ( isset( $package->title ) ) { $title = $package->title; } return $title; } function get_package_view_link( $link, $post_id, $hide_if_missing_link = false ) { $package = new WPML_Package( $post_id ); if ( ! $package ) { return $link; } //not ours return $this->build_package_link( $package->view_link, $package->title, $hide_if_missing_link ); } function get_package_edit_link( $link, $post_id, $hide_if_missing_link = false ) { $package = new WPML_Package( $post_id ); if ( ! $package ) { return $link; } //not ours return $this->build_package_link( $package->edit_link, esc_html( $package->title ), $hide_if_missing_link ); } private function build_package_link( $url, $title, $hide_if_missing_link = false ) { $link = '<a href="' . $url . '">' . $title . '</a>'; if ( false === $hide_if_missing_link ) { if ( ! $url ) { $link = $title; } } elseif ( ! $url ) { $link = ''; } return $link; } /** * @param stdClass|WPML_Package|array|int $package * @param array<string,mixed> $args */ function show_language_selector( $package, $args = array() ) { global $wpdb, $sitepress; $wpml_pt_meta = new WPML_Package_Translation_Metabox( $package, $wpdb, $sitepress, $args ); echo $wpml_pt_meta->get_metabox(); } /** * @param stdClass|WPML_Package|array|int $package * @param array<string,mixed> $args */ function show_admin_bar_language_selector( $package, $args = array() ) { require WPML_PACKAGE_TRANSLATION_PATH . '/inc/wpml-package-admin-lang-switcher.class.php'; $this->admin_lang_switcher = new WPML_Package_Admin_Lang_Switcher( $package, $args ); } function cleanup_translation_jobs_basket_packages( $translation_jobs_basket ) { if ( empty( $translation_jobs_basket['packages'] ) ) { return; } foreach ( $translation_jobs_basket['packages'] as $id => $data ) { if ( ! new WPML_Package( $id ) ) { TranslationProxy_Basket::delete_item_from_basket( $id ); } } } public function update_translation_jobs_basket( $translation_jobs_cart, $translation_jobs_basket, $item_type ) { if ( $item_type == 'package' ) { if ( ! isset( $translation_jobs_basket[ $item_type ] ) ) { return false; } $packages = $translation_jobs_basket[ $item_type ]; if ( empty( $packages ) ) { return false; } $this->cleanup_translation_jobs_basket_packages( $translation_jobs_basket ); global $sitepress; /** @var int[] $packages_ids */ $packages_ids = array_keys( $packages ); foreach ( $packages_ids as $package_id ) { $package = new WPML_Package( $package_id ); if ( $package ) { if ( ! isset( $package->ID ) || ! $package->ID ) { TranslationProxy_Basket::delete_item_from_basket( $package_id, 'package' ); continue; } $package_source_language = $packages[ $package_id ]['from_lang']; $package_target_languages = $packages[ $package_id ]['to_langs']; $language_names = $this->languages_to_csv( $package_target_languages ); $final_post = array(); $final_post['post_title'] = $package->title; $final_post['post_notes'] = get_post_meta( $package->ID, '_icl_translator_note', true ); $final_post['post_type'] = $package->kind; if ( isset( $package->post_status ) ) { $final_post['post_status'] = $package->post_status; } if ( isset( $package->post_date ) ) { $final_post['post_date'] = $package->post_date; } $final_post['from_lang'] = $package_source_language; $final_post['from_lang_string'] = ucfirst( $sitepress->get_display_language_name( $package_source_language, $sitepress->get_admin_language() ) ); $final_post['to_langs'] = $package_target_languages; $final_post['to_langs_string'] = implode( ', ', $language_names ); $translation_jobs_cart[ $package_id ] = $final_post; } } } return $translation_jobs_cart; } public function basket_items_types( $item_types ) { $item_types['package'] = 'custom'; return $item_types; } /** * @param array<string,string> $package_target_languages * * @return array<string> */ private function languages_to_csv( $package_target_languages ) { global $sitepress; $language_names = array(); foreach ( $package_target_languages as $language_code => $value ) { $language_names[] = ucfirst( $sitepress->get_display_language_name( $language_code, $sitepress->get_admin_language() ) ); } return $language_names; } function is_external( $result, $type ) { return $result || is_a( $type, 'WPML_Package' ) || $type == 'package'; } public function get_element_type( $type, $element ) { if ( $this->is_a_package( $element ) ) { $type = 'package'; } return $type; } /** * @param array<string,string> $attributes * * @return string */ public function attributes_to_string( $attributes ) { $result = ''; foreach ( $attributes as $key => $value ) { if ( $result ) { $result .= ' '; } $result .= esc_html( $key ) . '="' . esc_attr( $value ) . '"'; } return $result; } /** * @param string $kind_slug * * @return string */ public static function get_package_element_type( $kind_slug ) { if ( is_object( $kind_slug ) ) { $kind_slug = $kind_slug->kind_slug; } if ( is_array( $kind_slug ) ) { $kind_slug = $kind_slug['kind_slug']; } return 'package_' . $kind_slug; } /** * @param array<string,string> $package * * @return bool */ public function package_has_kind( $package ) { return isset( $package['kind'] ) && $package['kind']; } /** * @param array<string,string> $package * * @return bool */ public function package_has_name( $package ) { return isset( $package['name'] ) && $package['name']; } /** * @param array<string,string> $package * * @return bool */ public function package_has_title( $package ) { return isset( $package['title'] ) && $package['title']; } /** * @param array<string,string> $package * * @return bool */ public function package_has_kind_and_name( $package ) { return $this->package_has_kind( $package ) && $this->package_has_name( $package ); } /** * @param string $string_name * * @return mixed */ public function sanitize_string_with_underscores( $string_name ) { return preg_replace( '/[ \[\]]+/', '_', $string_name ); } function new_external_item( $type, $package_item, $get_string_data = false ) { // create a new external item for the Translation Dashboard or for translation jobs $package_id = $package_item['ID']; $item = new stdClass(); $item->external_type = true; $item->type = $type; $item->ID = $package_id; $item->post_type = $type; $item->post_id = 'external_' . $item->post_type . '_' . $package_item['ID']; $item->post_date = ''; $item->post_status = __( 'Active', 'wpml-string-translation' ); $item->post_title = $package_item['title']; $item->is_translation = false; if ( $get_string_data ) { $item->string_data = $this->_get_package_strings( $package_item ); } return $item; } function get_package_from_external_id( $post_id ) { global $wpdb; $packages = $wpdb->get_col( "SELECT ID FROM {$wpdb->prefix}icl_string_packages WHERE ID>0" ); foreach ( $packages as $package_id ) { $package = new WPML_Package( $package_id ); $test = $this->get_external_id_from_package( $package ); if ( is_string( $post_id ) && $post_id == $test ) { return $package; } } return false; // not a package type } function _get_package_strings( $package_item ) { global $wpdb; $strings = array(); $package_item_id = $package_item['ID']; $results = $wpdb->get_results( $wpdb->prepare( "SELECT name, value FROM {$wpdb->prefix}icl_strings WHERE string_package_id=%d", $package_item_id ) ); foreach ( $results as $result ) { $string_name = (bool) $package_item_id === true && strpos( $result->name, (string) $package_item_id ) === 0 ? substr( $result->name, strlen( $package_item_id ) + 1 ) : $result->name; $strings[ $string_name ] = $result->value; } // Add/update any registered strings if ( isset( $this->registered_strings[ $package_item_id ]['strings'] ) ) { foreach ( $this->registered_strings[ $package_item_id ]['strings'] as $id => $string_data ) { $strings[ $id ] = $string_data['value']; } } return $strings; } function get_link( $item, $package_item, $anchor, $hide_empty ) { if ( $item == '' ) { $package_item = $this->get_package_from_external_id( $package_item ); if ( ! $package_item ) { return ''; } $has_link = isset( $package_item->edit_link ) && $package_item->edit_link; if ( false === $anchor ) { if ( $has_link ) { $anchor = '<a href="' . $package_item->edit_link . '">' . $package_item['title'] . '</a>'; } elseif ( ! $hide_empty ) { $anchor = $package_item['title']; } } else { if ( $has_link ) { $anchor = '<a href="' . $package_item['edit_link'] . '">' . $anchor . '</a>'; } } $item = $anchor; } return $item; } /** * Update translations * * @param int $package_id * @param bool $is_new - set to true for newly created form (first save without fields) * @param bool $needs_update - when deleting single field we do not need to change the translation status of the form * * @internal param array $item - package information */ function update_package_translations( $package_id, $is_new, $needs_update = true ) { global $sitepress, $wpdb, $iclTranslationManagement; $item = $this->get_package_details( $package_id ); $post_id = $this->get_external_id_from_package( new WPML_Package( $package_id ) ); /** @var WPML_Package $post */ $post = $this->get_translatable_item( null, $post_id ); if ( ! $post ) { return; } $default_lang = $sitepress->get_default_language(); $icl_el_type = $this->get_package_element_type( $item ); $trid = $sitepress->get_element_trid( $item['ID'], $icl_el_type ); if ( $is_new ) { $sitepress->set_element_language_details( $post->ID, $icl_el_type, false, $default_lang, null, false ); // for new package nothing more to do return; } $sql = " SELECT t.translation_id, s.md5 FROM {$wpdb->prefix}icl_translations t NATURAL JOIN {$wpdb->prefix}icl_translation_status s WHERE t.trid=%d AND t.source_language_code IS NOT NULL "; $element_translations = $wpdb->get_results( $wpdb->prepare( $sql, $trid ) ); if ( ! empty( $element_translations ) ) { $md5 = $iclTranslationManagement->post_md5( $post ); if ( $md5 != $element_translations[0]->md5 ) { // all translations need update $translation_package = $iclTranslationManagement->create_translation_package( $post ); foreach ( $element_translations as $trans ) { $_prevstate = $wpdb->get_row( $wpdb->prepare( " SELECT status, translator_id, needs_update, md5, translation_service, translation_package, timestamp, links_fixed FROM {$wpdb->prefix}icl_translation_status WHERE translation_id = %d ", $trans->translation_id ), ARRAY_A ); if ( ! empty( $_prevstate ) ) { $data['_prevstate'] = serialize( $_prevstate ); } $data = array( 'translation_id' => $trans->translation_id, 'translation_package' => serialize( $translation_package ), 'md5' => $md5, ); // update only when something changed (we do not need to change status when deleting a field) if ( $needs_update ) { $data['needs_update'] = 1; } $update_result = $iclTranslationManagement->update_translation_status( $data ); $rid = $update_result[0]; $this->update_icl_translate( $rid, $post ); // change job status only when needs update if ( $needs_update ) { $job_id = $wpdb->get_var( $wpdb->prepare( "SELECT MAX(job_id) FROM {$wpdb->prefix}icl_translate_job WHERE rid=%d GROUP BY rid", $rid ) ); if ( $job_id ) { $wpdb->update( "{$wpdb->prefix}icl_translate_job", array( 'translated' => 0 ), array( 'job_id' => $job_id ), array( '%d' ), array( '%d' ) ); } } } } } } /** * Functions to update translations when packages are modified in admin * * @param int $rid * @param \stdClass|WPML_Package $post */ function update_icl_translate( $rid, $post ) { global $wpdb; $job_id = $wpdb->get_var( $wpdb->prepare( "SELECT MAX(job_id) FROM {$wpdb->prefix}icl_translate_job WHERE rid=%d GROUP BY rid", $rid ) ); $elements = $wpdb->get_results( $wpdb->prepare( "SELECT field_type, field_data, tid, field_translate FROM {$wpdb->prefix}icl_translate WHERE job_id=%d", $job_id ), OBJECT_K ); foreach ( $post->string_data as $field_type => $field_value ) { $field_data = base64_encode( $field_value ); if ( ! isset( $elements[ $field_type ] ) ) { // insert new field $data = array( 'job_id' => $job_id, 'content_id' => 0, 'field_type' => $field_type, 'field_format' => 'base64', 'field_translate' => 1, 'field_data' => $field_data, 'field_data_translated' => 0, 'field_finished' => 0, ); $wpdb->insert( $wpdb->prefix . 'icl_translate', $data ); } elseif ( $elements[ $field_type ]->field_data != $field_data ) { // update field value $wpdb->update( $wpdb->prefix . 'icl_translate', array( 'field_data' => $field_data, 'field_finished' => 0, ), array( 'tid' => $elements[ $field_type ]->tid ) ); } } foreach ( $elements as $field_type => $el ) { // delete fields that are no longer present if ( $el->field_translate && ! isset( $post->string_data[ $field_type ] ) ) { $wpdb->delete( $wpdb->prefix . 'icl_translate', array( 'tid' => $el->tid ), array( '%d' ) ); } } } private function get_package_details( $package_id ) { global $wpdb; static $cache = array(); if ( ! isset( $cache[ $package_id ] ) ) { $item = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}icl_string_packages WHERE ID=%d", $package_id ), ARRAY_A ); $cache[ $package_id ] = $item; } return $cache[ $package_id ]; } function get_string_context_title( $context, $string_details ) { global $wpdb; static $cache = array(); if ( ! isset( $cache[ $context ] ) ) { $package_id = $wpdb->get_var( $wpdb->prepare( "SELECT string_package_id FROM {$wpdb->prefix}icl_strings WHERE id=%d", $string_details['string_id'] ) ); if ( $package_id ) { $package_details = $this->get_package_details( $package_id ); if ( $package_details ) { $cache[ $context ] = $package_details->kind . ' - ' . $package_details->title; } else { $cache[ $context ] = $context; } } else { $cache[ $context ] = $context; } } return $cache[ $context ]; } function get_string_title( $title, $string_details ) { global $wpdb; $string_title = $wpdb->get_var( $wpdb->prepare( "SELECT title FROM {$wpdb->prefix}icl_strings WHERE id=%d", $string_details['string_id'] ) ); if ( $string_title ) { return $string_title; } else { return $title; } } function _get_post_translations( $package ) { global $sitepress; if ( is_object( $package ) ) { $package = get_object_vars( $package ); } $element_type = $this->get_package_element_type( $package['kind_slug'] ); $trid = $sitepress->get_element_trid( $package['ID'], $element_type ); return $sitepress->get_element_translations( $trid, $element_type ); } function _is_translation_in_progress( $package ) { global $wpdb; $post_translations = self::_get_post_translations( $package ); foreach ( $post_translations as $lang => $translation ) { $res = $wpdb->get_row( $wpdb->prepare( "SELECT status, needs_update, md5 FROM {$wpdb->prefix}icl_translation_status WHERE translation_id=%d", $translation->translation_id ) ); if ( $res && $res->status == ICL_TM_IN_PROGRESS ) { return true; } } return false; } function _delete_translation_job( $package_id ) { global $wpdb; $package = $this->get_package_details( $package_id ); $post_translations = $this->_get_post_translations( $package ); foreach ( $post_translations as $lang => $translation ) { $rid = $wpdb->get_var( $wpdb->prepare( "SELECT rid FROM {$wpdb->prefix}icl_translation_status WHERE translation_id=%d", $translation->translation_id ) ); if ( $rid ) { $job_id = $wpdb->get_var( $wpdb->prepare( "SELECT job_id FROM {$wpdb->prefix}icl_translate_job WHERE rid=%d", $rid ) ); if ( $job_id ) { $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}icl_translate_job WHERE job_id=%d", $job_id ) ); $wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->prefix}icl_translate WHERE job_id=%d", $job_id ) ); } } } } public function add_to_basket( $data ) { if ( isset( $data['tr_action'] ) ) { $posts_ids = TranslationProxy_Basket::get_elements_ids( $data, 'package' ); foreach ( $posts_ids as $id ) { $post_id = $id; $source_language = $data['translate_from']; $target_languages = $data['tr_action']; foreach ( $target_languages as $translate_to => $translation_action ) { $package = new WPML_Package( $post_id ); $tm = new WPML_Package_TM( $package ); $tm->add_package_to_basket( $translation_action, $source_language, $translate_to ); } } } } function _no_wpml_warning() { ?> <div class="message error"> <p> <?php printf( __( 'WPML Package Translation is enabled but not effective. It requires <a href="%s">WPML</a>, String Translation and Translation Management in order to work.', 'wpml-string-translation' ), 'http://wpml.org/' ); ?> </p> </div> <?php } public function tm_dashboard_sql_filter( $sql ) { global $wpdb; $sql .= " AND i.element_id NOT IN ( SELECT ID FROM {$wpdb->prefix}icl_string_packages WHERE post_id IS NOT NULL AND element_type = 'package_layout' )"; return $sql; } /** * @return bool */ private function is_refresh_required() { $refresh_required = get_option( 'wpml-package-translation-refresh-required', 'yes' ); return 'yes' === $refresh_required || '1' === $refresh_required; } private function set_refresh_not_required() { update_option( 'wpml-package-translation-refresh-required', 'no', false ); } public function save_package_translations( $element_type_prefix, $job, $decoder ) { if ( $element_type_prefix === 'package' ) { $element_type_prefix = $this->get_package_type_prefix( $element_type_prefix, $job->original_doc_id ); $needs_process_translation_files = false; foreach ( $job->elements as $field ) { if ( $field->field_translate ) { $string_id = icl_st_is_registered_string( $element_type_prefix, $field->field_type ); if ( ! $string_id ) { icl_register_string( $element_type_prefix, $field->field_type, $decoder( $field->field_data, $field->field_format ) ); $string_id = icl_st_is_registered_string( $element_type_prefix, $field->field_type ); } if ( $string_id ) { $needs_process_translation_files = true; icl_add_string_translation( $string_id, $job->language_code, $decoder( $field->field_data_translated, $field->field_format ), ICL_TM_COMPLETE ); } } } if ( $needs_process_translation_files ) { do_action( 'wpml_st_translation_files_process_queue' ); } } } } inc/wpml-package-translation-tm-jobs.class.php 0000644 00000015476 14721633032 0015425 0 ustar 00 <?php class WPML_Package_TM_Jobs { /** * @var WPML_Package|null */ protected $package; protected function __construct( $package ) { $this->package = $package; } final public function validate_translations( $create_if_missing = true ) { $trid = $this->get_trid( $create_if_missing ); return $trid != false; } final protected function get_trid( $create_if_missing = true ) { global $sitepress; $package = $this->package; $post_trid = $sitepress->get_element_trid( $package->ID, $package->get_translation_element_type() ); if ( ! $post_trid && $create_if_missing ) { $this->set_language_details(); $post_trid = $sitepress->get_element_trid( $package->ID, $package->get_translation_element_type() ); } return $post_trid; } final public function set_language_details( $language_code = null ) { global $sitepress; $package = $this->package; $post_id = $package->ID; /** @var WPML_Package $post */ $post = $this->get_translatable_item( $post_id ); $post_id = $post->ID; $element_type = $package->get_translation_element_type(); if ( ! $language_code ) { $language_code = icl_get_default_language(); } $sitepress->set_element_language_details( $post_id, $element_type, false, $language_code, null, false ); } /** * @param int|WP_Post|WPML_Package $package * @return WPML_Package */ final public function get_translatable_item( $package ) { // for TranslationManagement::send_jobs if ( ! is_object( $package ) || ! is_a( $package, 'WPML_Package' ) ) { $package = new WPML_Package( $package ); } return $package; } final public function delete_translation_jobs() { global $wpdb; $post_translations = $this->get_post_translations(); foreach ( $post_translations as $lang => $translation ) { $rid_query = "SELECT rid FROM {$wpdb->prefix}icl_translation_status WHERE translation_id=%d"; $rid_prepare = $wpdb->prepare( $rid_query, array( $translation->translation_id ) ); $rid = $wpdb->get_var( $rid_prepare ); if ( $rid ) { $job_id_query = "SELECT job_id FROM {$wpdb->prefix}icl_translate_job WHERE rid=%d"; $job_id_prepare = $wpdb->prepare( $job_id_query, array( $rid ) ); $job_id = $wpdb->get_var( $job_id_prepare ); if ( $job_id ) { $wpdb->delete( $wpdb->prefix . 'icl_translate_job', array( 'job_id' => $job_id ) ); $wpdb->delete( $wpdb->prefix . 'icl_translate', array( 'job_id' => $job_id ) ); } } } } final public function delete_translations() { global $sitepress; $sitepress->delete_element_translation( $this->get_trid(), $this->package->get_translation_element_type() ); } final public function get_post_translations() { global $sitepress; $package = $this->package; $translation_element_type = $package->get_translation_element_type(); $trid = $this->get_trid(); return $sitepress->get_element_translations( $trid, $translation_element_type ); } final protected function update_translation_job_needs_update( $job_id ) { global $wpdb; $update_data = array( 'translated' => 0 ); $update_where = array( 'job_id' => $job_id ); $wpdb->update( "{$wpdb->prefix}icl_translate_job", $update_data, $update_where ); } final function update_translation_job( $rid, $post ) { $updated = $this->update_translation_job_fields( $rid, $post ); $deleted = $this->delete_translation_job_fields( $rid, $post ); return ( $updated || $deleted ); } private function delete_translation_job_fields( $rid, $post ) { $deleted = false; $job_id = $this->get_translation_job_id( $rid ); $translation_fields = $this->get_translations_job_fields( $job_id ); foreach ( $translation_fields as $field_type => $el ) { // delete fields that are no longer present if ( $el->field_translate && ! isset( $post->string_data[ $field_type ] ) ) { $this->delete_translation_field( $el->tid ); if ( ! $deleted ) { $deleted = true; } } } return $deleted; } /** * @param int $rid * @param WPML_Package $post * * @return bool */ private function update_translation_job_fields( $rid, $post ) { $updated_any = false; $job_id = $this->get_translation_job_id( $rid ); $translation_fields = $this->get_translations_job_fields( $job_id ); if ( isset( $post->string_data ) && is_array( $post->string_data ) ) { foreach ( $post->string_data as $field_type => $field_value ) { $updated = $this->insert_update_translation_job_field( $field_value, $translation_fields, $field_type, $job_id ); if ( ! $updated_any && $updated ) { $updated_any = true; } } } return $updated_any; } protected function get_translation_job_id( $rid ) { global $wpdb; $job_id_query = "SELECT MAX(job_id) FROM {$wpdb->prefix}icl_translate_job WHERE rid=%d GROUP BY rid"; $job_id_prepare = $wpdb->prepare( $job_id_query, $rid ); $job_id = $wpdb->get_var( $job_id_prepare ); return $job_id; } private function get_translations_job_fields( $job_id ) { global $wpdb; $translation_fields_query = "SELECT field_type, field_data, tid, field_translate FROM {$wpdb->prefix}icl_translate WHERE job_id=%d"; $translation_fields_query = $wpdb->prepare( $translation_fields_query, $job_id ); $translation_fields = $wpdb->get_results( $translation_fields_query, OBJECT_K ); return $translation_fields; } private function delete_translation_field( $tid ) { global $wpdb; $wpdb->delete( $wpdb->prefix . 'icl_translate', array( 'tid' => $tid ), array( '%d' ) ); } private function insert_update_translation_job_field( $field_value, $translation_fields, $field_type, $job_id ) { $updated = false; $field_data = base64_encode( $field_value ); if ( ! isset( $translation_fields[ $field_type ] ) ) { $this->insert_translation_field( $job_id, $field_type, $field_data ); $updated = true; } elseif ( $translation_fields[ $field_type ]->field_data != $field_data ) { $this->update_translation_field( $field_data, $translation_fields, $field_type ); $updated = true; } return $updated; } private function update_translation_field( $field_data, $translation_fields, $field_type ) { global $wpdb; $wpdb->update( $wpdb->prefix . 'icl_translate', array( 'field_data' => $field_data, 'field_finished' => 0, ), array( 'tid' => $translation_fields[ $field_type ]->tid ) ); } private function insert_translation_field( $job_id, $field_type, $field_data ) { global $wpdb; $data = array( 'job_id' => $job_id, 'content_id' => 0, 'field_type' => $field_type, 'field_format' => 'base64', 'field_translate' => 1, 'field_data' => $field_data, 'field_data_translated' => 0, 'field_finished' => 0, ); $wpdb->insert( $wpdb->prefix . 'icl_translate', $data ); } } inc/wpml-package-translation-metabox.class.php 0000644 00000034403 14721633032 0015500 0 ustar 00 <?php class WPML_Package_Translation_Metabox { private $args; private $active_languages; private $container_attributes_html; private $dashboard_link; private $strings_link; private $default_language; /** @var array<string, mixed> */ private $main_container_attributes; private $show_description; private $show_link; private $show_status; private $show_title; /** * @var array<string, mixed> */ private $status_container_attributes; private $status_container_attributes_html; private $status_container_tag; private $status_element_tag; private $title_tag; public $metabox_data; /** * @var SitePress */ private $sitepress; private $translation_statuses; /** * @var wpdb */ private $wpdb; /** * @var \WPML_Package */ private $package; /** * @var string */ private $package_language; /** * WPML_Package_Translation_Metabox constructor. * * @param stdClass|WPML_Package|array|int $package * @param \wpdb $wpdb * @param \SitePress $sitepress * @param array<string,mixed> $args */ public function __construct( $package, $wpdb, $sitepress, $args = array() ) { $this->wpdb = $wpdb; $this->sitepress = $sitepress; $this->package = new WPML_Package( $package ); $this->args = $args; if ( $this->got_package() ) { $this->dashboard_link = admin_url( 'admin.php?page=' . WPML_TM_FOLDER . '/menu/main.php&sm=dashboard&type=' . $this->package->kind_slug . '&lang=' . $this->package->get_package_language() ); $this->strings_link = admin_url( 'admin.php?page=' . WPML_ST_FOLDER . '/menu/string-translation.php&context=' . $this->package->get_string_context_from_package() ); } $this->parse_arguments( $args ); $this->init_metabox_data(); } private function init_metabox_data() { $this->metabox_data = array(); $this->active_languages = $this->sitepress->get_active_languages(); $this->default_language = $this->sitepress->get_default_language(); $this->package_language = $this->package->get_package_language(); $this->package_language = $this->package_language ? $this->package_language : $this->default_language; $this->metabox_data['title'] = __( 'WPML Translation', 'wpml-string-translation' ); if ( $this->is_package_language_active() ) { $this->metabox_data['translate_title'] = __( 'Send to translation', 'wpml-string-translation' ); } else { $this->metabox_data['translate_title'] = __( 'Translate strings', 'wpml-string-translation' ); } if ( $this->got_package() ) { $this->metabox_data['statuses_title'] = __( 'Translation status:', 'wpml-string-translation' ); $this->init_translation_statuses(); $this->metabox_data['package_language_title'] = sprintf( __( 'Language of this %1$s is %2$s', 'wpml-string-translation' ), $this->package->kind, $this->get_lang_selector() ); } else { $this->metabox_data['package_language_title'] = ''; $this->metabox_data['statuses_title'] = __( 'There is nothing to translate.', 'wpml-string-translation' ); } } private function get_lang_selector() { $disable = $this->check_if_language_change_is_ok() ? '' : 'disabled="disabled" '; ob_start(); $languages = $this->active_languages; if ( ! $this->is_package_language_active() ) { $languages = array_merge( array( $this->sitepress->get_language_details( $this->package_language ) ), $languages ); } else { $languages = $this->active_languages; } $selector = new WPML_Simple_Language_Selector( $this->sitepress ); $selector->render( array( 'id' => 'icl_package_language', 'name' => 'icl_package_language', 'show_please_select' => false, 'languages' => $languages, 'selected' => $this->package_language, 'disabled' => ! $this->check_if_language_change_is_ok(), 'echo' => true, ) ); ?> <span class="spinner"></span> <?php return ob_get_clean(); } public function get_package_language_name() { if ( $this->is_package_language_active() ) { return $this->active_languages[ $this->package_language ]['display_name']; } else { $all_languages = $this->sitepress->get_languages(); return $all_languages[ $this->package_language ]['display_name']; } } private function get_lang_switcher_js() { ob_start(); ?> <script type="text/javascript"> var WPML_Package_Translation = WPML_Package_Translation || {}; WPML_Package_Translation.MetaBox = function () { var self = this; self.init = function () { jQuery('#icl_package_language').off('change'); jQuery('#icl_package_language').on('change', self.switch_lang); }; self.switch_lang = function() { self.disable_controls(true); var data = { action: 'wpml_change_package_lang', wpnonce: jQuery('#wpml_package_nonce').val(), package_id: jQuery('#wpml_package_id').val(), args: jQuery('#wpml_package_args').val(), package_lang: jQuery(this).val() }; jQuery.ajax( { url: ajaxurl, type: 'post', data: data, dataType: 'json', success: function (response) { var position = jQuery('#wpml_package_status').prev(); jQuery('#wpml_package_status').remove(); jQuery(response.metabox).insertAfter(position); jQuery('#icl_package_language').trigger('wpml-package-language-changed', [response.lang]); self.disable_controls(false); } }); }; self.disable_controls = function(state) { var lang_switcher = jQuery('#icl_package_language'); if (state) { lang_switcher.next('.spinner').show(); lang_switcher.prop('disabled', true); lang_switcher.closest('div').find('a').prop('disabled', true); } else { lang_switcher.next('.spinner').hide(); lang_switcher.prop('disabled', false); lang_switcher.closest('div').find('a').prop('disabled', false); } }; self.init(); }; jQuery(document).ready( function () { WPML_Package_Translation.meta_box = new WPML_Package_Translation.MetaBox(); } ); </script> <?php return ob_get_clean(); } function get_metabox() { $result = ''; $result .= '<div ' . $this->container_attributes_html . '>'; if ( $this->show_title ) { if ( $this->title_tag ) { $result .= $this->get_tag( $this->title_tag ); } $result .= $this->metabox_data['title']; if ( $this->title_tag ) { $result .= $this->get_tag( $this->title_tag, 'closed' ); } } if ( $this->show_description ) { $result .= '<div>' . $this->metabox_data['package_language_title'] . '</div>'; } if ( $this->show_status ) { $result .= '<p>' . $this->metabox_data['statuses_title'] . '</p>'; } $result .= $this->get_metabox_status(); $json_args = wp_json_encode( $this->args ) ? wp_json_encode( $this->args ) : ''; $result .= '</div>'; $result .= wp_nonce_field( 'wpml_package_nonce', 'wpml_package_nonce', true, false ); $result .= '<input type="hidden" id="wpml_package_id" value="' . $this->package->ID . '" />'; $result .= '<input type="hidden" id="wpml_package_args" value="' . base64_encode( $json_args ) . '" />'; if ( ! defined( 'DOING_AJAX' ) ) { $result .= $this->get_lang_switcher_js(); } return $result; } public function get_metabox_status() { $result = ''; if ( $this->got_package() ) { $result .= '<div id="wpml_package_status">'; if ( $this->show_status && $this->metabox_data['statuses'] ) { if ( $this->status_container_tag ) { $result .= $this->get_tag( $this->status_container_tag . ' ' . $this->status_container_attributes_html ); } foreach ( $this->metabox_data['statuses'] as $code => $status ) { $result .= $this->get_tag( $this->status_element_tag ); $result .= '<img width="18" height="12" src="' . $this->sitepress->get_flag_url( $code ) . '"> ' . $status['name'] . ' : ' . $status['status']; $result .= $this->get_tag( $this->status_element_tag, 'closed' ); } if ( $this->status_container_tag ) { $result .= $this->get_tag( $this->status_container_tag, 'closed' ); } } if ( $this->show_link ) { if ( $this->is_package_language_active() ) { $result .= '<p><a style="float:right" class="button-secondary" href="' . $this->dashboard_link . '" target="_blank">' . $this->metabox_data['translate_title'] . '</a></p>'; } else { $result .= '<p><a style="float:right" class="button-secondary" href="' . $this->strings_link . '" target="_blank">' . $this->metabox_data['translate_title'] . '</a></p>'; } } $result .= '<br /><br /></div>'; } return $result; } private function check_if_language_change_is_ok() { $ok = true; foreach ( $this->translation_statuses as $status ) { if ( isset( $status->status_code ) && $status->status_code != 0 ) { $ok = false; break; } } if ( $ok ) { $translations = $this->package->get_translated_strings( array() ); foreach ( $translations as $string ) { foreach ( $string as $lang => $data ) { if ( $data['status'] == ICL_STRING_TRANSLATION_COMPLETE ) { $ok = false; break; } } if ( ! $ok ) { break; } } } return $ok; } /** * @param array<string,mixed> $attributes * * @return string */ private function attributes_to_string( $attributes ) { $result = ''; foreach ( $attributes as $key => $value ) { if ( $result ) { $result .= ' '; } $result .= esc_html( $key ) . '="' . esc_attr( $value ) . '"'; } return $result; } function get_post_translations() { $element_type = $this->package->get_package_element_type(); $trid = $this->sitepress->get_element_trid( $this->package->ID, $element_type ); return $this->sitepress->get_element_translations( $trid, $element_type ); } private function get_tag( $tag, $closed = false ) { $result = '<'; if ( $closed ) { $result .= '/'; } $result .= $tag . '>'; return $result; } /** * @param array<string,string|array<string,mixed> > $args */ private function parse_arguments( $args ) { $default_args = array( 'show_title' => true, 'show_description' => true, 'show_status' => true, 'show_link' => true, 'title_tag' => 'h2', 'status_container_tag' => 'ul', 'status_element_tag' => 'li', 'main_container_attributes' => array(), 'status_container_attributes' => array( 'style' => 'padding-left: 10px' ), ); $args = array_merge( $default_args, $args ); $this->show_title = $args['show_title']; $this->show_description = $args['show_description']; $this->show_status = $args['show_status']; $this->show_link = $args['show_link']; $this->title_tag = $args['title_tag']; $this->status_container_tag = $args['status_container_tag']; $this->status_element_tag = $args['status_element_tag']; /** @var array<string, mixed> $main_container_attributes */ $main_container_attributes = $args['main_container_attributes']; $this->main_container_attributes = $main_container_attributes; /** @var array<string, mixed> $status_container_attributes */ $status_container_attributes = $args['status_container_attributes']; $this->status_container_attributes = $status_container_attributes; $this->container_attributes_html = $this->attributes_to_string( $this->main_container_attributes ); $this->status_container_attributes_html = $this->attributes_to_string( $this->status_container_attributes ); } /** * @return bool */ private function got_package() { return $this->package && $this->package->ID; } private function get_translation_statuses() { $post_translations = $this->get_post_translations(); $status = array(); foreach ( $post_translations as $language => $translation ) { $res_query = "SELECT status as status_code, needs_update FROM {$this->wpdb->prefix}icl_translation_status WHERE translation_id=%d"; $res_args = array( $translation->translation_id ); /** @var string $res_prepare */ $res_prepare = $this->wpdb->prepare( $res_query, $res_args ); /** @var \stdClass $res */ $res = $this->wpdb->get_row( $res_prepare ); if ( $res ) { $res->status = $res->status_code; switch ( $res->status ) { case ICL_TM_WAITING_FOR_TRANSLATOR: $res->status = __( 'Waiting for translator', 'wpml-string-translation' ); break; case ICL_TM_IN_PROGRESS: $res->status = __( 'In progress', 'wpml-string-translation' ); break; case ICL_TM_NEEDS_UPDATE: $res->status = ''; break; case ICL_TM_COMPLETE: $res->status = __( 'Complete', 'wpml-string-translation' ); break; default: $res->status = __( 'Not translated', 'wpml-string-translation' ); break; } if ( $res->needs_update ) { if ( $res->status ) { $res->status .= ' - '; } $res->status .= __( 'Needs update', 'wpml-string-translation' ); } $status[ $language ] = $res; } } return $status; } private function init_translation_statuses() { $this->metabox_data['statuses'] = array(); $this->translation_statuses = $this->get_translation_statuses(); foreach ( $this->active_languages as $language_data ) { if ( $language_data['code'] != $this->package_language ) { $display_name = $language_data['display_name']; $this->metabox_data['statuses'][ $language_data['code'] ] = array( 'name' => $display_name, 'status' => $this->get_status_value( $language_data ), ); } } } private function get_status_value( $language_data ) { if ( isset( $this->translation_statuses[ $language_data['code'] ] ) ) { $status_value = $this->translation_statuses[ $language_data['code'] ]->status; } else { $tm = new WPML_Package_TM( $this->package ); if ( $tm->is_in_basket( $language_data['code'] ) ) { $status_value = __( 'In translation basket', 'wpml-string-translation' ); } else { $status_value = __( 'Not translated', 'wpml-string-translation' ); } } return $status_value; } private function is_package_language_active() { return in_array( $this->package_language, array_keys( $this->active_languages ) ); } } inc/wpml-package-factory.class.php 0000644 00000001765 14721633032 0013161 0 ustar 00 <?php class WPML_ST_Package_Factory { /** @var WPML_WP_Cache_Factory $cache_factory */ private $cache_factory; public function __construct( WPML_WP_Cache_Factory $cache_factory = null ) { $this->cache_factory = $cache_factory; wp_cache_add_non_persistent_groups( __CLASS__ ); } /** * @param \stdClass|\WPML_Package|array|int $package_data * * @return WPML_Package */ public function create( $package_data ) { $cache_item = $this->get_cache_item( $package_data ); if ( ! $cache_item->exists() ) { $cache_item->set( new WPML_Package( $package_data ) ); } return $cache_item->get(); } /** * @param array|int|stdClass|WPML_Package $package_data * * @return WPML_WP_Cache_Item */ private function get_cache_item( $package_data ) { if ( ! $this->cache_factory ) { $this->cache_factory = new WPML_WP_Cache_Factory(); } $package_key = md5( (string) json_encode( $package_data ) ); return $this->cache_factory->create_cache_item( __CLASS__, $package_key ); } } inc/wpml-package-translation-html-packages.class.php 0000644 00000013576 14721633032 0016571 0 ustar 00 <?php class WPML_Package_Translation_HTML_Packages { var $load_priority = 101; public function __construct() { add_action( 'WPML_PT_HTML', array( $this, 'loaded' ), $this->load_priority ); } public function loaded() { $this->set_admin_hooks(); } private function set_admin_hooks() { if ( is_admin() ) { add_action( 'wpml_pt_package_table_columns', array( $this, 'render_package_table_columns' ), 10, 1 ); add_action( 'wpml_pt_package_table_options', array( $this, 'package_translation_menu_options' ), 10, 1 ); add_action( 'wpml_pt_package_table_body', array( $this, 'package_translation_menu_body' ), 10, 1 ); add_action( 'wpml_pt_package_status', array( $this, 'render_string_package_status' ), 10, 3 ); } } public static function package_translation_menu() { $packages = apply_filters( 'wpml_pt_all_packages', array() ); $package_kinds = array(); if ( $packages ) { foreach ( $packages as $package ) { $kind_slugs = array_keys( $package_kinds ); if ( ! in_array( $package->kind_slug, $kind_slugs ) ) { $package_kinds[ $package->kind_slug ] = $package->kind; } } } $table_title = __( 'Package Management', 'wpml-string-translation' ); $package_kind_label = __( 'Display packages for this kind:', 'wpml-string-translation' ); $package_kind_options[- 1] = __( 'Display packages for this kind:', 'wpml-string-translation' ); foreach ( $package_kinds as $kind_slug => $kind ) { $package_kind_options[ $kind_slug ] = $kind; } ?> <h2><?php echo $table_title; ?></h2> <p> <label for="package_kind_filter"><?php echo $package_kind_label; ?></label> <select id="package_kind_filter"> <?php do_action( 'wpml_pt_package_table_options', $package_kind_options ); ?> </select> </p> <table id="icl_package_translations" class="widefat" cellspacing="0"> <thead> <?php do_action( 'wpml_pt_package_table_columns', 'thead' ); ?> </thead> <tfoot> <?php do_action( 'wpml_pt_package_table_columns', 'tfoot' ); ?> </tfoot> <tbody> <?php do_action( 'wpml_pt_package_table_body', $packages ); ?> </tbody> </table> <br/> <input id="delete_packages" type="button" class="button-primary" value="<?php echo __( 'Delete Selected Packages', 'wpml-string-translation' ); ?>" disabled="disabled"/> <span class="spinner"></span> <span style="display:none" class="js-delete-confirm-message"><?php echo __( "Are you sure you want to delete these packages?\nTheir strings and translations will be deleted too.", 'wpml-string-translation' ); ?></span> <?php wp_nonce_field( 'wpml_package_nonce', 'wpml_package_nonce' ); } public function package_translation_menu_options( $package_kind_options ) { foreach ( $package_kind_options as $option_value => $option_label ) { ?> <option value="<?php echo esc_attr( $option_value ); ?>"><?php echo $option_label; ?></option> <?php } } /** * @param array<\WPML_Package> $packages */ public function package_translation_menu_body( $packages ) { if ( ! $packages ) { $this->package_translation_menu_no_packages(); } else { $this->package_translation_menu_items( $packages ); } } public function render_package_table_columns( $position ) { ?> <tr> <th scope="col" class="manage-column column-cb check-column"> <label for="select_all_package_<?php echo $position; ?>" style="display: none;"> <?php _e( 'Select All', 'wpml-string-translation' ); ?> </label> <input id="select_all_package_<?php echo $position; ?>" class="js_package_all_cb" type="checkbox"/> </th> <th scope="col"><?php echo __( 'Kind', 'wpml-string-translation' ); ?></th> <th scope="col"><?php echo __( 'Name', 'wpml-string-translation' ); ?></th> <th scope="col"><?php echo __( 'Info', 'wpml-string-translation' ); ?></th> </tr> <?php } public function render_string_package_status( $string_count, $translation_in_progress, $default_package_language ) { $package_statuses[] = sprintf( __( 'Contains %s strings', 'wpml-string-translation' ), $string_count ); if ( $translation_in_progress ) { $package_statuses[] = '(' . __( 'Translation is in progress', 'wpml-string-translation' ) . ')'; } $package_statuses[] = __( 'Default package language', 'wpml-string-translation' ) . ': ' . $default_package_language; echo implode( ' - ', $package_statuses ); } private function package_translation_menu_no_packages() { ?> <tr> <td colspan="6" align="center"> <strong><?php echo __( 'No packages found', 'wpml-string-translation' ); ?></strong> </td> </tr> <?php } /** * @param array<\WPML_Package> $packages */ private function package_translation_menu_items( $packages ) { global $wpdb, $sitepress; foreach ( $packages as $package ) { $package_language_code = $package->get_package_language(); $package_language = $sitepress->get_display_language_name( $package_language_code ); $tm = new WPML_Package_TM( $package ); $translation_in_progress = $tm->is_translation_in_progress(); $package_id = $package->ID; $string_count = $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$wpdb->prefix}icl_strings WHERE string_package_id=%d", $package_id ) ); $disabled = disabled( $translation_in_progress, true, false ); ?> <tr id="row_<?php echo $package_id; ?>" class="js_package js_package_<?php echo esc_attr( $package->kind_slug ); ?>"> <td> <input id="package_<?php echo $package_id; ?>" class="js_package_row_cb" type="checkbox" value="<?php echo $package_id; ?>" <?php echo $disabled; ?>/> </td> <td class="js-package-kind"> <?php echo $package->kind; ?> </td> <td> <label for="package_<?php echo $package_id; ?>"><?php echo esc_html( $package->title ); ?></label> </td> <td> <?php do_action( 'wpml_pt_package_status', $string_count, $translation_in_progress, $package_language ); ?> </td> </tr> <?php } } } inc/wpml-package.class.php 0000644 00000033517 14721633032 0011514 0 ustar 00 <?php #[\AllowDynamicProperties] class WPML_Package { const CACHE_GROUP = 'WPML_Package'; public $ID; public $view_link; public $edit_link; public $is_translation; public $string_data; public $title; public $new_title; public $kind_slug; public $kind; public $trid; public $name; public $translation_element_type; public $post_id; private $element_type_prefix; /** * This gives a context to determine what's really * required to load. When set to `true`, we skip * some useless DB queries in the constructor. * * @var bool */ private $translate_only = false; /** * @param stdClass|WPML_Package|array|int|WP_Post $data_item */ function __construct( $data_item ) { $this->element_type_prefix = 'package'; $this->view_link = ''; $this->edit_link = ''; $this->post_id = null; if ( $data_item ) { if ( is_object( $data_item ) ) { $data_item = get_object_vars( $data_item ); } if ( is_numeric( $data_item ) ) { $data_item = $this->init_from_id( $data_item, ARRAY_A ); } if ( isset( $data_item['title'] ) ) { $this->new_title = $data_item['title']; } if ( $data_item && is_array( $data_item ) ) { $this->init_from_array( $data_item ); } $this->new_title = $this->new_title != $this->title ? $this->new_title : null; } } private function init_from_id( $id, $output = OBJECT ) { global $wpdb; $packages_query = "SELECT * FROM {$wpdb->prefix}icl_string_packages WHERE id=%s"; $packages_prepared = $wpdb->prepare( $packages_query, $id ); $package = $wpdb->get_row( $packages_prepared, $output ); return $package; } public function __get( $property ) { if ( $property == 'id' ) { _deprecated_argument( 'id', '0.0.2', "Property 'id' is deprecated. Please use 'ID'." ); return $this->ID; } if ( $property == 'post_id' ) { return $this->ID; } if ( $property == 'post_title' ) { return $this->title; } if ( $property == 'post_type' ) { return $this->kind_slug; } return null; } public function __set( $property, $value ) { if ( $property == 'id' ) { _deprecated_argument( 'id', '0.0.2', "Property 'id' is deprecated. Please use 'ID'." ); $this->ID = $value; } else { $this->$property = $value; } } public function __isset( $property ) { if ( $property == 'id' ) { return isset( $this->ID ); } return false; } public function __unset( $property ) { if ( $property == 'id' ) { unset( $this->$property ); } } public function get_translation_element_type() { return $this->translation_element_type; } public function get_package_post_id() { return $this->get_element_type_prefix() . '_' . $this->kind_slug . '_' . $this->ID; } public function get_element_type_prefix() { return $this->element_type_prefix; } public function set_package_post_data() { $this->translation_element_type = $this->element_type_prefix . '_' . $this->kind_slug; $this->update_strings_data(); } public function update_strings_data() { $strings = []; $package_id = $this->ID; if ( $package_id ) { $results = $this->get_package_strings(); foreach ( $results as $result ) { $string_name = $this->get_package_string_name_from_st_name( $result ); $strings[ $string_name ] = $result->value; } $this->string_data = $strings; } } /** * @param bool $refresh * * @return mixed */ public function get_package_strings( $refresh = false ) { global $wpdb; $package_id = $this->ID; $results = false; if ( $package_id ) { $cache = new WPML_WP_Cache( self::CACHE_GROUP ); $cache_key = 'strings:' . $package_id; $found = false; $results = $cache->get( $cache_key, $found ); if ( ! $found || $refresh ) { $results_query = " SELECT id, name, value, wrap_tag, type, title FROM {$wpdb->prefix}icl_strings WHERE string_package_id=%d ORDER BY location, id ASC"; $results_prepare = $wpdb->prepare( $results_query, $package_id ); $results = $wpdb->get_results( $results_prepare ); $cache->set( $cache_key, $results ); } } return $results; } public function set_strings_language( $language_code ) { global $wpdb; $package_id = $this->ID; if ( $package_id ) { $update_query = "UPDATE {$wpdb->prefix}icl_strings SET language=%s WHERE string_package_id=%d"; $update_prepare = $wpdb->prepare( $update_query, $language_code, $package_id ); $wpdb->query( $update_prepare ); // Action called after string is updated. do_action( 'wpml_st_string_updated' ); } } /** * @param \stdClass $result * * @return string */ private function get_package_string_name_from_st_name( $result ) { // package string name is the same as the string name. return $result->name; } private function sanitize_attributes() { if ( isset( $this->name ) ) { $this->name = $this->sanitize_string_name( $this->name ); } if ( ( ! isset( $this->title ) || $this->title === '' ) && isset( $this->name ) ) { $this->title = $this->name; } if ( ! isset( $this->edit_link ) ) { $this->edit_link = ''; } $this->sanitize_kind(); } public function create_new_package_record() { $this->sanitize_attributes(); $package_id = $this->package_exists(); if ( ! $package_id ) { global $wpdb; $data = array( 'kind_slug' => $this->kind_slug, 'kind' => $this->kind, 'name' => $this->name, 'title' => $this->title, 'edit_link' => $this->edit_link, 'view_link' => $this->view_link, 'post_id' => $this->post_id, ); $wpdb->insert( $wpdb->prefix . 'icl_string_packages', $data ); $package_id = $wpdb->insert_id; $this->ID = $package_id; } return $package_id; } public function update_package_record() { $result = false; if ( $this->ID ) { global $wpdb; $update_data = array( 'kind_slug' => $this->kind_slug, 'kind' => $this->kind, 'name' => $this->name, 'title' => $this->title, 'edit_link' => $this->edit_link, 'view_link' => $this->view_link, ); $update_where = array( 'ID' => $this->ID, ); $result = $wpdb->update( $wpdb->prefix . 'icl_string_packages', $update_data, $update_where ); } return $result; } public function get_package_id() { return $this->ID; } public function sanitize_string_name( $string_name ) { $string_name = preg_replace( '/[ \[\]]+/', '-', $string_name ); return $string_name; } /** * @param string $string_value * @param string $sanitized_string_name * * @return string|mixed */ function translate_string( $string_value, $sanitized_string_name ) { if ( $this->translate_only || $this->get_package_id() ) { $sanitized_string_name = $this->sanitize_string_name( $sanitized_string_name ); $string_context = $this->get_string_context_from_package(); $string_name = $sanitized_string_name; return icl_translate( $string_context, $string_name, $string_value ); } else { return $string_value; } } function get_string_context_from_package() { return $this->kind_slug . '-' . $this->name; } public function get_string_id_from_package( $string_name, $string_value ) { $package_id = $this->get_package_id(); $string_context = $this->get_string_context_from_package(); $string_data = array( 'context' => $string_context, 'name' => $string_name, ); /** * @param int|null $default * @param array $string_data { * * @type string $context * @type string $name Optional * } */ $string_id = apply_filters( 'wpml_string_id', null, $string_data ); if ( ! $string_id ) { $string_id = icl_register_string( $string_context, $string_name, $string_value, false, $this->get_package_language() ); } return $string_id; } function get_translated_strings( $strings ) { $package_id = $this->get_package_id(); if ( $package_id ) { $results = $this->get_package_strings(); foreach ( $results as $result ) { $translations = icl_get_string_translations_by_id( $result->id ); if ( ! empty( $translations ) ) { $string_name = $this->get_package_string_name_from_st_name( $result ); $strings[ $string_name ] = $translations; } } } return $strings; } function set_translated_strings( $translations ) { global $wpdb; $this->sanitize_attributes(); $package_id = $this->get_package_id(); if ( $package_id ) { foreach ( $translations as $string_name => $languages ) { $string_id_query = "SELECT id FROM {$wpdb->prefix}icl_strings WHERE name='%s'"; $string_id_prepare = $wpdb->prepare( $string_id_query, $string_name ); $string_id = $wpdb->get_var( $string_id_prepare ); foreach ( $languages as $language_code => $language_data ) { icl_add_string_translation( $string_id, $language_code, $language_data['value'], $language_data['status'] ); } } } } private function init_from_array( $args ) { foreach ( $args as $key => $value ) { if ( 'id' == $key ) { $key = 'ID'; } $this->$key = $value; } $this->sanitize_attributes(); if ( $this->translate_only ) { return; } if ( $this->package_id_exists() || $this->package_name_and_kind_exists() ) { $this->set_package_from_db(); } $this->set_package_post_data(); } public function has_kind_and_name() { return ( isset( $this->kind ) && isset( $this->name ) && $this->kind && $this->name ); } private function set_package_from_db() { $package = false; if ( $this->package_id_exists() ) { $package = $this->get_package_from_id(); } elseif ( $this->package_name_and_kind_exists() ) { $package = $this->get_package_from_name_and_kind(); } if ( $package ) { $this->object_to_package( $package ); } $this->sanitize_kind(); } private function get_package_from_id() { $result = false; if ( $this->has_id() ) { global $wpdb; $package_query = "SELECT * FROM {$wpdb->prefix}icl_string_packages WHERE ID=%d"; $package_prepared = $wpdb->prepare( $package_query, array( $this->ID ) ); $result = $wpdb->get_row( $package_prepared ); } return $result; } private function get_package_from_name_and_kind() { global $wpdb; $cache = new WPML_WP_Cache( self::CACHE_GROUP ); $cache_key = 'name-kind:' . $this->kind_slug . $this->name; $found = false; $result = $cache->get( $cache_key, $found ); if ( ! $found ) { $package_query = "SELECT * FROM {$wpdb->prefix}icl_string_packages WHERE kind_slug=%s AND name=%s"; $package_prepared = $wpdb->prepare( $package_query, array( $this->kind_slug, $this->name ) ); $result = $wpdb->get_row( $package_prepared ); if ( $result ) { $cache->set( $cache_key, $result ); } } return $result; } private function package_name_and_kind_exists() { $result = false; if ( $this->has_kind_and_name() ) { $result = (bool) $this->get_package_from_name_and_kind(); } return $result; } private function package_id_exists() { $result = false; if ( $this->has_id() ) { global $wpdb; $package_query = "SELECT ID FROM {$wpdb->prefix}icl_string_packages WHERE ID=%d"; $package_prepared = $wpdb->prepare( $package_query, array( $this->ID ) ); $result = $wpdb->get_var( $package_prepared ); } return $result; } /** * @return bool|mixed */ protected function package_exists() { $existing_package = false; if ( $this->has_id() ) { $existing_package = $this->package_id_exists(); } elseif ( $this->has_kind_and_name() ) { $existing_package = $this->package_name_and_kind_exists(); } return $existing_package; } /** * @return bool */ private function has_id() { return isset( $this->ID ) && $this->ID; } /** * @param \stdClass $package */ private function object_to_package( $package ) { $this->ID = $package->ID; $this->kind_slug = $package->kind_slug; $this->kind = $package->kind; $this->name = $package->name; $this->title = $package->title; $this->edit_link = $package->edit_link; $this->view_link = $package->view_link; } private function get_kind_from_slug() { global $wpdb; if ( $this->kind_slug ) { $kinds_query = "SELECT kind FROM {$wpdb->prefix}icl_string_packages WHERE kind_slug=%s GROUP BY kind"; $kinds_prepared = $wpdb->prepare( $kinds_query, $this->kind_slug ); $kinds = $wpdb->get_col( $kinds_prepared ); if ( count( $kinds ) > 1 ) { throw new WPML_Package_Exception( 'error', 'Package contains multiple kinds' ); } if ( $kinds ) { return $kinds[0]; } } return null; } private function sanitize_kind() { if ( isset( $this->kind ) && ( ! isset( $this->kind_slug ) || trim( $this->kind_slug ) === '' ) ) { $this->kind_slug = sanitize_title_with_dashes( $this->kind ); } if ( $this->kind == $this->kind_slug ) { $this->kind = $this->get_kind_from_slug(); } } public function get_package_element_type() { return 'package_' . $this->kind_slug; } /** * @return string|null */ public function get_package_language() { global $sitepress; if ( $this->post_id ) { $details = null; $post = get_post( $this->post_id ); if ( $post ) { $details = $sitepress->get_element_language_details( $this->post_id, 'post_' . $post->post_type ); } } else { $element_type = $this->get_package_element_type(); $details = $sitepress->get_element_language_details( $this->ID, $element_type ); } if ( $details ) { return $details->language_code; } else { return null; } } public function are_all_strings_included( $strings ) { // check to see if all the strings in this package are present in $strings $package_strings = $this->get_package_strings(); if ( is_array( $package_strings ) ) { foreach ( $package_strings as $string ) { if ( ! in_array( $string->id, $strings ) ) { return false; } } } return true; } public function flush_cache() { $cache = new WPML_WP_Cache( self::CACHE_GROUP ); $cache->flush_group_cache(); } } inc/wpml-package-translation-schema.class.php 0000644 00000014061 14721633032 0015277 0 ustar 00 <?php class WPML_Package_Translation_Schema { const OPTION_NAME = 'wpml-package-translation-db-updates-run'; const REQUIRED_VERSION = '0.0.2'; private static $table_name; static function run_update() { $updates_run = get_option( self::OPTION_NAME, array() ); if ( defined( 'WPML_PT_VERSION_DEV' ) ) { delete_option( 'wpml-package-translation-string-packages-table-updated' ); if ( ( $key = array_search( WPML_PT_VERSION_DEV, $updates_run ) ) !== false ) { unset( $updates_run[ $key ] ); } } if ( ! in_array( self::REQUIRED_VERSION, $updates_run ) ) { // We need to make sure we build everything for 0.0.2 because users may // only be updating the string translation plugin and may not do an // activation. self::build_icl_string_packages_table(); self::build_icl_string_packages_columns_if_required(); self::fix_icl_string_packages_ID_column(); self::build_icl_strings_columns_if_required(); $updates_run[] = self::REQUIRED_VERSION; update_option( self::OPTION_NAME, $updates_run ); } } private static function current_table_has_column( $column ) { global $wpdb; $cols = $wpdb->get_results( 'SHOW COLUMNS FROM `' . self::$table_name . '`' ); $found = false; foreach ( $cols as $col ) { if ( $col->Field == $column ) { $found = true; break; } } return $found; } private static function add_string_package_id_to_icl_strings() { global $wpdb; $sql = 'ALTER TABLE `' . self::$table_name . '` ADD `string_package_id` BIGINT unsigned NULL AFTER value, ADD INDEX (`string_package_id`)'; $result = $wpdb->query( $sql ); // Action called after string_package_id column is added to icl_strings tale do_action( 'wpml_st_strings_table_altered' ); return $result; } private static function add_type_to_icl_strings() { global $wpdb; $sql = 'ALTER TABLE `' . self::$table_name . "` ADD `type` VARCHAR(40) NOT NULL DEFAULT 'LINE' AFTER string_package_id"; $result = $wpdb->query( $sql ); // Action called after type column is added to icl_strings tale do_action( 'wpml_st_strings_table_altered' ); return $result; } private static function add_title_to_icl_strings() { global $wpdb; $sql = 'ALTER TABLE `' . self::$table_name . '` ADD `title` VARCHAR(160) NULL AFTER type'; $result = $wpdb->query( $sql ); // Action called after title column is added to icl_strings tale do_action( 'wpml_st_strings_table_altered' ); return $result; } public static function build_icl_strings_columns_if_required() { global $wpdb; if ( ! get_option( 'wpml-package-translation-string-table-updated' ) ) { self::$table_name = $wpdb->prefix . 'icl_strings'; if ( $wpdb->get_var( "SHOW TABLES LIKE '" . self::$table_name . "'" ) == self::$table_name ) { if ( ! self::current_table_has_column( 'string_package_id' ) ) { self::add_string_package_id_to_icl_strings(); } if ( ! self::current_table_has_column( 'type' ) ) { self::add_type_to_icl_strings(); } if ( ! self::current_table_has_column( 'title' ) ) { self::add_title_to_icl_strings(); } update_option( 'wpml-package-translation-string-table-updated', true, 'no' ); } } } private static function build_icl_string_packages_columns_if_required() { global $wpdb; if ( get_option( 'wpml-package-translation-string-packages-table-updated' ) != '0.0.2' ) { self::$table_name = $wpdb->prefix . 'icl_string_packages'; if ( $wpdb->get_var( "SHOW TABLES LIKE '" . self::$table_name . "'" ) == self::$table_name ) { if ( ! self::current_table_has_column( 'kind_slug' ) ) { self::add_kind_slug_to_icl_string_packages(); } self::update_kind_slug(); if ( ! self::current_table_has_column( 'view_link' ) ) { self::add_view_link_to_icl_string_packages(); } update_option( 'wpml-package-translation-string-packages-table-updated', '0.0.2', 'no' ); } } } private static function add_kind_slug_to_icl_string_packages() { global $wpdb; $sql = 'ALTER TABLE `' . self::$table_name . "` ADD `kind_slug` varchar(160) DEFAULT '' NOT NULL AFTER `ID`"; $result = $wpdb->query( $sql ); return $result; } private static function add_view_link_to_icl_string_packages() { global $wpdb; $sql = 'ALTER TABLE `' . self::$table_name . '` ADD `view_link` TEXT NOT NULL AFTER `edit_link`'; return $wpdb->query( $sql ); } private static function fix_icl_string_packages_ID_column() { global $wpdb; self::$table_name = $wpdb->prefix . 'icl_string_packages'; if ( self::current_table_has_column( 'id' ) ) { $sql = 'ALTER TABLE `' . self::$table_name . '` CHANGE id ID BIGINT UNSIGNED NOT NULL auto_increment;'; $wpdb->query( $sql ); } } private static function build_icl_string_packages_table() { global $wpdb; $charset_collate = SitePress_Setup::get_charset_collate(); self::$table_name = $wpdb->prefix . 'icl_string_packages'; $sql = ' CREATE TABLE IF NOT EXISTS `' . self::$table_name . '` ( `ID` bigint(20) unsigned NOT NULL auto_increment, `kind_slug` varchar(160) NOT NULL, `kind` varchar(160) NOT NULL, `name` varchar(160) NOT NULL, `title` varchar(160) NOT NULL, `edit_link` TEXT NOT NULL, `view_link` TEXT NOT NULL, `post_id` INTEGER DEFAULT NULL, `word_count` VARCHAR(2000) DEFAULT NULL, PRIMARY KEY (`ID`) ) ' . $charset_collate . ''; if ( $wpdb->query( $sql ) === false ) { throw new Exception( $wpdb->last_error ); } } private static function update_kind_slug() { global $wpdb; $sql = 'SELECT kind FROM ' . self::$table_name . " WHERE IFNULL(kind_slug,'')='' GROUP BY kind"; $kinds = $wpdb->get_col( $sql ); $result = ( count( $kinds ) == 0 ); foreach ( $kinds as $kind ) { $kind_slug = sanitize_title_with_dashes( $kind ); $result = $wpdb->update( self::$table_name, array( 'kind_slug' => $kind_slug ), array( 'kind' => $kind ) ); if ( ! $result ) { break; } } return $result; } } inc/wpml-package-constants.php 0000644 00000000107 14721633032 0012407 0 ustar 00 <?php define( 'LINE', 0 ); define( 'AREA', 1 ); define( 'VISUAL', 2 ); inc/wpml-package-translation-tm.class.php 0000644 00000027121 14721633032 0014460 0 ustar 00 <?php class WPML_Package_TM extends WPML_Package_TM_Jobs { public function __construct( $package ) { parent::__construct( $package ); } public function get_translation_statuses() { global $sitepress; $package = $this->package; $post_trid = $this->get_trid(); $items = array(); if ( $post_trid ) { $translation_element_type = $package->get_translation_element_type(); $post_translations = $sitepress->get_element_translations( $post_trid, $translation_element_type ); foreach ( $post_translations as $lang => $translation ) { $translation->trid = $post_trid; $item[] = $this->set_translation_status( $package, $translation, $lang ); } } else { $items[] = $package; } return $items; } /** * @param \WPML_Package $package * @param \stdClass $translation * @param string $lang * * @return \WPML_Package */ private function set_translation_status( $package, $translation, $lang ) { global $wpdb; if ( ! $package->trid ) { $package->trid = $translation->trid; } $res_query = "SELECT status, needs_update, md5 FROM {$wpdb->prefix}icl_translation_status WHERE translation_id=%d"; $res_args = array( $translation->translation_id ); $res_prepare = $wpdb->prepare( $res_query, $res_args ); $res = $wpdb->get_row( $res_prepare ); $_suffix = str_replace( '-', '_', $lang ); $status = ICL_TM_NOT_TRANSLATED; if ( $res ) { $status = $res->status; $index = 'needs_update_' . $_suffix; $package->$index = $res->needs_update; } $index = 'status_' . $_suffix; $package->$index = apply_filters( 'wpml_translation_status', $status, $translation->trid, $lang, 'package' ); return $package; } public function is_translation_in_progress() { global $wpdb; $post_translations = $this->get_post_translations(); foreach ( $post_translations as $lang => $translation ) { $res_query = "SELECT status, needs_update, md5 FROM {$wpdb->prefix}icl_translation_status WHERE translation_id=%d"; $res_prepared = $wpdb->prepare( $res_query, array( $translation->translation_id ) ); $res = $wpdb->get_row( $res_prepared ); if ( $res && $res->status == ICL_TM_IN_PROGRESS ) { return true; } } return false; } /** * Update translations * * @param bool $is_new_package * @param bool $needs_update - when deleting single field we do not need to change the translation status of the form * * @return bool */ public function update_package_translations( $is_new_package, $needs_update = true ) { global $iclTranslationManagement; $updated = false; $package = $this->package; $trid = $this->get_trid(); if ( $is_new_package ) { $this->set_language_details(); return true; } $item_md5_translations = $this->get_item_md5_translations( $trid ); if ( $item_md5_translations ) { $md5 = $iclTranslationManagement->post_md5( $this->package ); if ( $md5 != $item_md5_translations[0]->md5 ) { // all translations need update $translation_package = $iclTranslationManagement->create_translation_package( $this->package ); foreach ( $item_md5_translations as $translation ) { $translation_id = $translation->translation_id; $previous_state = $this->get_translation_state( $translation ); $data = array(); if ( ! empty( $previous_state ) ) { $data['previous_state'] = serialize( $previous_state ); } $data = array( 'translation_id' => $translation_id, 'translation_package' => serialize( $translation_package ), 'md5' => $md5, ); if ( $needs_update ) { $data['needs_update'] = 1; } $update_result = $iclTranslationManagement->update_translation_status( $data ); $rid = $update_result[0]; $this->update_translation_job( $rid, $this->package ); // change job status only when needs update if ( $needs_update ) { $job_id = $this->get_translation_job_id( $rid ); if ( $job_id ) { $this->update_translation_job_needs_update( $job_id ); $updated = true; } } } } } return $updated; } private function get_item_md5_translations( $trid ) { global $wpdb; $item_md5_translations_query = " SELECT t.translation_id, s.md5 FROM {$wpdb->prefix}icl_translations t NATURAL JOIN {$wpdb->prefix}icl_translation_status s WHERE t.trid=%d AND t.source_language_code IS NOT NULL"; $item_md5_translations_prepare = $wpdb->prepare( $item_md5_translations_query, $trid ); $item_md5_translations = $wpdb->get_results( $item_md5_translations_prepare ); return $item_md5_translations; } private function get_translation_state( $translation ) { global $wpdb; $previous_state_query = " SELECT status, translator_id, needs_update, md5, translation_service, translation_package, timestamp, links_fixed FROM {$wpdb->prefix}icl_translation_status WHERE translation_id = %d "; $previous_state_prepare = $wpdb->prepare( $previous_state_query, $translation->translation_id ); $previous_state = $wpdb->get_row( $previous_state_prepare, ARRAY_A ); return $previous_state; } public function add_package_to_basket( $translation_action, $source_language, $target_language ) { if ( ! $this->validate_basket_package_item( $translation_action, $source_language ) ) { return false; } if ( $this->is_duplicate_or_do_nothing( $translation_action ) ) { $this->duplicate_or_do_nothing( $translation_action, $target_language ); } elseif ( $translation_action == 1 ) { $this->send_package_to_basket( $source_language, $target_language ); } return true; } private function duplicate_package( $package_id ) { // TODO: [WPML 3.3] duplication to be done // $this->make_duplicate( $package_id, $language_code ); } /** * @param int $translation_action * @param string $source_language * * @return bool */ private function validate_basket_package_item( $translation_action, $source_language ) { ICL_AdminNotifier::remove_message( 'the_basket_items_notification' ); $package = $this->package; $package_id = $package->ID; $basket = TranslationProxy_Basket::get_basket(); $package_is_valid = true; $basket_source_language = TranslationProxy_Basket::get_source_language(); if ( $basket && $basket_source_language ) { if ( $source_language != $basket_source_language ) { TranslationProxy_Basket::add_message( array( 'type' => 'update', 'text' => __( 'You cannot add packages in this language to the basket since it already contains posts, packages or strings of another source language! Either submit the current basket and then add the post or delete the posts of differing language in the current basket', 'wpml-string-translation' ), ) ); TranslationProxy_Basket::update_basket(); $package_is_valid = false; } } $select_one_lang_message = __( 'Please select at least one language to translate into.', 'wpml-string-translation' ); if ( ! $translation_action ) { TranslationProxy_Basket::add_message( array( 'type' => 'error', 'text' => $select_one_lang_message, ) ); $package_is_valid = false; } else { TranslationProxy_Basket::remove_message( $select_one_lang_message ); } if ( ! $package_id ) { TranslationProxy_Basket::add_message( array( 'type' => 'error', 'text' => __( 'Please select at least one document to translate.', 'wpml-string-translation' ), ) ); $package_is_valid = false; return $package_is_valid; } return $package_is_valid; } private function is_duplicate_or_do_nothing( $translation_action ) { return $translation_action == 0 || $translation_action == 2; } private function duplicate_or_do_nothing( $translation_action, $target_language ) { $basket = TranslationProxy_Basket::get_basket(); $package = $this->package; $package_id = $package->ID; // iterate posts ids, check if they are in wp_options // if they are set to translate for this particular language // end then remove it // check if we have this post in wp_options // end remove if ( isset( $basket['package'][ $package_id ]['to_langs'][ $target_language ] ) ) { unset( $basket['package'][ $package_id ]['to_langs'][ $target_language ] ); TranslationProxy_Basket::update_basket( $basket ); } // if user want to duplicate this post, lets do this if ( $translation_action == 2 ) { $this->duplicate_package( $package_id ); } } /** * @param string $source_language * @param string $target_language * * @throws WPML_Package_Exception */ public function send_package_to_basket( $source_language, $target_language ) { global $sitepress, $iclTranslationManagement; $package = $this->package; $package_id = $package->ID; $basket = TranslationProxy_Basket::get_basket(); $language_name = $sitepress->get_display_language_name( $target_language ); $send_to_basket = true; $package_helper = new WPML_Package_Helper(); /** @var WPML_Package $post */ $post = $package_helper->get_translatable_item( null, $package_id ); $post_title = esc_html( $post->title ); $element_type = $package->get_element_type_prefix() . '_' . $post->kind_slug; $trid = $sitepress->get_element_trid( $package_id, $element_type ); $job_id = $iclTranslationManagement->get_translation_job_id( $trid, $target_language ); if ( $job_id ) { $job_details = $iclTranslationManagement->get_translation_job( $job_id ); $send_to_basket = $this->validate_package_status( $job_details, $post_title, $language_name ); } if ( $send_to_basket ) { $basket['package'][ $package_id ]['from_lang'] = $source_language; $basket['package'][ $package_id ]['to_langs'][ $target_language ] = 1; // set basket language if not already set if ( ! isset( $basket['source_language'] ) ) { $basket['source_language'] = $source_language; } } TranslationProxy_Basket::update_basket( $basket ); } /** * @param \stdClass $job_details * @param string $post_title * @param string $language_name * * @return bool */ private function validate_package_status( $job_details, $post_title, $language_name ) { $send_to_basket = true; $message_args = array(); if ( ! $job_details->needs_update ) { if ( $job_details->status == ICL_TM_IN_PROGRESS ) { $message_args = array( 'type' => 'update', 'text' => sprintf( __( 'Post "%1$s" will be ignored for %2$s, because translation is already in progress.', 'wpml-string-translation' ), $post_title, $language_name ), ); $send_to_basket = false; } elseif ( $job_details->status == ICL_TM_WAITING_FOR_TRANSLATOR ) { $message_args = array( 'type' => 'update', 'text' => sprintf( __( 'Post "%1$s" will be ignored for %2$s, because translation is already waiting for translator.', 'wpml-string-translation' ), $post_title, $language_name ), ); $send_to_basket = false; } } if ( ! $send_to_basket ) { TranslationProxy_Basket::add_message( $message_args ); TranslationProxy_Basket::update_basket(); } return $send_to_basket; } public function is_in_basket( $target_lang ) { if ( class_exists( 'TranslationProxy_Basket' ) ) { $basket = TranslationProxy_Basket::get_basket(); return isset( $basket['package'][ $this->package->ID ]['to_langs'][ $target_lang ] ); } else { return false; } } } inc/wpml-package-translation-exception.class.php 0000644 00000000324 14721633032 0016032 0 ustar 00 <?php class WPML_Package_Exception extends Exception { public $type; public function __construct( $type = '', $message = '', $code = 0 ) { parent::__construct( $message, $code ); $this->type = $type; } } inc/wpml-package-translation-ui.class.php 0000644 00000005117 14721633032 0014456 0 ustar 00 <?php class WPML_Package_Translation_UI { var $load_priority = 101; private $menu_root = ''; const MENU_SLUG = 'wpml-package-management'; public function __construct() { add_action( 'wpml_loaded', array( $this, 'loaded' ), $this->load_priority ); } public function loaded() { if ( $this->passed_dependencies() ) { $this->set_admin_hooks(); do_action( 'WPML_PT_HTML' ); } } private function passed_dependencies() { return defined( 'ICL_SITEPRESS_VERSION' ) && defined( 'WPML_ST_VERSION' ) && defined( 'WPML_TM_VERSION' ); } private function set_admin_hooks() { if ( is_admin() ) { add_action( 'wpml_admin_menu_configure', array( $this, 'menu' ) ); add_action( 'wpml_admin_menu_root_configured', array( $this, 'main_menu_configured' ), 10, 2 ); add_action( 'admin_register_scripts', array( $this, 'admin_register_scripts' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) ); } } public function main_menu_configured( $menu_id, $root_slug ) { if ( 'WPML' === $menu_id ) { $this->menu_root = $root_slug; } } /** * @param string $menu_id */ public function menu( $menu_id ) { if ( 'WPML' !== $menu_id || ! defined( 'ICL_PLUGIN_PATH' ) ) { return; } /** @var SitePress|null $sitepress */ global $sitepress; if ( ! isset( $sitepress ) || ( method_exists( $sitepress, 'get_setting' ) && ! $sitepress->get_setting( 'setup_complete' ) ) ) { return; } global $sitepress_settings; if ( ! isset( $sitepress_settings['existing_content_language_verified'] ) || ! $sitepress_settings['existing_content_language_verified'] ) { return; } if ( current_user_can( 'wpml_manage_string_translation' ) ) { $menu = array(); $menu['order'] = 1300; $menu['page_title'] = __( 'Packages', 'wpml-string-translation' ); $menu['menu_title'] = __( 'Packages', 'wpml-string-translation' ); $menu['capability'] = 'wpml_manage_string_translation'; $menu['menu_slug'] = self::MENU_SLUG; $menu['function'] = array( 'WPML_Package_Translation_HTML_Packages', 'package_translation_menu', ); do_action( 'wpml_admin_menu_register_item', $menu ); $this->admin_register_scripts(); } } function admin_register_scripts() { wp_register_script( 'wpml-package-trans-man-script', WPML_PACKAGE_TRANSLATION_URL . '/resources/js/wpml_package_management.js', array( 'jquery' ) ); } function admin_enqueue_scripts( $hook ) { if ( get_plugin_page_hookname( self::MENU_SLUG, $this->menu_root ) === $hook ) { wp_enqueue_script( 'wpml-package-trans-man-script' ); } } } inc/wpml-package-admin-lang-switcher.class.php 0000644 00000007730 14721633032 0015345 0 ustar 00 <?php class WPML_Package_Admin_Lang_Switcher { private $package; private $args; public function __construct( $package, $args ) { $this->package = new WPML_Package( $package ); $this->args = $args; add_action( 'wp_before_admin_bar_render', array( $this, 'admin_language_switcher' ) ); add_action( 'wp_after_admin_bar_render', array( $this, 'add_meta_box' ) ); } function admin_language_switcher() { global $wp_admin_bar, $wpdb, $sitepress; $parent = 'WPML_PACKAGE_LANG'; $package_language = $this->package->get_package_language(); if ( ! $package_language ) { $package_language = $sitepress->get_default_language(); } $wpml_pt_meta = new WPML_Package_Translation_Metabox( $this->package, $wpdb, $sitepress, $this->args ); $package_language_name = $wpml_pt_meta->get_package_language_name(); $wp_admin_bar->add_menu( array( 'parent' => false, 'id' => $parent, 'title' => '<img width="18" height="12" src="' . $sitepress->get_flag_url( $package_language ) . '"> ' . $package_language_name, ) ); } function add_meta_box() { global $wpdb, $sitepress; $metabox = '<div id="wpml-package-admin-bar-popup" class="wpml-package-popup">'; $wpml_pt_meta = new WPML_Package_Translation_Metabox( $this->package, $wpdb, $sitepress, $this->args ); $metabox .= $wpml_pt_meta->get_metabox(); $metabox .= '</div>'; $metabox .= $this->add_js(); // This is required when a new package is created but it doesn't have any translated content yet. // https://onthegosystems.myjetbrains.com/youtrack/issue/wpmlst-556 WPML_Simple_Language_Selector::enqueue_scripts(); wp_enqueue_style( 'wpml-package-adminbar-popup', WPML_ST_URL . '/res/css/wpml-package-adminbar-popup.css', array(), ICL_SITEPRESS_VERSION ); echo $metabox; } function add_js() { ob_start(); ?> <script type="text/javascript"> var WPML_Package_Translation = WPML_Package_Translation || {}; WPML_Package_Translation.AdminLanguageSwitcher = function () { var self = this; self.init = function () { self.link = jQuery('#wp-admin-bar-WPML_PACKAGE_LANG').find('.ab-item'); self.link.hover(self.show_lang_box, self.hide_lang_box); self.popup = jQuery('#wpml-package-admin-bar-popup'); self.popup.css('left', self.link.offset().left); self.popup.hover(self.show_lang_box, self.hide_on_leave); jQuery('#icl_package_language').off('wpml-package-language-changed'); jQuery('#icl_package_language').on('wpml-package-language-changed', self.package_language_changed); }; self.show_lang_box = function() { self.popup.css('top', self.link.offset().top + self.link.height() - window.scrollTop); self.popup.show(); }; self.hide_lang_box = function() { self.popup.hide(); }; self.hide_on_leave = function(e) { // Make sure we are fully leaving the popup because this is sometimes // triggered when we open the language select and then move the mouse. var x = e.clientX; var y = e.clientY; var pos = self.popup.offset(); if ( x < pos.left || x > pos.left + self.popup.width() || y < pos.top || y > pos.top + self.popup.height()) { self.popup.fadeOut(800); } }; self.package_language_changed = function( e, lang ) { self.link.html( self.find_flag(lang) + ' ' + lang); self.popup.hide(); }; self.find_flag = function( lang ) { var flag = ''; jQuery('.js-simple-lang-selector option').each( function() { if (jQuery(this).text().trim() == lang.trim()) { flag = '<img width="18" height="12" src="' + jQuery(this).data('flag_url') + '">'; } }); return flag; }; self.init(); }; jQuery(document).ready( function () { WPML_Package_Translation.admin_language_switcher = new WPML_Package_Translation.AdminLanguageSwitcher(); } ); </script> <?php return ob_get_clean(); } } inc/wpml-package-translation-helper.class.php 0000644 00000053161 14721633032 0015322 0 ustar 00 <?php use WPML\FP\Obj; class WPML_Package_Helper { const PREFIX_BATCH_STRING = 'batch-string-'; private $default_language; private $last_registered_string_id; protected $registered_strings; private $package_cleanup; private $package_factory; private $cache_group; function __construct() { $this->registered_strings = array(); $this->cache_group = 'string_package'; $this->package_cleanup = new WPML_ST_Package_Cleanup(); $this->package_factory = new WPML_ST_Package_Factory(); } public function set_package_factory( WPML_ST_Package_Factory $factory ) { $this->package_factory = $factory; } /** * @param int $package_id */ protected function delete_package( $package_id ) { // delete the strings and the translations $this->delete_package_strings( $package_id ); $tm = new WPML_Package_TM( $this->package_factory->create( $package_id ) ); $tm->delete_translation_jobs(); $tm->delete_translations(); global $wpdb; $delete_query = "DELETE FROM {$wpdb->prefix}icl_string_packages WHERE id=%d"; $delete_prepare = $wpdb->prepare( $delete_query, $package_id ); $wpdb->query( $delete_prepare ); } /** * @param int $package_id * * @return array */ protected function get_strings_ids_from_package_id( $package_id ) { global $wpdb; $string_ids_query = "SELECT id FROM {$wpdb->prefix}icl_strings WHERE string_package_id=%d"; $string_ids_prepare = $wpdb->prepare( $string_ids_query, $package_id ); $string_ids = $wpdb->get_col( $string_ids_prepare ); return $string_ids; } /** * @param int $package_id */ protected function delete_package_strings( $package_id ) { $strings = $this->get_strings_ids_from_package_id( $package_id ); foreach ( $strings as $string_id ) { do_action( 'wpml_st_delete_all_string_data', $string_id ); } } protected function loaded() { $this->default_language = icl_get_default_language(); } /** * @param string $string_value * @param string $string_name * @param array|WPML_Package $package * @param string $string_title * @param string $string_type */ final function register_string_action( $string_value, $string_name, $package, $string_title, $string_type ) { $this->register_string_for_translation( $string_value, $string_name, $package, $string_title, $string_type ); return $this->last_registered_string_id; } /** * @param int $default * @param \stdClass|\WPML_Package|array|int $package * @param string $string_name * @param string $string_value * * @return bool|int|mixed */ function string_id_from_package_filter( $default, $package, $string_name, $string_value ) { $string_id = $this->get_string_id_from_package( $package, $string_name, $string_value ); if ( ! $string_id ) { return $default; } return $string_id; } function string_title_from_id_filter( $default, $string_id ) { global $wpdb; $string_title_query = 'SELECT title FROM ' . $wpdb->prefix . 'icl_strings WHERE id=%d'; $string_title_sql = $wpdb->prepare( $string_title_query, array( $string_id ) ); $string_title = $wpdb->get_var( $string_title_sql ); if ( ! $string_title ) { $string_title = $default; } return $string_title; } /** * @param string $string_value * @param string $string_name * @param array|WPML_Package $package * @param string $string_title * @param string $string_type * * @return string */ final public function register_string_for_translation( $string_value, $string_name, $package, $string_title, $string_type ) { $package = $this->package_factory->create( $package ); $package_id = $package->ID; if ( ! $package_id ) { // Need to create a new record. if ( $package->has_kind_and_name() ) { $package_id = self::create_new_package( $package ); $package = $this->package_factory->create( $package ); } } if ( $package_id ) { $this->maybe_update_package( $package ); $tm = new WPML_Package_TM( $package ); $tm->validate_translations(); $this->init_package_registered_strings( $package_id ); $string_name = $package->sanitize_string_name( $string_name ); $this->set_package_registered_strings( $package_id, $string_type, $string_title, $string_name, $string_value ); $this->last_registered_string_id = $this->register_string_with_wpml( $package, $string_name, $string_title, $string_type, $string_value ); $this->package_cleanup->record_register_string( $package, $this->last_registered_string_id ); } // Action called after string is registered do_action( 'wpml_st_string_registered' ); return $string_value; } final function get_string_context_from_package( $package ) { $package = $this->package_factory->create( $package ); return $package->get_string_context_from_package(); } /** * @param WPML_Package $package * @param string $string_name * @param string $string_title * @param string $string_type * @param string $string_value * * @return bool|int|mixed */ final function register_string_with_wpml( $package, $string_name, $string_title, $string_type, $string_value ) { global $wpdb; $string_id = $this->get_string_id_from_package( $package, $string_name, $string_value ); if ( $string_id ) { $package_storage = new WPML_ST_Package_Storage( $package->ID, $wpdb ); $did_update = $package_storage->update( $string_title, $string_type, $string_value, $string_id ); if ( $did_update ) { $this->flush_cache(); $package->flush_cache(); // Action called after package strings are updated. do_action( 'wpml_st_string_updated' ); } } return $string_id; } /** * @param string|mixed $string_value * @param string $string_name * @param array|object|int $package * * @return string|mixed */ final function translate_string( $string_value, $string_name, $package ) { $result = $string_value; if ( is_string( $string_value ) ) { /** @var array|stdClass $package */ $package = is_scalar( $package ) ? [ 'ID' => $package ] : Obj::assoc( 'translate_only', true, $package ); $package = $this->package_factory->create( $package ); if ( $package ) { $sanitized_string_name = $package->sanitize_string_name( $string_name ); $result = $package->translate_string( $string_value, $sanitized_string_name ); } } return $result; } final function get_translated_strings( $strings, $package ) { $package = $this->package_factory->create( $package ); return $package->get_translated_strings( $strings ); } final function set_translated_strings( $translations, $package ) { $package = $this->package_factory->create( $package ); $package->set_translated_strings( $translations ); } final function get_translatable_types( $types ) { global $wpdb; $package_kinds = $wpdb->get_results( "SELECT kind, kind_slug FROM {$wpdb->prefix}icl_string_packages WHERE id>0" ); // Add any packages found to the $types array foreach ( $package_kinds as $package_data ) { $package_kind_slug = $package_data->kind_slug; $package_kind = $package_data->kind; $kinds_added = array_keys( $types ); if ( ! in_array( $package_kind_slug, $kinds_added ) ) { $translatable_type = new stdClass(); $translatable_type->name = $package_kind_slug; $translatable_type->label = $package_kind; $translatable_type->prefix = 'package'; $translatable_type->labels = new stdClass(); $translatable_type->labels->singular_name = $package_kind; $translatable_type->labels->name = $package_kind; $translatable_type->external_type = 1; $types[ $package_kind_slug ] = $translatable_type; } } return $types; } /** * @param WPML_Package|null $item * @param int|WP_Post|WPML_Package $package * @param string $type * * @return null|WPML_Package */ final public function get_translatable_item( $item, $package, $type = 'package' ) { if ( $type === 'package' || explode( '_', is_null( $type ) ? '' : $type )[0] === 'package' ) { $tm = new WPML_Package_TM( $item ); return $tm->get_translatable_item( $package ); } return $item; } final function get_post_title( $title, $package_id ) { $package = $this->package_factory->create( $package_id ); if ( $package ) { $title = $package->kind . ' - ' . $package->title; } return $title; } final function get_editor_string_name( $name, $package ) { $package = $this->package_factory->create( $package ); $package_id = $package->ID; $title = $this->get_editor_string_element( $name, $package_id, 'title' ); if ( $title && $title != '' ) { $name = $title; } elseif ( \WPML\FP\Str::includes( self::PREFIX_BATCH_STRING, $name ) && ( $string = $this->get_st_string_by_batch_name( $name ) ) ) { $name = $this->empty_if_md5( $string->get_name() ) ?: ( $string->get_gettext_context() ?: ( $string->get_context() ?: $name ) ); } return $name; } private function empty_if_md5( $str ) { return preg_replace( '#^((.+)( - ))?([a-z0-9]{32})$#', '$2', $str ); } /** * @param string $batch_string_name * * @return WPML_ST_String|null * @throws \WPML\Auryn\InjectionException */ private function get_st_string_by_batch_name( $batch_string_name ) { $string_id = (int) \WPML\FP\Str::replace( self::PREFIX_BATCH_STRING, '', $batch_string_name ); if ( $string_id ) { $string_factory = WPML\Container\make( WPML_ST_String_Factory::class ); return $string_factory->find_by_id( $string_id ); } return null; } final function get_editor_string_style( $style, $field_type, $package ) { $package = $this->package_factory->create( $package ); $package_id = $package->ID; $element_style = $this->get_editor_string_element( $field_type, $package_id, 'type' ); if ( $element_style ) { $style = 0; if ( defined( $element_style ) ) { $style = constant( $element_style ); } } return $style; } final public function get_element_id_from_package_filter( $default, $package_id ) { global $wpdb; $element_id_query = 'SELECT name FROM ' . $wpdb->prefix . 'icl_string_packages WHERE ID=%d'; $element_id_prepare = $wpdb->prepare( $element_id_query, $package_id ); $element_id = $wpdb->get_var( $element_id_prepare ); if ( ! $element_id ) { $element_id = $default; } return $element_id; } final public function get_package_type( $type, $post_id ) { $package = $this->package_factory->create( $post_id ); if ( $package ) { return $this->get_package_context( $package ); } else { return $type; } } final public function get_package_type_prefix( $type, $post_id ) { if ( $type == 'package' ) { $package = $this->package_factory->create( $post_id ); if ( $package ) { $type = $package->get_string_context_from_package(); } } return $type; } /** * @param string $language_for_element * @param \WPML_Package $current_document * * @return null|string */ final public function get_language_for_element( $language_for_element, $current_document ) { if ( $this->is_a_package( $current_document ) ) { global $sitepress; $language_for_element = $sitepress->get_language_for_element( $current_document->ID, $current_document->get_translation_element_type() ); } return $language_for_element; } final protected function get_package_context( $package ) { $package = $this->package_factory->create( $package ); return $package->kind_slug . '-' . $package->name; } final function delete_packages_ajax() { if ( ! $this->verify_ajax_call( 'wpml_package_nonce' ) ) { die( 'verification failed' ); } $packages_ids = $_POST['packages']; $this->delete_packages( $packages_ids ); exit; } final function delete_package_action( $name, $kind ) { $package_data['name'] = $name; $package_data['kind'] = $kind; $package = $this->package_factory->create( $package_data ); if ( $package && $package->ID && $this->is_a_package( $package ) ) { $this->delete_package( $package->ID ); $this->flush_cache(); } } /** @param int $post_id */ final public function remove_post_packages( $post_id ) { $packages = $this->get_post_string_packages( array(), $post_id ); foreach ( $packages as $package ) { $this->delete_package( $package->ID ); } } final protected function delete_packages( $packages_ids ) { $flush_cache = false; foreach ( $packages_ids as $package_id ) { $this->delete_package( $package_id ); $flush_cache = true; } if ( $flush_cache ) { $this->flush_cache(); } } final function change_package_lang_ajax() { global $wpdb, $sitepress; if ( ! $this->verify_ajax_call( 'wpml_package_nonce' ) ) { die( 'verification failed' ); } $package_id = $_POST['package_id']; $package = $this->package_factory->create( $package_id ); $package->set_strings_language( $_POST['package_lang'] ); $package_job = new WPML_Package_TM( $package ); $package_job->set_language_details( $_POST['package_lang'] ); $args = json_decode( base64_decode( $_POST['args'] ) ); $args = array_map( 'sanitize_text_field', (array) $args ); $package_metabox = new WPML_Package_Translation_Metabox( $package, $wpdb, $sitepress, $args ); $response = array( 'metabox' => $package_metabox->get_metabox_status(), 'lang' => $package_metabox->get_package_language_name(), ); wp_send_json( $response ); } /** * @param string $string_name * @param int $package_id * @param string $column * * @return string */ private function get_editor_string_element( $string_name, $package_id, $column ) { global $wpdb; $element_query = 'SELECT ' . $column . " FROM {$wpdb->prefix}icl_strings WHERE string_package_id=%d AND name=%s"; $element_prepared = $wpdb->prepare( $element_query, array( $package_id, $string_name ) ); $element = $wpdb->get_var( $element_prepared ); return $element; } private function flush_cache() { // delete the cache key we use wp_cache_delete( 'get_all_packages', $this->cache_group ); } /** * @param WPML_Package $package * * @return int */ final public static function create_new_package( WPML_Package $package ) { $package_id = $package->create_new_package_record(); $tm = new WPML_Package_TM( $package ); $tm->update_package_translations( true ); return (int) $package_id; } /** * @param int $package_id */ private function init_package_registered_strings( $package_id ) { if ( ! isset( $this->registered_strings[ $package_id ] ) ) { $this->registered_strings[ $package_id ] = array( 'strings' => array() ); } } /** * @param int $package_id * @param string $string_type * @param string $string_title * @param string $string_name * @param string $string_value */ private function set_package_registered_strings( $package_id, $string_type, $string_title, $string_name, $string_value ) { $this->registered_strings[ $package_id ]['strings'][ $string_name ] = array( 'title' => $string_title, 'kind' => $string_type, 'value' => $string_value, ); } /** * @param \stdClass|\WPML_Package|array|int $package * @param string $string_name * @param string $string_value * * @return bool|int|mixed */ private function get_string_id_from_package( $package, $string_name, $string_value ) { if ( ! $package instanceof WPML_Package ) { $package = $this->package_factory->create( $package ); } return $package->get_string_id_from_package( $string_name, $string_value ); } final function get_external_id_from_package( $package ) { return 'external_' . $package['kind_slug'] . '_' . $package['ID']; } final function get_string_context( $package ) { return sanitize_title_with_dashes( $package['kind_slug'] . '-' . $package['name'] ); } final function get_package_id( $package, $from_cache = true ) { global $wpdb; static $cache = array(); if ( $this->is_a_package( $package ) ) { $package = object_to_array( $package ); } $key = $this->get_string_context( $package ); if ( ! $from_cache || ! array_key_exists( $key, $cache ) ) { $package_id_query = "SELECT ID FROM {$wpdb->prefix}icl_string_packages WHERE kind_slug = %s AND name = %s"; $package_id_prepare = $wpdb->prepare( $package_id_query, array( $package['kind_slug'], $package['name'] ) ); $package_id = $wpdb->get_var( $package_id_prepare ); if ( ! $package_id ) { return false; } $cache[ $key ] = $package_id; } return $cache[ $key ]; } final public function get_all_packages() { global $wpdb; $cache_key = 'get_all_packages'; $cache_found = false; $all_packages = wp_cache_get( $cache_key, $this->cache_group, false, $cache_found ); if ( ! $cache_found ) { $all_packages = array(); $all_packages_data_query = "SELECT * FROM {$wpdb->prefix}icl_string_packages"; $all_packages_data = $wpdb->get_results( $all_packages_data_query ); foreach ( $all_packages_data as $package_data ) { $package = $this->package_factory->create( $package_data ); $all_packages[ $package->ID ] = $package; } if ( $all_packages ) { wp_cache_set( $cache_key, $all_packages, $this->cache_group ); } } return $all_packages; } final protected function is_a_package( $element ) { return is_a( $element, 'WPML_Package' ); } protected function verify_ajax_call( $ajax_action ) { return isset( $_POST['wpnonce'] ) && wp_verify_nonce( $_POST['wpnonce'], $ajax_action ); } protected function sanitize_string_name( $string_name ) { $string_name = preg_replace( '/[ \[\]]+/', '-', $string_name ); return $string_name; } public function refresh_packages() { // TODO: deprecated. // This is required to support Layouts 1.0 do_action( 'WPML_register_string_packages', 'layout', array() ); // TODO: END deprecated. do_action( 'wpml_register_string_packages' ); } /** * @param WPML_Package $package */ private function maybe_update_package( $package ) { if ( $package->new_title ) { $package->title = $package->new_title; $package->update_package_record(); } } public function change_language_of_strings( $strings, $lang ) { global $wpdb; $all_ok = true; $strings_in = implode( ',', $strings ); $string_packages_query = "SELECT DISTINCT string_package_id FROM {$wpdb->prefix}icl_strings WHERE id IN ($strings_in)"; $package_ids = $wpdb->get_col( $string_packages_query ); foreach ( $package_ids as $package_id ) { if ( $package_id ) { $package = $this->package_factory->create( $package_id ); if ( ! $package->are_all_strings_included( $strings ) ) { $all_ok = false; break; } } } if ( $all_ok ) { $this->set_packages_language( $package_ids, $lang ); } $response = array(); $response['success'] = $all_ok; if ( ! $all_ok ) { $response['error'] = __( 'Some of the strings selected belong to packages. You can only change the language of these strings if all strings in the packages are selected.', 'wpml-string-translation' ); } return $response; } public function change_language_of_strings_in_domain( $domain, $langs, $to_lang ) { global $wpdb; if ( ! empty( $langs ) ) { foreach ( $langs as &$lang ) { $lang = "'" . $lang . "'"; } $langs = implode( ',', $langs ); $string_packages_query = "SELECT DISTINCT string_package_id FROM {$wpdb->prefix}icl_strings WHERE context='%s' AND language IN ($langs)"; $string_packages_query = $wpdb->prepare( $string_packages_query, $domain ); $package_ids = $wpdb->get_col( $string_packages_query ); $this->set_packages_language( $package_ids, $to_lang ); } } private function set_packages_language( $package_ids, $lang ) { foreach ( $package_ids as $package_id ) { if ( $package_id ) { $package = $this->package_factory->create( $package_id ); $package->set_strings_language( $lang ); $package_job = new WPML_Package_TM( $package ); $package_job->set_language_details( $lang ); } } } /** * @param null|array $packages * @param int $post_id * * @return WPML_Package[] */ public function get_post_string_packages( $packages, $post_id ) { global $wpdb; $query = $wpdb->prepare( "SELECT ID FROM {$wpdb->prefix}icl_string_packages WHERE post_id = %d", $post_id ); $package_ids = $wpdb->get_col( $query ); $packages = $packages ? $packages : array(); foreach ( $package_ids as $package_id ) { $packages[ $package_id ] = $this->package_factory->create( $package_id ); } return $packages; } /** * @param int $string_id * @param string $language * @param string|null $value * @param int|bool $status * @param int|null $translator_id * @param int|null $translation_service * @param int|null $batch_id */ public function add_string_translation_action( $string_id, $language, $value = null, $status = false, $translator_id = null, $translation_service = null, $batch_id = null ) { icl_add_string_translation( $string_id, $language, $value, $status, $translator_id, $translation_service, $batch_id ); } /** * @param mixed $package * @param int $package_id * * @return WPML_Package */ public function get_string_package( $package, $package_id ) { return $this->package_factory->create( $package_id ); } public function start_string_package_registration_action( $package ) { $this->package_cleanup->record_existing_strings( $this->package_factory->create( $package ) ); } public function delete_unused_package_strings_action( $package ) { $this->package_cleanup->delete_unused_strings( $this->package_factory->create( $package ) ); } } resources/js/wpml_package_management.js 0000644 00000005716 14721633032 0014370 0 ustar 00 /*globals jQuery, ajaxurl*/ /*jshint browser:true, devel:true*/ var WPML_Package_Translation = WPML_Package_Translation || {}; (function () { "use strict"; WPML_Package_Translation.ManagementPage = function () { var self = this; self.init = function () { jQuery('.js_package_all_cb').on('change', self.check_uncheck_all); jQuery('.js_package_row_cb').on('change', self.enable_disable_delete); jQuery('#delete_packages').on('click', self.delete_selected_packages); jQuery('#package_kind_filter').on('change', self.filter_by_kind); }; self.check_uncheck_all = function () { var package_all_cb = jQuery('.js_package_all_cb').first(); var checked = package_all_cb.prop('checked'); jQuery('.js_package_row_cb').each( function () { if (!jQuery(this).is(':disabled')) { jQuery(this).prop('checked', checked); } } ); self.enable_disable_delete(); }; self.enable_disable_delete = function () { var enable = jQuery('.js_package_row_cb:checked:visible').length !== 0; jQuery('#delete_packages').prop('disabled', !enable); }; self.delete_selected_packages = function () { if (confirm(jQuery('.js-delete-confirm-message').html())) { jQuery('#delete_packages').prop('disabled', true); jQuery('.spinner').css( 'float', 'none' ).addClass( 'is-active' ); var selected = jQuery('.js_package_row_cb:checked:visible'); var packages = []; selected.each( function () { packages.push(jQuery(this).val()); } ); var data = { action: 'wpml_delete_packages', wpnonce: jQuery('#wpml_package_nonce').attr('value'), packages: packages }; jQuery.ajax( { url: ajaxurl, type: 'post', data: data, success: function () { selected.each( function () { var package_row = jQuery(this).closest('.js_package'); package_row.fadeOut( 1000, function () { jQuery(this).remove(); } ); } ); jQuery('.spinner').removeClass( 'is-active' ); } } ); } }; self.all_selected = function () { var kind_slug = jQuery('#package_kind_filter').val(); return kind_slug === '-1'; }; self.filter_by_kind = function () { var kind_slug = jQuery('#package_kind_filter').val(); var icl_package_translations = jQuery('#icl_package_translations'); var icl_package_translations_body = icl_package_translations.find('tbody'); if (self.all_selected()) { icl_package_translations_body.find('tr').show(); } else { icl_package_translations_body.find('tr').hide(); icl_package_translations_body.find('tr.js_package.js_package_' + kind_slug).show(); } self.enable_disable_delete(); }; self.init(); }; jQuery( function () { WPML_Package_Translation.management_page = new WPML_Package_Translation.ManagementPage(); } ); }()); Hooks.php 0000644 00000001117 14721636505 0006351 0 ustar 00 <?php namespace WPML\ST\PackageTranslation; class Hooks implements \IWPML_Action, \IWPML_Backend_Action, \IWPML_Frontend_Action { public function add_hooks() { /** * @see Assign::stringsFromDomainToExistingPackage() */ add_action( 'wpml_st_assign_strings_from_domain_to_existing_package', Assign::class . '::stringsFromDomainToExistingPackage', 10, 2 ); /** * @see Assign::stringsFromDomainToNewPackage() */ add_action( 'wpml_st_assign_strings_from_domain_to_new_package', Assign::class . '::stringsFromDomainToNewPackage', 10, 2 ); } } class-wpml-st-package-cleanup.php 0000644 00000001625 14721636505 0013016 0 ustar 00 <?php class WPML_ST_Package_Cleanup { private $existing_strings_in_package = array(); public function record_existing_strings( WPML_Package $package ) { $strings = $package->get_package_strings(); $this->existing_strings_in_package[ $package->ID ] = array(); if ( $strings ) { foreach ( $strings as $string ) { $this->existing_strings_in_package[ $package->ID ][ $string->id ] = $string; } } } public function record_register_string( WPML_Package $package, $string_id ) { unset( $this->existing_strings_in_package[ $package->ID ][ $string_id ] ); } public function delete_unused_strings( WPML_Package $package ) { if ( array_key_exists( $package->ID, $this->existing_strings_in_package ) ) { foreach ( $this->existing_strings_in_package[ $package->ID ] as $string_data ) { icl_unregister_string( $package->get_string_context_from_package(), $string_data->name ); } } } } class-wpml-st-package-storage.php 0000644 00000005623 14721636505 0013035 0 ustar 00 <?php /** * Created by PhpStorm. * User: bruce * Date: 16/06/17 * Time: 10:57 AM */ class WPML_ST_Package_Storage { private $package_id; private $wpdb; /** * WPML_ST_Package_Storage constructor. * * @param int $package_id * @param \wpdb $wpdb */ public function __construct( $package_id, wpdb $wpdb ) { $this->package_id = $package_id; $this->wpdb = $wpdb; } /** * @param string $string_title * @param string $string_type * @param string $string_value * @param int $string_id * * @return bool */ public function update( $string_title, $string_type, $string_value, $string_id ) { $update_where = array( 'id' => $string_id ); $update_data = array( 'type' => $string_type, 'title' => $this->truncate_long_string( $string_title ), ); $type_or_title_updated = $this->wpdb->update( $this->wpdb->prefix . 'icl_strings', $update_data, $update_where ); $update_data = array( 'string_package_id' => $this->package_id, 'value' => $string_value, ); $package_id_or_value_updated = $this->wpdb->update( $this->wpdb->prefix . 'icl_strings', $update_data, $update_where ); if ( $package_id_or_value_updated ) { $this->set_string_status_to_needs_update_if_translated( $string_id ); $this->set_translations_to_needs_update(); } return $type_or_title_updated || $package_id_or_value_updated; } private function set_string_status_to_needs_update_if_translated( $string_id ) { $this->wpdb->query( $this->wpdb->prepare( "UPDATE {$this->wpdb->prefix}icl_strings SET status=%d WHERE id=%d AND status<>%d", ICL_TM_NEEDS_UPDATE, $string_id, ICL_TM_NOT_TRANSLATED ) ); $this->wpdb->query( $this->wpdb->prepare( "UPDATE {$this->wpdb->prefix}icl_string_translations SET status=%d WHERE string_id=%d AND status<>%d", ICL_TM_NEEDS_UPDATE, $string_id, ICL_TM_NOT_TRANSLATED ) ); } private function set_translations_to_needs_update() { $translation_ids = $this->wpdb->get_col( $this->wpdb->prepare( "SELECT translation_id FROM {$this->wpdb->prefix}icl_translations WHERE trid = ( SELECT trid FROM {$this->wpdb->prefix}icl_translations WHERE element_id = %d AND element_type LIKE 'package%%' LIMIT 1 )", $this->package_id ) ); if ( ! empty( $translation_ids ) ) { $this->wpdb->query( "UPDATE {$this->wpdb->prefix}icl_translation_status SET needs_update = 1 WHERE translation_id IN (" . wpml_prepare_in( $translation_ids, '%d' ) . ' ) ' ); } } private function truncate_long_string( $string ) { return strlen( $string ) > WPML_STRING_TABLE_NAME_CONTEXT_LENGTH ? mb_substr( $string, 0, WPML_STRING_TABLE_NAME_CONTEXT_LENGTH ) : $string; } } Assign.php 0000644 00000002367 14721636505 0006522 0 ustar 00 <?php namespace WPML\ST\PackageTranslation; class Assign { /** * Assign all strings from specified domain to existing package. * * @param string $domainName * @param int $packageId * * @since 3.1.0 */ public static function stringsFromDomainToExistingPackage( $domainName, $packageId ) { global $wpdb; $wpdb->update( $wpdb->prefix . 'icl_strings', [ 'string_package_id' => $packageId ], [ 'context' => $domainName ] ); } /** * Assign all strings from specified domain to new package which is created on fly. * * @param string $domainName * @param array $packageData { * * @type string $kind_slug e.g. toolset_forms * @type string $kind e.g. "Toolset forms" * @type string $name e.g. "1" * @type string $title e.g. "Form 1" * @type string $edit_link URL to edit page of resource * @type string $view_link (Optional) Url to frontend view page of resource * @type int $page_id (optional) * } * @since 3.1.0 */ public static function stringsFromDomainToNewPackage( $domainName, array $packageData ) { $packageId = \WPML_Package_Helper::create_new_package( new \WPML_Package( $packageData ) ); if ( $packageId ) { self::stringsFromDomainToExistingPackage( $domainName, $packageId ); } } }
| ver. 1.4 |
Github
|
.
| PHP 7.4.3-4ubuntu2.24 | Генерация страницы: 0.02 |
proxy
|
phpinfo
|
Настройка