PageRenderTime 52ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-content/plugins/wpglobus/includes/class-wpglobus-filters.php

https://gitlab.com/vovanduc/dainghia
PHP | 869 lines | 343 code | 123 blank | 403 comment | 82 complexity | a3e62771e81448068c3132688c71d7aa MD5 | raw file
Possible License(s): GPL-2.0, Apache-2.0, BSD-3-Clause
  1. <?php
  2. /**
  3. * Filters and actions
  4. * Only methods here. The add_filter calls are in the Controller
  5. * @package WPGlobus
  6. */
  7. /**
  8. * Class WPGlobus_Filters
  9. */
  10. class WPGlobus_Filters {
  11. /** @var string[] Meta keys where data can be multilingual */
  12. protected static $multilingual_meta_keys = array();
  13. /**
  14. * This is the basic filter used to extract the text portion in the current language from a string.
  15. * Applied to the main WP texts, such as post title, content and excerpt.
  16. *
  17. * @param string $text
  18. *
  19. * @return string
  20. */
  21. public static function filter__text( $text ) {
  22. return WPGlobus_Core::text_filter(
  23. $text,
  24. WPGlobus::Config()->language,
  25. null,
  26. WPGlobus::Config()->default_language
  27. );
  28. }
  29. /**
  30. * This filter is needed to display correctly the posts with the '--- MORE ---' separator
  31. * in archives.
  32. * Without it, the post content is truncated at the beginning of <!--more-->, thus keeping
  33. * only the first language.
  34. * *
  35. * 'the_posts' filter is used by @see get_posts(), which is commonly used in all sorts of places,
  36. * including, for instance, @see wp_get_associated_nav_menu_items while deleting a post.
  37. * So, to minimize potential side effects, we limit the scope to main queries, or
  38. * when the 'wpglobus_force_filter__the_posts' is set
  39. * (@see WPGlobus_QA::_test_get_posts for example).
  40. *
  41. * @param array $posts
  42. * @param WP_Query $query
  43. *
  44. * @return array
  45. * @since 1.0.14
  46. */
  47. public static function filter__the_posts( $posts, &$query ) {
  48. if ( $query->is_main_query() || $query->get( 'wpglobus_force_filter__the_posts' ) ) {
  49. foreach ( $posts as $post ) {
  50. WPGlobus_Core::translate_wp_post( $post, WPGlobus::Config()->language,
  51. WPGlobus::RETURN_IN_DEFAULT_LANGUAGE );
  52. }
  53. }
  54. return $posts;
  55. }
  56. /**
  57. * This is similar to the @see filter__text filter,
  58. * but it returns text in the DEFAULT language.
  59. *
  60. * @param string $text
  61. *
  62. * @return string
  63. * @since 1.0.8
  64. */
  65. public static function filter__text_default_language( $text ) {
  66. return WPGlobus_Core::text_filter(
  67. $text,
  68. WPGlobus::Config()->default_language,
  69. null,
  70. WPGlobus::Config()->default_language
  71. );
  72. }
  73. /**
  74. * Filter @see get_terms
  75. * @scope admin
  76. * @scope front
  77. *
  78. * @param string[]|object[] $terms
  79. *
  80. * @return array
  81. */
  82. public static function filter__get_terms( Array $terms ) {
  83. /**
  84. * @todo Example of a "stopper" filter
  85. * if ( apply_filters( 'wpglobus_do_filter__get_terms', true ) ) {}
  86. * Because it might affect the performance, this is a to-do for now.
  87. */
  88. foreach ( $terms as &$_term ) {
  89. WPGlobus_Core::translate_term( $_term, WPGlobus::Config()->language );
  90. }
  91. unset( $_term );
  92. reset( $terms );
  93. return $terms;
  94. }
  95. /**
  96. * Filter @see get_the_terms
  97. * @scope admin
  98. *
  99. * @param object[]|WP_Error $terms List of attached terms, or WP_Error on failure.
  100. *
  101. * @return array
  102. */
  103. public static function filter__get_the_terms( $terms ) {
  104. /**
  105. * @internal 15.01.31
  106. * Theoretically, we should not have this filter because @see get_the_terms
  107. * calls @see wp_get_object_terms, which is already filtered.
  108. * However, there is a case when the terms are retrieved from @see get_object_term_cache,
  109. * and when we do a Quick Edit / inline-save, we ourselves write raw terms to the cache.
  110. * As of now, we know only one such case, so we activate this filter only in admin,
  111. * and only on the 'single_row' call
  112. * @todo Keep watching this
  113. */
  114. if ( ! is_wp_error( $terms ) && WPGlobus_Utils::is_function_in_backtrace( 'single_row' ) ) {
  115. foreach ( $terms as &$_term ) {
  116. WPGlobus_Core::translate_term( $_term, WPGlobus::Config()->language );
  117. }
  118. unset( $_term );
  119. reset( $terms );
  120. }
  121. return $terms;
  122. }
  123. /**
  124. * Filter @see wp_get_object_terms()
  125. * @scope admin
  126. * @scope front
  127. *
  128. * @param string[]|object[] $terms An array of terms for the given object or objects.
  129. *
  130. * @return array
  131. */
  132. public static function filter__wp_get_object_terms( Array $terms ) {
  133. /**
  134. * @internal
  135. * Do not need to check for is_wp_error($terms),
  136. * because the WP_Error is returned by wp_get_object_terms() before applying filter.
  137. * Do not need to check for empty($terms) because foreach won't loop.
  138. */
  139. /**
  140. * Don't filter term names when saving or publishing posts
  141. * @todo Check this before add_filter and not here
  142. * @todo Describe exactly how to check this visually, and is possible - write the acceptance test
  143. */
  144. if (
  145. is_admin() &&
  146. WPGlobus_WP::is_pagenow( 'post.php' ) &&
  147. ( ! empty( $_POST['save'] ) || ! empty( $_POST['publish'] ) )
  148. ) {
  149. return $terms;
  150. }
  151. /**
  152. * Don't filter term names for trash and un-trash single post
  153. * @see we check post.php page instead of edit.php because redirect
  154. */
  155. if ( is_admin() && WPGlobus_WP::is_pagenow( 'post.php' ) && isset( $_GET['action'] ) && ( 'trash' == $_GET['action'] || 'untrash' == $_GET['action'] )
  156. ) {
  157. return $terms;
  158. }
  159. /**
  160. * Don't filter term names bulk trash and untrash posts
  161. */
  162. if ( is_admin() && WPGlobus_WP::is_pagenow( 'edit.php' ) && isset( $_GET['action'] ) && ( 'trash' == $_GET['action'] || 'untrash' == $_GET['action'] )
  163. ) {
  164. return $terms;
  165. }
  166. /**
  167. * Don't filter term names for bulk edit post from edit.php page
  168. */
  169. if ( is_admin() && WPGlobus_Utils::is_function_in_backtrace( 'bulk_edit_posts' ) ) {
  170. return $terms;
  171. }
  172. /**
  173. * Don't filter term names for inline-save ajax action from edit.php page
  174. * @see wp_ajax_inline_save
  175. * ...except when the same AJAX refreshes the table row @see WP_Posts_List_Table::single_row
  176. * -
  177. * @qa At the "All posts" admin page, do Quick Edit on any post. After update, categories and tags
  178. * must not show multilingual strings with delimiters.
  179. * @qa At Quick Edit, enter an existing tag. After save, check if there is no additional tag
  180. * on the "Tags" page. If a new tag is created then the "is tag exists" check was checking
  181. * only a single language representation of the tag, while there is a multilingual tag in the DB.
  182. */
  183. if ( WPGlobus_WP::is_http_post_action( 'inline-save' ) &&
  184. WPGlobus_WP::is_pagenow( 'admin-ajax.php' )
  185. ) {
  186. if ( ! WPGlobus_Utils::is_function_in_backtrace( 'single_row' ) ) {
  187. return $terms;
  188. }
  189. }
  190. /**
  191. * Don't filter term names for heartbeat autosave
  192. */
  193. if ( WPGlobus_WP::is_http_post_action( 'heartbeat' ) &&
  194. WPGlobus_WP::is_pagenow( 'admin-ajax.php' ) &&
  195. ! empty( $_POST['data']['wp_autosave'] )
  196. ) {
  197. return $terms;
  198. }
  199. /**
  200. * Don't filter term name at time generate checklist categories in metabox
  201. */
  202. if ( is_admin() &&
  203. WPGlobus_WP::is_pagenow( 'post.php' ) &&
  204. empty( $_POST ) &&
  205. WPGlobus_Utils::is_function_in_backtrace( 'wp_terms_checklist' )
  206. ) {
  207. return $terms;
  208. }
  209. foreach ( $terms as &$_term ) {
  210. WPGlobus_Core::translate_term( $_term, WPGlobus::Config()->language );
  211. }
  212. unset( $_term );
  213. reset( $terms );
  214. return $terms;
  215. }
  216. /**
  217. * This filter is needed to build correct permalink (slug, post_name)
  218. * using only the main part of the post title (in the default language).
  219. * -
  220. * Because 'sanitize_title' is a commonly used function, we have to apply our filter
  221. * only on very specific calls. Therefore, there are (ugly) debug_backtrace checks.
  222. * -
  223. * Case 1
  224. * When a draft post is created,
  225. * the post title is converted to the slug in the @see get_sample_permalink function,
  226. * using the 'sanitize_title' filter.
  227. * -
  228. * Case 2
  229. * When the draft is published, @see wp_insert_post calls
  230. * @see sanitize_title to set the slug
  231. * -
  232. * @see WPGLobus_QA::_test_post_name
  233. * -
  234. * @see WPSEO_Metabox::localize_script
  235. * @todo Check what's going on in localize_script of WPSEO?
  236. * @todo What if there is no EN language? Only ru and kz but - we cannot use 'en' for permalink
  237. * @todo check guid
  238. *
  239. * @param string $title
  240. *
  241. * @return string
  242. */
  243. public static function filter__sanitize_title( $title ) {
  244. $ok_to_filter = false;
  245. $callers = debug_backtrace();
  246. if ( isset( $callers[4]['function'] ) ) {
  247. if ( $callers[4]['function'] === 'get_sample_permalink' ) {
  248. /**
  249. * Case 1
  250. */
  251. $ok_to_filter = true;
  252. } elseif (
  253. /**
  254. * Case 2
  255. */
  256. $callers[4]['function'] === 'wp_insert_post'
  257. /** @todo This is probably not required. Keeping it until stable version */
  258. // and ( isset( $callers[5]['function'] ) and $callers[5]['function'] === 'wp_update_post' )
  259. ) {
  260. $ok_to_filter = true;
  261. }
  262. }
  263. if ( $ok_to_filter ) {
  264. /**
  265. * @internal Note: the DEFAULT language, not the current one
  266. */
  267. $title = WPGlobus_Core::text_filter( $title, WPGlobus::Config()->default_language );
  268. }
  269. return $title;
  270. }
  271. /**
  272. * Filter @see get_term()
  273. *
  274. * @param string|object $term
  275. *
  276. * @return string|object
  277. */
  278. public static function filter__get_term( $term ) {
  279. if ( WPGlobus_WP::is_http_post_action( 'inline-save-tax' ) ) {
  280. /**
  281. * Don't filter ajax action 'inline-save-tax' from edit-tags.php page.
  282. * See quick_edit() in includes/js/wpglobus.admin.js
  283. * for and example of working with taxonomy name and description
  284. * wp_current_filter contains
  285. * 0=wp_ajax_inline-save-tax
  286. * 1=get_term
  287. * @see wp_ajax_inline_save_tax()
  288. */
  289. // do nothing
  290. } else {
  291. WPGlobus_Core::translate_term( $term, WPGlobus::Config()->language );
  292. }
  293. return $term;
  294. }
  295. /**
  296. * Localize home_url
  297. * Should be processed on:
  298. * - front
  299. * - AJAX, except for several specific actions
  300. *
  301. * @param string $url
  302. *
  303. * @return string
  304. */
  305. public static function filter__home_url( $url ) {
  306. /**
  307. * @internal note
  308. * Example of URL in admin:
  309. * When admin interface is not in default language, we still should not see
  310. * any permalinks with language prefixes.
  311. * For that, we could check if we are at the 'post.php' screen:
  312. * if ( 'post.php' == $pagenow ) ....
  313. * However, we do not need it, because we disallowed almost any processing in admin.
  314. */
  315. /**
  316. * 1. Do not work in admin
  317. */
  318. $need_to_process = ( ! is_admin() );
  319. if ( WPGlobus_WP::is_pagenow( 'admin-ajax.php' ) ) {
  320. /**
  321. * 2. But work in AJAX, which is also admin
  322. */
  323. $need_to_process = true;
  324. /**
  325. * 3. However, don't convert url for these AJAX actions:
  326. */
  327. if ( WPGlobus_WP::is_http_post_action(
  328. array(
  329. 'heartbeat',
  330. 'sample-permalink',
  331. 'add-menu-item',
  332. )
  333. )
  334. ) {
  335. $need_to_process = false;
  336. }
  337. }
  338. if ( $need_to_process ) {
  339. $url = WPGlobus_Utils::localize_url( $url );
  340. }
  341. return $url;
  342. }
  343. /**
  344. * Filter @see get_pages
  345. * @qa See a list of available pages in the "Parent Page" metabox when editing a page.
  346. *
  347. * @param WP_Post[] $pages
  348. *
  349. * @return WP_Post[]
  350. */
  351. public static function filter__get_pages( $pages ) {
  352. foreach ( $pages as &$_page ) {
  353. WPGlobus_Core::translate_wp_post( $_page, WPGlobus::Config()->language );
  354. }
  355. unset( $_page );
  356. reset( $pages );
  357. return $pages;
  358. }
  359. /**
  360. * Filter for @see get_locale
  361. *
  362. * @param string $locale
  363. *
  364. * @return string
  365. * @todo Do we need to do setlocale(LC_???, $locale)? (*** NOT HERE )
  366. * @see setlocale
  367. * @link http://php.net/manual/en/function.setlocale.php
  368. * @example echo setlocale(LC_ALL, 'Russian'); => Russian_Russia.1251
  369. */
  370. public static function filter__get_locale(
  371. /** @noinspection PhpUnusedParameterInspection */
  372. $locale
  373. ) {
  374. /**
  375. * Special case: in admin area, show everything in the language of admin interface.
  376. * (set in the General Settings in WP 4.1)
  377. */
  378. /**
  379. * @internal
  380. * We need to exclude is_admin when it's a front-originated AJAX,
  381. * so we are doing a "hack" checking @see WPGlobus_WP::is_admin_doing_ajax.
  382. */
  383. if (
  384. is_admin() &&
  385. ( ! WPGlobus_WP::is_doing_ajax() || WPGlobus_WP::is_admin_doing_ajax() )
  386. ) {
  387. /**
  388. * @todo is_multisite
  389. * @todo Pre-WP4, WPLANG constant from wp-config
  390. */
  391. $WPLANG = get_option( 'WPLANG' );
  392. if ( empty( $WPLANG ) ) {
  393. $WPLANG = 'en_US';
  394. }
  395. WPGlobus::Config()->set_language( $WPLANG );
  396. }
  397. if ( is_admin() ) {
  398. /**
  399. * Checking case for set locale which does not set in WPGlobus
  400. */
  401. if ( WPGlobus::Config()->is_enabled_locale( $locale ) ) {
  402. $locale = WPGlobus::Config()->locale[ WPGlobus::Config()->language ];
  403. }
  404. } else {
  405. $locale = WPGlobus::Config()->locale[ WPGlobus::Config()->language ];
  406. }
  407. return $locale;
  408. }
  409. /**
  410. * Filter @see wp_setup_nav_menu_item in wp-includes\nav-menu.php for more info
  411. * @since 1.0.0
  412. *
  413. * @param WP_Post[] $object
  414. *
  415. * @return WP_Post[]
  416. */
  417. public static function filter__nav_menu_item( $object ) {
  418. /**
  419. * This filter is used at nav-menus.php page for .field-move elements
  420. */
  421. if ( is_object( $object ) && 'WP_Post' == get_class( $object ) ) {
  422. if ( ! empty( $object->title ) ) {
  423. $object->title = WPGlobus_Core::text_filter( $object->title, WPGlobus::Config()->language );
  424. }
  425. if ( ! empty( $object->description ) ) {
  426. $object->description = WPGlobus_Core::text_filter( $object->description, WPGlobus::Config()->language );
  427. }
  428. }
  429. return $object;
  430. }
  431. /**
  432. * Filter @see nav_menu_description
  433. * @since 1.0.0
  434. *
  435. * @param string $description
  436. *
  437. * @return string
  438. */
  439. public static function filter__nav_menu_description( $description ) {
  440. /**
  441. * This filter for translate menu item description
  442. */
  443. if ( ! empty( $description ) ) {
  444. $description = WPGlobus_Core::text_filter( $description, WPGlobus::Config()->language );
  445. }
  446. return $description;
  447. }
  448. /**
  449. * Filter @see heartbeat_received
  450. * @since 1.0.1
  451. *
  452. * @param array $response
  453. * @param array $data
  454. * @param string $screen_id
  455. *
  456. * @return array
  457. */
  458. public static function filter__heartbeat_received(
  459. $response, $data,
  460. /** @noinspection PhpUnusedParameterInspection */
  461. $screen_id
  462. ) {
  463. if ( false !== strpos( $_SERVER['HTTP_REFERER'], 'wpglobus=off' ) ) {
  464. /**
  465. * Check $_SERVER['HTTP_REFERER'] for wpglobus toggle is off because wpglobus-admin.js doesn't loaded in this mode
  466. */
  467. return $response;
  468. }
  469. if ( ! empty( $data['wp_autosave'] ) ) {
  470. if ( empty( $data['wp_autosave']['post_id'] ) || (int) $data['wp_autosave']['post_id'] == 0 ) {
  471. /**
  472. * wp_autosave may come from edit.php page
  473. */
  474. return $response;
  475. }
  476. if ( empty( $data['wpglobus_heartbeat'] ) ) {
  477. /**
  478. * Check for wpglobus key
  479. */
  480. return $response;
  481. }
  482. $title_wrap = false;
  483. $content_wrap = false;
  484. $post_title_ext = '';
  485. $content_ext = '';
  486. foreach ( WPGlobus::Config()->enabled_languages as $language ) {
  487. if ( $language == WPGlobus::Config()->default_language ) {
  488. $post_title_ext .= WPGlobus::add_locale_marks( $data['wp_autosave']['post_title'], $language );
  489. $content_ext .= WPGlobus::add_locale_marks( $data['wp_autosave']['content'], $language );
  490. } else {
  491. if ( ! empty( $data['wp_autosave'][ 'post_title_' . $language ] ) ) {
  492. $title_wrap = true;
  493. $post_title_ext .= WPGlobus::add_locale_marks( $data['wp_autosave'][ 'post_title_' . $language ], $language );
  494. }
  495. if ( ! empty( $data['wp_autosave'][ 'content_' . $language ] ) ) {
  496. $content_wrap = true;
  497. $content_ext .= WPGlobus::add_locale_marks( $data['wp_autosave'][ 'content_' . $language ], $language );
  498. }
  499. }
  500. }
  501. if ( $title_wrap ) {
  502. $data['wp_autosave']['post_title'] = $post_title_ext;
  503. }
  504. if ( $content_wrap ) {
  505. $data['wp_autosave']['content'] = $content_ext;
  506. }
  507. /**
  508. * Filter before autosave
  509. * @since 1.0.2
  510. *
  511. * @param array $data ['wp_autosave'] Array of post data.
  512. */
  513. $data['wp_autosave'] = apply_filters( 'wpglobus_autosave_post_data', $data['wp_autosave'] );
  514. $saved = wp_autosave( $data['wp_autosave'] );
  515. if ( is_wp_error( $saved ) ) {
  516. $response['wp_autosave'] = array( 'success' => false, 'message' => $saved->get_error_message() );
  517. } elseif ( empty( $saved ) ) {
  518. $response['wp_autosave'] = array( 'success' => false, 'message' => __( 'Error while saving.' ) );
  519. } else {
  520. /* translators: draft saved date format, see http://php.net/date */
  521. $draft_saved_date_format = __( 'g:i:s a' );
  522. /* translators: %s: date and time */
  523. $response['wp_autosave'] = array(
  524. 'success' => true,
  525. 'message' => sprintf( __( 'Draft saved at %s.' ), date_i18n( $draft_saved_date_format ) )
  526. );
  527. }
  528. }
  529. return $response;
  530. }
  531. /**
  532. * Filter @see wp_nav_menu_objects
  533. * @since 1.0.2
  534. *
  535. * @param array $object
  536. *
  537. * @return array
  538. */
  539. public static function filter__nav_menu_objects( $object ) {
  540. if ( is_array( $object ) ) {
  541. foreach ( $object as &$post ) {
  542. if ( ! empty( $post->attr_title ) ) {
  543. $post->attr_title = WPGlobus_Core::text_filter( $post->attr_title, WPGlobus::Config()->language );
  544. }
  545. }
  546. }
  547. return $object;
  548. }
  549. /**
  550. * Translate widget strings (besides the title handled by the `widget_title` filter)
  551. * @see WP_Widget::display_callback
  552. * @scope front
  553. *
  554. * @param string[] $instance
  555. *
  556. * @return string[]
  557. * @since 1.0.6
  558. */
  559. public static function filter__widget_display_callback( $instance ) {
  560. foreach ( $instance as &$widget_setting ) {
  561. if ( ! empty( $widget_setting ) && is_string( $widget_setting ) ) {
  562. $widget_setting =
  563. WPGlobus_Core::text_filter( $widget_setting, WPGlobus::Config()->language );
  564. }
  565. }
  566. return $instance;
  567. }
  568. /**
  569. * Filter @see comment_moderation_text,
  570. * @see comment_moderation_subject
  571. * @since 1.0.6
  572. *
  573. * @param string $text
  574. * @param int $comment_id
  575. *
  576. * @return string
  577. */
  578. public static function filter__comment_moderation( $text, $comment_id ) {
  579. $comment = get_comment( $comment_id );
  580. $post = get_post( $comment->comment_post_ID );
  581. $title = WPGlobus_Core::text_filter( $post->post_title, WPGlobus::Config()->language );
  582. return str_replace( $post->post_title, $title, $text );
  583. }
  584. /**
  585. * Filter @see wp_trim_words
  586. * @qa At the /wp-admin/index.php page is a Quick Draft metabox
  587. * which shows 3 last post drafts. This filter lets post content in default language.
  588. * @since 1.0.14
  589. *
  590. * @param string $text The trimmed text.
  591. * @param int $num_words The number of words to trim the text to.
  592. * @param string $more An optional string to append to the end of the trimmed text, e.g. &hellip;.
  593. * @param string $original_text The text before it was trimmed.
  594. *
  595. * @return string
  596. */
  597. public static function filter__wp_trim_words(
  598. /** @noinspection PhpUnusedParameterInspection */
  599. $text, $num_words, $more, $original_text
  600. ) {
  601. $text = WPGlobus_Core::text_filter( $original_text, WPGlobus::Config()->language );
  602. if ( null === $more ) {
  603. $more = __( '&hellip;' );
  604. }
  605. $text = wp_strip_all_tags( $text );
  606. /* translators: If your word count is based on single characters (East Asian characters),
  607. enter 'characters'. Otherwise, enter 'words'. Do not translate into your own language. */
  608. if ( 'characters' == _x( 'words', 'word count: words or characters?' ) && preg_match( '/^utf\-?8$/i', get_option( 'blog_charset' ) ) ) {
  609. $text = trim( preg_replace( "/[\n\r\t ]+/", ' ', $text ), ' ' );
  610. preg_match_all( '/./u', $text, $words_array );
  611. $words_array = array_slice( $words_array[0], 0, $num_words + 1 );
  612. $sep = '';
  613. } else {
  614. $words_array = preg_split( "/[\n\r\t ]+/", $text, $num_words + 1, PREG_SPLIT_NO_EMPTY );
  615. $sep = ' ';
  616. }
  617. if ( count( $words_array ) > $num_words ) {
  618. array_pop( $words_array );
  619. $text = implode( $sep, $words_array );
  620. $text = $text . $more;
  621. } else {
  622. $text = implode( $sep, $words_array );
  623. }
  624. return $text;
  625. }
  626. /**
  627. * Register the WPGlobus widgets
  628. * @wp-hook widgets_init
  629. * @since 1.0.7
  630. */
  631. public static function register_widgets() {
  632. register_widget( 'WPGlobusWidget' );
  633. }
  634. /**
  635. * Do something on admin_init hook.
  636. * @todo Note: runs on admin-ajax and admin-post, too
  637. */
  638. public static function action__admin_init() {
  639. /**
  640. * Display blog name correctly on the WooThemes Helper page
  641. * wp-admin/index.php?page=woothemes-helper
  642. */
  643. if ( WPGlobus_WP::is_plugin_page( 'woothemes-helper' ) ) {
  644. add_filter( 'option_blogname', array( 'WPGlobus_Filters', 'filter__text' ), 0 );
  645. }
  646. }
  647. /**
  648. * Specify meta keys where the meta data can be multilingual
  649. * @example
  650. * <code>
  651. * add_filter( 'wpglobus_multilingual_meta_keys',
  652. * function ( $multilingual_meta_keys ) {
  653. * $multilingual_meta_keys['slides'] = true;
  654. * return $multilingual_meta_keys;
  655. * }
  656. * );
  657. * </code>
  658. * @since 1.2.1
  659. */
  660. public static function set_multilingual_meta_keys() {
  661. self::$multilingual_meta_keys = apply_filters(
  662. 'wpglobus_multilingual_meta_keys', self::$multilingual_meta_keys
  663. );
  664. }
  665. /**
  666. * Translate meta data
  667. * @see \WPGlobus_Filters::set_multilingual_meta_keys
  668. *
  669. * @param string|array $value Null is passed. We set the value.
  670. * @param int $object_id Post ID
  671. * @param string $meta_key Passed by the filter. We need only one key.
  672. * @param string|array $single Meta value, or an array of values.
  673. *
  674. * @return string|array
  675. */
  676. public static function filter__postmeta( $value, $object_id, $meta_key, $single ) {
  677. /**
  678. * @todo Currently, only single values are supported
  679. */
  680. if ( ! $single ) {
  681. return $value;
  682. }
  683. /**
  684. * Will process only if the `meta_key` is one of the explicitly set.
  685. */
  686. if ( ! isset( self::$multilingual_meta_keys[ $meta_key ] ) ) {
  687. return $value;
  688. }
  689. /**
  690. * May be called many times on one page. Let's cache.
  691. */
  692. static $_cache;
  693. if ( isset( $_cache[ $meta_key ][ $object_id ] ) ) {
  694. return $_cache[ $meta_key ][ $object_id ];
  695. }
  696. /** @global wpdb $wpdb */
  697. global $wpdb;
  698. $meta_value = $wpdb->get_var( $wpdb->prepare(
  699. "SELECT meta_value FROM $wpdb->postmeta WHERE meta_key = %s AND post_id = %d LIMIT 1;",
  700. $meta_key, $object_id ) );
  701. if ( $meta_value ) {
  702. if ( is_serialized( $meta_value ) ) {
  703. /**
  704. * @todo Refactor this. Write a `filter__array` method.
  705. */
  706. $_meta_array = unserialize( $meta_value );
  707. foreach ( $_meta_array as &$_value ) {
  708. if ( is_array( $_value ) ) {
  709. foreach ( $_value as &$_deep_value ) {
  710. /**
  711. * @todo Assuming that the array had max. two levels, which is wrong.
  712. */
  713. $_deep_value = WPGlobus_Filters::filter__text( $_deep_value );
  714. }
  715. unset( $_deep_value );
  716. } else {
  717. $_value = WPGlobus_Filters::filter__text( $_value );
  718. }
  719. }
  720. unset( $_value );
  721. $value = $_meta_array;
  722. /**
  723. * If single is requested, the following code is executed by
  724. * @see get_metadata
  725. * <code>
  726. * if ( $single && is_array( $check ) )
  727. * return $check[0];
  728. * </code>
  729. * Therefore, we need to return the entire `$value` as the first element of
  730. * an array.
  731. */
  732. if ( $single ) {
  733. $value = array( $value );
  734. }
  735. } else {
  736. $value = WPGlobus_Filters::filter__text( $meta_value );
  737. }
  738. }
  739. /**
  740. * Save to cache, even if we did not do anything
  741. */
  742. $_cache[ $meta_key ][ $object_id ] = $value;
  743. return $value;
  744. }
  745. } // class
  746. # --- EOF