PluginProbe ʕ •ᴥ•ʔ
Permalink Manager Lite / 2.4.1.4
Permalink Manager Lite v2.4.1.4
2.6.0 2.5.5 2.5.4 2.5.3.4 2.2.18 2.2.19.2 2.2.19.3 2.2.19.3.1 2.2.2 2.2.20 2.2.20.1 2.2.20.3 2.2.4 2.2.5 2.2.6 2.2.7.2 2.2.7.3 2.2.7.5 2.2.7.6 2.2.8.4 2.2.8.5 2.2.8.6 2.2.8.7 2.2.8.9 2.2.9.1 2.2.9.2 2.2.9.2.1 2.2.9.3 2.2.9.4 2.2.9.6 2.2.9.7 2.2.9.9 2.3.0 2.3.1.1 2.4.0 2.4.1 2.4.1.2 2.4.1.3 2.4.1.4 2.4.1.5 2.4.1.6 2.4.2 2.4.2.1 2.4.3 2.4.3.1 2.4.3.2 2.4.3.3 2.4.3.4 2.4.4 2.4.4.1 2.4.4.2 2.4.4.3 2.5.0 2.5.1 2.5.1.1 2.5.1.2 2.5.1.3 2.5.1.4 2.5.2 2.5.2.1 2.5.2.2 2.5.2.3 2.5.2.4 2.5.3 2.5.3.1 2.5.3.2 2.5.3.3 trunk 0.2 0.3 0.3.1 0.3.2 0.3.3 0.3.4 0.4 0.4.1 0.4.2 0.4.3 0.4.4 0.4.6 0.4.7 0.4.8 0.4.9 0.5.3 0.5.4 1.0.0 1.0.1 1.0.4 1.1.0 1.1.1 1.1.2 1.11.6.3 2.0.0 2.0.3 2.0.4 2.0.4.3 2.0.5.1 2.0.5.2 2.0.5.3 2.0.5.3.1 2.0.5.4 2.0.5.4a 2.0.5.5 2.0.5.6 2.0.5.6.1 2.0.5.7 2.0.5.9a 2.0.6.2.1 2.0.6.2a 2.0.6.3 2.1.0 2.1.1 2.1.2.4 2.2.0 2.2.1.1 2.2.1.2 2.2.11 2.2.12 2.2.13.1 2.2.14 2.2.15.1 2.2.16 2.2.17
permalink-manager / includes / integrations / permalink-manager-woocommerce.php
permalink-manager / includes / integrations Last commit date
permalink-manager-language-plugins.php 2 years ago permalink-manager-seo-plugins.php 2 years ago permalink-manager-third-parties.php 2 years ago permalink-manager-woocommerce.php 2 years ago
permalink-manager-woocommerce.php
351 lines
1 <?php
2
3 /**
4 * WooCommerce plugins integration
5 */
6 class Permalink_Manager_WooCommerce {
7
8 public function __construct() {
9 add_action( 'init', array( $this, 'init_hooks' ), 99 );
10 add_action( 'plugins_loaded', array( $this, 'init_early_hooks' ), 99 );
11 }
12
13 /**
14 * Add support for SEO plugins using their hooks
15 */
16 function init_hooks() {
17 if ( class_exists( 'WooCommerce' ) ) {
18 add_filter( 'permalink_manager_filter_query', array( $this, 'woocommerce_detect' ), 8, 5 );
19 add_filter( 'template_redirect', array( $this, 'woocommerce_checkout_fix' ), 9 );
20
21 if ( class_exists( 'Permalink_Manager_Pro_Functions' ) ) {
22 if ( empty( $permalink_manager_options['general']['partial_disable']['post_types'] ) || ! in_array( 'shop_coupon', $permalink_manager_options['general']['partial_disable']['post_types'] ) ) {
23 if ( is_admin() ) {
24 add_filter( 'woocommerce_coupon_data_tabs', 'Permalink_Manager_Pro_Functions::woocommerce_coupon_tabs' );
25 add_action( 'woocommerce_coupon_data_panels', 'Permalink_Manager_Pro_Functions::woocommerce_coupon_panel' );
26 add_action( 'woocommerce_coupon_options_save', 'Permalink_Manager_Pro_Functions::woocommerce_save_coupon_uri', 9, 2 );
27 }
28
29 add_filter( 'request', 'Permalink_Manager_Pro_Functions::woocommerce_detect_coupon_code', 1, 1 );
30 add_filter( 'permalink_manager_disabled_post_types', 'Permalink_Manager_Pro_Functions::woocommerce_coupon_uris', 9, 1 );
31 }
32 }
33
34 // WooCommerce Import/Export
35 add_filter( 'woocommerce_product_export_product_default_columns', array( $this, 'woocommerce_csv_custom_uri_column' ), 9 );
36 add_filter( 'woocommerce_product_export_product_column_custom_uri', array( $this, 'woocommerce_export_custom_uri_value' ), 9, 3 );
37
38 add_filter( 'woocommerce_csv_product_import_mapping_options', array( $this, 'woocommerce_csv_custom_uri_column' ), 9 );
39 add_filter( 'woocommerce_csv_product_import_mapping_default_columns', array( $this, 'woocommerce_csv_custom_uri_column' ), 9 );
40 add_action( 'woocommerce_product_import_inserted_product_object', array( $this, 'woocommerce_csv_import_custom_uri' ), 9, 2 );
41
42 add_action( 'woocommerce_product_duplicate', array( $this, 'woocommerce_generate_permalinks_after_duplicate' ), 9, 2 );
43 add_filter( 'permalink_manager_filter_default_post_uri', array( $this, 'woocommerce_product_attributes' ), 5, 5 );
44
45 if ( wp_doing_ajax() && class_exists( 'SitePress' ) ) {
46 add_filter( 'permalink_manager_filter_final_post_permalink', array( $this, 'woocommerce_translate_ajax_fragments_urls' ), 9999, 3 );
47 }
48 }
49
50 // WooCommerce Wishlist Plugin
51 if ( function_exists( 'tinv_get_option' ) ) {
52 add_filter( 'permalink_manager_detect_uri', array( $this, 'ti_woocommerce_wishlist_uris' ), 15, 3 );
53 }
54
55 // WooCommerce Subscriptions
56 if ( class_exists( 'WC_Subscriptions' ) ) {
57 add_filter( 'permalink_manager_filter_final_post_permalink', array( $this, 'wcs_fix_subscription_links' ), 10, 3 );
58 }
59 }
60
61 /**
62 * Some hooks must be called shortly after all the plugins are loaded
63 */
64 public function init_early_hooks() {
65 if ( class_exists( 'WooCommerce' ) ) {
66 add_filter( 'woocommerce_get_endpoint_url', array( 'Permalink_Manager_Core_Functions', 'control_trailing_slashes' ), 9 );
67 add_action( 'before_woocommerce_init', array( $this, 'woocommerce_cot_compatibility' ) );
68 }
69 }
70
71 /**
72 * Fix query on WooCommerce shop page & disable the canonical redirect if WooCommerce query variables are set
73 */
74 function woocommerce_detect( $query, $old_query, $uri_parts, $pm_query, $content_type ) {
75 global $woocommerce, $pm_query;
76
77 $shop_page_id = get_option( 'woocommerce_shop_page_id' );
78
79 // WPML - translate shop page id
80 $shop_page_id = apply_filters( 'wpml_object_id', $shop_page_id, 'page', true );
81
82 // Fix shop page
83 if ( get_theme_support( 'woocommerce' ) && ! empty( $pm_query['id'] ) && is_numeric( $pm_query['id'] ) && $shop_page_id == $pm_query['id'] ) {
84 $query['post_type'] = 'product';
85 unset( $query['pagename'] );
86 }
87
88 // Fix WooCommerce pages
89 if ( ! empty( $woocommerce->query->query_vars ) ) {
90 $query_vars = $woocommerce->query->query_vars;
91
92 foreach ( $query_vars as $key => $val ) {
93 if ( isset( $query[ $key ] ) ) {
94 $query['do_not_redirect'] = 1;
95 break;
96 }
97 }
98 }
99
100 return $query;
101 }
102
103 /**
104 * Redirects the user from the Shop archive to the Shop page if the user is not searching for anything
105 * Disable canonical redirect on "thank you" & another WooCommerce pages
106 */
107 function woocommerce_checkout_fix() {
108 global $wp_query, $pm_query, $permalink_manager_options;
109
110 // Redirect from Shop archive to selected page
111 if ( is_shop() && empty( $pm_query['id'] ) ) {
112 $redirect_mode = ( ! empty( $permalink_manager_options['general']['redirect'] ) ) ? $permalink_manager_options['general']['redirect'] : false;
113 $redirect_shop = apply_filters( 'permalink_manager_redirect_shop_archive', false );
114 $shop_page = get_option( 'woocommerce_shop_page_id' );
115
116 if ( $redirect_mode && $redirect_shop && $shop_page && empty( $wp_query->query_vars['s'] ) ) {
117 $shop_url = get_permalink( $shop_page );
118 wp_safe_redirect( $shop_url, $redirect_mode );
119 exit();
120 }
121 }
122
123 if ( is_checkout() || ( function_exists( 'is_wc_endpoint_url' ) && is_wc_endpoint_url() ) ) {
124 $wp_query->query_vars['do_not_redirect'] = 1;
125 }
126 }
127
128 /**
129 * Generate a new custom permalink for duplicated product
130 *
131 * @param WC_Product $new_product The new product object.
132 * @param WC_Product $old_product The product that was duplicated.
133 */
134 function woocommerce_generate_permalinks_after_duplicate( $new_product, $old_product ) {
135 if ( ! empty( $new_product ) ) {
136 $product_id = $new_product->get_id();
137
138 // Ignore variations
139 if ( $new_product->get_type() !== 'variation' ) {
140 $custom_uri = Permalink_Manager_URI_Functions_Post::get_default_post_uri( $product_id, false, true );
141
142 Permalink_Manager_URI_Functions::save_single_uri( $product_id, $custom_uri, false, true );
143 }
144 }
145 }
146
147 /**
148 * If the URI contains %pa_attribute_name% tag, replace it with the value of the attribute
149 *
150 * @param string $default_uri The default custom permalink that WordPress would use for the post.
151 * @param string $slug The post slug.
152 * @param WP_Post $post The post object.
153 * @param string $post_name The post slug.
154 * @param bool $native_uri true if the URI is a native URI, false if it's a custom URI
155 *
156 * @return string The default custom permalink
157 */
158 function woocommerce_product_attributes( $default_uri, $slug, $post, $post_name, $native_uri ) {
159 // Do not affect native URIs
160 if ( $native_uri ) {
161 return $default_uri;
162 }
163
164 // Use only for products
165 if ( empty( $post->post_type ) || $post->post_type !== 'product' ) {
166 return $default_uri;
167 }
168
169 preg_match_all( "/%pa_(.[^\%]+)%/", $default_uri, $custom_fields );
170
171 if ( ! empty( $custom_fields[1] ) ) {
172 $product = wc_get_product( $post->ID );
173
174 foreach ( $custom_fields[1] as $i => $custom_field ) {
175 $attribute_name = sanitize_title( $custom_field );
176 $attribute_value = $product->get_attribute( $attribute_name );
177
178 $default_uri = str_replace( $custom_fields[0][ $i ], Permalink_Manager_Helper_Functions::sanitize_title( $attribute_value ), $default_uri );
179 }
180 }
181
182 return $default_uri;
183 }
184
185 /**
186 * Check the current request is a WooCommerce AJAX request. If it is, check the translated page's URL should be returned
187 *
188 * @param string $permalink The full URL of the post
189 * @param WP_Post $post The post object
190 * @param string $old_permalink The original URL of the post.
191 *
192 * @return string The permalink is being returned.
193 */
194 function woocommerce_translate_ajax_fragments_urls( $permalink, $post, $old_permalink ) {
195 // Use it only if the permalinks are different
196 if ( $permalink == $old_permalink || $post->post_type !== 'page' ) {
197 return $permalink;
198 }
199
200 // A. Native WooCommerce AJAX events
201 if ( ! empty( $_REQUEST['wc-ajax'] ) ) {
202 $action = sanitize_title( $_REQUEST['wc-ajax'] );
203 } // B. Shoptimizer theme
204 else if ( ! empty( $_REQUEST['action'] ) ) {
205 $action = sanitize_title( $_REQUEST['action'] );
206 }
207
208 // Allowed action names
209 $allowed_actions = array( 'shoptimizer_pdp_ajax_atc', 'get_refreshed_fragments' );
210
211 if ( ! empty( $action ) && in_array( $action, $allowed_actions ) ) {
212 $translated_post_id = apply_filters( 'wpml_object_id', $post->ID, 'page' );
213 $permalink = ( $translated_post_id !== $post->ID ) ? get_permalink( $translated_post_id ) : $permalink;
214 }
215
216 return $permalink;
217 }
218
219 /**
220 * 4FA. Add a new column to the WooCommerce CSV Import/Export tool
221 *
222 * @param array $columns The array of columns to be displayed.
223 *
224 * @return array The $columns array.
225 */
226 function woocommerce_csv_custom_uri_column( $columns ) {
227 if ( ! is_array( $columns ) ) {
228 return $columns;
229 }
230
231 $label = __( 'Custom URI', 'permalink-manager' );
232 $key = 'custom_uri';
233
234 if ( current_filter() == 'woocommerce_csv_product_import_mapping_default_columns' ) {
235 $columns[ $label ] = $key;
236 } else {
237 $columns[ $key ] = $label;
238 }
239
240 return $columns;
241 }
242
243 /**
244 * 4FB. Return the custom permalink of the product if it exists, otherwise return the default URI
245 *
246 * @param string $value The value of the column.
247 * @param WC_Product $product The product object.
248 * @param mixed $column_id The column ID.
249 *
250 * @return string The custom permalink or default permalink
251 */
252 function woocommerce_export_custom_uri_value( $value, $product, $column_id ) {
253 if ( empty( $value ) && ! empty( $product ) ) {
254 $product_id = $product->get_id();
255
256 // Get custom permalink or default permalink
257 $value = Permalink_Manager_URI_Functions_Post::get_post_uri( $product_id );
258 }
259
260 return $value;
261 }
262
263 /**
264 * 4FC. Set the custom URI for the product using the value from CSV file, if not set use the default permalink
265 *
266 * @param WC_Product $product The product object.
267 * @param array $data The data array for the current row being imported.
268 */
269 function woocommerce_csv_import_custom_uri( $product, $data ) {
270 global $permalink_manager_uris;
271
272 if ( ! empty( $product ) ) {
273 $product_id = $product->get_id();
274
275 // Ignore variations
276 if ( $product->get_type() == 'variation' ) {
277 return;
278 }
279
280 // A. Use default permalink if "Custom URI" is not set and did not exist before
281 if ( empty( $permalink_manager_uris[ $product_id ] ) && empty( $data['custom_uri'] ) ) {
282 $custom_uri = Permalink_Manager_URI_Functions_Post::get_default_post_uri( $product_id, false, true );
283 } else if ( ! empty( $data['custom_uri'] ) ) {
284 $custom_uri = Permalink_Manager_Helper_Functions::sanitize_title( $data['custom_uri'] );
285 } else {
286 return;
287 }
288
289 Permalink_Manager_URI_Functions::save_single_uri( $product_id, $custom_uri, false, true );
290 }
291 }
292
293 /**
294 * Declare support for 'High-Performance order storage (COT)' in WooCommerce
295 */
296 function woocommerce_cot_compatibility() {
297 if ( class_exists( '\Automattic\WooCommerce\Utilities\FeaturesUtil' ) && method_exists( '\Automattic\WooCommerce\Utilities\FeaturesUtil', 'declare_compatibility' ) ) {
298 $plugin_name = strtok( PERMALINK_MANAGER_BASENAME, '/' );
299 \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', $plugin_name );
300 }
301 }
302
303 /**
304 * Extract the Wishlist ID from the URI and add it to the $uri_parts array (WooCommerce Wishlist Plugin)
305 *
306 * @param array $uri_parts An array of the URI parts.
307 * @param string $request_url The URL that was requested.
308 * @param array $endpoints An array of all the endpoints that are currently registered.
309 *
310 * @return array The URI parts.
311 */
312 function ti_woocommerce_wishlist_uris( $uri_parts, $request_url, $endpoints ) {
313 global $permalink_manager_uris;
314
315 $wishlist_pid = function_exists( 'tinv_get_option' ) ? tinv_get_option( 'general', 'page_wishlist' ) : '';
316
317 // Find the Wishlist page URI
318 if ( is_numeric( $wishlist_pid ) && ! empty( $permalink_manager_uris[ $wishlist_pid ] ) ) {
319 $wishlist_uri = preg_quote( $permalink_manager_uris[ $wishlist_pid ], '/' );
320
321 // Extract the Wishlist ID
322 preg_match( "/^({$wishlist_uri})\/([^\/]+)\/?$/", $uri_parts['uri'], $output_array );
323
324 if ( ! empty( $output_array[2] ) ) {
325 $uri_parts['uri'] = $output_array[1];
326 $uri_parts['endpoint'] = 'tinvwlID';
327 $uri_parts['endpoint_value'] = $output_array[2];
328 }
329 }
330
331 return $uri_parts;
332 }
333
334 /**
335 * Keep the query strings appended to the product permalinks by WooCommerce Subscriptions
336 *
337 * @param string $permalink
338 * @param WP_Post $post
339 * @param string $old_permalink
340 *
341 * @return string
342 */
343 function wcs_fix_subscription_links( $permalink, $post, $old_permalink ) {
344 if ( ! empty( $post->post_type ) && $post->post_type == 'product' && strpos( $old_permalink, 'switch-subscription=' ) !== false ) {
345 $query_arg = parse_url( $old_permalink, PHP_URL_QUERY );
346 $permalink = "{$permalink}?{$query_arg}";
347 }
348
349 return $permalink;
350 }
351 }