/** * Mark containers that this parser might be interested in as unparsed. * * @uses blcContainerHelper::mark_as_unsynched_where() * * @param bool $only_return If true, just return the list of formats and container types without actually modifying any synch. records. * @return void|array Either nothing or an array in the form [ [format1=>timestamp1, ...], [container_type1=>timestamp1, ...] ] */ function resynch_relevant_containers($only_return = false) { global $blclog; $blclog->log(sprintf('...... Parser "%s" is marking relevant items as unsynched', $this->module_id)); $last_deactivated = $this->module_manager->get_last_deactivation_time($this->module_id); $formats = array(); foreach ($this->supported_formats as $format) { $formats[$format] = $last_deactivated; } $container_types = array(); foreach ($this->supported_containers as $container_type) { $container_types[$container_type] = $last_deactivated; } if ($only_return) { return array($formats, $container_types); } else { blcContainerHelper::mark_as_unsynched_where($formats, $container_types); } }
/** * 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(); }
/** * When a bookmark is deleted, remove the related DB records. * * @param int $link_id * @return void */ function hook_delete_link($link_id) { //Get the container object. $container = blcContainerHelper::get_container(array($this->container_type, $link_id)); //Get the link(s) associated with it. $links = $container->get_links(); //Remove synch. record & instance records. $container->delete(); //Clean up links associated with this bookmark (there's probably only one) $link_ids = array(); foreach ($links as $link) { $link_ids[] = $link->link_id; } blc_cleanup_links($link_ids); }
/** * Get the container object associated with this link instance * * @return blcContainer|null */ function &get_container() { if (is_null($this->_container)) { $this->_container =& blcContainerHelper::get_container(array($this->container_type, $this->container_id)); } return $this->_container; }
/** * The main worker function that does all kinds of things. * * @return void */ function work() { global $wpdb; if (!$this->acquire_lock()) { //FB::warn("Another instance of BLC is already working. Stop."); return; } if ($this->server_too_busy()) { //FB::warn("Server is too busy. Stop."); return; } $this->start_timer(); $max_execution_time = $this->conf->options['max_execution_time']; /***************************************** Preparation ******************************************/ // Check for safe mode if (blcUtility::is_safe_mode()) { // Do it the safe mode way - obey the existing max_execution_time setting $t = ini_get('max_execution_time'); if ($t && $t < $max_execution_time) { $max_execution_time = $t - 1; } } else { // Do it the regular way @set_time_limit($max_execution_time * 2); //x2 should be plenty, running any longer would mean a glitch. } //Don't stop the script when the connection is closed ignore_user_abort(true); //Close the connection as per http://www.php.net/manual/en/features.connection-handling.php#71172 //This reduces resource usage and may solve the mysterious slowdowns certain users have //encountered when activating the plugin. //(Disable when debugging or you won't get the FirePHP output) if (!headers_sent() && (!defined('BLC_DEBUG') || !constant('BLC_DEBUG'))) { @ob_end_clean(); //Discard the existing buffer, if any header("Connection: close"); ob_start(); echo 'Connection closed'; //This could be anything $size = ob_get_length(); header("Content-Length: {$size}"); ob_end_flush(); // Strange behaviour, will not work flush(); // Unless both are called ! } //Load modules for this context $moduleManager = blcModuleManager::getInstance(); $moduleManager->load_modules('work'); /***************************************** Parse posts and bookmarks ******************************************/ $orphans_possible = false; $still_need_resynch = $this->conf->options['need_resynch']; if ($still_need_resynch) { //FB::log("Looking for containers that need parsing..."); while ($containers = blcContainerHelper::get_unsynched_containers(50)) { //FB::log($containers, 'Found containers'); foreach ($containers as $container) { //FB::log($container, "Parsing container"); $container->synch(); //Check if we still have some execution time left if ($this->execution_time() > $max_execution_time) { //FB::log('The alloted execution time has run out'); blc_cleanup_links(); $this->release_lock(); return; } //Check if the server isn't overloaded if ($this->server_too_busy()) { //FB::log('Server overloaded, bailing out.'); blc_cleanup_links(); $this->release_lock(); return; } } $orphans_possible = true; } //FB::log('No unparsed items found.'); $still_need_resynch = false; } else { //FB::log('Resynch not required.'); } /****************************************** Resynch done? *******************************************/ if ($this->conf->options['need_resynch'] && !$still_need_resynch) { $this->conf->options['need_resynch'] = $still_need_resynch; $this->conf->save_options(); } /****************************************** Remove orphaned links *******************************************/ if ($orphans_possible) { //FB::log('Cleaning up the link table.'); blc_cleanup_links(); } //Check if we still have some execution time left if ($this->execution_time() > $max_execution_time) { //FB::log('The alloted execution time has run out'); $this->release_lock(); return; } if ($this->server_too_busy()) { //FB::log('Server overloaded, bailing out.'); $this->release_lock(); return; } /***************************************** Check links ******************************************/ while ($links = $this->get_links_to_check(30)) { //Some unchecked links found //FB::log("Checking ".count($links)." link(s)"); foreach ($links as $link) { //Does this link need to be checked? Excluded links aren't checked, but their URLs are still //tested periodically to see if they're still on the exlusion list. if (!$this->is_excluded($link->url)) { //Check the link. //FB::log($link->url, "Checking link {$link->link_id}"); $link->check(true); } else { //FB::info("The URL {$link->url} is excluded, skipping link {$link->link_id}."); $link->last_check_attempt = time(); $link->save(); } //Check if we still have some execution time left if ($this->execution_time() > $max_execution_time) { //FB::log('The alloted execution time has run out'); $this->release_lock(); return; } //Check if the server isn't overloaded if ($this->server_too_busy()) { //FB::log('Server overloaded, bailing out.'); $this->release_lock(); return; } } } //FB::log('No links need to be checked right now.'); $this->release_lock(); //FB::log('All done.'); }
/** * Get the message to display after $n containers of a specific type have been moved to the trash. * * @see blcContainerHelper::ui_bulk_delete_message() * * @param string $container_type * @param int $n * @return string */ static function ui_bulk_trash_message($container_type, $n) { $manager = blcContainerHelper::get_manager($container_type); if (is_null($manager)) { return sprintf(__("Container type '%s' not recognized", 'broken-link-checker'), $container_type); } else { return $manager->ui_bulk_trash_message($n); } }
/** * The main worker function that does all kinds of things. * * @return void */ function work() { global $blclog; //Close the session to prevent lock-ups. //PHP sessions are blocking. session_start() will wait until all other scripts that are using the same session //are finished. As a result, a long-running script that unintentionally keeps the session open can cause //the entire site to "lock up" for the current user/browser. WordPress itself doesn't use sessions, but some //plugins do, so we should explicitly close the session (if any) before starting the worker. if (session_id() != '') { session_write_close(); } if (!$this->acquire_lock()) { //FB::warn("Another instance of BLC is already working. Stop."); $blclog->info('Another instance of BLC is already working. Stop.'); return; } if ($this->server_too_busy()) { //FB::warn("Server is too busy. Stop."); $blclog->warn('Server load is too high, stopping.'); return; } $this->start_timer(); $blclog->info('work() starts'); $max_execution_time = $this->conf->options['max_execution_time']; /***************************************** Preparation ******************************************/ // Check for safe mode if (blcUtility::is_safe_mode()) { // Do it the safe mode way - obey the existing max_execution_time setting $t = ini_get('max_execution_time'); if ($t && $t < $max_execution_time) { $max_execution_time = $t - 1; } } else { // Do it the regular way @set_time_limit($max_execution_time * 2); //x2 should be plenty, running any longer would mean a glitch. } //Don't stop the script when the connection is closed ignore_user_abort(true); //Close the connection as per http://www.php.net/manual/en/features.connection-handling.php#71172 //This reduces resource usage. //(Disable when debugging or you won't get the FirePHP output) if (!headers_sent() && (defined('DOING_AJAX') && constant('DOING_AJAX')) && (!defined('BLC_DEBUG') || !constant('BLC_DEBUG'))) { @ob_end_clean(); //Discard the existing buffer, if any header("Connection: close"); ob_start(); echo 'Connection closed'; //This could be anything $size = ob_get_length(); header("Content-Length: {$size}"); ob_end_flush(); // Strange behaviour, will not work flush(); // Unless both are called ! } //Load modules for this context $moduleManager = blcModuleManager::getInstance(); $moduleManager->load_modules('work'); $target_usage_fraction = $this->conf->get('target_resource_usage', 0.25); //Target usage must be between 1% and 100%. $target_usage_fraction = max(min($target_usage_fraction, 1), 0.01); /***************************************** Parse posts and bookmarks ******************************************/ $orphans_possible = false; $still_need_resynch = $this->conf->options['need_resynch']; if ($still_need_resynch) { //FB::log("Looking for containers that need parsing..."); $max_containers_per_query = 50; $start = microtime(true); $containers = blcContainerHelper::get_unsynched_containers($max_containers_per_query); $get_containers_time = microtime(true) - $start; while (!empty($containers)) { //FB::log($containers, 'Found containers'); $this->sleep_to_maintain_ratio($get_containers_time, $target_usage_fraction); foreach ($containers as $container) { $synch_start_time = microtime(true); //FB::log($container, "Parsing container"); $container->synch(); $synch_elapsed_time = microtime(true) - $synch_start_time; $blclog->info(sprintf('Parsed container %s[%s] in %.2f ms', $container->container_type, $container->container_id, $synch_elapsed_time * 1000)); //Check if we still have some execution time left if ($this->execution_time() > $max_execution_time) { //FB::log('The allotted execution time has run out'); blc_cleanup_links(); $this->release_lock(); return; } //Check if the server isn't overloaded if ($this->server_too_busy()) { //FB::log('Server overloaded, bailing out.'); blc_cleanup_links(); $this->release_lock(); return; } //Intentionally slow down parsing to reduce the load on the server. Basically, //we work $target_usage_fraction of the time and sleep the rest of the time. $this->sleep_to_maintain_ratio($synch_elapsed_time, $target_usage_fraction); } $orphans_possible = true; $start = microtime(true); $containers = blcContainerHelper::get_unsynched_containers($max_containers_per_query); $get_containers_time = microtime(true) - $start; } //FB::log('No unparsed items found.'); $still_need_resynch = false; } else { //FB::log('Resynch not required.'); } /****************************************** Resynch done? *******************************************/ if ($this->conf->options['need_resynch'] && !$still_need_resynch) { $this->conf->options['need_resynch'] = $still_need_resynch; $this->conf->save_options(); } /****************************************** Remove orphaned links *******************************************/ if ($orphans_possible) { $start = microtime(true); $blclog->info('Removing orphaned links.'); blc_cleanup_links(); $get_links_time = microtime(true) - $start; $this->sleep_to_maintain_ratio($get_links_time, $target_usage_fraction); } //Check if we still have some execution time left if ($this->execution_time() > $max_execution_time) { //FB::log('The allotted execution time has run out'); $blclog->info('The allotted execution time has run out.'); $this->release_lock(); return; } if ($this->server_too_busy()) { //FB::log('Server overloaded, bailing out.'); $blclog->info('Server load too high, stopping.'); $this->release_lock(); return; } /***************************************** Check links ******************************************/ $max_links_per_query = 30; $start = microtime(true); $links = $this->get_links_to_check($max_links_per_query); $get_links_time = microtime(true) - $start; while ($links) { $this->sleep_to_maintain_ratio($get_links_time, $target_usage_fraction); //Some unchecked links found //FB::log("Checking ".count($links)." link(s)"); $blclog->info("Checking " . count($links) . " link(s)"); //Randomizing the array reduces the chances that we'll get several links to the same domain in a row. shuffle($links); $transactionManager = TransactionManager::getInstance(); $transactionManager->start(); foreach ($links as $link) { //Does this link need to be checked? Excluded links aren't checked, but their URLs are still //tested periodically to see if they're still on the exclusion list. if (!$this->is_excluded($link->url)) { //Check the link. //FB::log($link->url, "Checking link {$link->link_id}"); $link->check(true); } else { //FB::info("The URL {$link->url} is excluded, skipping link {$link->link_id}."); $link->last_check_attempt = time(); $link->save(); } //Check if we still have some execution time left if ($this->execution_time() > $max_execution_time) { //FB::log('The allotted execution time has run out'); $blclog->info('The allotted execution time has run out.'); $this->release_lock(); return; } //Check if the server isn't overloaded if ($this->server_too_busy()) { //FB::log('Server overloaded, bailing out.'); $blclog->info('Server load too high, stopping.'); $this->release_lock(); return; } } $transactionManager->commit(); $start = microtime(true); $links = $this->get_links_to_check($max_links_per_query); $get_links_time = microtime(true) - $start; } //FB::log('No links need to be checked right now.'); $this->release_lock(); $blclog->info('work(): All done.'); //FB::log('All done.'); }
function hook_untrash_post_comments($post_id) { //Unlike with the 'trashed_post_comments' hook, WP doesn't pass the list of (un)trashed //comments to callbacks assigned to the 'untrash_post_comments' and 'untrashed_post_comments' //actions. Therefore, we must read it from the appropriate metadata entry. $statuses = get_post_meta($post_id, '_wp_trash_meta_comments_status', true); if (empty($statuses) || !is_array($statuses)) { return; } foreach ($statuses as $comment_id => $comment_status) { if ($comment_status == '1') { //if approved $container = blcContainerHelper::get_container(array($this->container_type, $comment_id)); $container->mark_as_unsynched(); } } }
/** * When a post is restored, mark all of its custom fields as unparsed. * Called via the 'untrashed_post' action. * * @param int $post_id * @return void */ function post_untrashed($post_id) { //Get the associated container object $container =& blcContainerHelper::get_container(array($this->container_type, intval($post_id))); $container->mark_as_unsynched(); }
/** * When a post is saved or modified, mark it as unparsed. * * @param int $post_id * @return void */ function post_saved($post_id) { //Get the container type matching the type of the deleted post $post = get_post($post_id); if (!$post) { return; } //Only check links in currently enabled post types if (!in_array($post->post_type, $this->enabled_post_types)) { return; } //Only check posts that have one of the allowed statuses if (!in_array($post->post_status, $this->enabled_post_statuses)) { return; } //Get the container & mark it as unparsed $args = array($post->post_type, intval($post_id)); $post_container = blcContainerHelper::get_container($args); $post_container->mark_as_unsynched(); }
public static function hook_post_deleted($post_id) { if (get_option('mainwp_linkschecker_ext_enabled') !== "Y") { return; } if (!defined('BLC_ACTIVE') || !function_exists('blc_init')) { return; } blc_init(); //Get the container type matching the type of the deleted post $post = get_post($post_id); if (!$post) { return; } //Get the associated container object $post_container = blcContainerHelper::get_container(array($post->post_type, intval($post_id))); if ($post_container) { //Delete it $post_container->delete(); //Clean up any dangling links blc_cleanup_links(); } }