PluginProbe
wpForo Forum / 2.3.0
wpForo Forum v2.3.0
3.1.5 3.1.4 3.1.2 3.1.1 3.1.0 3.0.9 3.0.8 3.0.7 trunk 1.0.0 1.0.1 1.0.2 1.1.0 1.1.1 1.1.2 1.2.0 1.3.0 1.3.1 1.4.0 1.4.1 1.4.10 1.4.11 1.4.12 1.4.13 1.4.2 All 137 releases
wpforo / classes / Phrases.php

Phrases.php in wpForo Forum 2.3.0, at classes/Phrases.php

405 lines 13.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace wpforo\classes;
4
5 use wpforo\admin\listtables\Phrases as PhrasesListTable;
6
7 // Exit if accessed directly
8 if( ! defined( 'ABSPATH' ) ) exit;
9
10 class Phrases {
11 public $phrases;
12 public $__phrases;
13 public $list_table;
14 public $langid;
15
16 public function __construct() {
17 add_action('wpforo_after_change_board', function(){
18 $this->init();
19 });
20 }
21
22 private function init() {
23 if( WPF()->is_installed() ) {
24 $this->langid = $this->get_current_langid();
25 if( is_admin() ) $this->init_list_table();
26 if( $phrases = $this->get_phrases() ) {
27 foreach( $phrases as $phrase ) {
28 $this->phrases[ addslashes( strtolower( (string) $phrase['phrase_key'] ) ) ] = $phrase['phrase_value'];
29 $this->__phrases[ addslashes( strtolower( (string) $phrase['phrase_key'] ) ) ] = wpforo_phrase( $phrase['phrase_key'], false );
30 }
31 add_action( 'wp_ajax_nopriv_wpforo_get_phrases', [ $this, 'ajax_get_phrases' ] );
32 add_action( 'wp_ajax_wpforo_get_phrases', [ $this, 'ajax_get_phrases' ] );
33 }
34 }
35 }
36
37 public function init_list_table() {
38 if( wpfval( $_GET, 'page' ) === wpforo_prefix_slug( 'phrases' ) ) {
39 $this->list_table = new PhrasesListTable();
40 $this->list_table->prepare_items();
41 }
42 }
43
44 function add( $args = [], $clear_cache = true ) {
45 if( empty( $args ) && empty( $_REQUEST['phrase'] ) ) return false;
46 if( empty( $args ) && ! empty( $_REQUEST['phrase'] ) ) $args = $_REQUEST['phrase'];
47
48 if( empty( $args['langid'] ) ) $args['langid'] = $this->langid;
49 if( empty( $args['package'] ) ) $args['package'] = 'wpforo';
50 $sql = WPF()->db->prepare(
51 "INSERT IGNORE INTO `" . WPF()->tables->phrases . "`
52 (`langid`, `phrase_key`, `phrase_value`, `package`)
53 VALUES (%d, %s, %s, %s)",
54 intval( $args['langid'] ),
55 sanitize_text_field( stripslashes( (string) $args['key'] ) ),
56 sanitize_text_field( stripslashes( (string) $args['value'] ) ),
57 stripslashes( (string) $args['package'] )
58 );
59 if( false !== WPF()->db->query( $sql ) ) {
60 $phraseid = WPF()->db->insert_id;
61 WPF()->notice->add( 'Phrase successfully added', 'success' );
62 if( $clear_cache ) $this->clear_cache();
63
64 return $phraseid;
65 }
66 WPF()->notice->add( 'Phrase add error', 'error' );
67
68 return false;
69 }
70
71 function edit( $args = [] ) {
72 if( ! $args && ! empty( $_REQUEST['phrases'] ) ) $args = $_REQUEST['phrases'];
73 if( ! empty( $args ) ) {
74 foreach( $args as $phraseid => $phrase ) {
75 WPF()->db->update(
76 WPF()->tables->phrases,
77 [ 'phrase_value' => sanitize_text_field( stripslashes( (string) $phrase ) ) ],
78 [ 'phraseid' => intval( $phraseid ) ],
79 [ '%s' ],
80 [ '%d' ]
81 );
82 }
83 $this->clear_cache();
84 WPF()->notice->add( 'Phrase successfully updates', 'success' );
85
86 return true;
87 }
88
89 WPF()->notice->add( 'Phrase update error', 'error' );
90
91 return false;
92 }
93
94 function get_phrase( $phraseid ) {
95 $sql = 'SELECT * FROM ' . WPF()->tables->phrases . ' WHERE `phraseid` =' . intval( $phraseid );
96
97 return WPF()->db->get_row( $sql, ARRAY_A );
98 }
99
100 function get_phrases( $args = [], &$items_count = 0, $count = false ) {
101 $default = [
102 'include' => [], // array( 2, 10, 25 )
103 'exclude' => [], // array( 2, 10, 25 )
104 'langid' => $this->langid,
105 'package' => [],
106
107 'orderby' => 'phraseid',
108 'order' => 'ASC', // ASC DESC
109 'offset' => '', // this use when you give row_count
110 'row_count' => '',
111 ];
112
113 $args = wpforo_parse_args( $args, $default );
114
115 $key = WPF()->tables->phrases . substr( md5( serialize( $args ) ), 0, 10 );
116
117 extract( $args, EXTR_OVERWRITE );
118
119 $package = wpforo_parse_args( $package );
120 $include = wpforo_parse_args( $include );
121 $exclude = wpforo_parse_args( $exclude );
122
123 $wheres = [];
124
125 if( ! empty( $package ) ) $wheres[] = "`package` IN('" . implode( "','", array_map( 'esc_sql', array_map( 'sanitize_text_field', $package ) ) ) . "')";
126 if( ! empty( $include ) ) $wheres[] = "`phraseid` IN(" . implode( ', ', array_map( 'intval', $include ) ) . ")";
127 if( ! empty( $exclude ) ) $wheres[] = "`phraseid` NOT IN(" . implode( ', ', array_map( 'intval', $exclude ) ) . ")";
128 if( ! is_null( $langid ) ) $wheres[] = "`langid` = " . intval( $langid );
129
130 $sql = "SELECT * FROM `" . WPF()->tables->phrases . "`";
131 if( ! empty( $wheres ) ) {
132 $sql .= " WHERE " . implode( " AND ", $wheres );
133 }
134
135 if( $count ) {
136 $item_count_sql = preg_replace( '#SELECT.+?FROM#isu', 'SELECT count(*) FROM', $sql );
137 if( $item_count_sql ) $items_count = WPF()->db->get_var( $item_count_sql );
138 }
139
140 $sql .= esc_sql( " ORDER BY `$orderby` " . $order );
141
142 if( $row_count != '' && $offset == '' ) { // If you give only row_count this if fixed problam
143 $offset = $row_count;
144 $row_count = '';
145 }
146 $sql .= $offset != '' ? esc_sql( ' LIMIT ' . $offset ) : '';
147 $sql .= $row_count != '' ? esc_sql( ', ' . $row_count ) : '';
148
149 if( false === ( $phrases = get_transient( 'wpforo_get_phrases_' . $key ) ) ) {
150 $phrases = WPF()->db->get_results( $sql, ARRAY_A );
151 set_transient( 'wpforo_get_phrases_' . $key, $phrases, 60 * 60 * 24 );
152 }
153
154 return get_transient( 'wpforo_get_phrases_' . $key );
155 }
156
157 function search( $needle = '', $fields = [ 'phrase_key', 'phrase_value' ] ) {
158 $fields = (array) $fields;
159 if( ! $needle || empty( $fields ) ) return [];
160
161 $needle = substr( sanitize_text_field( (string) $needle ), 0, 60 );
162 $sql = "SELECT `phraseid` FROM " . WPF()->tables->phrases;
163 $wheres = [];
164 foreach( $fields as $field ) {
165 $field = sanitize_text_field( $field );
166 $wheres[] = "`" . esc_sql( $field ) . "` LIKE '%" . esc_sql( $needle ) . "%'";
167 }
168 if( $wheres ) $sql .= ' WHERE ' . implode( ' OR ', $wheres );
169
170 return WPF()->db->get_col( $sql );
171 }
172
173 public function xml_import( $xmlfile ) {
174 $file = WPFORO_DIR . '/admin/assets/xml/' . $xmlfile;
175 if( file_exists( $file ) && function_exists( 'xml_parser_create' ) ) {
176 $xr = xml_parser_create();
177 $fp = fopen( $file, "r" );
178 $xml = fread( $fp, filesize( $file ) );
179
180 xml_parser_set_option( $xr, XML_OPTION_CASE_FOLDING, 1 );
181 xml_parse_into_struct( $xr, $xml, $vals );
182 xml_parser_free( $xr );
183
184 delete_transient( 'wpforo_get_phrases' );
185
186 if( ! empty( $vals ) && isset( $vals[0]['tag'] ) && $vals[0]['tag'] == 'LANGUAGE' && isset( $vals[0]['attributes']['LANGUAGE'] ) && $vals[0]['attributes']['LANGUAGE'] ) {
187
188 $sql = "SELECT `langid` FROM `" . WPF()->tables->languages . "` WHERE `name` LIKE '" . esc_sql( sanitize_text_field( $vals[0]['attributes']['LANGUAGE'] ) ) . "'";
189 $langid = WPF()->db->get_var( $sql );
190
191 if( ! $langid ) {
192 $sql = "INSERT INTO `" . WPF()->tables->languages . "` (`name`) VALUES ( '" . esc_sql( sanitize_text_field( $vals[0]['attributes']['LANGUAGE'] ) ) . "' )";
193 if( WPF()->db->query( $sql ) ) {
194 $langid = WPF()->db->insert_id;
195 $this->set_language_status( $langid );
196 }
197 }
198
199 if( $langid ) {
200 foreach( $vals as $val ) {
201 if( isset( $val['tag'] ) && $val['tag'] == 'PHRASE' && isset( $val['attributes']['NAME'] ) && trim( (string) $val['attributes']['NAME'] ) && isset( $val['value'] ) && trim( (string) $val['value'] ) ) {
202 $sql = "INSERT IGNORE INTO `" . WPF()->tables->phrases . "`
203 (`phraseid`, `langid`, `phrase_key`, `phrase_value`)
204 VALUES( NULL,
205 '" . intval( $langid ) . "',
206 '" . esc_sql( stripslashes( htmlspecialchars_decode( (string) $val['attributes']['NAME'], ENT_QUOTES ) ) ) . "',
207 '" . esc_sql( stripslashes( htmlspecialchars_decode( (string) $val['value'], ENT_QUOTES ) ) ) . "')";
208 WPF()->db->query( $sql );
209 }
210 }
211
212 return $langid;
213 }
214 }
215 }
216
217 return false;
218 }
219
220 function add_lang() {
221 if( is_array( $_FILES['add_lang']['name'] ) && ! empty( $_FILES['add_lang']['name'] ) && isset( $_FILES['add_lang']['name']['xml'] ) ) {
222 if( ! is_dir( WPFORO_DIR . '/admin/xml' ) ) wp_mkdir_p( WPFORO_DIR . '/admin/xml' );
223
224 $error = $_FILES['add_lang']['error']['xml'];
225
226 if( $error ) {
227 $error = wpforo_file_upload_error( $error );
228 WPF()->notice->add( $error, 'error' );
229
230 return false;
231 }
232
233 $xmlfile = strtolower( sanitize_file_name( $_FILES['add_lang']['name']['xml'] ) );
234 $ext = strtolower( (string) pathinfo( $xmlfile, PATHINFO_EXTENSION ) );
235 if( $ext === 'xml' ) {
236 if( move_uploaded_file( sanitize_text_field( $_FILES['add_lang']['tmp_name']['xml'] ), WPFORO_DIR . '/admin/assets/xml/' . $xmlfile ) ) {
237 if( $langid = $this->xml_import( $xmlfile ) ) {
238 delete_transient( 'wpforo_get_phrases' );
239 WPF()->notice->add( 'New language successfully added and changed wpforo language to new language', 'success' );
240
241 return $langid;
242 }
243 }
244 } else {
245 WPF()->notice->add( 'Incorrect file type', 'error' );
246
247 return false;
248 }
249 }
250
251 WPF()->notice->add( 'Can\'t add new language', 'error' );
252
253 return false;
254 }
255
256 public function set_language_status( $langid ){
257 if( WPF()->db->update(
258 WPF()->tables->languages,
259 ['status' => 1],
260 ['langid' => $langid],
261 ['%d'],
262 ['%d']
263 )){
264 return false !== WPF()->db->query( WPF()->db->prepare(
265 "UPDATE `" . WPF()->tables->languages . "` SET `status` = 0 WHERE `langid` <> %d",
266 $langid
267 ));
268 }
269
270 return false;
271 }
272
273 public function get_current_langid(){
274 $langid = (int) WPF()->db->get_var(
275 "SELECT `langid` FROM `" . WPF()->tables->languages . "` WHERE `status` = 1 ORDER BY `langid` DESC"
276 );
277 if( !$langid ){
278 $langid = (int) WPF()->db->get_var(
279 "SELECT `langid` FROM `" . WPF()->tables->languages . "` ORDER BY `langid` DESC"
280 );
281 }
282
283 return $langid;
284 }
285
286 public function get_language( $langid ) {
287 return WPF()->db->get_row(
288 WPF()->db->prepare(
289 "SELECT * FROM `" . WPF()->tables->languages . "` WHERE `langid` = %d", $langid
290 ),
291 ARRAY_A
292 );
293 }
294
295 function get_languages() {
296 return WPF()->db->get_results( "SELECT * FROM `" . WPF()->tables->languages . "`", ARRAY_A );
297 }
298
299 function show_lang_list( $selected = null ) {
300 if( $langs = $this->get_languages() ) {
301 if( ! $selected ) $selected = $this->langid;
302 $selected = intval( $selected );
303 foreach( $langs as $lang ) {
304 $lang['langid'] = intval( $lang['langid'] );
305 printf(
306 '<option value="%1$d" %2$s>%3$s</option>',
307 $lang['langid'],
308 ( $lang['langid'] === $selected ) ? 'selected' : '',
309 esc_html( $lang['name'] )
310 );
311 }
312 }
313 }
314
315 public function get_distinct_packages() {
316 $sql = "SELECT DISTINCT `package` as packages FROM `" . WPF()->tables->phrases . "`";
317
318 return WPF()->db->get_col( $sql );
319 }
320
321 function clear_cache() {
322 WPF()->db->query( "DELETE FROM " . WPF()->db->options . " WHERE `option_name` LIKE '%_wpforo_get_phrases_%'" );
323 }
324
325 public function crawl_phrases( $pattern = null ) {
326 if( is_null( $pattern ) ) $pattern = dirname( WPFORO_DIR ) . DIRECTORY_SEPARATOR . 'wpforo*';
327 if( $matches = glob( $pattern ) ) {
328 $package = 'wpforo';
329 if( preg_match( '#[/\\\]wp-content[/\\\]plugins[/\\\]([^/\\\]+)[/\\\]#isu', (string) $pattern, $p ) ) {
330 $package = $p[1];
331 }
332 foreach( $matches as $match ) {
333 if( is_dir( $match ) ) {
334 $this->crawl_phrases( $match . DIRECTORY_SEPARATOR . '*' );
335 } elseif( is_file( $match ) && preg_match( '#\.(php|js)$#iu', (string) $match ) ) {
336 if( $file_content = wpforo_get_file_content( $match ) ) {
337 if( preg_match_all( '#(?:wpforo_phrase|WPF\(\)->notice->add|wpforo_notice_show|wpforo_load_show)\([\r\n\t\s\0]*[\'\"](?P<phrase_key>.+?)[\'\"][\r\n\t\s\0,)]+#isu', $file_content, $phrases, PREG_SET_ORDER ) ) {
338 foreach( $phrases as $phrase ) {
339 if( $phrase['phrase_key'] ) {
340 $args = [
341 'key' => $phrase['phrase_key'],
342 'value' => __( $phrase['phrase_key'], $package ),
343 'package' => $package,
344 ];
345 $this->add( $args, false );
346 }
347 }
348 }
349 }
350 }
351
352 }
353 }
354 }
355
356 public function rebuild_file_wpf_phrases_php() {
357 $file_path = wpforo_fix_dir_sep( WPFORO_DIR . '/includes/phrases.php' );
358 if( WPF()->is_installed() && $file_content = wpforo_get_file_content( $file_path ) ) {
359
360 if( $phrases = $this->get_phrases( [ 'package' => 'wpforo' ] ) ) {
361 foreach( $phrases as $phrase ) {
362 $key = addcslashes( $phrase['phrase_key'], '"' );
363
364 if( ! preg_match( '#[\'\"]' . preg_quote( $key ) . '[\'\"][\r\n\t\s\0]*=>[\r\n\t\s\0]*__\([\r\n\t\s\0]*[\'\"]' . preg_quote( $key ) . '[\'\"][\r\n\t\s\0]*,[\r\n\t\s\0]*[\'\"]wpforo[\'\"][\r\n\t\s\0]*\)#isu', (string) $file_content ) ) {
365 $file_content = preg_replace( '#(\$wpforo_phrases[\r\n\t\s\0]*=[\r\n\t\s\0]*array\([\r\n\t\s\0]*)#iu', '$1"' . $key . '" => __("' . $key . '", "wpforo"),' . "\r\n\t", (string) $file_content );
366 }
367 }
368
369 wpforo_write_file( $file_path, $file_content );
370 }
371
372 }
373 }
374
375 public function rebuild_file_english_xml() {
376 $file_path = wpforo_fix_dir_sep( WPFORO_DIR . '/admin/assets/xml/english.xml' );
377 if( WPF()->is_installed() && $file_content = wpforo_get_file_content( $file_path ) ) {
378
379 if( $phrases = $this->get_phrases( [ 'package' => 'wpforo' ] ) ) {
380 foreach( $phrases as $phrase ) {
381 $key = htmlspecialchars( $phrase['phrase_key'], ENT_QUOTES );
382
383 if( ! preg_match( '#<phrase[^<>]*?name=[\'\"]' . preg_quote( $key ) . '[\'\"][^<>]*?>[^<>]*?<\!\[CDATA\[' . preg_quote( $key ) . '\]\]>[^<>]*?</phrase>#isu', (string) $file_content ) ) {
384 $file_content = preg_replace( '#([\r\n\t\s\0]*</language>)#iu', "\r\n\t" . '<phrase name="' . $key . '"><![CDATA[' . $key . ']]></phrase>$1', (string) $file_content );
385 }
386 }
387
388 wpforo_write_file( $file_path, $file_content );
389 }
390
391 }
392 }
393
394 public function ajax_get_phrases() {
395 wpforo_verify_nonce( 'wpforo_get_phrases' );
396 echo json_encode( $this->__phrases );
397 exit();
398 }
399
400 public function get_wpforo_phrases_inline_js() {
401 return 'window.wpforo_phrases = ' . json_encode( $this->__phrases ) . ';';
402 }
403
404 }
405