init.php
15.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
<?php
/**
* If Cloud version is enabled we can stop here to save resources used from Local.
* When Cloud is active we still need to load init on Local admin manu page.
* When Local is active we don't need to load on Cloud admin menu page.
*/
if ( empty( WPMUDEV_BLC\App\Options\Settings\Model::instance()->get( 'use_legacy_blc_version' ) ) ) {
if ( empty( $_GET['page'] ) || WPMUDEV_BLC\App\Admin_Pages\Local_Submenu\Controller::instance()->get_menu_slug() !== $_GET['page'] ) {
if ( ! WPMUDEV_BLC\Core\Utils\Utilities::is_subsite() ) {
return;
}
}
} else if ( ! empty( $_GET['page'] ) && WPMUDEV_BLC\App\Admin_Pages\Local_Submenu\Controller::instance()->get_menu_slug() !== $_GET['page'] ) {
if ( ! WPMUDEV_BLC\Core\Utils\Utilities::is_subsite() ) {
return;
}
}
// To prevent conflicts, only one version of the plugin can be activated at any given time.
if ( defined( 'BLC_ACTIVE' ) ) {
trigger_error(
'Another version of Broken Link Checker is already active. Please deactivate it before activating this one.',
E_USER_ERROR
);
} else {
define( 'BLC_ACTIVE', true );
// Fail fast if the WP version is unsupported. The $wp_version variable may be obfuscated by other
// plugins, so use function detection to determine the version. get_post_stati was introduced in WP 3.0.0
if ( ! function_exists( 'get_post_stati' ) ) {
trigger_error(
'This version of Broken Link Checker requires WordPress 3.0 or later!',
E_USER_ERROR
);
}
/***********************************************
Debugging stuff
*/
// define('BLC_DEBUG', true);
/***********************************************
Constants
*/
/**
* For performance, some internal APIs used for retrieving multiple links, instances or containers
* can take an optional "$purpose" argument. Those APIs will try to use this argument to pre-load
* any DB data required for the specified purpose ahead of time.
* For example, if you're loading a bunch of link containers for the purposes of parsing them and
* thus set $purpose to BLC_FOR_PARSING, the relevant container managers will (if applicable) precache
* the parse-able fields in each returned container object. Still, setting $purpose to any particular
* value does not *guarantee* any data will be preloaded - it's only a suggestion that it should.
* The currently supported values for the $purpose argument are :
*/
define( 'BLC_FOR_EDITING', 'edit' );
define( 'BLC_FOR_PARSING', 'parse' );
define( 'BLC_FOR_DISPLAY', 'display' );
define( 'BLC_DATABASE_VERSION', 16 );
/***********************************************
Configuration
*/
// Load and initialize the plugin's configuration
require BLC_DIRECTORY_LEGACY . '/includes/config-manager.php';
global $blc_config_manager;
$blc_config_manager = new blcConfigurationManager(
// Save the plugin's configuration into this DB option
'wsblc_options',
// Initialize default settings
array(
'max_execution_time' => 7 * 60, // (in seconds) How long the worker instance may run, at most.
'check_threshold' => 72, // (in hours) Check each link every 72 hours.
'recheck_count' => 3, // How many times a broken link should be re-checked.
'recheck_threshold' => 30 * 60, // (in seconds) Re-check broken links after 30 minutes.
'run_in_dashboard' => true, // Run the link checker algo. continuously while the Dashboard is open.
'run_via_cron' => true, // Run it hourly via WordPress pseudo-cron.
'mark_broken_links' => true, // Whether to add the broken_link class to broken links in posts.
'broken_link_css' => ".broken_link, a.broken_link {\n\ttext-decoration: line-through;\n}",
'nofollow_broken_links' => false, // Whether to add rel="nofollow" to broken links in posts.
'mark_removed_links' => false, // Whether to add the removed_link class when un-linking a link.
'removed_link_css' => ".removed_link, a.removed_link {\n\ttext-decoration: line-through;\n}",
'exclusion_list' => array(), // Links that contain a substring listed in this array won't be checked.
'send_email_notifications' => true, // Whether to send the admin email notifications about broken links
'send_authors_email_notifications' => false, // Whether to send post authors notifications about broken links in their posts.
'notification_email_address' => '', // If set, send email notifications to this address instead of the admin.
'notification_schedule' => apply_filters( 'blc_notification_schedule_filter', 'daily' ), // How often (at most) notifications will be sent. Possible values : 'daily', 'weekly'. There is no option for this so we've added a fitler for it.
'last_notification_sent' => 0, // When the last email notification was sent (Unix timestamp)
'suggestions_enabled' => true, // Whether to suggest alternative URLs for broken links.
'warnings_enabled' => true, // Try to automatically detect temporary problems and false positives, and report them as "Warnings" instead of broken links.
'server_load_limit' => null, // Stop parsing stuff & checking links if the 1-minute load average goes over this value. Only works on Linux servers. 0 = no limit.
'enable_load_limit' => true, // Enable/disable load monitoring.
'custom_fields' => array(), // List of custom fields that can contain URLs and should be checked.
'acf_fields' => array(), // List of custom fields that can contain URLs and should be checked.
'enabled_post_statuses' => array( 'publish' ), // Only check posts that match one of these statuses
'autoexpand_widget' => true, // Autoexpand the Dashboard widget if broken links are detected
'dashboard_widget_capability' => 'edit_others_posts', // Only display the widget to users who have this capability
'show_link_count_bubble' => true, // Display a notification bubble in the menu when broken links are found
'table_layout' => 'flexible', // The layout of the link table. Possible values : 'classic', 'flexible'
'table_compact' => true, // Compact table mode on/off
'table_visible_columns' => array( 'new-url', 'status', 'used-in', 'new-link-text' ),
'table_links_per_page' => 30,
'table_color_code_status' => true, // Color-code link status text
'need_resynch' => false, // [Internal flag] True if there are unparsed items.
'current_db_version' => 0, // The currently set-up version of the plugin's tables
'timeout' => 30, // (in seconds) Links that take longer than this to respond will be treated as broken.
'highlight_permanent_failures' => false, // Highlight links that have appear to be permanently broken (in Tools -> Broken Links).
'failure_duration_threshold' => 3, // (days) Assume a link is permanently broken if it still hasn't recovered after this many days.
'logging_enabled' => false,
'log_file' => '',
'incorrect_path' => false,
'clear_log_on' => '',
'custom_log_file_enabled' => false,
'installation_complete' => false,
'installation_flag_cleared_on' => 0,
'installation_flag_set_on' => 0,
'show_link_actions' => array( 'blc-deredirect-action' => false ), // Visible link actions.
'youtube_api_key' => '',
'blc_post_modified' => '',
)
);
/***********************************************
Logging
*/
include BLC_DIRECTORY_LEGACY . '/includes/logger.php';
global $blclog;
if ( $blc_config_manager->get( 'logging_enabled', false ) && is_writable( $blc_config_manager->get( 'log_file' ) ) ) {
$blclog = new blcFileLogger( $blc_config_manager->get( 'log_file' ) );
} else {
$blclog = new blcDummyLogger();
}
/*
if ( defined('BLC_DEBUG') && constant('BLC_DEBUG') ){
//Load FirePHP for debug logging
if ( !class_exists('FB') && file_exists(BLC_DIRECTORY_LEGACY . '/FirePHPCore/fb.php4') ) {
require_once BLC_DIRECTORY_LEGACY . '/FirePHPCore/fb.php4';
}
//FB::setEnabled(false);
}
//to comment out all calls : (^[^\/]*)(FB::) -> $1\/\/$2
//to uncomment : \/\/(\s*FB::) -> $1
//*/
/***********************************************
Global functions
************************************************/
/**
* Get the configuration object used by Broken Link Checker.
*
* @return blcConfigurationManager
*/
function blc_get_configuration() {
return $GLOBALS['blc_config_manager'];
}
/**
* Notify the link checker that there are unsynched items
* that might contain links (e.g. a new or edited post).
*
* @return void
*/
function blc_got_unsynched_items() {
$conf = blc_get_configuration();
if ( ! $conf->options['need_resynch'] ) {
$conf->options['need_resynch'] = true;
$conf->save_options();
}
}
/**
* (Re)create synchronization records for all containers and mark them all as unparsed.
*
* @param bool $forced If true, the plugin will recreate all synch. records from scratch.
* @return void
*/
function blc_resynch( $forced = false ) {
global $wpdb, $blclog;
if ( $forced ) {
$blclog->info( '... Forced resynchronization initiated' );
// Drop all synchronization records
$wpdb->query( "TRUNCATE {$wpdb->prefix}blc_synch" );
} else {
$blclog->info( '... Resynchronization initiated' );
}
// Remove invalid DB entries
blc_cleanup_database();
// (Re)create and update synch. records for all container types.
$blclog->info( '... (Re)creating container records' );
blcContainerHelper::resynch( $forced );
$blclog->info( '... Setting resync. flags' );
blc_got_unsynched_items();
// All done.
$blclog->info( 'Database resynchronization complete.' );
}
/**
* Delete synch. records, instances and links that refer to missing or invalid items.
*
* @return void
*/
function blc_cleanup_database() {
global $blclog;
// Delete synch. records for container types that don't exist
$blclog->info( '... Deleting invalid container records' );
blcContainerHelper::cleanup_containers();
// Delete invalid instances
$blclog->info( '... Deleting invalid link instances' );
blc_cleanup_instances();
// Delete orphaned links
$blclog->info( '... Deleting orphaned links' );
blc_cleanup_links();
}
/***********************************************
Utility hooks
************************************************/
/**
* Adds the following cron schedules:
* - 10min: every 10 minutes.
* - weekly: once per week.
* - bimonthly : twice per month.
*
* @param array $schedules Existing Cron schedules.
* @return array
*/
function blc_cron_schedules( $schedules ) {
if ( ! isset( $schedules['10min'] ) ) {
$schedules['10min'] = array(
'interval' => 600,
'display' => __( 'Every 10 minutes' ),
);
}
if ( ! isset( $schedules['weekly'] ) ) {
$schedules['weekly'] = array(
'interval' => 604800, // 7 days
'display' => __( 'Once Weekly' ),
);
}
if ( ! isset( $schedules['bimonthly'] ) ) {
$schedules['bimonthly'] = array(
'interval' => 15 * 24 * 2600, // 15 days
'display' => __( 'Twice a Month' ),
);
}
return $schedules;
}
add_filter( 'cron_schedules', 'blc_cron_schedules' );
/***********************************************
Main functionality
*/
require BLC_DIRECTORY_LEGACY . '/includes/activation.php';
// Load the plugin if installed successfully
if ( $blc_config_manager->options['installation_complete'] ) {
function blc_init() {
global $blc_module_manager, $blc_config_manager, $ws_link_checker;
static $init_done = false;
if ( $init_done ) {
return;
}
$init_done = true;
// Ensure the database is up to date
if ( BLC_DATABASE_VERSION !== $blc_config_manager->options['current_db_version'] ) {
require_once BLC_DIRECTORY_LEGACY . '/includes/admin/db-upgrade.php';
blcDatabaseUpgrader::upgrade_database(); // Also updates the DB ver. in options['current_db_version'].
}
// Load the base classes and utilities
require_once BLC_DIRECTORY_LEGACY . '/includes/links.php';
require_once BLC_DIRECTORY_LEGACY . '/includes/link-query.php';
require_once BLC_DIRECTORY_LEGACY . '/includes/instances.php';
require_once BLC_DIRECTORY_LEGACY . '/includes/utility-class.php';
// Load the module subsystem
require_once BLC_DIRECTORY_LEGACY . '/includes/modules.php';
// Load the modules that want to be executed in all contexts
if ( is_object( $blc_module_manager ) && method_exists( $blc_module_manager, 'load_modules' ) ) {
$blc_module_manager->load_modules();
}
if ( is_admin() || defined( 'DOING_CRON' ) ) {
// It's an admin-side or Cron request. Load the core.
require_once BLC_DIRECTORY_LEGACY . '/core/core.php';
$ws_link_checker = new wsBrokenLinkChecker( BLC_PLUGIN_FILE_LEGACY, $blc_config_manager );
} else {
// This is user-side request, so we don't need to load the core.
// We might need to inject the CSS for removed links, though.
if ( $blc_config_manager->options['mark_removed_links'] && ! empty( $blc_config_manager->options['removed_link_css'] ) ) {
function blc_print_removed_link_css() {
global $blc_config_manager;
echo '<style type="text/css">',$blc_config_manager->options['removed_link_css'],'</style>';
}
add_action( 'wp_head', 'blc_print_removed_link_css' );
}
}
}
add_action( 'init', 'blc_init', 2000 );
} else {
// Display installation errors (if any) on the Dashboard.
function blc_print_installation_errors() {
global $blc_config_manager, $wpdb;
if ( $blc_config_manager->options['installation_complete'] ) {
return;
}
$messages = array(
'<strong>' . __( 'Broken Link Checker installation failed. Try deactivating and then reactivating the plugin.', 'broken-link-checker' ) . '</strong>',
);
if ( ! $blc_config_manager->db_option_loaded ) {
$messages[] = sprintf(
'<strong>Failed to load plugin settings from the "%s" option.</strong>',
$blc_config_manager->option_name
);
$messages[] = '';
$serialized_config = $wpdb->get_var(
$wpdb->prepare(
"SELECT `option_value` FROM `$wpdb->options` WHERE `option_name` = %s",
$blc_config_manager->option_name
)
);
if ( null === $serialized_config ) {
$messages[] = "Option doesn't exist in the {$wpdb->options} table.";
} else {
$messages[] = "Option exists in the {$wpdb->options} table and has the following value:";
$messages[] = '';
$messages[] = '<textarea cols="120" rows="20">' . htmlentities( $serialized_config ) . '</textarea>';
}
} else {
$logger = new blcCachedOptionLogger( 'blc_installation_log' );
$messages = array_merge(
$messages,
array(
'installation_complete = ' . ( isset( $blc_config_manager->options['installation_complete'] ) ? intval( $blc_config_manager->options['installation_complete'] ) : 'no value' ),
'installation_flag_cleared_on = ' . $blc_config_manager->options['installation_flag_cleared_on'],
'installation_flag_set_on = ' . $blc_config_manager->options['installation_flag_set_on'],
'',
'<em>Installation log follows :</em>',
),
$logger->get_messages()
);
}
echo '<div class="error"><p>', implode( "<br>\n", $messages ), '</p></div>';
}
add_action( 'admin_notices', 'blc_print_installation_errors' );
}
}