PluginProbe
Polylang / 3.0.2
Polylang v3.0.2
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.0.2, at modules/wpml/wpml-config.php

263 lines 7.9 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 * Constructor
30 *
31 * @since 1.0
32 */
33 public function __construct() {
34 if ( extension_loaded( 'simplexml' ) ) {
35 $this->init();
36 }
37 }
38
39 /**
40 * Access to the single instance of the class
41 *
42 * @since 1.7
43 *
44 * @return object
45 */
46 public static function instance() {
47 if ( empty( self::$instance ) ) {
48 self::$instance = new self();
49 }
50 return self::$instance;
51 }
52
53 /**
54 * Finds the wpml-config.xml files to parse and setup filters
55 *
56 * @since 1.0
57 *
58 * @return void
59 */
60 public function init() {
61 $this->xmls = array();
62
63 // Plugins
64 // 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
65 $plugins = ( is_multisite() && $sitewide_plugins = get_site_option( 'active_sitewide_plugins' ) ) && is_array( $sitewide_plugins ) ? array_keys( $sitewide_plugins ) : array();
66 $plugins = array_merge( $plugins, get_option( 'active_plugins', array() ) );
67
68 foreach ( $plugins as $plugin ) {
69 if ( file_exists( $file = WP_PLUGIN_DIR . '/' . dirname( $plugin ) . '/wpml-config.xml' ) && false !== $xml = simplexml_load_file( $file ) ) {
70 $this->xmls[ dirname( $plugin ) ] = $xml;
71 }
72 }
73
74 // Theme
75 if ( file_exists( $file = ( $template = get_template_directory() ) . '/wpml-config.xml' ) && false !== $xml = simplexml_load_file( $file ) ) {
76 $this->xmls[ get_template() ] = $xml;
77 }
78
79 // Child theme
80 if ( ( $stylesheet = get_stylesheet_directory() ) !== $template && file_exists( $file = $stylesheet . '/wpml-config.xml' ) && false !== $xml = simplexml_load_file( $file ) ) {
81 $this->xmls[ get_stylesheet() ] = $xml;
82 }
83
84 // Custom
85 if ( file_exists( $file = PLL_LOCAL_DIR . '/wpml-config.xml' ) && false !== $xml = simplexml_load_file( $file ) ) {
86 $this->xmls['Polylang'] = $xml;
87 }
88
89 if ( ! empty( $this->xmls ) ) {
90 add_filter( 'pll_copy_post_metas', array( $this, 'copy_post_metas' ), 20, 2 );
91 add_filter( 'pll_copy_term_metas', array( $this, 'copy_term_metas' ), 20, 2 );
92 add_filter( 'pll_get_post_types', array( $this, 'translate_types' ), 10, 2 );
93 add_filter( 'pll_get_taxonomies', array( $this, 'translate_taxonomies' ), 10, 2 );
94
95 foreach ( $this->xmls as $context => $xml ) {
96 $keys = $xml->xpath( 'admin-texts/key' );
97 if ( is_array( $keys ) ) {
98 foreach ( $keys as $key ) {
99 $attributes = $key->attributes();
100 $name = (string) $attributes['name'];
101
102 if ( false !== strpos( $name, '*' ) ) {
103 $pattern = '#^' . str_replace( '*', '(?:.+)', $name ) . '$#';
104 $names = preg_grep( $pattern, array_keys( wp_load_alloptions() ) );
105
106 if ( is_array( $names ) ) {
107 foreach ( $names as $_name ) {
108 $this->register_or_translate_option( $context, $_name, $key );
109 }
110 }
111 } else {
112 $this->register_or_translate_option( $context, $name, $key );
113 }
114 }
115 }
116 }
117 }
118 }
119
120 /**
121 * Adds custom fields to the list of metas to copy when creating a new translation.
122 *
123 * @since 1.0
124 *
125 * @param string[] $metas The list of custom fields to copy or synchronize.
126 * @param bool $sync True for sync, false for copy.
127 * @return string[] The list of custom fields to copy or synchronize.
128 */
129 public function copy_post_metas( $metas, $sync ) {
130 foreach ( $this->xmls as $xml ) {
131 $cfs = $xml->xpath( 'custom-fields/custom-field' );
132 if ( is_array( $cfs ) ) {
133 foreach ( $cfs as $cf ) {
134 $attributes = $cf->attributes();
135 if ( 'copy' == $attributes['action'] || ( ! $sync && in_array( $attributes['action'], array( 'translate', 'copy-once' ) ) ) ) {
136 $metas[] = (string) $cf;
137 } else {
138 $metas = array_diff( $metas, array( (string) $cf ) );
139 }
140 }
141 }
142 }
143 return $metas;
144 }
145
146 /**
147 * Adds term metas to the list of metas to copy when creating a new translation.
148 *
149 * @since 2.6
150 *
151 * @param string[] $metas The list of term metas to copy or synchronize.
152 * @param bool $sync True for sync, false for copy.
153 * @return string[] The list of term metas to copy or synchronize.
154 */
155 public function copy_term_metas( $metas, $sync ) {
156 foreach ( $this->xmls as $xml ) {
157 $cfs = $xml->xpath( 'custom-term-fields/custom-term-field' );
158 if ( is_array( $cfs ) ) {
159 foreach ( $cfs as $cf ) {
160 $attributes = $cf->attributes();
161 if ( 'copy' == $attributes['action'] || ( ! $sync && in_array( $attributes['action'], array( 'translate', 'copy-once' ) ) ) ) {
162 $metas[] = (string) $cf;
163 } else {
164 $metas = array_diff( $metas, array( (string) $cf ) );
165 }
166 }
167 }
168 }
169 return $metas;
170 }
171
172 /**
173 * Language and translation management for custom post types.
174 *
175 * @since 1.0
176 *
177 * @param string[] $types The list of post type names for which Polylang manages language and translations.
178 * @param bool $hide True when displaying the list in Polylang settings.
179 * @return string[] The list of post type names for which Polylang manages language and translations.
180 */
181 public function translate_types( $types, $hide ) {
182 foreach ( $this->xmls as $xml ) {
183 $pts = $xml->xpath( 'custom-types/custom-type' );
184 if ( is_array( $pts ) ) {
185 foreach ( $pts as $pt ) {
186 $attributes = $pt->attributes();
187 if ( 1 == $attributes['translate'] && ! $hide ) {
188 $types[ (string) $pt ] = (string) $pt;
189 } else {
190 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
191 }
192 }
193 }
194 }
195 return $types;
196 }
197
198 /**
199 * Language and translation management for custom taxonomies.
200 *
201 * @since 1.0
202 *
203 * @param string[] $taxonomies The list of taxonomy names for which Polylang manages language and translations.
204 * @param bool $hide True when displaying the list in Polylang settings.
205 * @return string[] The list of taxonomy names for which Polylang manages language and translations.
206 */
207 public function translate_taxonomies( $taxonomies, $hide ) {
208 foreach ( $this->xmls as $xml ) {
209 $taxos = $xml->xpath( 'taxonomies/taxonomy' );
210 if ( is_array( $taxos ) ) {
211 foreach ( $taxos as $tax ) {
212 $attributes = $tax->attributes();
213 if ( 1 == $attributes['translate'] && ! $hide ) {
214 $taxonomies[ (string) $tax ] = (string) $tax;
215 } else {
216 unset( $taxonomies[ (string) $tax ] ); // the theme/plugin author decided what to do with the taxonomy so don't allow the user to change this
217 }
218 }
219 }
220 }
221 return $taxonomies;
222 }
223
224 /**
225 * Registers or translates the strings for an option
226 *
227 * @since 2.8
228 *
229 * @param string $context The group in which the strings will be registered.
230 * @param string $name Option name.
231 * @param object $key XML node.
232 * @return void
233 */
234 protected function register_or_translate_option( $context, $name, $key ) {
235 $option_keys = $this->xml_to_array( $key );
236 new PLL_Translate_Option( $name, reset( $option_keys ), array( 'context' => $context ) );
237 }
238
239 /**
240 * Recursively transforms xml nodes to an array, ready for PLL_Translate_Option.
241 *
242 * @since 2.9
243 *
244 * @param object $key XML node.
245 * @param array $arr Array of option keys to translate.
246 * @return array
247 */
248 protected function xml_to_array( $key, &$arr = array() ) {
249 $attributes = $key->attributes();
250 $name = (string) $attributes['name'];
251 $children = $key->children();
252
253 if ( count( $children ) ) {
254 foreach ( $children as $child ) {
255 $arr[ $name ] = $this->xml_to_array( $child, $arr[ $name ] );
256 }
257 } else {
258 $arr[ $name ] = true; // Multiline as in WPML.
259 }
260 return $arr;
261 }
262 }
263