PluginProbe ʕ •ᴥ•ʔ
Permalink Manager Lite / 2.4.3.3
Permalink Manager Lite v2.4.3.3
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
357 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_declare_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' || Permalink_Manager_Helper_Functions::is_post_excluded( $product_id, true ) ) {
140 return;
141 }
142
143 $custom_uri = Permalink_Manager_URI_Functions_Post::get_default_post_uri( $product_id, false, true );
144 Permalink_Manager_URI_Functions::save_single_uri( $product_id, $custom_uri, false, true );
145 }
146 }
147
148 /**
149 * If the URI contains %pa_attribute_name% tag, replace it with the value of the attribute
150 *
151 * @param string $default_uri The default custom permalink that WordPress would use for the post.
152 * @param string $slug The post slug.
153 * @param WP_Post $post The post object.
154 * @param string $post_name The post slug.
155 * @param bool $native_uri true if the URI is a native URI, false if it's a custom URI
156 *
157 * @return string The default custom permalink
158 */
159 function woocommerce_product_attributes( $default_uri, $slug, $post, $post_name, $native_uri ) {
160 // Do not affect native URIs
161 if ( $native_uri ) {
162 return $default_uri;
163 }
164
165 // Use only for products
166 if ( empty( $post->post_type ) || $post->post_type !== 'product' ) {
167 return $default_uri;
168 }
169
170 preg_match_all( "/%pa_(.[^\%]+)%/", $default_uri, $custom_fields );
171
172 if ( ! empty( $custom_fields[1] ) ) {
173 $product = wc_get_product( $post->ID );
174
175 foreach ( $custom_fields[1] as $i => $custom_field ) {
176 $attribute_name = sanitize_title( $custom_field );
177 $attribute_value = $product->get_attribute( $attribute_name );
178
179 $default_uri = str_replace( $custom_fields[0][ $i ], Permalink_Manager_Helper_Functions::sanitize_title( $attribute_value ), $default_uri );
180 }
181 }
182
183 return $default_uri;
184 }
185
186 /**
187 * Check the current request is a WooCommerce AJAX request. If it is, check the translated page's URL should be returned
188 *
189 * @param string $permalink The full URL of the post
190 * @param WP_Post $post The post object
191 * @param string $old_permalink The original URL of the post.
192 *
193 * @return string The permalink is being returned.
194 */
195 function woocommerce_translate_ajax_fragments_urls( $permalink, $post, $old_permalink ) {
196 // Use it only if the permalinks are different
197 if ( $permalink == $old_permalink || $post->post_type !== 'page' ) {
198 return $permalink;
199 }
200
201 // A. Native WooCommerce AJAX events
202 if ( ! empty( $_REQUEST['wc-ajax'] ) ) {
203 $action = sanitize_title( $_REQUEST['wc-ajax'] );
204 } // B. Shoptimizer theme
205 else if ( ! empty( $_REQUEST['action'] ) ) {
206 $action = sanitize_title( $_REQUEST['action'] );
207 }
208
209 // Allowed action names
210 $allowed_actions = array( 'shoptimizer_pdp_ajax_atc', 'get_refreshed_fragments' );
211
212 if ( ! empty( $action ) && in_array( $action, $allowed_actions ) ) {
213 $translated_post_id = apply_filters( 'wpml_object_id', $post->ID, 'page' );
214 $permalink = ( $translated_post_id !== $post->ID ) ? get_permalink( $translated_post_id ) : $permalink;
215 }
216
217 return $permalink;
218 }
219
220 /**
221 * 4FA. Add a new column to the WooCommerce CSV Import/Export tool
222 *
223 * @param array $columns The array of columns to be displayed.
224 *
225 * @return array The $columns array.
226 */
227 function woocommerce_csv_custom_uri_column( $columns ) {
228 if ( ! is_array( $columns ) ) {
229 return $columns;
230 }
231
232 $label = __( 'Custom URI', 'permalink-manager' );
233 $key = 'custom_uri';
234
235 if ( current_filter() == 'woocommerce_csv_product_import_mapping_default_columns' ) {
236 $columns[ $label ] = $key;
237 } else {
238 $columns[ $key ] = $label;
239 }
240
241 return $columns;
242 }
243
244 /**
245 * 4FB. Return the custom permalink of the product if it exists, otherwise return the default URI
246 *
247 * @param string $value The value of the column.
248 * @param WC_Product $product The product object.
249 * @param mixed $column_id The column ID.
250 *
251 * @return string The custom permalink or default permalink
252 */
253 function woocommerce_export_custom_uri_value( $value, $product, $column_id ) {
254 if ( empty( $value ) && ! empty( $product ) ) {
255 $product_id = $product->get_id();
256
257 // Get custom permalink or default permalink
258 $value = Permalink_Manager_URI_Functions_Post::get_post_uri( $product_id );
259 }
260
261 return $value;
262 }
263
264 /**
265 * 4FC. Set the custom URI for the product using the value from CSV file, if not set use the default permalink
266 *
267 * @param WC_Product $product The product object.
268 * @param array $data The data array for the current row being imported.
269 */
270 function woocommerce_csv_import_custom_uri( $product, $data ) {
271 global $permalink_manager_uris;
272
273 if ( ! empty( $product ) ) {
274 $product_id = $product->get_id();
275
276 // Ignore variations
277 if ( $product->get_type() == 'variation' ) {
278 return;
279 }
280
281 // A. Use default permalink if "Custom URI" is not set and did not exist before
282 if ( empty( $permalink_manager_uris[ $product_id ] ) && empty( $data['custom_uri'] ) ) {
283 $custom_uri = Permalink_Manager_URI_Functions_Post::get_default_post_uri( $product_id, false, true );
284 } else if ( ! empty( $data['custom_uri'] ) ) {
285 $custom_uri = Permalink_Manager_Helper_Functions::sanitize_title( $data['custom_uri'] );
286 } else {
287 return;
288 }
289
290 Permalink_Manager_URI_Functions::save_single_uri( $product_id, $custom_uri, false, true );
291 }
292 }
293
294 /**
295 * Declare support for 'High-Performance order storage (COT)' and other features in WooCommerce
296 */
297 function woocommerce_declare_compatibility() {
298 $features_util_class = '\Automattic\WooCommerce\Utilities\FeaturesUtil';
299
300 if ( class_exists( $features_util_class ) && method_exists( $features_util_class, 'declare_compatibility' ) ) {
301 $features = method_exists( $features_util_class, 'get_features' ) ? $features_util_class::get_features( true ) : array();
302
303 foreach ( array_keys( $features ) as $feature ) {
304 $features_util_class::declare_compatibility( $feature, PERMALINK_MANAGER_BASENAME );
305 }
306 }
307 }
308
309 /**
310 * Extract the Wishlist ID from the URI and add it to the $uri_parts array (WooCommerce Wishlist Plugin)
311 *
312 * @param array $uri_parts An array of the URI parts.
313 * @param string $request_url The URL that was requested.
314 * @param array $endpoints An array of all the endpoints that are currently registered.
315 *
316 * @return array The URI parts.
317 */
318 function ti_woocommerce_wishlist_uris( $uri_parts, $request_url, $endpoints ) {
319 global $permalink_manager_uris;
320
321 $wishlist_pid = function_exists( 'tinv_get_option' ) ? tinv_get_option( 'general', 'page_wishlist' ) : '';
322
323 // Find the Wishlist page URI
324 if ( is_numeric( $wishlist_pid ) && ! empty( $permalink_manager_uris[ $wishlist_pid ] ) ) {
325 $wishlist_uri = preg_quote( $permalink_manager_uris[ $wishlist_pid ], '/' );
326
327 // Extract the Wishlist ID
328 preg_match( "/^({$wishlist_uri})\/([^\/]+)\/?$/", $uri_parts['uri'], $output_array );
329
330 if ( ! empty( $output_array[2] ) ) {
331 $uri_parts['uri'] = $output_array[1];
332 $uri_parts['endpoint'] = 'tinvwlID';
333 $uri_parts['endpoint_value'] = $output_array[2];
334 }
335 }
336
337 return $uri_parts;
338 }
339
340 /**
341 * Keep the query strings appended to the product permalinks by WooCommerce Subscriptions
342 *
343 * @param string $permalink
344 * @param WP_Post $post
345 * @param string $old_permalink
346 *
347 * @return string
348 */
349 function wcs_fix_subscription_links( $permalink, $post, $old_permalink ) {
350 if ( ! empty( $post->post_type ) && $post->post_type == 'product' && strpos( $old_permalink, 'switch-subscription=' ) !== false ) {
351 $query_arg = parse_url( $old_permalink, PHP_URL_QUERY );
352 $permalink = "{$permalink}?{$query_arg}";
353 }
354
355 return $permalink;
356 }
357 }