PluginProbe
Polylang / 3.2.8
Polylang v3.2.8
3.8.9 3.8.8 3.8.7 3.8.6 3.8.5 3.8.4 3.8.3 2.7 2.7.0.1 2.7.1 2.7.2 2.7.3 2.7.4 2.8 2.8.1 2.8.2 2.8.3 2.8.4 2.9 2.9.1 2.9.2 3.0 3.0.1 3.0.2 3.0.3 All 233 releases
polylang / modules / wpml / wpml-config.php

wpml-config.php in Polylang 3.2.8, at modules/wpml/wpml-config.php

304 lines 8.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * @package Polylang
4 */
5
6 /**
7 * Reads and interprets the file wpml-config.xml
8 * See http://wpml.org/documentation/support/language-configuration-files/
9 * The language switcher configuration is not interpreted
10 *
11 * @since 1.0
12 */
13 class PLL_WPML_Config {
14 /**
15 * Singleton instance
16 *
17 * @var PLL_WPML_Config
18 */
19 protected static $instance;
20
21 /**
22 * The content of all read xml files.
23 *
24 * @var SimpleXMLElement[]
25 */
26 protected $xmls;
27
28 /**
29 * The list of xml files.
30 *
31 * @var string[]
32 */
33 protected $files;
34
35 /**
36 * Constructor
37 *
38 * @since 1.0
39 */
40 public function __construct() {
41 if ( extension_loaded( 'simplexml' ) ) {
42 $this->init();
43 }
44 }
45
46 /**
47 * Access to the single instance of the class
48 *
49 * @since 1.7
50 *
51 * @return PLL_WPML_Config
52 */
53 public static function instance() {
54 if ( empty( self::$instance ) ) {
55 self::$instance = new self();
56 }
57 return self::$instance;
58 }
59
60 /**
61 * Finds the wpml-config.xml files to parse and setup filters
62 *
63 * @since 1.0
64 *
65 * @return void
66 */
67 public function init() {
68 $this->xmls = array();
69 $files = $this->get_files();
70
71 if ( ! empty( $files ) ) {
72
73 // Read all files.
74 if ( extension_loaded( 'simplexml' ) ) {
75 foreach ( $files as $context => $file ) {
76 $xml = simplexml_load_file( $file );
77 if ( false !== $xml ) {
78 $this->xmls[ $context ] = $xml;
79 }
80 }
81 }
82 }
83
84 if ( ! empty( $this->xmls ) ) {
85 add_filter( 'pll_copy_post_metas', array( $this, 'copy_post_metas' ), 20, 2 );
86 add_filter( 'pll_copy_term_metas', array( $this, 'copy_term_metas' ), 20, 2 );
87 add_filter( 'pll_get_post_types', array( $this, 'translate_types' ), 10, 2 );
88 add_filter( 'pll_get_taxonomies', array( $this, 'translate_taxonomies' ), 10, 2 );
89
90 foreach ( $this->xmls as $context => $xml ) {
91 $keys = $xml->xpath( 'admin-texts/key' );
92 if ( is_array( $keys ) ) {
93 foreach ( $keys as $key ) {
94 $attributes = $key->attributes();
95 $name = (string) $attributes['name'];
96
97 if ( false !== strpos( $name, '*' ) ) {
98 $pattern = '#^' . str_replace( '*', '(?:.+)', $name ) . '$#';
99 $names = preg_grep( $pattern, array_keys( wp_load_alloptions() ) );
100
101 if ( is_array( $names ) ) {
102 foreach ( $names as $_name ) {
103 $this->register_or_translate_option( $context, $_name, $key );
104 }
105 }
106 } else {
107 $this->register_or_translate_option( $context, $name, $key );
108 }
109 }
110 }
111 }
112 }
113 }
114
115 /**
116 * Get all wpml-config.xml files in plugins, theme, child theme and Polylang custom directory.
117 *
118 * @since 3.1
119 *
120 * @return array
121 */
122 public function get_files() {
123
124 if ( ! empty( $this->files ) ) {
125 return $this->files;
126 }
127
128 $files = array();
129
130 // Plugins
131 // Don't forget sitewide active plugins thanks to Reactorshop http://wordpress.org/support/topic/polylang-and-yoast-seo-plugin/page/2?replies=38#post-4801829
132 $plugins = ( is_multisite() && $sitewide_plugins = get_site_option( 'active_sitewide_plugins' ) ) && is_array( $sitewide_plugins ) ? array_keys( $sitewide_plugins ) : array();
133 $plugins = array_merge( $plugins, get_option( 'active_plugins', array() ) );
134
135 foreach ( $plugins as $plugin ) {
136 if ( file_exists( $file = WP_PLUGIN_DIR . '/' . dirname( $plugin ) . '/wpml-config.xml' ) ) {
137 $files[ dirname( $plugin ) ] = $file;
138 }
139 }
140
141 // Theme
142 if ( file_exists( $file = ( $template = get_template_directory() ) . '/wpml-config.xml' ) ) {
143 $files[ get_template() ] = $file;
144 }
145
146 // Child theme
147 if ( ( $stylesheet = get_stylesheet_directory() ) !== $template && file_exists( $file = $stylesheet . '/wpml-config.xml' ) ) {
148 $files[ get_stylesheet() ] = $file;
149 }
150
151 // Custom
152 if ( file_exists( $file = PLL_LOCAL_DIR . '/wpml-config.xml' ) ) {
153 $files['Polylang'] = $file;
154 }
155
156 $this->files = $files;
157
158 return $files;
159 }
160
161 /**
162 * Adds custom fields to the list of metas to copy when creating a new translation.
163 *
164 * @since 1.0
165 *
166 * @param string[] $metas The list of custom fields to copy or synchronize.
167 * @param bool $sync True for sync, false for copy.
168 * @return string[] The list of custom fields to copy or synchronize.
169 */
170 public function copy_post_metas( $metas, $sync ) {
171 foreach ( $this->xmls as $xml ) {
172 $cfs = $xml->xpath( 'custom-fields/custom-field' );
173 if ( is_array( $cfs ) ) {
174 foreach ( $cfs as $cf ) {
175 $attributes = $cf->attributes();
176 if ( 'copy' == $attributes['action'] || ( ! $sync && in_array( $attributes['action'], array( 'translate', 'copy-once' ) ) ) ) {
177 $metas[] = (string) $cf;
178 } else {
179 $metas = array_diff( $metas, array( (string) $cf ) );
180 }
181 }
182 }
183 }
184 return $metas;
185 }
186
187 /**
188 * Adds term metas to the list of metas to copy when creating a new translation.
189 *
190 * @since 2.6
191 *
192 * @param string[] $metas The list of term metas to copy or synchronize.
193 * @param bool $sync True for sync, false for copy.
194 * @return string[] The list of term metas to copy or synchronize.
195 */
196 public function copy_term_metas( $metas, $sync ) {
197 foreach ( $this->xmls as $xml ) {
198 $cfs = $xml->xpath( 'custom-term-fields/custom-term-field' );
199 if ( is_array( $cfs ) ) {
200 foreach ( $cfs as $cf ) {
201 $attributes = $cf->attributes();
202 if ( 'copy' == $attributes['action'] || ( ! $sync && in_array( $attributes['action'], array( 'translate', 'copy-once' ) ) ) ) {
203 $metas[] = (string) $cf;
204 } else {
205 $metas = array_diff( $metas, array( (string) $cf ) );
206 }
207 }
208 }
209 }
210 return $metas;
211 }
212
213 /**
214 * Language and translation management for custom post types.
215 *
216 * @since 1.0
217 *
218 * @param string[] $types The list of post type names for which Polylang manages language and translations.
219 * @param bool $hide True when displaying the list in Polylang settings.
220 * @return string[] The list of post type names for which Polylang manages language and translations.
221 */
222 public function translate_types( $types, $hide ) {
223 foreach ( $this->xmls as $xml ) {
224 $pts = $xml->xpath( 'custom-types/custom-type' );
225 if ( is_array( $pts ) ) {
226 foreach ( $pts as $pt ) {
227 $attributes = $pt->attributes();
228 if ( 1 == $attributes['translate'] && ! $hide ) {
229 $types[ (string) $pt ] = (string) $pt;
230 } else {
231 unset( $types[ (string) $pt ] ); // The theme/plugin author decided what to do with the post type so don't allow the user to change this
232 }
233 }
234 }
235 }
236 return $types;
237 }
238
239 /**
240 * Language and translation management for custom taxonomies.
241 *
242 * @since 1.0
243 *
244 * @param string[] $taxonomies The list of taxonomy names for which Polylang manages language and translations.
245 * @param bool $hide True when displaying the list in Polylang settings.
246 * @return string[] The list of taxonomy names for which Polylang manages language and translations.
247 */
248 public function translate_taxonomies( $taxonomies, $hide ) {
249 foreach ( $this->xmls as $xml ) {
250 $taxos = $xml->xpath( 'taxonomies/taxonomy' );
251 if ( is_array( $taxos ) ) {
252 foreach ( $taxos as $tax ) {
253 $attributes = $tax->attributes();
254 if ( 1 == $attributes['translate'] && ! $hide ) {
255 $taxonomies[ (string) $tax ] = (string) $tax;
256 } else {
257 unset( $taxonomies[ (string) $tax ] ); // the theme/plugin author decided what to do with the taxonomy so don't allow the user to change this
258 }
259 }
260 }
261 }
262 return $taxonomies;
263 }
264
265 /**
266 * Registers or translates the strings for an option
267 *
268 * @since 2.8
269 *
270 * @param string $context The group in which the strings will be registered.
271 * @param string $name Option name.
272 * @param SimpleXMLElement $key XML node.
273 * @return void
274 */
275 protected function register_or_translate_option( $context, $name, $key ) {
276 $option_keys = $this->xml_to_array( $key );
277 new PLL_Translate_Option( $name, reset( $option_keys ), array( 'context' => $context ) );
278 }
279
280 /**
281 * Recursively transforms xml nodes to an array, ready for PLL_Translate_Option.
282 *
283 * @since 2.9
284 *
285 * @param SimpleXMLElement $key XML node.
286 * @param array $arr Array of option keys to translate.
287 * @return array
288 */
289 protected function xml_to_array( $key, &$arr = array() ) {
290 $attributes = $key->attributes();
291 $name = (string) $attributes['name'];
292 $children = $key->children();
293
294 if ( count( $children ) ) {
295 foreach ( $children as $child ) {
296 $arr[ $name ] = $this->xml_to_array( $child, $arr[ $name ] );
297 }
298 } else {
299 $arr[ $name ] = true; // Multiline as in WPML.
300 }
301 return $arr;
302 }
303 }
304