PluginProbe ʕ •ᴥ•ʔ
Permalink Manager Lite / 2.6.0
Permalink Manager Lite v2.6.0
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 / permalink-manager.php
permalink-manager Last commit date
includes 3 days ago languages 3 days ago out 3 days ago LICENSE.txt 1 year ago README.txt 3 days ago permalink-manager.php 3 days ago
permalink-manager.php
401 lines
1 <?php
2
3 /**
4 * Plugin Name: Permalink Manager Lite
5 * Plugin URI: https://permalinkmanager.pro?utm_source=plugin
6 * Description: Advanced plugin that allows to set up custom permalinks (bulk editors included), slugs and permastructures (WooCommerce compatible).
7 * Version: 2.6.0
8 * Author: Maciej Bis
9 * Author URI: http://maciejbis.net/
10 * License: GPL-2.0+
11 * License URI: http://www.gnu.org/licenses/gpl-2.0.txt
12 * Text Domain: permalink-manager
13 * Domain Path: /languages
14 * WC requires at least: 3.0.0
15 * WC tested up to: 11.0.0
16 */
17
18 // If this file is called directly or plugin is already defined, abort
19 if ( ! defined( 'WPINC' ) ) {
20 die;
21 }
22
23 if ( ! class_exists( 'Permalink_Manager_Class' ) ) {
24
25 // Define the directories used to load plugin files.
26 define( 'PERMALINK_MANAGER_PLUGIN_NAME', 'Permalink Manager' );
27 define( 'PERMALINK_MANAGER_PLUGIN_SLUG', 'permalink-manager' );
28 define( 'PERMALINK_MANAGER_VERSION', '2.6.0' );
29 define( 'PERMALINK_MANAGER_FILE', __FILE__ );
30 define( 'PERMALINK_MANAGER_DIR', untrailingslashit( dirname( __FILE__ ) ) );
31 define( 'PERMALINK_MANAGER_BASENAME', plugin_basename( __FILE__ ) );
32 define( 'PERMALINK_MANAGER_URL', untrailingslashit( plugins_url( '', __FILE__ ) ) );
33 define( 'PERMALINK_MANAGER_WEBSITE', 'https://permalinkmanager.pro' );
34
35 /**
36 * The base class responsible for loading the plugin data as well as any plugin subclasses and additional functions
37 */
38 class Permalink_Manager_Class {
39 public $permalink_manager_options;
40 public $functions;
41
42 /**
43 * Get options from DB, load subclasses & hooks
44 */
45 public function __construct() {
46 $this->include_subclasses();
47 $this->register_init_hooks();
48 }
49
50 /**
51 * Include back-end classes and set their instances
52 */
53 function include_subclasses() {
54 // WP_List_Table needed for post types & taxonomies editors
55 if ( ! class_exists( 'WP_List_Table' ) ) {
56 require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
57 }
58
59 $classes = array(
60 'core' => array(
61 'helper-functions' => 'Permalink_Manager_Helper_Functions',
62 'uri-functions' => 'Permalink_Manager_URI_Functions',
63 'uri-functions-post' => 'Permalink_Manager_URI_Functions_Post',
64 'uri-functions-tax' => 'Permalink_Manager_URI_Functions_Tax',
65 'admin-functions' => 'Permalink_Manager_Admin_Functions',
66 'actions' => 'Permalink_Manager_Actions',
67 'core-functions' => 'Permalink_Manager_Core_Functions',
68 'permastructures-functions' => 'Permalink_Manager_Permastructure_Functions',
69 'gutenberg' => 'Permalink_Manager_Gutenberg',
70 'debug' => 'Permalink_Manager_Debug_Functions',
71 'pro-license' => 'Permalink_Manager_Pro_License',
72 'pro-functions' => 'Permalink_Manager_Pro_Functions'
73 ),
74 'integrations' => array(
75 'third-parties' => 'Permalink_Manager_Third_Parties',
76 'woocommerce' => 'Permalink_Manager_WooCommerce',
77 'seo-plugins' => 'Permalink_Manager_SEO_Plugins',
78 'language-plugins' => 'Permalink_Manager_Language_Plugins',
79 'rest-api' => 'Permalink_Manager_REST_API'
80 ),
81 'views' => array(
82 'ui-elements' => 'Permalink_Manager_UI_Elements',
83 'uri-editor' => 'Permalink_Manager_URI_Editor',
84 'tools' => 'Permalink_Manager_Tools',
85 'permastructures' => 'Permalink_Manager_Permastructs',
86 'settings' => 'Permalink_Manager_Settings',
87 'debug' => 'Permalink_Manager_Debug',
88 'pro-addons' => 'Permalink_Manager_Pro_Addons',
89 'help' => 'Permalink_Manager_Help',
90 'setup-wizard' => 'Permalink_Manager_Setup_Wizard',
91 'uri-editor-tax' => false,
92 'uri-editor-post' => false
93 )
94 );
95
96 // Load classes and set-up their instances
97 foreach ( $classes as $class_type => $classes_array ) {
98 foreach ( $classes_array as $class => $class_name ) {
99 $filename = PERMALINK_MANAGER_DIR . "/includes/{$class_type}/permalink-manager-{$class}.php";
100
101 if ( file_exists( $filename ) ) {
102 require_once $filename;
103 if ( $class_name ) {
104 $this->functions[ $class ] = new $class_name();
105 }
106 }
107 }
108 }
109 }
110
111 /**
112 * Register general hooks
113 */
114 public function register_init_hooks() {
115 // Localize plugin
116 add_action( 'init', array( $this, 'localize_me' ), 1 );
117
118 // Support deprecated hooks
119 add_action( 'plugins_loaded', array( $this, 'deprecated_hooks' ), 9 );
120
121 // Deactivate free version if Permalink Manager Pro is activated
122 add_action( 'plugins_loaded', array( $this, 'is_pro_activated' ), 9 );
123
124 // Load globals & options
125 add_action( 'plugins_loaded', array( $this, 'get_options_and_globals' ), 9 );
126 add_action( 'init', array( $this, 'get_output_globals' ), 9 );
127
128 // Legacy support
129 add_action( 'init', array( $this, 'legacy_support' ), 2 );
130
131 // Default settings & alerts
132 add_filter( 'permalink_manager_options', array( $this, 'default_settings' ), 1 );
133 add_filter( 'permalink_manager_alerts', array( $this, 'default_alerts' ), 1 );
134 }
135
136 /**
137 * Localize this plugin
138 */
139 function localize_me() {
140 // phpcs:ignore PluginCheck.CodeAnalysis.DiscouragedFunctions.load_plugin_textdomainFound -- Make sure that the same textdomain is loaded for both Lite and Pro versions
141 load_plugin_textdomain( 'permalink-manager', false, basename( dirname( __FILE__ ) ) . "/languages" );
142 }
143
144 /**
145 * Get options values & set global variables
146 */
147 public function get_options_and_globals() {
148 // 1. Globals with data stored in DB
149 global $permalink_manager_options, $permalink_manager_uris, $permalink_manager_permastructs, $permalink_manager_redirects, $permalink_manager_external_redirects;
150
151 $permalink_manager_options = (array) apply_filters( 'permalink_manager_options', get_option( 'permalink-manager', array() ) );
152 $permalink_manager_uris = (array) apply_filters( 'permalink_manager_uris', get_option( 'permalink-manager-uris', array() ) );
153 $permalink_manager_permastructs = (array) apply_filters( 'permalink_manager_permastructs', get_option( 'permalink-manager-permastructs', array() ) );
154 $permalink_manager_redirects = (array) apply_filters( 'permalink_manager_redirects', get_option( 'permalink-manager-redirects', array() ) );
155 $permalink_manager_external_redirects = (array) apply_filters( 'permalink_manager_external_redirects', get_option( 'permalink-manager-external-redirects', array() ) );
156 }
157
158 /**
159 * Get global variables
160 */
161 public function get_output_globals() {
162 // 2. Globals used to display additional content (e.g. alerts)
163 global $permalink_manager_alerts, $permalink_manager_before_sections_html, $permalink_manager_after_sections_html;
164
165 $permalink_manager_alerts = apply_filters( 'permalink_manager_alerts', array() );
166 $permalink_manager_before_sections_html = apply_filters( 'permalink_manager_before_sections', '' );
167 $permalink_manager_after_sections_html = apply_filters( 'permalink_manager_after_sections', '' );
168 }
169
170 /**
171 * Set the initial/default settings (including "Screen Options")
172 *
173 * @param array $settings
174 *
175 * @return array
176 */
177 public function default_settings( $settings ) {
178 $default_settings = apply_filters( 'permalink_manager_default_options', array(
179 'screen-options' => array(
180 'per_page' => 20,
181 'post_statuses' => array( 'publish' ),
182 'group' => false
183 ),
184 'general' => array(
185 'auto_update_uris' => 0,
186 'show_native_slug_field' => 0,
187 'pagination_redirect' => 0,
188 'sslwww_redirect' => 1,
189 'canonical_redirect' => 1,
190 'old_slug_redirect' => 0,
191 'setup_redirects' => 0,
192 'redirect' => '301',
193 'extra_redirects' => 1,
194 'copy_query_redirect' => 1,
195 'trailing_slashes' => 0,
196 'trailing_slash_redirect' => 1,
197 'auto_fix_duplicates' => 0,
198 'fix_language_mismatch' => 0,
199 'wpml_support' => 1,
200 'wpml_translate_mode' => 0,
201 'pmxi_support' => 1,
202 'um_support' => 1,
203 'yoast_breadcrumbs' => 0,
204 'rankmath_redirect' => 1,
205 'primary_category' => 1,
206 'force_custom_slugs' => 0,
207 'disable_slug_sanitization' => 0,
208 'keep_accents' => 0,
209 'partial_disable' => array(
210 'post_types' => array( 'attachment', 'tribe_events', 'e-landing-page' )
211 ),
212 'partial_disable_strict' => 1,
213 'ignore_drafts' => 1,
214 'edit_uris_cap' => 'publish_posts',
215 'force_unique_uris' => 0,
216 'debug_mode' => 0
217 ),
218 'licence' => array()
219 ) );
220
221 // Check if settings array is empty
222 $settings_empty = empty( $settings );
223
224 // Apply the default settings (if empty values) in all settings sections
225 foreach ( $default_settings as $group_name => $fields ) {
226 foreach ( $fields as $field_name => $field ) {
227 if ( $settings_empty || ( ! isset( $settings[ $group_name ][ $field_name ] ) && strpos( $field_name, 'partial_disable' ) === false ) ) {
228 $settings[ $group_name ][ $field_name ] = $field;
229 }
230 }
231 }
232
233 return $settings;
234 }
235
236 /**
237 * Set the initial/default admin notices
238 *
239 * @param array $alerts
240 *
241 * @return array
242 */
243 public function default_alerts( $alerts ) {
244 $website_url = Permalink_Manager_Admin_Functions::get_plugin_website_url( 'pricing' );
245
246 $default_alerts = apply_filters( 'permalink_manager_default_alerts', array(
247 'aug26-promo' => array(
248 'txt' => sprintf( "<strong>Save 30%% on Permalink Manager Pro</strong><br />Get custom taxonomy and WooCommerce support, custom fields in permalinks, and priority email support. <a href=\"%s\" target=\"_blank\">Upgrade today</a> and save 30%% with code <code>SUMMER26</code>.", $website_url ),
249 'type' => 'notice-info',
250 'show' => 'pro_hide',
251 'plugin_only' => false,
252 'until' => '2026-08-15'
253 )
254 ) );
255
256 // Apply the default settings (if empty values) in all settings sections
257 return (array) $alerts + (array) $default_alerts;
258 }
259
260 /**
261 * Make sure that the Permalink Manager options stored in DB match the new structure
262 */
263 function legacy_support() {
264 global $permalink_manager_permastructs, $permalink_manager_options;
265
266 if ( isset( $permalink_manager_options['base-editor'] ) ) {
267 $new_options['post_types'] = $permalink_manager_options['base-editor'];
268 update_option( 'permalink-manager-permastructs', $new_options );
269 } else if ( empty( $permalink_manager_permastructs['post_types'] ) && empty( $permalink_manager_permastructs['taxonomies'] ) && count( $permalink_manager_permastructs ) > 0 ) {
270 $new_options['post_types'] = $permalink_manager_permastructs;
271 update_option( 'permalink-manager-permastructs', $new_options );
272 }
273
274 // Separate "Trailing slashes" & "Trailing slashes redirect" setting fields
275 if ( ! empty( $permalink_manager_options['general']['trailing_slashes'] ) && $permalink_manager_options['general']['trailing_slashes'] >= 10 ) {
276 $permalink_manager_unfiltered_options = ( ! empty( $permalink_manager_unfiltered_options ) ) ? $permalink_manager_unfiltered_options : $permalink_manager_options;
277
278 $permalink_manager_unfiltered_options['general']['trailing_slashes_redirect'] = 1;
279 $permalink_manager_unfiltered_options['general']['trailing_slashes'] = ( $permalink_manager_options['general']['trailing_slashes'] == 10 ) ? 1 : 2;
280 }
281
282 // Save the settings in database
283 if ( ! empty( $permalink_manager_unfiltered_options ) ) {
284 update_option( 'permalink-manager', $permalink_manager_unfiltered_options );
285 }
286
287 // Remove obsolete 'permalink-manager-alerts' from wp_options table
288 if ( get_option( 'permalink-manager-alerts' ) ) {
289 delete_option( 'permalink-manager-alerts' );
290 }
291 }
292
293 /**
294 * Return the array of deprecated hooks
295 *
296 * @return array
297 */
298 function deprecated_hooks_list() {
299 return array(
300 'permalink_manager_default_options' => 'permalink-manager-default-options',
301 'permalink_manager_options' => 'permalink-manager-options',
302 'permalink_manager_uris' => 'permalink-manager-uris',
303 'permalink_manager_redirects' => 'permalink-manager-redirects',
304 'permalink_manager_external_redirects' => 'permalink-manager-external-redirects',
305 'permalink_manager_permastructs' => 'permalink-manager-permastructs',
306
307 'permalink_manager_alerts' => 'permalink-manager-alerts',
308 'permalink_manager_before_sections' => 'permalink-manager-before-sections',
309 'permalink_manager_sections' => 'permalink-manager-sections',
310 'permalink_manager_after_sections' => 'permalink-manager-after-sections',
311
312 'permalink_manager_field_args' => 'permalink-manager-field-args',
313 'permalink_manager_field_output' => 'permalink-manager-field-output',
314
315 'permalink_manager_deep_uri_detect' => 'permalink-manager-deep-uri-detect',
316 'permalink_manager_detect_uri' => 'permalink-manager-detect-uri',
317 'permalink_manager_detected_element_id' => 'permalink-manager-detected-initial-id',
318 'permalink_manager_detected_term_id' => 'permalink-manager-detected-term-id',
319 'permalink_manager_detected_post_id' => 'permalink-manager-detected-post-id',
320
321 'permalink_manager_primary_term' => 'permalink-manager-primary-term',
322 'permalink_manager_disabled_post_types' => 'permalink-manager-disabled-post-types',
323 'permalink_manager_disabled_taxonomies' => 'permalink-manager-disabled-taxonomies',
324 'permalink_manager_endpoints' => 'permalink-manager-endpoints',
325 'permalink_manager_filter_permalink_base' => 'permalink_manager-filter-permalink-base',
326 'permalink_manager_force_lowercase_uris' => 'permalink-manager-force-lowercase-uris',
327
328 'permalink_manager_uri_editor_extra_info' => 'permalink-manager-uri-editor-extra-info',
329 'permalink_manager_debug_fields' => 'permalink-manager-debug-fields',
330 'permalink_manager_permastructs_fields' => 'permalink-manager-permastructs-fields',
331 'permalink_manager_settings_fields' => 'permalink-manager-settings-fields',
332 'permalink_manager_tools_fields' => 'permalink-manager-tools-fields',
333
334 'permalink_manager_uri_editor_columns' => 'permalink-manager-uri-editor-columns',
335 'permalink_manager_uri_editor_column_content' => 'permalink-manager-uri-editor-column-content',
336
337 'permalink_manager_redirect_shop_archive' => 'permalink-manager-redirect-shop-archive'
338 );
339 }
340
341 /**
342 * Map the deprecated hooks to their relevant equivalents.
343 */
344 function deprecated_hooks() {
345 $deprecated_filters = $this->deprecated_hooks_list();
346 foreach ( $deprecated_filters as $new => $old ) {
347 add_filter( $new, array( $this, 'deprecated_hooks_mapping' ), - 1000, 8 );
348 }
349 }
350
351 /**
352 * Apply the deprecated filters to the relevant hooks
353 *
354 * @param mixed $data
355 *
356 * @return mixed
357 */
358 function deprecated_hooks_mapping( $data ) {
359 $deprecated_filters = $this->deprecated_hooks_list();
360 $filter = current_filter();
361
362 if ( isset( $deprecated_filters[ $filter ] ) ) {
363 if ( has_filter( $deprecated_filters[ $filter ] ) ) {
364 do_action( 'deprecated_function_run', $deprecated_filters[ $filter ], $filter, '2.4.3' ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- Use built-in mechanism for flagging
365
366 $args = func_get_args();
367 $data = apply_filters_ref_array( $deprecated_filters[ $filter ], $args ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.DynamicHooknameFound
368 }
369 }
370
371 return $data;
372 }
373
374 /**
375 * Deactivate Permalink Manager Lite if Permalink Manager Pro is enabled
376 */
377 function is_pro_activated() {
378 if ( function_exists( 'is_plugin_active' ) && is_plugin_active( 'permalink-manager/permalink-manager.php' ) && is_plugin_active( 'permalink-manager-pro/permalink-manager.php' ) ) {
379 deactivate_plugins( 'permalink-manager/permalink-manager.php' );
380 }
381 }
382
383 }
384
385 /**
386 * Begins execution of the plugin
387 */
388 function permalink_manager_run() {
389 global $permalink_manager;
390
391 // Do not run when Elementor is opened
392 // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- No data is processed here
393 if ( ( ! empty( $_REQUEST['action'] ) && is_string( $_REQUEST['action'] ) && strpos( $_REQUEST['action'], 'elementor' ) !== false ) || isset( $_REQUEST['elementor-preview'] ) || isset( $_REQUEST['disable-pm'] ) ) {
394 return;
395 }
396
397 $permalink_manager = new Permalink_Manager_Class();
398 }
399
400 permalink_manager_run();
401 }