PluginProbe
WP EXtra – One Click Optimize / 8.7.0
WP EXtra – One Click Optimize v8.7.0
8.7.1 8.6.8 8.7.0 trunk 5.9 8.0 8.5.0 8.5.4 8.5.5 8.6.0 8.6.1 8.6.2 8.6.3 8.6.5
wp-extra / src / Modules / Common / Permalinks.php

Permalinks.php in WP EXtra – One Click Optimize 8.7.0, at src/Modules/Common/Permalinks.php

260 lines 9.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace WPEXtra\Modules\Common;
3
4 if ( ! defined( 'ABSPATH' ) ) {
5 exit;
6 }
7
8 use WPEXtra\Settings;
9 use WPEXtra\Helper;
10 use WPEXtra\Base;
11
12 class Permalinks extends Base {
13
14 public function __construct() {
15 parent::__construct();
16 add_action('update_option_wp_extra', [$this, 'sync_rewrite_rules'], 10, 2);
17 }
18
19 public function sync_rewrite_rules($old_value, $value) {
20 $keys = ['slug_post_type', 'slug_taxonomy'];
21 $needs_flush = false;
22 foreach ($keys as $key) {
23 if (($old_value[$key] ?? null) !== ($value[$key] ?? null)) {
24 $needs_flush = true;
25 break;
26 }
27 }
28 if ($needs_flush) {
29 flush_rewrite_rules(false);
30 }
31 }
32
33 protected $features = [
34 'external_links',
35 'redirect_attachment',
36 'redirect_single_post',
37 'slug_post_type',
38 'slug_taxonomy',
39 'robots_txt',
40 ];
41
42 public function external_links() {
43 add_filter('the_content', [$this, 'filter_external_links'], 99);
44 }
45
46 public function filter_external_links($content) {
47 if (empty($content) || !is_string($content)) {
48 return $content;
49 }
50
51 $site_host = wp_parse_url(home_url(), PHP_URL_HOST);
52
53 if (class_exists('\WP_HTML_Tag_Processor')) {
54 $processor = new \WP_HTML_Tag_Processor($content);
55
56 while ($processor->next_tag(['tag_name' => 'a'])) {
57 $href = (string) $processor->get_attribute('href');
58 if ($href && preg_match('#^https?://#i', $href)) {
59 $link_host = wp_parse_url($href, PHP_URL_HOST);
60 if ($link_host && strcasecmp($link_host, $site_host) !== 0) {
61 $processor->set_attribute('target', '_blank');
62
63 $rel = (string) $processor->get_attribute('rel');
64 $rel_parts = array_filter(array_map('trim', explode(' ', $rel)));
65
66 if (!in_array('nofollow', $rel_parts, true)) {
67 $rel_parts[] = 'nofollow';
68 }
69 if (!in_array('noopener', $rel_parts, true)) {
70 $rel_parts[] = 'noopener';
71 }
72 if (!in_array('noreferrer', $rel_parts, true)) {
73 $rel_parts[] = 'noreferrer';
74 }
75
76 $processor->set_attribute('rel', implode(' ', array_unique($rel_parts)));
77 }
78 }
79 }
80
81 return $processor->get_updated_html();
82 }
83
84 // Regex fallback
85 return preg_replace_callback('/<a\s+([^>]+)>/i', function($matches) use ($site_host) {
86 $attrs = $matches[1];
87 if (preg_match('/href=["\'](https?:\/\/[^"\']+)["\']/i', $attrs, $url_match)) {
88 $link_host = wp_parse_url($url_match[1], PHP_URL_HOST);
89 if ($link_host && strcasecmp($link_host, $site_host) !== 0) {
90 if (!preg_match('/target=["\']/i', $attrs)) {
91 $attrs .= ' target="_blank"';
92 }
93 if (preg_match('/rel=["\']([^"\']*)["\']/i', $attrs, $rel_match)) {
94 $rel = $rel_match[1];
95 if (strpos($rel, 'nofollow') === false) $rel .= ' nofollow';
96 if (strpos($rel, 'noopener') === false) $rel .= ' noopener';
97 if (strpos($rel, 'noreferrer') === false) $rel .= ' noreferrer';
98 $attrs = preg_replace('/rel=["\'][^"\']*["\']/i', 'rel="' . trim($rel) . '"', $attrs);
99 } else {
100 $attrs .= ' rel="nofollow noopener noreferrer"';
101 }
102 }
103 }
104 return '<a ' . trim($attrs) . '>';
105 }, $content);
106 }
107
108 public function redirect_attachment() {
109 add_action('template_redirect', [$this, 'redirect_attachment_page']);
110 }
111
112 public function redirect_attachment_page() {
113 if (is_attachment()) {
114 global $post;
115 if ($post && !empty($post->post_parent)) {
116 wp_safe_redirect(esc_url(get_permalink($post->post_parent)), 301);
117 exit;
118 } else {
119 wp_safe_redirect(esc_url(home_url('/')), 301);
120 exit;
121 }
122 }
123 }
124
125 public function redirect_single_post() {
126 add_action('template_redirect', [$this, 'search_results_return_one_post']);
127 }
128
129 public function search_results_return_one_post() {
130 if (is_search()) {
131 global $wp_query;
132 if ($wp_query && $wp_query->post_count == 1 && $wp_query->max_num_pages == 1 && !empty($wp_query->posts[0])) {
133 wp_safe_redirect(get_permalink($wp_query->posts[0]->ID));
134 exit;
135 }
136 }
137 }
138
139 public function robots_txt() {
140 add_filter('robots_txt', [$this, 'filter_robots_txt'], 99, 2);
141 }
142
143 public function filter_robots_txt($output, $public) {
144 $custom = Helper::get_option('robots_txt');
145 if (!empty($custom)) {
146 return $custom;
147 }
148 return $output;
149 }
150
151 public function slug_post_type() {
152 add_action('pre_get_posts', [$this, 'rempostslug_parse_request'], 1, 1);
153 add_filter('post_type_link', [$this, 'rempostslug_fun'], 10, 3);
154 add_filter('get_the_permalink', [$this, 'rempostslug_fun'], 10, 3);
155 add_filter('the_permalink', [$this, 'rempostslug_fun'], 10, 3);
156 }
157
158 public function slug_taxonomy() {
159 add_filter('request', [$this, 'remtaxslug_change_term_request'], 1, 1);
160 add_filter('term_link', [$this, 'remtaxslug_term_permalink'], 10, 2);
161 add_filter('get_category_link', [$this, 'remtaxslug_term_permalink'], 10, 3);
162 add_filter('get_term_link', [$this, 'remtaxslug_term_permalink'], 10, 3);
163 add_filter('category_link', [$this, 'remtaxslug_term_permalink'], 10, 3);
164 }
165
166 public function rempostslug_fun($post_link, $post) {
167 $post_type_list = (array) Helper::get_option('slug_post_type', []);
168 if (empty($post_type_list) || !($post instanceof \WP_Post)) {
169 return $post_link;
170 }
171 if (in_array(get_post_type($post), $post_type_list, true)) {
172 $post_link = trailingslashit(get_option('home')) . user_trailingslashit($post->post_name);
173 }
174 return $post_link;
175 }
176
177 public function rempostslug_parse_request($query) {
178 $post_type_list = (array) Helper::get_option('slug_post_type', []);
179 if (!$query->is_main_query() || count($query->query) !== 2 || !isset($query->query['page'])) {
180 return;
181 }
182 if (!empty($query->query['name']) && !empty($post_type_list)) {
183 $query->set('post_type', $post_type_list);
184 }
185 }
186
187 public function remtaxslug_change_term_request($query) {
188 $tax_names = (array) Helper::get_option('slug_taxonomy', []);
189 foreach ($tax_names as $current_tax_name) {
190 if (array_key_exists('attachment', $query) && $query['attachment']) {
191 $include_children = true;
192 $name = $query['attachment'];
193 } else {
194 $include_children = false;
195 $name = array_key_exists('name', $query) ? $query['name'] : '';
196 }
197
198 $term = get_term_by('slug', $name, $current_tax_name);
199
200 if (!empty($name) && !empty($term) && !is_wp_error($term)) {
201 if ($include_children) {
202 unset($query['attachment']);
203 $parent = $term->parent;
204 while ($parent) {
205 $parent_term = get_term($parent, $current_tax_name);
206 if ($parent_term && !is_wp_error($parent_term)) {
207 $name = $parent_term->slug . '/' . $name;
208 $parent = $parent_term->parent;
209 } else {
210 break;
211 }
212 }
213 } else {
214 unset($query['name']);
215 }
216
217 switch ($current_tax_name) {
218 case 'category':
219 $query['category_name'] = $name;
220 break;
221 case 'post_tag':
222 $query['tag'] = $name;
223 break;
224 default:
225 $query[$current_tax_name] = $name;
226 break;
227 }
228 }
229 }
230
231 return $query;
232 }
233
234 public function remtaxslug_term_permalink($url, $taxonomy) {
235 if (is_int($taxonomy)) {
236 $taxonomy_term = get_term($taxonomy);
237 if (!($taxonomy_term instanceof \WP_Term)) {
238 return $url;
239 }
240 $taxonomy_slug = $taxonomy_term->slug;
241 $taxonomy_name = $taxonomy_term->taxonomy;
242 } elseif (is_object($taxonomy) && isset($taxonomy->slug, $taxonomy->taxonomy)) {
243 $taxonomy_slug = $taxonomy->slug;
244 $taxonomy_name = $taxonomy->taxonomy;
245 } else {
246 return $url;
247 }
248 $saved_value = (array) Helper::get_option('slug_taxonomy', []);
249 if (empty($saved_value)) {
250 return $url;
251 }
252 if (in_array($taxonomy_name, $saved_value, true)) {
253 $url = trailingslashit(get_option('home')) . user_trailingslashit($taxonomy_slug);
254 }
255
256 return $url;
257 }
258
259 }
260