Version Description
- Reworked code
- Added settings page
- Added Debug mode for administrators (settings page)
- Added the ability to disable "Redirect to Homepage" if nothing found (settings page)
- Added the ability to choose between 301 or 302 HTTP Headers (settings page)
- Added the ability preview URL Redirections (settings page)
Download this release
Release Info
Developer | hwk-fr |
Plugin | WP 404 Auto Redirect to Similar Post |
Version | 0.7 |
Comparing to | |
See all releases |
Code changes from version 0.4.0.2 to 0.7
- logo.png +0 -0
- readme.txt +23 -15
- wp-404-auto-redirect-similar-post.js +28 -0
- wp-404-auto-redirect-similar-post.php +367 -238
logo.png
ADDED
Binary file
|
readme.txt
CHANGED
@@ -3,26 +3,28 @@ Contributors: hwk-fr
|
|
3 |
Donate link: http://hwk.fr/
|
4 |
Tags: 404, Redirect, 301, Similar Post, SEO, Broken Link, Webmaster Tools
|
5 |
Requires at least: 4.0
|
6 |
-
Tested up to: 4.
|
7 |
-
Stable tag: 0.
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
11 |
-
Automatically Redirect any 404 to a Similar Post based on the Title
|
12 |
|
13 |
== Description ==
|
14 |
|
15 |
Welcome to WP 404 Auto Redirect to Similar Post!
|
16 |
|
17 |
-
This plugin will automatically redirect all your 404 to a similar post
|
18 |
|
19 |
= Features: =
|
20 |
|
21 |
-
* Easy to Install / Uninstall.
|
22 |
* Automatically detect any 404
|
23 |
-
* Automatically search a similar post based on Title, Post Type, Category & Taxonomy
|
24 |
-
* Redirect to
|
25 |
-
*
|
|
|
|
|
26 |
|
27 |
= Requirements: =
|
28 |
|
@@ -34,18 +36,24 @@ This plugin will automatically redirect all your 404 to a similar post, based on
|
|
34 |
|
35 |
1. Upload the plugin files to the `/wp-content/plugins/wp-404-auto-redirect-similar-post` directory, or install the plugin through the WordPress plugins screen directly.
|
36 |
2. Activate the plugin through the 'Plugins' screen in WordPress.
|
37 |
-
3.
|
|
|
38 |
|
39 |
-
==
|
40 |
|
41 |
-
|
42 |
-
|
43 |
-
1. Post Title + Post Type
|
44 |
-
2. Category / Taxonomy
|
45 |
-
4. Homepage
|
46 |
|
47 |
== Changelog ==
|
48 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
49 |
= 0.4.0.2 =
|
50 |
* Fixed sanitization bug
|
51 |
* Fixed debug typo
|
3 |
Donate link: http://hwk.fr/
|
4 |
Tags: 404, Redirect, 301, Similar Post, SEO, Broken Link, Webmaster Tools
|
5 |
Requires at least: 4.0
|
6 |
+
Tested up to: 4.8.2
|
7 |
+
Stable tag: 0.7
|
8 |
License: GPLv2 or later
|
9 |
License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
10 |
|
11 |
+
Automatically Redirect any 404 to a Similar Post based on the Requested URL Title & Post Type using 301 or 302 Redirects!
|
12 |
|
13 |
== Description ==
|
14 |
|
15 |
Welcome to WP 404 Auto Redirect to Similar Post!
|
16 |
|
17 |
+
This plugin will automatically redirect all your 404 to a similar post based on Title & Post Types. If nothing similar is found, the plugin will redirect the 404 to the homepage.
|
18 |
|
19 |
= Features: =
|
20 |
|
21 |
+
* Easy to Install / Uninstall.
|
22 |
* Automatically detect any 404
|
23 |
+
* Automatically search a similar post based on the Title, Post Type, Category & Taxonomy
|
24 |
+
* **NEW** Redirect to Homepage if no similar post is found (can be disabled)
|
25 |
+
* **NEW** Choose the redirection HTTP header code: 301 or 302
|
26 |
+
* **NEW** Debug console for administrators
|
27 |
+
* **NEW** Preview URL directly from the admin panel
|
28 |
|
29 |
= Requirements: =
|
30 |
|
36 |
|
37 |
1. Upload the plugin files to the `/wp-content/plugins/wp-404-auto-redirect-similar-post` directory, or install the plugin through the WordPress plugins screen directly.
|
38 |
2. Activate the plugin through the 'Plugins' screen in WordPress.
|
39 |
+
3. Go to Settings > WP 404 Auto Redirect to change your settings.
|
40 |
+
4. Everything is ready! Modify an url in your browser to try to trigger a 404.
|
41 |
|
42 |
+
== Screenshots ==
|
43 |
|
44 |
+
1. WP 404 Auto Redirect to Similar Post: Settings Page
|
45 |
+
2. WP 404 Auto Redirect to Similar Post: Front Debug Console (for administrators)
|
|
|
|
|
|
|
46 |
|
47 |
== Changelog ==
|
48 |
|
49 |
+
= 0.7 =
|
50 |
+
* Reworked code
|
51 |
+
* Added settings page
|
52 |
+
* Added Debug mode for administrators (settings page)
|
53 |
+
* Added the ability to disable "Redirect to Homepage" if nothing found (settings page)
|
54 |
+
* Added the ability to choose between 301 or 302 HTTP Headers (settings page)
|
55 |
+
* Added the ability preview URL Redirections (settings page)
|
56 |
+
|
57 |
= 0.4.0.2 =
|
58 |
* Fixed sanitization bug
|
59 |
* Fixed debug typo
|
wp-404-auto-redirect-similar-post.js
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
jQuery(document).ready(function($){
|
2 |
+
var ajaxurl = '/wp-admin/admin-ajax.php';
|
3 |
+
|
4 |
+
if($('#wp404arsp_settings_test').length > 0){
|
5 |
+
$('#wp404arsp_settings_test .button').click(function(){
|
6 |
+
$request = $('#wp404arsp_settings_test input[type=text]').val();
|
7 |
+
if($request.length == 0)
|
8 |
+
return;
|
9 |
+
|
10 |
+
if($request.substring(0,1) != '/'){
|
11 |
+
$request = '/' + $request;
|
12 |
+
$('#wp404arsp_settings_test input[type=text]').val($request)
|
13 |
+
}
|
14 |
+
|
15 |
+
data = {
|
16 |
+
action: 'wp404arsp_ajax_test',
|
17 |
+
request: $request,
|
18 |
+
};
|
19 |
+
$.post(ajaxurl, data)
|
20 |
+
.done(
|
21 |
+
function(response){
|
22 |
+
$('#wp404arsp_settings_test .results').html(response);
|
23 |
+
}
|
24 |
+
);
|
25 |
+
});
|
26 |
+
}
|
27 |
+
|
28 |
+
});
|
wp-404-auto-redirect-similar-post.php
CHANGED
@@ -3,110 +3,301 @@
|
|
3 |
* Plugin Name: WP 404 Auto Redirect to Similar Post
|
4 |
* Description: Automatically Redirect any 404 to a Similar Post based on the Title, Post Type, Category & Taxonomy using 301 Redirects!
|
5 |
* Author: hwk-fr
|
6 |
-
* Version: 0.
|
7 |
* Author URI: http://hwk.fr
|
8 |
*/
|
9 |
|
10 |
if(!defined('ABSPATH'))
|
11 |
die('You are not allowed to call this page directly.');
|
12 |
|
13 |
-
|
14 |
-
|
15 |
-
|
|
|
|
|
|
|
|
|
|
|
16 |
}
|
17 |
|
18 |
-
|
19 |
-
function
|
20 |
-
|
21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
22 |
return;
|
23 |
|
24 |
-
|
25 |
-
wp404arsp_search($query);
|
26 |
|
27 |
}
|
28 |
|
29 |
-
function
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
30 |
|
31 |
$path = pathinfo(urldecode(htmlspecialchars(strtok($request, '?'))));
|
32 |
-
$path['filename'] =
|
33 |
-
$path['dirname'] =
|
34 |
-
$path['dirname'] =
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
35 |
|
36 |
-
if(!empty($
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
37 |
|
38 |
-
|
39 |
-
|
40 |
-
|
41 |
-
|
42 |
-
}
|
43 |
-
}else{
|
44 |
-
$path['directories'][] = sanitize_title($path['dirname']);
|
45 |
-
}
|
46 |
|
|
|
|
|
47 |
}
|
48 |
|
49 |
-
$
|
50 |
|
51 |
-
$keywords
|
52 |
-
$keywords
|
|
|
|
|
|
|
53 |
|
54 |
-
$keywords['full'] = implode('/', $keywords['split']);
|
55 |
|
56 |
-
$
|
57 |
-
|
58 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
59 |
|
60 |
-
|
61 |
-
|
62 |
-
|
63 |
-
|
64 |
-
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
|
70 |
-
|
71 |
-
|
72 |
-
|
73 |
-
|
74 |
-
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
|
85 |
-
|
86 |
-
|
87 |
-
|
88 |
-
|
89 |
-
|
90 |
-
|
91 |
-
|
92 |
-
|
93 |
-
|
94 |
-
$get_taxonomies = get_taxonomies(array('public' => true), 'names');
|
95 |
-
foreach($get_taxonomies as $taxonomy){
|
96 |
-
if($tax = get_term_by('slug', $keyword, $taxonomy)){
|
97 |
-
$return['known'][$i]['slug'] = $keyword;
|
98 |
-
$return['known'][$i]['type'] = 'term';
|
99 |
-
$return['known'][$i]['data']['taxonomy'] = $taxonomy;
|
100 |
-
break;
|
101 |
-
}
|
102 |
-
}
|
103 |
-
|
104 |
-
}
|
105 |
|
106 |
-
|
107 |
-
|
108 |
|
109 |
-
$i++;
|
110 |
}
|
111 |
|
112 |
}
|
@@ -115,189 +306,119 @@ function wp404arsp_query_setup($request){
|
|
115 |
|
116 |
}
|
117 |
|
118 |
-
function
|
119 |
|
120 |
-
|
|
|
|
|
121 |
|
122 |
-
if(
|
123 |
-
return
|
124 |
|
125 |
-
|
126 |
-
|
127 |
|
128 |
-
$
|
|
|
129 |
|
130 |
-
|
131 |
-
foreach($known as $slug){
|
132 |
-
|
133 |
-
$get_permalink = false;
|
134 |
-
|
135 |
-
if($slug['type'] == 'post')
|
136 |
-
$get_permalink = get_permalink($slug['data']['ID']);
|
137 |
-
|
138 |
-
if($slug['type'] == 'post_type')
|
139 |
-
$get_permalink = get_post_type_archive_link($slug['data']['post_type']);
|
140 |
-
|
141 |
-
if($slug['type'] == 'term')
|
142 |
-
$get_permalink = get_term_link($slug['slug'], $slug['data']['taxonomy']);
|
143 |
-
|
144 |
-
wp404arsp_redirect($get_permalink, $debug);
|
145 |
-
}
|
146 |
-
}
|
147 |
|
148 |
-
|
149 |
-
|
150 |
-
|
151 |
-
|
152 |
-
|
153 |
-
|
154 |
-
|
155 |
-
|
156 |
-
$
|
157 |
-
foreach($explode as $word){
|
158 |
-
$sql .= " if(INSTR(LCASE(p.post_name),'" . $word . "'), 1, 0) + ";
|
159 |
-
}
|
160 |
-
$sql .= "0 as score FROM " . $wpdb->posts . " AS p
|
161 |
-
WHERE p.post_status = 'publish' AND p.post_type <> 'attachment' AND p.post_type <> 'nav_menu_item'
|
162 |
-
ORDER BY score DESC, post_modified DESC LIMIT 1";
|
163 |
-
|
164 |
-
$debug['sql'] = $sql;
|
165 |
-
|
166 |
-
$get_post = $wpdb->get_row($sql);
|
167 |
-
if(!empty($get_post)){
|
168 |
-
$debug['result'] = array('score' => $get_post->score, 'id' => (int)$get_post->ID, 'url' => get_permalink($get_post->ID));
|
169 |
-
if($get_post->score > 0){
|
170 |
-
$get_permalink = get_permalink((int)$get_post->ID);
|
171 |
-
}
|
172 |
-
}
|
173 |
-
|
174 |
-
wp404arsp_redirect($get_permalink, $debug);
|
175 |
-
|
176 |
-
/*
|
177 |
-
$sql = "SELECT t.term_id, ";
|
178 |
-
|
179 |
-
foreach(wp404arsp_remove_stop_words($search) as $word){
|
180 |
-
$sql .= " if(INSTR(LCASE(t.slug),'" . $word . "'), 1, 0) + ";
|
181 |
-
}
|
182 |
-
|
183 |
-
$sql .= "0 as score FROM " . $wpdb->terms . " AS t
|
184 |
-
INNER JOIN $wpdb->term_taxonomy AS tt ON (t.term_id = tt.term_id)
|
185 |
-
WHERE tt.taxonomy = '".$query['wp_query']['taxonomy']."'
|
186 |
-
ORDER BY score DESC LIMIT 1";
|
187 |
-
|
188 |
-
$debug['sql'] = $sql;
|
189 |
|
190 |
-
|
191 |
-
|
192 |
-
$debug['results'][] = array('id' => (int)$get_term->term_id, 'url' => get_term_link((int)$get_term->term_id, $query['wp_query']['taxonomy']), 'score' => $get_term->score);
|
193 |
-
$post = (int)$get_term->term_id;
|
194 |
-
}
|
195 |
-
*/
|
196 |
|
197 |
-
|
198 |
-
|
199 |
|
200 |
}
|
201 |
|
202 |
-
|
203 |
-
foreach($known as $slug){
|
204 |
-
|
205 |
-
foreach($unknown as $word){
|
206 |
-
$collapse[] = $word['slug'];
|
207 |
-
}
|
208 |
-
$explode = explode('-', implode('-', $collapse));
|
209 |
-
|
210 |
-
$get_permalink = false;
|
211 |
-
|
212 |
-
if($slug['type'] == 'post_type'){
|
213 |
-
|
214 |
-
$sql = "SELECT p.ID, ";
|
215 |
-
foreach($explode as $word){
|
216 |
-
$sql .= " if(INSTR(LCASE(p.post_name),'" . $word . "'), 1, 0) + ";
|
217 |
-
}
|
218 |
-
$sql .= "0 as score FROM " . $wpdb->posts . " AS p
|
219 |
-
WHERE
|
220 |
-
p.post_type = '".$slug['data']['post_type']."'
|
221 |
-
AND p.post_status = 'publish' AND p.post_type <> 'attachment' AND p.post_type <> 'nav_menu_item'
|
222 |
-
ORDER BY score DESC, post_modified DESC LIMIT 1";
|
223 |
-
|
224 |
-
$debug['sql'] = $sql;
|
225 |
-
|
226 |
-
$get_post = $wpdb->get_row($sql);
|
227 |
-
if(!empty($get_post)){
|
228 |
-
$debug['result'] = array('score' => $get_post->score, 'id' => (int)$get_post->ID, 'url' => get_permalink($get_post->ID));
|
229 |
-
if($get_post->score > 0){
|
230 |
-
$get_permalink = get_permalink((int)$get_post->ID);
|
231 |
-
}
|
232 |
-
}
|
233 |
-
|
234 |
-
wp404arsp_redirect($get_permalink, $debug);
|
235 |
-
|
236 |
-
}
|
237 |
-
|
238 |
-
if($slug['type'] == 'term'){
|
239 |
-
|
240 |
-
$sql = "SELECT p.ID, ";
|
241 |
-
foreach($explode as $word){
|
242 |
-
$sql .= " if(INSTR(LCASE(p.post_name),'" . $word . "'), 1, 0) + ";
|
243 |
-
}
|
244 |
-
$sql .= "0 as score FROM " . $wpdb->posts . " AS p
|
245 |
-
INNER JOIN $wpdb->term_relationships AS tr ON (p.ID = tr.object_id)
|
246 |
-
INNER JOIN $wpdb->term_taxonomy AS tt ON (tr.term_taxonomy_id = tt.term_taxonomy_id)
|
247 |
-
INNER JOIN $wpdb->terms AS t ON (t.term_id = tt.term_id)
|
248 |
-
WHERE
|
249 |
-
tt.taxonomy = '".$slug['data']['taxonomy']."' AND t.slug = '".$slug['slug']."'
|
250 |
-
AND p.post_status = 'publish' AND p.post_type <> 'attachment' AND p.post_type <> 'nav_menu_item'
|
251 |
-
ORDER BY score DESC, post_modified DESC LIMIT 1";
|
252 |
-
|
253 |
-
$debug['sql'] = $sql;
|
254 |
-
|
255 |
-
$get_post = $wpdb->get_row($sql);
|
256 |
-
if(!empty($get_post)){
|
257 |
-
$debug['result'] = array('score' => $get_post->score, 'id' => (int)$get_post->ID, 'url' => get_permalink($get_post->ID));
|
258 |
-
if($get_post->score > 0){
|
259 |
-
$get_permalink = get_permalink((int)$get_post->ID);
|
260 |
-
}
|
261 |
-
}
|
262 |
-
|
263 |
-
wp404arsp_redirect($get_permalink, $debug);
|
264 |
-
|
265 |
-
}
|
266 |
-
|
267 |
-
}
|
268 |
-
|
269 |
-
unset($query['unknown']);
|
270 |
-
wp404arsp_search($query, $debug);
|
271 |
-
|
272 |
-
}
|
273 |
|
274 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
275 |
|
|
|
276 |
}
|
277 |
|
278 |
-
function
|
279 |
-
|
280 |
-
$wp404arsp_settings = wp404arsp_settings();
|
281 |
-
|
282 |
-
if(is_super_admin() && $wp404arsp_settings['debug']){
|
283 |
-
echo "<pre>"; echo 'Redirect to: ' . ((!empty($url)) ? $url : '<span>Empty</span>') . "</pre>";
|
284 |
|
285 |
-
|
286 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
287 |
|
288 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
289 |
return;
|
290 |
-
}
|
291 |
|
292 |
-
|
293 |
-
|
294 |
-
|
295 |
-
}
|
296 |
|
297 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
298 |
|
299 |
function wp404arsp_remove_stop_words($input){
|
300 |
-
|
301 |
$words = array('a', 'about', 'above', 'after', 'again', 'against', 'all', 'am', 'an', 'and', 'any', 'are', 'arent', 'as', 'at', 'be', 'because', 'been', 'before', 'being', 'below', 'between', 'both', 'but', 'by', 'cant', 'cannot', 'could', 'couldnt', 'did', 'didnt', 'do', 'does', 'doesnt', 'doing', 'dont', 'down', 'during', 'each', 'few', 'for', 'from', 'further', 'had', 'hadnt', 'has', 'hasnt', 'have', 'havent', 'having', 'he', 'hed', 'hell', 'hes', 'her', 'here', 'heres', 'hers', 'herself', 'him', 'himself', 'his', 'how', 'hows', 'i', 'id', 'ill', 'im', 'ive', 'if', 'in', 'into', 'is', 'isnt', 'it', 'its', 'itself', 'lets', 'me', 'more', 'most', 'mustnt', 'my', 'myself', 'no', 'nor', 'not', 'of', 'off', 'on', 'once', 'only', 'or', 'other', 'ought', 'our', 'ours', 'ourselves', 'out', 'over', 'own', 'same', 'shant', 'she', 'shed', 'shell', 'shes', 'should', 'shouldnt', 'so', 'some', 'such', 'than', 'that', 'thats', 'the', 'their', 'theirs', 'them', 'themselves', 'then', 'there', 'theres', 'these', 'they', 'theyd', 'theyll', 'theyre', 'theyve', 'this', 'those', 'to', 'too', 'under', 'until', 'up', 'very', 'was', 'wasnt', 'we', 'wed', 'well', 'were', 'weve', 'werent', 'what', 'whats', 'when', 'whens', 'where', 'wheres', 'which', 'while', 'who', 'whos', 'whom', 'why', 'whys', 'with', 'wont', 'would', 'wouldnt', 'you', 'youd', 'youll', 'youre', 'youve', 'your', 'yours', 'category', 'page', 'paged');
|
302 |
|
303 |
if(is_array($input)){
|
@@ -314,4 +435,12 @@ function wp404arsp_remove_stop_words($input){
|
|
314 |
return preg_replace('/\b('.implode('|', $words).')\b/', '', $input);
|
315 |
|
316 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
317 |
}
|
3 |
* Plugin Name: WP 404 Auto Redirect to Similar Post
|
4 |
* Description: Automatically Redirect any 404 to a Similar Post based on the Title, Post Type, Category & Taxonomy using 301 Redirects!
|
5 |
* Author: hwk-fr
|
6 |
+
* Version: 0.7
|
7 |
* Author URI: http://hwk.fr
|
8 |
*/
|
9 |
|
10 |
if(!defined('ABSPATH'))
|
11 |
die('You are not allowed to call this page directly.');
|
12 |
|
13 |
+
add_action('admin_menu', 'wp404arsp_admin_menu');
|
14 |
+
function wp404arsp_admin_menu(){
|
15 |
+
$menu = add_submenu_page('options-general.php', 'WP 404 Auto Redirect', 'WP 404 Auto Redirect', 'manage_options', 'wp-404-auto-redirect', 'wp404arsp_admin_page_html');
|
16 |
+
|
17 |
+
add_action('admin_print_scripts-' . $menu, function(){
|
18 |
+
wp_enqueue_script('wp404arsp_admin_js', plugins_url('wp-404-auto-redirect-similar-post.js', __FILE__), array('jquery'));
|
19 |
+
});
|
20 |
+
|
21 |
}
|
22 |
|
23 |
+
add_filter('plugin_action_links_' . plugin_basename(__FILE__), 'wp404arsp_plugin_link');
|
24 |
+
function wp404arsp_plugin_link($links){
|
25 |
+
return array_merge($links, array('<a href="' . admin_url('options-general.php?page=wp-404-auto-redirect') . '">Settings</a>'));
|
26 |
+
}
|
27 |
+
|
28 |
+
add_action('admin_init', 'wp404arsp_admin_settings');
|
29 |
+
function wp404arsp_admin_settings(){
|
30 |
+
register_setting('wp404arsp_settings', 'wp404arsp_settings');
|
31 |
+
}
|
32 |
+
|
33 |
+
function wp404arsp_admin_page_html(){
|
34 |
+
?>
|
35 |
+
<div class="wrap">
|
36 |
+
<h1 class="wp-heading-inline">WP 404 Auto Redirect to Similar Post</h1>
|
37 |
+
<hr class="wp-header-end">
|
38 |
+
|
39 |
+
<div id="poststuff">
|
40 |
+
<div id="post-body" class="metabox-holder columns-2">
|
41 |
+
|
42 |
+
<div id="post-body-content">
|
43 |
+
<div class="meta-box-sortables ui-sortable">
|
44 |
+
|
45 |
+
<div class="postbox">
|
46 |
+
<h2 class="hndle"><span>Settings</span></h2>
|
47 |
+
<form method="post" action="options.php">
|
48 |
+
<?php
|
49 |
+
settings_fields('wp404arsp_settings');
|
50 |
+
do_settings_sections('wp404arsp_settings');
|
51 |
+
$wp404arsp_settings = wp404arsp_get_settings();
|
52 |
+
?>
|
53 |
+
|
54 |
+
<div class="inside">
|
55 |
+
<table class="form-table">
|
56 |
+
<tbody>
|
57 |
+
|
58 |
+
<tr>
|
59 |
+
<th scope="row">Debug Mode</th>
|
60 |
+
<td>
|
61 |
+
<fieldset>
|
62 |
+
<legend class="screen-reader-text"><span>Debug</span></legend>
|
63 |
+
<label for="wp404arsp_settings[debug]">
|
64 |
+
<input name="wp404arsp_settings[debug]" id="wp404arsp_settings[debug]" value="1" type="checkbox" <?php if($wp404arsp_settings['debug'] == "1") echo "checked"; ?>>
|
65 |
+
Activate
|
66 |
+
</label>
|
67 |
+
</fieldset>
|
68 |
+
<p class="description" id="tagline-description">Administrators will get the debug console instead of being redirected.</p>
|
69 |
+
</td>
|
70 |
+
</tr>
|
71 |
+
|
72 |
+
<tr>
|
73 |
+
<th scope="row">Redirect to Home</th>
|
74 |
+
<td>
|
75 |
+
<fieldset>
|
76 |
+
<legend class="screen-reader-text"><span>Do not redirect to Home</span></legend>
|
77 |
+
<label for="wp404arsp_settings[home]">
|
78 |
+
<input name="wp404arsp_settings[home]" id="wp404arsp_settings[home]" value="1" type="checkbox" <?php if($wp404arsp_settings['home'] == "1") echo "checked"; ?>>
|
79 |
+
Disable
|
80 |
+
</label>
|
81 |
+
</fieldset>
|
82 |
+
<p class="description" id="tagline-description">Do not redirect to <a href="<?php echo home_url(); ?>"><?php echo home_url(); ?></a> if no similar post is found.</p>
|
83 |
+
</td>
|
84 |
+
</tr>
|
85 |
+
|
86 |
+
<tr>
|
87 |
+
<th scope="row">Redirect Headers</th>
|
88 |
+
<td>
|
89 |
+
<select name="wp404arsp_settings[method]" id="wp404arsp_settings[method]">
|
90 |
+
<option value="" <?php if(!$wp404arsp_settings['method']) echo "selected"; ?>>301 method</option>
|
91 |
+
<option value="302" <?php if($wp404arsp_settings['method'] == "302") echo "selected"; ?>>302 method</option>
|
92 |
+
</select>
|
93 |
+
<p class="description" id="tagline-description">Learn more about <a href="https://en.wikipedia.org/wiki/List_of_HTTP_status_codes" target="_blank">HTTP headers & redirections</a>.</p>
|
94 |
+
</td>
|
95 |
+
</tr>
|
96 |
+
|
97 |
+
</tbody>
|
98 |
+
</table>
|
99 |
+
|
100 |
+
<p class="submit" style="padding:0;">
|
101 |
+
<?php submit_button('Save Settings', 'primary', '', false); ?>
|
102 |
+
</p>
|
103 |
+
</div>
|
104 |
+
</form>
|
105 |
+
</div>
|
106 |
+
|
107 |
+
<div id="wp404arsp_settings_test">
|
108 |
+
<div class="postbox">
|
109 |
+
<h2 class="hndle"><span>Redirection Preview</span></h2>
|
110 |
+
<div class="inside">
|
111 |
+
<table class="form-table">
|
112 |
+
<tbody>
|
113 |
+
|
114 |
+
<tr>
|
115 |
+
<th scope="row"><?php echo home_url(); ?></th>
|
116 |
+
<td>
|
117 |
+
<input class="request" type="text" value="/example-url" style="width:500px;" />
|
118 |
+
<p class="description" id="tagline-description">Enter the URL you would like to test, starting with <code>/</code></p>
|
119 |
+
</td>
|
120 |
+
</tr>
|
121 |
+
</tbody>
|
122 |
+
</table>
|
123 |
+
|
124 |
+
<p class="submit" style="padding:0;">
|
125 |
+
<?php submit_button('Preview URL', 'secondary', '', false); ?>
|
126 |
+
</p>
|
127 |
+
|
128 |
+
<div class="results"></div>
|
129 |
+
|
130 |
+
</div>
|
131 |
+
</div>
|
132 |
+
</div>
|
133 |
+
|
134 |
+
</div>
|
135 |
+
|
136 |
+
</div>
|
137 |
+
|
138 |
+
<div id="postbox-container-1" class="postbox-container">
|
139 |
+
<div class="meta-box-sortables">
|
140 |
+
<div class="postbox">
|
141 |
+
|
142 |
+
<div class="inside">
|
143 |
+
<img src="<?php echo plugins_url('logo.png', __FILE__); ?>" style="max-width:100%; height:auto; margin:20px auto 30px; display:block;" />
|
144 |
+
|
145 |
+
|
146 |
+
|
147 |
+
<p>Found a bug? Need help? Head over the <a href="https://wordpress.org/plugins/wp-404-auto-redirect-to-similar-post/" target="_blank">official plugin page</a>.</p>
|
148 |
+
|
149 |
+
<hr />
|
150 |
+
|
151 |
+
<p>Enjoying this plugin? Please rate it. It's always much appreciated!</p>
|
152 |
+
<p>
|
153 |
+
<a href="https://wordpress.org/support/plugin/wp-404-auto-redirect-to-similar-post/reviews/#new-post" target="_blank" class="button">Rate the plugin</a>
|
154 |
+
</p>
|
155 |
+
</div>
|
156 |
+
|
157 |
+
</div>
|
158 |
+
</div>
|
159 |
+
</div>
|
160 |
+
|
161 |
+
</div>
|
162 |
+
<br class="clear">
|
163 |
+
|
164 |
+
</div>
|
165 |
+
</div>
|
166 |
+
<?php }
|
167 |
+
|
168 |
+
add_action('template_redirect', 'wp404arsp_init');
|
169 |
+
function wp404arsp_init(){
|
170 |
+
|
171 |
+
if( !is_404() || wp_doing_ajax() || is_admin() || $_SERVER['SCRIPT_URI'] == admin_url('admin-ajax.php') || (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && !empty($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) == 'xmlhttprequest') )
|
172 |
return;
|
173 |
|
174 |
+
wp404arsp_request($_SERVER['REQUEST_URI']);
|
|
|
175 |
|
176 |
}
|
177 |
|
178 |
+
function wp404arsp_request($request, $preview = false){
|
179 |
+
|
180 |
+
$query = array();
|
181 |
+
$query['request']['full'] = urldecode(htmlspecialchars($request));
|
182 |
+
|
183 |
+
if($preview)
|
184 |
+
$query['preview'] = true;
|
185 |
+
|
186 |
+
if(preg_match('#/(?<slug>page|paged)/(?<page>[0-9]+)/?$#i', $request, $pagination)){
|
187 |
+
$request_no_pagination = str_replace($pagination[0], '', $request);
|
188 |
+
$query['request']['pagination'] = array(
|
189 |
+
'full' => $pagination[0],
|
190 |
+
'slug' => $pagination['slug'],
|
191 |
+
'page' => $pagination['page']
|
192 |
+
);
|
193 |
+
}
|
194 |
|
195 |
$path = pathinfo(urldecode(htmlspecialchars(strtok($request, '?'))));
|
196 |
+
$path['filename'] = wp404arsp_sanitize(pathinfo(basename($request), PATHINFO_FILENAME));
|
197 |
+
$path['dirname'] = trim($path['dirname'], '/');
|
198 |
+
$path['dirname'] = trim($path['dirname'], '\\');
|
199 |
+
|
200 |
+
$query['request']['dirname'] = $path['dirname'];
|
201 |
+
$query['request']['filename'] = $path['filename'];
|
202 |
+
$query['request']['extension'] = (!empty($path['extension'])) ? $path['extension'] : '';
|
203 |
+
|
204 |
+
|
205 |
+
// Pagination found, try the URL without pagination
|
206 |
+
if(!empty($query['request']['pagination']))
|
207 |
+
return wp404arsp_redirect(array_merge( $query, array(
|
208 |
+
'url' => home_url() . $request_no_pagination,
|
209 |
+
'why' => "Pagination found in the requested url. Trying to reach same url without pagination."
|
210 |
+
))
|
211 |
+
);
|
212 |
+
|
213 |
+
wp404arsp_setup($query);
|
214 |
+
|
215 |
+
}
|
216 |
+
|
217 |
+
function wp404arsp_setup($query){
|
218 |
|
219 |
+
if(!isset($query['request']['full']) || empty($query['request']['full']))
|
220 |
+
return;
|
221 |
+
|
222 |
+
$query['process']['request'] = $query['request']['full'];
|
223 |
+
|
224 |
+
global $wp_query;
|
225 |
+
$wp_query = $wp_query->query;
|
226 |
+
|
227 |
+
if(isset($wp_query['post_type'])){
|
228 |
|
229 |
+
$query['process']['post_type'] = $wp_query['post_type'];
|
230 |
+
$post_type = get_post_type_object($wp_query['post_type']);
|
231 |
+
if( stripos($query['request']['full'], $post_type->rewrite['slug']) !== false )
|
232 |
+
$query['process']['request'] = str_replace('//', '/', substr_replace($query['request']['full'], '', stripos($query['request']['full'], $post_type->rewrite['slug']), strlen($post_type->rewrite['slug'])));
|
|
|
|
|
|
|
|
|
233 |
|
234 |
+
elseif( stripos($query['request']['full'], $post_type->has_archive) !== false )
|
235 |
+
$query['process']['request'] = str_replace('//', '/', substr_replace($query['request']['full'], '', stripos($query['request']['full'], $post_type->has_archive), strlen($post_type->has_archive)));
|
236 |
}
|
237 |
|
238 |
+
$query['process']['keywords']['sanitized'] = wp404arsp_sanitize(str_replace('.' . $query['request']['extension'], '', $query['process']['request']));
|
239 |
|
240 |
+
$keywords = explode('/', trim($query['process']['request'], '/'));
|
241 |
+
foreach($keywords as $keyword){
|
242 |
+
$query['process']['keywords']['explode'][] = str_replace('.' . $query['request']['extension'], '', $keyword);
|
243 |
+
}
|
244 |
+
$query['process']['keywords']['explode'] = array_reverse($query['process']['keywords']['explode']);
|
245 |
|
|
|
246 |
|
247 |
+
foreach($query['process']['keywords']['explode'] as $keyword){
|
248 |
+
$get_posts_types = get_post_types(array('public' => true), 'names');
|
249 |
+
foreach($get_posts_types as $post_type){
|
250 |
+
if($post = get_page_by_path($keyword, 'object', $post_type))
|
251 |
+
return wp404arsp_redirect(array_merge( $query, array(
|
252 |
+
'score' => 'direct',
|
253 |
+
'id' => (int)$post->ID,
|
254 |
+
'url' => get_permalink((int)$post->ID),
|
255 |
+
'why' => "The request url already exist as post of the post type " . get_post_type((int)$post->ID)
|
256 |
+
))
|
257 |
+
);
|
258 |
+
}
|
259 |
+
}
|
260 |
+
|
261 |
+
return wp404arsp_redirect(wp404arsp_search($query));
|
262 |
|
263 |
+
}
|
264 |
+
|
265 |
+
function wp404arsp_search($query){
|
266 |
+
|
267 |
+
$keywords = explode('-', $query['process']['keywords']['sanitized']);
|
268 |
+
$post_type = (isset($query['process']['post_type']) && !empty($query['process']['post_type'])) ? $query['process']['post_type'] : '';
|
269 |
+
|
270 |
+
$sql = wp404arsp_search_sql($keywords, '');
|
271 |
+
if(empty($sql['post']) || $sql['post']['score'] < 1)
|
272 |
+
return array_merge( $query, array(
|
273 |
+
'why' => "Nothing found in DB matching the request url"
|
274 |
+
)
|
275 |
+
);
|
276 |
+
|
277 |
+
$return = array_merge( $query, array(
|
278 |
+
'score' => $sql['post']['score'],
|
279 |
+
'id' => (int)$sql['post']['ID'],
|
280 |
+
'url' => get_permalink((int)$sql['post']['ID']),
|
281 |
+
'why' => "Highest score based on the requested url was found"
|
282 |
+
)
|
283 |
+
);
|
284 |
+
|
285 |
+
// If Post Type found, check other post types & compare score
|
286 |
+
if(!empty($post_type)){
|
287 |
+
|
288 |
+
$sql = wp404arsp_search_sql($keywords, $post_type);
|
289 |
+
if(!empty($sql['post']) && $sql['post']['score'] >= 1 && $sql['post']['score'] >= $return['score']){
|
290 |
+
$return = array_merge( $query, array(
|
291 |
+
'score' => $sql['post']['score'],
|
292 |
+
'id' => (int)$sql['post']['ID'],
|
293 |
+
'url' => get_permalink((int)$sql['post']['ID']),
|
294 |
+
'why' => "Highest score based on the requested url was found"
|
295 |
+
)
|
296 |
+
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
297 |
|
298 |
+
}else{
|
299 |
+
$return['why'] = "Post type " . $query['process']['post_type'] . " found, but the highest score based on the requested url was found within the post type " . get_post_type($return['id']);
|
300 |
|
|
|
301 |
}
|
302 |
|
303 |
}
|
306 |
|
307 |
}
|
308 |
|
309 |
+
function wp404arsp_redirect($args){
|
310 |
|
311 |
+
$wp404arsp_settings = wp404arsp_get_settings();
|
312 |
+
$method = (!$wp404arsp_settings['method']) ? 301 : $wp404arsp_settings['method'];
|
313 |
+
$home_url = (!$wp404arsp_settings['home']) ? home_url() : false;
|
314 |
|
315 |
+
if( is_user_logged_in() && current_user_can('manage_options') && ($wp404arsp_settings['debug'] || $args['preview']) )
|
316 |
+
return wp404arsp_debug($args);
|
317 |
|
318 |
+
if(isset($args['url']) && !empty($args['url']))
|
319 |
+
return wp_redirect($args['url'], $method);
|
320 |
|
321 |
+
if($home_url)
|
322 |
+
return wp_redirect($home_url, $method);
|
323 |
|
324 |
+
return false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
325 |
|
326 |
+
}
|
327 |
+
|
328 |
+
function wp404arsp_debug($args){
|
329 |
+
$wp404arsp_settings = wp404arsp_get_settings();
|
330 |
+
$method = (!$wp404arsp_settings['method']) ? 301 : $wp404arsp_settings['method'];
|
331 |
+
|
332 |
+
$title = '';
|
333 |
+
if(isset($args['url']) && !empty($args['url'])){
|
334 |
+
$title = 'Redirection to: ' . "<a href='" . $args['url'] . "'>" . $args['url'] . "</a>" . ' (' . $method . ' Headers)';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
335 |
|
336 |
+
}elseif($wp404arsp_settings['home'] == "1"){
|
337 |
+
$title = 'Redirect to Home disabled. Displaying 404.';
|
|
|
|
|
|
|
|
|
338 |
|
339 |
+
}else{
|
340 |
+
$title = 'Redirection to: ' . "<a href='" . home_url() . "'>" . home_url() . "</a>" . ' (' . $method . ' Headers)';
|
341 |
|
342 |
}
|
343 |
|
344 |
+
ob_start(); ?>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
345 |
|
346 |
+
<style type="text/css">
|
347 |
+
.wp404arsp_debug_page{margin:0 auto; max-width:1150px; font-family: arial, sans-serif;}
|
348 |
+
.wp404arsp_debug_page h2,
|
349 |
+
.wp404arsp_debug_page h4{text-align:center;}
|
350 |
+
.wp404arsp_debug_page pre{background:#f4f4f4; padding:15px; overflow:auto;}
|
351 |
+
.wp404arsp_debug_page a{color:blue;}
|
352 |
+
.wp404arsp_debug_page p{font-size:12px;}
|
353 |
+
</style>
|
354 |
+
<div class="wp404arsp_debug_page">
|
355 |
+
<?php if(!isset($args['preview'])){ ?>
|
356 |
+
<h2>WP 404 Auto Redirect to Similar Post</h2>
|
357 |
+
<p>This is the <strong>debug console</strong> of WP 404 Auto redirect to Similar Post Plugin which is only visible to administrators. If you would like to to disable the Debug mode, please head over your <a href="<?php echo admin_url('options-general.php?page=wp-404-auto-redirect'); ?>">Settings page</a>.</p>
|
358 |
+
<hr />
|
359 |
+
<?php } ?>
|
360 |
+
<pre>Requested URL: <a href="<?php echo home_url(); ?><?php echo $args['request']['full']; ?>"><?php echo home_url(); ?><?php echo $args['request']['full']; ?></a><br />
|
361 |
+
<?php echo $title; ?><br />
|
362 |
+
Details: <?php echo $args['why']; ?>
|
363 |
+
</pre>
|
364 |
+
<pre><?php print_r($args); ?></pre>
|
365 |
+
</div>
|
366 |
|
367 |
+
<?php echo ob_get_clean(); exit;
|
368 |
}
|
369 |
|
370 |
+
function wp404arsp_search_sql($keywords, $post_type = ''){
|
371 |
+
global $wpdb;
|
|
|
|
|
|
|
|
|
372 |
|
373 |
+
$sql = "SELECT p.ID, ";
|
374 |
+
foreach($keywords as $k){
|
375 |
+
$sql .= "if(INSTR(LCASE(p.post_name),'" . $k . "'), 1, 0) + ";
|
376 |
+
}
|
377 |
+
$sql .= "0 as score FROM " . $wpdb->posts . " AS p
|
378 |
+
WHERE p.post_status = 'publish' AND ";
|
379 |
+
|
380 |
+
if(!empty($post_type))
|
381 |
+
$sql .= "p.post_type = '" . $post_type . "'";
|
382 |
|
383 |
+
else
|
384 |
+
$sql .= "p.post_type <> 'attachment' AND p.post_type <> 'nav_menu_item'";
|
385 |
+
|
386 |
+
$sql .= " ORDER BY score DESC, post_modified DESC LIMIT 1";
|
387 |
+
|
388 |
+
return array(
|
389 |
+
'post' => $wpdb->get_row($sql, 'ARRAY_A'),
|
390 |
+
'dump' => $sql
|
391 |
+
);
|
392 |
+
}
|
393 |
+
|
394 |
+
function wp404arsp_ajax_test() {
|
395 |
+
if( !defined('DOING_AJAX') || !DOING_AJAX || !isset($_POST['action']) || !current_user_can('manage_options') )
|
396 |
return;
|
|
|
397 |
|
398 |
+
$request = $_POST['request'];
|
399 |
+
wp404arsp_request($request, true);
|
400 |
+
die();
|
|
|
401 |
|
402 |
}
|
403 |
+
add_action('wp_ajax_wp404arsp_ajax_test', 'wp404arsp_ajax_test');
|
404 |
+
|
405 |
+
function wp404arsp_sanitize($input){
|
406 |
+
return sanitize_title(str_replace(array('_', '/'), '-', $input));
|
407 |
+
}
|
408 |
+
|
409 |
+
function wp404arsp_get_settings(){
|
410 |
+
return wp_parse_args(get_option('wp404arsp_settings'),
|
411 |
+
array(
|
412 |
+
'debug' => null,
|
413 |
+
'logs' => null,
|
414 |
+
'home' => null,
|
415 |
+
'method' => null
|
416 |
+
)
|
417 |
+
);
|
418 |
+
}
|
419 |
|
420 |
function wp404arsp_remove_stop_words($input){
|
421 |
+
|
422 |
$words = array('a', 'about', 'above', 'after', 'again', 'against', 'all', 'am', 'an', 'and', 'any', 'are', 'arent', 'as', 'at', 'be', 'because', 'been', 'before', 'being', 'below', 'between', 'both', 'but', 'by', 'cant', 'cannot', 'could', 'couldnt', 'did', 'didnt', 'do', 'does', 'doesnt', 'doing', 'dont', 'down', 'during', 'each', 'few', 'for', 'from', 'further', 'had', 'hadnt', 'has', 'hasnt', 'have', 'havent', 'having', 'he', 'hed', 'hell', 'hes', 'her', 'here', 'heres', 'hers', 'herself', 'him', 'himself', 'his', 'how', 'hows', 'i', 'id', 'ill', 'im', 'ive', 'if', 'in', 'into', 'is', 'isnt', 'it', 'its', 'itself', 'lets', 'me', 'more', 'most', 'mustnt', 'my', 'myself', 'no', 'nor', 'not', 'of', 'off', 'on', 'once', 'only', 'or', 'other', 'ought', 'our', 'ours', 'ourselves', 'out', 'over', 'own', 'same', 'shant', 'she', 'shed', 'shell', 'shes', 'should', 'shouldnt', 'so', 'some', 'such', 'than', 'that', 'thats', 'the', 'their', 'theirs', 'them', 'themselves', 'then', 'there', 'theres', 'these', 'they', 'theyd', 'theyll', 'theyre', 'theyve', 'this', 'those', 'to', 'too', 'under', 'until', 'up', 'very', 'was', 'wasnt', 'we', 'wed', 'well', 'were', 'weve', 'werent', 'what', 'whats', 'when', 'whens', 'where', 'wheres', 'which', 'while', 'who', 'whos', 'whom', 'why', 'whys', 'with', 'wont', 'would', 'wouldnt', 'you', 'youd', 'youll', 'youre', 'youve', 'your', 'yours', 'category', 'page', 'paged');
|
423 |
|
424 |
if(is_array($input)){
|
435 |
return preg_replace('/\b('.implode('|', $words).')\b/', '', $input);
|
436 |
|
437 |
}
|
438 |
+
}
|
439 |
+
|
440 |
+
function wp404arsp_search_array($array, $key, $value) {
|
441 |
+
foreach($array as $k => $v){
|
442 |
+
if ($v[$key] === $value)
|
443 |
+
return $k;
|
444 |
+
}
|
445 |
+
return null;
|
446 |
}
|