Example #1
0
 /**
  * Create or update synchronization records for all containers managed by this class.
  *
  * @param bool $forced If true, assume that all synch. records are gone and will need to be recreated from scratch. 
  * @return void
  */
 function resynch($forced = false)
 {
     global $wpdb;
     /** @var wpdb $wpdb */
     global $blclog;
     //Only check custom fields on selected post types. By default, that's "post" and "page".
     $post_types = array('post', 'page');
     if (class_exists('blcPostTypeOverlord')) {
         $overlord = blcPostTypeOverlord::getInstance();
         $post_types = array_merge($post_types, $overlord->enabled_post_types);
         $post_types = array_unique($post_types);
     }
     $escaped_post_types = "'" . implode("', '", array_map('esc_sql', $post_types)) . "'";
     if ($forced) {
         //Create new synchronization records for all posts.
         $blclog->log('...... Creating synch records for all custom fields on ' . $escaped_post_types);
         $start = microtime(true);
         $q = "INSERT INTO {$wpdb->prefix}blc_synch(container_id, container_type, synched)\r\r\n\t\t\t\t  SELECT id, '{$this->container_type}', 0\r\r\n\t\t\t\t  FROM {$wpdb->posts}\r\r\n\t\t\t\t  WHERE\r\r\n\t\t\t\t  \t{$wpdb->posts}.post_status = 'publish'\r\r\n\t \t\t\t\tAND {$wpdb->posts}.post_type IN ({$escaped_post_types})";
         $wpdb->query($q);
         $blclog->log(sprintf('...... %d rows inserted in %.3f seconds', $wpdb->rows_affected, microtime(true) - $start));
     } else {
         //Delete synch records corresponding to posts that no longer exist.
         $blclog->log('...... Deleting custom field synch records corresponding to deleted posts');
         $start = microtime(true);
         $q = "DELETE synch.*\r\r\n\t\t\t\t  FROM \r\r\n\t\t\t\t\t {$wpdb->prefix}blc_synch AS synch LEFT JOIN {$wpdb->posts} AS posts\r\r\n\t\t\t\t\t ON posts.ID = synch.container_id\r\r\n\t\t\t\t  WHERE \r\r\n\t\t\t\t\t synch.container_type = '{$this->container_type}' AND posts.ID IS NULL";
         $wpdb->query($q);
         $blclog->log(sprintf('...... %d rows deleted in %.3f seconds', $wpdb->rows_affected, microtime(true) - $start));
         //Remove the 'synched' flag from all posts that have been updated
         //since the last time they were parsed/synchronized.
         $blclog->log('...... Marking custom fields on changed posts as unsynched');
         $start = microtime(true);
         $q = "UPDATE\r\r\n\t\t\t\t\t{$wpdb->prefix}blc_synch AS synch\r\r\n\t\t\t\t\tJOIN {$wpdb->posts} AS posts ON (synch.container_id = posts.ID and synch.container_type='{$this->container_type}')\r\r\n\t\t\t\t  SET \r\r\n\t\t\t\t\tsynched = 0\r\r\n\t\t\t\t  WHERE\r\r\n\t\t\t\t\tsynch.last_synch < posts.post_modified";
         $wpdb->query($q);
         $blclog->log(sprintf('...... %d rows updated in %.3f seconds', $wpdb->rows_affected, microtime(true) - $start));
         //Create synch. records for posts that don't have them.
         $blclog->log('...... Creating custom field synch records for new ' . $escaped_post_types);
         $start = microtime(true);
         $q = "INSERT INTO {$wpdb->prefix}blc_synch(container_id, container_type, synched)\r\r\n\t\t\t\t  SELECT id, '{$this->container_type}', 0\r\r\n\t\t\t\t  FROM \r\r\n\t\t\t\t    {$wpdb->posts} AS posts LEFT JOIN {$wpdb->prefix}blc_synch AS synch\r\r\n\t\t\t\t\tON (synch.container_id = posts.ID and synch.container_type='{$this->container_type}')  \r\r\n\t\t\t\t  WHERE\r\r\n\t\t\t\t  \tposts.post_status = 'publish'\r\r\n\t \t\t\t\tAND posts.post_type IN ({$escaped_post_types})\r\r\n\t\t\t\t\tAND synch.container_id IS NULL";
         $wpdb->query($q);
         $blclog->log(sprintf('...... %d rows inserted in %.3f seconds', $wpdb->rows_affected, microtime(true) - $start));
     }
 }
Example #2
0
        function options_page()
        {
            $moduleManager = blcModuleManager::getInstance();
            //Prior to 1.5.2 (released 2012-05-27), there was a bug that would cause the donation flag to be
            //set incorrectly. So we'll unset the flag in that case.
            $reset_donation_flag = $this->conf->get('first_installation_timestamp', 0) < strtotime('2012-05-27 00:00') && !$this->conf->get('donation_flag_fixed', false);
            if ($reset_donation_flag) {
                $this->conf->set('user_has_donated', false);
                $this->conf->set('donation_flag_fixed', true);
                $this->conf->save_options();
            }
            if (isset($_POST['recheck']) && !empty($_POST['recheck'])) {
                $this->initiate_recheck();
                //Redirect back to the settings page
                $base_url = remove_query_arg(array('_wpnonce', 'noheader', 'updated', 'error', 'action', 'message'));
                wp_redirect(add_query_arg(array('recheck-initiated' => true), $base_url));
                die;
            }
            $available_link_actions = array('edit' => __('Edit URL', 'broken-link-checker'), 'delete' => __('Unlink', 'broken-link-checker'), 'blc-discard-action' => __('Not broken', 'broken-link-checker'), 'blc-dismiss-action' => __('Dismiss', 'broken-link-checker'), 'blc-recheck-action' => __('Recheck', 'broken-link-checker'), 'blc-deredirect-action' => _x('Fix redirect', 'link action; replace one redirect with a direct link', 'broken-link-checker'));
            if (isset($_POST['submit'])) {
                check_admin_referer('link-checker-options');
                $cleanPost = $_POST;
                if (function_exists('wp_magic_quotes')) {
                    $cleanPost = stripslashes_deep($cleanPost);
                    //Ceterum censeo, WP shouldn't mangle superglobals.
                }
                //Activate/deactivate modules
                if (!empty($_POST['module'])) {
                    $active = array_keys($_POST['module']);
                    $moduleManager->set_active_modules($active);
                }
                //Only post statuses that actually exist can be selected
                if (isset($_POST['enabled_post_statuses']) && is_array($_POST['enabled_post_statuses'])) {
                    $available_statuses = get_post_stati();
                    $enabled_post_statuses = array_intersect($_POST['enabled_post_statuses'], $available_statuses);
                } else {
                    $enabled_post_statuses = array();
                }
                //At least one status must be enabled; defaults to "Published".
                if (empty($enabled_post_statuses)) {
                    $enabled_post_statuses = array('publish');
                }
                //Did the user add/remove any post statuses?
                $same_statuses = array_intersect($enabled_post_statuses, $this->conf->options['enabled_post_statuses']);
                $post_statuses_changed = count($same_statuses) != count($enabled_post_statuses) || count($same_statuses) !== count($this->conf->options['enabled_post_statuses']);
                $this->conf->options['enabled_post_statuses'] = $enabled_post_statuses;
                //The execution time limit must be above zero
                $new_execution_time = intval($_POST['max_execution_time']);
                if ($new_execution_time > 0) {
                    $this->conf->options['max_execution_time'] = $new_execution_time;
                }
                //The check threshold also must be > 0
                $new_check_threshold = intval($_POST['check_threshold']);
                if ($new_check_threshold > 0) {
                    $this->conf->options['check_threshold'] = $new_check_threshold;
                }
                $this->conf->options['mark_broken_links'] = !empty($_POST['mark_broken_links']);
                $new_broken_link_css = trim($cleanPost['broken_link_css']);
                $this->conf->options['broken_link_css'] = $new_broken_link_css;
                $this->conf->options['mark_removed_links'] = !empty($_POST['mark_removed_links']);
                $new_removed_link_css = trim($cleanPost['removed_link_css']);
                $this->conf->options['removed_link_css'] = $new_removed_link_css;
                $this->conf->options['nofollow_broken_links'] = !empty($_POST['nofollow_broken_links']);
                $this->conf->options['suggestions_enabled'] = !empty($_POST['suggestions_enabled']);
                $this->conf->options['exclusion_list'] = array_filter(preg_split('/[\\s\\r\\n]+/', $cleanPost['exclusion_list'], -1, PREG_SPLIT_NO_EMPTY));
                //Parse the custom field list
                $new_custom_fields = array_filter(preg_split('/[\\r\\n]+/', $cleanPost['blc_custom_fields'], -1, PREG_SPLIT_NO_EMPTY));
                //Calculate the difference between the old custom field list and the new one (used later)
                $diff1 = array_diff($new_custom_fields, $this->conf->options['custom_fields']);
                $diff2 = array_diff($this->conf->options['custom_fields'], $new_custom_fields);
                $this->conf->options['custom_fields'] = $new_custom_fields;
                //Turning off warnings turns existing warnings into "broken" links.
                $warnings_enabled = !empty($_POST['warnings_enabled']);
                if ($this->conf->get('warnings_enabled') && !$warnings_enabled) {
                    $this->promote_warnings_to_broken();
                }
                $this->conf->options['warnings_enabled'] = $warnings_enabled;
                //HTTP timeout
                $new_timeout = intval($_POST['timeout']);
                if ($new_timeout > 0) {
                    $this->conf->options['timeout'] = $new_timeout;
                }
                //Server load limit
                if (isset($_POST['server_load_limit'])) {
                    $this->conf->options['server_load_limit'] = floatval($_POST['server_load_limit']);
                    if ($this->conf->options['server_load_limit'] < 0) {
                        $this->conf->options['server_load_limit'] = 0;
                    }
                    $this->conf->options['enable_load_limit'] = $this->conf->options['server_load_limit'] > 0;
                }
                //Target resource usage (1% to 100%)
                if (isset($_POST['target_resource_usage'])) {
                    $usage = floatval($_POST['target_resource_usage']);
                    $usage = max(min($usage / 100, 1), 0.01);
                    $this->conf->options['target_resource_usage'] = $usage;
                }
                //When to run the checker
                $this->conf->options['run_in_dashboard'] = !empty($_POST['run_in_dashboard']);
                $this->conf->options['run_via_cron'] = !empty($_POST['run_via_cron']);
                //Email notifications on/off
                $email_notifications = !empty($_POST['send_email_notifications']);
                $send_authors_email_notifications = !empty($_POST['send_authors_email_notifications']);
                if ($email_notifications && !$this->conf->options['send_email_notifications'] || $send_authors_email_notifications && !$this->conf->options['send_authors_email_notifications']) {
                    /*
                                	The plugin should only send notifications about links that have become broken
                    since the time when email notifications were turned on. If we don't do this,
                    the first email notification will be sent nigh-immediately and list *all* broken
                    links that the plugin currently knows about.
                    */
                    $this->conf->options['last_notification_sent'] = time();
                }
                $this->conf->options['send_email_notifications'] = $email_notifications;
                $this->conf->options['send_authors_email_notifications'] = $send_authors_email_notifications;
                $this->conf->options['notification_email_address'] = strval($_POST['notification_email_address']);
                if (!filter_var($this->conf->options['notification_email_address'], FILTER_VALIDATE_EMAIL)) {
                    $this->conf->options['notification_email_address'] = '';
                }
                $widget_cap = strval($_POST['dashboard_widget_capability']);
                if (!empty($widget_cap)) {
                    $this->conf->options['dashboard_widget_capability'] = $widget_cap;
                }
                //Link actions. The user can hide some of them to reduce UI clutter.
                $show_link_actions = array();
                foreach (array_keys($available_link_actions) as $action) {
                    $show_link_actions[$action] = isset($_POST['show_link_actions']) && !empty($_POST['show_link_actions'][$action]);
                }
                $this->conf->set('show_link_actions', $show_link_actions);
                //Logging. The plugin can log various events and results for debugging purposes.
                $this->conf->options['logging_enabled'] = !empty($_POST['logging_enabled']);
                $this->conf->options['custom_log_file_enabled'] = !empty($_POST['custom_log_file_enabled']);
                if ($this->conf->options['logging_enabled']) {
                    if ($this->conf->options['custom_log_file_enabled']) {
                        $log_file = strval($cleanPost['log_file']);
                    } else {
                        //Default log file is /wp-content/uploads/broken-link-checker/blc-log.txt
                        $log_directory = self::get_default_log_directory();
                        $log_file = $log_directory . '/' . self::get_default_log_basename();
                        //Attempt to create the log directory.
                        if (!is_dir($log_directory)) {
                            if (mkdir($log_directory, 0750)) {
                                //Add a .htaccess to hide the log file from site visitors.
                                file_put_contents($log_directory . '/.htaccess', 'Deny from all');
                            }
                        }
                    }
                    $this->conf->options['log_file'] = $log_file;
                    //Attempt to create the log file if not already there.
                    if (!is_file($log_file)) {
                        file_put_contents($log_file, '');
                    }
                    //The log file must be writable.
                    if (!is_writable($log_file) || !is_file($log_file)) {
                        $this->conf->options['logging_enabled'] = false;
                    }
                }
                //Make settings that affect our Cron events take effect immediately
                $this->setup_cron_events();
                $this->conf->save_options();
                /*
                If the list of custom fields was modified then we MUST resynchronize or
                custom fields linked with existing posts may not be detected. This is somewhat
                inefficient.  
                */
                if (count($diff1) > 0 || count($diff2) > 0) {
                    $manager = blcContainerHelper::get_manager('custom_field');
                    if (!is_null($manager)) {
                        $manager->resynch();
                        blc_got_unsynched_items();
                    }
                }
                //Resynchronize posts when the user enables or disables post statuses.
                if ($post_statuses_changed) {
                    $overlord = blcPostTypeOverlord::getInstance();
                    $overlord->enabled_post_statuses = $this->conf->get('enabled_post_statuses', array());
                    $overlord->resynch('wsh_status_resynch_trigger');
                    blc_got_unsynched_items();
                    blc_cleanup_instances();
                    blc_cleanup_links();
                }
                //Redirect back to the settings page
                $base_url = remove_query_arg(array('_wpnonce', 'noheader', 'updated', 'error', 'action', 'message'));
                wp_redirect(add_query_arg(array('settings-updated' => true), $base_url));
            }
            //Show a confirmation message when settings are saved.
            if (!empty($_GET['settings-updated'])) {
                echo '<div id="message" class="updated fade"><p><strong>', __('Settings saved.', 'broken-link-checker'), '</strong></p></div>';
            }
            //Show a thank-you message when a donation is made.
            if (!empty($_GET['donated'])) {
                echo '<div id="message" class="updated fade"><p><strong>', __('Thank you for your donation!', 'broken-link-checker'), '</strong></p></div>';
                $this->conf->set('user_has_donated', true);
                $this->conf->save_options();
            }
            //Show one when recheck is started, too.
            if (!empty($_GET['recheck-initiated'])) {
                echo '<div id="message" class="updated fade"><p><strong>', __('Complete site recheck started.', 'broken-link-checker'), '</strong></p></div>';
            }
            //Cull invalid and missing modules
            $moduleManager->validate_active_modules();
            $debug = $this->get_debug_info();
            add_filter('blc-module-settings-custom_field', array($this, 'make_custom_field_input'), 10, 2);
            //Translate and markup-ify module headers for display
            $modules = $moduleManager->get_modules_by_category('', true, true);
            //Output the custom broken link/removed link styles for example links
            printf('<style type="text/css">%s %s</style>', $this->conf->options['broken_link_css'], $this->conf->options['removed_link_css']);
            $section_names = array('general' => __('General', 'broken-link-checker'), 'where' => __('Look For Links In', 'broken-link-checker'), 'which' => __('Which Links To Check', 'broken-link-checker'), 'how' => __('Protocols & APIs', 'broken-link-checker'), 'advanced' => __('Advanced', 'broken-link-checker'));
            ?>
		
		<!--[if lte IE 7]>
		<style type="text/css">
		/* Simulate inline-block in IE7 */
		ul.ui-tabs-nav li {
			display: inline; 
			zoom: 1;
		}
		</style>
		<![endif]-->
		
        <div class="wrap" id="blc-settings-wrap">
		<h2><?php 
            _e('Broken Link Checker Options', 'broken-link-checker');
            ?>
</h2>
		
		
        <div id="blc-sidebar">
			<div class="metabox-holder">
				<?php 
            include BLC_DIRECTORY . '/includes/admin/sidebar.php';
            ?>
			</div>
		</div>
		
        
        <div id="blc-admin-content">
		
        <form name="link_checker_options" id="link_checker_options" method="post" action="<?php 
            echo admin_url('options-general.php?page=link-checker-settings&noheader=1');
            ?>
">
        <?php 
            wp_nonce_field('link-checker-options');
            ?>
		
		<div id="blc-tabs">
		
		<ul class="hide-if-no-js">
			<?php 
            foreach ($section_names as $section_id => $section_name) {
                printf('<li id="tab-button-%s"><a href="#section-%s" title="%s">%s</a></li>', esc_attr($section_id), esc_attr($section_id), esc_attr($section_name), $section_name);
            }
            ?>
		</ul>

		<div id="section-general" class="blc-section">
		<h3 class="hide-if-js"><?php 
            echo $section_names['general'];
            ?>
</h3>
		
        <table class="form-table">

        <tr valign="top">
        <th scope="row">
			<?php 
            _e('Status', 'broken-link-checker');
            ?>
			<br>
			<a href="javascript:void(0)" id="blc-debug-info-toggle"><?php 
            _e('Show debug info', 'broken-link-checker');
            ?>
</a>
		</th>
        <td>

        <div id='wsblc_full_status'>
            <br/><br/><br/>
        </div>
        
        <table id="blc-debug-info">
        <?php 
            //Output the debug info in a table
            foreach ($debug as $key => $value) {
                printf('<tr valign="top" class="blc-debug-item-%s"><th scope="row">%s</th><td>%s<div class="blc-debug-message">%s</div></td></tr>', $value['state'], $key, $value['value'], array_key_exists('message', $value) ? $value['message'] : '');
            }
            ?>
        </table>
        
        </td>
        </tr>

        <tr valign="top">
        <th scope="row"><?php 
            _e('Check each link', 'broken-link-checker');
            ?>
</th>
        <td>

		<?php 
            printf(__('Every %s hours', 'broken-link-checker'), sprintf('<input type="text" name="check_threshold" id="check_threshold" value="%d" size="5" maxlength="5" />', $this->conf->options['check_threshold']));
            ?>
        <br/>
        <span class="description">
        <?php 
            _e('Existing links will be checked this often. New links will usually be checked ASAP.', 'broken-link-checker');
            ?>
        </span>

        </td>
        </tr>
        
        <tr valign="top">
        <th scope="row"><?php 
            _e('E-mail notifications', 'broken-link-checker');
            ?>
</th>
        <td>
        	<p style="margin-top: 0;">
        	<label for='send_email_notifications'>
        		<input type="checkbox" name="send_email_notifications" id="send_email_notifications"
            	<?php 
            if ($this->conf->options['send_email_notifications']) {
                echo ' checked="checked"';
            }
            ?>
/>
            	<?php 
            _e('Send me e-mail notifications about newly detected broken links', 'broken-link-checker');
            ?>
			</label><br />
			</p>

	        <p>
        	<label for='send_authors_email_notifications'>
        		<input type="checkbox" name="send_authors_email_notifications" id="send_authors_email_notifications"
            	<?php 
            if ($this->conf->options['send_authors_email_notifications']) {
                echo ' checked="checked"';
            }
            ?>
/>
            	<?php 
            _e('Send authors e-mail notifications about broken links in their posts', 'broken-link-checker');
            ?>
			</label><br />
			</p>
        </td>
        </tr>

		<tr valign="top">
			<th scope="row"><?php 
            echo __('Notification e-mail address', 'broken-link-checker');
            ?>
</th>
			<td>
				<p>
				<label>
					<input
						type="text"
						name="notification_email_address"
						id="notification_email_address"
						value="<?php 
            echo esc_attr($this->conf->get('notification_email_address', ''));
            ?>
"
						class="regular-text ltr">
				</label><br>
				<span class="description">
					<?php 
            echo __('Leave empty to use the e-mail address specified in Settings &rarr; General.', 'broken-link-checker');
            ?>
				</span>
				</p>
			</td>
		</tr>

        <tr valign="top">
        <th scope="row"><?php 
            _e('Link tweaks', 'broken-link-checker');
            ?>
</th>
        <td>
        	<p style="margin-top: 0; margin-bottom: 0.5em;">
        	<label for='mark_broken_links'>
        		<input type="checkbox" name="mark_broken_links" id="mark_broken_links"
            	<?php 
            if ($this->conf->options['mark_broken_links']) {
                echo ' checked="checked"';
            }
            ?>
/>
            	<?php 
            _e('Apply custom formatting to broken links', 'broken-link-checker');
            ?>
			</label>
			|
			<a id="toggle-broken-link-css-editor" href="#" class="blc-toggle-link"><?php 
            _e('Edit CSS', 'broken-link-checker');
            ?>
</a>
			</p>
			
			<div id="broken-link-css-wrap"<?php 
            if (!blcUtility::get_cookie('broken-link-css-wrap', false)) {
                echo ' class="hidden"';
            }
            ?>
>
		        <textarea name="broken_link_css" id="broken_link_css" cols='45' rows='4'><?php 
            if (isset($this->conf->options['broken_link_css'])) {
                echo $this->conf->options['broken_link_css'];
            }
            ?>
</textarea>
		        <p class="description"><?php 
            printf(__('Example : Lorem ipsum <a %s>broken link</a>, dolor sit amet.', 'broken-link-checker'), ' href="#" class="broken_link" onclick="return false;"');
            echo ' ', __('Click "Save Changes" to update example output.', 'broken-link-checker');
            ?>
</p>
        	</div>
        	
        	<p style="margin-bottom: 0.5em;">
        	<label for='mark_removed_links'>
        		<input type="checkbox" name="mark_removed_links" id="mark_removed_links"
            	<?php 
            if ($this->conf->options['mark_removed_links']) {
                echo ' checked="checked"';
            }
            ?>
/>
            	<?php 
            _e('Apply custom formatting to removed links', 'broken-link-checker');
            ?>
			</label>
			|
			<a id="toggle-removed-link-css-editor" href="#" class="blc-toggle-link"><?php 
            _e('Edit CSS', 'broken-link-checker');
            ?>
</a>
			</p>
			
			<div id="removed-link-css-wrap" <?php 
            if (!blcUtility::get_cookie('removed-link-css-wrap', false)) {
                echo ' class="hidden"';
            }
            ?>
>
		        <textarea name="removed_link_css" id="removed_link_css" cols='45' rows='4'><?php 
            if (isset($this->conf->options['removed_link_css'])) {
                echo $this->conf->options['removed_link_css'];
            }
            ?>
</textarea>
		        
		        <p class="description"><?php 
            printf(__('Example : Lorem ipsum <span %s>removed link</span>, dolor sit amet.', 'broken-link-checker'), ' class="removed_link"');
            echo ' ', __('Click "Save Changes" to update example output.', 'broken-link-checker');
            ?>

				</p>
        	</div>
        
        	<p>
        	<label for='nofollow_broken_links'>
        		<input type="checkbox" name="nofollow_broken_links" id="nofollow_broken_links"
            	<?php 
            if ($this->conf->options['nofollow_broken_links']) {
                echo ' checked="checked"';
            }
            ?>
/>
            	<?php 
            _e('Stop search engines from following broken links', 'broken-link-checker');
            ?>
			</label>
			</p>

			<p class="description">
				<?php 
            echo _x('These settings only apply to the content of posts, not comments or custom fields.', '"Link tweaks" settings', 'broken-link-checker');
            ?>
			</p>
        </td>
        </tr>

			<tr valign="top">
				<th scope="row"><?php 
            echo _x('Suggestions', 'settings page', 'broken-link-checker');
            ?>
</th>
				<td>
					<label>
						<input type="checkbox" name="suggestions_enabled" id="suggestions_enabled"
							<?php 
            checked($this->conf->options['suggestions_enabled']);
            ?>
/>
						<?php 
            _e('Suggest alternatives to broken links', 'broken-link-checker');
            ?>
					</label>
				</td>
			</tr>

			<tr valign="top">
				<th scope="row"><?php 
            echo _x('Warnings', 'settings page', 'broken-link-checker');
            ?>
</th>
				<td id="blc_warning_settings">
					<label>
						<input type="checkbox" name="warnings_enabled" id="warnings_enabled"
							<?php 
            checked($this->conf->options['warnings_enabled']);
            ?>
/>
						<?php 
            _e('Show uncertain or minor problems as "warnings" instead of "broken"', 'broken-link-checker');
            ?>
					</label>
					<p class="description"><?php 
            _e('Turning off this option will make the plugin report all problems as broken links.', 'broken-link-checker');
            ?>
</p>
				</td>
			</tr>

        </table>
        
        </div>
        
        <div id="section-where" class="blc-section">
		<h3 class="hide-if-js"><?php 
            echo $section_names['where'];
            ?>
</h3>
        
        <table class="form-table">
        
        <tr valign="top">
        <th scope="row"><?php 
            _e('Look for links in', 'broken-link-checker');
            ?>
</th>
        <td>
    	<?php 
            if (!empty($modules['container'])) {
                uasort($modules['container'], create_function('$a, $b', 'return strcasecmp($a["Name"], $b["Name"]);'));
                $this->print_module_list($modules['container'], $this->conf->options);
            }
            ?>
    	</td></tr>
    	
    	<tr valign="top">
        <th scope="row"><?php 
            _e('Post statuses', 'broken-link-checker');
            ?>
</th>
        <td>
    	<?php 
            $available_statuses = get_post_stati(array('internal' => false), 'objects');
            if (isset($this->conf->options['enabled_post_statuses'])) {
                $enabled_post_statuses = $this->conf->options['enabled_post_statuses'];
            } else {
                $enabled_post_statuses = array();
            }
            foreach ($available_statuses as $status => $status_object) {
                printf('<p><label><input type="checkbox" name="enabled_post_statuses[]" value="%s"%s> %s</label></p>', esc_attr($status), in_array($status, $enabled_post_statuses) ? ' checked="checked"' : '', $status_object->label);
            }
            ?>
    	</td></tr>
    	
        </table>
        
        </div>
        
        
        <div id="section-which" class="blc-section">
		<h3 class="hide-if-js"><?php 
            echo $section_names['which'];
            ?>
</h3>
		
        <table class="form-table">
        
        <tr valign="top">
        <th scope="row"><?php 
            _e('Link types', 'broken-link-checker');
            ?>
</th>
        <td>
        <?php 
            if (!empty($modules['parser'])) {
                $this->print_module_list($modules['parser'], $this->conf->options);
            } else {
                echo __('Error : All link parsers missing!', 'broken-link-checker');
            }
            ?>
    	</td>
		</tr>
    	
    	<tr valign="top">
        <th scope="row"><?php 
            _e('Exclusion list', 'broken-link-checker');
            ?>
</th>
        <td><?php 
            _e("Don't check links where the URL contains any of these words (one per line) :", 'broken-link-checker');
            ?>
<br/>
        <textarea name="exclusion_list" id="exclusion_list" cols='45' rows='4'><?php 
            if (isset($this->conf->options['exclusion_list'])) {
                echo esc_textarea(implode("\n", $this->conf->options['exclusion_list']));
            }
            ?>
</textarea>

        </td>
        </tr>
        
        </table>
        </div>
        
        <div id="section-how" class="blc-section">
		<h3 class="hide-if-js"><?php 
            echo $section_names['how'];
            ?>
</h3>
		
        <table class="form-table">
        
        <tr valign="top">
        <th scope="row"><?php 
            _e('Check links using', 'broken-link-checker');
            ?>
</th>
        <td>
        <?php 
            if (!empty($modules['checker'])) {
                $modules['checker'] = array_reverse($modules['checker']);
                $this->print_module_list($modules['checker'], $this->conf->options);
            }
            ?>
    	</td></tr>
        
        </table>
        </div>
        
        <div id="section-advanced" class="blc-section">
		<h3 class="hide-if-js"><?php 
            echo $section_names['advanced'];
            ?>
</h3>
        
        <table class="form-table">
        
        <tr valign="top">
        <th scope="row"><?php 
            _e('Timeout', 'broken-link-checker');
            ?>
</th>
        <td>

		<?php 
            printf(__('%s seconds', 'broken-link-checker'), sprintf('<input type="text" name="timeout" id="blc_timeout" value="%d" size="5" maxlength="3" />', $this->conf->options['timeout']));
            ?>
        <br/><span class="description">
        <?php 
            _e('Links that take longer than this to load will be marked as broken.', 'broken-link-checker');
            ?>
 
		</span>

        </td>
        </tr>
        
        <tr valign="top">
        <th scope="row"><?php 
            _e('Link monitor', 'broken-link-checker');
            ?>
</th>
        <td>
        
        	<p>
			<label for='run_in_dashboard'>
				
	        		<input type="checkbox" name="run_in_dashboard" id="run_in_dashboard"
	            	<?php 
            if ($this->conf->options['run_in_dashboard']) {
                echo ' checked="checked"';
            }
            ?>
/>
	            	<?php 
            _e('Run continuously while the Dashboard is open', 'broken-link-checker');
            ?>
			</label>
			</p>
			
			<p>
			<label for='run_via_cron'>
	        		<input type="checkbox" name="run_via_cron" id="run_via_cron"
	            	<?php 
            if ($this->conf->options['run_via_cron']) {
                echo ' checked="checked"';
            }
            ?>
/>
	            	<?php 
            _e('Run hourly in the background', 'broken-link-checker');
            ?>
			</label>
			</p>		

        </td>
        </tr>

        <tr valign="top">
	        <th scope="row"><?php 
            _e('Show the dashboard widget for', 'broken-link-checker');
            ?>
</th>
	        <td>

		        <?php 
            $widget_caps = array(_x('Administrator', 'dashboard widget visibility', 'broken-link-checker') => 'manage_options', _x('Editor and above', 'dashboard widget visibility', 'broken-link-checker') => 'edit_others_posts', _x('Nobody (disables the widget)', 'dashboard widget visibility', 'broken-link-checker') => 'do_not_allow');
            foreach ($widget_caps as $title => $capability) {
                printf('<p><label><input type="radio" name="dashboard_widget_capability" value="%s"%s> %s</label></p>', esc_attr($capability), checked($capability, $this->conf->get('dashboard_widget_capability'), false), $title);
            }
            ?>
	        </td>
        </tr>

		<tr valign="top">
			<th scope="row"><?php 
            echo _x('Show link actions', 'settings page', 'broken-link-checker');
            ?>
</th>
			<td>
				<?php 
            $show_link_actions = $this->conf->get('show_link_actions', array());
            foreach ($available_link_actions as $action => $text) {
                $enabled = isset($show_link_actions[$action]) ? (bool) $show_link_actions[$action] : true;
                printf('<p><label><input type="checkbox" name="show_link_actions[%1$s]" %3$s> %2$s</label></p>', $action, $text, checked($enabled, true, false));
            }
            ?>
			</td>
		</tr>
        
        <tr valign="top">
        <th scope="row"><?php 
            _e('Max. execution time', 'broken-link-checker');
            ?>
</th>
        <td>

		<?php 
            printf(__('%s seconds', 'broken-link-checker'), sprintf('<input type="text" name="max_execution_time" id="max_execution_time" value="%d" size="5" maxlength="5" />', $this->conf->options['max_execution_time']));
            ?>
 
        <br/><span class="description">
        <?php 
            _e('The plugin works by periodically launching a background job that parses your posts for links, checks the discovered URLs, and performs other time-consuming tasks. Here you can set for how long, at most, the link monitor may run each time before stopping.', 'broken-link-checker');
            ?>
 
		</span>

        </td>
        </tr>
        
        <tr valign="top">
        <th scope="row"><?php 
            _e('Server load limit', 'broken-link-checker');
            ?>
</th>
        <td>
		<?php 
            $load = blcUtility::get_server_load();
            $available = !empty($load);
            if ($available) {
                $value = !empty($this->conf->options['server_load_limit']) ? sprintf('%.2f', $this->conf->options['server_load_limit']) : '';
                printf('<input type="text" name="server_load_limit" id="server_load_limit" value="%s" size="5" maxlength="5"/> ', $value);
                printf(__('Current load : %s', 'broken-link-checker'), '<span id="wsblc_current_load">...</span>');
                echo '<br/><span class="description">';
                printf(__('Link checking will be suspended if the average <a href="%s">server load</a> rises above this number. Leave this field blank to disable load limiting.', 'broken-link-checker'), 'http://en.wikipedia.org/wiki/Load_(computing)');
                echo '</span>';
            } else {
                echo '<input type="text" disabled="disabled" value="', esc_attr(__('Not available', 'broken-link-checker')), '" size="13"/><br>';
                echo '<span class="description">';
                _e('Load limiting only works on Linux-like systems where <code>/proc/loadavg</code> is present and accessible.', 'broken-link-checker');
                echo '</span>';
            }
            ?>
 
        </td>
        </tr>

		<tr valign="top">
			<th scope="row"><?php 
            _e('Target resource usage', 'broken-link-checker');
            ?>
</th>
			<td>
				<?php 
            $target_resource_usage = $this->conf->get('target_resource_usage', 0.25);
            printf('<input name="target_resource_usage" value="%d"
						type="range" min="1" max="100" id="target_resource_usage">', $target_resource_usage * 100);
            ?>

				<span id="target_resource_usage_percent"><?php 
            echo sprintf('%.0f%%', $target_resource_usage * 100);
            ?>
</span>
			</td>
		</tr>

		<tr valign="top">
			<th scope="row"><?php 
            _e('Logging', 'broken-link-checker');
            ?>
</th>
			<td>
				<p>
					<label for='logging_enabled'>
						<input type="checkbox" name="logging_enabled" id="logging_enabled"
							<?php 
            checked($this->conf->options['logging_enabled']);
            ?>
/>
						<?php 
            _e('Enable logging', 'broken-link-checker');
            ?>
					</label>
				</p>
			</td>
		</tr>

		<tr valign="top">
			<th scope="row"><?php 
            _e('Log file location', 'broken-link-checker');
            ?>
</th>
			<td>

				<div id="blc-logging-options">

				<p>
				<label>
					<input type="radio" name="custom_log_file_enabled" value=""
						<?php 
            checked(!$this->conf->options['custom_log_file_enabled']);
            ?>
>
					<?php 
            echo _x('Default', 'log file location', 'broken-link-checker');
            ?>
				</label>
				<br>
					<span class="description">
						<code><?php 
            echo self::get_default_log_directory(), '/', self::get_default_log_basename();
            ?>
</code>
					</span>
				</p>

				<p>
				<label>
					<input type="radio" name="custom_log_file_enabled" value="1"
						<?php 
            checked($this->conf->options['custom_log_file_enabled']);
            ?>
>
					<?php 
            echo _x('Custom', 'log file location', 'broken-link-checker');
            ?>
				</label>
				<br><input type="text" name="log_file" id="log_file" size="90"
						   value="<?php 
            echo esc_attr($this->conf->options['log_file']);
            ?>
">
				</p>

				</div>
			</td>
		</tr>

        
        <tr valign="top">
        <th scope="row"><?php 
            _e('Forced recheck', 'broken-link-checker');
            ?>
</th>
        <td>
        	<input class="button" type="button" name="start-recheck" id="start-recheck" 
				  value="<?php 
            _e('Re-check all pages', 'broken-link-checker');
            ?>
"  />
  			<input type="hidden" name="recheck" value="" id="recheck" />
			<br />
  			<span class="description"><?php 
            _e('The "Nuclear Option". Click this button to make the plugin empty its link database and recheck the entire site from scratch.', 'broken-link-checker');
            ?>
</span>
		</td>
		</tr>
        
        </table>
        </div>
        
        </div>
        
        <p class="submit"><input type="submit" name="submit" class='button-primary' value="<?php 
            _e('Save Changes');
            ?>
" /></p>
        </form>
        
        </div> <!-- First postbox-container -->
        
        
        </div>
        
        
        
        <?php 
            //The various JS for this page is stored in a separate file for the purposes readability.
            include dirname($this->loader) . '/includes/admin/options-page-js.php';
        }
 /**
  * Create or update synchronization records for all posts.
  *
  * @param bool $forced If true, assume that all synch. records are gone and will need to be recreated from scratch. 
  * @return void
  */
 function resynch($forced = false)
 {
     $overlord = blcPostTypeOverlord::getInstance();
     $overlord->resynch($this->container_type, $forced);
 }