class-wcml-admin-menus.php
322 lines
| 1 | <?php |
| 2 | |
| 3 | use function WCML\functions\getSetting; |
| 4 | use function WCML\functions\isStandAlone; |
| 5 | use WCML\AdminNotices\WizardNotice; |
| 6 | use WCML\StandAlone\UI\AdminMenu; |
| 7 | use WCML\Utilities\AdminPages; |
| 8 | use WCML\Utilities\AdminUrl; |
| 9 | use WPML\FP\Fns; |
| 10 | use WPML\FP\Str; |
| 11 | |
| 12 | class WCML_Admin_Menus { |
| 13 | |
| 14 | const SLUG = 'wpml-wcml'; |
| 15 | |
| 16 | private static $woocommerce_wpml; |
| 17 | |
| 18 | private static $sitepress; |
| 19 | |
| 20 | private static $wpdb; |
| 21 | |
| 22 | public static function set_up_menus( $woocommerce_wpml, $sitepress, $wpdb ) { |
| 23 | self::$woocommerce_wpml = $woocommerce_wpml; |
| 24 | self::$sitepress = $sitepress; |
| 25 | self::$wpdb = $wpdb; |
| 26 | |
| 27 | if ( |
| 28 | \WPML\Container\make( WCML_Dependencies::class )->check() && |
| 29 | ! current_user_can( 'wpml_manage_woocommerce_multilingual' ) && |
| 30 | current_user_can( 'wpml_operate_woocommerce_multilingual' ) && |
| 31 | ! current_user_can( 'translate' ) |
| 32 | ) { |
| 33 | add_filter( 'wpml_menu_page', [ __CLASS__, 'wpml_menu_page' ] ); |
| 34 | } |
| 35 | |
| 36 | add_action( 'admin_menu', [ __CLASS__, 'register_menus' ], 80 ); |
| 37 | |
| 38 | if ( AdminPages::isWcmlSettings() ) { |
| 39 | add_action( 'admin_body_class', Str::concat( Fns::__, ' ' . self::SLUG . '-' . AdminPages::getTabToDisplay() ) ); |
| 40 | } |
| 41 | |
| 42 | if ( self::is_page_without_admin_language_switcher() ) { |
| 43 | self::remove_wpml_admin_language_switcher(); |
| 44 | } |
| 45 | |
| 46 | if ( is_admin() && ! is_null( $sitepress ) && \WPML\Container\make( WCML_Dependencies::class )->check() && WCML_Capabilities::canManageWcml() ) { |
| 47 | add_action( 'admin_head', [ __CLASS__, 'hide_multilingual_content_setup_box' ] ); |
| 48 | if ( ! isStandAlone() ) { |
| 49 | add_action( 'admin_footer', [ __CLASS__, 'documentation_links' ] ); |
| 50 | add_action( 'admin_init', [ __CLASS__, 'restrict_admin_with_redirect' ] ); |
| 51 | } |
| 52 | add_filter( 'plugin_action_links_woocommerce-multilingual/wpml-woocommerce.php', [ __CLASS__, 'add_settings_links_to_plugin_actions' ] ); |
| 53 | } |
| 54 | |
| 55 | add_filter( 'woocommerce_prevent_admin_access', [ __CLASS__, 'check_user_admin_access' ] ); |
| 56 | |
| 57 | if ( ! isStandAlone() ) { |
| 58 | add_action( 'admin_head', [ __CLASS__, 'add_menu_warning' ] ); |
| 59 | } |
| 60 | } |
| 61 | |
| 62 | private static function is_page_without_admin_language_switcher() { |
| 63 | $get_page = isset( $_GET['page'] ) ? sanitize_text_field( $_GET['page'] ) : false; |
| 64 | |
| 65 | $is_page_wpml_wcml = self::SLUG === $get_page; |
| 66 | $is_shipping_zones = 'shipping_zones' === $get_page; |
| 67 | $is_attributes_page = apply_filters( 'wcml_is_attributes_page', 'product_attributes' === $get_page ); |
| 68 | $is_order_create_or_edit = \WCML\Orders\Helper::isOrderCreateAdminScreen() || \WCML\Orders\Helper::isOrderEditAdminScreen(); |
| 69 | $is_coupon_create_or_edit = \WCML\Coupons\Helper::isCouponCreateAdminScreen() || \WCML\Coupons\Helper::isCouponEditAdminScreen(); |
| 70 | |
| 71 | return is_admin() && ( |
| 72 | $is_page_wpml_wcml || |
| 73 | $is_order_create_or_edit || |
| 74 | $is_coupon_create_or_edit || |
| 75 | $is_shipping_zones || |
| 76 | $is_attributes_page |
| 77 | ); |
| 78 | } |
| 79 | |
| 80 | public static function remove_wpml_admin_language_switcher() { |
| 81 | remove_action( 'wp_before_admin_bar_render', [ self::$sitepress, 'admin_language_switcher' ] ); |
| 82 | } |
| 83 | |
| 84 | public static function wpml_menu_page( $menu ) { |
| 85 | if ( isset( $menu['menu_slug'] ) && WPML_TM_FOLDER . '/menu/translations-queue.php' === $menu['menu_slug'] ) { |
| 86 | $menu['capability'] = 'wpml_operate_woocommerce_multilingual'; |
| 87 | } |
| 88 | |
| 89 | return $menu; |
| 90 | } |
| 91 | |
| 92 | public static function register_menus() { |
| 93 | $pageTitle = $menuTitle = self::getWcmlShortLabel(); |
| 94 | |
| 95 | if ( \WPML\Container\make( WCML_Dependencies::class )->check() || class_exists( 'WooCommerce' ) ) { |
| 96 | add_submenu_page( |
| 97 | 'woocommerce', |
| 98 | $pageTitle, |
| 99 | $menuTitle, |
| 100 | 'wpml_operate_woocommerce_multilingual', |
| 101 | self::SLUG, |
| 102 | [ __CLASS__, 'render_menus' ] |
| 103 | ); |
| 104 | } else { |
| 105 | add_menu_page( |
| 106 | $pageTitle, |
| 107 | $menuTitle, |
| 108 | 'wpml_manage_woocommerce_multilingual', |
| 109 | self::SLUG, |
| 110 | [ __CLASS__, 'render_menus' ], |
| 111 | WCML_PLUGIN_URL . '/res/images/icon16.png' |
| 112 | ); |
| 113 | |
| 114 | } |
| 115 | } |
| 116 | |
| 117 | public static function render_menus() { |
| 118 | global $sitepress_settings; |
| 119 | |
| 120 | if ( \WPML\Container\make( WCML_Dependencies::class )->check() ) { |
| 121 | if ( isStandAlone() ) { |
| 122 | $plugins_wrap = new AdminMenu( self::$sitepress, self::$woocommerce_wpml ); |
| 123 | $plugins_wrap->show(); |
| 124 | } elseif ( getSetting( 'set_up_wizard_run' ) ) { |
| 125 | $menus_wrap = new WCML_Menus_Wrap( self::$woocommerce_wpml, self::$sitepress, $sitepress_settings ); |
| 126 | $menus_wrap->show(); |
| 127 | } else { |
| 128 | $wizard_wrap = new WizardNotice( self::$woocommerce_wpml ); |
| 129 | $wizard_wrap->show(); |
| 130 | } |
| 131 | } |
| 132 | } |
| 133 | |
| 134 | public static function documentation_links() { |
| 135 | global $post, $pagenow; |
| 136 | |
| 137 | if ( $post && ! is_object( $post ) ) { |
| 138 | $post = get_post( $post ); |
| 139 | } |
| 140 | |
| 141 | if ( ! $post ) { |
| 142 | return; |
| 143 | } |
| 144 | |
| 145 | $get_post_type = get_post_type( $post->ID ); |
| 146 | |
| 147 | if ( 'product' === $get_post_type && 'edit.php' === $pagenow ) { |
| 148 | $quick_edit_notice = '<p>'; |
| 149 | $quick_edit_notice .= esc_html__( 'Quick Edit isn\'t available for product translations:', 'woocommerce-multilingual' ); |
| 150 | $quick_edit_notice .= '</p>'; |
| 151 | |
| 152 | $quick_edit_notice .= '<ul>'; |
| 153 | $quick_edit_notice .= '<li>'; |
| 154 | $quick_edit_notice .= sprintf( |
| 155 | /* translators: %1$s and %2$s are opening and closing HTML link tags */ |
| 156 | esc_html__( '- To edit this product\'s translation, use the %1$sTranslation Dashboard%2$s.', 'woocommerce-multilingual' ), |
| 157 | '<a href="' . esc_url( AdminUrl::getWPMLTMDashboardProducts() ) . '">', |
| 158 | '</a>' |
| 159 | ); |
| 160 | $quick_edit_notice .= '</li>'; |
| 161 | $quick_edit_notice .= '<li>'; |
| 162 | $quick_edit_notice .= esc_html__( '- To edit the original product, switch back to the default language.', 'woocommerce-multilingual' ); |
| 163 | $quick_edit_notice .= '</li>'; |
| 164 | $quick_edit_notice .= '</ul>'; |
| 165 | |
| 166 | ?> |
| 167 | <script type="text/javascript"> |
| 168 | jQuery( '.subsubsub' ).append( '<div id="quick_edit_notice" style="display:none;"><?php echo wp_filter_post_kses( $quick_edit_notice ); ?></div>' ); |
| 169 | |
| 170 | //lock feature for translations |
| 171 | jQuery( document ).on( 'click', '.featured a', function() { |
| 172 | if ( jQuery( this ).closest( 'tr' ).find( '.quick_hide' ).size() > 0 ) { |
| 173 | return false; |
| 174 | } |
| 175 | |
| 176 | } ); |
| 177 | </script> |
| 178 | <?php |
| 179 | } |
| 180 | } |
| 181 | |
| 182 | public static function hide_multilingual_content_setup_box() { |
| 183 | remove_meta_box( 'icl_div_config', convert_to_screen( 'shop_order' ), 'normal' ); |
| 184 | remove_meta_box( 'icl_div_config', convert_to_screen( 'shop_coupon' ), 'normal' ); |
| 185 | } |
| 186 | |
| 187 | public static function restrict_admin_with_redirect() { |
| 188 | global $pagenow; |
| 189 | |
| 190 | if ( |
| 191 | self::$woocommerce_wpml->is_wpml_prior_4_2() && |
| 192 | self::$woocommerce_wpml->settings['trnsl_interface'] ) { |
| 193 | |
| 194 | if ( |
| 195 | 'post.php' === $pagenow && |
| 196 | ! wp_doing_ajax() && |
| 197 | self::is_post_product_translation_screen() && |
| 198 | self::is_post_action_needs_redirect() |
| 199 | ) { |
| 200 | $prid = (int) $_GET['post']; |
| 201 | if ( 'auto-draft' !== get_post_status( $prid ) ) { |
| 202 | wcml_safe_redirect( AdminUrl::getWPMLTMDashboardProducts().'&prid=' . $prid ); |
| 203 | } |
| 204 | } elseif ( self::is_admin_duplicate_page_action( $pagenow ) && self::is_post_product_translation_screen() ) { |
| 205 | wcml_safe_redirect( AdminUrl::getWPMLTMDashboardProducts() ); |
| 206 | } |
| 207 | } elseif ( 'post.php' === $pagenow && self::is_post_product_translation_screen() ) { |
| 208 | add_action( 'admin_notices', [ __CLASS__, 'inf_editing_product_in_non_default_lang' ] ); |
| 209 | } |
| 210 | } |
| 211 | |
| 212 | private static function is_post_product_translation_screen() { |
| 213 | return isset( $_GET['post'] ) && 'product' === get_post_type( $_GET['post'] ) && ! self::$woocommerce_wpml->products->is_original_product( $_GET['post'] ); |
| 214 | } |
| 215 | |
| 216 | private static function is_post_action_needs_redirect(): bool { |
| 217 | return ! isset( $_GET['action'] ) || |
| 218 | ( isset( $_GET['action'] ) && |
| 219 | ! in_array ( |
| 220 | $_GET['action'], |
| 221 | [ 'trash', 'delete', 'untrash' ], |
| 222 | true |
| 223 | ) |
| 224 | ); |
| 225 | } |
| 226 | |
| 227 | private static function is_admin_duplicate_page_action( $pagenow ) { |
| 228 | return 'admin.php' === $pagenow && isset( $_GET['action'] ) && 'duplicate_product' === $_GET['action']; |
| 229 | } |
| 230 | |
| 231 | public static function add_settings_links_to_plugin_actions( $actions ) { |
| 232 | $getLink = function( $label, $url ) { |
| 233 | return '<a href="' . esc_url( $url ) . '">' . $label . '</a>'; |
| 234 | }; |
| 235 | |
| 236 | return array_merge( |
| 237 | [ |
| 238 | 'settings-ml' => $getLink( |
| 239 | esc_html__( 'Multilingual Settings', 'woocommerce-multilingual' ), |
| 240 | AdminUrl::getMultilingualTab() |
| 241 | ), |
| 242 | 'settings-mc' => $getLink( |
| 243 | esc_html__( 'Multicurrency Settings', 'woocommerce-multilingual' ), |
| 244 | AdminUrl::getMultiCurrencyTab() |
| 245 | ), |
| 246 | ], |
| 247 | $actions |
| 248 | ); |
| 249 | } |
| 250 | |
| 251 | public static function inf_editing_product_in_non_default_lang() { |
| 252 | if ( ! self::$woocommerce_wpml->settings['dismiss_tm_warning'] ) { |
| 253 | $url = $_SERVER['REQUEST_URI']; |
| 254 | |
| 255 | $message = '<div class="message error otgs-is-dismissible"><p>'; |
| 256 | |
| 257 | $message .= sprintf( |
| 258 | /* translators: 1: open <a> tag, 2: close <a> tag */ |
| 259 | esc_html__( 'It’s recommended that you translate products from the %1$sTranslation Dashboard%2$s.', 'woocommerce-multilingual' ), |
| 260 | '<a href="' . esc_url( AdminUrl::getWPMLTMDashboardProducts() ) . '">', |
| 261 | '</a>' |
| 262 | ); |
| 263 | $message .= '</p><a class="notice-dismiss" href="' . esc_url( add_query_arg( 'wcml_action', 'dismiss_tm_warning', $url ) ) . '"><span class="screen-reader-text">' . __( 'Dismiss', 'woocommerce-multilingual' ) . '</span></a>'; |
| 264 | $message .= '</div>'; |
| 265 | |
| 266 | echo wp_kses_post( $message ); |
| 267 | } |
| 268 | } |
| 269 | |
| 270 | public static function check_user_admin_access( $prevent_access ) { |
| 271 | if ( \WPML\Container\make( WCML_Dependencies::class )->check() ) { |
| 272 | $user_lang_pairs = get_user_meta( get_current_user_id(), self::$wpdb->prefix . 'language_pairs', true ); |
| 273 | if ( current_user_can( 'wpml_manage_woocommerce_multilingual' ) || ! empty( $user_lang_pairs ) ) { |
| 274 | return false; |
| 275 | } |
| 276 | } |
| 277 | |
| 278 | return $prevent_access; |
| 279 | } |
| 280 | |
| 281 | public static function add_menu_warning() { |
| 282 | global $submenu, $menu; |
| 283 | |
| 284 | if ( |
| 285 | class_exists( 'WooCommerce' ) && |
| 286 | ( |
| 287 | empty( self::$woocommerce_wpml->settings['set_up_wizard_run'] ) || |
| 288 | ( |
| 289 | empty( self::$woocommerce_wpml->settings['set_up_wizard_run'] ) && |
| 290 | self::$woocommerce_wpml->settings['set_up_wizard_splash'] |
| 291 | ) |
| 292 | ) |
| 293 | ) { |
| 294 | if ( isset( $submenu['woocommerce'] ) ) { |
| 295 | $wcml_short_label = self::getWcmlShortLabel(); |
| 296 | foreach ( $submenu['woocommerce'] as $key => $menu_item ) { |
| 297 | if ( $wcml_short_label === $menu_item[0] ) { |
| 298 | $submenu['woocommerce'][ $key ][0] .= '<span class="wcml-menu-warn"><i class="otgs-ico-warning"></i></span>'; |
| 299 | break; |
| 300 | } |
| 301 | } |
| 302 | } |
| 303 | |
| 304 | $woocommerce_label = __( 'WooCommerce', 'woocommerce' ); |
| 305 | foreach ( $menu as $key => $menu_item ) { |
| 306 | if ( $woocommerce_label === $menu_item[0] ) { |
| 307 | $menu[ $key ][0] .= '<span class="wcml-menu-warn"><i class="otgs-ico-warning"></i></span>'; |
| 308 | break; |
| 309 | } |
| 310 | } |
| 311 | } |
| 312 | } |
| 313 | |
| 314 | public static function getWcmlLabel() { |
| 315 | return __( 'WPML Multilingual & Multicurrency for WooCommerce', 'woocommerce-multilingual' ); |
| 316 | } |
| 317 | |
| 318 | public static function getWcmlShortLabel() { |
| 319 | return __( 'WCML', 'woocommerce-multilingual' ); |
| 320 | } |
| 321 | } |
| 322 |