PluginProbe ʕ •ᴥ•ʔ
WPML Multilingual & Multicurrency for WooCommerce / 5.5.7
WPML Multilingual & Multicurrency for WooCommerce v5.5.7
5.5.7 5.3.8 5.3.9 5.4.3 5.4.4 5.4.5 5.5.1 5.5.1.1 5.5.2.2 5.5.2.3 5.5.3 5.5.3.1 5.5.4 5.5.5 5.5.6 trunk 0.9 1.0 1.1 1.2 1.3 1.4 1.5 2.0 2.2 2.3 2.3.1 2.3.2 3.0 3.0.1 3.1 3.2 3.2.1 3.2.2 3.3 3.3.1 3.3.2 3.3.3 3.3.4 3.4 3.4.1 3.4.2 3.4.3 3.5 3.5.1 3.5.2 3.5.3 3.5.4 3.5.5 3.6 3.6.1 3.6.10 3.6.11 3.6.2 3.6.3 3.6.4 3.6.5 3.6.5.1 3.6.6 3.6.7 3.6.8 3.6.9 3.7 3.7.1 3.7.10 3.7.11 3.7.12 3.7.13 3.7.14 3.7.15 3.7.16 3.7.2 3.7.3 3.7.4 3.7.5 3.7.6 3.7.7 3.7.8 3.7.9 3.8.0 3.8.1 3.8.2 3.8.3 3.8.4 3.8.5 3.8.6 3.9.0 3.9.1 3.9.1.1 3.9.2 3.9.3 3.9.4 3.9.5 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4 4.10.0 4.10.1 4.10.2 4.10.3 4.10.4 4.11.2 4.11.3.2 4.11.5 4.11.6 4.12.1 4.12.4 4.12.5 4.12.6 4.2.0 4.2.0.1 4.2.1 4.2.1.1 4.2.10 4.2.2 4.2.3 4.2.4 4.2.5 4.2.6 4.2.7 4.2.7.1 4.2.8 4.2.8.1 4.2.9 4.3.0 4.3.1 4.3.2 4.3.2.1 4.3.3 4.3.4 4.3.5 4.3.6 4.3.7 4.4.0 4.4.1 4.4.2 4.4.2.1 4.5.0 4.6.0 4.6.1 4.6.2 4.6.2.1 4.6.3 4.6.5 4.6.6 4.6.7 4.7.0 4.7.1 4.7.2 4.7.3 4.7.4 4.7.5 4.7.6 4.7.7 4.7.8 4.7.9 4.8.0 4.9.0 4.9.1 5.0.1 5.0.2 5.1.1 5.1.2 5.1.3 5.2.0 5.2.1 5.3.2 5.3.3.1 5.3.4 5.3.5 5.3.6 5.3.7
woocommerce-multilingual / classes / TranslationControls / Hooks.php
woocommerce-multilingual / classes / TranslationControls Last commit date
Hooks.php 1 week ago
Hooks.php
232 lines
1 <?php
2
3 namespace WCML\TranslationControls;
4
5 use IWPML_Backend_Action;
6 use IWPML_DIC_Action;
7 use IWPML_REST_Action;
8 use SitePress;
9 use WCML\PointerUi\Factory;
10 use WCML\StandAlone\NullSitePress;
11 use WCML\Utilities\AdminUrl;
12 use WCML_WC_Strings;
13 use wpdb;
14 use WPML\Core\ISitePress;
15 use WPML\FP\Obj;
16 use WPML_Simple_Language_Selector;
17
18 abstract class Hooks implements IWPML_Backend_Action, IWPML_DIC_Action, IWPML_REST_Action {
19
20 const KEY_PREFIX = 'wcml_lang';
21 const LANGUAGE_SELECTOR_ID_SUFFIX = 'language_selector';
22
23 protected $sitepress;
24
25 protected $wcmlStrings;
26
27 protected $pointerFactory;
28
29 protected $wpdb;
30
31 public function __construct(
32 ISitePress $sitepress,
33 WCML_WC_Strings $wcmlStrings,
34 Factory $pointerFactory,
35 wpdb $wpdb
36 ) {
37 $this->sitepress = $sitepress;
38 $this->wcmlStrings = $wcmlStrings;
39 $this->pointerFactory = $pointerFactory;
40 $this->wpdb = $wpdb;
41 }
42
43 public function add_hooks() {
44 if ( $this->isAdminPage() ) {
45 add_action( 'admin_enqueue_scripts', [ $this, 'loadAssets' ] );
46 $this->addAdminPageHooks();
47 }
48 }
49
50 abstract protected function isAdminPage();
51
52 abstract protected function addAdminPageHooks();
53
54 public function loadAssets() {
55 wp_register_style( 'wcml_tc', WCML_PLUGIN_URL . '/res/css/translation-controls.css', [], WCML_VERSION );
56 wp_enqueue_style( 'wcml_tc' );
57 }
58
59 protected function hasStringsInDomain( $domain, $namePrefix = '' ) {
60 $args = [ $domain ];
61 $and = 'AND s.context = %s';
62 if ( $namePrefix ) {
63 $args[] = $namePrefix . '%';
64 $and .= ' AND s.name LIKE %s';
65 }
66
67 $results = $this->wpdb->get_results( $this->wpdb->prepare(
68 "SELECT context
69 FROM {$this->wpdb->prefix}icl_strings s
70 WHERE TRIM(s.value) <> ''
71 {$and}
72 LIMIT 1",
73 $args
74 ) );
75
76 return ! empty( $results );
77 }
78
79 abstract public function translationInstructions();
80
81 protected function getInstructionsLink( $domain, $search = '' ) {
82 return AdminUrl::getWPMLTMDashboardStringDomain( $domain );
83 }
84
85 protected function getInstructionsWithRegisteredStrings( $domain, $search = '' ) {
86 return sprintf(
87 /* translators: %1$s and %2$s are opening and closing HTML link tags */
88 esc_html__( 'To translate this content, go to the %1$sTranslation Dashboard%2$s.', 'woocommerce-multilingual' ),
89 '<a href="' . esc_url( $this->getInstructionsLink( $domain, $search ) ) . '">',
90 '</a>'
91 );
92 }
93
94 protected function getInstructionsWithoutRegisteredStrings( $domain, $search = '' ) {
95 return esc_html__( 'To see how to translate this text, save your changes here first.', 'woocommerce-multilingual' );
96 }
97
98 protected function getInstructions( $domain, $search = '' ) {
99 if ( $this->hasStringsInDomain( $domain, $search ) ) {
100 return $this->getInstructionsWithRegisteredStrings( $domain, $search );
101 }
102 return $this->getInstructionsWithoutRegisteredStrings( $domain, $search );
103 }
104
105 protected function getTranslationControl( $contextKey, $itemKey, $value, $domain, $stringName ) {
106 return [
107 'inputId' => $this->getInputId( $contextKey, $itemKey ),
108 'inputName' => $this->getInputName( $contextKey, $itemKey ),
109 'id' => $this->getLanguageSelectorId( $contextKey, $itemKey ),
110 'name' => $this->getLanguageSelectorName( $contextKey, $itemKey ),
111 'language' => $this->wcmlStrings->get_string_language(
112 $value,
113 $domain,
114 $stringName
115 ),
116 ];
117 }
118
119 abstract protected function getTranslationControls();
120
121 public function translationControls() {
122 $controls = $this->getTranslationControls();
123 if ( empty( $controls ) ) {
124 return;
125 }
126
127 $languageSelector = new WPML_Simple_Language_Selector( $this->sitepress );
128 foreach ( $controls as $control ) {
129 $languageSelector->render(
130 [
131 'id' => $control['id'],
132 'name' => $control['name'],
133 'selected' => $control['language'] ?? $this->sitepress->get_default_language(),
134 'show_please_select' => false,
135 'echo' => true,
136 ]
137 );
138 }
139
140 $getInputSelector = function( $controlItem ) {
141 $controlItemId = Obj::prop( 'inputId', $controlItem );
142 if ( ! empty( $controlItemId ) ) {
143 return '#' . $controlItemId;
144 }
145 $controlItemName = Obj::prop( 'inputName', $controlItem );
146 if ( ! empty( $controlItemName ) ) {
147 return "input[name='" . $controlItemName . "']";
148 }
149 return '';
150 };
151 ?>
152 <script>
153 if ( typeof window.wcmlSetTranslationControls === 'undefined' ) {
154 window.wcmlSetTranslationControls = function( $inputSelector, $languageSelector ) {
155 var input = jQuery( $inputSelector );
156 if ( input.length ) {
157 var container = input.parent();
158 container.append( '<div class="translation_controls"></div>' );
159 jQuery( $languageSelector ).prependTo( container.find( '.translation_controls' ) );
160 } else {
161 jQuery( $languageSelector ).remove();
162 }
163 }
164 }
165 <?php
166 foreach ( $controls as $control ) {
167 $inputSelector = $getInputSelector( $control );
168 if ( empty( $inputSelector ) ) {
169 continue;
170 }
171 ?>
172 wcmlSetTranslationControls( '<?php echo esc_js( $inputSelector ); ?>', '#<?php echo esc_html( $control['id'] ); ?>' );
173 <?php
174 }
175 ?>
176 </script>
177 <?php
178 }
179
180 abstract public function registerStringsOnSave();
181
182 protected function getStringLanguage( $context, $name ) {
183 return $this->wpdb->get_var( $this->wpdb->prepare(
184 "SELECT language
185 FROM {$this->wpdb->prefix}icl_strings
186 WHERE context = %s AND name = %s
187 LIMIT 1",
188 [ $context, $name ]
189 ) );
190 }
191
192 protected function replaceStringAndLanguage( $value, $context, $name, $language = null ) {
193 $previousStringLanguage = $this->getStringLanguage( $context, $name ) ?? $this->sitepress->get_default_language();
194 do_action( 'wpml_register_single_string', $context, $name, $value, false, $previousStringLanguage );
195 if ( $language ) {
196 $this->wcmlStrings->set_string_language( $value, $context, $name, $language );
197 }
198
199 $this->flushWpmlStringTranslationCache( $context, $name );
200 }
201
202 protected function flushWpmlStringTranslationCache( $domain, $name ) {
203 $key = md5( $domain . '_' . $name );
204
205 wp_cache_delete( $key, 'wpml-string-translation' );
206
207 if ( function_exists( 'wp_cache_supports' ) && wp_cache_supports( 'flush_group' ) ) {
208 wp_cache_flush_group( 'WPML_Register_String_Filter::' . $domain );
209 }
210
211 wp_cache_delete( $domain, 'WPML_Register_String_Filter' );
212
213 wp_cache_delete( \WCML_Endpoints::STRING_CONTEXT, \WCML_Endpoints::class );
214 if ( class_exists( \WPML_Endpoints_Support::class ) ) {
215 wp_cache_delete( \WPML_Endpoints_Support::STRING_CONTEXT, \WPML_Endpoints_Support::class );
216 }
217 }
218
219 abstract protected function getStringName( $contextKey, $itemKey );
220
221 protected function getInputName( $contextKey, $itemKey ) {
222 return $this->getInputId( $contextKey, $itemKey );
223 }
224
225 abstract protected function getInputId( $contextKey, $itemKey );
226
227 abstract protected function getLanguageSelectorId( $contextKey, $itemKey );
228
229 abstract protected function getLanguageSelectorName( $contextKey, $itemKey );
230
231 }
232